Skip to content

Commit

Permalink
Implemented fenced Divs.
Browse files Browse the repository at this point in the history
+ 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.
  • Loading branch information
jgm committed Oct 24, 2017
1 parent 896803b commit fda0c01
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 0 deletions.
31 changes: 31 additions & 0 deletions MANUAL.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3073,6 +3073,37 @@ For the most part this should give the same output as `raw_html`,
but it makes it easier to write pandoc filters to manipulate groups
of inlines.

#### Extension: `fenced_divs` ####

Allow special fenced syntax for native `Div` blocks. A Div
starts with a fence containing at least three consecutive
colons plus some attributes. The attributes may optionally
be followed by another string of consecutive colons.
The attribute syntax is exactly as in fenced code blocks (see
[Extension-fenced_code_attributes], above). The Div ends with
another line containing a string of at least three consecutive
colons. The fenced Div should be separated by blank lines from
preceding and following blocks.

Example:

::::: {#special .sidebar}
Here is a paragraph.

And another.
:::::

Fenced divs can be nested. Opening fences are distinguished
because they *must* have attributes:

::: Warning
This is a warning.

::: Danger
This is a warning within a warning.
:::
:::

#### Extension: `raw_tex` ####

In addition to raw HTML, pandoc allows raw LaTeX, TeX, and ConTeXt to be
Expand Down
2 changes: 2 additions & 0 deletions src/Text/Pandoc/Extensions.hs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ data Extension =
| Ext_raw_attribute -- ^ Allow explicit raw blocks/inlines
| Ext_markdown_in_html_blocks -- ^ Interpret as markdown inside HTML blocks
| Ext_native_divs -- ^ Use Div blocks for contents of <div> tags
| Ext_fenced_divs -- ^ Allow fenced div syntax :::
| Ext_native_spans -- ^ Use Span inlines for contents of <span>
| Ext_bracketed_spans -- ^ Bracketed spans with attributes
| Ext_markdown_attribute -- ^ Interpret text inside HTML as markdown
Expand Down Expand Up @@ -183,6 +184,7 @@ pandocExtensions = extensionsFromList
, Ext_raw_attribute
, Ext_markdown_in_html_blocks
, Ext_native_divs
, Ext_fenced_divs
, Ext_native_spans
, Ext_bracketed_spans
, Ext_escaped_line_breaks
Expand Down
2 changes: 2 additions & 0 deletions src/Text/Pandoc/Parsing.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1069,6 +1069,7 @@ data ParserState = ParserState
-- roles), 3) Additional classes (rest of Attr is unused)).
stateCaption :: Maybe Inlines, -- ^ Caption in current environment
stateInHtmlBlock :: Maybe String, -- ^ Tag type of HTML block being parsed
stateFencedDivLevel :: Int, -- ^ Depth of fenced div
stateContainers :: [String], -- ^ parent include files
stateLogMessages :: [LogMessage], -- ^ log messages
stateMarkdownAttribute :: Bool -- ^ True if in markdown=1 context
Expand Down Expand Up @@ -1185,6 +1186,7 @@ defaultParserState =
stateRstCustomRoles = M.empty,
stateCaption = Nothing,
stateInHtmlBlock = Nothing,
stateFencedDivLevel = 0,
stateContainers = [],
stateLogMessages = [],
stateMarkdownAttribute = False
Expand Down
28 changes: 28 additions & 0 deletions src/Text/Pandoc/Readers/Markdown.hs
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,7 @@ block = do
, header
, lhsCodeBlock
, divHtml
, divFenced
, htmlBlock
, table
, codeBlockIndented
Expand Down Expand Up @@ -1686,6 +1687,9 @@ endline = try $ do
guardEnabled Ext_blank_before_header <|> (notFollowedBy . char =<< atxChar) -- atx header
guardDisabled Ext_backtick_code_blocks <|>
notFollowedBy (() <$ (lookAhead (char '`') >> codeBlockFenced))
guardDisabled Ext_fenced_divs <|>
do divLevel <- stateFencedDivLevel <$> getState
guard (divLevel < 1) <|> notFollowedBy fenceEnd
notFollowedByHtmlCloser
(eof >> return mempty)
<|> (guardEnabled Ext_hard_line_breaks >> return (return B.linebreak))
Expand Down Expand Up @@ -1930,6 +1934,30 @@ divHtml = try $ do
else -- avoid backtracing
return $ return (B.rawBlock "html" (rawtag <> bls)) <> contents

divFenced :: PandocMonad m => MarkdownParser m (F Blocks)
divFenced = try $ do
guardEnabled Ext_fenced_divs
nonindentSpaces
string ":::"
skipMany (char ':')
skipMany spaceChar
attribs <- attributes <|> ((\x -> ("",[x],[])) <$> many1 nonspaceChar)
skipMany spaceChar
skipMany (char ':')
blankline
updateState $ \st -> st{ stateFencedDivLevel = stateFencedDivLevel st + 1 }
bs <- mconcat <$> manyTill block fenceEnd
updateState $ \st -> st{ stateFencedDivLevel = stateFencedDivLevel st - 1 }
return $ B.divWith attribs <$> bs

fenceEnd :: PandocMonad m => MarkdownParser m ()
fenceEnd = try $ do
nonindentSpaces
string ":::"
skipMany (char ':')
blanklines
return ()

rawHtmlInline :: PandocMonad m => MarkdownParser m (F Inlines)
rawHtmlInline = do
guardEnabled Ext_raw_html
Expand Down
30 changes: 30 additions & 0 deletions test/command/168.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
```
% pandoc -t native
:::::::::: warning ::::::::::::
This is the warning!
1. list
2. another
::: {#myid .class key=val}
nested div
:::
:::::::::::::::::::::::::::::::
^D
[Div ("",["warning"],[])
[Para [Str "This",Space,Str "is",Space,Str "the",Space,Str "warning!"]
,OrderedList (1,Decimal,Period)
[[Plain [Str "list"]]
,[Plain [Str "another"]]]
,Div ("myid",["class"],[("key","val")])
[Plain [Str "nested",Space,Str "div"]]]]
```

```
% pandoc -t native
foo
:::
bar
^D
[Para [Str "foo",SoftBreak,Str ":::",SoftBreak,Str "bar"]]
```

0 comments on commit fda0c01

Please sign in to comment.