From cd0653914a05c0753f1732d60a1fc9b1e183e734 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 31 Oct 2023 16:54:03 -0700 Subject: [PATCH] Parse footnote definitions with lazy continuation Fixes #126 This change brings it into alignment with GitHub, [markdown-it](https://markdown-it.github.io/#md3=%7B%22source%22%3A%22%5B%5Efoo%5D%3Abar%5Cnbaz%5Cn%5Cn%20%20%20%20quux%5Cnarst%5Cn%20%20%20%20qwfp%5Cn%5Cn%5B%5Efoo%5D%22%2C%22defaults%22%3A%7B%22html%22%3Afalse%2C%22xhtmlOut%22%3Afalse%2C%22breaks%22%3Afalse%2C%22langPrefix%22%3A%22language-%22%2C%22linkify%22%3Atrue%2C%22typographer%22%3Atrue%2C%22_highlight%22%3Atrue%2C%22_strict%22%3Afalse%2C%22_view%22%3A%22html%22%7D%7D), and hugo/goldmark. --- .../src/Commonmark/Extensions/Footnote.hs | 20 ++++--- commonmark-extensions/test/footnotes.md | 56 +++++++++++++++++++ 2 files changed, 69 insertions(+), 7 deletions(-) diff --git a/commonmark-extensions/src/Commonmark/Extensions/Footnote.hs b/commonmark-extensions/src/Commonmark/Extensions/Footnote.hs index c2d11b1..8fd555a 100644 --- a/commonmark-extensions/src/Commonmark/Extensions/Footnote.hs +++ b/commonmark-extensions/src/Commonmark/Extensions/Footnote.hs @@ -66,25 +66,31 @@ footnoteBlockSpec = BlockSpec updateState $ \s -> s{ counters = M.insert "footnote" (toDyn (num + 1)) (counters s) } + isBlankLine <- option False $ try (skipWhile (hasType Spaces) >> True <$ lookAhead lineEnd) addNodeToStack $ Node (defBlockData footnoteBlockSpec){ - blockData = toDyn (num, lab') + blockData = toDyn (num, lab', isBlankLine) , blockStartPos = [pos] } [] return BlockStartMatch , blockCanContain = const True , blockContainsLines = False , blockParagraph = False - , blockContinue = \n -> try $ do - () <$ (gobbleSpaces 4) - <|> (skipWhile (hasType Spaces) >> () <$ lookAhead lineEnd) - pos <- getPosition - return $! (pos, n) + , blockContinue = \(Node root children) -> try $ do + let (num, lab', needsIndented) = fromDyn (blockData root) (1 :: Int, mempty :: Text, False) + isBlankLine <- option False $ try (skipWhile (hasType Spaces) >> True <$ lookAhead lineEnd) + if needsIndented && not isBlankLine then + gobbleSpaces 4 + else + gobbleUpToSpaces 4 + pos <- getPosition + let footnoteData = toDyn (num, lab', isBlankLine) + return $! (pos, Node root{ blockData = footnoteData} children) , blockConstructor = \node -> mconcat <$> mapM (\n -> blockConstructor (blockSpec (rootLabel n)) n) (subForest (reverseSubforests node)) , blockFinalize = \(Node root children) parent -> do - let (num, lab') = fromDyn (blockData root) (1, mempty) + let (num, lab', _indented) = fromDyn (blockData root) (1, mempty, False) st <- getState let mkNoteContents refmap = runParserT diff --git a/commonmark-extensions/test/footnotes.md b/commonmark-extensions/test/footnotes.md index 148e5f9..b98673a 100644 --- a/commonmark-extensions/test/footnotes.md +++ b/commonmark-extensions/test/footnotes.md @@ -196,3 +196,59 @@ second [^third fourth]

```````````````````````````````` + +Only the first line of a footnote's following paragraph needs indented. + +```````````````````````````````` example +[^foo]:bar +baz + + quux +arst + qwfp + +[^foo] +. +

1

+
+
+
+1 +
+
+

bar +baz

+

quux +arst +qwfp

+
+
+
+```````````````````````````````` + +Lazy continuations require the first line to have text in it, +and to lazily continue a paragraph after the first, it will need to +start with an indented line also. + +```````````````````````````````` example +[^foo]: +baz + + quux + +[^foo] +. +

baz

+
quux
+
+

1

+
+
+
+1 +
+
+
+
+
+````````````````````````````````