git.iko.soy/typeable/pandoc
on master help sign in
Added Zim Wiki writer, template and tests.
a73c95fAlex Ivkin
data/templates+1−1

Submodule changed.

pandoc.cabal+1
@@ -363,6 +363,7 @@ Library
363 Text.Pandoc.Writers.Textile,
363 Text.Pandoc.Writers.Textile,
364 Text.Pandoc.Writers.MediaWiki,
364 Text.Pandoc.Writers.MediaWiki,
365 Text.Pandoc.Writers.DokuWiki,
365 Text.Pandoc.Writers.DokuWiki,
366+ Text.Pandoc.Writers.ZimWiki,
366 Text.Pandoc.Writers.RTF,
367 Text.Pandoc.Writers.RTF,
367 Text.Pandoc.Writers.ODT,
368 Text.Pandoc.Writers.ODT,
368 Text.Pandoc.Writers.Docx,
369 Text.Pandoc.Writers.Docx,
src/Text/Pandoc.hs+3
@@ -104,6 +104,7 @@ module Text.Pandoc
104 , writeMan
104 , writeMan
105 , writeMediaWiki
105 , writeMediaWiki
106 , writeDokuWiki
106 , writeDokuWiki
107+ , writeZimWiki
107 , writeTextile
108 , writeTextile
108 , writeRTF
109 , writeRTF
109 , writeODT
110 , writeODT
@@ -164,6 +165,7 @@ import Text.Pandoc.Writers.Man
164import Text.Pandoc.Writers.RTF
165import Text.Pandoc.Writers.RTF
165import Text.Pandoc.Writers.MediaWiki
166import Text.Pandoc.Writers.MediaWiki
166import Text.Pandoc.Writers.DokuWiki
167import Text.Pandoc.Writers.DokuWiki
168+import Text.Pandoc.Writers.ZimWiki
167import Text.Pandoc.Writers.Textile
169import Text.Pandoc.Writers.Textile
168import Text.Pandoc.Writers.Org
170import Text.Pandoc.Writers.Org
169import Text.Pandoc.Writers.AsciiDoc
171import Text.Pandoc.Writers.AsciiDoc
@@ -310,6 +312,7 @@ writers = [
310 ,("rst" , PureStringWriter writeRST)
312 ,("rst" , PureStringWriter writeRST)
311 ,("mediawiki" , PureStringWriter writeMediaWiki)
313 ,("mediawiki" , PureStringWriter writeMediaWiki)
312 ,("dokuwiki" , PureStringWriter writeDokuWiki)
314 ,("dokuwiki" , PureStringWriter writeDokuWiki)
315+ ,("zimwiki" , PureStringWriter writeZimWiki)
313 ,("textile" , PureStringWriter writeTextile)
316 ,("textile" , PureStringWriter writeTextile)
314 ,("rtf" , IOStringWriter writeRTFWithEmbeddedImages)
317 ,("rtf" , IOStringWriter writeRTFWithEmbeddedImages)
315 ,("org" , PureStringWriter writeOrg)
318 ,("org" , PureStringWriter writeOrg)
src/Text/Pandoc/Writers/ZimWiki.hsnew file+361
@@ -0,0 +1,361 @@
1+{-
2+Copyright (C) 2008-2015 John MacFarlane <jgm@berkeley.edu>
3+
4+This program is free software; you can redistribute it and/or modify
5+it under the terms of the GNU General Public License as published by
6+the Free Software Foundation; either version 2 of the License, or
7+(at your option) any later version.
8+
9+This program is distributed in the hope that it will be useful,
10+but WITHOUT ANY WARRANTY; without even the implied warranty of
11+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+GNU General Public License for more details.
13+
14+You should have received a copy of the GNU General Public License
15+along with this program; if not, write to the Free Software
16+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17+-}
18+
19+{- |
20+ Module : Text.Pandoc.Writers.ZimWiki
21+ Copyright : Copyright (C) 2008-2015 John MacFarlane, 2016 Alex Ivkin
22+ License : GNU GPL, version 2 or above
23+
24+ Maintainer : Alex Ivkin <alex@ivkin.net>
25+ Stability : alpha
26+ Portability : portable
27+
28+Conversion of 'Pandoc' documents to ZimWiki markup.
29+
30+http://zim-wiki.org/manual/Help/Wiki_Syntax.html
31+-}
32+
33+module Text.Pandoc.Writers.ZimWiki ( writeZimWiki ) where
34+import Text.Pandoc.Definition
35+import Text.Pandoc.Options ( WriterOptions(writerTableOfContents, writerStandalone, writerTemplate, writerWrapText), WrapOption(..) )
36+import Text.Pandoc.Shared ( escapeURI, removeFormatting, trimr, substitute )
37+import Text.Pandoc.Writers.Shared ( defField, metaToJSON )
38+import Text.Pandoc.ImageSize
39+import Text.Pandoc.Templates ( renderTemplate' )
40+import Data.List ( intercalate, isPrefixOf, transpose, isInfixOf )
41+import Data.Text ( breakOnAll, pack )
42+import Data.Default (Default(..))
43+import Network.URI ( isURI )
44+import Control.Monad ( zipWithM )
45+import Control.Monad.State ( modify, State, get, evalState )
46+--import Control.Monad.Reader ( ReaderT, runReaderT, ask, local )
47+
48+data WriterState = WriterState {
49+ stItemNum :: Int,
50+ stIndent :: String -- Indent after the marker at the beginning of list items
51+ }
52+
53+instance Default WriterState where
54+ def = WriterState { stItemNum = 1, stIndent = "" }
55+
56+-- | Convert Pandoc to ZimWiki.
57+writeZimWiki :: WriterOptions -> Pandoc -> String
58+writeZimWiki opts document = evalState (pandocToZimWiki opts document) (WriterState 1 "")
59+
60+-- | Return ZimWiki representation of document.
61+pandocToZimWiki :: WriterOptions -> Pandoc -> State WriterState String
62+pandocToZimWiki opts (Pandoc meta blocks) = do
63+ metadata <- metaToJSON opts
64+ (fmap trimr . blockListToZimWiki opts)
65+ (inlineListToZimWiki opts)
66+ meta
67+ body <- blockListToZimWiki opts blocks
68+ --let header = "Content-Type: text/x-zim-wiki\nWiki-Format: zim 0.4\n"
69+ let main = body
70+ let context = defField "body" main
71+ $ defField "toc" (writerTableOfContents opts)
72+ $ metadata
73+ if writerStandalone opts
74+ then return $ renderTemplate' (writerTemplate opts) context
75+ else return main
76+
77+-- | Escape special characters for ZimWiki.
78+escapeString :: String -> String
79+escapeString = substitute "__" "''__''" .
80+ substitute "**" "''**''" .
81+ substitute "~~" "''~~''" .
82+ substitute "//" "''//''"
83+
84+-- | Convert Pandoc block element to ZimWiki.
85+blockToZimWiki :: WriterOptions -> Block -> State WriterState String
86+
87+blockToZimWiki _ Null = return ""
88+
89+blockToZimWiki opts (Div _attrs bs) = do
90+ contents <- blockListToZimWiki opts bs
91+ return $ contents ++ "\n"
92+
93+blockToZimWiki opts (Plain inlines) = inlineListToZimWiki opts inlines
94+
95+-- title beginning with fig: indicates that the image is a figure
96+-- ZimWiki doesn't support captions - so combine together alt and caption into alt
97+blockToZimWiki opts (Para [Image attr txt (src,'f':'i':'g':':':tit)]) = do
98+ capt <- if null txt
99+ then return ""
100+ else (" " ++) `fmap` inlineListToZimWiki opts txt
101+ let opt = if null txt
102+ then ""
103+ else "|" ++ if null tit then capt else tit ++ capt
104+ -- Relative links fail isURI and receive a colon
105+ prefix = if isURI src then "" else ":"
106+ return $ "{{" ++ prefix ++ src ++ imageDims opts attr ++ opt ++ "}}\n"
107+
108+blockToZimWiki opts (Para inlines) = do
109+ indent <- stIndent <$> get
110+ -- useTags <- stUseTags <$> get
111+ contents <- inlineListToZimWiki opts inlines
112+ return $ contents ++ if null indent then "\n" else ""
113+
114+blockToZimWiki opts (RawBlock f str)
115+ | f == Format "zimwiki" = return str
116+ | f == Format "html" = do cont <- indentFromHTML opts str; return cont
117+ | otherwise = return "" -- $ "** unknown raw block "++ show f ++ "=" ++ str ++ " **"
118+
119+blockToZimWiki _ HorizontalRule = return "\n----\n"
120+
121+blockToZimWiki opts (Header level _ inlines) = do
122+ contents <- inlineListToZimWiki opts $ removeFormatting inlines -- emphasis, links etc. not allowed in headers
123+ let eqs = replicate ( 7 - level ) '='
124+ return $ eqs ++ " " ++ contents ++ " " ++ eqs ++ "\n"
125+
126+blockToZimWiki _ (CodeBlock (_,classes,_) str) = do
127+ return $ case classes of
128+ [] -> "'''\n" ++ cleanupCode str ++ "\n'''\n" -- no lang block is a quote block
129+ (x:_) -> "{{{code: lang=\"" ++ x ++ "\" linenumbers=\"True\"\n" ++ str ++ "\n}}}\n" -- for zim's code plugin, go verbatim on the lang spec
130+
131+blockToZimWiki opts (BlockQuote blocks) = do
132+ contents <- blockListToZimWiki opts blocks
133+ return $ unlines $ map ("> " ++) $ lines contents
134+
135+blockToZimWiki opts (Table capt aligns _ headers rows) = do
136+ captionDoc <- if null capt
137+ then return ""
138+ else do
139+ c <- inlineListToZimWiki opts capt
140+ return $ "" ++ c ++ "\n"
141+ headers' <- if all null headers
142+ then zipWithM (tableItemToZimWiki opts) aligns (rows !! 0)
143+ else zipWithM (tableItemToZimWiki opts) aligns headers
144+ rows' <- mapM (zipWithM (tableItemToZimWiki opts) aligns) rows
145+ let widths = map (maximum . map length) $ transpose (headers':rows')
146+ let padTo (width, al) s =
147+ case (width - length s) of
148+ x | x > 0 ->
149+ if al == AlignLeft || al == AlignDefault
150+ then s ++ replicate x ' '
151+ else if al == AlignRight
152+ then replicate x ' ' ++ s
153+ else replicate (x `div` 2) ' ' ++
154+ s ++ replicate (x - x `div` 2) ' '
155+ | otherwise -> s
156+ let borderCell (width, al) _ =
157+ if al == AlignLeft
158+ then ":"++ replicate (width-1) '-'
159+ else if al == AlignDefault
160+ then replicate width '-'
161+ else if al == AlignRight
162+ then replicate (width-1) '-' ++ ":"
163+ else ":" ++ replicate (width-2) '-' ++ ":"
164+ let underheader = "|" ++ intercalate "|" (zipWith borderCell (zip widths aligns) headers') ++ "|"
165+ let renderRow sep cells = sep ++ intercalate sep (zipWith padTo (zip widths aligns) cells) ++ sep
166+ return $ captionDoc ++
167+ (if null headers' then "" else renderRow "|" headers' ++ "\n") ++ underheader ++ "\n" ++
168+ unlines (map (renderRow "|") rows')
169+
170+blockToZimWiki opts (BulletList items) = do
171+ indent <- stIndent <$> get
172+ modify $ \s -> s { stIndent = stIndent s ++ "\t" }
173+ contents <- (mapM (listItemToZimWiki opts) items)
174+ modify $ \s -> s{ stIndent = indent } -- drop 1 (stIndent s) }
175+ return $ vcat contents ++ if null indent then "\n" else ""
176+
177+blockToZimWiki opts (OrderedList _ items) = do
178+ indent <- stIndent <$> get
179+ modify $ \s -> s { stIndent = stIndent s ++ "\t", stItemNum = 1 }
180+ contents <- (mapM (orderedListItemToZimWiki opts) items)
181+ modify $ \s -> s{ stIndent = indent } -- drop 1 (stIndent s) }
182+ return $ vcat contents ++ if null indent then "\n" else ""
183+
184+blockToZimWiki opts (DefinitionList items) = do
185+ contents <- (mapM (definitionListItemToZimWiki opts) items)
186+ return $ vcat contents
187+
188+definitionListItemToZimWiki :: WriterOptions -> ([Inline],[[Block]]) -> State WriterState String
189+definitionListItemToZimWiki opts (label, items) = do
190+ labelText <- inlineListToZimWiki opts label
191+ contents <- mapM (blockListToZimWiki opts) items
192+ indent <- stIndent <$> get
193+ return $ indent ++ "* **" ++ labelText ++ "** " ++ concat contents
194+
195+-- Auxiliary functions for lists:
196+indentFromHTML :: WriterOptions -> String -> State WriterState String
197+indentFromHTML _ str = do
198+ indent <- stIndent <$> get
199+ itemnum <- stItemNum <$> get
200+ if isInfixOf "<li>" str then return $ indent ++ show itemnum ++ "."
201+ else if isInfixOf "</li>" str then return "\n"
202+ else if isInfixOf "<li value=" str then do
203+ -- poor man's cut
204+ let val = drop 10 $ reverse $ drop 1 $ reverse str
205+ --let val = take ((length valls) - 2) valls
206+ modify $ \s -> s { stItemNum = read val }
207+ return "" -- $ indent ++ val ++ "." -- zim does its own numbering
208+ else if isInfixOf "<ol>" str then do
209+ let olcount=countSubStrs "<ol>" str
210+ modify $ \s -> s { stIndent = stIndent s ++ replicate olcount '\t', stItemNum = 1 }
211+ return "" -- $ "OL-ON[" ++ newfix ++"]"
212+ else if isInfixOf "</ol>" str then do
213+ let olcount=countSubStrs "/<ol>" str
214+ modify $ \s -> s{ stIndent = drop olcount (stIndent s) }
215+ return "" -- $ "OL-OFF[" ++ newfix ++"]"
216+ else
217+ return $ "" -- ** unknown inner HTML "++ str ++"**"
218+
219+countSubStrs :: String -> String -> Int
220+countSubStrs sub str = length $ breakOnAll (pack sub) (pack str)
221+
222+cleanupCode :: String -> String
223+cleanupCode = substitute "<nowiki>" "" . substitute "</nowiki>" ""
224+
225+vcat :: [String] -> String
226+vcat = intercalate "\n"
227+
228+-- | Convert bullet list item (list of blocks) to ZimWiki.
229+listItemToZimWiki :: WriterOptions -> [Block] -> State WriterState String
230+listItemToZimWiki opts items = do
231+ contents <- blockListToZimWiki opts items
232+ indent <- stIndent <$> get
233+ return $ indent ++ "* " ++ contents
234+
235+-- | Convert ordered list item (list of blocks) to ZimWiki.
236+orderedListItemToZimWiki :: WriterOptions -> [Block] -> State WriterState String
237+orderedListItemToZimWiki opts items = do
238+ contents <- blockListToZimWiki opts items
239+ indent <- stIndent <$> get
240+ itemnum <- stItemNum <$> get
241+ --modify $ \s -> s { stItemNum = itemnum + 1 } -- this is not strictly necessary for zim as zim does its own renumbering
242+ return $ indent ++ show itemnum ++ ". " ++ contents
243+
244+-- Auxiliary functions for tables:
245+tableItemToZimWiki :: WriterOptions -> Alignment -> [Block] -> State WriterState String
246+tableItemToZimWiki opts align' item = do
247+ let mkcell x = (if align' == AlignRight || align' == AlignCenter
248+ then " "
249+ else "") ++ x ++
250+ (if align' == AlignLeft || align' == AlignCenter
251+ then " "
252+ else "")
253+ contents <- blockListToZimWiki opts item -- local (\s -> s { stBackSlashLB = True }) $
254+ return $ mkcell contents
255+
256+-- | Convert list of Pandoc block elements to ZimWiki.
257+blockListToZimWiki :: WriterOptions -> [Block] -> State WriterState String
258+blockListToZimWiki opts blocks = vcat <$> mapM (blockToZimWiki opts) blocks
259+
260+-- | Convert list of Pandoc inline elements to ZimWiki.
261+inlineListToZimWiki :: WriterOptions -> [Inline] -> State WriterState String
262+inlineListToZimWiki opts lst = concat <$> (mapM (inlineToZimWiki opts) lst)
263+
264+-- | Convert Pandoc inline element to ZimWiki.
265+inlineToZimWiki :: WriterOptions -> Inline -> State WriterState String
266+
267+inlineToZimWiki opts (Emph lst) = do
268+ contents <- inlineListToZimWiki opts lst
269+ return $ "//" ++ contents ++ "//"
270+
271+inlineToZimWiki opts (Strong lst) = do
272+ contents <- inlineListToZimWiki opts lst
273+ return $ "**" ++ contents ++ "**"
274+
275+inlineToZimWiki opts (Strikeout lst) = do
276+ contents <- inlineListToZimWiki opts lst
277+ return $ "~~" ++ contents ++ "~~"
278+
279+inlineToZimWiki opts (Superscript lst) = do
280+ contents <- inlineListToZimWiki opts lst
281+ return $ "^{" ++ contents ++ "}"
282+
283+inlineToZimWiki opts (Subscript lst) = do
284+ contents <- inlineListToZimWiki opts lst
285+ return $ "_{" ++ contents ++ "}"
286+
287+inlineToZimWiki opts (Quoted SingleQuote lst) = do
288+ contents <- inlineListToZimWiki opts lst
289+ return $ "\8216" ++ contents ++ "\8217"
290+
291+inlineToZimWiki opts (Quoted DoubleQuote lst) = do
292+ contents <- inlineListToZimWiki opts lst
293+ return $ "\8220" ++ contents ++ "\8221"
294+
295+inlineToZimWiki opts (Span _attrs ils) = inlineListToZimWiki opts ils
296+
297+inlineToZimWiki opts (SmallCaps lst) = inlineListToZimWiki opts lst
298+
299+inlineToZimWiki opts (Cite _ lst) = inlineListToZimWiki opts lst
300+
301+inlineToZimWiki _ (Code _ str) = return $ "''" ++ str ++ "''"
302+
303+inlineToZimWiki _ (Str str) = return $ escapeString str
304+
305+inlineToZimWiki _ (Math mathType str) = return $ delim ++ str ++ delim -- note: str should NOT be escaped
306+ where delim = case mathType of
307+ DisplayMath -> "$$"
308+ InlineMath -> "$"
309+
310+-- | f == Format "html" = return $ "<html>" ++ str ++ "</html>"
311+inlineToZimWiki opts (RawInline f str)
312+ | f == Format "zimwiki" = return str
313+ | f == Format "html" = do cont <- indentFromHTML opts str; return cont
314+ | otherwise = return ""
315+
316+inlineToZimWiki _ (LineBreak) = return "\n" -- was \\\\
317+
318+inlineToZimWiki opts SoftBreak =
319+ case writerWrapText opts of
320+ WrapNone -> return " "
321+ WrapAuto -> return " "
322+ WrapPreserve -> return "\n"
323+
324+inlineToZimWiki _ Space = return " "
325+
326+inlineToZimWiki opts (Link _ txt (src, _)) = do
327+ label <- inlineListToZimWiki opts txt
328+ case txt of
329+ [Str s] | "mailto:" `isPrefixOf` src -> return $ "<" ++ s ++ ">"
330+ | escapeURI s == src -> return src
331+ _ -> if isURI src
332+ then return $ "[[" ++ src ++ "|" ++ label ++ "]]"
333+ else return $ "[[" ++ src' ++ "|" ++ label ++ "]]"
334+ where src' = case src of
335+ '/':xs -> xs -- with leading / it's a
336+ _ -> src -- link to a help page
337+inlineToZimWiki opts (Image attr alt (source, tit)) = do
338+ alt' <- inlineListToZimWiki opts alt
339+ let txt = case (tit, alt) of
340+ ("", []) -> ""
341+ ("", _ ) -> "|" ++ alt'
342+ (_ , _ ) -> "|" ++ tit
343+ -- Relative links fail isURI and receive a colon
344+ prefix = if isURI source then "" else ":"
345+ return $ "{{" ++ prefix ++ source ++ imageDims opts attr ++ txt ++ "}}"
346+
347+inlineToZimWiki opts (Note contents) = do
348+ contents' <- blockListToZimWiki opts contents
349+ return $ "((" ++ contents' ++ "))"
350+ -- note - may not work for notes with multiple blocks
351+
352+imageDims :: WriterOptions -> Attr -> String
353+imageDims opts attr = go (toPx $ dimension Width attr) (toPx $ dimension Height attr)
354+ where
355+ toPx = fmap (showInPixel opts) . checkPct
356+ checkPct (Just (Percent _)) = Nothing
357+ checkPct maybeDim = maybeDim
358+ go (Just w) Nothing = "?" ++ w
359+ go (Just w) (Just h) = "?" ++ w ++ "x" ++ h
360+ go Nothing (Just h) = "?0x" ++ h
361+ go Nothing Nothing = ""
tests/Tests/Old.hs+1−1
@@ -166,7 +166,7 @@ tests = [ testGroup "markdown"
166 "twiki-reader.twiki" "twiki-reader.native" ]
166 "twiki-reader.twiki" "twiki-reader.native" ]
167 , testGroup "other writers" $ map (\f -> testGroup f $ writerTests f)
167 , testGroup "other writers" $ map (\f -> testGroup f $ writerTests f)
168 [ "opendocument" , "context" , "texinfo", "icml", "tei"
168 [ "opendocument" , "context" , "texinfo", "icml", "tei"
169− , "man" , "plain" , "rtf", "org", "asciidoc"
169+ , "man" , "plain" , "rtf", "org", "asciidoc", "zimwiki"
170 ]
170 ]
171 , testGroup "writers-lang-and-dir"
171 , testGroup "writers-lang-and-dir"
172 [ test "latex" ["-f", "native", "-t", "latex", "-s"]
172 [ test "latex" ["-f", "native", "-t", "latex", "-s"]
tests/tables.zimwikinew file+56
@@ -0,0 +1,56 @@
1+Simple table with caption:
2+
3+Demonstration of simple table syntax.
4+| Right|Left | Center |Default|
5+|------:|:-----|:--------:|-------|
6+| 12|12 | 12 |12 |
7+| 123|123 | 123 |123 |
8+| 1|1 | 1 |1 |
9+
10+Simple table without caption:
11+
12+| Right|Left | Center |Default|
13+|------:|:-----|:--------:|-------|
14+| 12|12 | 12 |12 |
15+| 123|123 | 123 |123 |
16+| 1|1 | 1 |1 |
17+
18+Simple table indented two spaces:
19+
20+Demonstration of simple table syntax.
21+| Right|Left | Center |Default|
22+|------:|:-----|:--------:|-------|
23+| 12|12 | 12 |12 |
24+| 123|123 | 123 |123 |
25+| 1|1 | 1 |1 |
26+
27+Multiline table with caption:
28+
29+Here's the caption. It may span multiple lines.
30+| Centered Header |Left Aligned | Right Aligned|Default aligned |
31+|:-----------------:|:-------------|--------------:|:------------------------------------------------------|
32+| First |row | 12.0|Example of a row that spans multiple lines. |
33+| Second |row | 5.0|Here's another one. Note the blank line between rows. |
34+
35+Multiline table without caption:
36+
37+| Centered Header |Left Aligned | Right Aligned|Default aligned |
38+|:-----------------:|:-------------|--------------:|:------------------------------------------------------|
39+| First |row | 12.0|Example of a row that spans multiple lines. |
40+| Second |row | 5.0|Here's another one. Note the blank line between rows. |
41+
42+Table without column headers:
43+
44+| 12|12 | 12 | 12|
45+|----:|:----|:-----:|----:|
46+| 12|12 | 12 | 12|
47+| 123|123 | 123 | 123|
48+| 1|1 | 1 | 1|
49+
50+Multiline table without column headers:
51+
52+| First |row | 12.0|Example of a row that spans multiple lines. |
53+|:--------:|:----|-----:|-----------------------------------------------------|
54+| First |row | 12.0|Example of a row that spans multiple lines. |
55+| Second |row | 5.0|Here's another one. Note the blank line between rows.|
56+
tests/writer.zimwikinew file+627
@@ -0,0 +1,627 @@
1+Content-Type: text/x-zim-wiki
2+Wiki-Format: zim 0.4
3+
4+This is a set of tests for pandoc. Most of them are adapted from John Gruber’s markdown test suite.
5+
6+
7+----
8+
9+====== Headers ======
10+
11+===== Level 2 with an embedded link =====
12+
13+==== Level 3 with emphasis ====
14+
15+=== Level 4 ===
16+
17+== Level 5 ==
18+
19+====== Level 1 ======
20+
21+===== Level 2 with emphasis =====
22+
23+==== Level 3 ====
24+
25+with no blank line
26+
27+===== Level 2 =====
28+
29+with no blank line
30+
31+
32+----
33+
34+====== Paragraphs ======
35+
36+Here’s a regular paragraph.
37+
38+In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item. Because a hard-wrapped line in the middle of a paragraph looked like a list item.
39+
40+Here’s one with a bullet. * criminey.
41+
42+There should be a hard line break
43+here.
44+
45+
46+----
47+
48+====== Block Quotes ======
49+
50+E-mail style:
51+
52+> This is a block quote. It is pretty short.
53+
54+> Code in a block quote:
55+>
56+> '''
57+> sub status {
58+> print "working";
59+> }
60+> '''
61+>
62+> A list:
63+>
64+> 1. item one
65+> 1. item two
66+>
67+> Nested block quotes:
68+>
69+> > nested
70+>
71+> > nested
72+
73+This should not be a block quote: 2 > 1.
74+
75+And a following paragraph.
76+
77+
78+----
79+
80+====== Code Blocks ======
81+
82+Code:
83+
84+'''
85+---- (should be four hyphens)
86+
87+sub status {
88+ print "working";
89+}
90+
91+this code block is indented by one tab
92+'''
93+
94+And:
95+
96+'''
97+ this code block is indented by two tabs
98+
99+These should not be escaped: \$ \\ \> \[ \{
100+'''
101+
102+
103+----
104+
105+====== Lists ======
106+
107+===== Unordered =====
108+
109+Asterisks tight:
110+
111+ * asterisk 1
112+ * asterisk 2
113+ * asterisk 3
114+
115+Asterisks loose:
116+
117+ * asterisk 1
118+ * asterisk 2
119+ * asterisk 3
120+
121+Pluses tight:
122+
123+ * Plus 1
124+ * Plus 2
125+ * Plus 3
126+
127+Pluses loose:
128+
129+ * Plus 1
130+ * Plus 2
131+ * Plus 3
132+
133+Minuses tight:
134+
135+ * Minus 1
136+ * Minus 2
137+ * Minus 3
138+
139+Minuses loose:
140+
141+ * Minus 1
142+ * Minus 2
143+ * Minus 3
144+
145+===== Ordered =====
146+
147+Tight:
148+
149+ 1. First
150+ 1. Second
151+ 1. Third
152+
153+and:
154+
155+ 1. One
156+ 1. Two
157+ 1. Three
158+
159+Loose using tabs:
160+
161+ 1. First
162+ 1. Second
163+ 1. Third
164+
165+and using spaces:
166+
167+ 1. One
168+ 1. Two
169+ 1. Three
170+
171+Multiple paragraphs:
172+
173+ 1. Item 1, graf one.
174+Item 1. graf two. The quick brown fox jumped over the lazy dog’s back.
175+ 1. Item 2.
176+ 1. Item 3.
177+
178+===== Nested =====
179+
180+ * Tab
181+ * Tab
182+ * Tab
183+
184+Here’s another:
185+
186+ 1. First
187+ 1. Second:
188+ * Fee
189+ * Fie
190+ * Foe
191+ 1. Third
192+
193+Same thing but with paragraphs:
194+
195+ 1. First
196+ 1. Second:
197+ * Fee
198+ * Fie
199+ * Foe
200+ 1. Third
201+
202+===== Tabs and spaces =====
203+
204+ * this is a list item indented with tabs
205+ * this is a list item indented with spaces
206+ * this is an example list item indented with tabs
207+ * this is an example list item indented with spaces
208+
209+===== Fancy list markers =====
210+
211+ 1. begins with 2
212+ 1. and now 3
213+with a continuation
214+ 1. sublist with roman numerals, starting with 4
215+ 1. more items
216+ 1. a subsublist
217+ 1. a subsublist
218+
219+Nesting:
220+
221+ 1. Upper Alpha
222+ 1. Upper Roman.
223+ 1. Decimal start with 6
224+ 1. Lower alpha with paren
225+
226+Autonumbering:
227+
228+ 1. Autonumber.
229+ 1. More.
230+ 1. Nested.
231+
232+Should not be a list item:
233+
234+M.A. 2007
235+
236+B. Williams
237+
238+
239+----
240+
241+====== Definition Lists ======
242+
243+Tight using spaces:
244+
245+* **apple** red fruit
246+* **orange** orange fruit
247+* **banana** yellow fruit
248+Tight using tabs:
249+
250+* **apple** red fruit
251+* **orange** orange fruit
252+* **banana** yellow fruit
253+Loose:
254+
255+* **apple** red fruit
256+
257+* **orange** orange fruit
258+
259+* **banana** yellow fruit
260+
261+Multiple blocks with italics:
262+
263+* **//apple//** red fruit
264+
265+contains seeds, crisp, pleasant to taste
266+
267+* **//orange//** orange fruit
268+
269+'''
270+{ orange code block }
271+'''
272+
273+> orange block quote
274+
275+Multiple definitions, tight:
276+
277+* **apple** red fruitcomputer
278+* **orange** orange fruitbank
279+Multiple definitions, loose:
280+
281+* **apple** red fruit
282+computer
283+
284+* **orange** orange fruit
285+bank
286+
287+Blank line after term, indented marker, alternate markers:
288+
289+* **apple** red fruit
290+computer
291+
292+* **orange** orange fruit
293+
294+ 1. sublist
295+ 1. sublist
296+
297+====== HTML Blocks ======
298+
299+Simple block on one line:
300+
301+foo
302+
303+And nested without indentation:
304+
305+foo
306+
307+
308+
309+bar
310+
311+
312+Interpreted markdown in a table:
313+
314+
315+
316+
317+This is //emphasized//
318+
319+
320+And this is **strong**
321+
322+
323+
324+
325+Here’s a simple block:
326+
327+foo
328+
329+
330+This should be a code block, though:
331+
332+'''
333+<div>
334+ foo
335+</div>
336+'''
337+
338+As should this:
339+
340+'''
341+<div>foo</div>
342+'''
343+
344+Now, nested:
345+
346+foo
347+
348+
349+
350+This should just be an HTML comment:
351+
352+
353+Multiline:
354+
355+
356+
357+Code block:
358+
359+'''
360+<!-- Comment -->
361+'''
362+
363+Just plain comment, with trailing spaces on the line:
364+
365+
366+Code:
367+
368+'''
369+<hr />
370+'''
371+
372+Hr’s:
373+
374+
375+
376+
377+
378+
379+
380+
381+
382+
383+
384+----
385+
386+====== Inline Markup ======
387+
388+This is //emphasized//, and so //is this//.
389+
390+This is **strong**, and so **is this**.
391+
392+An //[[url|emphasized link]]//.
393+
394+**//This is strong and em.//**
395+
396+So is **//this//** word.
397+
398+**//This is strong and em.//**
399+
400+So is **//this//** word.
401+
402+This is code: ''>'', ''$'', ''\'', ''\$'', ''<html>''.
403+
404+~~This is //strikeout//.~~
405+
406+Superscripts: a^{bc}d a^{//hello//} a^{hello there}.
407+
408+Subscripts: H_{2}O, H_{23}O, H_{many of them}O.
409+
410+These should not be superscripts or subscripts, because of the unescaped spaces: a^b c^d, a~b c~d.
411+
412+
413+----
414+
415+====== Smart quotes, ellipses, dashes ======
416+
417+“Hello,” said the spider. “‘Shelob’ is my name.”
418+
419+‘A’, ‘B’, and ‘C’ are letters.
420+
421+‘Oak,’ ‘elm,’ and ‘beech’ are names of trees. So is ‘pine.’
422+
423+‘He said, “I want to go.”’ Were you alive in the 70’s?
424+
425+Here is some quoted ‘''code''’ and a “[[http://example.com/?foo=1&bar=2|quoted link]]”.
426+
427+Some dashes: one—two — three—four — five.
428+
429+Dashes between numbers: 5–7, 255–66, 1987–1999.
430+
431+Ellipses…and…and….
432+
433+
434+----
435+
436+====== LaTeX ======
437+
438+ *
439+ * $2+2=4$
440+ * $x \in y$
441+ * $\alpha \wedge \omega$
442+ * $223$
443+ * $p$-Tree
444+ * Here’s some display math: $$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$$
445+ * Here’s one that has a line break in it: $\alpha + \omega \times x^2$.
446+
447+These shouldn’t be math:
448+
449+ * To get the famous equation, write ''$e = mc^2$''.
450+ * $22,000 is a //lot// of money. So is $34,000. (It worked if “lot” is emphasized.)
451+ * Shoes ($20) and socks ($5).
452+ * Escaped ''$'': $73 //this should be emphasized// 23$.
453+
454+Here’s a LaTeX table:
455+
456+
457+
458+----
459+
460+====== Special Characters ======
461+
462+Here is some unicode:
463+
464+ * I hat: Î
465+ * o umlaut: ö
466+ * section: §
467+ * set membership: ∈
468+ * copyright: ©
469+
470+AT&T has an ampersand in their name.
471+
472+AT&T is another way to write it.
473+
474+This & that.
475+
476+4 < 5.
477+
478+6 > 5.
479+
480+Backslash: \
481+
482+Backtick: `
483+
484+Asterisk: *
485+
486+Underscore: _
487+
488+Left brace: {
489+
490+Right brace: }
491+
492+Left bracket: [
493+
494+Right bracket: ]
495+
496+Left paren: (
497+
498+Right paren: )
499+
500+Greater-than: >
501+
502+Hash: #
503+
504+Period: .
505+
506+Bang: !
507+
508+Plus: +
509+
510+Minus: -
511+
512+
513+----
514+
515+====== Links ======
516+
517+===== Explicit =====
518+
519+Just a [[url/|URL]].
520+
521+[[url/|URL and title]].
522+
523+[[url/|URL and title]].
524+
525+[[url/|URL and title]].
526+
527+[[url/|URL and title]]
528+
529+[[url/|URL and title]]
530+
531+[[url/with_underscore|with_underscore]]
532+
533+[[mailto:nobody@nowhere.net|Email link]]
534+
535+[[|Empty]].
536+
537+===== Reference =====
538+
539+Foo [[url/|bar]].
540+
541+Foo [[url/|bar]].
542+
543+Foo [[url/|bar]].
544+
545+With [[url/|embedded [brackets]]].
546+
547+[[url/|b]] by itself should be a link.
548+
549+Indented [[url|once]].
550+
551+Indented [[url|twice]].
552+
553+Indented [[url|thrice]].
554+
555+This should [not][] be a link.
556+
557+'''
558+[not]: /url
559+'''
560+
561+Foo [[url/|bar]].
562+
563+Foo [[url/|biz]].
564+
565+===== With ampersands =====
566+
567+Here’s a [[http://example.com/?foo=1&bar=2|link with an ampersand in the URL]].
568+
569+Here’s a link with an amersand in the link text: [[http://att.com/|AT&T]].
570+
571+Here’s an [[script?foo=1&bar=2|inline link]].
572+
573+Here’s an [[script?foo=1&bar=2|inline link in pointy braces]].
574+
575+===== Autolinks =====
576+
577+With an ampersand: http://example.com/?foo=1&bar=2
578+
579+ * In a list?
580+ * http://example.com/
581+ * It should.
582+
583+An e-mail address: <nobody@nowhere.net>
584+
585+> Blockquoted: http://example.com/
586+
587+Auto-links should not occur here: ''<http://example.com/>''
588+
589+'''
590+or here: <http://example.com/>
591+'''
592+
593+
594+----
595+
596+====== Images ======
597+
598+From “Voyage dans la Lune” by Georges Melies (1902):
599+
600+{{:lalune.jpg|Voyage dans la Lune lalune}}
601+
602+Here is a movie {{:movie.jpg|movie}} icon.
603+
604+
605+----
606+
607+====== Footnotes ======
608+
609+Here is a footnote reference,((Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of the document.
610+)) and another.((Here’s the long note. This one contains multiple blocks.
611+
612+Subsequent blocks are indented to show that they belong to the footnote (as with list items).
613+
614+'''
615+ { <code> }
616+'''
617+
618+If you want, you can indent every line, but you can also be lazy and just indent the first line of each block.
619+)) This should //not// be a footnote reference, because it contains a space.[^my note] Here is an inline note.((This is //easier// to type. Inline notes may contain [[http://google.com|links]] and '']'' verbatim characters, as well as [bracketed text].
620+))
621+
622+> Notes can go in quotes.((In quote.
623+> ))
624+
625+ 1. And in list items.((In list.))
626+
627+This paragraph should not be part of the note, as it is not indented.