You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

117 line
3.1KB

  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2014 Carsten Brandt
  4. * @license https://github.com/cebe/markdown/blob/master/LICENSE
  5. * @link https://github.com/cebe/markdown#readme
  6. */
  7. namespace cebe\markdown\block;
  8. /**
  9. * Adds the table blocks
  10. */
  11. trait TableTrait
  12. {
  13. private $_tableCellTag = 'td';
  14. private $_tableCellCount = 0;
  15. private $_tableCellAlign = [];
  16. /**
  17. * identify a line as the beginning of a table block.
  18. */
  19. protected function identifyTable($line, $lines, $current)
  20. {
  21. return strpos($line, '|') !== false && preg_match('~|.*|~', $line) && isset($lines[$current + 1]) && preg_match('~^[\s\|\:-]+$~', $lines[$current + 1]);
  22. }
  23. /**
  24. * Consume lines for a table
  25. */
  26. protected function consumeTable($lines, $current)
  27. {
  28. // consume until newline
  29. $block = [
  30. 'table',
  31. 'cols' => [],
  32. 'rows' => [],
  33. ];
  34. $beginsWithPipe = $lines[$current][0] === '|';
  35. for ($i = $current, $count = count($lines); $i < $count; $i++) {
  36. $line = $lines[$i];
  37. if ($i == $current+1) { // skip second line
  38. $cols = explode('|', trim($line, ' |'));
  39. foreach($cols as $col) {
  40. $col = trim($col);
  41. if (empty($col)) {
  42. $block['cols'][] = '';
  43. continue;
  44. }
  45. $l = ($col[0] === ':');
  46. $r = (substr($col, -1, 1) === ':');
  47. if ($l && $r) {
  48. $block['cols'][] = 'center';
  49. } elseif ($l) {
  50. $block['cols'][] = 'left';
  51. } elseif ($r) {
  52. $block['cols'][] = 'right';
  53. } else {
  54. $block['cols'][] = '';
  55. }
  56. }
  57. continue;
  58. }
  59. if (trim($line) === '' || $beginsWithPipe && $line[0] !== '|') {
  60. break;
  61. }
  62. if (substr($line, -2, 2) !== '\\|' || substr($line, -3, 3) === '\\\\|') {
  63. $block['rows'][] = trim($line, '| ');
  64. } else {
  65. $block['rows'][] = ltrim($line, '| ');
  66. }
  67. }
  68. return [$block, --$i];
  69. }
  70. /**
  71. * render a table block
  72. */
  73. protected function renderTable($block)
  74. {
  75. $content = '';
  76. $this->_tableCellAlign = $block['cols'];
  77. $content .= "<thead>\n";
  78. $first = true;
  79. foreach($block['rows'] as $row) {
  80. $this->_tableCellTag = $first ? 'th' : 'td';
  81. $align = empty($this->_tableCellAlign[$this->_tableCellCount]) ? '' : ' align="' . $this->_tableCellAlign[$this->_tableCellCount++] . '"';
  82. $tds = "<$this->_tableCellTag$align>" . $this->renderAbsy($this->parseInline($row)) . "</$this->_tableCellTag>"; // TODO move this to the consume step
  83. $content .= "<tr>$tds</tr>\n";
  84. if ($first) {
  85. $content .= "</thead>\n<tbody>\n";
  86. }
  87. $first = false;
  88. $this->_tableCellCount = 0;
  89. }
  90. return "<table>\n$content</tbody>\n</table>\n";
  91. }
  92. /**
  93. * @marker |
  94. */
  95. protected function parseTd($markdown)
  96. {
  97. if (isset($this->context[1]) && $this->context[1] === 'table') {
  98. $align = empty($this->_tableCellAlign[$this->_tableCellCount]) ? '' : ' align="' . $this->_tableCellAlign[$this->_tableCellCount++] . '"';
  99. return [['text', "</$this->_tableCellTag><$this->_tableCellTag$align>"], isset($markdown[1]) && $markdown[1] === ' ' ? 2 : 1]; // TODO make a absy node
  100. }
  101. return [['text', $markdown[0]], 1];
  102. }
  103. abstract protected function parseInline($text);
  104. abstract protected function renderAbsy($absy);
  105. }