Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -11,11 +11,10 @@ unzip "${TMP_KD2}/kd2.zip" -d include/lib rm -rf ${TMP_KD2} wget -O "include/lib/Parsedown.php" "https://raw.githubusercontent.com/erusev/parsedown/1.7.x/Parsedown.php" - wget -O "include/lib/ParsedownExtra.php" "https://raw.githubusercontent.com/erusev/parsedown-extra/0.8.x/ParsedownExtra.php" dev-server: php -S localhost:8082 -t www www/_route.php test: Index: src/include/lib/Garradin/Web/Render/Parsedown.php ================================================================== --- src/include/lib/Garradin/Web/Render/Parsedown.php +++ src/include/lib/Garradin/Web/Render/Parsedown.php @@ -1,32 +1,38 @@ BlockTypes['<'][] = 'SkrivExtension'; $this->BlockTypes['['][]= 'TOC'; - parent::__construct(); + # identify footnote definitions before reference definitions + array_unshift($this->BlockTypes['['], 'Footnote'); + + # identify footnote markers before before links + array_unshift($this->InlineTypes['['], 'FootnoteMarker'); + $this->skriv = new Skriv($file); } protected function blockSkrivExtension(array $line): ?array { @@ -114,10 +120,102 @@ $out .= ''; return $out; } + + /** + * Footnotes implementation, inspired by ParsedownExtra + * We're not using ParsedownExtra as it's buggy and unmaintained + */ + protected function blockFootnote(array $line): ?array + { + if (preg_match('/^\[\^(.+?)\]:[ ]?(.*)$/', $line['text'], $matches)) + { + $block = array( + 'footnotes' => [$matches[1] => $matches[2]], + ); + + return $block; + } + + return null; + } + + protected function blockFootnoteContinue(array $line, array $block): ?array + { + if ($line['text'][0] === '[' && preg_match('/^\[\^(.+?)\]: ?(.*)$/', $line['text'], $matches)) + { + $block['footnotes'][$matches[1]] = $matches[2]; + return $block; + } + + end($block['footnotes']); + $last = key($block['footnotes']); + + if (isset($block['interrupted'])) + { + if ($line['indent'] >= 4) + { + $block['footnotes'][$last] .= "\n\n" . $line['text']; + + return $block; + } + } + else + { + $block['footnotes'][$last] .= "\n" . $line['text']; + + return $block; + } + } + + protected function blockFootnoteComplete(array $in) + { + $html = ''; + + foreach ($in['footnotes'] as $name => $value) { + $html .= sprintf('