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.

121 satır
3.2KB

  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 && isset($lines[$current + 1])
  22. && preg_match('~^\\s*\\|?(\\s*:?-[\\-\\s]*:?\\s*\\|\\s*:?-[\\-\\s]*:?\\s*)+\\|?\\s*$~', $lines[$current + 1]);
  23. }
  24. /**
  25. * Consume lines for a table
  26. */
  27. protected function consumeTable($lines, $current)
  28. {
  29. // consume until newline
  30. $block = [
  31. 'table',
  32. 'cols' => [],
  33. 'rows' => [],
  34. ];
  35. $beginsWithPipe = $lines[$current][0] === '|';
  36. for ($i = $current, $count = count($lines); $i < $count; $i++) {
  37. $line = rtrim($lines[$i]);
  38. // extract alignment from second line
  39. if ($i == $current+1) {
  40. $cols = explode('|', trim($line, ' |'));
  41. foreach($cols as $col) {
  42. $col = trim($col);
  43. if (empty($col)) {
  44. $block['cols'][] = '';
  45. continue;
  46. }
  47. $l = ($col[0] === ':');
  48. $r = (substr($col, -1, 1) === ':');
  49. if ($l && $r) {
  50. $block['cols'][] = 'center';
  51. } elseif ($l) {
  52. $block['cols'][] = 'left';
  53. } elseif ($r) {
  54. $block['cols'][] = 'right';
  55. } else {
  56. $block['cols'][] = '';
  57. }
  58. }
  59. continue;
  60. }
  61. if ($line === '' || $beginsWithPipe && $line[0] !== '|') {
  62. break;
  63. }
  64. if ($line[0] === '|') {
  65. $line = substr($line, 1);
  66. }
  67. if (substr($line, -1, 1) === '|' && (substr($line, -2, 2) !== '\\|' || substr($line, -3, 3) === '\\\\|')) {
  68. $line = substr($line, 0, -1);
  69. }
  70. $block['rows'][] = $line;
  71. }
  72. return [$block, --$i];
  73. }
  74. /**
  75. * render a table block
  76. */
  77. protected function renderTable($block)
  78. {
  79. $content = '';
  80. $this->_tableCellAlign = $block['cols'];
  81. $content .= "<thead>\n";
  82. $first = true;
  83. foreach($block['rows'] as $row) {
  84. $this->_tableCellTag = $first ? 'th' : 'td';
  85. $align = empty($this->_tableCellAlign[$this->_tableCellCount]) ? '' : ' align="' . $this->_tableCellAlign[$this->_tableCellCount++] . '"';
  86. $tds = "<$this->_tableCellTag$align>" . trim($this->renderAbsy($this->parseInline($row))) . "</$this->_tableCellTag>"; // TODO move this to the consume step
  87. $content .= "<tr>$tds</tr>\n";
  88. if ($first) {
  89. $content .= "</thead>\n<tbody>\n";
  90. }
  91. $first = false;
  92. $this->_tableCellCount = 0;
  93. }
  94. return "<table>\n$content</tbody>\n</table>\n";
  95. }
  96. /**
  97. * @marker |
  98. */
  99. protected function parseTd($markdown)
  100. {
  101. if (isset($this->context[1]) && $this->context[1] === 'table') {
  102. $align = empty($this->_tableCellAlign[$this->_tableCellCount]) ? '' : ' align="' . $this->_tableCellAlign[$this->_tableCellCount++] . '"';
  103. return [['text', "</$this->_tableCellTag><$this->_tableCellTag$align>"], isset($markdown[1]) && $markdown[1] === ' ' ? 2 : 1]; // TODO make a absy node
  104. }
  105. return [['text', $markdown[0]], 1];
  106. }
  107. abstract protected function parseInline($text);
  108. abstract protected function renderAbsy($absy);
  109. }