git.iko.soy/typeable/pandoc
on master help sign in
Org reader: support Pandocs citation extension
ceeb701Albert Krewinkel
src/Text/Pandoc.hs+1−1
@@ -275,6 +275,7 @@ getDefaultExtensions "markdown_mmd" = multimarkdownExtensions
275getDefaultExtensions "markdown_github" = githubMarkdownExtensions
275getDefaultExtensions "markdown_github" = githubMarkdownExtensions
276getDefaultExtensions "markdown" = pandocExtensions
276getDefaultExtensions "markdown" = pandocExtensions
277getDefaultExtensions "plain" = pandocExtensions
277getDefaultExtensions "plain" = pandocExtensions
278+getDefaultExtensions "org" = Set.fromList [Ext_citations]
278getDefaultExtensions "textile" = Set.fromList [Ext_auto_identifiers, Ext_raw_tex]
279getDefaultExtensions "textile" = Set.fromList [Ext_auto_identifiers, Ext_raw_tex]
279getDefaultExtensions _ = Set.fromList [Ext_auto_identifiers]
280getDefaultExtensions _ = Set.fromList [Ext_auto_identifiers]
280
281
@@ -319,4 +320,3 @@ readJSON _ = either error id . eitherDecode' . UTF8.fromStringLazy
319
320
320writeJSON :: WriterOptions -> Pandoc -> String
321writeJSON :: WriterOptions -> Pandoc -> String
321writeJSON _ = UTF8.toStringLazy . encode
322writeJSON _ = UTF8.toStringLazy . encode
322−
src/Text/Pandoc/Readers/Org.hs+53−2
@@ -869,6 +869,7 @@ inline :: OrgParser (F Inlines)
869inline =
869inline =
870 choice [ whitespace
870 choice [ whitespace
871 , linebreak
871 , linebreak
872+ , cite
872 , footnote
873 , footnote
873 , linkOrImage
874 , linkOrImage
874 , anchor
875 , anchor
@@ -933,6 +934,51 @@ endline = try $ do
933 updateLastPreCharPos
934 updateLastPreCharPos
934 return . return $ B.space
935 return . return $ B.space
935
936
937+cite :: OrgParser (F Inlines)
938+cite = try $ do
939+ guardEnabled Ext_citations
940+ (cs, raw) <- withRaw normalCite
941+ return $ (flip B.cite (B.text raw)) <$> cs
942+
943+normalCite :: OrgParser (F [Citation])
944+normalCite = try $ char '['
945+ *> skipSpaces
946+ *> citeList
947+ <* skipSpaces
948+ <* char ']'
949+
950+citeList :: OrgParser (F [Citation])
951+citeList = sequence <$> sepBy1 citation (try $ char ';' *> skipSpaces)
952+
953+citation :: OrgParser (F Citation)
954+citation = try $ do
955+ pref <- prefix
956+ (suppress_author, key) <- citeKey
957+ suff <- suffix
958+ return $ do
959+ x <- pref
960+ y <- suff
961+ return $ Citation{ citationId = key
962+ , citationPrefix = B.toList x
963+ , citationSuffix = B.toList y
964+ , citationMode = if suppress_author
965+ then SuppressAuthor
966+ else NormalCitation
967+ , citationNoteNum = 0
968+ , citationHash = 0
969+ }
970+ where
971+ prefix = trimInlinesF . mconcat <$>
972+ manyTill inline (char ']' <|> (']' <$ lookAhead citeKey))
973+ suffix = try $ do
974+ hasSpace <- option False (notFollowedBy nonspaceChar >> return True)
975+ skipSpaces
976+ rest <- trimInlinesF . mconcat <$>
977+ many (notFollowedBy (oneOf ";]") *> inline)
978+ return $ if hasSpace
979+ then (B.space <>) <$> rest
980+ else rest
981+
936footnote :: OrgParser (F Inlines)
982footnote :: OrgParser (F Inlines)
937footnote = try $ inlineNote <|> referencedNote
983footnote = try $ inlineNote <|> referencedNote
938
984
@@ -1007,7 +1053,7 @@ selfTarget :: OrgParser String
1007selfTarget = try $ char '[' *> linkTarget <* char ']'
1053selfTarget = try $ char '[' *> linkTarget <* char ']'
1008
1054
1009linkTarget :: OrgParser String
1055linkTarget :: OrgParser String
1010−linkTarget = enclosed (char '[') (char ']') (noneOf "\n\r[]")
1056+linkTarget = enclosedByPair '[' ']' (noneOf "\n\r[]")
1011
1057
1012applyCustomLinkFormat :: String -> OrgParser (F String)
1058applyCustomLinkFormat :: String -> OrgParser (F String)
1013applyCustomLinkFormat link = do
1059applyCustomLinkFormat link = do
@@ -1083,7 +1129,12 @@ inlineCodeBlock = try $ do
1083 let attrClasses = [translateLang lang, rundocBlockClass]
1129 let attrClasses = [translateLang lang, rundocBlockClass]
1084 let attrKeyVal = map toRundocAttrib (("language", lang) : opts)
1130 let attrKeyVal = map toRundocAttrib (("language", lang) : opts)
1085 returnF $ B.codeWith ("", attrClasses, attrKeyVal) inlineCode
1131 returnF $ B.codeWith ("", attrClasses, attrKeyVal) inlineCode
1132+
1133+enclosedByPair :: Char -- ^ opening char
1134+ -> Char -- ^ closing char
1135+ -> OrgParser a -- ^ parser
1136+ -> OrgParser [a]
1086− where enclosedByPair s e p = char s *> many1Till p (char e)
1137+enclosedByPair s e p = char s *> many1Till p (char e)
1087
1138
1088emph :: OrgParser (F Inlines)
1139emph :: OrgParser (F Inlines)
1089emph = fmap B.emph <$> emphasisBetween '/'
1140emph = fmap B.emph <$> emphasisBetween '/'
tests/Tests/Readers/Org.hs+22
@@ -225,6 +225,28 @@ tests =
225 ]
225 ]
226 )
226 )
227 "echo 'Hello, World'")
227 "echo 'Hello, World'")
228+
229+ , "Citation" =:
230+ "[@nonexistent]" =?>
231+ let citation = Citation
232+ { citationId = "nonexistent"
233+ , citationPrefix = []
234+ , citationSuffix = []
235+ , citationMode = NormalCitation
236+ , citationNoteNum = 0
237+ , citationHash = 0}
238+ in (para $ cite [citation] "[@nonexistent]")
239+
240+ , "Citation containing text" =:
241+ "[see @item1 p. 34-35]" =?>
242+ let citation = Citation
243+ { citationId = "item1"
244+ , citationPrefix = [Str "see"]
245+ , citationSuffix = [Space ,Str "p.",Space,Str "34-35"]
246+ , citationMode = NormalCitation
247+ , citationNoteNum = 0
248+ , citationHash = 0}
249+ in (para $ cite [citation] "[see @item1 p. 34-35]")
228 ]
250 ]
229
251
230 , testGroup "Meta Information" $
252 , testGroup "Meta Information" $