@@ -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)