diff --git a/MarkdownExtra.php b/MarkdownExtra.php index eedcf77..c20614e 100644 --- a/MarkdownExtra.php +++ b/MarkdownExtra.php @@ -2,6 +2,7 @@ namespace cebe\markdown; +use cebe\markdown\block\FooterTrait; use cebe\markdown\block\TableTrait; // work around https://github.com/facebook/hhvm/issues/1120 @@ -19,6 +20,7 @@ class MarkdownExtra extends Markdown // include block element parsing using traits use block\TableTrait; use block\FencedCodeTrait; + use block\FooterTrait; // include inline element parsing using traits // TODO @@ -60,8 +62,6 @@ class MarkdownExtra extends Markdown // TODO implement definition lists - // TODO implement footnotes - // TODO implement Abbreviations diff --git a/block/FooterTrait.php b/block/FooterTrait.php new file mode 100644 index 0000000..d215284 --- /dev/null +++ b/block/FooterTrait.php @@ -0,0 +1,154 @@ + + * @copyright 1997-2021 Pan Russian solovov.ru + */ + +namespace cebe\markdown\block; + + +trait FooterTrait +{ + + protected $footnotes = []; + protected $footnoteNum = 1; + + /** + * @param $text + * @return string + */ + public function parse($text) + { + $absy = $this->parseBlocks(explode("\n", $text)); + + foreach ($absy as $block) { + if ($block[0] == 'footnote') { + $block['num'] = $this->footnoteNum; + $this->footnotes[] = $block; + $this->footnoteNum++; + } + } + $markup = parent::parse($text); + $markup = $this->applyFooter($markup, $this->footnotes); + + return $markup; + } + + /** + * @param $content + * @param $blocks + * @return string + */ + protected function applyFooter($content, $blocks) + { + foreach ($blocks as $block) { + $number = $block['num'] . ". "; + $link = ''; + $text = $this->renderAbsy($block['content']); + $text = $this->renderAbsy($this->parseInline($text)); + $text = substr_replace($text, $number, 3, 0); + $text = substr_replace($text, $link, -5, 0); + + $content .= '' . $text . "\n"; + } + return $content; + } + + /** + * Parses a footnote link indicated by `[^`. + * @marker [^ + * @param $text + * @return array + */ + protected function parseFootnoteLink($text) + { + if (preg_match('/^\[\^(.+?)\]/', $text, $matches)) { + return [ + ['footnoteLink', $matches[1]], + strlen($matches[0]) + ]; + } + return [['text', $text[0]], 1]; + } + + /** + * @param $block + * @return string + */ + protected function renderFootnoteLink($block) + { + $footnoteId = $block[1]; + $num = 0; + $found = false; + foreach ($this->footnotes as $footnote) { + $num ++; + if ($footnote['id']==$footnoteId) { + $found = true; + break; + } + } + if (!$found) + $num = '?'; + + $text = htmlspecialchars($block[1], ENT_NOQUOTES | ENT_SUBSTITUTE, 'UTF-8'); + return '[' . $num . ']'; + } + + /** + * identify a line as the beginning of a footnote block + * + * @param $line + * @return false|int + */ + protected function identifyFootnoteList($line) + { + return preg_match('/^\[\^(.+?)\]:/', $line); + } + + /** + * Consume lines for a footnote + */ + protected function consumeFootnoteList($lines, $current) + { + $id = ''; + $content = []; + $count = count($lines); + for ($i = $current; $i < $count; $i++) { + $line = $lines[$i]; + + if ($id == '') { + if (preg_match('/^\[\^(.+?)\]:[ \t]+/', $line, $matches)) { + $id = $matches[1]; + $str = substr($line, strlen($matches[0])); + $content[] = $str; + } + } else if (strlen(trim($line)) == 0) { + break; + } else { + $content[] = ltrim($line); + } + } + + $block = ['footnote', 'id' => $id, 'content' => $this->parseBlocks($content)]; + + return [$block, $i]; + } + + /** + * @param $block + * @return string + */ + protected function renderFootnote($block) + { + return ''; + } + + +} \ No newline at end of file diff --git a/tests/extra-data/footernote.md b/tests/extra-data/footernote.md new file mode 100644 index 0000000..cd47d7f --- /dev/null +++ b/tests/extra-data/footernote.md @@ -0,0 +1,3 @@ +The implementation focus is to be fast (see benchmark) and extensible [^1] + +[^1]: See [benchmark](https://github.com/kzykhys/Markbench#readme). \ No newline at end of file diff --git a/tests/extra-data/foternote.html b/tests/extra-data/foternote.html new file mode 100644 index 0000000..85d2a0c --- /dev/null +++ b/tests/extra-data/foternote.html @@ -0,0 +1,6 @@ +The implementation focus is to be fast (see benchmark) and extensible [1] + +
+

1. See benchmark. +

+
\ No newline at end of file