asciidoc 0.1.0.1 → 0.1.0.2
raw patch · 15 files changed
+471/−32 lines, 15 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- CHANGELOG.md +10/−0
- asciidoc.cabal +2/−1
- src/AsciiDoc/Parse.hs +32/−31
- test/regression/issue_4a.test +23/−0
- test/regression/issue_4b.test +26/−0
- test/regression/issue_4c.test +26/−0
- test/regression/issue_4d.test +29/−0
- test/regression/issue_4e.test +30/−0
- test/regression/issue_4f.test +30/−0
- test/regression/issue_4g.test +32/−0
- test/regression/issue_4h.test +36/−0
- test/regression/issue_5.test +116/−0
- test/regression/issue_8.test +40/−0
- test/regression/issue_9.test +27/−0
- test/regression/issue_9_include.adoc +12/−0
CHANGELOG.md view
@@ -1,5 +1,15 @@ # Revision history for asciidoc-hs +## 0.1.0.2 -- 2026-03-17++ * Allow fenced constructions to end with end-of-input (#9).++ * Fix issue in parsing bracketed arguments (#8).++ * Fix bug in table parsing with rowspans (#5).++ * Improved parsing of line and block comments (#4).+ ## 0.1.0.1 -- 2026-02-01 * Fix character escaping issue (#3). Unconstrained forms of
asciidoc.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.4 name: asciidoc-version: 0.1.0.1+version: 0.1.0.2 synopsis: AsciiDoc parser. description: A parser for AsciiDoc syntax. license: BSD-3-Clause@@ -13,6 +13,7 @@ extra-doc-files: CHANGELOG.md extra-source-files: test/asciidoctor/**/*.test test/regression/*.test+ test/regression/issue_9_include.adoc test/feature/**/*.test test/feature/include/**/*.adoc
src/AsciiDoc/Parse.hs view
@@ -12,7 +12,7 @@ import Prelude hiding (takeWhile) import Text.HTML.TagSoup.Entity (lookupNamedEntity)-import Data.Maybe (isNothing, listToMaybe, fromMaybe)+import Data.Maybe (isNothing, listToMaybe, fromMaybe, catMaybes) import Data.Bifunctor (first) import Data.Either (lefts, rights) import qualified Data.Map as M@@ -254,7 +254,7 @@ bs <- (case M.lookup "hardbreaks-option" attr' of Just "" -> withHardBreaks _ -> id) $- withBlockContext (SectionContext (minSectionLevel - 1)) (many pBlock)+ withBlockContext (SectionContext (minSectionLevel - 1)) pBlocks skipWhile isSpace endOfInput attr <- gets docAttrs@@ -371,8 +371,8 @@ skipBlankLines = do contexts <- asks blockContexts case contexts of- ListContext{} : _ -> void $ many $ vchar '+' *> pBlankLine- _ -> void $ many pBlankLine+ ListContext{} : _ -> skipMany $ vchar '+' *> pBlankLine+ _ -> skipMany pBlankLine pBlankLine :: P () pBlankLine = takeWhile (\c -> c == ' ' || c == '\t') *> (pLineComment <|> endOfLine)@@ -397,7 +397,7 @@ skipBlankLines skipMany pDocAttribute skipBlankLines- pure bs+ pure $ catMaybes bs parseAsciidoc :: Text -> P Document parseAsciidoc = parseWith pDocument . (<> "\n") . T.strip@@ -415,14 +415,13 @@ parseInlines :: Text -> P [Inline] parseInlines = parseWith pInlines . T.strip -pBlock :: P Block+pBlock :: P (Maybe Block) pBlock = do contexts <- asks blockContexts skipBlankLines skipMany pDocAttribute skipBlankLines (mbtitle, attr) <- pTitlesAndAttributes- skipMany (pCommentBlock attr) case contexts of ListContext{} : _ -> skipWhile (== ' ') _ -> pure ()@@ -432,7 +431,8 @@ | Just opts <- M.lookup "options" kvs -> "hardbreaks" `T.isInfixOf` opts _ -> False- (if hardbreaks then withHardBreaks else id) $+ (Nothing <$ pCommentBlock attr) <|> fmap Just+ ((if hardbreaks then withHardBreaks else id) $ pBlockMacro mbtitle attr <|> pDiscreteHeading mbtitle attr <|> pExampleBlock mbtitle attr@@ -454,7 +454,7 @@ , pDefinitionList , pIndentedLiteral , pPara- ]+ ]) pIndentedLiteral :: P BlockType@@ -556,7 +556,7 @@ guard (lev > sectionLevel && lev >= 0 && lev <= 5) vchar ' ' title <- pLine >>= parseInlines- contents <- withBlockContext (SectionContext lev) $ many pBlock+ contents <- withBlockContext (SectionContext lev) pBlocks -- note: we use sectionLevel, not lev, so in improperly nested content, e.g., -- == foo -- ==== bar@@ -629,7 +629,7 @@ let newContext = case contexts of ListContext ':' n : _ -> ListContext ':' (n + 1) _ -> ListContext ':' 1- defn <- withBlockContext newContext (many pBlock)+ defn <- withBlockContext newContext pBlocks void $ many pBlankLine pure (term, defn) @@ -700,14 +700,14 @@ pListItem = do mbCheckboxState <- optional pCheckbox skipWhile (==' ')- bs <- many pBlock+ bs <- pBlocks pure $ ListItem mbCheckboxState bs pDelimitedLiteralBlock :: Char -> Int -> P [T.Text] pDelimitedLiteralBlock c minimumNumber = do len <- length <$> some (vchar c) <* pBlankLine guard $ len >= minimumNumber- let endFence = count len (vchar c) *> pBlankLine+ let endFence = count len (vchar c) *> (pBlankLine <|> endOfInput) manyTill pLine endFence pDelimitedBlock :: Char -> Int -> P [Block]@@ -716,7 +716,7 @@ guard $ len >= minimumNumber let endFence = count len (vchar c) *> pBlankLine withBlockContext (DelimitedContext c len) $- manyTill pBlock endFence+ catMaybes <$> manyTill pBlock endFence pPassBlock :: Maybe BlockTitle -> Attr -> P Block pPassBlock mbtitle attr = do@@ -905,6 +905,7 @@ pNormalLine :: P Text pNormalLine = do+ notFollowedBy (string "////" *> pBlankLine) -- block comment t <- pLine fp <- asks filePath guard $ not $ T.all (\c -> c == ' ' || c == '\t') t@@ -970,16 +971,16 @@ -- if there are rowspans from rows above, we need to skip some: let mbspecs' = case mbspecs of Nothing -> Nothing- Just specs' -> Just [s | (s,0) <- zip specs' rowspans]+ Just specs' -> Just [s | (s,n) <- zip specs' rowspans, n <= 0] row@(TableRow cells) <- pTableRow tableOpts mbspecs' let numcols = sum (map cellColspan cells) let specs = fromMaybe (replicate numcols defaultColumnSpec) mbspecs -- now, update rowspans in light of new row let updateRowspans [] rs = rs updateRowspans (c:cs) rs =- map (+ (cellRowspan c - 1)) (take (cellColspan c) rs)+ map (+ (cellRowspan c)) (take (cellColspan c) rs) ++ updateRowspans cs (drop (cellColspan c) rs)- let rowspans' = updateRowspans cells rowspans+ let rowspans' = updateRowspans cells (map (\x -> x - 1) rowspans) (\(rows, colspecs') -> (row:rows, case rows of [] -> specs _ -> colspecs'))@@ -1289,17 +1290,18 @@ pure $ T.pack result pInlines' :: [Char] -> P [Inline]-pInlines' cs =- (do il' <- pInline cs- let il = case il' of- Inline (Attr ps kvs) (Span ils)- | Nothing <- M.lookup "role" kvs- -> Inline (Attr ps kvs) (Highlight ils)- _ -> il'- addStr . (il:) <$> pInlines' [])- <|> (do c <- anyChar- pInlines' (c:cs))- <|> (addStr [] <$ endOfInput)+pInlines' cs = do+ (pLineComment *> pInlines' cs)+ <|> (do il' <- pInline cs+ let il = case il' of+ Inline (Attr ps kvs) (Span ils)+ | Nothing <- M.lookup "role" kvs+ -> Inline (Attr ps kvs) (Highlight ils)+ _ -> il'+ addStr . (il:) <$> pInlines' [])+ <|> (do c <- anyChar+ pInlines' (c:cs))+ <|> (addStr [] <$ endOfInput) where addStr = case cs of [] -> id@@ -1348,7 +1350,6 @@ (d:_) -> isSpace d || isPunctuation d || d == '+' [] -> True let inMatched = pInMatched maybeUnconstrained- skipMany pLineComment (do attr <- pFormattedTextAttributes <|> pure mempty c <- peekChar' case c of@@ -1391,7 +1392,7 @@ <$> (string "+++" *> manyTill anyChar (string "+++")) pLineComment :: P ()-pLineComment = string "//" *> skipWhile (== ' ') *> void pLine+pLineComment = string "//" *> satisfy (\c -> c == ' ' || c == '\t') *> void pLine pCrossReference :: P Inline pCrossReference = do@@ -1600,7 +1601,7 @@ (T.pack <$> some ((vchar '\\' *> char ']') <|> (vchar '+' *> vchar '+' *> char ']' <* vchar '+' <* vchar '+') <|>- satisfy (\c -> c /= ']' && not (isEndOfLine c)) <|>+ satisfy (\c -> c /= ']' && c /= '[' && not (isEndOfLine c)) <|> (' ' <$ (vchar '\\' <* endOfLine))) <|> ((\x -> "[" <> x <> "]") <$> pBracketedText))) <* vchar ']'
+ test/regression/issue_4a.test view
@@ -0,0 +1,23 @@+<<<+Asciidoc text followed by a line comment.+// LINE COMMENT+>>>+Document+ { docMeta =+ Meta+ { docTitle = []+ , docTitleAttributes = Nothing+ , docAuthors = []+ , docRevision = Nothing+ , docAttributes = fromList [ ( "sectids" , "" ) ]+ }+ , docBlocks =+ [ Block mempty Nothing PageBreak+ , Block+ mempty+ Nothing+ (Paragraph+ [ Inline mempty (Str "Asciidoc text followed by a line comment.\n")+ ])+ ]+ }
+ test/regression/issue_4b.test view
@@ -0,0 +1,26 @@+<<<+Asciidoc text followed by a blank line and a line comment.++// LINE COMMENT+>>>+Document+ { docMeta =+ Meta+ { docTitle = []+ , docTitleAttributes = Nothing+ , docAuthors = []+ , docRevision = Nothing+ , docAttributes = fromList [ ( "sectids" , "" ) ]+ }+ , docBlocks =+ [ Block mempty Nothing PageBreak+ , Block+ mempty+ Nothing+ (Paragraph+ [ Inline+ mempty+ (Str "Asciidoc text followed by a blank line and a line comment.")+ ])+ ]+ }
+ test/regression/issue_4c.test view
@@ -0,0 +1,26 @@+<<<+Asciidoc text followed by a line comment+// LINE COMMENT+followed by text.+>>>+Document+ { docMeta =+ Meta+ { docTitle = []+ , docTitleAttributes = Nothing+ , docAuthors = []+ , docRevision = Nothing+ , docAttributes = fromList [ ( "sectids" , "" ) ]+ }+ , docBlocks =+ [ Block mempty Nothing PageBreak+ , Block+ mempty+ Nothing+ (Paragraph+ [ Inline+ mempty+ (Str "Asciidoc text followed by a line comment\nfollowed by text.")+ ])+ ]+ }
+ test/regression/issue_4d.test view
@@ -0,0 +1,29 @@+<<<+Asciidoc text followed by a line comment.+// LINE COMMENT++Followed by a new paragraph.+>>>+Document+ { docMeta =+ Meta+ { docTitle = []+ , docTitleAttributes = Nothing+ , docAuthors = []+ , docRevision = Nothing+ , docAttributes = fromList [ ( "sectids" , "" ) ]+ }+ , docBlocks =+ [ Block mempty Nothing PageBreak+ , Block+ mempty+ Nothing+ (Paragraph+ [ Inline mempty (Str "Asciidoc text followed by a line comment.\n")+ ])+ , Block+ mempty+ Nothing+ (Paragraph [ Inline mempty (Str "Followed by a new paragraph.") ])+ ]+ }
+ test/regression/issue_4e.test view
@@ -0,0 +1,30 @@+<<<+Asciidoc text followed by a line comment.++// LINE COMMENT++Followed by a new paragraph.+>>>+Document+ { docMeta =+ Meta+ { docTitle = []+ , docTitleAttributes = Nothing+ , docAuthors = []+ , docRevision = Nothing+ , docAttributes = fromList [ ( "sectids" , "" ) ]+ }+ , docBlocks =+ [ Block mempty Nothing PageBreak+ , Block+ mempty+ Nothing+ (Paragraph+ [ Inline mempty (Str "Asciidoc text followed by a line comment.")+ ])+ , Block+ mempty+ Nothing+ (Paragraph [ Inline mempty (Str "Followed by a new paragraph.") ])+ ]+ }
+ test/regression/issue_4f.test view
@@ -0,0 +1,30 @@+<<<+Asciidoc text followed by a block comment+////+BLOCK COMMENT+////+followed by text.+>>>+Document+ { docMeta =+ Meta+ { docTitle = []+ , docTitleAttributes = Nothing+ , docAuthors = []+ , docRevision = Nothing+ , docAttributes = fromList [ ( "sectids" , "" ) ]+ }+ , docBlocks =+ [ Block mempty Nothing PageBreak+ , Block+ mempty+ Nothing+ (Paragraph+ [ Inline mempty (Str "Asciidoc text followed by a block comment")+ ])+ , Block+ mempty+ Nothing+ (Paragraph [ Inline mempty (Str "followed by text.") ])+ ]+ }
+ test/regression/issue_4g.test view
@@ -0,0 +1,32 @@+<<<+Asciidoc text followed by a block comment.++////+BLOCK COMMENT+////++Followed by a new paragraph.+>>>+Document+ { docMeta =+ Meta+ { docTitle = []+ , docTitleAttributes = Nothing+ , docAuthors = []+ , docRevision = Nothing+ , docAttributes = fromList [ ( "sectids" , "" ) ]+ }+ , docBlocks =+ [ Block mempty Nothing PageBreak+ , Block+ mempty+ Nothing+ (Paragraph+ [ Inline mempty (Str "Asciidoc text followed by a block comment.")+ ])+ , Block+ mempty+ Nothing+ (Paragraph [ Inline mempty (Str "Followed by a new paragraph.") ])+ ]+ }
+ test/regression/issue_4h.test view
@@ -0,0 +1,36 @@+<<<+Asciidoc text followed by a multi-line block comment.++////+BLOCK COMMENT LINE 1+LINE 2+LINE 3+////++Followed by a new paragraph.+>>>+Document+ { docMeta =+ Meta+ { docTitle = []+ , docTitleAttributes = Nothing+ , docAuthors = []+ , docRevision = Nothing+ , docAttributes = fromList [ ( "sectids" , "" ) ]+ }+ , docBlocks =+ [ Block mempty Nothing PageBreak+ , Block+ mempty+ Nothing+ (Paragraph+ [ Inline+ mempty+ (Str "Asciidoc text followed by a multi-line block comment.")+ ])+ , Block+ mempty+ Nothing+ (Paragraph [ Inline mempty (Str "Followed by a new paragraph.") ])+ ]+ }
+ test/regression/issue_5.test view
@@ -0,0 +1,116 @@+<<<+|===+|col1|col2+|11 .2+|12|13+|21 .2+|22|23+|===+>>>+Document+ { docMeta =+ Meta+ { docTitle = []+ , docTitleAttributes = Nothing+ , docAuthors = []+ , docRevision = Nothing+ , docAttributes = fromList [ ( "sectids" , "" ) ]+ }+ , docBlocks =+ [ Block mempty Nothing PageBreak+ , Block+ mempty+ Nothing+ (Table+ [ ColumnSpec+ { colHorizAlign = Nothing+ , colVertAlign = Nothing+ , colWidth = Nothing+ , colStyle = Nothing+ }+ , ColumnSpec+ { colHorizAlign = Nothing+ , colVertAlign = Nothing+ , colWidth = Nothing+ , colStyle = Nothing+ }+ ]+ (Just+ [ TableRow+ [ TableCell+ { cellContent =+ [ Block mempty Nothing (Paragraph [ Inline mempty (Str "col1") ]) ]+ , cellHorizAlign = Nothing+ , cellVertAlign = Nothing+ , cellColspan = 1+ , cellRowspan = 1+ }+ , TableCell+ { cellContent =+ [ Block mempty Nothing (Paragraph [ Inline mempty (Str "col2") ]) ]+ , cellHorizAlign = Nothing+ , cellVertAlign = Nothing+ , cellColspan = 1+ , cellRowspan = 1+ }+ ]+ ])+ [ TableRow+ [ TableCell+ { cellContent =+ [ Block mempty Nothing (Paragraph [ Inline mempty (Str "11") ]) ]+ , cellHorizAlign = Nothing+ , cellVertAlign = Nothing+ , cellColspan = 1+ , cellRowspan = 1+ }+ , TableCell+ { cellContent =+ [ Block mempty Nothing (Paragraph [ Inline mempty (Str "12") ]) ]+ , cellHorizAlign = Nothing+ , cellVertAlign = Nothing+ , cellColspan = 1+ , cellRowspan = 2+ }+ ]+ , TableRow+ [ TableCell+ { cellContent =+ [ Block mempty Nothing (Paragraph [ Inline mempty (Str "13") ]) ]+ , cellHorizAlign = Nothing+ , cellVertAlign = Nothing+ , cellColspan = 1+ , cellRowspan = 1+ }+ ]+ , TableRow+ [ TableCell+ { cellContent =+ [ Block mempty Nothing (Paragraph [ Inline mempty (Str "21") ]) ]+ , cellHorizAlign = Nothing+ , cellVertAlign = Nothing+ , cellColspan = 1+ , cellRowspan = 1+ }+ , TableCell+ { cellContent =+ [ Block mempty Nothing (Paragraph [ Inline mempty (Str "22") ]) ]+ , cellHorizAlign = Nothing+ , cellVertAlign = Nothing+ , cellColspan = 1+ , cellRowspan = 2+ }+ ]+ ]+ (Just+ [ TableRow+ [ TableCell+ { cellContent =+ [ Block mempty Nothing (Paragraph [ Inline mempty (Str "23") ]) ]+ , cellHorizAlign = Nothing+ , cellVertAlign = Nothing+ , cellColspan = 1+ , cellRowspan = 1+ }+ ]+ ]))+ ]+ }
+ test/regression/issue_8.test view
@@ -0,0 +1,40 @@+A sentence.footnote:[See https://pandoc.org/MANUAL.html[manual] and other https://pandoc.org/demos.html[demos].]+>>>+Document+ { docMeta =+ Meta+ { docTitle = []+ , docTitleAttributes = Nothing+ , docAuthors = []+ , docRevision = Nothing+ , docAttributes = fromList [ ( "sectids" , "" ) ]+ }+ , docBlocks =+ [ Block+ mempty+ Nothing+ (Paragraph+ [ Inline mempty (Str "A sentence.")+ , Inline+ mempty+ (Footnote+ Nothing+ [ Inline mempty (Str "See ")+ , Inline+ mempty+ (Link+ URLLink+ (Target "https://pandoc.org/MANUAL.html")+ [ Inline mempty (Str "manual") ])+ , Inline mempty (Str " and other ")+ , Inline+ mempty+ (Link+ URLLink+ (Target "https://pandoc.org/demos.html")+ [ Inline mempty (Str "demos") ])+ , Inline mempty (Str ".")+ ])+ ])+ ]+ }
+ test/regression/issue_9.test view
@@ -0,0 +1,27 @@+include::issue_9_include.adoc[]+>>>+Document+ { docMeta =+ Meta+ { docTitle = []+ , docTitleAttributes = Nothing+ , docAuthors = []+ , docRevision = Nothing+ , docAttributes = fromList [ ( "sectids" , "" ) ]+ }+ , docBlocks =+ [ Block+ mempty+ Nothing+ (Include+ "test/regression/issue_9_include.adoc"+ (Just+ [ Block+ Attr+ ( [ "source" , "cpp" ] , fromList [] )+ Nothing+ (LiteralBlock+ "#include \"MyFile.h\"\n\nMyClass::MyClass(LibParent *parent,\n LibCollectionPtr inputCollection)\n : LibClass(parent) {\n \n myMemberFn(inputCollection, this->getLibItem());\n \n}\n")+ ]))+ ]+ }
+ test/regression/issue_9_include.adoc view
@@ -0,0 +1,12 @@+[source, cpp] +.... +#include "MyFile.h" + +MyClass::MyClass(LibParent *parent, + LibCollectionPtr inputCollection) + : LibClass(parent) { + + myMemberFn(inputCollection, this->getLibItem()); + +} +....