git.iko.soy/typeable/pandoc
on master help sign in
RST reader: Handle replace:: and unicode:: substitutions.
commite5740a138e291995d97e91d038d174977b0456f0 authorJohn MacFarlane <jgm@berkeley.edu> dateSun 30 Sep 2012, 09:53 (14 years ago) parentd360172
1 file changed+77−8
src/Text/Pandoc/Readers/RST.hs+77−8
src/Text/Pandoc/Readers/RST.hs+77−8
@@ -500,29 +500,66 @@ directive = try $ do
500500 string ".."
501501 directive'
502502
503+-- TODO: line-block, parsed-literal, table, csv-table, list-table
504+-- replace, unicode
505+-- date
506+-- include
507+-- raw (consolidate)
508+-- class
509+-- title
503510directive' :: RSTParser Blocks
504511directive' = do
505512 skipMany1 spaceChar
506513 label <- directiveLabel
507514 skipMany spaceChar
508515 top <- many $ satisfy (/='\n')
509− <|> try (char '\n' <* notFollowedBy blankline <*
510− notFollowedBy' (lookAhead (many spaceChar)
511− >>= rawFieldListItem))
516+ <|> try (char '\n' <*
517+ notFollowedBy' (rawFieldListItem " ") <*
518+ count 3 (char ' ') <*
519+ notFollowedBy blankline)
512520 newline
513− indent <- lookAhead $ many spaceChar
514− fields <- many $ rawFieldListItem indent
515− blanklines
516− body <- option "" indentedBlock
521+ fields <- many $ rawFieldListItem " "
522+ body <- option "" $ try $ blanklines >> indentedBlock
523+ optional blanklines
517524 let body' = body ++ "\n\n"
518525 case label of
519526 "container" -> parseFromString parseBlocks body'
527+ "replace" -> B.para <$> -- consumed by substKey
528+ parseFromString (trimInlines . mconcat <$> many inline)
529+ (trim top)
530+ "unicode" -> B.para <$> -- consumed by substKey
531+ parseFromString (trimInlines . mconcat <$> many inline)
532+ (trim $ unicodeTransform top)
520533 "compound" -> parseFromString parseBlocks body'
521534 "pull-quote" -> B.blockQuote <$> parseFromString parseBlocks body'
522535 "epigraph" -> B.blockQuote <$> parseFromString parseBlocks body'
523536 "highlights" -> B.blockQuote <$> parseFromString parseBlocks body'
524537 "rubric" -> B.para . B.strong <$> parseFromString
525538 (trimInlines . mconcat <$> many inline) top
539+ _ | label `elem` ["attention","caution","danger","error","hint",
540+ "important","note","tip","warning"] ->
541+ do let tit = B.para $ B.strong $ B.str label
542+ bod <- parseFromString parseBlocks $ top ++ "\n\n" ++ body'
543+ return $ B.blockQuote $ tit <> bod
544+ "admonition" ->
545+ do tit <- B.para . B.strong <$> parseFromString
546+ (trimInlines . mconcat <$> many inline) top
547+ bod <- parseFromString parseBlocks body'
548+ return $ B.blockQuote $ tit <> bod
549+ "sidebar" ->
550+ do let subtit = maybe "" trim $ lookup "subtitle" fields
551+ tit <- B.para . B.strong <$> parseFromString
552+ (trimInlines . mconcat <$> many inline)
553+ (trim top ++ if null subtit
554+ then ""
555+ else (": " ++ subtit))
556+ bod <- parseFromString parseBlocks body'
557+ return $ B.blockQuote $ tit <> bod
558+ "topic" ->
559+ do tit <- B.para . B.strong <$> parseFromString
560+ (trimInlines . mconcat <$> many inline) top
561+ bod <- parseFromString parseBlocks body'
562+ return $ tit <> bod
526563 "default-role" -> mempty <$ updateState (\s ->
527564 s { stateRstDefaultRole =
528565 case trim top of
@@ -546,6 +583,38 @@ directive' = do
546583 Nothing -> B.image src "" alt
547584 _ -> return mempty
548585
586+-- Can contain haracter codes as decimal numbers or
587+-- hexadecimal numbers, prefixed by 0x, x, \x, U+, u, or \u
588+-- or as XML-style hexadecimal character entities, e.g. &#x1a2b;
589+-- or text, which is used as-is. Comments start with ..
590+unicodeTransform :: String -> String
591+unicodeTransform t =
592+ case t of
593+ ('.':'.':xs) -> unicodeTransform $ dropWhile (/='\n') xs -- comment
594+ ('0':'x':xs) -> go "0x" xs
595+ ('x':xs) -> go "x" xs
596+ ('\\':'x':xs) -> go "\\x" xs
597+ ('U':'+':xs) -> go "U+" xs
598+ ('u':xs) -> go "u" xs
599+ ('\\':'u':xs) -> go "\\u" xs
600+ ('&':'#':'x':xs) -> maybe ("&#x" ++ unicodeTransform xs)
601+ -- drop semicolon
602+ (\(c,s) -> c : unicodeTransform (drop 1 s))
603+ $ extractUnicodeChar xs
604+ (x:xs) -> x : unicodeTransform xs
605+ [] -> []
606+ where go pref zs = maybe (pref ++ unicodeTransform zs)
607+ (\(c,s) -> c : unicodeTransform s)
608+ $ extractUnicodeChar zs
609+
610+extractUnicodeChar :: String -> Maybe (Char, String)
611+extractUnicodeChar s = maybe Nothing (\c -> Just (c,rest)) mbc
612+ where (ds,rest) = span isHexDigit s
613+ mbc = safeRead ('\'':'\\':'x':ds ++ "'")
614+
615+isHexDigit :: Char -> Bool
616+isHexDigit c = c `elem` "0123456789ABCDEFabcdef"
617+
549618extractCaption :: RSTParser (Inlines, Blocks)
550619extractCaption = do
551620 capt <- trimInlines . mconcat <$> many inline
@@ -662,7 +731,7 @@ substKey = try $ do
662731 skipMany1 spaceChar
663732 (alt,ref) <- withRaw $ trimInlines . mconcat
664733 <$> enclosed (char '|') (char '|') inline
665− res <- B.toList <$> (directive' <|> para)
734+ res <- B.toList <$> directive'
666735 il <- case res of
667736 -- use alt unless :alt: attribute on image:
668737 [Para [Image [Str "image"] (src,tit)]] ->