git.iko.soy/typeable/pandoc
on master help sign in
Org reader: support org-ref style citations

The *org-ref* package is an org-mode extension commonly used to manage citations in org documents. Basic support for the `cite:citeKey` and `[[cite:citeKey][prefix text::suffix text]]` syntax is added.

commitf226cb88b040dcd19e09ca7772ee0c6172eaecc2 authorAlbert Krewinkel <albert@zeitkraut.de> dateFri 27 May 2016, 09:19 (10 years ago) parentf54873d
3 files changed+107−7
src/Text/Pandoc/Readers/Org/Inlines.hs+70−7 src/Text/Pandoc/Readers/Org/Parsing.hs+1 tests/Tests/Readers/Org.hs+36
src/Text/Pandoc/Readers/Org/Inlines.hs+70−7
@@ -192,15 +192,78 @@ endline = try $ do
192192cite :: OrgParser (F Inlines)
193193cite = try $ do
194194 guardEnabled Ext_citations
195− (cs, raw) <- withRaw normalCite
195+ (cs, raw) <- withRaw (pandocOrgCite <|> orgRefCite)
196196 return $ (flip B.cite (B.text raw)) <$> cs
197197
198−normalCite :: OrgParser (F [Citation])
199−normalCite = try $ char '['
200− *> skipSpaces
201− *> citeList
202− <* skipSpaces
203− <* char ']'
198+-- | A citation in Pandoc Org-mode style (@[\@citekey]@).
199+pandocOrgCite :: OrgParser (F [Citation])
200+pandocOrgCite = try $
201+ char '[' *> skipSpaces *> citeList <* skipSpaces <* char ']'
202+
203+orgRefCite :: OrgParser (F [Citation])
204+orgRefCite = try $ normalOrgRefCite <|> (fmap (:[]) <$> linkLikeOrgRefCite)
205+
206+normalOrgRefCite :: OrgParser (F [Citation])
207+normalOrgRefCite = try $ do
208+ mode <- orgRefCiteMode
209+ sequence <$> sepBy1 (orgRefCiteList mode) (char ',')
210+ where
211+ -- | A list of org-ref style citation keys, parsed as citation of the given
212+ -- citation mode.
213+ orgRefCiteList :: CitationMode -> OrgParser (F Citation)
214+ orgRefCiteList citeMode = try $ do
215+ key <- orgRefCiteKey
216+ returnF $ Citation
217+ { citationId = key
218+ , citationPrefix = mempty
219+ , citationSuffix = mempty
220+ , citationMode = citeMode
221+ , citationNoteNum = 0
222+ , citationHash = 0
223+ }
224+
225+-- | Read a link-like org-ref style citation. The citation includes pre and
226+-- post text. However, multiple citations are not possible due to limitations
227+-- in the syntax.
228+linkLikeOrgRefCite :: OrgParser (F Citation)
229+linkLikeOrgRefCite = try $ do
230+ _ <- string "[["
231+ mode <- orgRefCiteMode
232+ key <- orgRefCiteKey
233+ _ <- string "]["
234+ pre <- trimInlinesF . mconcat <$> manyTill inline (try $ string "::")
235+ spc <- option False (True <$ spaceChar)
236+ suf <- trimInlinesF . mconcat <$> manyTill inline (try $ string "]]")
237+ return $ do
238+ pre' <- pre
239+ suf' <- suf
240+ return Citation
241+ { citationId = key
242+ , citationPrefix = B.toList pre'
243+ , citationSuffix = B.toList (if spc then B.space <> suf' else suf')
244+ , citationMode = mode
245+ , citationNoteNum = 0
246+ , citationHash = 0
247+ }
248+
249+-- | Read a citation key. The characters allowed in citation keys are taken
250+-- from the `org-ref-cite-re` variable in `org-ref.el`.
251+orgRefCiteKey :: OrgParser String
252+orgRefCiteKey = try . many1 . satisfy $ \c ->
253+ isAlphaNum c || c `elem` ("-_:\\./"::String)
254+
255+-- | Supported citation types. Only a small subset of org-ref types is
256+-- supported for now. TODO: rewrite this, use LaTeX reader as template.
257+orgRefCiteMode :: OrgParser CitationMode
258+orgRefCiteMode =
259+ choice $ map (\(s, mode) -> mode <$ try (string s <* char ':'))
260+ [ ("cite", AuthorInText)
261+ , ("citep", NormalCitation)
262+ , ("citep*", NormalCitation)
263+ , ("citet", AuthorInText)
264+ , ("citet*", AuthorInText)
265+ , ("citeyear", SuppressAuthor)
266+ ]
204267
205268citeList :: OrgParser (F [Citation])
206269citeList = sequence <$> sepBy1 citation (try $ char ';' *> skipSpaces)
src/Text/Pandoc/Readers/Org/Parsing.hs+1
@@ -79,6 +79,7 @@ module Text.Pandoc.Readers.Org.Parsing
7979 , skipMany1
8080 , spaces
8181 , anyChar
82+ , satisfy
8283 , string
8384 , count
8485 , eof
tests/Tests/Readers/Org.hs+36
@@ -300,6 +300,42 @@ tests =
300300 , citationHash = 0}
301301 in (para $ cite [citation] "[see @item1 p. 34-35]")
302302
303+ , "Org-ref simple citation" =:
304+ "cite:pandoc" =?>
305+ let citation = Citation
306+ { citationId = "pandoc"
307+ , citationPrefix = mempty
308+ , citationSuffix = mempty
309+ , citationMode = AuthorInText
310+ , citationNoteNum = 0
311+ , citationHash = 0
312+ }
313+ in (para $ cite [citation] "cite:pandoc")
314+
315+ , "Org-ref simple citep citation" =:
316+ "citep:pandoc" =?>
317+ let citation = Citation
318+ { citationId = "pandoc"
319+ , citationPrefix = mempty
320+ , citationSuffix = mempty
321+ , citationMode = NormalCitation
322+ , citationNoteNum = 0
323+ , citationHash = 0
324+ }
325+ in (para $ cite [citation] "citep:pandoc")
326+
327+ , "Org-ref extended citation" =:
328+ "[[citep:Dominik201408][See page 20::, for example]]" =?>
329+ let citation = Citation
330+ { citationId = "Dominik201408"
331+ , citationPrefix = toList "See page 20"
332+ , citationSuffix = toList ", for example"
333+ , citationMode = NormalCitation
334+ , citationNoteNum = 0
335+ , citationHash = 0
336+ }
337+ in (para $ cite [citation] "[[citep:Dominik201408][See page 20::, for example]]")
338+
303339 , "Inline LaTeX symbol" =:
304340 "\\dots" =?>
305341 para "…"