git.iko.soy/typeable/pandoc
on master help sign in
Merge pull request #4177 from stencila/jats-xml-reader

Add Basic JATS reader based on DocBook reader

commitaf048816555046d83f2cc4813d61e0430321476e authorJohn MacFarlane <jgm@berkeley.edu> dateThu 21 Dec 2017, 23:16 (9 years ago) parent32f9dbbd853571
10 files changed+2761−20
pandoc.cabal+3 src/Text/Pandoc/Readers.hs+4−1 src/Text/Pandoc/Readers/JATS.hs+404 src/Text/Pandoc/Writers/JATS.hs+29−18 test/Tests/Old.hs+2 test/Tests/Readers/JATS.hs+116 test/Tests/Writers/JATS.hs+6−1 test/jats-reader.native+422 test/jats-reader.xml+1773 test/test-pandoc.hs+2
pandoc.cabal+3
@@ -212,6 +212,7 @@ extra-source-files:
212212 test/creole-reader.txt
213213 test/creole-reader.native
214214 test/rst-reader.rst
215+ test/jats-reader.xml
215216 test/s5-basic.html
216217 test/s5-fancy.html
217218 test/s5-fragment.html
@@ -434,6 +435,7 @@ library
434435 Text.Pandoc.Readers.RST,
435436 Text.Pandoc.Readers.Org,
436437 Text.Pandoc.Readers.DocBook,
438+ Text.Pandoc.Readers.JATS,
437439 Text.Pandoc.Readers.OPML,
438440 Text.Pandoc.Readers.Textile,
439441 Text.Pandoc.Readers.Native,
@@ -623,6 +625,7 @@ test-suite test-pandoc
623625 Tests.Shared
624626 Tests.Readers.LaTeX
625627 Tests.Readers.HTML
628+ Tests.Readers.JATS
626629 Tests.Readers.Markdown
627630 Tests.Readers.Org
628631 Tests.Readers.RST
src/Text/Pandoc/Readers.hs+4−1
@@ -52,6 +52,7 @@ module Text.Pandoc.Readers
5252 , readOrg
5353 , readLaTeX
5454 , readHtml
55+ , readJATS
5556 , readTextile
5657 , readDocBook
5758 , readOPML
@@ -84,7 +85,8 @@ import Text.Pandoc.Readers.DocBook
8485import Text.Pandoc.Readers.Docx
8586import Text.Pandoc.Readers.EPUB
8687import Text.Pandoc.Readers.Haddock
87−import Text.Pandoc.Readers.HTML
88+import Text.Pandoc.Readers.HTML (readHtml)
89+import Text.Pandoc.Readers.JATS (readJATS)
8890import Text.Pandoc.Readers.LaTeX
8991import Text.Pandoc.Readers.Markdown
9092import Text.Pandoc.Readers.MediaWiki
@@ -129,6 +131,7 @@ readers = [ ("native" , TextReader readNative)
129131 ,("org" , TextReader readOrg)
130132 ,("textile" , TextReader readTextile) -- TODO : textile+lhs
131133 ,("html" , TextReader readHtml)
134+ ,("jats" , TextReader readJATS)
132135 ,("latex" , TextReader readLaTeX)
133136 ,("haddock" , TextReader readHaddock)
134137 ,("twiki" , TextReader readTWiki)
src/Text/Pandoc/Readers/JATS.hsnew file+404
@@ -0,0 +1,404 @@
1+{-# LANGUAGE ExplicitForAll, TupleSections #-}
2+module Text.Pandoc.Readers.JATS ( readJATS ) where
3+import Control.Monad.State.Strict
4+import Data.Char (isDigit, isSpace, toUpper)
5+import Data.Default
6+import Data.Generics
7+import Data.List (intersperse)
8+import Data.Maybe (maybeToList, fromMaybe)
9+import Data.Text (Text)
10+import qualified Data.Text as T
11+import Text.HTML.TagSoup.Entity (lookupEntity)
12+import Text.Pandoc.Builder
13+import Text.Pandoc.Class (PandocMonad)
14+import Text.Pandoc.Options
15+import Text.Pandoc.Shared (underlineSpan, crFilter, safeRead)
16+import Text.TeXMath (readMathML, writeTeX)
17+import Text.XML.Light
18+import qualified Data.Set as S (fromList, member)
19+import Data.Set ((\\))
20+
21+type JATS m = StateT JATSState m
22+
23+data JATSState = JATSState{ jatsSectionLevel :: Int
24+ , jatsQuoteType :: QuoteType
25+ , jatsMeta :: Meta
26+ , jatsAcceptsMeta :: Bool
27+ , jatsBook :: Bool
28+ , jatsFigureTitle :: Inlines
29+ , jatsContent :: [Content]
30+ } deriving Show
31+
32+instance Default JATSState where
33+ def = JATSState{ jatsSectionLevel = 0
34+ , jatsQuoteType = DoubleQuote
35+ , jatsMeta = mempty
36+ , jatsAcceptsMeta = False
37+ , jatsBook = False
38+ , jatsFigureTitle = mempty
39+ , jatsContent = [] }
40+
41+
42+readJATS :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
43+readJATS _ inp = do
44+ let tree = normalizeTree . parseXML
45+ $ T.unpack $ crFilter inp
46+ (bs, st') <- flip runStateT (def{ jatsContent = tree }) $ mapM parseBlock tree
47+ return $ Pandoc (jatsMeta st') (toList . mconcat $ bs)
48+
49+-- normalize input, consolidating adjacent Text and CRef elements
50+normalizeTree :: [Content] -> [Content]
51+normalizeTree = everywhere (mkT go)
52+ where go :: [Content] -> [Content]
53+ go (Text (CData CDataRaw _ _):xs) = xs
54+ go (Text (CData CDataText s1 z):Text (CData CDataText s2 _):xs) =
55+ Text (CData CDataText (s1 ++ s2) z):xs
56+ go (Text (CData CDataText s1 z):CRef r:xs) =
57+ Text (CData CDataText (s1 ++ convertEntity r) z):xs
58+ go (CRef r:Text (CData CDataText s1 z):xs) =
59+ Text (CData CDataText (convertEntity r ++ s1) z):xs
60+ go (CRef r1:CRef r2:xs) =
61+ Text (CData CDataText (convertEntity r1 ++ convertEntity r2) Nothing):xs
62+ go xs = xs
63+
64+convertEntity :: String -> String
65+convertEntity e = Data.Maybe.fromMaybe (map toUpper e) (lookupEntity e)
66+
67+-- convenience function to get an attribute value, defaulting to ""
68+attrValue :: String -> Element -> String
69+attrValue attr =
70+ fromMaybe "" . maybeAttrValue attr
71+
72+maybeAttrValue :: String -> Element -> Maybe String
73+maybeAttrValue attr elt =
74+ lookupAttrBy (\x -> qName x == attr) (elAttribs elt)
75+
76+-- convenience function
77+named :: String -> Element -> Bool
78+named s e = qName (elName e) == s
79+
80+--
81+
82+acceptingMetadata :: PandocMonad m => JATS m a -> JATS m a
83+acceptingMetadata p = do
84+ modify (\s -> s { jatsAcceptsMeta = True } )
85+ res <- p
86+ modify (\s -> s { jatsAcceptsMeta = False })
87+ return res
88+
89+checkInMeta :: (PandocMonad m, Monoid a) => JATS m () -> JATS m a
90+checkInMeta p = do
91+ accepts <- jatsAcceptsMeta <$> get
92+ when accepts p
93+ return mempty
94+
95+addMeta :: PandocMonad m => ToMetaValue a => String -> a -> JATS m ()
96+addMeta field val = modify (setMeta field val)
97+
98+instance HasMeta JATSState where
99+ setMeta field v s = s {jatsMeta = setMeta field v (jatsMeta s)}
100+ deleteMeta field s = s {jatsMeta = deleteMeta field (jatsMeta s)}
101+
102+isBlockElement :: Content -> Bool
103+isBlockElement (Elem e) = qName (elName e) `S.member` blocktags
104+ where blocktags = S.fromList (paragraphLevel ++ lists ++ mathML ++ other) \\ S.fromList inlinetags
105+ paragraphLevel = ["address", "array", "boxed-text", "chem-struct-wrap",
106+ "code", "fig", "fig-group", "graphic", "media", "preformat",
107+ "supplementary-material", "table-wrap", "table-wrap-group",
108+ "alternatives", "disp-formula", "disp-formula-group"]
109+ lists = ["def-list", "list"]
110+ mathML = ["tex-math", "mml:math"]
111+ other = ["p", "related-article", "related-object", "ack", "disp-quote",
112+ "speech", "statement", "verse-group", "x"]
113+ inlinetags = ["email", "ext-link", "uri", "inline-supplementary-material",
114+ "related-article", "related-object", "hr", "bold", "fixed-case",
115+ "italic", "monospace", "overline", "overline-start", "overline-end",
116+ "roman", "sans-serif", "sc", "strike", "underline", "underline-start",
117+ "underline-end", "ruby", "alternatives", "inline-graphic", "private-char",
118+ "chem-struct", "inline-formula", "tex-math", "mml:math", "abbrev",
119+ "milestone-end", "milestone-start", "named-content", "styled-content",
120+ "fn", "target", "xref", "sub", "sup", "x", "address", "array",
121+ "boxed-text", "chem-struct-wrap", "code", "fig", "fig-group", "graphic",
122+ "media", "preformat", "supplementary-material", "table-wrap",
123+ "table-wrap-group", "disp-formula", "disp-formula-group",
124+ "citation-alternatives", "element-citation", "mixed-citation",
125+ "nlm-citation", "award-id", "funding-source", "open-access",
126+ "def-list", "list", "ack", "disp-quote", "speech", "statement",
127+ "verse-group"]
128+isBlockElement _ = False
129+
130+-- Trim leading and trailing newline characters
131+trimNl :: String -> String
132+trimNl = reverse . go . reverse . go
133+ where go ('\n':xs) = xs
134+ go xs = xs
135+
136+-- function that is used by both graphic (in parseBlock)
137+-- and inline-graphic (in parseInline)
138+getGraphic :: PandocMonad m => Element -> JATS m Inlines
139+getGraphic e = do
140+ let atVal a = attrValue a e
141+ attr = (atVal "id", words $ atVal "role", [])
142+ imageUrl = atVal "href"
143+ captionOrLabel = case filterChild (\x -> named "caption" x
144+ || named "label" x) e of
145+ Nothing -> return mempty
146+ Just z -> mconcat <$>
147+ mapM parseInline (elContent z)
148+ figTitle <- gets jatsFigureTitle
149+ let (caption, title) = if isNull figTitle
150+ then (captionOrLabel, atVal "title")
151+ else (return figTitle, "fig:")
152+ fmap (imageWith attr imageUrl title) caption
153+
154+getBlocks :: PandocMonad m => Element -> JATS m Blocks
155+getBlocks e = mconcat <$>
156+ mapM parseBlock (elContent e)
157+
158+
159+parseBlock :: PandocMonad m => Content -> JATS m Blocks
160+parseBlock (Text (CData CDataRaw _ _)) = return mempty -- DOCTYPE
161+parseBlock (Text (CData _ s _)) = if all isSpace s
162+ then return mempty
163+ else return $ plain $ trimInlines $ text s
164+parseBlock (CRef x) = return $ plain $ str $ map toUpper x
165+parseBlock (Elem e) =
166+ case qName (elName e) of
167+ "p" -> parseMixed para (elContent e)
168+ "code" -> codeBlockWithLang
169+ "preformat" -> codeBlockWithLang
170+ "disp-quote" -> parseBlockquote
171+ "list" -> case attrValue "list-type" e of
172+ "bullet" -> bulletList <$> listitems
173+ listType -> do
174+ let start = fromMaybe 1 $
175+ (strContent <$> (filterElement (named "list-item") e
176+ >>= filterElement (named "lable")))
177+ >>= safeRead
178+ orderedListWith (start, parseListStyleType listType, DefaultDelim)
179+ <$> listitems
180+ "def-list" -> definitionList <$> deflistitems
181+ "sec" -> gets jatsSectionLevel >>= sect . (+1)
182+ "title" -> return mempty
183+ "title-group" -> checkInMeta getTitle
184+ "graphic" -> para <$> getGraphic e
185+ "journal-meta" -> metaBlock
186+ "article-meta" -> metaBlock
187+ "custom-meta" -> metaBlock
188+ "table" -> parseTable
189+ "fig" -> divWith (attrValue "id" e, ["fig"], []) <$> getBlocks e
190+ "table-wrap" -> divWith (attrValue "id" e, ["table-wrap"], []) <$> getBlocks e
191+ "caption" -> divWith (attrValue "id" e, ["caption"], []) <$> sect 6
192+ "ref-list" -> divWith ("refs", [], []) <$> getBlocks e
193+ "ref" -> divWith ("ref-" <> attrValue "id" e, [], []) <$> getBlocks e
194+ "?xml" -> return mempty
195+ _ -> getBlocks e
196+ where parseMixed container conts = do
197+ let (ils,rest) = break isBlockElement conts
198+ ils' <- (trimInlines . mconcat) <$> mapM parseInline ils
199+ let p = if ils' == mempty then mempty else container ils'
200+ case rest of
201+ [] -> return p
202+ (r:rs) -> do
203+ b <- parseBlock r
204+ x <- parseMixed container rs
205+ return $ p <> b <> x
206+ codeBlockWithLang = do
207+ let classes' = case attrValue "language" e of
208+ "" -> []
209+ x -> [x]
210+ return $ codeBlockWith (attrValue "id" e, classes', [])
211+ $ trimNl $ strContentRecursive e
212+ parseBlockquote = do
213+ attrib <- case filterChild (named "attribution") e of
214+ Nothing -> return mempty
215+ Just z -> (para . (str "— " <>) . mconcat)
216+ <$>
217+ mapM parseInline (elContent z)
218+ contents <- getBlocks e
219+ return $ blockQuote (contents <> attrib)
220+ parseListStyleType "roman-lower" = LowerRoman
221+ parseListStyleType "roman-upper" = UpperRoman
222+ parseListStyleType "alpha-lower" = LowerAlpha
223+ parseListStyleType "alpha-upper" = UpperAlpha
224+ parseListStyleType _ = DefaultStyle
225+ listitems = mapM getBlocks $ filterChildren (named "list-item") e
226+ deflistitems = mapM parseVarListEntry $ filterChildren
227+ (named "def-item") e
228+ parseVarListEntry e' = do
229+ let terms = filterChildren (named "term") e'
230+ let items = filterChildren (named "def") e'
231+ terms' <- mapM getInlines terms
232+ items' <- mapM getBlocks items
233+ return (mconcat $ intersperse (str "; ") terms', items')
234+ getTitle = do
235+ tit <- case filterChild (named "article-title") e of
236+ Just s -> getInlines s
237+ Nothing -> return mempty
238+ subtit <- case filterChild (named "subtitle") e of
239+ Just s -> (text ": " <>) <$>
240+ getInlines s
241+ Nothing -> return mempty
242+ addMeta "title" (tit <> subtit)
243+
244+ parseTable = do
245+ let isCaption x = named "title" x || named "caption" x
246+ caption <- case filterChild isCaption e of
247+ Just t -> getInlines t
248+ Nothing -> return mempty
249+ let e' = fromMaybe e $ filterChild (named "tgroup") e
250+ let isColspec x = named "colspec" x || named "col" x
251+ let colspecs = case filterChild (named "colgroup") e' of
252+ Just c -> filterChildren isColspec c
253+ _ -> filterChildren isColspec e'
254+ let isRow x = named "row" x || named "tr" x
255+ headrows <- case filterChild (named "thead") e' of
256+ Just h -> case filterChild isRow h of
257+ Just x -> parseRow x
258+ Nothing -> return []
259+ Nothing -> return []
260+ bodyrows <- case filterChild (named "tbody") e' of
261+ Just b -> mapM parseRow
262+ $ filterChildren isRow b
263+ Nothing -> mapM parseRow
264+ $ filterChildren isRow e'
265+ let toAlignment c = case findAttr (unqual "align") c of
266+ Just "left" -> AlignLeft
267+ Just "right" -> AlignRight
268+ Just "center" -> AlignCenter
269+ _ -> AlignDefault
270+ let toWidth c = case findAttr (unqual "colwidth") c of
271+ Just w -> fromMaybe 0
272+ $ safeRead $ '0': filter (\x ->
273+ isDigit x || x == '.') w
274+ Nothing -> 0 :: Double
275+ let numrows = case bodyrows of
276+ [] -> 0
277+ xs -> maximum $ map length xs
278+ let aligns = case colspecs of
279+ [] -> replicate numrows AlignDefault
280+ cs -> map toAlignment cs
281+ let widths = case colspecs of
282+ [] -> replicate numrows 0
283+ cs -> let ws = map toWidth cs
284+ tot = sum ws
285+ in if all (> 0) ws
286+ then map (/ tot) ws
287+ else replicate numrows 0
288+ let headrows' = if null headrows
289+ then replicate numrows mempty
290+ else headrows
291+ return $ table caption (zip aligns widths)
292+ headrows' bodyrows
293+ isEntry x = named "entry" x || named "td" x || named "th" x
294+ parseRow = mapM (parseMixed plain . elContent) . filterChildren isEntry
295+ sect n = do isbook <- gets jatsBook
296+ let n' = if isbook || n == 0 then n + 1 else n
297+ headerText <- case filterChild (named "title") e `mplus`
298+ (filterChild (named "info") e >>=
299+ filterChild (named "title")) of
300+ Just t -> getInlines t
301+ Nothing -> return mempty
302+ oldN <- gets jatsSectionLevel
303+ modify $ \st -> st{ jatsSectionLevel = n }
304+ b <- getBlocks e
305+ let ident = attrValue "id" e
306+ modify $ \st -> st{ jatsSectionLevel = oldN }
307+ return $ headerWith (ident,[],[]) n' headerText <> b
308+-- lineItems = mapM getInlines $ filterChildren (named "line") e
309+ metaBlock = acceptingMetadata (getBlocks e) >> return mempty
310+
311+getInlines :: PandocMonad m => Element -> JATS m Inlines
312+getInlines e' = (trimInlines . mconcat) <$>
313+ mapM parseInline (elContent e')
314+
315+strContentRecursive :: Element -> String
316+strContentRecursive = strContent .
317+ (\e' -> e'{ elContent = map elementToStr $ elContent e' })
318+
319+elementToStr :: Content -> Content
320+elementToStr (Elem e') = Text $ CData CDataText (strContentRecursive e') Nothing
321+elementToStr x = x
322+
323+parseInline :: PandocMonad m => Content -> JATS m Inlines
324+parseInline (Text (CData _ s _)) = return $ text s
325+parseInline (CRef ref) =
326+ return $ maybe (text $ map toUpper ref) text $ lookupEntity ref
327+parseInline (Elem e) =
328+ case qName (elName e) of
329+ "italic" -> emph <$> innerInlines
330+ "bold" -> strong <$> innerInlines
331+ "strike" -> strikeout <$> innerInlines
332+ "sub" -> subscript <$> innerInlines
333+ "sup" -> superscript <$> innerInlines
334+ "underline" -> underlineSpan <$> innerInlines
335+ "break" -> return linebreak
336+ "sc" -> smallcaps <$> innerInlines
337+
338+ "code" -> codeWithLang
339+ "monospace" -> codeWithLang
340+
341+ "inline-graphic" -> getGraphic e
342+ "disp-quote" -> do
343+ qt <- gets jatsQuoteType
344+ let qt' = if qt == SingleQuote then DoubleQuote else SingleQuote
345+ modify $ \st -> st{ jatsQuoteType = qt' }
346+ contents <- innerInlines
347+ modify $ \st -> st{ jatsQuoteType = qt }
348+ return $ if qt == SingleQuote
349+ then singleQuoted contents
350+ else doubleQuoted contents
351+
352+ "xref" -> do
353+ ils <- innerInlines
354+ let rid = attrValue "rid" e
355+ let refType = ("ref-type",) <$> maybeAttrValue "ref-type" e
356+ let attr = (attrValue "id" e, [], maybeToList refType)
357+ return $ linkWith attr ('#' : rid) "" ils
358+ "ext-link" -> do
359+ ils <- innerInlines
360+ let title = fromMaybe "" $ findAttr (QName "title" (Just "http://www.w3.org/1999/xlink") Nothing) e
361+ let href = case findAttr (QName "href" (Just "http://www.w3.org/1999/xlink") Nothing) e of
362+ Just h -> h
363+ _ -> '#' : attrValue "rid" e
364+ let ils' = if ils == mempty then str href else ils
365+ let attr = (attrValue "id" e, [], [])
366+ return $ linkWith attr href title ils'
367+
368+ "disp-formula" -> formula displayMath
369+ "inline-formula" -> formula math
370+ "math" | qPrefix (elName e) == Just "mml" -> return . math $ mathML e
371+ "tex-math" -> return . math $ strContent e
372+
373+ "email" -> return $ link ("mailto:" ++ strContent e) ""
374+ $ str $ strContent e
375+ "uri" -> return $ link (strContent e) "" $ str $ strContent e
376+ "fn" -> (note . mconcat) <$>
377+ mapM parseBlock (elContent e)
378+ -- Note: this isn't a real docbook tag; it's what we convert
379+ -- <?asciidor-br?> to in handleInstructions, above. A kludge to
380+ -- work around xml-light's inability to parse an instruction.
381+ _ -> innerInlines
382+ where innerInlines = (trimInlines . mconcat) <$>
383+ mapM parseInline (elContent e)
384+ mathML x =
385+ case readMathML . showElement $ everywhere (mkT removePrefix) x of
386+ Left _ -> mempty
387+ Right m -> writeTeX m
388+ formula constructor = do
389+ let whereToLook = fromMaybe e $ filterElement (named "alternatives") e
390+ texMaths = map strContent $
391+ filterChildren (named "tex-math") whereToLook
392+ mathMLs = map mathML $
393+ filterChildren isMathML whereToLook
394+ return . mconcat . take 1 . map constructor $ texMaths ++ mathMLs
395+
396+ isMathML x = qName (elName x) == "math" &&
397+ qPrefix (elName x) == Just "mml"
398+ removePrefix elname = elname { qPrefix = Nothing }
399+ codeWithLang = do
400+ let classes' = case attrValue "language" e of
401+ "" -> []
402+ l -> [l]
403+ return $ codeWith (attrValue "id" e,classes',[]) $ strContentRecursive e
404+
src/Text/Pandoc/Writers/JATS.hs+29−18
@@ -170,6 +170,28 @@ imageMimeType src kvs =
170170 ((drop 1 . dropWhile (/='/')) <$> mbMT)
171171 in (maintype, subtype)
172172
173+languageFor :: [String] -> String
174+languageFor classes =
175+ case langs of
176+ (l:_) -> escapeStringForXML l
177+ [] -> ""
178+ where isLang l = map toLower l `elem` map (map toLower) languages
179+ langsFrom s = if isLang s
180+ then [s]
181+ else languagesByExtension . map toLower $ s
182+ langs = concatMap langsFrom classes
183+
184+codeAttr :: Attr -> (String, [(String, String)])
185+codeAttr (ident,classes,kvs) = (lang, attr)
186+ where
187+ attr = [("id",ident) | not (null ident)] ++
188+ [("language",lang) | not (null lang)] ++
189+ [(k,v) | (k,v) <- kvs, k `elem` ["code-type",
190+ "code-version", "executable",
191+ "language-version", "orientation",
192+ "platforms", "position", "specific-use"]]
193+ lang = languageFor classes
194+
173195-- | Convert a Pandoc block element to JATS.
174196blockToJATS :: PandocMonad m => WriterOptions -> Block -> JATS m Doc
175197blockToJATS _ Null = return empty
@@ -233,23 +255,10 @@ blockToJATS opts (LineBlock lns) =
233255 blockToJATS opts $ linesToPara lns
234256blockToJATS opts (BlockQuote blocks) =
235257 inTagsIndented "disp-quote" <$> blocksToJATS opts blocks
236−blockToJATS _ (CodeBlock (ident,classes,kvs) str) = return $
258+blockToJATS _ (CodeBlock a str) = return $
237259 inTags False tag attr (flush (text (escapeStringForXML str)))
238− where attr = [("id",ident) | not (null ident)] ++
239− [("language",lang) | not (null lang)] ++
240− [(k,v) | (k,v) <- kvs, k `elem` ["code-type",
241− "code-version", "executable",
242− "language-version", "orientation",
243− "platforms", "position", "specific-use"]]
244− tag = if null lang then "preformat" else "code"
245− lang = case langs of
246− (l:_) -> escapeStringForXML l
247− [] -> ""
248− isLang l = map toLower l `elem` map (map toLower) languages
249− langsFrom s = if isLang s
250− then [s]
251− else languagesByExtension . map toLower $ s
252− langs = concatMap langsFrom classes
260+ where (lang, attr) = codeAttr a
261+ tag = if null lang then "preformat" else "code"
253262blockToJATS _ (BulletList []) = return empty
254263blockToJATS opts (BulletList lst) =
255264 inTags True "list" [("list-type", "bullet")] <$>
@@ -349,8 +358,10 @@ inlineToJATS opts (Quoted SingleQuote lst) = do
349358inlineToJATS opts (Quoted DoubleQuote lst) = do
350359 contents <- inlinesToJATS opts lst
351360 return $ char '“' <> contents <> char '”'
352−inlineToJATS _ (Code _ str) =
353− return $ inTagsSimple "monospace" $ text (escapeStringForXML str)
361+inlineToJATS _ (Code a str) =
362+ return $ inTags False tag attr $ text (escapeStringForXML str)
363+ where (lang, attr) = codeAttr a
364+ tag = if null lang then "monospace" else "code"
354365inlineToJATS _ il@(RawInline f x)
355366 | f == "jats" = return $ text x
356367 | otherwise = do
test/Tests/Old.hs+2
@@ -79,6 +79,8 @@ tests = [ testGroup "markdown"
7979 ]
8080 , testGroup "jats"
8181 [ testGroup "writer" $ writerTests "jats"
82+ , test "reader" ["-r", "jats", "-w", "native", "-s"]
83+ "jats-reader.xml" "jats-reader.native"
8284 ]
8385 , testGroup "native"
8486 [ testGroup "writer" $ writerTests "native"
test/Tests/Readers/JATS.hsnew file+116
@@ -0,0 +1,116 @@
1+{-# LANGUAGE OverloadedStrings #-}
2+module Tests.Readers.JATS (tests) where
3+
4+import Data.Text (Text)
5+import Test.Tasty
6+import Tests.Helpers
7+import Text.Pandoc
8+import Text.Pandoc.Arbitrary ()
9+import Text.Pandoc.Builder
10+
11+jats :: Text -> Pandoc
12+jats = purely $ readJATS def
13+
14+tests :: [TestTree]
15+tests = [ testGroup "inline code"
16+ [ test jats "basic" $ "<p>\n <monospace>@&amp;</monospace>\n</p>" =?> para (code "@&")
17+ , test jats "lang" $ "<p>\n <code language=\"c\">@&amp;</code>\n</p>" =?> para (codeWith ("", ["c"], []) "@&")
18+ ]
19+ , testGroup "block code"
20+ [ test jats "basic" $ "<preformat>@&amp;</preformat>" =?> codeBlock "@&"
21+ , test jats "lang" $ "<code language=\"c\">@&amp;</code>" =?> codeBlockWith ("", ["c"], []) "@&"
22+ ]
23+ , testGroup "images"
24+ [ test jats "basic" $ "<graphic mimetype=\"image\" mime-subtype=\"\" xlink:href=\"/url\" xlink:title=\"title\" />"
25+ =?> para (image "/url" "title" mempty)
26+ ]
27+ , test jats "bullet list" $
28+ "<list list-type=\"bullet\">\n\
29+ \ <list-item>\n\
30+ \ <p>\n\
31+ \ first\n\
32+ \ </p>\n\
33+ \ </list-item>\n\
34+ \ <list-item>\n\
35+ \ <p>\n\
36+ \ second\n\
37+ \ </p>\n\
38+ \ </list-item>\n\
39+ \ <list-item>\n\
40+ \ <p>\n\
41+ \ third\n\
42+ \ </p>\n\
43+ \ </list-item>\n\
44+ \</list>"
45+ =?> bulletList [ para $ text "first"
46+ , para $ text "second"
47+ , para $ text "third"
48+ ]
49+ , testGroup "definition lists"
50+ [ test jats "with internal link" $
51+ "<def-list>\n\
52+ \ <def-item>\n\
53+ \ <term>\n\
54+ \ <xref alt=\"testing\" rid=\"go\">testing</xref>\n\
55+ \ </term>\n\
56+ \ <def>\n\
57+ \ <p>\n\
58+ \ hi there\n\
59+ \ </p>\n\
60+ \ </def>\n\
61+ \ </def-item>\n\
62+ \</def-list>"
63+ =?> definitionList [(link "#go" "" (str "testing"),
64+ [para (text "hi there")])]
65+ ]
66+ , testGroup "math"
67+ [ test jats "escape |" $
68+ "<p>\n\
69+ \ <inline-formula><alternatives>\n\
70+ \ <tex-math><![CDATA[\\sigma|_{\\{x\\}}]]></tex-math>\n\
71+ \ <mml:math display=\"inline\" xmlns:mml=\"http://www.w3.org/1998/Math/MathML\"><mml:mrow><mml:mi>σ</mml:mi><mml:msub><mml:mo stretchy=\"false\" form=\"prefix\">|</mml:mo><mml:mrow><mml:mo stretchy=\"false\" form=\"prefix\">{</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy=\"false\" form=\"postfix\">}</mml:mo></mml:mrow></mml:msub></mml:mrow></mml:math></alternatives></inline-formula>\n\
72+ \</p>"
73+ =?> para (math "\\sigma|_{\\{x\\}}")
74+ , test jats "tex-math only" $
75+ "<p>\n\
76+ \ <inline-formula><alternatives>\n\
77+ \ <tex-math><![CDATA[\\sigma|_{\\{x\\}}]]></tex-math>\n\
78+ \</p>"
79+ =?> para (math "\\sigma|_{\\{x\\}}")
80+ , test jats "math ml only" $
81+ "<p>\n\
82+ \ <inline-formula><alternatives>\n\
83+ \ <mml:math display=\"inline\" xmlns:mml=\"http://www.w3.org/1998/Math/MathML\"><mml:mrow><mml:mi>σ</mml:mi><mml:msub><mml:mo stretchy=\"false\" form=\"prefix\">|</mml:mo><mml:mrow><mml:mo stretchy=\"false\" form=\"prefix\">{</mml:mo><mml:mi>x</mml:mi><mml:mo stretchy=\"false\" form=\"postfix\">}</mml:mo></mml:mrow></mml:msub></mml:mrow></mml:math></alternatives></inline-formula>\n\
84+ \</p>"
85+ =?> para (math "\\sigma|_{\\{ x\\}}")
86+ ]
87+ , testGroup "headers"
88+-- TODO fix footnotes in headers
89+-- [ test jats "unnumbered header" $
90+-- "<sec>\n\
91+-- \ <title>Header 1<fn>\n\
92+-- \ <p>\n\
93+-- \ note\n\
94+-- \ </p>\n\
95+-- \ </fn></title>\n\
96+-- \</sec>"
97+-- =?> header 1
98+-- (text "Header 1" <> note (plain $ text "note"))
99+ [ test jats "unnumbered sub header" $
100+ "<sec id=\"foo\">\n\
101+ \ <title>Header</title>\n\
102+ \ <sec id=\"foo2\">\n\
103+ \ <title>Sub-Header</title>\n\
104+ \ </sec>\n\
105+ \</sec>"
106+ =?> headerWith ("foo", [], []) 1
107+ (text "Header")
108+ <> headerWith ("foo2", [], []) 2
109+ (text "Sub-Header")
110+ , test jats "containing image" $
111+ "<sec>\n\
112+ \ <title><inline-graphic mimetype=\"image\" mime-subtype=\"jpeg\" xlink:href=\"imgs/foo.jpg\" /></title>\n\
113+ \</sec>"
114+ =?> header 1 (image "imgs/foo.jpg" "" mempty)
115+ ]
116+ ]
test/Tests/Writers/JATS.hs+6−1
@@ -31,6 +31,11 @@ infix 4 =:
3131tests :: [TestTree]
3232tests = [ testGroup "inline code"
3333 [ "basic" =: code "@&" =?> "<p>\n <monospace>@&amp;</monospace>\n</p>"
34+ , "lang" =: codeWith ("", ["c"], []) "@&" =?> "<p>\n <code language=\"c\">@&amp;</code>\n</p>"
35+ ]
36+ , testGroup "block code"
37+ [ "basic" =: codeBlock "@&" =?> "<preformat>@&amp;</preformat>"
38+ , "lang" =: codeBlockWith ("", ["c"], []) "@&" =?> "<code language=\"c\">@&amp;</code>"
3439 ]
3540 , testGroup "images"
3641 [ "basic" =:
@@ -38,7 +43,7 @@ tests = [ testGroup "inline code"
3843 =?> "<graphic mimetype=\"image\" mime-subtype=\"\" xlink:href=\"/url\" xlink:title=\"title\" />"
3944 ]
4045 , testGroup "inlines"
41− [ "Emphasis" =: emph ("emphasized")
46+ [ "Emphasis" =: emph "emphasized"
4247 =?> "<p>\n <italic>emphasized</italic>\n</p>"
4348 ]
4449 , "bullet list" =: bulletList [ plain $ text "first"
test/jats-reader.nativenew file+422
@@ -0,0 +1,422 @@
1+Pandoc (Meta {unMeta = fromList [("title",MetaInlines [Str "Pandoc",Space,Str "Test",Space,Str "Suite"])]})
2+[Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "set",Space,Str "of",Space,Str "tests",Space,Str "for",Space,Str "pandoc.",Space,Str "Most",Space,Str "of",Space,Str "them",Space,Str "are",Space,Str "adapted",Space,Str "from",Space,Str "John",SoftBreak,Str "Gruber's",Space,Str "markdown",Space,Str "test",Space,Str "suite."]
3+,Header 1 ("headers",[],[]) [Str "Headers"]
4+,Header 2 ("level-2-with-an-embedded-link",[],[]) [Str "Level",Space,Str "2",Space,Str "with",Space,Str "an",SoftBreak,Link ("",[],[]) [Str "embedded",SoftBreak,Str "link"] ("/url","")]
5+,Header 3 ("level-3-with-emphasis",[],[]) [Str "Level",Space,Str "3",Space,Str "with",Space,Emph [Str "emphasis"]]
6+,Header 4 ("level-4",[],[]) [Str "Level",Space,Str "4"]
7+,Header 5 ("level-5",[],[]) [Str "Level",Space,Str "5"]
8+,Header 1 ("level-1",[],[]) [Str "Level",Space,Str "1"]
9+,Header 2 ("level-2-with-emphasis",[],[]) [Str "Level",Space,Str "2",Space,Str "with",Space,Emph [Str "emphasis"]]
10+,Header 3 ("level-3",[],[]) [Str "Level",Space,Str "3"]
11+,Para [Str "with",Space,Str "no",Space,Str "blank",Space,Str "line"]
12+,Header 2 ("level-2",[],[]) [Str "Level",Space,Str "2"]
13+,Para [Str "with",Space,Str "no",Space,Str "blank",Space,Str "line"]
14+,Header 1 ("paragraphs",[],[]) [Str "Paragraphs"]
15+,Para [Str "Here's",Space,Str "a",Space,Str "regular",Space,Str "paragraph."]
16+,Para [Str "In",Space,Str "Markdown",Space,Str "1.0.0",Space,Str "and",Space,Str "earlier.",Space,Str "Version",Space,Str "8.",Space,Str "This",Space,Str "line",Space,Str "turns",Space,Str "into",Space,Str "a",SoftBreak,Str "list",Space,Str "item.",Space,Str "Because",Space,Str "a",Space,Str "hard-wrapped",Space,Str "line",Space,Str "in",Space,Str "the",Space,Str "middle",Space,Str "of",Space,Str "a",Space,Str "paragraph",SoftBreak,Str "looked",Space,Str "like",Space,Str "a",Space,Str "list",Space,Str "item."]
17+,Para [Str "Here's",Space,Str "one",Space,Str "with",Space,Str "a",Space,Str "bullet.",Space,Str "*",Space,Str "criminey."]
18+,Para [Str "There",Space,Str "should",Space,Str "be",Space,Str "a",Space,Str "hard",Space,Str "line",Space,Str "break",LineBreak,Str "here."]
19+,Header 1 ("block-quotes",[],[]) [Str "Block",Space,Str "Quotes"]
20+,Para [Str "E-mail",Space,Str "style:"]
21+,BlockQuote
22+ [Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "block",Space,Str "quote.",Space,Str "It",Space,Str "is",Space,Str "pretty",Space,Str "short."]]
23+,BlockQuote
24+ [Para [Str "Code",Space,Str "in",Space,Str "a",Space,Str "block",Space,Str "quote:"]
25+ ,CodeBlock ("",[],[]) "sub status {\n print \"working\";\n}"
26+ ,Para [Str "A",Space,Str "list:"]
27+ ,OrderedList (1,DefaultStyle,DefaultDelim)
28+ [[Para [Str "item",Space,Str "one"]]
29+ ,[Para [Str "item",Space,Str "two"]]]
30+ ,Para [Str "Nested",Space,Str "block",Space,Str "quotes:"]
31+ ,BlockQuote
32+ [Para [Str "nested"]]
33+ ,BlockQuote
34+ [Para [Str "nested"]]]
35+,Para [Str "This",Space,Str "should",Space,Str "not",Space,Str "be",Space,Str "a",Space,Str "block",Space,Str "quote:",Space,Str "2",Space,Str ">",Space,Str "1."]
36+,Para [Str "Box-style:"]
37+,BlockQuote
38+ [Para [Str "Example:"]
39+ ,CodeBlock ("",[],[]) "sub status {\n print \"working\";\n}"]
40+,BlockQuote
41+ [OrderedList (1,DefaultStyle,DefaultDelim)
42+ [[Para [Str "do",Space,Str "laundry"]]
43+ ,[Para [Str "take",Space,Str "out",Space,Str "the",Space,Str "trash"]]]]
44+,Para [Str "Here's",Space,Str "a",Space,Str "nested",Space,Str "one:"]
45+,BlockQuote
46+ [Para [Str "Joe",Space,Str "said:"]
47+ ,BlockQuote
48+ [Para [Str "Don't",Space,Str "quote",Space,Str "me."]]]
49+,Para [Str "And",Space,Str "a",Space,Str "following",Space,Str "paragraph."]
50+,Header 1 ("code-blocks",[],[]) [Str "Code",Space,Str "Blocks"]
51+,Para [Str "Code:"]
52+,CodeBlock ("",[],[]) "---- (should be four hyphens)\n\nsub status {\n print \"working\";\n}\n\nthis code block is indented by one tab"
53+,Para [Str "And:"]
54+,CodeBlock ("",[],[]) " this code block is indented by two tabs\n\nThese should not be escaped: \\$ \\\\ \\> \\[ \\{"
55+,Header 1 ("lists",[],[]) [Str "Lists"]
56+,Header 2 ("unordered",[],[]) [Str "Unordered"]
57+,Para [Str "Asterisks",Space,Str "tight:"]
58+,BulletList
59+ [[Para [Str "asterisk",Space,Str "1"]]
60+ ,[Para [Str "asterisk",Space,Str "2"]]
61+ ,[Para [Str "asterisk",Space,Str "3"]]]
62+,Para [Str "Asterisks",Space,Str "loose:"]
63+,BulletList
64+ [[Para [Str "asterisk",Space,Str "1"]]
65+ ,[Para [Str "asterisk",Space,Str "2"]]
66+ ,[Para [Str "asterisk",Space,Str "3"]]]
67+,Para [Str "Pluses",Space,Str "tight:"]
68+,BulletList
69+ [[Para [Str "Plus",Space,Str "1"]]
70+ ,[Para [Str "Plus",Space,Str "2"]]
71+ ,[Para [Str "Plus",Space,Str "3"]]]
72+,Para [Str "Pluses",Space,Str "loose:"]
73+,BulletList
74+ [[Para [Str "Plus",Space,Str "1"]]
75+ ,[Para [Str "Plus",Space,Str "2"]]
76+ ,[Para [Str "Plus",Space,Str "3"]]]
77+,Para [Str "Minuses",Space,Str "tight:"]
78+,BulletList
79+ [[Para [Str "Minus",Space,Str "1"]]
80+ ,[Para [Str "Minus",Space,Str "2"]]
81+ ,[Para [Str "Minus",Space,Str "3"]]]
82+,Para [Str "Minuses",Space,Str "loose:"]
83+,BulletList
84+ [[Para [Str "Minus",Space,Str "1"]]
85+ ,[Para [Str "Minus",Space,Str "2"]]
86+ ,[Para [Str "Minus",Space,Str "3"]]]
87+,Header 2 ("ordered",[],[]) [Str "Ordered"]
88+,Para [Str "Tight:"]
89+,OrderedList (1,DefaultStyle,DefaultDelim)
90+ [[Para [Str "First"]]
91+ ,[Para [Str "Second"]]
92+ ,[Para [Str "Third"]]]
93+,Para [Str "and:"]
94+,OrderedList (1,DefaultStyle,DefaultDelim)
95+ [[Para [Str "One"]]
96+ ,[Para [Str "Two"]]
97+ ,[Para [Str "Three"]]]
98+,Para [Str "Loose",Space,Str "using",Space,Str "tabs:"]
99+,OrderedList (1,DefaultStyle,DefaultDelim)
100+ [[Para [Str "First"]]
101+ ,[Para [Str "Second"]]
102+ ,[Para [Str "Third"]]]
103+,Para [Str "and",Space,Str "using",Space,Str "spaces:"]
104+,OrderedList (1,DefaultStyle,DefaultDelim)
105+ [[Para [Str "One"]]
106+ ,[Para [Str "Two"]]
107+ ,[Para [Str "Three"]]]
108+,Para [Str "Multiple",Space,Str "paragraphs:"]
109+,OrderedList (1,DefaultStyle,DefaultDelim)
110+ [[Para [Str "Item",Space,Str "1,",Space,Str "graf",Space,Str "one."]
111+ ,Para [Str "Item",Space,Str "1.",Space,Str "graf",Space,Str "two.",Space,Str "The",Space,Str "quick",Space,Str "brown",Space,Str "fox",Space,Str "jumped",Space,Str "over",Space,Str "the",Space,Str "lazy",SoftBreak,Str "dog's",Space,Str "back."]]
112+ ,[Para [Str "Item",Space,Str "2."]]
113+ ,[Para [Str "Item",Space,Str "3."]]]
114+,Para [Str "List",Space,Str "styles:"]
115+,OrderedList (1,DefaultStyle,DefaultDelim)
116+ []
117+,OrderedList (1,LowerRoman,DefaultDelim)
118+ []
119+,Header 2 ("nested",[],[]) [Str "Nested"]
120+,BulletList
121+ [[Para [Str "Tab"]
122+ ,BulletList
123+ [[Para [Str "Tab"]
124+ ,BulletList
125+ [[Para [Str "Tab"]]]]]]]
126+,Para [Str "Here's",Space,Str "another:"]
127+,OrderedList (1,DefaultStyle,DefaultDelim)
128+ [[Para [Str "First"]]
129+ ,[Para [Str "Second:"]
130+ ,BulletList
131+ [[Para [Str "Fee"]]
132+ ,[Para [Str "Fie"]]
133+ ,[Para [Str "Foe"]]]]
134+ ,[Para [Str "Third"]]]
135+,Para [Str "Same",Space,Str "thing",Space,Str "but",Space,Str "with",Space,Str "paragraphs:"]
136+,OrderedList (1,DefaultStyle,DefaultDelim)
137+ [[Para [Str "First"]]
138+ ,[Para [Str "Second:"]
139+ ,BulletList
140+ [[Para [Str "Fee"]]
141+ ,[Para [Str "Fie"]]
142+ ,[Para [Str "Foe"]]]]
143+ ,[Para [Str "Third"]]]
144+,Header 2 ("tabs-and-spaces",[],[]) [Str "Tabs",Space,Str "and",Space,Str "spaces"]
145+,BulletList
146+ [[Para [Str "this",Space,Str "is",Space,Str "a",Space,Str "list",Space,Str "item",Space,Str "indented",Space,Str "with",Space,Str "tabs"]]
147+ ,[Para [Str "this",Space,Str "is",Space,Str "a",Space,Str "list",Space,Str "item",Space,Str "indented",Space,Str "with",Space,Str "spaces"]
148+ ,BulletList
149+ [[Para [Str "this",Space,Str "is",Space,Str "an",Space,Str "example",Space,Str "list",Space,Str "item",Space,Str "indented",Space,Str "with",Space,Str "tabs"]]
150+ ,[Para [Str "this",Space,Str "is",Space,Str "an",Space,Str "example",Space,Str "list",Space,Str "item",Space,Str "indented",Space,Str "with",Space,Str "spaces"]]]]]
151+,Header 2 ("fancy-list-markers",[],[]) [Str "Fancy",Space,Str "list",Space,Str "markers"]
152+,Para [Str "Autonumbering:"]
153+,OrderedList (1,DefaultStyle,DefaultDelim)
154+ [[Para [Str "Autonumber."]]
155+ ,[Para [Str "More."]
156+ ,OrderedList (1,DefaultStyle,DefaultDelim)
157+ [[Para [Str "Nested."]]]]]
158+,Header 2 ("definition",[],[]) [Str "Definition"]
159+,DefinitionList
160+ [([Str "Violin"],
161+ [[Para [Str "Stringed",Space,Str "musical",Space,Str "instrument."]
162+ ,Para [Str "Torture",Space,Str "device."]]])
163+ ,([Str "Cello",LineBreak,Str "Violoncello"],
164+ [[Para [Str "Low-voiced",Space,Str "stringed",Space,Str "instrument."]]])]
165+,Header 1 ("inline-markup",[],[]) [Str "Inline",Space,Str "Markup"]
166+,Para [Str "This",Space,Str "is",Space,Emph [Str "emphasized"],Str ",",Space,Str "and",Space,Str "so",Space,Emph [Str "is",SoftBreak,Str "this"],Str "."]
167+,Para [Str "This",Space,Str "is",Space,Strong [Str "strong"],Str ",",Space,Str "and",Space,Str "so",SoftBreak,Strong [Str "is",Space,Str "this"],Str "."]
168+,Para [Str "Empty",Space,Strong [],Space,Str "and",Space,Emph [],Str "."]
169+,Para [Str "An",SoftBreak,Emph [Link ("",[],[]) [Str "emphasized",SoftBreak,Str "link"] ("/url","")],Str "."]
170+,Para [Strong [Emph [Str "This",Space,Str "is",Space,Str "strong",Space,Str "and",Space,Str "em."]]]
171+,Para [Str "So",Space,Str "is",Space,Strong [Emph [Str "this"]],Space,Str "word."]
172+,Para [Strong [Emph [Str "This",Space,Str "is",Space,Str "strong",Space,Str "and",Space,Str "em."]]]
173+,Para [Str "So",Space,Str "is",Space,Strong [Emph [Str "this"]],Space,Str "word."]
174+,Para [Str "This",Space,Str "is",Space,Str "code:",Space,Code ("",[],[]) ">",Str ",",Space,Code ("",[],[]) "$",Str ",",SoftBreak,Code ("",[],[]) "\\",Str ",",Space,Code ("",[],[]) "\\$",Str ",",SoftBreak,Code ("",[],[]) "<html>",Str "."]
175+,Para [Str "This",Space,Str "is",Space,SmallCaps [Str "small",Space,Str "caps"],Str "."]
176+,Para [Str "These",Space,Str "are",Space,Str "all",Space,Str "underlined:",Space,Str "foo",Space,Str "and",Space,Str "bar."]
177+,Para [Str "These",Space,Str "are",Space,Str "all",Space,Str "strikethrough:",Space,Strikeout [Str "foo"],Str ",",SoftBreak,Strikeout [Str "bar"],Str ",",Space,Str "and",Space,Strikeout [Str "baz"],Str "."]
178+,Header 1 ("smart-quotes-ellipses-dashes",[],[]) [Str "Smart",Space,Str "quotes,",Space,Str "ellipses,",Space,Str "dashes"]
179+,Para [Str "\"Hello,\"",Space,Str "said",Space,Str "the",Space,Str "spider.",Space,Str "\"'Shelob'",Space,Str "is",Space,Str "my",Space,Str "name.\""]
180+,Para [Str "'A',",Space,Str "'B',",Space,Str "and",Space,Str "'C'",Space,Str "are",Space,Str "letters."]
181+,Para [Str "'Oak,'",Space,Str "'elm,'",Space,Str "and",Space,Str "'beech'",Space,Str "are",Space,Str "names",Space,Str "of",Space,Str "trees.",Space,Str "So",Space,Str "is",Space,Str "'pine.'"]
182+,Para [Str "'He",Space,Str "said,",Space,Str "\"I",Space,Str "want",Space,Str "to",Space,Str "go.\"'",Space,Str "Were",Space,Str "you",Space,Str "alive",Space,Str "in",Space,Str "the",Space,Str "70's?"]
183+,Para [Str "Here",Space,Str "is",Space,Str "some",Space,Str "quoted",Space,Str "'",Code ("",[],[]) "code",Str "'",Space,Str "and",Space,Str "a",SoftBreak,Str "\"",Link ("",[],[]) [Str "quoted",SoftBreak,Str "link"] ("http://example.com/?foo=1&bar=2",""),Str "\"."]
184+,Para [Str "Some",Space,Str "dashes:",Space,Str "one---two",Space,Str "---",Space,Str "three--four",Space,Str "--",Space,Str "five."]
185+,Para [Str "Dashes",Space,Str "between",Space,Str "numbers:",Space,Str "5-7,",Space,Str "255-66,",Space,Str "1987-1999."]
186+,Para [Str "Ellipses...and.",Space,Str ".",Space,Str ".and",Space,Str ".",Space,Str ".",Space,Str ".",Space,Str "."]
187+,Header 1 ("latex",[],[]) [Str "LaTeX"]
188+,BulletList
189+ [[Para [Str "\\cite[22-23]{smith.1899}"]]
190+ ,[Para [Str "\\doublespacing"]]
191+ ,[Para [Str "$2+2=4$"]]
192+ ,[Para [Str "$x",Space,Str "\\in",Space,Str "y$"]]
193+ ,[Para [Str "$\\alpha",Space,Str "\\wedge",Space,Str "\\omega$"]]
194+ ,[Para [Str "$223$"]]
195+ ,[Para [Str "$p$-Tree"]]
196+ ,[Para [Str "$\\frac{d}{dx}f(x)=\\lim_{h\\to",Space,Str "0}\\frac{f(x+h)-f(x)}{h}$"]]
197+ ,[Para [Str "Here's",Space,Str "one",Space,Str "that",Space,Str "has",Space,Str "a",Space,Str "line",Space,Str "break",Space,Str "in",Space,Str "it:",Space,Str "$\\alpha",Space,Str "+",Space,Str "\\omega",Space,Str "\\times",SoftBreak,Str "x^2$."]]]
198+,Para [Str "These",Space,Str "shouldn't",Space,Str "be",Space,Str "math:"]
199+,BulletList
200+ [[Para [Str "To",Space,Str "get",Space,Str "the",Space,Str "famous",Space,Str "equation,",Space,Str "write",SoftBreak,Code ("",[],[]) "$e = mc^2$",Str "."]]
201+ ,[Para [Str "$22,000",Space,Str "is",Space,Str "a",Space,Emph [Str "lot"],Space,Str "of",Space,Str "money.",Space,Str "So",Space,Str "is",Space,Str "$34,000.",Space,Str "(It",SoftBreak,Str "worked",Space,Str "if",Space,Str "\"lot\"",Space,Str "is",Space,Str "emphasized.)"]]
202+ ,[Para [Str "Escaped",Space,Code ("",[],[]) "$",Str ":",Space,Str "$73",Space,Emph [Str "this",Space,Str "should",Space,Str "be",SoftBreak,Str "emphasized"],Space,Str "23$."]]]
203+,Para [Str "Here's",Space,Str "a",Space,Str "LaTeX",Space,Str "table:"]
204+,Para [Str "\\begin{tabular}{|l|l|}\\hline",Space,Str "Animal",Space,Str "&",Space,Str "Number",Space,Str "\\\\",Space,Str "\\hline",Space,Str "Dog",Space,Str "&",SoftBreak,Str "2",Space,Str "\\\\",Space,Str "Cat",Space,Str "&",Space,Str "1",Space,Str "\\\\",Space,Str "\\hline",Space,Str "\\end{tabular}"]
205+,Header 1 ("special-characters",[],[]) [Str "Special",Space,Str "Characters"]
206+,Para [Str "Here",Space,Str "is",Space,Str "some",Space,Str "unicode:"]
207+,BulletList
208+ [[Para [Str "I",Space,Str "hat:",Space,Str "\206"]]
209+ ,[Para [Str "o",Space,Str "umlaut:",Space,Str "\246"]]
210+ ,[Para [Str "section:",Space,Str "\167"]]
211+ ,[Para [Str "set",Space,Str "membership:",Space,Str "elem"]]
212+ ,[Para [Str "copyright:",Space,Str "\169"]]]
213+,Para [Str "AT&T",Space,Str "has",Space,Str "an",Space,Str "ampersand",Space,Str "in",Space,Str "their",Space,Str "name."]
214+,Para [Str "AT&T",Space,Str "is",Space,Str "another",Space,Str "way",Space,Str "to",Space,Str "write",Space,Str "it."]
215+,Para [Str "This",Space,Str "&",Space,Str "that."]
216+,Para [Str "4",Space,Str "<",Space,Str "5."]
217+,Para [Str "6",Space,Str ">",Space,Str "5."]
218+,Para [Str "Backslash:",Space,Str "\\"]
219+,Para [Str "Backtick:",Space,Str "`"]
220+,Para [Str "Asterisk:",Space,Str "*"]
221+,Para [Str "Underscore:",Space,Str "_"]
222+,Para [Str "Left",Space,Str "brace:",Space,Str "{"]
223+,Para [Str "Right",Space,Str "brace:",Space,Str "}"]
224+,Para [Str "Left",Space,Str "bracket:",Space,Str "["]
225+,Para [Str "Right",Space,Str "bracket:",Space,Str "]"]
226+,Para [Str "Left",Space,Str "paren:",Space,Str "("]
227+,Para [Str "Right",Space,Str "paren:",Space,Str ")"]
228+,Para [Str "Greater-than:",Space,Str ">"]
229+,Para [Str "Hash:",Space,Str "#"]
230+,Para [Str "Period:",Space,Str "."]
231+,Para [Str "Bang:",Space,Str "!"]
232+,Para [Str "Plus:",Space,Str "+"]
233+,Para [Str "Minus:",Space,Str "-"]
234+,Header 1 ("links",[],[]) [Str "Links"]
235+,Header 2 ("explicit",[],[]) [Str "Explicit"]
236+,Para [Str "Just",Space,Str "a",SoftBreak,Link ("",[],[]) [Str "URL"] ("/url/",""),Str "."]
237+,Para [Link ("",[],[]) [Str "URL",SoftBreak,Str "and",Space,Str "title"] ("/url/","title"),Str "."]
238+,Para [Link ("",[],[]) [Str "URL",SoftBreak,Str "and",Space,Str "title"] ("/url/","title preceded by two spaces"),Str "."]
239+,Para [Link ("",[],[]) [Str "URL",SoftBreak,Str "and",Space,Str "title"] ("/url/","title preceded by a tab"),Str "."]
240+,Para [Link ("",[],[]) [Str "URL",SoftBreak,Str "and",Space,Str "title"] ("/url/","title with \"quotes\" in it")]
241+,Para [Link ("",[],[]) [Str "URL",SoftBreak,Str "and",Space,Str "title"] ("/url/","title with single quotes")]
242+,Para [Str "Email",Space,Str "link",Space,Str "(nobody",Space,Str "[at]",Space,Str "nowhere.net)"]
243+,Para [Link ("",[],[]) [Str "Empty"] ("",""),Str "."]
244+,Header 2 ("reference",[],[]) [Str "Reference"]
245+,Para [Str "Foo",SoftBreak,Link ("",[],[]) [Str "bar"] ("/url/",""),Str "."]
246+,Para [Str "Foo",SoftBreak,Link ("",[],[]) [Str "bar"] ("/url/",""),Str "."]
247+,Para [Str "Foo",SoftBreak,Link ("",[],[]) [Str "bar"] ("/url/",""),Str "."]
248+,Para [Str "With",Space,Link ("",[],[]) [Str "embedded",SoftBreak,Str "[brackets]"] ("/url/",""),Str "."]
249+,Para [Link ("",[],[]) [Str "b"] ("/url/",""),Space,Str "by",SoftBreak,Str "itself",Space,Str "should",Space,Str "be",Space,Str "a",Space,Str "link."]
250+,Para [Str "Indented",SoftBreak,Link ("",[],[]) [Str "once"] ("/url",""),Str "."]
251+,Para [Str "Indented",SoftBreak,Link ("",[],[]) [Str "twice"] ("/url",""),Str "."]
252+,Para [Str "Indented",SoftBreak,Link ("",[],[]) [Str "thrice"] ("/url",""),Str "."]
253+,Para [Str "This",Space,Str "should",Space,Str "[not]",Space,Str "be",Space,Str "a",Space,Str "link."]
254+,CodeBlock ("",[],[]) "[not]: /url"
255+,Para [Str "Foo",SoftBreak,Link ("",[],[]) [Str "bar"] ("/url/","Title with \"quotes\" inside"),Str "."]
256+,Para [Str "Foo",SoftBreak,Link ("",[],[]) [Str "biz"] ("/url/","Title with \"quote\" inside"),Str "."]
257+,Header 2 ("with-ampersands",[],[]) [Str "With",Space,Str "ampersands"]
258+,Para [Str "Here's",Space,Str "a",SoftBreak,Link ("",[],[]) [Str "link",SoftBreak,Str "with",Space,Str "an",Space,Str "ampersand",Space,Str "in",Space,Str "the",Space,Str "URL"] ("http://example.com/?foo=1&bar=2",""),Str "."]
259+,Para [Str "Here's",Space,Str "a",Space,Str "link",Space,Str "with",Space,Str "an",Space,Str "amersand",Space,Str "in",Space,Str "the",Space,Str "link",Space,Str "text:",SoftBreak,Link ("",[],[]) [Str "AT&T"] ("http://att.com/","AT&T"),Str "."]
260+,Para [Str "Here's",Space,Str "an",SoftBreak,Link ("",[],[]) [Str "inline",SoftBreak,Str "link"] ("/script?foo=1&bar=2",""),Str "."]
261+,Para [Str "Here's",Space,Str "an",SoftBreak,Link ("",[],[]) [Str "inline",SoftBreak,Str "link",Space,Str "in",Space,Str "pointy",Space,Str "braces"] ("/script?foo=1&bar=2",""),Str "."]
262+,Header 2 ("autolinks",[],[]) [Str "Autolinks"]
263+,Para [Str "With",Space,Str "an",Space,Str "ampersand:",SoftBreak,Link ("",[],[]) [Str "http://example.com/?foo=1&bar=2"] ("http://example.com/?foo=1&bar=2","")]
264+,BulletList
265+ [[Para [Str "In",Space,Str "a",Space,Str "list?"]]
266+ ,[Para [Link ("",[],[]) [Str "http://example.com/"] ("http://example.com/","")]]
267+ ,[Para [Str "It",Space,Str "should."]]]
268+,Para [Str "An",Space,Str "e-mail",Space,Str "address:",Space,Str "nobody",Space,Str "[at]",Space,Str "nowhere.net"]
269+,BlockQuote
270+ [Para [Str "Blockquoted:",SoftBreak,Link ("",[],[]) [Str "http://example.com/"] ("http://example.com/","")]]
271+,Para [Str "Auto-links",Space,Str "should",Space,Str "not",Space,Str "occur",Space,Str "here:",SoftBreak,Code ("",[],[]) "<http://example.com/>"]
272+,CodeBlock ("",[],[]) "or here: <http://example.com/>"
273+,Header 1 ("images",[],[]) [Str "Images"]
274+,Para [Str "From",Space,Str "\"Voyage",Space,Str "dans",Space,Str "la",Space,Str "Lune\"",Space,Str "by",Space,Str "Georges",Space,Str "Melies",Space,Str "(1902):"]
275+,Para [Image ("",[],[]) [] ("lalune.jpg","Voyage dans la Lune")]
276+,Para [Str "Here",Space,Str "is",Space,Str "a",Space,Str "movie",SoftBreak,Image ("",[],[]) [] ("movie.jpg",""),SoftBreak,Str "icon."]
277+,Header 1 ("footnotes",[],[]) [Str "Footnotes"]
278+,Para [Str "Here",Space,Str "is",Space,Str "a",Space,Str "footnote",Space,Str "reference",Link ("",[],[]) [Str "(1)"] ("#note_1",""),Str ",",SoftBreak,Str "and",SoftBreak,Str "another",Link ("",[],[]) [Str "(longnote)"] ("#note_longnote",""),Str ".",SoftBreak,Str "This",Space,Str "should",Space,Emph [Str "not"],Space,Str "be",Space,Str "a",Space,Str "footnote",Space,Str "reference,",Space,Str "because",Space,Str "it",SoftBreak,Str "contains",Space,Str "a",Space,Str "space^(my",Space,Str "note)."]
279+,Para [Link ("",[],[]) [Str "(1)"] ("#ref_1",""),Space,Str "Here",Space,Str "is",Space,Str "the",Space,Str "footnote.",Space,Str "It",Space,Str "can",SoftBreak,Str "go",Space,Str "anywhere",Space,Str "in",Space,Str "the",Space,Str "document,",Space,Str "not",Space,Str "just",Space,Str "at",Space,Str "the",Space,Str "end."]
280+,Para [Link ("",[],[]) [Str "(longnote)"] ("#ref_longnote",""),Space,Str "Here's",SoftBreak,Str "the",Space,Str "other",Space,Str "note.",Space,Str "This",Space,Str "one",Space,Str "contains",Space,Str "multiple",Space,Str "blocks."]
281+,Para [Str "Caret",Space,Str "characters",Space,Str "are",Space,Str "used",Space,Str "to",Space,Str "indicate",Space,Str "that",Space,Str "the",Space,Str "blocks",Space,Str "all",Space,Str "belong",Space,Str "to",SoftBreak,Str "a",Space,Str "single",Space,Str "footnote",Space,Str "(as",Space,Str "with",Space,Str "block",Space,Str "quotes)."]
282+,CodeBlock ("",[],[]) " { <code> }"
283+,Para [Str "If",Space,Str "you",Space,Str "want,",Space,Str "you",Space,Str "can",Space,Str "use",Space,Str "a",Space,Str "caret",Space,Str "at",Space,Str "the",Space,Str "beginning",Space,Str "of",Space,Str "every",Space,Str "line,",Space,Str "as",SoftBreak,Str "with",Space,Str "blockquotes,",Space,Str "but",Space,Str "all",Space,Str "that",Space,Str "you",Space,Str "need",Space,Str "is",Space,Str "a",Space,Str "caret",Space,Str "at",Space,Str "the",Space,Str "beginning",SoftBreak,Str "of",Space,Str "the",Space,Str "first",Space,Str "line",Space,Str "of",Space,Str "the",Space,Str "block",Space,Str "and",Space,Str "any",Space,Str "preceding",Space,Str "blank",Space,Str "lines."]
284+,Para [Str "text",Space,Emph [Str "Leading",Space,Str "space"]]
285+,Para [Emph [Str "Trailing",Space,Str "space"],Space,Str "text"]
286+,Para [Str "text",Space,Emph [Str "Leading",Space,Str "spaces"]]
287+,Para [Emph [Str "Trailing",Space,Str "spaces"],Space,Str "text"]
288+,Header 1 ("tables",[],[]) [Str "Tables"]
289+,Header 2 ("tables-with-headers",[],[]) [Str "Tables",Space,Str "with",Space,Str "Headers"]
290+,Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
291+ [[Para [Str "X"]]
292+ ,[Para [Str "Y"]]
293+ ,[Para [Str "Z"]]]
294+ [[[Para [Str "1"]]
295+ ,[Para [Str "2"]]
296+ ,[Para [Str "3"]]]
297+ ,[[Para [Str "4"]]
298+ ,[Para [Str "5"]]
299+ ,[Para [Str "6"]]]]
300+,Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
301+ [[Para [Str "X"]]
302+ ,[Para [Str "Y"]]
303+ ,[Para [Str "Z"]]]
304+ [[[Para [Str "1"]]
305+ ,[Para [Str "2"]]
306+ ,[Para [Str "3"]]]
307+ ,[[Para [Str "4"]]
308+ ,[Para [Str "5"]]
309+ ,[Para [Str "6"]]]]
310+,Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
311+ [[Para [Str "X"]]
312+ ,[Para [Str "Y"]]
313+ ,[Para [Str "Z"]]]
314+ [[[Para [Str "1"]]
315+ ,[Para [Str "2"]]
316+ ,[Para [Str "3"]]]
317+ ,[[Para [Str "4"]]
318+ ,[Para [Str "5"]]
319+ ,[Para [Str "6"]]]]
320+,Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
321+ [[Para [Str "X"]]
322+ ,[Para [Str "Y"]]
323+ ,[Para [Str "Z"]]]
324+ [[[Para [Str "1"]]
325+ ,[Para [Str "2"]]
326+ ,[Para [Str "3"]]]
327+ ,[[Para [Str "4"]]
328+ ,[Para [Str "5"]]
329+ ,[Para [Str "6"]]]]
330+,Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
331+ [[Para [Str "X"]]
332+ ,[Para [Str "Y"]]
333+ ,[Para [Str "Z"]]]
334+ [[[Para [Str "1"]]
335+ ,[Para [Str "2"]]
336+ ,[Para [Str "3"]]]
337+ ,[[Para [Str "4"]]
338+ ,[Para [Str "5"]]
339+ ,[Para [Str "6"]]]]
340+,Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
341+ [[Para [Str "X"]]
342+ ,[Para [Str "Y"]]
343+ ,[Para [Str "Z"]]]
344+ [[[Para [Str "1"]]
345+ ,[Para [Str "2"]]
346+ ,[Para [Str "3"]]]
347+ ,[[Para [Str "4"]]
348+ ,[Para [Str "5"]]
349+ ,[Para [Str "6"]]]]
350+,Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
351+ [[Para [Str "X"]]
352+ ,[Para [Str "Y"]]
353+ ,[Para [Str "Z"]]]
354+ [[[Para [Str "1"]]
355+ ,[Para [Str "2"]]
356+ ,[Para [Str "3"]]]
357+ ,[[Para [Str "4"]]
358+ ,[Para [Str "5"]]
359+ ,[Para [Str "6"]]]]
360+,Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
361+ [[Para [Str "X"]]
362+ ,[Para [Str "Y"]]
363+ ,[Para [Str "Z"]]]
364+ [[[Para [Str "1"]]
365+ ,[Para [Str "2"]]
366+ ,[Para [Str "3"]]]
367+ ,[[Para [Str "4"]]
368+ ,[Para [Str "5"]]
369+ ,[Para [Str "6"]]]]
370+,Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
371+ [[Para [Str "X"]]
372+ ,[Para [Str "Y"]]
373+ ,[Para [Str "Z"]]]
374+ [[[Para [Str "1"]]
375+ ,[Para [Str "2"]]
376+ ,[Para [Str "3"]]]
377+ ,[[Para [Str "4"]]
378+ ,[Para [Str "5"]]
379+ ,[Para [Str "6"]]]]
380+,Header 2 ("tables-without-headers",[],[]) [Str "Tables",Space,Str "without",Space,Str "Headers"]
381+,Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
382+ [[]
383+ ,[]
384+ ,[]]
385+ [[[Para [Str "1"]]
386+ ,[Para [Str "2"]]
387+ ,[Para [Str "3"]]]
388+ ,[[Para [Str "4"]]
389+ ,[Para [Str "5"]]
390+ ,[Para [Str "6"]]]]
391+,Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
392+ [[]
393+ ,[]
394+ ,[]]
395+ [[[Para [Str "1"]]
396+ ,[Para [Str "2"]]
397+ ,[Para [Str "3"]]]
398+ ,[[Para [Str "4"]]
399+ ,[Para [Str "5"]]
400+ ,[Para [Str "6"]]]]
401+,Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
402+ [[]
403+ ,[]
404+ ,[]]
405+ [[[Para [Str "1"]]
406+ ,[Para [Str "2"]]
407+ ,[Para [Str "3"]]]
408+ ,[[Para [Str "4"]]
409+ ,[Para [Str "5"]]
410+ ,[Para [Str "6"]]]]
411+,Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]
412+ [[]
413+ ,[]
414+ ,[]]
415+ [[[Para [Str "1"]]
416+ ,[Para [Str "2"]]
417+ ,[Para [Str "3"]]]
418+ ,[[Para [Str "4"]]
419+ ,[Para [Str "5"]]
420+ ,[Para [Str "6"]]]]
421+,Header 2 ("empty-tables",[],[]) [Str "Empty",Space,Str "Tables"]
422+,Para [Str "This",Space,Str "section",Space,Str "should",Space,Str "be",Space,Str "empty."]]
test/jats-reader.xmlnew file+1773
@@ -0,0 +1,1773 @@
1+<?xml version="1.0" encoding="utf-8" ?>
2+<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Publishing DTD v1.0 20120330//EN"
3+ "JATS-journalpublishing1.dtd">
4+<article xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:xlink="http://www.w3.org/1999/xlink" dtd-version="1.0" article-type="other">
5+<front>
6+<journal-meta>
7+<journal-title-group>
8+</journal-title-group>
9+<publisher>
10+<publisher-name></publisher-name>
11+</publisher>
12+</journal-meta>
13+<article-meta>
14+<title-group>
15+<article-title>Pandoc Test Suite</article-title>
16+</title-group>
17+</article-meta>
18+</front>
19+<body>
20+<p>
21+ This is a set of tests for pandoc. Most of them are adapted from John
22+ Gruber's markdown test suite.
23+</p>
24+<sec id="headers">
25+ <title>Headers</title>
26+ <sec id="level-2-with-an-embedded-link">
27+ <title>Level 2 with an
28+ <ext-link ext-link-type="uri" xlink:href="/url">embedded
29+ link</ext-link></title>
30+ <sec id="level-3-with-emphasis">
31+ <title>Level 3 with <italic>emphasis</italic></title>
32+ <sec id="level-4">
33+ <title>Level 4</title>
34+ <sec id="level-5">
35+ <title>Level 5</title>
36+ </sec>
37+ </sec>
38+ </sec>
39+ </sec>
40+</sec>
41+<sec id="level-1">
42+ <title>Level 1</title>
43+ <sec id="level-2-with-emphasis">
44+ <title>Level 2 with <italic>emphasis</italic></title>
45+ <sec id="level-3">
46+ <title>Level 3</title>
47+ <p>
48+ with no blank line
49+ </p>
50+ </sec>
51+ </sec>
52+ <sec id="level-2">
53+ <title>Level 2</title>
54+ <p>
55+ with no blank line
56+ </p>
57+ </sec>
58+</sec>
59+<sec id="paragraphs">
60+ <title>Paragraphs</title>
61+ <p>
62+ Here's a regular paragraph.
63+ </p>
64+ <p>
65+ In Markdown 1.0.0 and earlier. Version 8. This line turns into a
66+ list item. Because a hard-wrapped line in the middle of a paragraph
67+ looked like a list item.
68+ </p>
69+ <p>
70+ Here's one with a bullet. * criminey.
71+ </p>
72+ <p>
73+ There should be a hard line break<break />here.
74+ </p>
75+</sec>
76+<sec id="block-quotes">
77+ <title>Block Quotes</title>
78+ <p>
79+ E-mail style:
80+ </p>
81+ <disp-quote>
82+ <p>
83+ This is a block quote. It is pretty short.
84+ </p>
85+ </disp-quote>
86+ <disp-quote>
87+ <p>
88+ Code in a block quote:
89+ </p>
90+ <preformat>sub status {
91+ print &quot;working&quot;;
92+}</preformat>
93+ <p>
94+ A list:
95+ </p>
96+ <list list-type="order">
97+ <list-item>
98+ <p>
99+ item one
100+ </p>
101+ </list-item>
102+ <list-item>
103+ <p>
104+ item two
105+ </p>
106+ </list-item>
107+ </list>
108+ <p>
109+ Nested block quotes:
110+ </p>
111+ <disp-quote>
112+ <p>
113+ nested
114+ </p>
115+ </disp-quote>
116+ <disp-quote>
117+ <p>
118+ nested
119+ </p>
120+ </disp-quote>
121+ </disp-quote>
122+ <p>
123+ This should not be a block quote: 2 &gt; 1.
124+ </p>
125+ <p>
126+ Box-style:
127+ </p>
128+ <disp-quote>
129+ <p>
130+ Example:
131+ </p>
132+ <preformat>sub status {
133+ print &quot;working&quot;;
134+}</preformat>
135+ </disp-quote>
136+ <disp-quote>
137+ <list list-type="order">
138+ <list-item>
139+ <p>
140+ do laundry
141+ </p>
142+ </list-item>
143+ <list-item>
144+ <p>
145+ take out the trash
146+ </p>
147+ </list-item>
148+ </list>
149+ </disp-quote>
150+ <p>
151+ Here's a nested one:
152+ </p>
153+ <disp-quote>
154+ <p>
155+ Joe said:
156+ </p>
157+ <disp-quote>
158+ <p>
159+ Don't quote me.
160+ </p>
161+ </disp-quote>
162+ </disp-quote>
163+ <p>
164+ And a following paragraph.
165+ </p>
166+</sec>
167+<sec id="code-blocks">
168+ <title>Code Blocks</title>
169+ <p>
170+ Code:
171+ </p>
172+ <preformat>---- (should be four hyphens)
173+
174+sub status {
175+ print &quot;working&quot;;
176+}
177+
178+this code block is indented by one tab</preformat>
179+ <p>
180+ And:
181+ </p>
182+ <preformat> this code block is indented by two tabs
183+
184+These should not be escaped: \$ \\ \&gt; \[ \{</preformat>
185+</sec>
186+<sec id="lists">
187+ <title>Lists</title>
188+ <sec id="unordered">
189+ <title>Unordered</title>
190+ <p>
191+ Asterisks tight:
192+ </p>
193+ <list list-type="bullet">
194+ <list-item>
195+ <p>
196+ asterisk 1
197+ </p>
198+ </list-item>
199+ <list-item>
200+ <p>
201+ asterisk 2
202+ </p>
203+ </list-item>
204+ <list-item>
205+ <p>
206+ asterisk 3
207+ </p>
208+ </list-item>
209+ </list>
210+ <p>
211+ Asterisks loose:
212+ </p>
213+ <list list-type="bullet">
214+ <list-item>
215+ <p>
216+ asterisk 1
217+ </p>
218+ </list-item>
219+ <list-item>
220+ <p>
221+ asterisk 2
222+ </p>
223+ </list-item>
224+ <list-item>
225+ <p>
226+ asterisk 3
227+ </p>
228+ </list-item>
229+ </list>
230+ <p>
231+ Pluses tight:
232+ </p>
233+ <list list-type="bullet">
234+ <list-item>
235+ <p>
236+ Plus 1
237+ </p>
238+ </list-item>
239+ <list-item>
240+ <p>
241+ Plus 2
242+ </p>
243+ </list-item>
244+ <list-item>
245+ <p>
246+ Plus 3
247+ </p>
248+ </list-item>
249+ </list>
250+ <p>
251+ Pluses loose:
252+ </p>
253+ <list list-type="bullet">
254+ <list-item>
255+ <p>
256+ Plus 1
257+ </p>
258+ </list-item>
259+ <list-item>
260+ <p>
261+ Plus 2
262+ </p>
263+ </list-item>
264+ <list-item>
265+ <p>
266+ Plus 3
267+ </p>
268+ </list-item>
269+ </list>
270+ <p>
271+ Minuses tight:
272+ </p>
273+ <list list-type="bullet">
274+ <list-item>
275+ <p>
276+ Minus 1
277+ </p>
278+ </list-item>
279+ <list-item>
280+ <p>
281+ Minus 2
282+ </p>
283+ </list-item>
284+ <list-item>
285+ <p>
286+ Minus 3
287+ </p>
288+ </list-item>
289+ </list>
290+ <p>
291+ Minuses loose:
292+ </p>
293+ <list list-type="bullet">
294+ <list-item>
295+ <p>
296+ Minus 1
297+ </p>
298+ </list-item>
299+ <list-item>
300+ <p>
301+ Minus 2
302+ </p>
303+ </list-item>
304+ <list-item>
305+ <p>
306+ Minus 3
307+ </p>
308+ </list-item>
309+ </list>
310+ </sec>
311+ <sec id="ordered">
312+ <title>Ordered</title>
313+ <p>
314+ Tight:
315+ </p>
316+ <list list-type="order">
317+ <list-item>
318+ <p>
319+ First
320+ </p>
321+ </list-item>
322+ <list-item>
323+ <p>
324+ Second
325+ </p>
326+ </list-item>
327+ <list-item>
328+ <p>
329+ Third
330+ </p>
331+ </list-item>
332+ </list>
333+ <p>
334+ and:
335+ </p>
336+ <list list-type="order">
337+ <list-item>
338+ <p>
339+ One
340+ </p>
341+ </list-item>
342+ <list-item>
343+ <p>
344+ Two
345+ </p>
346+ </list-item>
347+ <list-item>
348+ <p>
349+ Three
350+ </p>
351+ </list-item>
352+ </list>
353+ <p>
354+ Loose using tabs:
355+ </p>
356+ <list list-type="order">
357+ <list-item>
358+ <p>
359+ First
360+ </p>
361+ </list-item>
362+ <list-item>
363+ <p>
364+ Second
365+ </p>
366+ </list-item>
367+ <list-item>
368+ <p>
369+ Third
370+ </p>
371+ </list-item>
372+ </list>
373+ <p>
374+ and using spaces:
375+ </p>
376+ <list list-type="order">
377+ <list-item>
378+ <p>
379+ One
380+ </p>
381+ </list-item>
382+ <list-item>
383+ <p>
384+ Two
385+ </p>
386+ </list-item>
387+ <list-item>
388+ <p>
389+ Three
390+ </p>
391+ </list-item>
392+ </list>
393+ <p>
394+ Multiple paragraphs:
395+ </p>
396+ <list list-type="order">
397+ <list-item>
398+ <p>
399+ Item 1, graf one.
400+ </p>
401+ <p>
402+ Item 1. graf two. The quick brown fox jumped over the lazy
403+ dog's back.
404+ </p>
405+ </list-item>
406+ <list-item>
407+ <p>
408+ Item 2.
409+ </p>
410+ </list-item>
411+ <list-item>
412+ <p>
413+ Item 3.
414+ </p>
415+ </list-item>
416+ </list>
417+ <p>
418+ List styles:
419+ </p>
420+ <list list-type="order"></list>
421+ <list list-type="roman-lower"></list>
422+ </sec>
423+ <sec id="nested">
424+ <title>Nested</title>
425+ <list list-type="bullet">
426+ <list-item>
427+ <p>
428+ Tab
429+ </p>
430+ <list list-type="bullet">
431+ <list-item>
432+ <p>
433+ Tab
434+ </p>
435+ <list list-type="bullet">
436+ <list-item>
437+ <p>
438+ Tab
439+ </p>
440+ </list-item>
441+ </list>
442+ </list-item>
443+ </list>
444+ </list-item>
445+ </list>
446+ <p>
447+ Here's another:
448+ </p>
449+ <list list-type="order">
450+ <list-item>
451+ <p>
452+ First
453+ </p>
454+ </list-item>
455+ <list-item>
456+ <p>
457+ Second:
458+ </p>
459+ <list list-type="bullet">
460+ <list-item>
461+ <p>
462+ Fee
463+ </p>
464+ </list-item>
465+ <list-item>
466+ <p>
467+ Fie
468+ </p>
469+ </list-item>
470+ <list-item>
471+ <p>
472+ Foe
473+ </p>
474+ </list-item>
475+ </list>
476+ </list-item>
477+ <list-item>
478+ <p>
479+ Third
480+ </p>
481+ </list-item>
482+ </list>
483+ <p>
484+ Same thing but with paragraphs:
485+ </p>
486+ <list list-type="order">
487+ <list-item>
488+ <p>
489+ First
490+ </p>
491+ </list-item>
492+ <list-item>
493+ <p>
494+ Second:
495+ </p>
496+ <list list-type="bullet">
497+ <list-item>
498+ <p>
499+ Fee
500+ </p>
501+ </list-item>
502+ <list-item>
503+ <p>
504+ Fie
505+ </p>
506+ </list-item>
507+ <list-item>
508+ <p>
509+ Foe
510+ </p>
511+ </list-item>
512+ </list>
513+ </list-item>
514+ <list-item>
515+ <p>
516+ Third
517+ </p>
518+ </list-item>
519+ </list>
520+ </sec>
521+ <sec id="tabs-and-spaces">
522+ <title>Tabs and spaces</title>
523+ <list list-type="bullet">
524+ <list-item>
525+ <p>
526+ this is a list item indented with tabs
527+ </p>
528+ </list-item>
529+ <list-item>
530+ <p>
531+ this is a list item indented with spaces
532+ </p>
533+ <list list-type="bullet">
534+ <list-item>
535+ <p>
536+ this is an example list item indented with tabs
537+ </p>
538+ </list-item>
539+ <list-item>
540+ <p>
541+ this is an example list item indented with spaces
542+ </p>
543+ </list-item>
544+ </list>
545+ </list-item>
546+ </list>
547+ </sec>
548+ <sec id="fancy-list-markers">
549+ <title>Fancy list markers</title>
550+ <p>
551+ Autonumbering:
552+ </p>
553+ <list list-type="order">
554+ <list-item>
555+ <p>
556+ Autonumber.
557+ </p>
558+ </list-item>
559+ <list-item>
560+ <p>
561+ More.
562+ </p>
563+ <list list-type="order">
564+ <list-item>
565+ <p>
566+ Nested.
567+ </p>
568+ </list-item>
569+ </list>
570+ </list-item>
571+ </list>
572+ </sec>
573+ <sec id="definition">
574+ <title>Definition</title>
575+ <def-list>
576+ <def-item>
577+ <term>
578+ Violin
579+ </term>
580+ <def>
581+ <p>
582+ Stringed musical instrument.
583+ </p>
584+ <p>
585+ Torture device.
586+ </p>
587+ </def>
588+ </def-item>
589+ <def-item>
590+ <term>
591+ Cello<break />Violoncello
592+ </term>
593+ <def>
594+ <p>
595+ Low-voiced stringed instrument.
596+ </p>
597+ </def>
598+ </def-item>
599+ </def-list>
600+ </sec>
601+</sec>
602+<sec id="inline-markup">
603+ <title>Inline Markup</title>
604+ <p>
605+ This is <italic>emphasized</italic>, and so <italic>is
606+ this</italic>.
607+ </p>
608+ <p>
609+ This is <bold role="strong">strong</bold>, and so
610+ <bold role="strong">is this</bold>.
611+ </p>
612+ <p>
613+ Empty <bold role="strong"></bold> and <italic></italic>.
614+ </p>
615+ <p>
616+ An
617+ <italic><ext-link ext-link-type="uri" xlink:href="/url">emphasized
618+ link</ext-link></italic>.
619+ </p>
620+ <p>
621+ <bold role="strong"><italic>This is strong and em.</italic></bold>
622+ </p>
623+ <p>
624+ So is <bold role="strong"><italic>this</italic></bold> word.
625+ </p>
626+ <p>
627+ <bold role="strong"><italic>This is strong and em.</italic></bold>
628+ </p>
629+ <p>
630+ So is <bold role="strong"><italic>this</italic></bold> word.
631+ </p>
632+ <p>
633+ This is code: <monospace>&gt;</monospace>, <monospace>$</monospace>,
634+ <monospace>\</monospace>, <monospace>\$</monospace>,
635+ <monospace>&lt;html&gt;</monospace>.
636+ </p>
637+ <p>
638+ This is <sc role="smallcaps">small caps</sc>.
639+ </p>
640+ <p>
641+ These are all underlined: foo and bar.
642+ </p>
643+ <p>
644+ These are all strikethrough: <strike>foo</strike>,
645+ <strike>bar</strike>, and <strike>baz</strike>.
646+ </p>
647+</sec>
648+<sec id="smart-quotes-ellipses-dashes">
649+ <title>Smart quotes, ellipses, dashes</title>
650+ <p>
651+ &quot;Hello,&quot; said the spider. &quot;'Shelob' is my name.&quot;
652+ </p>
653+ <p>
654+ 'A', 'B', and 'C' are letters.
655+ </p>
656+ <p>
657+ 'Oak,' 'elm,' and 'beech' are names of trees. So is 'pine.'
658+ </p>
659+ <p>
660+ 'He said, &quot;I want to go.&quot;' Were you alive in the 70's?
661+ </p>
662+ <p>
663+ Here is some quoted '<monospace>code</monospace>' and a
664+ &quot;<ext-link ext-link-type="uri" xlink:href="http://example.com/?foo=1&amp;bar=2">quoted
665+ link</ext-link>&quot;.
666+ </p>
667+ <p>
668+ Some dashes: one---two --- three--four -- five.
669+ </p>
670+ <p>
671+ Dashes between numbers: 5-7, 255-66, 1987-1999.
672+ </p>
673+ <p>
674+ Ellipses...and. . .and . . . .
675+ </p>
676+</sec>
677+<sec id="latex">
678+ <title>LaTeX</title>
679+ <list list-type="bullet">
680+ <list-item>
681+ <p>
682+ \cite[22-23]{smith.1899}
683+ </p>
684+ </list-item>
685+ <list-item>
686+ <p>
687+ \doublespacing
688+ </p>
689+ </list-item>
690+ <list-item>
691+ <p>
692+ $2+2=4$
693+ </p>
694+ </list-item>
695+ <list-item>
696+ <p>
697+ $x \in y$
698+ </p>
699+ </list-item>
700+ <list-item>
701+ <p>
702+ $\alpha \wedge \omega$
703+ </p>
704+ </list-item>
705+ <list-item>
706+ <p>
707+ $223$
708+ </p>
709+ </list-item>
710+ <list-item>
711+ <p>
712+ $p$-Tree
713+ </p>
714+ </list-item>
715+ <list-item>
716+ <p>
717+ $\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$
718+ </p>
719+ </list-item>
720+ <list-item>
721+ <p>
722+ Here's one that has a line break in it: $\alpha + \omega \times
723+ x^2$.
724+ </p>
725+ </list-item>
726+ </list>
727+ <p>
728+ These shouldn't be math:
729+ </p>
730+ <list list-type="bullet">
731+ <list-item>
732+ <p>
733+ To get the famous equation, write
734+ <monospace>$e = mc^2$</monospace>.
735+ </p>
736+ </list-item>
737+ <list-item>
738+ <p>
739+ $22,000 is a <italic>lot</italic> of money. So is $34,000. (It
740+ worked if &quot;lot&quot; is emphasized.)
741+ </p>
742+ </list-item>
743+ <list-item>
744+ <p>
745+ Escaped <monospace>$</monospace>: $73 <italic>this should be
746+ emphasized</italic> 23$.
747+ </p>
748+ </list-item>
749+ </list>
750+ <p>
751+ Here's a LaTeX table:
752+ </p>
753+ <p>
754+ \begin{tabular}{|l|l|}\hline Animal &amp; Number \\ \hline Dog &amp;
755+ 2 \\ Cat &amp; 1 \\ \hline \end{tabular}
756+ </p>
757+</sec>
758+<sec id="special-characters">
759+ <title>Special Characters</title>
760+ <p>
761+ Here is some unicode:
762+ </p>
763+ <list list-type="bullet">
764+ <list-item>
765+ <p>
766+ I hat: Î
767+ </p>
768+ </list-item>
769+ <list-item>
770+ <p>
771+ o umlaut: ö
772+ </p>
773+ </list-item>
774+ <list-item>
775+ <p>
776+ section: §
777+ </p>
778+ </list-item>
779+ <list-item>
780+ <p>
781+ set membership: elem
782+ </p>
783+ </list-item>
784+ <list-item>
785+ <p>
786+ copyright: ©
787+ </p>
788+ </list-item>
789+ </list>
790+ <p>
791+ AT&amp;T has an ampersand in their name.
792+ </p>
793+ <p>
794+ AT&amp;T is another way to write it.
795+ </p>
796+ <p>
797+ This &amp; that.
798+ </p>
799+ <p>
800+ 4 &lt; 5.
801+ </p>
802+ <p>
803+ 6 &gt; 5.
804+ </p>
805+ <p>
806+ Backslash: \
807+ </p>
808+ <p>
809+ Backtick: `
810+ </p>
811+ <p>
812+ Asterisk: *
813+ </p>
814+ <p>
815+ Underscore: _
816+ </p>
817+ <p>
818+ Left brace: {
819+ </p>
820+ <p>
821+ Right brace: }
822+ </p>
823+ <p>
824+ Left bracket: [
825+ </p>
826+ <p>
827+ Right bracket: ]
828+ </p>
829+ <p>
830+ Left paren: (
831+ </p>
832+ <p>
833+ Right paren: )
834+ </p>
835+ <p>
836+ Greater-than: &gt;
837+ </p>
838+ <p>
839+ Hash: #
840+ </p>
841+ <p>
842+ Period: .
843+ </p>
844+ <p>
845+ Bang: !
846+ </p>
847+ <p>
848+ Plus: +
849+ </p>
850+ <p>
851+ Minus: -
852+ </p>
853+</sec>
854+<sec id="links">
855+ <title>Links</title>
856+ <sec id="explicit">
857+ <title>Explicit</title>
858+ <p>
859+ Just a
860+ <ext-link ext-link-type="uri" xlink:href="/url/">URL</ext-link>.
861+ </p>
862+ <p>
863+ <ext-link ext-link-type="uri" xlink:href="/url/" xlink:title="title">URL
864+ and title</ext-link>.
865+ </p>
866+ <p>
867+ <ext-link ext-link-type="uri" xlink:href="/url/" xlink:title="title preceded by two spaces">URL
868+ and title</ext-link>.
869+ </p>
870+ <p>
871+ <ext-link ext-link-type="uri" xlink:href="/url/" xlink:title="title preceded by a tab">URL
872+ and title</ext-link>.
873+ </p>
874+ <p>
875+ <ext-link ext-link-type="uri" xlink:href="/url/" xlink:title="title with &quot;quotes&quot; in it">URL
876+ and title</ext-link>
877+ </p>
878+ <p>
879+ <ext-link ext-link-type="uri" xlink:href="/url/" xlink:title="title with single quotes">URL
880+ and title</ext-link>
881+ </p>
882+ <p>
883+ Email link (nobody [at] nowhere.net)
884+ </p>
885+ <p>
886+ <ext-link ext-link-type="uri" xlink:href="">Empty</ext-link>.
887+ </p>
888+ </sec>
889+ <sec id="reference">
890+ <title>Reference</title>
891+ <p>
892+ Foo
893+ <ext-link ext-link-type="uri" xlink:href="/url/">bar</ext-link>.
894+ </p>
895+ <p>
896+ Foo
897+ <ext-link ext-link-type="uri" xlink:href="/url/">bar</ext-link>.
898+ </p>
899+ <p>
900+ Foo
901+ <ext-link ext-link-type="uri" xlink:href="/url/">bar</ext-link>.
902+ </p>
903+ <p>
904+ With <ext-link ext-link-type="uri" xlink:href="/url/">embedded
905+ [brackets]</ext-link>.
906+ </p>
907+ <p>
908+ <ext-link ext-link-type="uri" xlink:href="/url/">b</ext-link> by
909+ itself should be a link.
910+ </p>
911+ <p>
912+ Indented
913+ <ext-link ext-link-type="uri" xlink:href="/url">once</ext-link>.
914+ </p>
915+ <p>
916+ Indented
917+ <ext-link ext-link-type="uri" xlink:href="/url">twice</ext-link>.
918+ </p>
919+ <p>
920+ Indented
921+ <ext-link ext-link-type="uri" xlink:href="/url">thrice</ext-link>.
922+ </p>
923+ <p>
924+ This should [not] be a link.
925+ </p>
926+ <preformat>[not]: /url</preformat>
927+ <p>
928+ Foo
929+ <ext-link ext-link-type="uri" xlink:href="/url/" xlink:title="Title with &quot;quotes&quot; inside">bar</ext-link>.
930+ </p>
931+ <p>
932+ Foo
933+ <ext-link ext-link-type="uri" xlink:href="/url/" xlink:title="Title with &quot;quote&quot; inside">biz</ext-link>.
934+ </p>
935+ </sec>
936+ <sec id="with-ampersands">
937+ <title>With ampersands</title>
938+ <p>
939+ Here's a
940+ <ext-link ext-link-type="uri" xlink:href="http://example.com/?foo=1&amp;bar=2">link
941+ with an ampersand in the URL</ext-link>.
942+ </p>
943+ <p>
944+ Here's a link with an amersand in the link text:
945+ <ext-link ext-link-type="uri" xlink:href="http://att.com/" xlink:title="AT&amp;T">AT&amp;T</ext-link>.
946+ </p>
947+ <p>
948+ Here's an
949+ <ext-link ext-link-type="uri" xlink:href="/script?foo=1&amp;bar=2">inline
950+ link</ext-link>.
951+ </p>
952+ <p>
953+ Here's an
954+ <ext-link ext-link-type="uri" xlink:href="/script?foo=1&amp;bar=2">inline
955+ link in pointy braces</ext-link>.
956+ </p>
957+ </sec>
958+ <sec id="autolinks">
959+ <title>Autolinks</title>
960+ <p>
961+ With an ampersand:
962+ <ext-link ext-link-type="uri" xlink:href="http://example.com/?foo=1&amp;bar=2">http://example.com/?foo=1&amp;bar=2</ext-link>
963+ </p>
964+ <list list-type="bullet">
965+ <list-item>
966+ <p>
967+ In a list?
968+ </p>
969+ </list-item>
970+ <list-item>
971+ <p>
972+ <ext-link ext-link-type="uri" xlink:href="http://example.com/">http://example.com/</ext-link>
973+ </p>
974+ </list-item>
975+ <list-item>
976+ <p>
977+ It should.
978+ </p>
979+ </list-item>
980+ </list>
981+ <p>
982+ An e-mail address: nobody [at] nowhere.net
983+ </p>
984+ <disp-quote>
985+ <p>
986+ Blockquoted:
987+ <ext-link ext-link-type="uri" xlink:href="http://example.com/">http://example.com/</ext-link>
988+ </p>
989+ </disp-quote>
990+ <p>
991+ Auto-links should not occur here:
992+ <monospace>&lt;http://example.com/&gt;</monospace>
993+ </p>
994+ <preformat>or here: &lt;http://example.com/&gt;</preformat>
995+ </sec>
996+</sec>
997+<sec id="images">
998+ <title>Images</title>
999+ <p>
1000+ From &quot;Voyage dans la Lune&quot; by Georges Melies (1902):
1001+ </p>
1002+ <p>
1003+ <inline-graphic mimetype="image" mime-subtype="jpeg" xlink:href="lalune.jpg" xlink:title="Voyage dans la Lune" />
1004+ </p>
1005+ <p>
1006+ Here is a movie
1007+ <inline-graphic mimetype="image" mime-subtype="jpeg" xlink:href="movie.jpg" />
1008+ icon.
1009+ </p>
1010+</sec>
1011+<sec id="footnotes">
1012+ <title>Footnotes</title>
1013+ <p>
1014+ Here is a footnote reference<xref alt="(1)" rid="note_1">(1)</xref>,
1015+ and
1016+ another<xref alt="(longnote)" rid="note_longnote">(longnote)</xref>.
1017+ This should <italic>not</italic> be a footnote reference, because it
1018+ contains a space^(my note).
1019+ </p>
1020+ <p>
1021+ <xref alt="(1)" rid="ref_1">(1)</xref> Here is the footnote. It can
1022+ go anywhere in the document, not just at the end.
1023+ </p>
1024+ <p>
1025+ <xref alt="(longnote)" rid="ref_longnote">(longnote)</xref> Here's
1026+ the other note. This one contains multiple blocks.
1027+ </p>
1028+ <p>
1029+ Caret characters are used to indicate that the blocks all belong to
1030+ a single footnote (as with block quotes).
1031+ </p>
1032+ <preformat> { &lt;code&gt; }</preformat>
1033+ <p>
1034+ If you want, you can use a caret at the beginning of every line, as
1035+ with blockquotes, but all that you need is a caret at the beginning
1036+ of the first line of the block and any preceding blank lines.
1037+ </p>
1038+ <p>
1039+ text <italic>Leading space</italic>
1040+ </p>
1041+ <p>
1042+ <italic>Trailing space</italic> text
1043+ </p>
1044+ <p>
1045+ text <italic>Leading spaces</italic>
1046+ </p>
1047+ <p>
1048+ <italic>Trailing spaces</italic> text
1049+ </p>
1050+</sec>
1051+<sec id="tables">
1052+ <title>Tables</title>
1053+ <sec id="tables-with-headers">
1054+ <title>Tables with Headers</title>
1055+ <table>
1056+ <col align="left" />
1057+ <col align="left" />
1058+ <col align="left" />
1059+ <thead>
1060+ <tr>
1061+ <th>
1062+ <p>
1063+ X
1064+ </p>
1065+ </th>
1066+ <th>
1067+ <p>
1068+ Y
1069+ </p>
1070+ </th>
1071+ <th>
1072+ <p>
1073+ Z
1074+ </p>
1075+ </th>
1076+ </tr>
1077+ </thead>
1078+ <tbody>
1079+ <tr>
1080+ <td>
1081+ <p>
1082+ 1
1083+ </p>
1084+ </td>
1085+ <td>
1086+ <p>
1087+ 2
1088+ </p>
1089+ </td>
1090+ <td>
1091+ <p>
1092+ 3
1093+ </p>
1094+ </td>
1095+ </tr>
1096+ <tr>
1097+ <td>
1098+ <p>
1099+ 4
1100+ </p>
1101+ </td>
1102+ <td>
1103+ <p>
1104+ 5
1105+ </p>
1106+ </td>
1107+ <td>
1108+ <p>
1109+ 6
1110+ </p>
1111+ </td>
1112+ </tr>
1113+ </tbody>
1114+ </table>
1115+ <table>
1116+ <col align="left" />
1117+ <col align="left" />
1118+ <col align="left" />
1119+ <thead>
1120+ <tr>
1121+ <th>
1122+ <p>
1123+ X
1124+ </p>
1125+ </th>
1126+ <th>
1127+ <p>
1128+ Y
1129+ </p>
1130+ </th>
1131+ <th>
1132+ <p>
1133+ Z
1134+ </p>
1135+ </th>
1136+ </tr>
1137+ </thead>
1138+ <tbody>
1139+ <tr>
1140+ <td>
1141+ <p>
1142+ 1
1143+ </p>
1144+ </td>
1145+ <td>
1146+ <p>
1147+ 2
1148+ </p>
1149+ </td>
1150+ <td>
1151+ <p>
1152+ 3
1153+ </p>
1154+ </td>
1155+ </tr>
1156+ <tr>
1157+ <td>
1158+ <p>
1159+ 4
1160+ </p>
1161+ </td>
1162+ <td>
1163+ <p>
1164+ 5
1165+ </p>
1166+ </td>
1167+ <td>
1168+ <p>
1169+ 6
1170+ </p>
1171+ </td>
1172+ </tr>
1173+ </tbody>
1174+ </table>
1175+ <table>
1176+ <col align="left" />
1177+ <col align="left" />
1178+ <col align="left" />
1179+ <thead>
1180+ <tr>
1181+ <th>
1182+ <p>
1183+ X
1184+ </p>
1185+ </th>
1186+ <th>
1187+ <p>
1188+ Y
1189+ </p>
1190+ </th>
1191+ <th>
1192+ <p>
1193+ Z
1194+ </p>
1195+ </th>
1196+ </tr>
1197+ </thead>
1198+ <tbody>
1199+ <tr>
1200+ <td>
1201+ <p>
1202+ 1
1203+ </p>
1204+ </td>
1205+ <td>
1206+ <p>
1207+ 2
1208+ </p>
1209+ </td>
1210+ <td>
1211+ <p>
1212+ 3
1213+ </p>
1214+ </td>
1215+ </tr>
1216+ <tr>
1217+ <td>
1218+ <p>
1219+ 4
1220+ </p>
1221+ </td>
1222+ <td>
1223+ <p>
1224+ 5
1225+ </p>
1226+ </td>
1227+ <td>
1228+ <p>
1229+ 6
1230+ </p>
1231+ </td>
1232+ </tr>
1233+ </tbody>
1234+ </table>
1235+ <table>
1236+ <col align="left" />
1237+ <col align="left" />
1238+ <col align="left" />
1239+ <thead>
1240+ <tr>
1241+ <th>
1242+ <p>
1243+ X
1244+ </p>
1245+ </th>
1246+ <th>
1247+ <p>
1248+ Y
1249+ </p>
1250+ </th>
1251+ <th>
1252+ <p>
1253+ Z
1254+ </p>
1255+ </th>
1256+ </tr>
1257+ </thead>
1258+ <tbody>
1259+ <tr>
1260+ <td>
1261+ <p>
1262+ 1
1263+ </p>
1264+ </td>
1265+ <td>
1266+ <p>
1267+ 2
1268+ </p>
1269+ </td>
1270+ <td>
1271+ <p>
1272+ 3
1273+ </p>
1274+ </td>
1275+ </tr>
1276+ <tr>
1277+ <td>
1278+ <p>
1279+ 4
1280+ </p>
1281+ </td>
1282+ <td>
1283+ <p>
1284+ 5
1285+ </p>
1286+ </td>
1287+ <td>
1288+ <p>
1289+ 6
1290+ </p>
1291+ </td>
1292+ </tr>
1293+ </tbody>
1294+ </table>
1295+ <table>
1296+ <col align="left" />
1297+ <col align="left" />
1298+ <col align="left" />
1299+ <thead>
1300+ <tr>
1301+ <th>
1302+ <p>
1303+ X
1304+ </p>
1305+ </th>
1306+ <th>
1307+ <p>
1308+ Y
1309+ </p>
1310+ </th>
1311+ <th>
1312+ <p>
1313+ Z
1314+ </p>
1315+ </th>
1316+ </tr>
1317+ </thead>
1318+ <tbody>
1319+ <tr>
1320+ <td>
1321+ <p>
1322+ 1
1323+ </p>
1324+ </td>
1325+ <td>
1326+ <p>
1327+ 2
1328+ </p>
1329+ </td>
1330+ <td>
1331+ <p>
1332+ 3
1333+ </p>
1334+ </td>
1335+ </tr>
1336+ <tr>
1337+ <td>
1338+ <p>
1339+ 4
1340+ </p>
1341+ </td>
1342+ <td>
1343+ <p>
1344+ 5
1345+ </p>
1346+ </td>
1347+ <td>
1348+ <p>
1349+ 6
1350+ </p>
1351+ </td>
1352+ </tr>
1353+ </tbody>
1354+ </table>
1355+ <table>
1356+ <col align="left" />
1357+ <col align="left" />
1358+ <col align="left" />
1359+ <thead>
1360+ <tr>
1361+ <th>
1362+ <p>
1363+ X
1364+ </p>
1365+ </th>
1366+ <th>
1367+ <p>
1368+ Y
1369+ </p>
1370+ </th>
1371+ <th>
1372+ <p>
1373+ Z
1374+ </p>
1375+ </th>
1376+ </tr>
1377+ </thead>
1378+ <tbody>
1379+ <tr>
1380+ <td>
1381+ <p>
1382+ 1
1383+ </p>
1384+ </td>
1385+ <td>
1386+ <p>
1387+ 2
1388+ </p>
1389+ </td>
1390+ <td>
1391+ <p>
1392+ 3
1393+ </p>
1394+ </td>
1395+ </tr>
1396+ <tr>
1397+ <td>
1398+ <p>
1399+ 4
1400+ </p>
1401+ </td>
1402+ <td>
1403+ <p>
1404+ 5
1405+ </p>
1406+ </td>
1407+ <td>
1408+ <p>
1409+ 6
1410+ </p>
1411+ </td>
1412+ </tr>
1413+ </tbody>
1414+ </table>
1415+ <table>
1416+ <col align="left" />
1417+ <col align="left" />
1418+ <col align="left" />
1419+ <thead>
1420+ <tr>
1421+ <th>
1422+ <p>
1423+ X
1424+ </p>
1425+ </th>
1426+ <th>
1427+ <p>
1428+ Y
1429+ </p>
1430+ </th>
1431+ <th>
1432+ <p>
1433+ Z
1434+ </p>
1435+ </th>
1436+ </tr>
1437+ </thead>
1438+ <tbody>
1439+ <tr>
1440+ <td>
1441+ <p>
1442+ 1
1443+ </p>
1444+ </td>
1445+ <td>
1446+ <p>
1447+ 2
1448+ </p>
1449+ </td>
1450+ <td>
1451+ <p>
1452+ 3
1453+ </p>
1454+ </td>
1455+ </tr>
1456+ <tr>
1457+ <td>
1458+ <p>
1459+ 4
1460+ </p>
1461+ </td>
1462+ <td>
1463+ <p>
1464+ 5
1465+ </p>
1466+ </td>
1467+ <td>
1468+ <p>
1469+ 6
1470+ </p>
1471+ </td>
1472+ </tr>
1473+ </tbody>
1474+ </table>
1475+ <table>
1476+ <col align="left" />
1477+ <col align="left" />
1478+ <col align="left" />
1479+ <thead>
1480+ <tr>
1481+ <th>
1482+ <p>
1483+ X
1484+ </p>
1485+ </th>
1486+ <th>
1487+ <p>
1488+ Y
1489+ </p>
1490+ </th>
1491+ <th>
1492+ <p>
1493+ Z
1494+ </p>
1495+ </th>
1496+ </tr>
1497+ </thead>
1498+ <tbody>
1499+ <tr>
1500+ <td>
1501+ <p>
1502+ 1
1503+ </p>
1504+ </td>
1505+ <td>
1506+ <p>
1507+ 2
1508+ </p>
1509+ </td>
1510+ <td>
1511+ <p>
1512+ 3
1513+ </p>
1514+ </td>
1515+ </tr>
1516+ <tr>
1517+ <td>
1518+ <p>
1519+ 4
1520+ </p>
1521+ </td>
1522+ <td>
1523+ <p>
1524+ 5
1525+ </p>
1526+ </td>
1527+ <td>
1528+ <p>
1529+ 6
1530+ </p>
1531+ </td>
1532+ </tr>
1533+ </tbody>
1534+ </table>
1535+ <table>
1536+ <col width="33*" align="left" />
1537+ <col width="33*" align="left" />
1538+ <col width="33*" align="left" />
1539+ <thead>
1540+ <tr>
1541+ <th>
1542+ <p>
1543+ X
1544+ </p>
1545+ </th>
1546+ <th>
1547+ <p>
1548+ Y
1549+ </p>
1550+ </th>
1551+ <th>
1552+ <p>
1553+ Z
1554+ </p>
1555+ </th>
1556+ </tr>
1557+ </thead>
1558+ <tbody>
1559+ <tr>
1560+ <td>
1561+ <p>
1562+ 1
1563+ </p>
1564+ </td>
1565+ <td>
1566+ <p>
1567+ 2
1568+ </p>
1569+ </td>
1570+ <td>
1571+ <p>
1572+ 3
1573+ </p>
1574+ </td>
1575+ </tr>
1576+ <tr>
1577+ <td>
1578+ <p>
1579+ 4
1580+ </p>
1581+ </td>
1582+ <td>
1583+ <p>
1584+ 5
1585+ </p>
1586+ </td>
1587+ <td>
1588+ <p>
1589+ 6
1590+ </p>
1591+ </td>
1592+ </tr>
1593+ </tbody>
1594+ </table>
1595+ </sec>
1596+ <sec id="tables-without-headers">
1597+ <title>Tables without Headers</title>
1598+ <table>
1599+ <col align="left" />
1600+ <col align="left" />
1601+ <col align="left" />
1602+ <tbody>
1603+ <tr>
1604+ <td>
1605+ <p>
1606+ 1
1607+ </p>
1608+ </td>
1609+ <td>
1610+ <p>
1611+ 2
1612+ </p>
1613+ </td>
1614+ <td>
1615+ <p>
1616+ 3
1617+ </p>
1618+ </td>
1619+ </tr>
1620+ <tr>
1621+ <td>
1622+ <p>
1623+ 4
1624+ </p>
1625+ </td>
1626+ <td>
1627+ <p>
1628+ 5
1629+ </p>
1630+ </td>
1631+ <td>
1632+ <p>
1633+ 6
1634+ </p>
1635+ </td>
1636+ </tr>
1637+ </tbody>
1638+ </table>
1639+ <table>
1640+ <col align="left" />
1641+ <col align="left" />
1642+ <col align="left" />
1643+ <tbody>
1644+ <tr>
1645+ <td>
1646+ <p>
1647+ 1
1648+ </p>
1649+ </td>
1650+ <td>
1651+ <p>
1652+ 2
1653+ </p>
1654+ </td>
1655+ <td>
1656+ <p>
1657+ 3
1658+ </p>
1659+ </td>
1660+ </tr>
1661+ <tr>
1662+ <td>
1663+ <p>
1664+ 4
1665+ </p>
1666+ </td>
1667+ <td>
1668+ <p>
1669+ 5
1670+ </p>
1671+ </td>
1672+ <td>
1673+ <p>
1674+ 6
1675+ </p>
1676+ </td>
1677+ </tr>
1678+ </tbody>
1679+ </table>
1680+ <table>
1681+ <col align="left" />
1682+ <col align="left" />
1683+ <col align="left" />
1684+ <tbody>
1685+ <tr>
1686+ <td>
1687+ <p>
1688+ 1
1689+ </p>
1690+ </td>
1691+ <td>
1692+ <p>
1693+ 2
1694+ </p>
1695+ </td>
1696+ <td>
1697+ <p>
1698+ 3
1699+ </p>
1700+ </td>
1701+ </tr>
1702+ <tr>
1703+ <td>
1704+ <p>
1705+ 4
1706+ </p>
1707+ </td>
1708+ <td>
1709+ <p>
1710+ 5
1711+ </p>
1712+ </td>
1713+ <td>
1714+ <p>
1715+ 6
1716+ </p>
1717+ </td>
1718+ </tr>
1719+ </tbody>
1720+ </table>
1721+ <table>
1722+ <col align="left" />
1723+ <col align="left" />
1724+ <col align="left" />
1725+ <tbody>
1726+ <tr>
1727+ <td>
1728+ <p>
1729+ 1
1730+ </p>
1731+ </td>
1732+ <td>
1733+ <p>
1734+ 2
1735+ </p>
1736+ </td>
1737+ <td>
1738+ <p>
1739+ 3
1740+ </p>
1741+ </td>
1742+ </tr>
1743+ <tr>
1744+ <td>
1745+ <p>
1746+ 4
1747+ </p>
1748+ </td>
1749+ <td>
1750+ <p>
1751+ 5
1752+ </p>
1753+ </td>
1754+ <td>
1755+ <p>
1756+ 6
1757+ </p>
1758+ </td>
1759+ </tr>
1760+ </tbody>
1761+ </table>
1762+ </sec>
1763+ <sec id="empty-tables">
1764+ <title>Empty Tables</title>
1765+ <p>
1766+ This section should be empty.
1767+ </p>
1768+ </sec>
1769+</sec>
1770+</body>
1771+<back>
1772+</back>
1773+</article>
test/test-pandoc.hs+2
@@ -11,6 +11,7 @@ import qualified Tests.Readers.Creole
1111import qualified Tests.Readers.Docx
1212import qualified Tests.Readers.EPUB
1313import qualified Tests.Readers.HTML
14+import qualified Tests.Readers.JATS
1415import qualified Tests.Readers.LaTeX
1516import qualified Tests.Readers.Markdown
1617import qualified Tests.Readers.Muse
@@ -61,6 +62,7 @@ tests = testGroup "pandoc tests" [ Tests.Command.tests
6162 [ testGroup "LaTeX" Tests.Readers.LaTeX.tests
6263 , testGroup "Markdown" Tests.Readers.Markdown.tests
6364 , testGroup "HTML" Tests.Readers.HTML.tests
65+ , testGroup "JATS" Tests.Readers.JATS.tests
6466 , testGroup "Org" Tests.Readers.Org.tests
6567 , testGroup "RST" Tests.Readers.RST.tests
6668 , testGroup "Docx" Tests.Readers.Docx.tests