diff --git a/src/Text/Pandoc/Parsing.hs b/src/Text/Pandoc/Parsing.hs index 0bb609e5d..44a64c80a 100644 --- a/src/Text/Pandoc/Parsing.hs +++ b/src/Text/Pandoc/Parsing.hs @@ -794,7 +794,7 @@ data ParserState = ParserState stateAuthors :: [[Inline]], -- ^ Authors of document stateDate :: [Inline], -- ^ Date of document stateHeaderTable :: [HeaderType], -- ^ Ordered list of header types used - stateHeaders :: [[Inline]], -- ^ List of headers (used for implicit ref links) + stateHeaders :: M.Map Inlines String, -- ^ List of headers and ids (used for implicit ref links) stateIdentifiers :: [String], -- ^ List of header identifiers used stateNextExample :: Int, -- ^ Number of next example stateExamples :: M.Map String Int, -- ^ Map from example labels to numbers @@ -823,7 +823,7 @@ defaultParserState = stateAuthors = [], stateDate = [], stateHeaderTable = [], - stateHeaders = [], + stateHeaders = M.empty, stateIdentifiers = [], stateNextExample = 1, stateExamples = M.empty, diff --git a/src/Text/Pandoc/Readers/Markdown.hs b/src/Text/Pandoc/Readers/Markdown.hs index e037c0897..29eac02bf 100644 --- a/src/Text/Pandoc/Readers/Markdown.hs +++ b/src/Text/Pandoc/Readers/Markdown.hs @@ -390,15 +390,22 @@ header = setextHeader <|> atxHeader <?> "header" -- returns unique identifier addToHeaderList :: Attr -> F Inlines -> MarkdownParser Attr addToHeaderList (ident,classes,kvs) text = do - let headerList = B.toList $ runF text defaultParserState - updateState $ \st -> st{ stateHeaders = headerList : stateHeaders st } - (do guardEnabled Ext_auto_identifiers - ids <- stateIdentifiers `fmap` getState - let id' = if null ident - then uniqueIdent headerList ids - else ident - updateState $ \st -> st{ stateIdentifiers = id' : ids } - return (id',classes,kvs)) <|> return ("",classes,kvs) + let header' = runF text defaultParserState + exts <- getOption readerExtensions + let insert' = M.insertWith (\_new old -> old) + if null ident && Ext_auto_identifiers `Set.member` exts + then do + ids <- stateIdentifiers `fmap` getState + let id' = uniqueIdent (B.toList header') ids + updateState $ \st -> st{ + stateIdentifiers = id' : ids, + stateHeaders = insert' header' id' $ stateHeaders st } + return (id',classes,kvs) + else do + unless (null ident) $ + updateState $ \st -> st{ + stateHeaders = insert' header' ident $ stateHeaders st } + return (ident,classes,kvs) atxHeader :: MarkdownParser (F Blocks) atxHeader = try $ do @@ -1539,13 +1546,13 @@ referenceLink constructor (lab, raw) = do case M.lookup key keys of Nothing -> do headers <- asksF stateHeaders - let ref' = B.toList $ runF (if labIsRef then lab else ref) - defaultParserState - if implicitHeaderRefs && ref' `elem` headers - then do - let src = '#' : uniqueIdent ref' [] - constructor src "" <$> lab - else (\x -> B.str "[" <> x <> B.str "]" <> B.str raw') <$> fallback + let ref' = runF (if labIsRef then lab else ref) defaultParserState + let makeFallback x = B.str "[" <> x <> B.str "]" <> B.str raw' + if implicitHeaderRefs + then case M.lookup ref' headers of + Just ident -> constructor ('#':ident) "" <$> lab + Nothing -> makeFallback <$> fallback + else makeFallback <$> fallback Just (src,tit) -> constructor src tit <$> lab bareURL :: MarkdownParser (F Inlines) diff --git a/tests/markdown-reader-more.native b/tests/markdown-reader-more.native index 84d3a71e2..612358522 100644 --- a/tests/markdown-reader-more.native +++ b/tests/markdown-reader-more.native @@ -61,8 +61,9 @@ ,Header 2 ("implicit-header-references",[],[]) [Str "Implicit",Space,Str "header",Space,Str "references"] ,Header 3 ("my-header-1",[],[]) [Str "My",Space,Str "header"] ,Header 3 ("my-other-header",[],[]) [Str "My",Space,Str "other",Space,Str "header"] -,Para [Str "A",Space,Str "link",Space,Str "to",Space,Link [Str "My",Space,Str "header"] ("#my-header",""),Str "."] -,Para [Str "Another",Space,Str "link",Space,Str "to",Space,Link [Str "it"] ("#my-header",""),Str "."] +,Para [Str "A",Space,Str "link",Space,Str "to",Space,Link [Str "My",Space,Str "header"] ("#my-header-1",""),Str "."] +,Para [Str "Another",Space,Str "link",Space,Str "to",Space,Link [Str "it"] ("#my-header-1",""),Str "."] +,Para [Str "Link",Space,Str "to",Space,Link [Str "Explicit",Space,Str "header",Space,Str "attributes"] ("#foobar",""),Str "."] ,Para [Str "But",Space,Str "this",Space,Str "is",Space,Str "not",Space,Str "a",Space,Str "link",Space,Str "to",Space,Link [Str "My",Space,Str "other",Space,Str "header"] ("/foo",""),Str ",",Space,Str "since",Space,Str "the",Space,Str "reference",Space,Str "is",Space,Str "defined."] ,Header 2 ("foobar",["baz"],[("key","val")]) [Str "Explicit",Space,Str "header",Space,Str "attributes"] ,Header 2 ("line-blocks",[],[]) [Str "Line",Space,Str "blocks"] diff --git a/tests/markdown-reader-more.txt b/tests/markdown-reader-more.txt index b0a4ff6e8..cf5e930e1 100644 --- a/tests/markdown-reader-more.txt +++ b/tests/markdown-reader-more.txt @@ -144,6 +144,8 @@ A link to [My header]. Another link to [it][My header]. +Link to [Explicit header attributes]. + [my other header]: /foo But this is not a link to [My other header], since the reference is defined.