git.iko.soy/typeable/pandoc
on master help sign in
Support `yaml_metadata_block` extension form commonmark, gfm.

This is a bit more limited than with markdown, as documented in the manual: - The YAML block must be the first thing in the input. - The leaf notes are parsed in isolation from the rest of the document. So, for example, you can't use reference links if the references are defined later in the document. Closes #6537.

commitc389211e2f678d9327cd2c008d54a1e438f07a07 authorJohn MacFarlane <jgm@berkeley.edu> dateSat 20 Mar 2021, 15:45 (6 years ago) parent2274eb8
4 files changed+50−1
MANUAL.txt+16 src/Text/Pandoc/Extensions.hs+3 src/Text/Pandoc/Parsing.hs+1−1 src/Text/Pandoc/Readers/CommonMark.hs+30
MANUAL.txt+16
@@ -4240,6 +4240,22 @@ will be interpreted as markdown. For example:
42404240 \renewcommand{\section}[1]{\clearpage\oldsection{#1}}
42414241 ```
42424242
4243+Note: the `yaml_metadata_block` extension works with
4244+`commonmark` as well as `markdown` (and it is enabled by default
4245+in `gfm` and `commonmark_x`). However, in these formats the
4246+following restrictions apply:
4247+
4248+- The YAML metadata block must occur at the beginning of the
4249+ document (and there can be only one). If multiple files are
4250+ given as arguments to pandoc, only the first can be a YAML
4251+ metadata block.
4252+
4253+- The leaf nodes of the YAML structure are parsed in isolation from
4254+ each other and from the rest of the document. So, for
4255+ example, you can't use a reference link in these contexts
4256+ if the link definition is somewhere else in the document.
4257+
4258+
42434259## Backslash escapes
42444260
42454261#### Extension: `all_symbols_escapable` ####
src/Text/Pandoc/Extensions.hs+3
@@ -354,6 +354,7 @@ getDefaultExtensions "gfm" = extensionsFromList
354354 , Ext_strikeout
355355 , Ext_task_lists
356356 , Ext_emoji
357+ , Ext_yaml_metadata_block
357358 ]
358359getDefaultExtensions "commonmark" = extensionsFromList
359360 [Ext_raw_html]
@@ -379,6 +380,7 @@ getDefaultExtensions "commonmark_x" = extensionsFromList
379380 , Ext_raw_attribute
380381 , Ext_implicit_header_references
381382 , Ext_attributes
383+ , Ext_yaml_metadata_block
382384 ]
383385getDefaultExtensions "org" = extensionsFromList
384386 [Ext_citations,
@@ -511,6 +513,7 @@ getAllExtensions f = universalExtensions <> getAll f
511513 , Ext_implicit_header_references
512514 , Ext_attributes
513515 , Ext_sourcepos
516+ , Ext_yaml_metadata_block
514517 ]
515518 getAll "commonmark_x" = getAll "commonmark"
516519 getAll "org" = autoIdExtensions <>
src/Text/Pandoc/Parsing.hs+1−1
@@ -517,7 +517,7 @@ parseFromString :: (Stream s m Char, IsString s)
517517 -> ParserT s st m r
518518parseFromString parser str = do
519519 oldPos <- getPosition
520− setPosition $ initialPos "chunk"
520+ setPosition $ initialPos " chunk"
521521 oldInput <- getInput
522522 setInput $ fromString $ T.unpack str
523523 result <- parser
src/Text/Pandoc/Readers/CommonMark.hs+30
@@ -26,13 +26,43 @@ import Text.Pandoc.Definition
2626import Text.Pandoc.Builder as B
2727import Text.Pandoc.Options
2828import Text.Pandoc.Error
29+import Text.Pandoc.Readers.Metadata (yamlMetaBlock)
2930import Control.Monad.Except
3031import Data.Functor.Identity (runIdentity)
3132import Data.Typeable
33+import Text.Pandoc.Parsing (runParserT, getPosition, sourceLine,
34+ runF, defaultParserState, take1WhileP, option)
35+import qualified Data.Text as T
3236
3337-- | Parse a CommonMark formatted string into a 'Pandoc' structure.
3438readCommonMark :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
3539readCommonMark opts s
40+ | isEnabled Ext_yaml_metadata_block opts
41+ , "---" `T.isPrefixOf` s = do
42+ let metaValueParser = do
43+ inp <- option "" $ take1WhileP (const True)
44+ case runIdentity
45+ (commonmarkWith (specFor opts) "metadata value" inp) of
46+ Left _ -> mzero
47+ Right (Cm bls :: Cm () Blocks)
48+ -> return $ return $ B.toMetaValue bls
49+ res <- runParserT (do meta <- yamlMetaBlock metaValueParser
50+ pos <- getPosition
51+ return (meta, pos))
52+ defaultParserState "YAML metadata" s
53+ case res of
54+ Left _ -> readCommonMarkBody opts s
55+ Right (meta, pos) -> do
56+ let dropLines 0 = id
57+ dropLines n = dropLines (n - 1) . T.drop 1 . T.dropWhile (/='\n')
58+ let metaLines = sourceLine pos - 1
59+ let body = T.replicate metaLines "\n" <> dropLines metaLines s
60+ Pandoc _ bs <- readCommonMarkBody opts body
61+ return $ Pandoc (runF meta defaultParserState) bs
62+ | otherwise = readCommonMarkBody opts s
63+
64+readCommonMarkBody :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
65+readCommonMarkBody opts s
3666 | isEnabled Ext_sourcepos opts =
3767 case runIdentity (commonmarkWith (specFor opts) "" s) of
3868 Left err -> throwError $ PandocParsecError s err