git.iko.soy/typeable/pandoc
on master help sign in
Merge branch 'asciidoc'
commitc552aa24cf9696dee67ea3df42865b9f77b5733f authorJohn MacFarlane <fiddlosopher@gmail.com> dateFri 18 Nov 2011, 19:53 (15 years ago) parent43c6c1d679e94e
9 files changed+1121−5
pandoc.cabal+6−3 src/Tests/Old.hs+1−1 src/Text/Pandoc.hs+3 src/Text/Pandoc/Pretty.hs+13 src/Text/Pandoc/Writers/Asciidoc.hs+369 src/pandoc.hs+1 templates+1−1 tests/tables.asciidoc+71 tests/writer.asciidoc+656
pandoc.cabal+6−3
@@ -19,8 +19,8 @@ Description: Pandoc is a Haskell library for converting from one markup
1919 reStructuredText, HTML, LaTeX and Textile, and it can write
2020 markdown, reStructuredText, HTML, LaTeX, ConTeXt, Docbook,
2121 OpenDocument, ODT, RTF, MediaWiki, Textile, groff man pages,
22− plain text, Emacs Org-Mode, EPUB, and S5 and Slidy HTML
23− slide shows.
22+ plain text, Emacs Org-Mode, Asciidoc, EPUB,
23+ and S5 and Slidy HTML slide shows.
2424 .
2525 Pandoc extends standard markdown syntax with footnotes,
2626 embedded LaTeX, definition lists, tables, and other
@@ -44,7 +44,7 @@ Data-Files:
4444 templates/default.rst, templates/default.plain,
4545 templates/default.mediawiki, templates/default.rtf,
4646 templates/default.s5, templates/default.slidy,
47− templates/default.dzslides,
47+ templates/default.dzslides, templates/default.asciidoc,
4848 templates/default.textile, templates/default.org
4949 -- data for ODT writer
5050 reference.odt,
@@ -122,6 +122,7 @@ Extra-Source-Files:
122122 tests/tables.native,
123123 tests/tables.opendocument,
124124 tests/tables.org,
125+ tests/tables.asciidoc,
125126 tests/tables.texinfo,
126127 tests/tables.rst,
127128 tests/tables.rtf,
@@ -141,6 +142,7 @@ Extra-Source-Files:
141142 tests/writer.native,
142143 tests/writer.opendocument,
143144 tests/writer.org,
145+ tests/writer.asciidoc,
144146 tests/writer.rst,
145147 tests/writer.rtf,
146148 tests/writer.texinfo,
@@ -253,6 +255,7 @@ Library
253255 Text.Pandoc.Writers.Markdown,
254256 Text.Pandoc.Writers.RST,
255257 Text.Pandoc.Writers.Org,
258+ Text.Pandoc.Writers.Asciidoc,
256259 Text.Pandoc.Writers.Textile,
257260 Text.Pandoc.Writers.MediaWiki,
258261 Text.Pandoc.Writers.RTF,
src/Tests/Old.hs+1−1
@@ -105,7 +105,7 @@ tests = [ testGroup "markdown"
105105 ]
106106 , testGroup "other writers" $ map (\f -> testGroup f $ writerTests f)
107107 [ "docbook", "opendocument" , "context" , "texinfo"
108− , "man" , "plain" , "mediawiki", "rtf", "org"
108+ , "man" , "plain" , "mediawiki", "rtf", "org", "asciidoc"
109109 ]
110110 ]
111111
src/Text/Pandoc.hs+3
@@ -96,6 +96,7 @@ module Text.Pandoc
9696 , writeODT
9797 , writeEPUB
9898 , writeOrg
99+ , writeAsciidoc
99100 -- * Writer options used in writers
100101 , WriterOptions (..)
101102 , HTMLSlideVariant (..)
@@ -135,6 +136,7 @@ import Text.Pandoc.Writers.RTF
135136import Text.Pandoc.Writers.MediaWiki
136137import Text.Pandoc.Writers.Textile
137138import Text.Pandoc.Writers.Org
139+import Text.Pandoc.Writers.Asciidoc
138140import Text.Pandoc.Templates
139141import Text.Pandoc.Parsing
140142import Text.Pandoc.Shared
@@ -193,6 +195,7 @@ writers = [("native" , writeNative)
193195 ,("textile" , writeTextile)
194196 ,("rtf" , writeRTF)
195197 ,("org" , writeOrg)
198+ ,("asciidoc" , writeAsciidoc)
196199 ]
197200
198201-- | Converts a transformation on the Pandoc AST into a function
src/Text/Pandoc/Pretty.hs+13
@@ -59,6 +59,7 @@ module Text.Pandoc.Pretty (
5959 , hsep
6060 , vcat
6161 , vsep
62+ , chomp
6263 , inside
6364 , braces
6465 , brackets
@@ -164,6 +165,17 @@ vcat = foldr ($$) empty
164165vsep :: [Doc] -> Doc
165166vsep = foldr ($+$) empty
166167
168+-- | Chomps trailing blank space off of a 'Doc'.
169+chomp :: Doc -> Doc
170+chomp d = Doc (fromList dl')
171+ where dl = toList (unDoc d)
172+ dl' = reverse $ dropWhile removeable $ reverse dl
173+ removeable BreakingSpace = True
174+ removeable CarriageReturn = True
175+ removeable NewLine = True
176+ removeable BlankLine = True
177+ removeable _ = False
178+
167179outp :: (IsString a, Monoid a)
168180 => Int -> String -> DocState a
169181outp off s | off <= 0 = do
@@ -427,3 +439,4 @@ quotes = inside (char '\'') (char '\'')
427439-- | Wraps a 'Doc' in double quotes.
428440doubleQuotes :: Doc -> Doc
429441doubleQuotes = inside (char '"') (char '"')
442+
src/Text/Pandoc/Writers/Asciidoc.hsnew file+369
@@ -0,0 +1,369 @@
1+{-# LANGUAGE OverloadedStrings #-}
2+{-
3+Copyright (C) 2006-2010 John MacFarlane <jgm@berkeley.edu>
4+
5+This program is free software; you can redistribute it and/or modify
6+it under the terms of the GNU General Public License as published by
7+the Free Software Foundation; either version 2 of the License, or
8+(at your option) any later version.
9+
10+This program is distributed in the hope that it will be useful,
11+but WITHOUT ANY WARRANTY; without even the implied warranty of
12+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+GNU General Public License for more details.
14+
15+You should have received a copy of the GNU General Public License
16+along with this program; if not, write to the Free Software
17+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18+-}
19+
20+{- |
21+ Module : Text.Pandoc.Writers.Asciidoc
22+ Copyright : Copyright (C) 2006-2010 John MacFarlane
23+ License : GNU GPL, version 2 or above
24+
25+ Maintainer : John MacFarlane <jgm@berkeley.edu>
26+ Stability : alpha
27+ Portability : portable
28+
29+Conversion of 'Pandoc' documents to asciidoc.
30+
31+Note that some information may be lost in conversion, due to
32+expressive limitations of asciidoc. Footnotes and table cells with
33+paragraphs (or other block items) are not possible in asciidoc.
34+If pandoc encounters one of these, it will insert a message indicating
35+that it has omitted the construct.
36+
37+Asciidoc: <http://www.methods.co.nz/asciidoc/>
38+-}
39+module Text.Pandoc.Writers.Asciidoc (writeAsciidoc) where
40+import Text.Pandoc.Definition
41+import Text.Pandoc.Templates (renderTemplate)
42+import Text.Pandoc.Shared
43+import Text.Pandoc.Parsing hiding (blankline)
44+import Text.ParserCombinators.Parsec ( runParser, GenParser )
45+import Data.List ( isPrefixOf, intersperse, intercalate )
46+import Text.Pandoc.Pretty
47+import Control.Monad.State
48+
49+data WriterState = WriterState { defListMarker :: String
50+ , orderedListLevel :: Int
51+ , bulletListLevel :: Int
52+ }
53+
54+-- | Convert Pandoc to Asciidoc.
55+writeAsciidoc :: WriterOptions -> Pandoc -> String
56+writeAsciidoc opts document =
57+ evalState (pandocToAsciidoc opts document) WriterState{
58+ defListMarker = "::"
59+ , orderedListLevel = 1
60+ , bulletListLevel = 1
61+ }
62+
63+-- | Return markdown representation of document.
64+pandocToAsciidoc :: WriterOptions -> Pandoc -> State WriterState String
65+pandocToAsciidoc opts (Pandoc (Meta title authors date) blocks) = do
66+ title' <- inlineListToAsciidoc opts title
67+ let title'' = title' $$ text (replicate (offset title') '=')
68+ authors' <- mapM (inlineListToAsciidoc opts) authors
69+ -- asciidoc only allows a singel author
70+ date' <- inlineListToAsciidoc opts date
71+ let titleblock = not $ null title && null authors && null date
72+ body <- blockListToAsciidoc opts blocks
73+ let colwidth = if writerWrapText opts
74+ then Just $ writerColumns opts
75+ else Nothing
76+ let main = render colwidth body
77+ let context = writerVariables opts ++
78+ [ ("body", main)
79+ , ("title", render colwidth title'')
80+ , ("date", render colwidth date')
81+ ] ++
82+ [ ("toc", "yes") | writerTableOfContents opts &&
83+ writerStandalone opts ] ++
84+ [ ("titleblock", "yes") | titleblock ] ++
85+ [ ("author", render colwidth a) | a <- authors' ]
86+ if writerStandalone opts
87+ then return $ renderTemplate context $ writerTemplate opts
88+ else return main
89+
90+-- | Escape special characters for Asciidoc.
91+escapeString :: String -> String
92+escapeString = escapeStringUsing markdownEscapes
93+ where markdownEscapes = backslashEscapes "\\`*_>#~^{+"
94+
95+-- | Ordered list start parser for use in Para below.
96+olMarker :: GenParser Char ParserState Char
97+olMarker = do (start, style', delim) <- anyOrderedListMarker
98+ if delim == Period &&
99+ (style' == UpperAlpha || (style' == UpperRoman &&
100+ start `elem` [1, 5, 10, 50, 100, 500, 1000]))
101+ then spaceChar >> spaceChar
102+ else spaceChar
103+
104+-- | True if string begins with an ordered list marker
105+beginsWithOrderedListMarker :: String -> Bool
106+beginsWithOrderedListMarker str =
107+ case runParser olMarker defaultParserState "para start" (take 10 str) of
108+ Left _ -> False
109+ Right _ -> True
110+
111+-- | Convert Pandoc block element to markdown.
112+blockToAsciidoc :: WriterOptions -- ^ Options
113+ -> Block -- ^ Block element
114+ -> State WriterState Doc
115+blockToAsciidoc _ Null = return empty
116+blockToAsciidoc opts (Plain inlines) = do
117+ contents <- inlineListToAsciidoc opts inlines
118+ return $ contents <> cr
119+blockToAsciidoc opts (Para inlines) = do
120+ contents <- inlineListToAsciidoc opts inlines
121+ -- escape if para starts with ordered list marker
122+ let esc = if beginsWithOrderedListMarker (render Nothing contents)
123+ then text "\\"
124+ else empty
125+ return $ esc <> contents <> blankline
126+blockToAsciidoc _ (RawBlock _ _) = return empty
127+blockToAsciidoc _ HorizontalRule =
128+ return $ blankline <> text "'''''" <> blankline
129+blockToAsciidoc opts (Header level inlines) = do
130+ contents <- inlineListToAsciidoc opts inlines
131+ let len = offset contents
132+ return $ contents <> cr <>
133+ (case level of
134+ 1 -> text $ replicate len '-'
135+ 2 -> text $ replicate len '~'
136+ 3 -> text $ replicate len '^'
137+ 4 -> text $ replicate len '+'
138+ _ -> empty) <> blankline
139+blockToAsciidoc _ (CodeBlock (_,classes,_) str) = return $
140+ flush (attrs <> dashes <> space <> attrs <> cr <> text str <>
141+ cr <> dashes) <> blankline
142+ where dashes = text $ replicate (maximum $ map length $ lines str) '-'
143+ attrs = if null classes
144+ then empty
145+ else text $ intercalate "," $ "code" : classes
146+blockToAsciidoc opts (BlockQuote blocks) = do
147+ contents <- blockListToAsciidoc opts blocks
148+ let isBlock (BlockQuote _) = True
149+ isBlock _ = False
150+ -- if there are nested block quotes, put in an open block
151+ let contents' = if any isBlock blocks
152+ then "--" $$ contents $$ "--"
153+ else contents
154+ let cols = offset contents'
155+ let bar = text $ replicate cols '_'
156+ return $ bar $$ chomp contents' $$ bar <> blankline
157+blockToAsciidoc opts (Table caption aligns widths headers rows) = do
158+ caption' <- inlineListToAsciidoc opts caption
159+ let caption'' = if null caption
160+ then empty
161+ else "." <> caption' <> cr
162+ let isSimple = all (== 0) widths
163+ let relativePercentWidths = if isSimple
164+ then widths
165+ else map (/ (sum widths)) widths
166+ let widths'' :: [Integer]
167+ widths'' = map (floor . (* 100)) relativePercentWidths
168+ -- ensure that the widths sum to 100
169+ let widths' = case widths'' of
170+ _ | isSimple -> widths''
171+ (w:ws) | sum (w:ws) < 100
172+ -> (100 - sum ws) : ws
173+ ws -> ws
174+ let totalwidth :: Integer
175+ totalwidth = floor $ sum widths * 100
176+ let colspec al wi = (case al of
177+ AlignLeft -> "<"
178+ AlignCenter -> "^"
179+ AlignRight -> ">"
180+ AlignDefault -> "") ++
181+ if wi == 0 then "" else (show wi ++ "%")
182+ let headerspec = if all null headers
183+ then empty
184+ else text "options=\"header\","
185+ let widthspec = if totalwidth == 0
186+ then empty
187+ else text "width="
188+ <> doubleQuotes (text $ show totalwidth ++ "%")
189+ <> text ","
190+ let tablespec = text "["
191+ <> widthspec
192+ <> text "cols="
193+ <> doubleQuotes (text $ intercalate ","
194+ $ zipWith colspec aligns widths')
195+ <> text ","
196+ <> headerspec <> text "]"
197+ let makeCell [Plain x] = do d <- blockListToAsciidoc opts [Plain x]
198+ return $ text "|" <> chomp d
199+ makeCell [Para x] = makeCell [Plain x]
200+ makeCell _ = return $ text "|" <> "[multiblock cell omitted]"
201+ let makeRow cells = hsep `fmap` mapM makeCell cells
202+ rows' <- mapM makeRow rows
203+ head' <- makeRow headers
204+ let head'' = if all null headers then empty else head'
205+ let colwidth = if writerWrapText opts
206+ then writerColumns opts
207+ else 100000
208+ let maxwidth = maximum $ map offset (head':rows')
209+ let body = if maxwidth > colwidth then vsep rows' else vcat rows'
210+ let border = text $ "|" ++ replicate ((min maxwidth colwidth) - 1) '='
211+ return $
212+ caption'' $$ tablespec $$ border $$ head'' $$ body $$ border $$ blankline
213+blockToAsciidoc opts (BulletList items) = do
214+ contents <- mapM (bulletListItemToAsciidoc opts) items
215+ return $ cat contents <> blankline
216+blockToAsciidoc opts (OrderedList (start, sty, _delim) items) = do
217+ let markers = orderedListMarkers (start, sty, Period)
218+ let markers' = map (\m -> if length m < 3
219+ then m ++ replicate (3 - length m) ' '
220+ else m) markers
221+ contents <- mapM (\(item, num) -> orderedListItemToAsciidoc opts item num) $
222+ zip markers' items
223+ return $ cat contents <> blankline
224+blockToAsciidoc opts (DefinitionList items) = do
225+ contents <- mapM (definitionListItemToAsciidoc opts) items
226+ return $ cat contents <> blankline
227+
228+-- | Convert bullet list item (list of blocks) to markdown.
229+bulletListItemToAsciidoc :: WriterOptions -> [Block] -> State WriterState Doc
230+bulletListItemToAsciidoc opts blocks = do
231+ let addBlock :: Doc -> Block -> State WriterState Doc
232+ addBlock d b | isEmpty d = chomp `fmap` blockToAsciidoc opts b
233+ addBlock d b@(BulletList _) = do x <- blockToAsciidoc opts b
234+ return $ d <> cr <> chomp x
235+ addBlock d b@(OrderedList _ _) = do x <- blockToAsciidoc opts b
236+ return $ d <> cr <> chomp x
237+ addBlock d b = do x <- blockToAsciidoc opts b
238+ return $ d <> cr <> text "+" <> cr <> chomp x
239+ lev <- bulletListLevel `fmap` get
240+ modify $ \s -> s{ bulletListLevel = lev + 1 }
241+ contents <- foldM addBlock empty blocks
242+ modify $ \s -> s{ bulletListLevel = lev }
243+ let marker = text (replicate lev '*')
244+ return $ marker <> space <> contents <> cr
245+
246+-- | Convert ordered list item (a list of blocks) to markdown.
247+orderedListItemToAsciidoc :: WriterOptions -- ^ options
248+ -> String -- ^ list item marker
249+ -> [Block] -- ^ list item (list of blocks)
250+ -> State WriterState Doc
251+orderedListItemToAsciidoc opts marker blocks = do
252+ let addBlock :: Doc -> Block -> State WriterState Doc
253+ addBlock d b | isEmpty d = chomp `fmap` blockToAsciidoc opts b
254+ addBlock d b@(BulletList _) = do x <- blockToAsciidoc opts b
255+ return $ d <> cr <> chomp x
256+ addBlock d b@(OrderedList _ _) = do x <- blockToAsciidoc opts b
257+ return $ d <> cr <> chomp x
258+ addBlock d b = do x <- blockToAsciidoc opts b
259+ return $ d <> cr <> text "+" <> cr <> chomp x
260+ lev <- orderedListLevel `fmap` get
261+ modify $ \s -> s{ orderedListLevel = lev + 1 }
262+ contents <- foldM addBlock empty blocks
263+ modify $ \s -> s{ orderedListLevel = lev }
264+ return $ text marker <> space <> contents <> cr
265+
266+-- | Convert definition list item (label, list of blocks) to markdown.
267+definitionListItemToAsciidoc :: WriterOptions
268+ -> ([Inline],[[Block]])
269+ -> State WriterState Doc
270+definitionListItemToAsciidoc opts (label, defs) = do
271+ labelText <- inlineListToAsciidoc opts label
272+ marker <- defListMarker `fmap` get
273+ if marker == "::"
274+ then modify (\st -> st{ defListMarker = ";;"})
275+ else modify (\st -> st{ defListMarker = "::"})
276+ let divider = cr <> text "+" <> cr
277+ let defsToAsciidoc :: [Block] -> State WriterState Doc
278+ defsToAsciidoc ds = (vcat . intersperse divider . map chomp)
279+ `fmap` mapM (blockToAsciidoc opts) ds
280+ defs' <- mapM defsToAsciidoc defs
281+ modify (\st -> st{ defListMarker = marker })
282+ let contents = nest 2 $ vcat $ intersperse divider $ map chomp defs'
283+ return $ labelText <> text marker <> cr <> contents <> cr
284+
285+-- | Convert list of Pandoc block elements to markdown.
286+blockListToAsciidoc :: WriterOptions -- ^ Options
287+ -> [Block] -- ^ List of block elements
288+ -> State WriterState Doc
289+blockListToAsciidoc opts blocks = cat `fmap` mapM (blockToAsciidoc opts) blocks
290+
291+-- | Convert list of Pandoc inline elements to markdown.
292+inlineListToAsciidoc :: WriterOptions -> [Inline] -> State WriterState Doc
293+inlineListToAsciidoc opts lst =
294+ mapM (inlineToAsciidoc opts) lst >>= return . cat
295+
296+-- | Convert Pandoc inline element to markdown.
297+inlineToAsciidoc :: WriterOptions -> Inline -> State WriterState Doc
298+inlineToAsciidoc opts (Emph lst) = do
299+ contents <- inlineListToAsciidoc opts lst
300+ return $ "_" <> contents <> "_"
301+inlineToAsciidoc opts (Strong lst) = do
302+ contents <- inlineListToAsciidoc opts lst
303+ return $ "*" <> contents <> "*"
304+inlineToAsciidoc opts (Strikeout lst) = do
305+ contents <- inlineListToAsciidoc opts lst
306+ return $ "[line-through]*" <> contents <> "*"
307+inlineToAsciidoc opts (Superscript lst) = do
308+ contents <- inlineListToAsciidoc opts lst
309+ return $ "^" <> contents <> "^"
310+inlineToAsciidoc opts (Subscript lst) = do
311+ contents <- inlineListToAsciidoc opts lst
312+ return $ "~" <> contents <> "~"
313+inlineToAsciidoc opts (SmallCaps lst) = inlineListToAsciidoc opts lst
314+inlineToAsciidoc opts (Quoted SingleQuote lst) = do
315+ contents <- inlineListToAsciidoc opts lst
316+ return $ "`" <> contents <> "'"
317+inlineToAsciidoc opts (Quoted DoubleQuote lst) = do
318+ contents <- inlineListToAsciidoc opts lst
319+ return $ "``" <> contents <> "''"
320+inlineToAsciidoc _ EmDash = return "\8212"
321+inlineToAsciidoc _ EnDash = return "\8211"
322+inlineToAsciidoc _ Apostrophe = return "\8217"
323+inlineToAsciidoc _ Ellipses = return "\8230"
324+inlineToAsciidoc _ (Code _ str) = return $
325+ text "`" <> text (escapeStringUsing (backslashEscapes "`") str) <> "`"
326+inlineToAsciidoc _ (Str str) = return $ text $ escapeString str
327+inlineToAsciidoc _ (Math InlineMath str) =
328+ return $ "latexmath:[$" <> text str <> "$]"
329+inlineToAsciidoc _ (Math DisplayMath str) =
330+ return $ "latexmath:[$$" <> text str <> "$$]"
331+inlineToAsciidoc _ (RawInline _ _) = return empty
332+inlineToAsciidoc _ (LineBreak) = return $ " +" <> cr
333+inlineToAsciidoc _ Space = return space
334+inlineToAsciidoc opts (Cite _ lst) = inlineListToAsciidoc opts lst
335+inlineToAsciidoc opts (Link txt (src', _tit)) = do
336+-- relative: link:downloads/foo.zip[download foo.zip]
337+-- abs: http://google.cod[Google]
338+-- or my@email.com[email john]
339+ linktext <- inlineListToAsciidoc opts txt
340+ let src = unescapeURI src'
341+ let isRelative = ':' `notElem` src
342+ let prefix = if isRelative
343+ then text "link:"
344+ else empty
345+ let srcSuffix = if isPrefixOf "mailto:" src then drop 7 src else src
346+ let useAuto = case txt of
347+ [Code _ s] | s == srcSuffix -> True
348+ _ -> False
349+ return $ if useAuto
350+ then text srcSuffix
351+ else prefix <> text src <> "[" <> linktext <> "]"
352+inlineToAsciidoc opts (Image alternate (src', tit)) = do
353+-- image:images/logo.png[Company logo, title="blah"]
354+ let txt = if (null alternate) || (alternate == [Str ""])
355+ then [Str "image"]
356+ else alternate
357+ linktext <- inlineListToAsciidoc opts txt
358+ let linktitle = if null tit
359+ then empty
360+ else text $ ",title=\"" ++ tit ++ "\""
361+ let src = unescapeURI src'
362+ return $ "image:" <> text src <> "[" <> linktext <> linktitle <> "]"
363+inlineToAsciidoc opts (Note [Para inlines]) =
364+ inlineToAsciidoc opts (Note [Plain inlines])
365+inlineToAsciidoc opts (Note [Plain inlines]) = do
366+ contents <- inlineListToAsciidoc opts inlines
367+ return $ text "footnote:[" <> contents <> "]"
368+-- asciidoc can't handle blank lines in notes
369+inlineToAsciidoc _ (Note _) = return "[multiblock footnote omitted]"
src/pandoc.hs+1
@@ -647,6 +647,7 @@ defaultWriterName x =
647647 ".odt" -> "odt"
648648 ".epub" -> "epub"
649649 ".org" -> "org"
650+ ".asciidoc" -> "asciidoc"
650651 ['.',y] | y `elem` ['1'..'9'] -> "man"
651652 _ -> "html"
652653
templates+1−1

Submodule changed.

tests/tables.asciidocnew file+71
@@ -0,0 +1,71 @@
1+Simple table with caption:
2+
3+.Demonstration of simple table syntax.
4+[cols=">,<,^,",options="header",]
5+|============================
6+|Right |Left |Center |Default
7+|12 |12 |12 |12
8+|123 |123 |123 |123
9+|1 |1 |1 |1
10+|============================
11+
12+Simple table without caption:
13+
14+[cols=">,<,^,",options="header",]
15+|============================
16+|Right |Left |Center |Default
17+|12 |12 |12 |12
18+|123 |123 |123 |123
19+|1 |1 |1 |1
20+|============================
21+
22+Simple table indented two spaces:
23+
24+.Demonstration of simple table syntax.
25+[cols=">,<,^,",options="header",]
26+|============================
27+|Right |Left |Center |Default
28+|12 |12 |12 |12
29+|123 |123 |123 |123
30+|1 |1 |1 |1
31+|============================
32+
33+Multiline table with caption:
34+
35+.Here's the caption. It may span multiple lines.
36+[width="78%",cols="^21%,<17%,>20%,<42%",options="header",]
37+|=======================================================================
38+|Centered Header |Left Aligned |Right Aligned |Default aligned
39+|First |row |12.0 |Example of a row that spans multiple lines.
40+|Second |row |5.0 |Here's another one. Note the blank line between rows.
41+|=======================================================================
42+
43+Multiline table without caption:
44+
45+[width="78%",cols="^21%,<17%,>20%,<42%",options="header",]
46+|=======================================================================
47+|Centered Header |Left Aligned |Right Aligned |Default aligned
48+|First |row |12.0 |Example of a row that spans multiple lines.
49+|Second |row |5.0 |Here's another one. Note the blank line between rows.
50+|=======================================================================
51+
52+Table without column headers:
53+
54+[cols=">,<,^,>",]
55+|=============================================================================
56+|12 |12 |12 |12
57+
58+|123 |123 |123 |123
59+
60+|1 |1 |1 |1
61+|=============================================================================
62+
63+Multiline table without column headers:
64+
65+[width="78%",cols="^21%,<17%,>20%,42%",]
66+|=============================================================================
67+|First |row |12.0 |Example of a row that spans multiple lines.
68+
69+|Second |row |5.0 |Here's another one. Note the blank line between rows.
70+|=============================================================================
71+
tests/writer.asciidocnew file+656
@@ -0,0 +1,656 @@
1+Pandoc Test Suite
2+=================
3+:author: John MacFarlane
4+:author: Anonymous
5+:date: July 17, 2006
6+
7+This is a set of tests for pandoc. Most of them are adapted from John Gruber’s
8+markdown test suite.
9+
10+'''''
11+
12+Headers
13+-------
14+
15+Level 2 with an link:/url[embedded link]
16+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
17+
18+Level 3 with _emphasis_
19+^^^^^^^^^^^^^^^^^^^^^^^
20+
21+Level 4
22++++++++
23+
24+Level 5
25+
26+Level 1
27+-------
28+
29+Level 2 with _emphasis_
30+~~~~~~~~~~~~~~~~~~~~~~~
31+
32+Level 3
33+^^^^^^^
34+
35+with no blank line
36+
37+Level 2
38+~~~~~~~
39+
40+with no blank line
41+
42+'''''
43+
44+Paragraphs
45+----------
46+
47+Here’s a regular paragraph.
48+
49+In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item.
50+Because a hard-wrapped line in the middle of a paragraph looked like a list
51+item.
52+
53+Here’s one with a bullet. \* criminey.
54+
55+There should be a hard line break +
56+here.
57+
58+'''''
59+
60+Block Quotes
61+------------
62+
63+E-mail style:
64+
65+__________________________________________
66+This is a block quote. It is pretty short.
67+__________________________________________
68+
69+______________________
70+--
71+Code in a block quote:
72+
73+--------------------
74+sub status {
75+ print "working";
76+}
77+--------------------
78+
79+A list:
80+
81+1. item one
82+2. item two
83+
84+Nested block quotes:
85+
86+______
87+nested
88+______
89+
90+______
91+nested
92+______
93+
94+--
95+______________________
96+
97+This should not be a block quote: 2 \> 1.
98+
99+And a following paragraph.
100+
101+'''''
102+
103+Code Blocks
104+-----------
105+
106+Code:
107+
108+--------------------------------------
109+---- (should be four hyphens)
110+
111+sub status {
112+ print "working";
113+}
114+
115+this code block is indented by one tab
116+--------------------------------------
117+
118+And:
119+
120+--------------------------------------------
121+ this code block is indented by two tabs
122+
123+These should not be escaped: \$ \\ \> \[ \{
124+--------------------------------------------
125+
126+'''''
127+
128+Lists
129+-----
130+
131+Unordered
132+~~~~~~~~~
133+
134+Asterisks tight:
135+
136+* asterisk 1
137+* asterisk 2
138+* asterisk 3
139+
140+Asterisks loose:
141+
142+* asterisk 1
143+* asterisk 2
144+* asterisk 3
145+
146+Pluses tight:
147+
148+* Plus 1
149+* Plus 2
150+* Plus 3
151+
152+Pluses loose:
153+
154+* Plus 1
155+* Plus 2
156+* Plus 3
157+
158+Minuses tight:
159+
160+* Minus 1
161+* Minus 2
162+* Minus 3
163+
164+Minuses loose:
165+
166+* Minus 1
167+* Minus 2
168+* Minus 3
169+
170+Ordered
171+~~~~~~~
172+
173+Tight:
174+
175+1. First
176+2. Second
177+3. Third
178+
179+and:
180+
181+1. One
182+2. Two
183+3. Three
184+
185+Loose using tabs:
186+
187+1. First
188+2. Second
189+3. Third
190+
191+and using spaces:
192+
193+1. One
194+2. Two
195+3. Three
196+
197+Multiple paragraphs:
198+
199+1. Item 1, graf one.
200++
201+Item 1. graf two. The quick brown fox jumped over the lazy dog’s back.
202+2. Item 2.
203+3. Item 3.
204+
205+Nested
206+~~~~~~
207+
208+* Tab
209+** Tab
210+*** Tab
211+
212+Here’s another:
213+
214+1. First
215+2. Second:
216+* Fee
217+* Fie
218+* Foe
219+3. Third
220+
221+Same thing but with paragraphs:
222+
223+1. First
224+2. Second:
225+* Fee
226+* Fie
227+* Foe
228+3. Third
229+
230+Tabs and spaces
231+~~~~~~~~~~~~~~~
232+
233+* this is a list item indented with tabs
234+* this is a list item indented with spaces
235+** this is an example list item indented with tabs
236+** this is an example list item indented with spaces
237+
238+Fancy list markers
239+~~~~~~~~~~~~~~~~~~
240+
241+2. begins with 2
242+3. and now 3
243++
244+with a continuation
245+iv. sublist with roman numerals, starting with 4
246+v. more items
247+A. a subsublist
248+B. a subsublist
249+
250+Nesting:
251+
252+A. Upper Alpha
253+I. Upper Roman.
254+6. Decimal start with 6
255+c. Lower alpha with paren
256+
257+Autonumbering:
258+
259+1. Autonumber.
260+2. More.
261+1. Nested.
262+
263+Should not be a list item:
264+
265+M.A. 2007
266+
267+B. Williams
268+
269+'''''
270+
271+Definition Lists
272+----------------
273+
274+Tight using spaces:
275+
276+apple::
277+ red fruit
278+orange::
279+ orange fruit
280+banana::
281+ yellow fruit
282+
283+Tight using tabs:
284+
285+apple::
286+ red fruit
287+orange::
288+ orange fruit
289+banana::
290+ yellow fruit
291+
292+Loose:
293+
294+apple::
295+ red fruit
296+orange::
297+ orange fruit
298+banana::
299+ yellow fruit
300+
301+Multiple blocks with italics:
302+
303+_apple_::
304+ red fruit
305+ +
306+ contains seeds, crisp, pleasant to taste
307+_orange_::
308+ orange fruit
309+ +
310+---------------------
311+{ orange code block }
312+---------------------
313+ +
314+ __________________
315+ orange block quote
316+ __________________
317+
318+Multiple definitions, tight:
319+
320+apple::
321+ red fruit
322+ +
323+ computer
324+orange::
325+ orange fruit
326+ +
327+ bank
328+
329+Multiple definitions, loose:
330+
331+apple::
332+ red fruit
333+ +
334+ computer
335+orange::
336+ orange fruit
337+ +
338+ bank
339+
340+Blank line after term, indented marker, alternate markers:
341+
342+apple::
343+ red fruit
344+ +
345+ computer
346+orange::
347+ orange fruit
348+ +
349+ 1. sublist
350+ 2. sublist
351+
352+HTML Blocks
353+-----------
354+
355+Simple block on one line:
356+
357+foo
358+And nested without indentation:
359+
360+foo
361+bar
362+Interpreted markdown in a table:
363+
364+This is _emphasized_
365+And this is *strong*
366+Here’s a simple block:
367+
368+foo
369+This should be a code block, though:
370+
371+-------
372+<div>
373+ foo
374+</div>
375+-------
376+
377+As should this:
378+
379+--------------
380+<div>foo</div>
381+--------------
382+
383+Now, nested:
384+
385+foo
386+This should just be an HTML comment:
387+
388+Multiline:
389+
390+Code block:
391+
392+----------------
393+<!-- Comment -->
394+----------------
395+
396+Just plain comment, with trailing spaces on the line:
397+
398+Code:
399+
400+------
401+<hr />
402+------
403+
404+Hr’s:
405+
406+'''''
407+
408+Inline Markup
409+-------------
410+
411+This is _emphasized_, and so _is this_.
412+
413+This is *strong*, and so *is this*.
414+
415+An _link:/url[emphasized link]_.
416+
417+*_This is strong and em._*
418+
419+So is *_this_* word.
420+
421+*_This is strong and em._*
422+
423+So is *_this_* word.
424+
425+This is code: `>`, `$`, `\`, `\$`, `<html>`.
426+
427+[line-through]*This is _strikeout_.*
428+
429+Superscripts: a^bc^d a^_hello_^ a^hello there^.
430+
431+Subscripts: H~2~O, H~23~O, H~many of them~O.
432+
433+These should not be superscripts or subscripts, because of the unescaped
434+spaces: a\^b c\^d, a\~b c\~d.
435+
436+'''''
437+
438+Smart quotes, ellipses, dashes
439+------------------------------
440+
441+``Hello,'' said the spider. ```Shelob' is my name.''
442+
443+`A', `B', and `C' are letters.
444+
445+`Oak,' `elm,' and `beech' are names of trees. So is `pine.'
446+
447+`He said, ``I want to go.''' Were you alive in the 70’s?
448+
449+Here is some quoted ``code`' and a ``http://example.com/?foo=1&bar=2[quoted
450+link]''.
451+
452+Some dashes: one—two — three—four — five.
453+
454+Dashes between numbers: 5–7, 255–66, 1987–1999.
455+
456+Ellipses…and…and….
457+
458+'''''
459+
460+LaTeX
461+-----
462+
463+*
464+* latexmath:[$2+2=4$]
465+* latexmath:[$x \in y$]
466+* latexmath:[$\alpha \wedge \omega$]
467+* latexmath:[$223$]
468+* latexmath:[$p$]-Tree
469+* Here’s some display math:
470+latexmath:[$$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$$]
471+* Here’s one that has a line break in it:
472+latexmath:[$\alpha + \omega \times x^2$].
473+
474+These shouldn’t be math:
475+
476+* To get the famous equation, write `$e = mc^2$`.
477+* $22,000 is a _lot_ of money. So is $34,000. (It worked if ``lot'' is
478+emphasized.)
479+* Shoes ($20) and socks ($5).
480+* Escaped `$`: $73 _this should be emphasized_ 23$.
481+
482+Here’s a LaTeX table:
483+
484+'''''
485+
486+Special Characters
487+------------------
488+
489+Here is some unicode:
490+
491+* I hat: Î
492+* o umlaut: ö
493+* section: §
494+* set membership: ∈
495+* copyright: ©
496+
497+AT&T has an ampersand in their name.
498+
499+AT&T is another way to write it.
500+
501+This & that.
502+
503+4 < 5.
504+
505+6 \> 5.
506+
507+Backslash: \\
508+
509+Backtick: \`
510+
511+Asterisk: \*
512+
513+Underscore: \_
514+
515+Left brace: \{
516+
517+Right brace: }
518+
519+Left bracket: [
520+
521+Right bracket: ]
522+
523+Left paren: (
524+
525+Right paren: )
526+
527+Greater-than: \>
528+
529+Hash: \#
530+
531+Period: .
532+
533+Bang: !
534+
535+Plus: \+
536+
537+Minus: -
538+
539+'''''
540+
541+Links
542+-----
543+
544+Explicit
545+~~~~~~~~
546+
547+Just a link:/url/[URL].
548+
549+link:/url/[URL and title].
550+
551+link:/url/[URL and title].
552+
553+link:/url/[URL and title].
554+
555+link:/url/[URL and title]
556+
557+link:/url/[URL and title]
558+
559+link:/url/with_underscore[with\_underscore]
560+
561+mailto:nobody@nowhere.net[Email link]
562+
563+link:[Empty].
564+
565+Reference
566+~~~~~~~~~
567+
568+Foo link:/url/[bar].
569+
570+Foo link:/url/[bar].
571+
572+Foo link:/url/[bar].
573+
574+With link:/url/[embedded [brackets]].
575+
576+link:/url/[b] by itself should be a link.
577+
578+Indented link:/url[once].
579+
580+Indented link:/url[twice].
581+
582+Indented link:/url[thrice].
583+
584+This should [not][] be a link.
585+
586+-----------
587+[not]: /url
588+-----------
589+
590+Foo link:/url/[bar].
591+
592+Foo link:/url/[biz].
593+
594+With ampersands
595+~~~~~~~~~~~~~~~
596+
597+Here’s a http://example.com/?foo=1&bar=2[link with an ampersand in the URL].
598+
599+Here’s a link with an amersand in the link text: http://att.com/[AT&T].
600+
601+Here’s an link:/script?foo=1&bar=2[inline link].
602+
603+Here’s an link:/script?foo=1&bar=2[inline link in pointy braces].
604+
605+Autolinks
606+~~~~~~~~~
607+
608+With an ampersand: http://example.com/?foo=1&bar=2
609+
610+* In a list?
611+* http://example.com/
612+* It should.
613+
614+An e-mail address: nobody@nowhere.net
615+
616+________________________________
617+Blockquoted: http://example.com/
618+________________________________
619+
620+Auto-links should not occur here: `<http://example.com/>`
621+
622+------------------------------
623+or here: <http://example.com/>
624+------------------------------
625+
626+'''''
627+
628+Images
629+------
630+
631+From ``Voyage dans la Lune'' by Georges Melies (1902):
632+
633+image:lalune.jpg[lalune,title="Voyage dans la Lune"]
634+
635+Here is a movie image:movie.jpg[movie] icon.
636+
637+'''''
638+
639+Footnotes
640+---------
641+
642+Here is a footnote reference,footnote:[Here is the footnote. It can go
643+anywhere after the footnote reference. It need not be placed at the end of the
644+document.] and another.[multiblock footnote omitted] This should _not_ be a
645+footnote reference, because it contains a space.[\^my note] Here is an inline
646+note.footnote:[This is _easier_ to type. Inline notes may contain
647+http://google.com[links] and `]` verbatim characters, as well as [bracketed
648+text].]
649+
650+___________________________________________
651+Notes can go in quotes.footnote:[In quote.]
652+___________________________________________
653+
654+1. And in list items.footnote:[In list.]
655+
656+This paragraph should not be part of the note, as it is not indented.