115 lines
2.7KB

  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;
  8. /**
  9. * Markdown parser for github flavored markdown.
  10. *
  11. * @author Carsten Brandt <mail@cebe.cc>
  12. */
  13. class GithubMarkdown extends Markdown
  14. {
  15. // include block element parsing using traits
  16. use block\TableTrait;
  17. use block\FencedCodeTrait;
  18. // include inline element parsing using traits
  19. use inline\StrikeoutTrait;
  20. use inline\UrlLinkTrait;
  21. /**
  22. * @var boolean whether to interpret newlines as `<br />`-tags.
  23. * This feature is useful for comments where newlines are often meant to be real new lines.
  24. */
  25. public $enableNewlines = false;
  26. /**
  27. * @inheritDoc
  28. */
  29. protected $escapeCharacters = [
  30. // from Markdown
  31. '\\', // backslash
  32. '`', // backtick
  33. '*', // asterisk
  34. '_', // underscore
  35. '{', '}', // curly braces
  36. '[', ']', // square brackets
  37. '(', ')', // parentheses
  38. '#', // hash mark
  39. '+', // plus sign
  40. '-', // minus sign (hyphen)
  41. '.', // dot
  42. '!', // exclamation mark
  43. '<', '>',
  44. // added by GithubMarkdown
  45. ':', // colon
  46. '|', // pipe
  47. ];
  48. /**
  49. * Consume lines for a paragraph
  50. *
  51. * Allow headlines, lists and code to break paragraphs
  52. */
  53. protected function consumeParagraph($lines, $current)
  54. {
  55. // consume until newline
  56. $content = [];
  57. for ($i = $current, $count = count($lines); $i < $count; $i++) {
  58. $line = $lines[$i];
  59. if ($line === ''
  60. || ltrim($line) === ''
  61. || !ctype_alpha($line[0]) && (
  62. $this->identifyQuote($line, $lines, $i) ||
  63. $this->identifyFencedCode($line, $lines, $i) ||
  64. $this->identifyUl($line, $lines, $i) ||
  65. $this->identifyOl($line, $lines, $i) ||
  66. $this->identifyHr($line, $lines, $i)
  67. )
  68. || $this->identifyHeadline($line, $lines, $i))
  69. {
  70. break;
  71. } elseif ($this->identifyCode($line, $lines, $i)) {
  72. // possible beginning of a code block
  73. // but check for continued inline HTML
  74. // e.g. <img src="file.jpg"
  75. // alt="some alt aligned with src attribute" title="some text" />
  76. if (preg_match('~<\w+([^>]+)$~s', implode("\n", $content))) {
  77. $content[] = $line;
  78. } else {
  79. break;
  80. }
  81. } else {
  82. $content[] = $line;
  83. }
  84. }
  85. $block = [
  86. 'paragraph',
  87. 'content' => $this->parseInline(implode("\n", $content)),
  88. ];
  89. return [$block, --$i];
  90. }
  91. /**
  92. * @inheritdocs
  93. *
  94. * Parses a newline indicated by two spaces on the end of a markdown line.
  95. */
  96. protected function renderText($text)
  97. {
  98. if ($this->enableNewlines) {
  99. $br = $this->html5 ? "<br>\n" : "<br />\n";
  100. return strtr($text[1], [" \n" => $br, "\n" => $br]);
  101. } else {
  102. return parent::renderText($text);
  103. }
  104. }
  105. }