Skip to content

Commit

Permalink
Textile Reader:
Browse files Browse the repository at this point in the history
 - Adding a Parser to look for ordered list start attribute numbers if any
 - Add command test for ordered list start attributes (jgm#2465)
 - Cleanup and formatting
  • Loading branch information
vkraven committed Nov 29, 2022
1 parent f53ab3c commit cb3941c
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 10 deletions.
62 changes: 52 additions & 10 deletions src/Text/Pandoc/Readers/Textile.hs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import Text.Pandoc.Parsing
import Text.Pandoc.Readers.HTML (htmlTag, isBlockTag, isInlineTag)
import Text.Pandoc.Readers.LaTeX (rawLaTeXBlock, rawLaTeXInline)
import Text.Pandoc.Shared (trim, tshow)
import Text.Read (readMaybe)

-- | Parse a Textile text and return a Pandoc document.
readTextile :: (PandocMonad m, ToSources a)
Expand Down Expand Up @@ -229,43 +230,77 @@ bulletListAtDepth depth = try $ B.bulletList <$> many1 (bulletListItemAtDepth d
-- | Bullet List Item of given depth, depth being the number of
-- leading '*'
bulletListItemAtDepth :: PandocMonad m => Int -> TextileParser m Blocks
bulletListItemAtDepth = genericListItemAtDepth '*'
bulletListItemAtDepth depth = try $ do
bulletListStartAtDepth depth
genericListItemContentsAtDepth depth

-- | Ordered List of given depth, depth being the number of
-- leading '#'
-- The first Ordered List Item may have a start attribute
orderedListAtDepth :: PandocMonad m => Int -> TextileParser m Blocks
orderedListAtDepth depth = try $ do
items <- many1 (orderedListItemAtDepth depth)
return $ B.orderedList items
(startNum, firstItem) <- firstOrderedListItemAtDepth depth
moreItems <- many (orderedListItemAtDepth depth)
let listItems = firstItem : moreItems
return $ B.orderedListWith (startNum, DefaultStyle, DefaultDelim) listItems

-- | The first Ordered List Item, which could have a start attribute
firstOrderedListItemAtDepth :: PandocMonad m => Int
-> TextileParser m (Int, Blocks)
firstOrderedListItemAtDepth depth = try $ do
startNum <- orderedListStartAtDepth depth
contents <- genericListItemContentsAtDepth depth
return (startNum, contents)

-- | Ordered List Item of given depth, depth being the number of
-- leading '#'
orderedListItemAtDepth :: PandocMonad m => Int -> TextileParser m Blocks
orderedListItemAtDepth = genericListItemAtDepth '#'

-- | Common implementation of list items
genericListItemAtDepth :: PandocMonad m => Char -> Int -> TextileParser m Blocks
genericListItemAtDepth c depth = try $ do
count depth (char c) >> attributes >> whitespace
orderedListItemAtDepth depth = try $ do
orderedListStartAtDepth depth
genericListItemContentsAtDepth depth

-- | Lists always start with a number of leading characters '#' or '*'
-- Ordered list start characters '#' can be followed by the start attribute
-- number, but bullet list characters '*' can not
orderedListStartAtDepth :: PandocMonad m => Int -> TextileParser m Int
orderedListStartAtDepth depth = count depth (char '#') >>
try orderedListStartAttr <* (attributes >> whitespace)

bulletListStartAtDepth :: PandocMonad m => Int -> TextileParser m ()
bulletListStartAtDepth depth = () <$ (count depth (char '*') >>
attributes >> whitespace)

-- | The leading characters and start attributes differ between ordered and
-- unordered lists, but their contents have the same structure and can
-- share a Parser
genericListItemContentsAtDepth :: PandocMonad m => Int
-> TextileParser m Blocks
genericListItemContentsAtDepth depth = do
contents <- mconcat <$> many ((B.plain . mconcat <$> many1 inline) <|>
try (newline >> codeBlockHtml))
newline
sublist <- option mempty (anyListAtDepth (depth + 1))
return $ contents <> sublist


-- | A definition list is a set of consecutive definition items
definitionList :: PandocMonad m => TextileParser m Blocks
definitionList = try $ B.definitionList <$> many1 definitionListItem

-- | List start character.
listStart :: PandocMonad m => TextileParser m ()
listStart = genericListStart '*'
<|> () <$ genericListStart '#'
<|> () <$ orderedListStart
<|> () <$ definitionListStart

genericListStart :: PandocMonad m => Char -> TextileParser m ()
genericListStart c = () <$ try (many1 (char c) >> whitespace)

orderedListStart :: PandocMonad m => TextileParser m ()
orderedListStart = () <$ try (many1 (char '#') >>
try orderedListStartAttr >>
whitespace)

basicDLStart :: PandocMonad m => TextileParser m ()
basicDLStart = do
char '-'
Expand Down Expand Up @@ -631,6 +666,13 @@ code2 = do
htmlTag (tagOpen (=="tt") null)
B.code . T.pack <$> manyTill anyChar' (try $ htmlTag $ tagClose (=="tt"))

orderedListStartAttr :: PandocMonad m => TextileParser m Int
orderedListStartAttr = do
digits <- many digit
case readMaybe digits :: Maybe Int of
Nothing -> return 1
Just n -> return n

-- | Html / CSS attributes
attributes :: PandocMonad m => TextileParser m Attr
attributes = foldl' (flip ($)) ("",[],[]) <$>
Expand Down
59 changes: 59 additions & 0 deletions test/command/2465.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
```
% pandoc -f textile -t native
This list starts:
# one
# two
This list should continue at 3:
#3 three
# four
This list should restart at 1:
# one again
# two again
^D
[ Para
[ Str "This" , Space , Str "list" , Space , Str "starts:" ]
, OrderedList
( 1 , DefaultStyle , DefaultDelim )
[ [ Plain [ Str "one" ] ] , [ Plain [ Str "two" ] ] ]
, Para
[ Str "This"
, Space
, Str "list"
, Space
, Str "should"
, Space
, Str "continue"
, Space
, Str "at"
, Space
, Str "3:"
]
, OrderedList
( 3 , DefaultStyle , DefaultDelim )
[ [ Plain [ Str "three" ] ] , [ Plain [ Str "four" ] ] ]
, Para
[ Str "This"
, Space
, Str "list"
, Space
, Str "should"
, Space
, Str "restart"
, Space
, Str "at"
, Space
, Str "1:"
]
, OrderedList
( 1 , DefaultStyle , DefaultDelim )
[ [ Plain [ Str "one" , Space , Str "again" ] ]
, [ Plain [ Str "two" , Space , Str "again" ] ]
]
]
```

0 comments on commit cb3941c

Please sign in to comment.