mirror of
https://github.com/jgm/pandoc.git
synced 2026-08-29 01:41:20 +08:00
Markdown reader: make definition lists behave like other lists.
If the `four_space_rule` extension is not enabled, figure out the indentation needed for child blocks dynamically, by looking at the first nonspace content after the `:` marker. Previously the four-space rule was always obeyed. Remove the old `compact_definition_lists` extension. This was neded to preserve backwards compatibility after pandoc 1.12 was released, but at this point we can get rid of it. T.P.Extensions: remove `Ext_compact_definition_lists` constructor for `Extension` [API change]. Fix tight/loose detection for definition lists, to conform to the documentation. Closes #10889.
This commit is contained in:
-30
@@ -4502,9 +4502,6 @@ definition:
|
||||
~ Definition 2b
|
||||
|
||||
Note that space between items in a definition list is required.
|
||||
(A variant that loosens this requirement, but disallows "lazy"
|
||||
hard wrapping, can be activated with the [`compact_definition_lists`
|
||||
extension][Extension: `compact_definition_lists`].)
|
||||
|
||||
[^3]: I have been influenced by the suggestions of [David
|
||||
Wheeler](https://justatheory.com/2009/02/modest-markdown-proposal/).
|
||||
@@ -6109,33 +6106,6 @@ and image references. This extension should not be confused with the
|
||||
Parses MultiMarkdown-style heading identifiers (in square brackets,
|
||||
after the heading but before any trailing `#`s in an ATX heading).
|
||||
|
||||
### Extension: `compact_definition_lists` ###
|
||||
|
||||
Activates the definition list syntax of pandoc 1.12.x and earlier.
|
||||
This syntax differs from the one described above under [Definition lists]
|
||||
in several respects:
|
||||
|
||||
- No blank line is required between consecutive items of the
|
||||
definition list.
|
||||
- To get a "tight" or "compact" list, omit space between consecutive
|
||||
items; the space between a term and its definition does not affect
|
||||
anything.
|
||||
- Lazy wrapping of paragraphs is not allowed: the entire definition must
|
||||
be indented four spaces.[^6]
|
||||
|
||||
[^6]: To see why laziness is incompatible with relaxing the requirement
|
||||
of a blank line between items, consider the following example:
|
||||
|
||||
bar
|
||||
: definition
|
||||
foo
|
||||
: definition
|
||||
|
||||
Is this a single list item with two definitions of "bar," the first of
|
||||
which is lazily wrapped, or two list items? To remove the ambiguity
|
||||
we must either disallow lazy wrapping or require a blank line between
|
||||
list items.
|
||||
|
||||
### Extension: `gutenberg` ###
|
||||
|
||||
Use [Project Gutenberg] conventions for `plain` output:
|
||||
|
||||
@@ -59,8 +59,6 @@ data Extension =
|
||||
| Ext_blank_before_header -- ^ Require blank line before a header
|
||||
| Ext_bracketed_spans -- ^ Bracketed spans with attributes
|
||||
| Ext_citations -- ^ Pandoc/citeproc citations
|
||||
| Ext_compact_definition_lists -- ^ Definition lists without space between items,
|
||||
-- and disallow laziness
|
||||
| Ext_definition_lists -- ^ Definition lists as in pandoc, mmd, php
|
||||
| Ext_east_asian_line_breaks -- ^ Newlines in paragraphs are ignored between
|
||||
-- East Asian wide characters. Note: this extension
|
||||
@@ -511,7 +509,6 @@ getAllExtensions f = universalExtensions <> getAll f
|
||||
, Ext_mark
|
||||
, Ext_mmd_link_attributes
|
||||
, Ext_mmd_header_identifiers
|
||||
, Ext_compact_definition_lists
|
||||
, Ext_gutenberg
|
||||
, Ext_smart
|
||||
, Ext_literate_haskell
|
||||
|
||||
@@ -845,7 +845,9 @@ orderedListStart mbstydelim = try $ do
|
||||
return (num, style, delim))
|
||||
|
||||
listStart :: PandocMonad m => MarkdownParser m ()
|
||||
listStart = bulletListStart <|> Control.Monad.void (orderedListStart Nothing)
|
||||
listStart = bulletListStart
|
||||
<|> Control.Monad.void (orderedListStart Nothing)
|
||||
<|> defListStart
|
||||
|
||||
listLine :: PandocMonad m => Int -> MarkdownParser m Text
|
||||
listLine continuationIndent = try $ do
|
||||
@@ -967,67 +969,39 @@ bulletList = do
|
||||
|
||||
-- definition lists
|
||||
|
||||
defListMarker :: PandocMonad m => MarkdownParser m ()
|
||||
defListMarker = do
|
||||
sps <- nonindentSpaces
|
||||
defListStart :: PandocMonad m => MarkdownParser m ()
|
||||
defListStart = do
|
||||
nonindentSpaces
|
||||
char ':' <|> char '~'
|
||||
tabStop <- getOption readerTabStop
|
||||
let remaining = tabStop - (T.length sps + 1)
|
||||
if remaining > 0
|
||||
then try (count remaining (char ' ')) <|> string "\t" <|> many1 spaceChar
|
||||
else mzero
|
||||
return ()
|
||||
gobbleSpaces 1 <|> () <$ lookAhead newline
|
||||
try (gobbleAtMostSpaces 3 >> notFollowedBy spaceChar) <|> return ()
|
||||
|
||||
definitionListItem :: PandocMonad m => Bool -> MarkdownParser m (F (Inlines, [Blocks]))
|
||||
definitionListItem compact = try $ do
|
||||
definitionListItem :: PandocMonad m => MarkdownParser m (F (Inlines, [Blocks]))
|
||||
definitionListItem = try $ do
|
||||
rawLine' <- anyLine
|
||||
raw <- many1 $ defRawBlock compact
|
||||
term <- parseFromString' (trimInlinesF <$> inlines) rawLine'
|
||||
contents <- mapM (parseFromString' parseBlocks . (<> "\n")) raw
|
||||
isTight <- (False <$ blanklines) <|> pure True
|
||||
fourSpaceRule <- (True <$ guardEnabled Ext_four_space_rule) <|> pure False
|
||||
contents <- many1 $ listItem fourSpaceRule defListStart
|
||||
optional blanklines
|
||||
return $ liftM2 (,) term (sequence contents)
|
||||
return $ liftM2 (,)
|
||||
term
|
||||
((if isTight
|
||||
then fmap (fmap (fmap paraToPlain))
|
||||
else id) (sequence contents))
|
||||
|
||||
defRawBlock :: PandocMonad m => Bool -> MarkdownParser m Text
|
||||
defRawBlock compact = try $ do
|
||||
hasBlank <- option False $ blankline >> return True
|
||||
defListMarker
|
||||
firstline <- anyLineNewline
|
||||
let dline = try
|
||||
( do notFollowedBy blankline
|
||||
notFollowedByHtmlCloser
|
||||
notFollowedByDivCloser
|
||||
if compact -- laziness not compatible with compact
|
||||
then () <$ indentSpaces
|
||||
else (() <$ indentSpaces)
|
||||
<|> notFollowedBy defListMarker
|
||||
anyLine )
|
||||
rawlines <- many dline
|
||||
cont <- fmap T.concat $ many $ try $ do
|
||||
trailing <- option "" blanklines
|
||||
ln <- indentSpaces >> notFollowedBy blankline >> anyLine
|
||||
lns <- many dline
|
||||
return $ trailing <> T.unlines (ln:lns)
|
||||
return $ trimr (firstline <> T.unlines rawlines <> cont) <>
|
||||
if hasBlank || not (T.null cont) then "\n\n" else ""
|
||||
paraToPlain :: Block -> Block
|
||||
paraToPlain (Para ils) = Plain ils
|
||||
paraToPlain x = x
|
||||
|
||||
definitionList :: PandocMonad m => MarkdownParser m (F Blocks)
|
||||
definitionList = try $ do
|
||||
guardEnabled Ext_definition_lists
|
||||
lookAhead (anyLine >>
|
||||
optional (blankline >> notFollowedBy (Control.Monad.void table)) >>
|
||||
-- don't capture table caption as def list!
|
||||
defListMarker)
|
||||
compactDefinitionList <|> normalDefinitionList
|
||||
|
||||
compactDefinitionList :: PandocMonad m => MarkdownParser m (F Blocks)
|
||||
compactDefinitionList = do
|
||||
guardEnabled Ext_compact_definition_lists
|
||||
items <- fmap sequence $ many1 $ definitionListItem True
|
||||
return $ B.definitionList <$> fmap compactifyDL items
|
||||
|
||||
normalDefinitionList :: PandocMonad m => MarkdownParser m (F Blocks)
|
||||
normalDefinitionList = do
|
||||
guardEnabled Ext_definition_lists
|
||||
items <- fmap sequence $ many1 $ definitionListItem False
|
||||
defListStart)
|
||||
items <- fmap sequence $ many1 definitionListItem
|
||||
return $ B.definitionList <$> items
|
||||
|
||||
--
|
||||
|
||||
@@ -860,17 +860,11 @@ definitionListItemToMarkdown opts (label, defs) = do
|
||||
let isTight = case defs of
|
||||
((Plain _ : _): _) -> True
|
||||
_ -> False
|
||||
if isEnabled Ext_compact_definition_lists opts
|
||||
then do
|
||||
let contents = vcat $ map (\d -> hang tabStop (leader <> sps)
|
||||
$ vcat d <> cr) defs'
|
||||
return $ nowrap labelText <> cr <> contents <> cr
|
||||
else do
|
||||
let contents = (if isTight then vcat else vsep) $ map
|
||||
(\d -> hang tabStop (leader <> sps) $ vcat d)
|
||||
defs'
|
||||
return $ blankline <> nowrap labelText $$
|
||||
(if isTight then empty else blankline) <> contents <> blankline
|
||||
let contents = (if isTight then vcat else vsep) $ map
|
||||
(\d -> hang tabStop (leader <> sps) $ vcat d)
|
||||
defs'
|
||||
return $ blankline <> nowrap labelText $$
|
||||
(if isTight then empty else blankline) <> contents <> blankline
|
||||
else
|
||||
return $ nowrap (chomp labelText <> literal " " <> cr) <>
|
||||
vsep (map vsep defs') <> blankline
|
||||
|
||||
@@ -29,10 +29,6 @@ markdownSmart :: Text -> Pandoc
|
||||
markdownSmart = purely $ readMarkdown def { readerExtensions =
|
||||
enableExtension Ext_smart pandocExtensions }
|
||||
|
||||
markdownCDL :: Text -> Pandoc
|
||||
markdownCDL = purely $ readMarkdown def { readerExtensions = enableExtension
|
||||
Ext_compact_definition_lists pandocExtensions }
|
||||
|
||||
markdownGH :: Text -> Pandoc
|
||||
markdownGH = purely $ readMarkdown def {readerExtensions = enableExtension
|
||||
Ext_wikilinks_title_before_pipe githubMarkdownExtensions }
|
||||
@@ -461,14 +457,14 @@ tests = [ testGroup "inline code"
|
||||
, "blank space before first def" =:
|
||||
"foo1\n\n : bar\n\nfoo2\n\n : bar2\n : bar3\n" =?>
|
||||
definitionList [ (text "foo1", [para (text "bar")])
|
||||
, (text "foo2", [para (text "bar2"),
|
||||
plain (text "bar3")])
|
||||
, (text "foo2", [plain (text "bar2"),
|
||||
para (text "bar3")])
|
||||
]
|
||||
, "blank space before second def" =:
|
||||
"foo1\n : bar\n\nfoo2\n : bar2\n\n : bar3\n" =?>
|
||||
definitionList [ (text "foo1", [plain (text "bar")])
|
||||
, (text "foo2", [plain (text "bar2"),
|
||||
para (text "bar3")])
|
||||
plain (text "bar3")])
|
||||
]
|
||||
, "laziness" =:
|
||||
"foo1\n : bar\nbaz\n : bar2\n" =?>
|
||||
@@ -478,8 +474,8 @@ tests = [ testGroup "inline code"
|
||||
]
|
||||
, "no blank space before first of two paragraphs" =:
|
||||
"foo1\n : bar\n\n baz\n" =?>
|
||||
definitionList [ (text "foo1", [para (text "bar") <>
|
||||
para (text "baz")])
|
||||
definitionList [ (text "foo1", [plain (text "bar") <>
|
||||
plain (text "baz")])
|
||||
]
|
||||
, "first line not indented" =:
|
||||
"foo\n: bar\n" =?>
|
||||
@@ -492,14 +488,6 @@ tests = [ testGroup "inline code"
|
||||
divWith nullAttr (definitionList
|
||||
[ (text "foo", [bulletList [plain (text "bar")]]) ])
|
||||
]
|
||||
, testGroup "+compact_definition_lists"
|
||||
[ test markdownCDL "basic compact list" $
|
||||
"foo1\n: bar\n baz\nfoo2\n: bar2\n" =?>
|
||||
definitionList [ (text "foo1", [plain (text "bar" <> softbreak <>
|
||||
text "baz")])
|
||||
, (text "foo2", [plain (text "bar2")])
|
||||
]
|
||||
]
|
||||
, testGroup "lists"
|
||||
[ "issue #1154" =:
|
||||
" - <div>\n first div breaks\n </div>\n\n <button>if this button exists</button>\n\n <div>\n with this div too.\n </div>\n"
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
```
|
||||
% pandoc
|
||||
apple
|
||||
|
||||
: pomaceous
|
||||
|
||||
fruit
|
||||
^D
|
||||
<dl>
|
||||
<dt>apple</dt>
|
||||
<dd>
|
||||
<p>pomaceous</p>
|
||||
<p>fruit</p>
|
||||
</dd>
|
||||
</dl>
|
||||
```
|
||||
@@ -33,6 +33,7 @@ Definition
|
||||
2. list
|
||||
^D
|
||||
\begin{description}
|
||||
\tightlist
|
||||
\item[Definition]
|
||||
Foo
|
||||
|
||||
|
||||
Reference in New Issue
Block a user