git.iko.soy/typeable/pandoc
on master help sign in
Implemented fenced Divs.

+ Added Ext_fenced_divs to Extensions (default for pandoc Markdown). + Document fenced_divs extension in manual. + Implemented fenced code divs in Markdown reader. + Added test. Closes #168.

commitfda0c0119f415c6df95b20730650388c0471241d authorJohn MacFarlane <jgm@berkeley.edu> dateMon 23 Oct 2017, 21:40 (9 years ago) parent896803b
5 files changed+93
MANUAL.txt+31 src/Text/Pandoc/Extensions.hs+2 src/Text/Pandoc/Parsing.hs+2 src/Text/Pandoc/Readers/Markdown.hs+28 test/command/168.md+30
MANUAL.txt+31
@@ -3073,6 +3073,37 @@ For the most part this should give the same output as `raw_html`,
30733073but it makes it easier to write pandoc filters to manipulate groups
30743074of inlines.
30753075
3076+#### Extension: `fenced_divs` ####
3077+
3078+Allow special fenced syntax for native `Div` blocks. A Div
3079+starts with a fence containing at least three consecutive
3080+colons plus some attributes. The attributes may optionally
3081+be followed by another string of consecutive colons.
3082+The attribute syntax is exactly as in fenced code blocks (see
3083+[Extension-fenced_code_attributes], above). The Div ends with
3084+another line containing a string of at least three consecutive
3085+colons. The fenced Div should be separated by blank lines from
3086+preceding and following blocks.
3087+
3088+Example:
3089+
3090+ ::::: {#special .sidebar}
3091+ Here is a paragraph.
3092+
3093+ And another.
3094+ :::::
3095+
3096+Fenced divs can be nested. Opening fences are distinguished
3097+because they *must* have attributes:
3098+
3099+ ::: Warning
3100+ This is a warning.
3101+
3102+ ::: Danger
3103+ This is a warning within a warning.
3104+ :::
3105+ :::
3106+
30763107#### Extension: `raw_tex` ####
30773108
30783109In addition to raw HTML, pandoc allows raw LaTeX, TeX, and ConTeXt to be
src/Text/Pandoc/Extensions.hs+2
@@ -107,6 +107,7 @@ data Extension =
107107 | Ext_raw_attribute -- ^ Allow explicit raw blocks/inlines
108108 | Ext_markdown_in_html_blocks -- ^ Interpret as markdown inside HTML blocks
109109 | Ext_native_divs -- ^ Use Div blocks for contents of <div> tags
110+ | Ext_fenced_divs -- ^ Allow fenced div syntax :::
110111 | Ext_native_spans -- ^ Use Span inlines for contents of <span>
111112 | Ext_bracketed_spans -- ^ Bracketed spans with attributes
112113 | Ext_markdown_attribute -- ^ Interpret text inside HTML as markdown
@@ -183,6 +184,7 @@ pandocExtensions = extensionsFromList
183184 , Ext_raw_attribute
184185 , Ext_markdown_in_html_blocks
185186 , Ext_native_divs
187+ , Ext_fenced_divs
186188 , Ext_native_spans
187189 , Ext_bracketed_spans
188190 , Ext_escaped_line_breaks
src/Text/Pandoc/Parsing.hs+2
@@ -1069,6 +1069,7 @@ data ParserState = ParserState
10691069 -- roles), 3) Additional classes (rest of Attr is unused)).
10701070 stateCaption :: Maybe Inlines, -- ^ Caption in current environment
10711071 stateInHtmlBlock :: Maybe String, -- ^ Tag type of HTML block being parsed
1072+ stateFencedDivLevel :: Int, -- ^ Depth of fenced div
10721073 stateContainers :: [String], -- ^ parent include files
10731074 stateLogMessages :: [LogMessage], -- ^ log messages
10741075 stateMarkdownAttribute :: Bool -- ^ True if in markdown=1 context
@@ -1185,6 +1186,7 @@ defaultParserState =
11851186 stateRstCustomRoles = M.empty,
11861187 stateCaption = Nothing,
11871188 stateInHtmlBlock = Nothing,
1189+ stateFencedDivLevel = 0,
11881190 stateContainers = [],
11891191 stateLogMessages = [],
11901192 stateMarkdownAttribute = False
src/Text/Pandoc/Readers/Markdown.hs+28
@@ -499,6 +499,7 @@ block = do
499499 , header
500500 , lhsCodeBlock
501501 , divHtml
502+ , divFenced
502503 , htmlBlock
503504 , table
504505 , codeBlockIndented
@@ -1686,6 +1687,9 @@ endline = try $ do
16861687 guardEnabled Ext_blank_before_header <|> (notFollowedBy . char =<< atxChar) -- atx header
16871688 guardDisabled Ext_backtick_code_blocks <|>
16881689 notFollowedBy (() <$ (lookAhead (char '`') >> codeBlockFenced))
1690+ guardDisabled Ext_fenced_divs <|>
1691+ do divLevel <- stateFencedDivLevel <$> getState
1692+ guard (divLevel < 1) <|> notFollowedBy fenceEnd
16891693 notFollowedByHtmlCloser
16901694 (eof >> return mempty)
16911695 <|> (guardEnabled Ext_hard_line_breaks >> return (return B.linebreak))
@@ -1930,6 +1934,30 @@ divHtml = try $ do
19301934 else -- avoid backtracing
19311935 return $ return (B.rawBlock "html" (rawtag <> bls)) <> contents
19321936
1937+divFenced :: PandocMonad m => MarkdownParser m (F Blocks)
1938+divFenced = try $ do
1939+ guardEnabled Ext_fenced_divs
1940+ nonindentSpaces
1941+ string ":::"
1942+ skipMany (char ':')
1943+ skipMany spaceChar
1944+ attribs <- attributes <|> ((\x -> ("",[x],[])) <$> many1 nonspaceChar)
1945+ skipMany spaceChar
1946+ skipMany (char ':')
1947+ blankline
1948+ updateState $ \st -> st{ stateFencedDivLevel = stateFencedDivLevel st + 1 }
1949+ bs <- mconcat <$> manyTill block fenceEnd
1950+ updateState $ \st -> st{ stateFencedDivLevel = stateFencedDivLevel st - 1 }
1951+ return $ B.divWith attribs <$> bs
1952+
1953+fenceEnd :: PandocMonad m => MarkdownParser m ()
1954+fenceEnd = try $ do
1955+ nonindentSpaces
1956+ string ":::"
1957+ skipMany (char ':')
1958+ blanklines
1959+ return ()
1960+
19331961rawHtmlInline :: PandocMonad m => MarkdownParser m (F Inlines)
19341962rawHtmlInline = do
19351963 guardEnabled Ext_raw_html
test/command/168.mdnew file+30
@@ -0,0 +1,30 @@
1+```
2+% pandoc -t native
3+:::::::::: warning ::::::::::::
4+This is the warning!
5+
6+1. list
7+2. another
8+
9+::: {#myid .class key=val}
10+nested div
11+:::
12+:::::::::::::::::::::::::::::::
13+^D
14+[Div ("",["warning"],[])
15+ [Para [Str "This",Space,Str "is",Space,Str "the",Space,Str "warning!"]
16+ ,OrderedList (1,Decimal,Period)
17+ [[Plain [Str "list"]]
18+ ,[Plain [Str "another"]]]
19+ ,Div ("myid",["class"],[("key","val")])
20+ [Plain [Str "nested",Space,Str "div"]]]]
21+```
22+
23+```
24+% pandoc -t native
25+foo
26+:::
27+bar
28+^D
29+[Para [Str "foo",SoftBreak,Str ":::",SoftBreak,Str "bar"]]
30+```