@@ -193,15 +193,78 @@ endline = try $ do
193193cite :: OrgParser (F Inlines)
194194cite = try $ do
195195 guardEnabled Ext_citations
196− (cs, raw) <- withRaw normalCite
196+ (cs, raw) <- withRaw (pandocOrgCite <|> orgRefCite)
197197 return $ (flip B.cite (B.text raw)) <$> cs
198198
199−normalCite :: OrgParser (F [Citation])
200−normalCite = try $ char '['
201− *> skipSpaces
202− *> citeList
203− <* skipSpaces
204− <* char ']'
199+-- | A citation in Pandoc Org-mode style (@[\@citekey]@).
200+pandocOrgCite :: OrgParser (F [Citation])
201+pandocOrgCite = try $
202+ char '[' *> skipSpaces *> citeList <* skipSpaces <* char ']'
203+
204+orgRefCite :: OrgParser (F [Citation])
205+orgRefCite = try $ normalOrgRefCite <|> (fmap (:[]) <$> linkLikeOrgRefCite)
206+
207+normalOrgRefCite :: OrgParser (F [Citation])
208+normalOrgRefCite = try $ do
209+ mode <- orgRefCiteMode
210+ sequence <$> sepBy1 (orgRefCiteList mode) (char ',')
211+ where
212+ -- | A list of org-ref style citation keys, parsed as citation of the given
213+ -- citation mode.
214+ orgRefCiteList :: CitationMode -> OrgParser (F Citation)
215+ orgRefCiteList citeMode = try $ do
216+ key <- orgRefCiteKey
217+ returnF $ Citation
218+ { citationId = key
219+ , citationPrefix = mempty
220+ , citationSuffix = mempty
221+ , citationMode = citeMode
222+ , citationNoteNum = 0
223+ , citationHash = 0
224+ }
225+
226+-- | Read a link-like org-ref style citation. The citation includes pre and
227+-- post text. However, multiple citations are not possible due to limitations
228+-- in the syntax.
229+linkLikeOrgRefCite :: OrgParser (F Citation)
230+linkLikeOrgRefCite = try $ do
231+ _ <- string "[["
232+ mode <- orgRefCiteMode
233+ key <- orgRefCiteKey
234+ _ <- string "]["
235+ pre <- trimInlinesF . mconcat <$> manyTill inline (try $ string "::")
236+ spc <- option False (True <$ spaceChar)
237+ suf <- trimInlinesF . mconcat <$> manyTill inline (try $ string "]]")
238+ return $ do
239+ pre' <- pre
240+ suf' <- suf
241+ return Citation
242+ { citationId = key
243+ , citationPrefix = B.toList pre'
244+ , citationSuffix = B.toList (if spc then B.space <> suf' else suf')
245+ , citationMode = mode
246+ , citationNoteNum = 0
247+ , citationHash = 0
248+ }
249+
250+-- | Read a citation key. The characters allowed in citation keys are taken
251+-- from the `org-ref-cite-re` variable in `org-ref.el`.
252+orgRefCiteKey :: OrgParser String
253+orgRefCiteKey = try . many1 . satisfy $ \c ->
254+ isAlphaNum c || c `elem` ("-_:\\./"::String)
255+
256+-- | Supported citation types. Only a small subset of org-ref types is
257+-- supported for now. TODO: rewrite this, use LaTeX reader as template.
258+orgRefCiteMode :: OrgParser CitationMode
259+orgRefCiteMode =
260+ choice $ map (\(s, mode) -> mode <$ try (string s <* char ':'))
261+ [ ("cite", AuthorInText)
262+ , ("citep", NormalCitation)
263+ , ("citep*", NormalCitation)
264+ , ("citet", AuthorInText)
265+ , ("citet*", AuthorInText)
266+ , ("citeyear", SuppressAuthor)
267+ ]
205268
206269citeList :: OrgParser (F [Citation])
207270citeList = sequence <$> sepBy1 citation (try $ char ';' *> skipSpaces)