git.iko.soy/typeable/pandoc
on master help sign in
Org reader: add auto identifiers if not present on headers
f1c87edJuliusz Gonera
src/Text/Pandoc.hs+2−1
@@ -320,7 +320,8 @@ getDefaultExtensions "markdown_mmd" = multimarkdownExtensions
320getDefaultExtensions "markdown_github" = githubMarkdownExtensions
320getDefaultExtensions "markdown_github" = githubMarkdownExtensions
321getDefaultExtensions "markdown" = pandocExtensions
321getDefaultExtensions "markdown" = pandocExtensions
322getDefaultExtensions "plain" = plainExtensions
322getDefaultExtensions "plain" = plainExtensions
323−getDefaultExtensions "org" = Set.fromList [Ext_citations]
323+getDefaultExtensions "org" = Set.fromList [Ext_citations,
324+ Ext_auto_identifiers]
324getDefaultExtensions "textile" = Set.fromList [Ext_auto_identifiers]
325getDefaultExtensions "textile" = Set.fromList [Ext_auto_identifiers]
325getDefaultExtensions "html" = Set.fromList [Ext_auto_identifiers,
326getDefaultExtensions "html" = Set.fromList [Ext_auto_identifiers,
326 Ext_native_divs,
327 Ext_native_divs,
src/Text/Pandoc/Readers/Org.hs+16−1
@@ -70,6 +70,14 @@ data OrgParserLocal = OrgParserLocal { orgLocalQuoteContext :: QuoteContext }
70
70
71type OrgParser = ParserT [Char] OrgParserState (Reader OrgParserLocal)
71type OrgParser = ParserT [Char] OrgParserState (Reader OrgParserLocal)
72
72
73+instance HasIdentifierList OrgParserState where
74+ extractIdentifierList = orgStateIdentifiers
75+ updateIdentifierList f s = s{ orgStateIdentifiers = f (orgStateIdentifiers s) }
76+
77+instance HasHeaderMap OrgParserState where
78+ extractHeaderMap = orgStateHeaderMap
79+ updateHeaderMap f s = s{ orgStateHeaderMap = f (orgStateHeaderMap s) }
80+
73parseOrg :: OrgParser Pandoc
81parseOrg :: OrgParser Pandoc
74parseOrg = do
82parseOrg = do
75 blocks' <- parseBlocks
83 blocks' <- parseBlocks
@@ -135,6 +143,8 @@ data OrgParserState = OrgParserState
135 , orgStateMeta :: Meta
143 , orgStateMeta :: Meta
136 , orgStateMeta' :: F Meta
144 , orgStateMeta' :: F Meta
137 , orgStateNotes' :: OrgNoteTable
145 , orgStateNotes' :: OrgNoteTable
146+ , orgStateIdentifiers :: [String]
147+ , orgStateHeaderMap :: M.Map Inlines String
138 }
148 }
139
149
140instance Default OrgParserLocal where
150instance Default OrgParserLocal where
@@ -174,6 +184,8 @@ defaultOrgParserState = OrgParserState
174 , orgStateMeta = nullMeta
184 , orgStateMeta = nullMeta
175 , orgStateMeta' = return nullMeta
185 , orgStateMeta' = return nullMeta
176 , orgStateNotes' = []
186 , orgStateNotes' = []
187+ , orgStateIdentifiers = []
188+ , orgStateHeaderMap = M.empty
177 }
189 }
178
190
179recordAnchorId :: String -> OrgParser ()
191recordAnchorId :: String -> OrgParser ()
@@ -668,7 +680,10 @@ header = try $ do
668 title <- manyTill inline (lookAhead headerEnd)
680 title <- manyTill inline (lookAhead headerEnd)
669 tags <- headerEnd
681 tags <- headerEnd
670 let inlns = trimInlinesF . mconcat $ title <> map tagToInlineF tags
682 let inlns = trimInlinesF . mconcat $ title <> map tagToInlineF tags
683+ st <- getState
684+ let inlines = runF inlns st
685+ attr <- registerHeader nullAttr inlines
671− return $ B.header level <$> inlns
686+ return $ pure (B.headerWith attr level inlines)
672 where
687 where
673 tagToInlineF :: String -> F Inlines
688 tagToInlineF :: String -> F Inlines
674 tagToInlineF t = return $ B.spanWith ("", ["tag"], [("data-tag-name", t)]) mempty
689 tagToInlineF t = return $ B.spanWith ("", ["tag"], [("data-tag-name", t)]) mempty
tests/Tests/Readers/Org.hs+38−20
@@ -457,21 +457,25 @@ tests =
457
457
458 , "First Level Header" =:
458 , "First Level Header" =:
459 "* Headline\n" =?>
459 "* Headline\n" =?>
460− header 1 "Headline"
460+ headerWith ("headline", [], []) 1 "Headline"
461
461
462 , "Third Level Header" =:
462 , "Third Level Header" =:
463 "*** Third Level Headline\n" =?>
463 "*** Third Level Headline\n" =?>
464− header 3 ("Third" <> space <>
464+ headerWith ("third-level-headline", [], [])
465+ 3
465− "Level" <> space <>
466+ ("Third" <> space <> "Level" <> space <> "Headline")
466− "Headline")
467
467
468 , "Compact Headers with Paragraph" =:
468 , "Compact Headers with Paragraph" =:
469 unlines [ "* First Level"
469 unlines [ "* First Level"
470 , "** Second Level"
470 , "** Second Level"
471 , " Text"
471 , " Text"
472 ] =?>
472 ] =?>
473+ mconcat [ headerWith ("first-level", [], [])
474+ 1
473− mconcat [ header 1 ("First" <> space <> "Level")
475+ ("First" <> space <> "Level")
476+ , headerWith ("second-level", [], [])
477+ 2
474− , header 2 ("Second" <> space <> "Level")
478+ ("Second" <> space <> "Level")
475 , para "Text"
479 , para "Text"
476 ]
480 ]
477
481
@@ -482,8 +486,12 @@ tests =
482 , ""
486 , ""
483 , " Text"
487 , " Text"
484 ] =?>
488 ] =?>
489+ mconcat [ headerWith ("first-level", [], [])
490+ 1
485− mconcat [ header 1 ("First" <> space <> "Level")
491+ ("First" <> space <> "Level")
492+ , headerWith ("second-level", [], [])
493+ 2
486− , header 2 ("Second" <> space <> "Level")
494+ ("Second" <> space <> "Level")
487 , para "Text"
495 , para "Text"
488 ]
496 ]
489
497
@@ -492,9 +500,13 @@ tests =
492 , "Spaghetti and meatballs tonight."
500 , "Spaghetti and meatballs tonight."
493 , "** walk dog"
501 , "** walk dog"
494 ] =?>
502 ] =?>
503+ mconcat [ headerWith ("eat-dinner", [], [])
504+ 2
495− mconcat [ header 2 ("eat" <> space <> "dinner")
505+ ("eat" <> space <> "dinner")
496 , para $ spcSep [ "Spaghetti", "and", "meatballs", "tonight." ]
506 , para $ spcSep [ "Spaghetti", "and", "meatballs", "tonight." ]
507+ , headerWith ("walk-dog", [], [])
508+ 2
497− , header 2 ("walk" <> space <> "dog")
509+ ("walk" <> space <> "dog")
498 ]
510 ]
499
511
500 , "Tagged headers" =:
512 , "Tagged headers" =:
@@ -503,14 +515,20 @@ tests =
503 , "** Call John :@PHONE:JOHN: "
515 , "** Call John :@PHONE:JOHN: "
504 ] =?>
516 ] =?>
505 let tagSpan t = spanWith ("", ["tag"], [("data-tag-name", t)]) mempty
517 let tagSpan t = spanWith ("", ["tag"], [("data-tag-name", t)]) mempty
518+ in mconcat [ headerWith ("personal", [], [])
519+ 1
506− in mconcat [ header 1 ("Personal" <> tagSpan "PERSONAL")
520+ ("Personal" <> tagSpan "PERSONAL")
521+ , headerWith ("call-mom", [], [])
522+ 2
507− , header 2 ("Call Mom" <> tagSpan "@PHONE")
523+ ("Call Mom" <> tagSpan "@PHONE")
524+ , headerWith ("call-john", [], [])
525+ 2
508− , header 2 ("Call John" <> tagSpan "@PHONE" <> tagSpan "JOHN")
526+ ("Call John" <> tagSpan "@PHONE" <> tagSpan "JOHN")
509 ]
527 ]
510
528
511 , "Untagged header containing colons" =:
529 , "Untagged header containing colons" =:
512 "* This: is not: tagged" =?>
530 "* This: is not: tagged" =?>
513− header 1 "This: is not: tagged"
531+ headerWith ("this-is-not-tagged", [], []) 1 "This: is not: tagged"
514
532
515 , "Comment Trees" =:
533 , "Comment Trees" =:
516 unlines [ "* COMMENT A comment tree"
534 unlines [ "* COMMENT A comment tree"
@@ -518,7 +536,7 @@ tests =
518 , "** This will be dropped"
536 , "** This will be dropped"
519 , "* Comment tree above"
537 , "* Comment tree above"
520 ] =?>
538 ] =?>
521− header 1 "Comment tree above"
539+ headerWith ("comment-tree-above", [], []) 1 "Comment tree above"
522
540
523 , "Nothing but a COMMENT header" =:
541 , "Nothing but a COMMENT header" =:
524 "* COMMENT Test" =?>
542 "* COMMENT Test" =?>
@@ -640,7 +658,7 @@ tests =
640 [ "Another", space, "note"
658 [ "Another", space, "note"
641 , note $ para ("This" <> space <> "is" <> space <> "great!")
659 , note $ para ("This" <> space <> "is" <> space <> "great!")
642 ])
660 ])
643− , header 2 "Headline"
661+ , headerWith ("headline", [], []) 2 "Headline"
644 ]
662 ]
645 ]
663 ]
646
664
@@ -664,7 +682,7 @@ tests =
664 "* Item2\n") =?>
682 "* Item2\n") =?>
665 bulletList [ plain "Item1"
683 bulletList [ plain "Item1"
666 ] <>
684 ] <>
667− header 1 "Item2"
685+ headerWith ("item2", [], []) 1 "Item2"
668
686
669 , "Multi-line Bullet Lists" =:
687 , "Multi-line Bullet Lists" =:
670 ("- *Fat\n" ++
688 ("- *Fat\n" ++
@@ -724,7 +742,7 @@ tests =
724 mconcat [ bulletList [ plain "Discovery"
742 mconcat [ bulletList [ plain "Discovery"
725 , plain ("Human" <> space <> "After" <> space <> "All")
743 , plain ("Human" <> space <> "After" <> space <> "All")
726 ]
744 ]
727− , header 1 "Homework"
745+ , headerWith ("homework", [], []) 1 "Homework"
728 ]
746 ]
729
747
730 , "Bullet List Unindented with trailing Header" =:
748 , "Bullet List Unindented with trailing Header" =:
@@ -734,7 +752,7 @@ tests =
734 mconcat [ bulletList [ plain "Discovery"
752 mconcat [ bulletList [ plain "Discovery"
735 , plain "Homework"
753 , plain "Homework"
736 ]
754 ]
737− , header 1 "NotValidListItem"
755+ , headerWith ("notvalidlistitem", [], []) 1 "NotValidListItem"
738 ]
756 ]
739
757
740 , "Simple Ordered List" =:
758 , "Simple Ordered List" =:
@@ -839,7 +857,7 @@ tests =
839 mconcat [ definitionList [ ("definition", [plain "list"])
857 mconcat [ definitionList [ ("definition", [plain "list"])
840 , ("cool", [plain "defs"])
858 , ("cool", [plain "defs"])
841 ]
859 ]
842− , header 1 "header"
860+ , headerWith ("header", [], []) 1 "header"
843 ]
861 ]
844
862
845 , "Loose bullet list" =:
863 , "Loose bullet list" =: