git.iko.soy/typeable/pandoc
on master help sign in
Add Muse writer (#3489)

* Add Muse writer * Advertise new Muse writer * Muse writer: add regressions tests

commitd037c5019d51b9fc64690f5e73158c1dd683012b authorAlexander Krotov <ilabdsf@gmail.com> dateFri 10 Mar 2017, 13:16 (10 years ago) parentebb2acb
12 files changed+1489−3
README.md+2−1 data/templates/default.muse+44 deb/control.in+1−1 pandoc.cabal+6−1 src/Text/Pandoc.hs+3 src/Text/Pandoc/Writers/Muse.hs+336 test/Tests/Old.hs+3 test/Tests/Writers/Muse.hs+273 test/tables.muse+46 test/test-pandoc.hs+2 test/writer.muse+772 trypandoc/index.html+1
README.md+2−1
@@ -26,7 +26,7 @@ write plain text, [Markdown], [CommonMark], [PHP Markdown Extra],
2626[DocBook], [OpenDocument], [ODT], [Word docx], [GNU Texinfo], [MediaWiki
2727markup], [DokuWiki markup], [ZimWiki markup], [Haddock markup],
2828[EPUB] \(v2 or v3\), [FictionBook2], [Textile], [groff man] pages,
29−[Emacs Org mode], [AsciiDoc], [InDesign ICML], [TEI Simple], and [Slidy],
29+[Emacs Org mode], [AsciiDoc], [InDesign ICML], [TEI Simple], [Muse], and [Slidy],
3030[Slideous], [DZSlides], [reveal.js] or [S5] HTML slide shows. It can also
3131produce [PDF] output on systems where LaTeX, ConTeXt, or `wkhtmltopdf` is
3232installed.
@@ -97,6 +97,7 @@ Markdown can be expected to be lossy.
9797[FictionBook2]: http://www.fictionbook.org/index.php/Eng:XML_Schema_Fictionbook_2.1
9898[InDesign ICML]: https://www.adobe.com/content/dam/Adobe/en/devnet/indesign/cs55-docs/IDML/idml-specification.pdf
9999[TEI Simple]: https://github.com/TEIC/TEI-Simple
100+[Muse]: https://amusewiki.org/library/manual
100101
101102
102103
data/templates/default.musenew file+44
@@ -0,0 +1,44 @@
1+$if(author)$
2+#author $author$
3+$endif$
4+$if(title)$
5+#title $title$
6+$endif$
7+$if(lang)$
8+#lang $lang$
9+$endif$
10+$if(LISTtitle)$
11+#LISTtitle $LISTtitle$
12+$endif$
13+$if(subtitle)$
14+#subtitle $subtitle$
15+$endif$
16+$if(SORTauthors)$
17+#SORTauthors $SORTauthors$
18+$endif$
19+$if(SORTtopics)$
20+#SORTtopics $SORTtopics$
21+$endif$
22+$if(date)$
23+#date $date$
24+$endif$
25+$if(notes)$
26+#notes $notes$
27+$endif$
28+$if(source)$
29+#source $source$
30+$endif$
31+
32+$for(header-includes)$
33+$header-includes$
34+
35+$endfor$
36+$for(include-before)$
37+$include-before$
38+
39+$endfor$
40+$body$
41+$for(include-after)$
42+
43+$include-after$
44+$endfor$
deb/control.in+1−1
@@ -16,5 +16,5 @@ Description: general markup converter
1616 Docbook, OPML, OpenDocument, ODT, Word docx, RTF, MediaWiki,
1717 DokuWiki, Textile, groff man pages, plain text, Emacs Org-Mode,
1818 AsciiDoc, Haddock markup, EPUB (v2 and v3), FictionBook2,
19− InDesign ICML, and several kinds of HTML/javascript
19+ InDesign ICML, Muse, and several kinds of HTML/javascript
2020 slide shows (S5, Slidy, Slideous, DZSlides, reveal.js).
pandoc.cabal+6−1
@@ -24,7 +24,7 @@ Description: Pandoc is a Haskell library for converting from one markup
2424 Word docx, RTF, MediaWiki, DokuWiki, ZimWiki, Textile,
2525 groff man pages, plain text, Emacs Org-Mode, AsciiDoc,
2626 Haddock markup, EPUB (v2 and v3), FictionBook2, InDesign ICML,
27− and several kinds of HTML/javascript slide shows (S5, Slidy,
27+ Muse, and several kinds of HTML/javascript slide shows (S5, Slidy,
2828 Slideous, DZSlides, reveal.js).
2929 .
3030 In contrast to most existing tools for converting Markdown
@@ -50,6 +50,7 @@ Data-Files:
5050 data/templates/default.texinfo
5151 data/templates/default.man
5252 data/templates/default.markdown
53+ data/templates/default.muse
5354 data/templates/default.commonmark
5455 data/templates/default.rst
5556 data/templates/default.plain
@@ -169,6 +170,7 @@ Extra-Source-Files:
169170 test/tables.rtf
170171 test/tables.txt
171172 test/tables.fb2
173+ test/tables.muse
172174 test/testsuite.txt
173175 test/writer.latex
174176 test/writer.context
@@ -194,6 +196,7 @@ Extra-Source-Files:
194196 test/writer.opml
195197 test/writer.dokuwiki
196198 test/writer.zimwiki
199+ test/writer.muse
197200 test/writers-lang-and-dir.latex
198201 test/writers-lang-and-dir.context
199202 test/dokuwiki_inline_formatting.dokuwiki
@@ -389,6 +392,7 @@ Library
389392 Text.Pandoc.Writers.EPUB,
390393 Text.Pandoc.Writers.FB2,
391394 Text.Pandoc.Writers.TEI,
395+ Text.Pandoc.Writers.Muse,
392396 Text.Pandoc.Writers.Math,
393397 Text.Pandoc.Writers.Shared,
394398 Text.Pandoc.PDF,
@@ -540,6 +544,7 @@ Test-Suite test-pandoc
540544 Tests.Writers.Docx
541545 Tests.Writers.RST
542546 Tests.Writers.TEI
547+ Tests.Writers.Muse
543548 Ghc-Options: -rtsopts -Wall -fno-warn-unused-do-bind -threaded
544549 Default-Language: Haskell98
545550
src/Text/Pandoc.hs+3
@@ -136,6 +136,7 @@ module Text.Pandoc
136136 , writeCommonMark
137137 , writeCustom
138138 , writeTEI
139+ , writeMuse
139140 -- * Rendering templates and default templates
140141 , module Text.Pandoc.Templates
141142 -- * Miscellaneous
@@ -191,6 +192,7 @@ import Text.Pandoc.Writers.LaTeX
191192import Text.Pandoc.Writers.Man
192193import Text.Pandoc.Writers.Markdown
193194import Text.Pandoc.Writers.MediaWiki
195+import Text.Pandoc.Writers.Muse
194196import Text.Pandoc.Writers.Native
195197import Text.Pandoc.Writers.ODT
196198import Text.Pandoc.Writers.OpenDocument
@@ -307,6 +309,7 @@ writers = [
307309 ,("haddock" , StringWriter writeHaddock)
308310 ,("commonmark" , StringWriter writeCommonMark)
309311 ,("tei" , StringWriter writeTEI)
312+ ,("muse" , StringWriter writeMuse)
310313 ]
311314
312315getDefaultExtensions :: String -> Extensions
src/Text/Pandoc/Writers/Muse.hsnew file+336
@@ -0,0 +1,336 @@
1+{-# LANGUAGE OverloadedStrings #-}
2+{-
3+Copyright (C) 2017 Alexander Krotov <ilabdsf@gmail.com>
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.Muse
22+ Copyright : Copyright (C) 2017 Alexander Krotov
23+ License : GNU GPL, version 2 or above
24+
25+ Maintainer : Alexander Krotov <ilabdsf@gmail.com>
26+ Stability : stable
27+ Portability : portable
28+
29+Conversion of 'Pandoc' documents to Muse.
30+
31+This module is mostly intended for <https://amusewiki.org/ Amusewiki> markup support,
32+as described by <https://amusewiki.org/library/manual Text::Amuse markup manual>.
33+Original <https://www.gnu.org/software/emacs-muse/ Emacs Muse> markup support
34+is a secondary goal.
35+
36+Where Text::Amuse markup
37+<https://metacpan.org/pod/Text::Amuse#DIFFERENCES-WITH-THE-ORIGINAL-EMACS-MUSE-MARKUP differs>
38+from <https://www.gnu.org/software/emacs-muse/manual/ Emacs Muse markup>,
39+Text::Amuse markup is supported.
40+For example, native tables are always used instead of Org Mode tables.
41+However, @\<literal style="html">@ tag is used for HTML raw blocks
42+even though it is supported only in Emacs Muse.
43+-}
44+module Text.Pandoc.Writers.Muse (writeMuse) where
45+import Control.Monad.State
46+import Data.List (intersperse, transpose, isInfixOf)
47+import System.FilePath (takeExtension)
48+import Text.Pandoc.Class (PandocMonad)
49+import Text.Pandoc.Definition
50+import Text.Pandoc.Options
51+import Text.Pandoc.Pretty
52+import Text.Pandoc.Shared
53+import Text.Pandoc.Templates (renderTemplate')
54+import Text.Pandoc.Writers.Math
55+import Text.Pandoc.Writers.Shared
56+
57+type Notes = [[Block]]
58+data WriterState =
59+ WriterState { stNotes :: Notes
60+ , stOptions :: WriterOptions
61+ , stTopLevel :: Bool
62+ , stInsideBlock :: Bool
63+ }
64+
65+-- | Convert Pandoc to Muse.
66+writeMuse :: PandocMonad m
67+ => WriterOptions
68+ -> Pandoc
69+ -> m String
70+writeMuse opts document =
71+ let st = WriterState { stNotes = []
72+ , stOptions = opts
73+ , stTopLevel = True
74+ , stInsideBlock = False
75+ }
76+ in evalStateT (pandocToMuse document) st
77+
78+-- | Return Muse representation of document.
79+pandocToMuse :: PandocMonad m
80+ => Pandoc
81+ -> StateT WriterState m String
82+pandocToMuse (Pandoc meta blocks) = do
83+ opts <- gets stOptions
84+ let colwidth = if writerWrapText opts == WrapAuto
85+ then Just $ writerColumns opts
86+ else Nothing
87+ metadata <- metaToJSON opts
88+ (fmap (render colwidth) . blockListToMuse)
89+ (fmap (render colwidth) . inlineListToMuse)
90+ meta
91+ body <- blockListToMuse blocks
92+ notes <- liftM (reverse . stNotes) get >>= notesToMuse
93+ let main = render colwidth $ body $+$ notes
94+ let context = defField "body" main
95+ $ metadata
96+ case writerTemplate opts of
97+ Nothing -> return main
98+ Just tpl -> return $ renderTemplate' tpl context
99+
100+-- | Convert list of Pandoc block elements to Muse.
101+blockListToMuse :: PandocMonad m
102+ => [Block] -- ^ List of block elements
103+ -> StateT WriterState m Doc
104+blockListToMuse blocks = do
105+ oldState <- get
106+ modify $ \s -> s { stTopLevel = not $ stInsideBlock s
107+ , stInsideBlock = True
108+ }
109+ contents <- mapM blockToMuse blocks
110+ modify $ \s -> s { stTopLevel = stTopLevel oldState
111+ , stInsideBlock = stInsideBlock oldState
112+ }
113+ return $ cat contents
114+
115+-- | Convert Pandoc block element to Muse.
116+blockToMuse :: PandocMonad m
117+ => Block -- ^ Block element
118+ -> StateT WriterState m Doc
119+blockToMuse (Plain inlines) = inlineListToMuse inlines
120+blockToMuse (Para inlines) = do
121+ contents <- inlineListToMuse inlines
122+ return $ contents <> blankline
123+blockToMuse (LineBlock lns) = do
124+ let splitStanza [] = []
125+ splitStanza xs = case break (== mempty) xs of
126+ (l, []) -> l : []
127+ (l, _:r) -> l : splitStanza r
128+ let joinWithLinefeeds = nowrap . mconcat . intersperse cr
129+ let joinWithBlankLines = mconcat . intersperse blankline
130+ let prettyfyStanza ls = joinWithLinefeeds <$> mapM inlineListToMuse ls
131+ contents <- joinWithBlankLines <$> mapM prettyfyStanza (splitStanza lns)
132+ return $ blankline $$ "<verse>" $$ contents $$ "</verse>" <> blankline
133+blockToMuse (CodeBlock (_,_,_) str) = do
134+ return $ "<example>" $$ text str $$ "</example>" $$ blankline
135+blockToMuse (RawBlock (Format format) str) =
136+ return $ blankline $$ "<literal style=\"" <> text format <> "\">" $$
137+ text str $$ "</literal>" $$ blankline
138+blockToMuse (BlockQuote blocks) = do
139+ contents <- blockListToMuse blocks
140+ return $ blankline
141+ <> "<quote>"
142+ $$ flush contents -- flush to drop blanklines
143+ $$ "</quote>"
144+ <> blankline
145+blockToMuse (OrderedList (start, style, _) items) = do
146+ let markers = take (length items) $ orderedListMarkers
147+ (start, style, Period)
148+ let maxMarkerLength = maximum $ map length markers
149+ let markers' = map (\m -> let s = maxMarkerLength - length m
150+ in m ++ replicate s ' ') markers
151+ contents <- mapM (\(item, num) -> orderedListItemToMuse item num) $
152+ zip markers' items
153+ -- ensure that sublists have preceding blank line
154+ topLevel <- gets stTopLevel
155+ return $ cr $$ ((if topLevel then nest 1 else id) $ vcat contents) $$ blankline
156+ where orderedListItemToMuse :: PandocMonad m
157+ => String -- ^ marker for list item
158+ -> [Block] -- ^ list item (list of blocks)
159+ -> StateT WriterState m Doc
160+ orderedListItemToMuse marker item = do
161+ contents <- blockListToMuse item
162+ return $ hang (length marker + 1) (text marker <> space) contents
163+blockToMuse (BulletList items) = do
164+ contents <- mapM bulletListItemToMuse items
165+ -- ensure that sublists have preceding blank line
166+ topLevel <- gets stTopLevel
167+ return $ cr $$ ((if topLevel then nest 1 else id) $ vcat contents) $$ blankline
168+ where bulletListItemToMuse :: PandocMonad m
169+ => [Block]
170+ -> StateT WriterState m Doc
171+ bulletListItemToMuse item = do
172+ contents <- blockListToMuse item
173+ return $ hang 2 "- " contents
174+blockToMuse (DefinitionList items) = do
175+ contents <- mapM definitionListItemToMuse items
176+ return $ cr $$ (nest 1 $ vcat $ contents) $$ blankline
177+ where definitionListItemToMuse :: PandocMonad m
178+ => ([Inline], [[Block]])
179+ -> StateT WriterState m Doc
180+ definitionListItemToMuse (label, defs) = do
181+ label' <- inlineListToMuse label
182+ contents <- liftM vcat $ mapM blockListToMuse defs
183+ let label'' = label' <> " :: "
184+ let ind = offset label''
185+ return $ hang ind label'' contents
186+blockToMuse (Header level (ident,_,_) inlines) = do
187+ contents <- inlineListToMuse inlines
188+ let attr' = if null ident
189+ then empty
190+ else "#" <> text ident <> cr
191+ let header' = text $ replicate level '*'
192+ return $ blankline <> nowrap (header' <> space <> contents)
193+ <> blankline <> attr'
194+-- https://www.gnu.org/software/emacs-muse/manual/muse.html#Horizontal-Rules-and-Anchors
195+blockToMuse HorizontalRule = return $ blankline $$ "----" $$ blankline
196+blockToMuse (Table caption _ _ headers rows) = do
197+ caption' <- inlineListToMuse caption
198+ headers' <- mapM blockListToMuse headers
199+ rows' <- mapM (mapM blockListToMuse) rows
200+ let noHeaders = all null headers
201+
202+ let numChars = maximum . map offset
203+ -- FIXME: width is not being used.
204+ let widthsInChars =
205+ map numChars $ transpose (headers' : rows')
206+ -- FIXME: Muse doesn't allow blocks with height more than 1.
207+ let hpipeBlocks sep blocks = hcat $ intersperse sep' blocks
208+ where h = maximum (1 : map height blocks)
209+ sep' = lblock (length sep) $ vcat (map text $ replicate h sep)
210+ let makeRow sep = hpipeBlocks sep . zipWith lblock widthsInChars
211+ let head' = makeRow " || " headers'
212+ let rowSeparator = if noHeaders then " | " else " | "
213+ rows'' <- mapM (\row -> do cols <- mapM blockListToMuse row
214+ return $ makeRow rowSeparator cols) rows
215+ let body = vcat rows''
216+ return $ (if noHeaders then empty else head')
217+ $$ body
218+ $$ (if null caption then empty else "|+ " <> caption' <> " +|")
219+ $$ blankline
220+blockToMuse (Div _ bs) = blockListToMuse bs
221+blockToMuse Null = return empty
222+
223+-- | Return Muse representation of notes.
224+notesToMuse :: PandocMonad m
225+ => Notes
226+ -> StateT WriterState m Doc
227+notesToMuse notes =
228+ mapM (\(num, note) -> noteToMuse num note) (zip [1..] notes) >>=
229+ return . vsep
230+
231+-- | Return Muse representation of a note.
232+noteToMuse :: PandocMonad m
233+ => Int
234+ -> [Block]
235+ -> StateT WriterState m Doc
236+noteToMuse num note = do
237+ contents <- blockListToMuse note
238+ let marker = "[" ++ show num ++ "] "
239+ return $ hang (length marker) (text marker) contents
240+
241+-- | Escape special characters for Muse.
242+escapeString :: String -> String
243+escapeString s =
244+ "<verbatim>" ++
245+ substitute "</verbatim>" "<</verbatim><verbatim>/verbatim>" s ++
246+ "</verbatim>"
247+
248+-- | Escape special characters for Muse if needed.
249+conditionalEscapeString :: String -> String
250+conditionalEscapeString s
251+ | any (`elem` ("*<=>[]|" :: String)) s ||
252+ "::" `isInfixOf` s = escapeString s
253+ | otherwise = s
254+
255+-- | Convert list of Pandoc inline elements to Muse.
256+inlineListToMuse :: PandocMonad m
257+ => [Inline]
258+ -> StateT WriterState m Doc
259+inlineListToMuse lst = mapM inlineToMuse lst >>= return . hcat
260+
261+-- | Convert Pandoc inline element to Muse.
262+inlineToMuse :: PandocMonad m
263+ => Inline
264+ -> StateT WriterState m Doc
265+inlineToMuse (Str str) = return $ text $ conditionalEscapeString str
266+inlineToMuse (Emph lst) = do
267+ contents <- inlineListToMuse lst
268+ return $ "<em>" <> contents <> "</em>"
269+inlineToMuse (Strong lst) = do
270+ contents <- inlineListToMuse lst
271+ return $ "<strong>" <> contents <> "</strong>"
272+inlineToMuse (Strikeout lst) = do
273+ contents <- inlineListToMuse lst
274+ return $ "<del>" <> contents <> "</del>"
275+inlineToMuse (Superscript lst) = do
276+ contents <- inlineListToMuse lst
277+ return $ "<sup>" <> contents <> "</sup>"
278+inlineToMuse (Subscript lst) = do
279+ contents <- inlineListToMuse lst
280+ return $ "<sub>" <> contents <> "</sub>"
281+inlineToMuse (SmallCaps lst) = inlineListToMuse lst
282+inlineToMuse (Quoted SingleQuote lst) = do
283+ contents <- inlineListToMuse lst
284+ return $ "'" <> contents <> "'"
285+inlineToMuse (Quoted DoubleQuote lst) = do
286+ contents <- inlineListToMuse lst
287+ return $ "\"" <> contents <> "\""
288+-- Amusewiki does not support <cite> tag,
289+-- and Emacs Muse citation support is limited
290+-- (https://www.gnu.org/software/emacs-muse/manual/html_node/Citations.html#Citation)
291+-- so just fallback to expanding inlines.
292+inlineToMuse (Cite _ lst) = inlineListToMuse lst
293+inlineToMuse (Code _ str) = return $
294+ "<code>" <> text (conditionalEscapeString str) <> "</code>"
295+inlineToMuse (Math InlineMath str) =
296+ lift (texMathToInlines InlineMath str) >>= inlineListToMuse
297+inlineToMuse (Math DisplayMath str) = do
298+ contents <- lift (texMathToInlines DisplayMath str) >>= inlineListToMuse
299+ return $ "<verse>" <> contents <> "</verse>" <> blankline
300+inlineToMuse (RawInline (Format f) str) =
301+ return $ "<literal style=\"" <> text f <> "\">" <> text str <> "</literal>"
302+inlineToMuse LineBreak = return $ "<br>" <> cr
303+inlineToMuse Space = return space
304+inlineToMuse SoftBreak = do
305+ wrapText <- gets $ writerWrapText . stOptions
306+ return $ if wrapText == WrapPreserve then cr else space
307+inlineToMuse (Link _ txt (src, _)) = do
308+ case txt of
309+ [Str x] | escapeURI x == src ->
310+ return $ "[[" <> text (escapeLink x) <> "]]"
311+ _ -> do contents <- inlineListToMuse txt
312+ return $ "[[" <> text (escapeLink src) <> "][" <> contents <> "]]"
313+ where escapeLink lnk = escapeURI (if isImageUrl lnk then "URL:" ++ lnk else lnk)
314+ -- Taken from muse-image-regexp defined in Emacs Muse file lisp/muse-regexps.el
315+ imageExtensions = [".eps", ".gif", ".jpg", ".jpeg", ".pbm", ".png", ".tiff", ".xbm", ".xpm"]
316+ isImageUrl = (`elem` imageExtensions) . takeExtension
317+inlineToMuse (Image attr alt (source,'f':'i':'g':':':title)) =
318+ inlineToMuse (Image attr alt (source,title))
319+inlineToMuse (Image _ inlines (source, title)) = do
320+ alt <- inlineListToMuse inlines
321+ let title' = if null title
322+ then if null inlines
323+ then ""
324+ else "[" <> alt <> "]"
325+ else "[" <> text title <> "]"
326+ return $ "[[" <> text source <> "]" <> title' <> "]"
327+inlineToMuse (Note contents) = do
328+ -- add to notes in state
329+ notes <- gets stNotes
330+ modify $ \st -> st { stNotes = contents:notes }
331+ let ref = show $ (length notes) + 1
332+ return $ "[" <> text ref <> "]"
333+inlineToMuse (Span (_,name:_,_) inlines) = do
334+ contents <- inlineListToMuse inlines
335+ return $ "<class name=\"" <> text name <> "\">" <> contents <> "</class>"
336+inlineToMuse (Span _ lst) = inlineListToMuse lst
test/Tests/Old.hs+3
@@ -142,6 +142,9 @@ tests = [ testGroup "markdown"
142142 , test "context" ["-f", "native", "-t", "context", "-s"]
143143 "writers-lang-and-dir.native" "writers-lang-and-dir.context"
144144 ]
145+ , testGroup "muse"
146+ [ testGroup "writer" $ writerTests "muse"
147+ ]
145148 ]
146149
147150-- makes sure file is fully closed after reading
test/Tests/Writers/Muse.hsnew file+273
@@ -0,0 +1,273 @@
1+module Tests.Writers.Muse (tests) where
2+
3+import Test.Framework
4+import Tests.Helpers
5+import Text.Pandoc
6+import Text.Pandoc.Arbitrary()
7+import Text.Pandoc.Builder
8+
9+muse :: (ToPandoc a) => a -> String
10+muse = museWithOpts def{ writerWrapText = WrapNone }
11+
12+museWithOpts :: (ToPandoc a) => WriterOptions -> a -> String
13+museWithOpts opts = purely (writeMuse opts) . toPandoc
14+
15+infix 4 =:
16+(=:) :: (ToString a, ToPandoc a)
17+ => String -> (a, String) -> Test
18+(=:) = test muse
19+
20+tests :: [Test]
21+tests = [ testGroup "block elements"
22+ [ "plain" =: plain (text "Foo bar.") =?> "Foo bar."
23+ , testGroup "paragraphs"
24+ [ "single paragraph" =: para (text "Sample paragraph.")
25+ =?> "Sample paragraph."
26+ , "two paragraphs" =: para (text "First paragraph.") <>
27+ para (text "Second paragraph.")
28+ =?> unlines [ "First paragraph."
29+ , ""
30+ , "Second paragraph."
31+ ]
32+ ]
33+ , "line block" =: lineBlock ([text "Foo", text "bar", text "baz"])
34+ =?> unlines [ "<verse>"
35+ , "Foo"
36+ , "bar"
37+ , "baz"
38+ , "</verse>"
39+ ]
40+ , "code block" =: codeBlock ("int main(void) {\n\treturn 0;\n}")
41+ =?> unlines [ "<example>"
42+ , "int main(void) {"
43+ , "\treturn 0;"
44+ , "}"
45+ , "</example>"
46+ ]
47+ , "html raw block" =: rawBlock "html" "<hr>"
48+ =?> unlines [ "<literal style=\"html\">"
49+ , "<hr>"
50+ , "</literal>"
51+ ]
52+ , "block quote" =: blockQuote (para (text "Foo"))
53+ =?> unlines [ "<quote>"
54+ , "Foo"
55+ , "</quote>"
56+ ]
57+ , testGroup "lists"
58+ [ testGroup "simple lists"
59+ [
60+ "ordered list" =: orderedList [ plain $ text "first"
61+ , plain $ text "second"
62+ , plain $ text "third"
63+ ]
64+ =?> unlines [ " 1. first"
65+ , " 2. second"
66+ , " 3. third"
67+ ]
68+ , "ordered list with Roman numerals"
69+ =: orderedListWith (1, UpperRoman, DefaultDelim)
70+ [ plain $ text "first"
71+ , plain $ text "second"
72+ , plain $ text "third"
73+ ]
74+ =?> unlines [ " I. first"
75+ , " II. second"
76+ , " III. third"
77+ ]
78+ , "bullet list" =: bulletList [ plain $ text "first"
79+ , plain $ text "second"
80+ , plain $ text "third"
81+ ]
82+ =?> unlines [ " - first"
83+ , " - second"
84+ , " - third"
85+ ]
86+ , "definition list" =: definitionList [ (text "first definition", [plain $ text "first description"])
87+ , (text "second definition", [plain $ text "second description"])
88+ , (text "third definition", [plain $ text "third description"])
89+ ]
90+ =?> unlines [ " first definition :: first description"
91+ , " second definition :: second description"
92+ , " third definition :: third description"
93+ ]
94+ ]
95+ , testGroup "nested lists"
96+ [ "nested ordered list" =: orderedList [ plain $ text "First outer"
97+ , plain (text "Second outer:") <>
98+ orderedList [ plain $ text "first"
99+ , plain $ text "second"
100+ ]
101+ , plain $ text "Third outer"
102+ ]
103+ =?> unlines [ " 1. First outer"
104+ , " 2. Second outer:"
105+ , " 1. first"
106+ , " 2. second"
107+ , " 3. Third outer"
108+ ]
109+ , "nested bullet lists" =: bulletList [ plain $ text "First outer"
110+ , plain (text "Second outer:") <>
111+ bulletList [ plain $ text "first"
112+ , plain $ text "second"
113+ ]
114+ , plain $ text "Third outer"
115+ ]
116+ =?> unlines [ " - First outer"
117+ , " - Second outer:"
118+ , " - first"
119+ , " - second"
120+ , " - Third outer"
121+ ]
122+ , "nested definition lists" =: definitionList [ (text "first definition", [plain $ text "first description"])
123+ , (text "second definition",
124+ [ plain (text "second description")
125+ , definitionList [ ( text "first inner definition"
126+ , [plain $ text "first inner description"])
127+ , ( text "second inner definition"
128+ , [plain $ text "second inner description"])
129+ ]
130+ ]
131+ )
132+ ]
133+ =?> unlines [ " first definition :: first description"
134+ , " second definition :: second description"
135+ , " first inner definition :: first inner description"
136+ , " second inner definition :: second inner description"
137+ ]
138+ ]
139+ ]
140+ , testGroup "headings"
141+ [ "normal heading" =:
142+ header 1 (text "foo") =?> "* foo"
143+ , "heading levels" =:
144+ header 1 (text "First level") <>
145+ header 3 (text "Third level") =?>
146+ unlines [ "* First level"
147+ , ""
148+ , "*** Third level"
149+ ]
150+ ]
151+ , "horizontal rule" =: horizontalRule =?> "----"
152+ , testGroup "tables"
153+ [ "table without header" =:
154+ let rows = [[para $ text "Para 1.1", para $ text "Para 1.2"]
155+ ,[para $ text "Para 2.1", para $ text "Para 2.2"]]
156+ in simpleTable [] rows
157+ =?>
158+ unlines [ "Para 1.1 | Para 1.2"
159+ , "Para 2.1 | Para 2.2"
160+ ]
161+ , "table with header" =:
162+ let headers = [plain $ text "header 1", plain $ text "header 2"]
163+ rows = [[para $ text "Para 1.1", para $ text "Para 1.2"]
164+ ,[para $ text "Para 2.1", para $ text "Para 2.2"]]
165+ in simpleTable headers rows
166+ =?>
167+ unlines [ "header 1 || header 2"
168+ , "Para 1.1 | Para 1.2"
169+ , "Para 2.1 | Para 2.2"
170+ ]
171+ , "table with header and caption" =:
172+ let caption = text "Table 1"
173+ headers = [plain $ text "header 1", plain $ text "header 2"]
174+ rows = [[para $ text "Para 1.1", para $ text "Para 1.2"]
175+ ,[para $ text "Para 2.1", para $ text "Para 2.2"]]
176+ in table caption mempty headers rows
177+ =?> unlines [ "header 1 || header 2"
178+ , "Para 1.1 | Para 1.2"
179+ , "Para 2.1 | Para 2.2"
180+ , "|+ Table 1 +|"
181+ ]
182+ ]
183+ -- Div is trivial
184+ -- Null is trivial
185+ ]
186+ , testGroup "inline elements"
187+ [ testGroup "string"
188+ [ "string" =: str "foo" =?> "foo"
189+ , "escape footnote" =: str "[1]" =?> "<verbatim>[1]</verbatim>"
190+ , "escape verbatim close tag" =: str "foo</verbatim>bar"
191+ =?> "<verbatim>foo<</verbatim><verbatim>/verbatim>bar</verbatim>"
192+ , "escape pipe to avoid accidental tables" =: str "foo | bar"
193+ =?> "<verbatim>foo | bar</verbatim>"
194+ , "escape definition list markers" =: str "::" =?> "<verbatim>::</verbatim>"
195+ -- We don't want colons to be escaped if they can't be confused
196+ -- with definition list item markers.
197+ , "do not escape colon" =: str ":" =?> ":"
198+ ]
199+ , testGroup "emphasis"
200+ [ "emph" =: emph (text "foo") =?> "<em>foo</em>"
201+ , "strong" =: strong (text "foo") =?> "<strong>foo</strong>"
202+ , "strikeout" =: strikeout (text "foo") =?> "<del>foo</del>"
203+ ]
204+ , "superscript" =: superscript (text "foo") =?> "<sup>foo</sup>"
205+ , "subscript" =: subscript (text "foo") =?> "<sub>foo</sub>"
206+ , "smallcaps" =: smallcaps (text "foo") =?> "foo"
207+ , "single quoted" =: singleQuoted (text "foo") =?> "'foo'"
208+ , "double quoted" =: doubleQuoted (text "foo") =?> "\"foo\""
209+ -- Cite is trivial
210+ , testGroup "code"
211+ [ "simple" =: code "foo" =?> "<code>foo</code>"
212+ , "escape lightweight markup" =: code "foo = bar" =?> "<code><verbatim>foo = bar</verbatim></code>"
213+ , "escape tag" =: code "<code>foo = bar</code> baz" =?> "<code><verbatim><code>foo = bar</code> baz</verbatim></code>"
214+ ]
215+ , testGroup "spaces"
216+ [ "space" =: text "a" <> space <> text "b" =?> "a b"
217+ , "soft break" =: text "a" <> softbreak <> text "b" =?> "a b"
218+ , test (museWithOpts def{ writerWrapText = WrapPreserve })
219+ "preserve soft break" $ text "a" <> softbreak <> text "b"
220+ =?> "a\nb"
221+ , "line break" =: text "a" <> linebreak <> text "b" =?> "a<br>\nb"
222+ ]
223+ , testGroup "math"
224+ [ "inline math" =: math "2^3" =?> "2<sup>3</sup>"
225+ , "display math" =: displayMath "2^3" =?> "<verse>2<sup>3</sup></verse>"
226+ ]
227+ , "raw inline"
228+ =: rawInline "html" "<mark>marked text</mark>"
229+ =?> "<literal style=\"html\"><mark>marked text</mark></literal>"
230+ , testGroup "links"
231+ [ "link with description" =: link "https://example.com" "" (str "Link 1")
232+ =?> "[[https://example.com][Link 1]]"
233+ , "link without description" =: link "https://example.com" "" (str "https://example.com")
234+ =?> "[[https://example.com]]"
235+ -- Internal links in Muse include '#'
236+ , "link to anchor" =: link "#intro" "" (str "Introduction")
237+ =?> "[[#intro][Introduction]]"
238+ -- According to Emacs Muse manual, links to images should be prefixed with "URL:"
239+ , "link to image with description" =: link "1.png" "" (str "Link to image")
240+ =?> "[[URL:1.png][Link to image]]"
241+ , "link to image without description" =: link "1.png" "" (str "1.png")
242+ =?> "[[URL:1.png]]"
243+ ]
244+ , "image" =: image "image.png" "Image 1" (str "") =?> "[[image.png][Image 1]]"
245+ , "note" =: note (plain (text "Foo"))
246+ =?> unlines [ "[1]"
247+ , ""
248+ , "[1] Foo"
249+ ]
250+ , "span" =: spanWith ("",["foobar"],[]) (str "Some text")
251+ =?> "<class name=\"foobar\">Some text</class>"
252+ , testGroup "combined"
253+ [ "emph word before" =:
254+ para (text "foo" <> emph (text "bar")) =?>
255+ "foo<em>bar</em>"
256+ , "emph word after" =:
257+ para (emph (text "foo") <> text "bar") =?>
258+ "<em>foo</em>bar"
259+ , "emph quoted" =:
260+ para (doubleQuoted (emph (text "foo"))) =?>
261+ "\"<em>foo</em>\""
262+ , "strong word before" =:
263+ para (text "foo" <> strong (text "bar")) =?>
264+ "foo<strong>bar</strong>"
265+ , "strong word after" =:
266+ para (strong (text "foo") <> text "bar") =?>
267+ "<strong>foo</strong>bar"
268+ , "strong quoted" =:
269+ para (singleQuoted (strong (text "foo"))) =?>
270+ "'<strong>foo</strong>'"
271+ ]
272+ ]
273+ ]
test/tables.musenew file+46
@@ -0,0 +1,46 @@
1+Simple table with caption:
2+
3+Right || Left || Center || Default
4+12 | 12 | 12 | 12
5+123 | 123 | 123 | 123
6+1 | 1 | 1 | 1
7+|+ Demonstration of simple table syntax. +|
8+
9+Simple table without caption:
10+
11+Right || Left || Center || Default
12+12 | 12 | 12 | 12
13+123 | 123 | 123 | 123
14+1 | 1 | 1 | 1
15+
16+Simple table indented two spaces:
17+
18+Right || Left || Center || Default
19+12 | 12 | 12 | 12
20+123 | 123 | 123 | 123
21+1 | 1 | 1 | 1
22+|+ Demonstration of simple table syntax. +|
23+
24+Multiline table with caption:
25+
26+Centered Header || Left Aligned || Right Aligned || Default aligned
27+First | row | 12.0 | Example of a row that spans multiple lines.
28+Second | row | 5.0 | Here’s another one. Note the blank line between rows.
29+|+ Here’s the caption. It may span multiple lines. +|
30+
31+Multiline table without caption:
32+
33+Centered Header || Left Aligned || Right Aligned || Default aligned
34+First | row | 12.0 | Example of a row that spans multiple lines.
35+Second | row | 5.0 | Here’s another one. Note the blank line between rows.
36+
37+Table without column headers:
38+
39+12 | 12 | 12 | 12
40+123 | 123 | 123 | 123
41+1 | 1 | 1 | 1
42+
43+Multiline table without column headers:
44+
45+First | row | 12.0 | Example of a row that spans multiple lines.
46+Second | row | 5.0 | Here’s another one. Note the blank line between rows.
test/test-pandoc.hs+2
@@ -29,6 +29,7 @@ import qualified Tests.Writers.Org
2929import qualified Tests.Writers.Plain
3030import qualified Tests.Writers.RST
3131import qualified Tests.Writers.TEI
32+import qualified Tests.Writers.Muse
3233import Text.Pandoc.Shared (inDirectory)
3334
3435tests :: [Test]
@@ -48,6 +49,7 @@ tests = [ Tests.Command.tests
4849 , testGroup "Docx" Tests.Writers.Docx.tests
4950 , testGroup "RST" Tests.Writers.RST.tests
5051 , testGroup "TEI" Tests.Writers.TEI.tests
52+ , testGroup "Muse" Tests.Writers.Muse.tests
5153 ]
5254 , testGroup "Readers"
5355 [ testGroup "LaTeX" Tests.Readers.LaTeX.tests
test/writer.musenew file+772
@@ -0,0 +1,772 @@
1+#author John MacFarlane
2+#title Pandoc Test Suite
3+#date July 17, 2006
4+
5+This is a set of tests for pandoc. Most of them are adapted from John Gruber’s
6+markdown test suite.
7+
8+----
9+
10+* Headers
11+
12+#headers
13+
14+** Level 2 with an [[/url][embedded link]]
15+
16+#level-2-with-an-embedded-link
17+
18+*** Level 3 with <em>emphasis</em>
19+
20+#level-3-with-emphasis
21+
22+**** Level 4
23+
24+#level-4
25+
26+***** Level 5
27+
28+#level-5
29+
30+* Level 1
31+
32+#level-1
33+
34+** Level 2 with <em>emphasis</em>
35+
36+#level-2-with-emphasis
37+
38+*** Level 3
39+
40+#level-3
41+with no blank line
42+
43+** Level 2
44+
45+#level-2
46+with no blank line
47+
48+----
49+
50+* Paragraphs
51+
52+#paragraphs
53+Here’s a regular paragraph.
54+
55+In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item.
56+Because a hard-wrapped line in the middle of a paragraph looked like a list
57+item.
58+
59+Here’s one with a bullet. <verbatim>*</verbatim> criminey.
60+
61+There should be a hard line break<br>
62+here.
63+
64+----
65+
66+* Block Quotes
67+
68+#block-quotes
69+E-mail style:
70+
71+<quote>
72+This is a block quote. It is pretty short.
73+</quote>
74+
75+<quote>
76+Code in a block quote:
77+
78+<example>
79+sub status {
80+ print "working";
81+}
82+</example>
83+
84+A list:
85+
86+1. item one
87+2. item two
88+
89+Nested block quotes:
90+
91+<quote>
92+nested
93+</quote>
94+
95+<quote>
96+nested
97+</quote>
98+</quote>
99+
100+This should not be a block quote: 2 <verbatim>></verbatim> 1.
101+
102+And a following paragraph.
103+
104+----
105+
106+* Code Blocks
107+
108+#code-blocks
109+Code:
110+
111+<example>
112+---- (should be four hyphens)
113+
114+sub status {
115+ print "working";
116+}
117+
118+this code block is indented by one tab
119+</example>
120+
121+And:
122+
123+<example>
124+ this code block is indented by two tabs
125+
126+These should not be escaped: \$ \\ \> \[ \{
127+</example>
128+
129+----
130+
131+* Lists
132+
133+#lists
134+
135+** Unordered
136+
137+#unordered
138+Asterisks tight:
139+
140+ - asterisk 1
141+ - asterisk 2
142+ - asterisk 3
143+
144+Asterisks loose:
145+
146+ - asterisk 1
147+ - asterisk 2
148+ - asterisk 3
149+
150+Pluses tight:
151+
152+ - Plus 1
153+ - Plus 2
154+ - Plus 3
155+
156+Pluses loose:
157+
158+ - Plus 1
159+ - Plus 2
160+ - Plus 3
161+
162+Minuses tight:
163+
164+ - Minus 1
165+ - Minus 2
166+ - Minus 3
167+
168+Minuses loose:
169+
170+ - Minus 1
171+ - Minus 2
172+ - Minus 3
173+
174+** Ordered
175+
176+#ordered
177+Tight:
178+
179+ 1. First
180+ 2. Second
181+ 3. Third
182+
183+and:
184+
185+ 1. One
186+ 2. Two
187+ 3. Three
188+
189+Loose using tabs:
190+
191+ 1. First
192+ 2. Second
193+ 3. Third
194+
195+and using spaces:
196+
197+ 1. One
198+ 2. Two
199+ 3. Three
200+
201+Multiple paragraphs:
202+
203+ 1. Item 1, graf one.
204+
205+ Item 1. graf two. The quick brown fox jumped over the lazy dog’s back.
206+ 2. Item 2.
207+ 3. Item 3.
208+
209+** Nested
210+
211+#nested
212+ - Tab
213+ - Tab
214+ - Tab
215+
216+Here’s another:
217+
218+ 1. First
219+ 2. Second:
220+ - Fee
221+ - Fie
222+ - Foe
223+ 3. Third
224+
225+Same thing but with paragraphs:
226+
227+ 1. First
228+ 2. Second:
229+
230+ - Fee
231+ - Fie
232+ - Foe
233+ 3. Third
234+
235+** Tabs and spaces
236+
237+#tabs-and-spaces
238+ - this is a list item indented with tabs
239+ - this is a list item indented with spaces
240+
241+ - this is an example list item indented with tabs
242+ - this is an example list item indented with spaces
243+
244+** Fancy list markers
245+
246+#fancy-list-markers
247+ 2. begins with 2
248+ 3. and now 3
249+
250+ with a continuation
251+
252+ iv. sublist with roman numerals, starting with 4
253+ v. more items
254+ A. a subsublist
255+ B. a subsublist
256+
257+Nesting:
258+
259+ A. Upper Alpha
260+ I. Upper Roman.
261+ 6. Decimal start with 6
262+ c. Lower alpha with paren
263+
264+Autonumbering:
265+
266+ 1. Autonumber.
267+ 2. More.
268+ 1. Nested.
269+
270+Should not be a list item:
271+
272+M.A. 2007
273+
274+B. Williams
275+
276+----
277+
278+* Definition Lists
279+
280+#definition-lists
281+Tight using spaces:
282+
283+ apple :: red fruit
284+ orange :: orange fruit
285+ banana :: yellow fruit
286+
287+Tight using tabs:
288+
289+ apple :: red fruit
290+ orange :: orange fruit
291+ banana :: yellow fruit
292+
293+Loose:
294+
295+ apple :: red fruit
296+ orange :: orange fruit
297+ banana :: yellow fruit
298+
299+Multiple blocks with italics:
300+
301+ <em>apple</em> :: red fruit
302+
303+ contains seeds, crisp, pleasant to taste
304+ <em>orange</em> :: orange fruit
305+
306+ <example>
307+ { orange code block }
308+ </example>
309+
310+ <quote>
311+orange block quote
312+ </quote>
313+
314+Multiple definitions, tight:
315+
316+ apple :: red fruit
317+ computer
318+ orange :: orange fruit
319+ bank
320+
321+Multiple definitions, loose:
322+
323+ apple :: red fruit
324+
325+ computer
326+ orange :: orange fruit
327+
328+ bank
329+
330+Blank line after term, indented marker, alternate markers:
331+
332+ apple :: red fruit
333+
334+ computer
335+ orange :: orange fruit
336+
337+ 1. sublist
338+ 2. sublist
339+
340+* HTML Blocks
341+
342+#html-blocks
343+Simple block on one line:
344+
345+fooAnd nested without indentation:
346+
347+foo
348+
349+barInterpreted markdown in a table:
350+
351+<literal style="html">
352+<table>
353+</literal>
354+
355+<literal style="html">
356+<tr>
357+</literal>
358+
359+<literal style="html">
360+<td>
361+</literal>
362+
363+This is <em>emphasized</em>
364+
365+<literal style="html">
366+</td>
367+</literal>
368+
369+<literal style="html">
370+<td>
371+</literal>
372+
373+And this is <strong>strong</strong>
374+
375+<literal style="html">
376+</td>
377+</literal>
378+
379+<literal style="html">
380+</tr>
381+</literal>
382+
383+<literal style="html">
384+</table>
385+</literal>
386+
387+<literal style="html">
388+<script type="text/javascript">document.write('This *should not* be interpreted as markdown');</script>
389+</literal>
390+
391+Here’s a simple block:
392+
393+foo
394+
395+This should be a code block, though:
396+
397+<example>
398+<div>
399+ foo
400+</div>
401+</example>
402+
403+As should this:
404+
405+<example>
406+<div>foo</div>
407+</example>
408+
409+Now, nested:
410+
411+fooThis should just be an HTML comment:
412+
413+<literal style="html">
414+<!-- Comment -->
415+</literal>
416+
417+Multiline:
418+
419+<literal style="html">
420+<!--
421+Blah
422+Blah
423+-->
424+</literal>
425+
426+<literal style="html">
427+<!--
428+ This is another comment.
429+-->
430+</literal>
431+
432+Code block:
433+
434+<example>
435+<!-- Comment -->
436+</example>
437+
438+Just plain comment, with trailing spaces on the line:
439+
440+<literal style="html">
441+<!-- foo -->
442+</literal>
443+
444+Code:
445+
446+<example>
447+<hr />
448+</example>
449+
450+Hr’s:
451+
452+<literal style="html">
453+<hr>
454+</literal>
455+
456+<literal style="html">
457+<hr />
458+</literal>
459+
460+<literal style="html">
461+<hr />
462+</literal>
463+
464+<literal style="html">
465+<hr>
466+</literal>
467+
468+<literal style="html">
469+<hr />
470+</literal>
471+
472+<literal style="html">
473+<hr />
474+</literal>
475+
476+<literal style="html">
477+<hr class="foo" id="bar" />
478+</literal>
479+
480+<literal style="html">
481+<hr class="foo" id="bar" />
482+</literal>
483+
484+<literal style="html">
485+<hr class="foo" id="bar">
486+</literal>
487+
488+----
489+
490+* Inline Markup
491+
492+#inline-markup
493+This is <em>emphasized</em>, and so <em>is this</em>.
494+
495+This is <strong>strong</strong>, and so <strong>is this</strong>.
496+
497+An <em>[[/url][emphasized link]]</em>.
498+
499+<strong><em>This is strong and em.</em></strong>
500+
501+So is <strong><em>this</em></strong> word.
502+
503+<strong><em>This is strong and em.</em></strong>
504+
505+So is <strong><em>this</em></strong> word.
506+
507+This is code: <code><verbatim>></verbatim></code>, <code>$</code>,
508+<code>\</code>, <code>\$</code>, <code><verbatim><html></verbatim></code>.
509+
510+<del>This is <em>strikeout</em>.</del>
511+
512+Superscripts: a<sup>bc</sup>d a<sup><em>hello</em></sup>
513+a<sup>hello there</sup>.
514+
515+Subscripts: H<sub>2</sub>O, H<sub>23</sub>O, H<sub>many of them</sub>O.
516+
517+These should not be superscripts or subscripts, because of the unescaped
518+spaces: a^b c^d, a~b c~d.
519+
520+----
521+
522+* Smart quotes, ellipses, dashes
523+
524+#smart-quotes-ellipses-dashes
525+"Hello," said the spider. "'Shelob' is my name."
526+
527+'A', 'B', and 'C' are letters.
528+
529+'Oak,' 'elm,' and 'beech' are names of trees. So is 'pine.'
530+
531+'He said, "I want to go."' Were you alive in the 70’s?
532+
533+Here is some quoted '<code>code</code>' and a
534+"[[http://example.com/?foo=1&bar=2][quoted link]]".
535+
536+Some dashes: one—two — three—four — five.
537+
538+Dashes between numbers: 5–7, 255–66, 1987–1999.
539+
540+Ellipses…and…and….
541+
542+----
543+
544+* LaTeX
545+
546+#latex
547+ - <literal style="tex">\cite[22-23]{smith.1899}</literal>
548+ - 2 + 2 <verbatim>=</verbatim> 4
549+ - <em>x</em> ∈ <em>y</em>
550+ - <em>α</em> ∧ <em>ω</em>
551+ - 223
552+ - <em>p</em>-Tree
553+ - Here’s some display math:
554+ <verse><verbatim>$$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$$</verbatim></verse>
555+ - Here’s one that has a line break in it:
556+ <em>α</em> + <em>ω</em> × <em>x</em><sup>2</sup>.
557+
558+These shouldn’t be math:
559+
560+ - To get the famous equation, write
561+ <code><verbatim>$e = mc^2$</verbatim></code>.
562+ - $22,000 is a <em>lot</em> of money. So is $34,000. (It worked if "lot" is
563+ emphasized.)
564+ - Shoes ($20) and socks ($5).
565+ - Escaped <code>$</code>: $73 <em>this should be emphasized</em> 23$.
566+
567+Here’s a LaTeX table:
568+
569+<literal style="latex">
570+\begin{tabular}{|l|l|}\hline
571+Animal & Number \\ \hline
572+Dog & 2 \\
573+Cat & 1 \\ \hline
574+\end{tabular}
575+</literal>
576+
577+----
578+
579+* Special Characters
580+
581+#special-characters
582+Here is some unicode:
583+
584+ - I hat: Î
585+ - o umlaut: ö
586+ - section: §
587+ - set membership: ∈
588+ - copyright: ©
589+
590+AT&T has an ampersand in their name.
591+
592+AT&T is another way to write it.
593+
594+This & that.
595+
596+4 <verbatim><</verbatim> 5.
597+
598+6 <verbatim>></verbatim> 5.
599+
600+Backslash: \
601+
602+Backtick: `
603+
604+Asterisk: <verbatim>*</verbatim>
605+
606+Underscore: _
607+
608+Left brace: {
609+
610+Right brace: }
611+
612+Left bracket: <verbatim>[</verbatim>
613+
614+Right bracket: <verbatim>]</verbatim>
615+
616+Left paren: (
617+
618+Right paren: )
619+
620+Greater-than: <verbatim>></verbatim>
621+
622+Hash: #
623+
624+Period: .
625+
626+Bang: !
627+
628+Plus: +
629+
630+Minus: -
631+
632+----
633+
634+* Links
635+
636+#links
637+
638+** Explicit
639+
640+#explicit
641+Just a [[/url/][URL]].
642+
643+[[/url/][URL and title]].
644+
645+[[/url/][URL and title]].
646+
647+[[/url/][URL and title]].
648+
649+[[/url/][URL and title]]
650+
651+[[/url/][URL and title]]
652+
653+[[/url/with_underscore][with_underscore]]
654+
655+[[mailto:nobody@nowhere.net][Email link]]
656+
657+[[][Empty]].
658+
659+** Reference
660+
661+#reference
662+Foo [[/url/][bar]].
663+
664+Foo [[/url/][bar]].
665+
666+Foo [[/url/][bar]].
667+
668+With [[/url/][embedded <verbatim>[brackets]</verbatim>]].
669+
670+[[/url/][b]] by itself should be a link.
671+
672+Indented [[/url][once]].
673+
674+Indented [[/url][twice]].
675+
676+Indented [[/url][thrice]].
677+
678+This should <verbatim>[not][]</verbatim> be a link.
679+
680+<example>
681+[not]: /url
682+</example>
683+
684+Foo [[/url/][bar]].
685+
686+Foo [[/url/][biz]].
687+
688+** With ampersands
689+
690+#with-ampersands
691+Here’s a [[http://example.com/?foo=1&bar=2][link with an ampersand in the
692+URL]].
693+
694+Here’s a link with an amersand in the link text: [[http://att.com/][AT&T]].
695+
696+Here’s an [[/script?foo=1&bar=2][inline link]].
697+
698+Here’s an [[/script?foo=1&bar=2][inline link in pointy braces]].
699+
700+** Autolinks
701+
702+#autolinks
703+With an ampersand: [[http://example.com/?foo=1&bar=2]]
704+
705+ - In a list?
706+ - [[http://example.com/]]
707+ - It should.
708+
709+An e-mail address: [[mailto:nobody@nowhere.net][nobody@nowhere.net]]
710+
711+<quote>
712+Blockquoted: [[http://example.com/]]
713+</quote>
714+
715+Auto-links should not occur here:
716+<code><verbatim><http://example.com/></verbatim></code>
717+
718+<example>
719+or here: <http://example.com/>
720+</example>
721+
722+----
723+
724+* Images
725+
726+#images
727+From "Voyage dans la Lune" by Georges Melies (1902):
728+
729+[[lalune.jpg][Voyage dans la Lune]]
730+
731+Here is a movie [[movie.jpg][movie]] icon.
732+
733+----
734+
735+* Footnotes
736+
737+#footnotes
738+Here is a footnote reference,[1] and another.[2] This should <em>not</em> be a
739+footnote reference, because it contains a <verbatim>space.[^my</verbatim>
740+<verbatim>note]</verbatim> Here is an inline note.[3]
741+
742+<quote>
743+Notes can go in quotes.[4]
744+</quote>
745+
746+ 1. And in list items.[5]
747+
748+This paragraph should not be part of the note, as it is not indented.
749+
750+[1] Here is the footnote. It can go anywhere after the footnote reference. It
751+ need not be placed at the end of the document.
752+
753+[2] Here’s the long note. This one contains multiple blocks.
754+
755+ Subsequent blocks are indented to show that they belong to the footnote
756+ (as with list items).
757+
758+ <example>
759+ { <code> }
760+ </example>
761+
762+ If you want, you can indent every line, but you can also be lazy and just
763+ indent the first line of each block.
764+
765+[3] This is <em>easier</em> to type. Inline notes may contain
766+ [[http://google.com][links]] and <code><verbatim>]</verbatim></code>
767+ verbatim characters, as well as <verbatim>[bracketed</verbatim>
768+ <verbatim>text].</verbatim>
769+
770+[4] In quote.
771+
772+[5] In list.
trypandoc/index.html+1
@@ -129,6 +129,7 @@ $(document).ready(function() {
129129 <option value="slideous">Slideous</option>
130130 <option value="slidy">Slidy</option>
131131 <option value="texinfo">Texinfo</option>
132+ <option value="muse">Muse</option>
132133 </select>
133134 <br/>
134135 <pre id="results"></pre>