git.iko.soy/typeable/pandoc
on master help sign in
Merge branch 'opml'
commit8aa617238042ce8605863e4526e8f5002647fd97 authorJohn MacFarlane <fiddlosopher@gmail.com> dateTue 19 Mar 2013, 20:23 (14 years ago) parentd596b0d74d53f4
8 files changed+268−4
README+4−3 pandoc.cabal+4−1 pandoc.hs+1 src/Text/Pandoc.hs+3 src/Text/Pandoc/Readers/OPML.hs+95 tests/Tests/Old.hs+4 tests/opml-reader.native+66 tests/opml-reader.opml+91
README+4−3
@@ -13,8 +13,8 @@ Description
1313Pandoc is a [Haskell] library for converting from one markup format to
1414another, and a command-line tool that uses this library. It can read
1515[markdown] and (subsets of) [Textile], [reStructuredText], [HTML],
16−[LaTeX], [MediaWiki markup], and [DocBook XML]; and it can write plain
17−text, [markdown], [reStructuredText], [XHTML], [HTML 5], [LaTeX]
16+[LaTeX], [MediaWiki markup], [OPML], and [DocBook XML]; and it can write
17+plain text, [markdown], [reStructuredText], [XHTML], [HTML 5], [LaTeX]
1818(including [beamer] slide shows), [ConTeXt], [RTF], [DocBook XML],
1919[OpenDocument XML], [ODT], [Word docx], [GNU Texinfo], [MediaWiki
2020markup], [EPUB] (v2 or v3), [FictionBook2], [Textile], [groff man] pages, [Emacs
@@ -143,7 +143,7 @@ General options
143143 `markdown_phpextra` (PHP Markdown Extra extended markdown),
144144 `markdown_github` (github extended markdown),
145145 `textile` (Textile), `rst` (reStructuredText), `html` (HTML),
146− `docbook` (DocBook XML), `mediawiki` (MediaWiki markup),
146+ `docbook` (DocBook XML), `opml` (OPML), `mediawiki` (MediaWiki markup),
147147 or `latex` (LaTeX). If `+lhs` is appended to `markdown`, `rst`,
148148 `latex`, the input will be treated as literate Haskell source:
149149 see [Literate Haskell support](#literate-haskell-support), below.
@@ -2624,6 +2624,7 @@ Sergey Astanin, Arlo O'Keeffe, Denis Laxalde, Brent Yorgey.
26242624[ConTeXt]: http://www.pragma-ade.nl/
26252625[RTF]: http://en.wikipedia.org/wiki/Rich_Text_Format
26262626[DocBook XML]: http://www.docbook.org/
2627+[OPML]: http://dev.opml.org/spec2.html
26272628[OpenDocument XML]: http://opendocument.xml.org/
26282629[ODT]: http://en.wikipedia.org/wiki/OpenDocument
26292630[Textile]: http://redcloth.org/textile
pandoc.cabal+4−1
@@ -16,7 +16,7 @@ Synopsis: Conversion between markup formats
1616Description: Pandoc is a Haskell library for converting from one markup
1717 format to another, and a command-line tool that uses
1818 this library. It can read markdown and (subsets of) HTML,
19− reStructuredText, LaTeX, DocBook, MediaWiki markup,
19+ reStructuredText, LaTeX, DocBook, MediaWiki markup, OPML,
2020 and Textile, and it can write markdown, reStructuredText,
2121 HTML, LaTeX, ConTeXt, Docbook, OpenDocument, ODT,
2222 Word docx, RTF, MediaWiki, Textile, groff man pages,
@@ -105,6 +105,8 @@ Extra-Source-Files:
105105 tests/docbook-reader.native
106106 tests/html-reader.html,
107107 tests/html-reader.native,
108+ tests/opml-reader.html,
109+ tests/opml-reader.native,
108110 tests/insert,
109111 tests/lalune.jpg,
110112 tests/movie.jpg,
@@ -278,6 +280,7 @@ Library
278280 Text.Pandoc.Readers.MediaWiki,
279281 Text.Pandoc.Readers.RST,
280282 Text.Pandoc.Readers.DocBook,
283+ Text.Pandoc.Readers.OPML,
281284 Text.Pandoc.Readers.TeXMath,
282285 Text.Pandoc.Readers.Textile,
283286 Text.Pandoc.Readers.Native,
pandoc.hs+1
@@ -758,6 +758,7 @@ defaultReaderName fallback (x:xs) =
758758 ".rst" -> "rst"
759759 ".lhs" -> "markdown+lhs"
760760 ".db" -> "docbook"
761+ ".opml" -> "opml"
761762 ".wiki" -> "mediawiki"
762763 ".textile" -> "textile"
763764 ".native" -> "native"
src/Text/Pandoc.hs+3
@@ -72,6 +72,7 @@ module Text.Pandoc
7272 , readHtml
7373 , readTextile
7474 , readDocBook
75+ , readOPML
7576 , readNative
7677 -- * Writers: converting /from/ Pandoc format
7778 , Writer (..)
@@ -113,6 +114,7 @@ import Text.Pandoc.Readers.Markdown
113114import Text.Pandoc.Readers.MediaWiki
114115import Text.Pandoc.Readers.RST
115116import Text.Pandoc.Readers.DocBook
117+import Text.Pandoc.Readers.OPML
116118import Text.Pandoc.Readers.LaTeX
117119import Text.Pandoc.Readers.HTML
118120import Text.Pandoc.Readers.Textile
@@ -192,6 +194,7 @@ readers = [("native" , \_ s -> return $ readNative s)
192194 ,("rst" , \o s -> return $ readRST o s)
193195 ,("mediawiki" , \o s -> return $ readMediaWiki o s)
194196 ,("docbook" , \o s -> return $ readDocBook o s)
197+ ,("opml" , \o s -> return $ readOPML o s)
195198 ,("textile" , \o s -> return $ readTextile o s) -- TODO : textile+lhs
196199 ,("html" , \o s -> return $ readHtml o s)
197200 ,("latex" , \o s -> return $ readLaTeX o s)
src/Text/Pandoc/Readers/OPML.hsnew file+95
@@ -0,0 +1,95 @@
1+module Text.Pandoc.Readers.OPML ( readOPML ) where
2+import Data.Char (toUpper)
3+import Text.Pandoc.Options
4+import Text.Pandoc.Definition
5+import Text.Pandoc.Builder
6+import Text.Pandoc.Readers.HTML (readHtml)
7+import Text.Pandoc.Readers.Markdown (readMarkdown)
8+import Text.XML.Light
9+import Text.HTML.TagSoup.Entity (lookupEntity)
10+import Data.Generics
11+import Data.Monoid
12+import Control.Monad.State
13+import Control.Applicative ((<$>), (<$))
14+
15+type OPML = State OPMLState
16+
17+data OPMLState = OPMLState{
18+ opmlSectionLevel :: Int
19+ , opmlDocTitle :: Inlines
20+ , opmlDocAuthors :: [Inlines]
21+ , opmlDocDate :: Inlines
22+ } deriving Show
23+
24+readOPML :: ReaderOptions -> String -> Pandoc
25+readOPML _ inp = setTitle (opmlDocTitle st')
26+ $ setAuthors (opmlDocAuthors st')
27+ $ setDate (opmlDocDate st')
28+ $ doc $ mconcat bs
29+ where (bs, st') = runState (mapM parseBlock $ normalizeTree $ parseXML inp)
30+ OPMLState{ opmlSectionLevel = 0
31+ , opmlDocTitle = mempty
32+ , opmlDocAuthors = []
33+ , opmlDocDate = mempty
34+ }
35+
36+-- normalize input, consolidating adjacent Text and CRef elements
37+normalizeTree :: [Content] -> [Content]
38+normalizeTree = everywhere (mkT go)
39+ where go :: [Content] -> [Content]
40+ go (Text (CData CDataRaw _ _):xs) = xs
41+ go (Text (CData CDataText s1 z):Text (CData CDataText s2 _):xs) =
42+ Text (CData CDataText (s1 ++ s2) z):xs
43+ go (Text (CData CDataText s1 z):CRef r:xs) =
44+ Text (CData CDataText (s1 ++ convertEntity r) z):xs
45+ go (CRef r:Text (CData CDataText s1 z):xs) =
46+ Text (CData CDataText (convertEntity r ++ s1) z):xs
47+ go (CRef r1:CRef r2:xs) =
48+ Text (CData CDataText (convertEntity r1 ++ convertEntity r2) Nothing):xs
49+ go xs = xs
50+
51+convertEntity :: String -> String
52+convertEntity e = maybe (map toUpper e) (:[]) (lookupEntity e)
53+
54+-- convenience function to get an attribute value, defaulting to ""
55+attrValue :: String -> Element -> String
56+attrValue attr elt =
57+ case lookupAttrBy (\x -> qName x == attr) (elAttribs elt) of
58+ Just z -> z
59+ Nothing -> ""
60+
61+asHtml :: String -> Inlines
62+asHtml s = case readHtml def s of
63+ Pandoc _ [Plain ils] -> fromList ils
64+ _ -> mempty
65+
66+asMarkdown :: String -> Blocks
67+asMarkdown s = fromList bs
68+ where Pandoc _ bs = readMarkdown def s
69+
70+getBlocks :: Element -> OPML Blocks
71+getBlocks e = mconcat <$> (mapM parseBlock $ elContent e)
72+
73+parseBlock :: Content -> OPML Blocks
74+parseBlock (Elem e) =
75+ case qName (elName e) of
76+ "ownerName" -> mempty <$ modify (\st ->
77+ st{opmlDocAuthors = [text $ strContent e]})
78+ "dateModified" -> mempty <$ modify (\st ->
79+ st{opmlDocDate = text $ strContent e})
80+ "title" -> mempty <$ modify (\st ->
81+ st{opmlDocTitle = text $ strContent e})
82+ "outline" -> gets opmlSectionLevel >>= sect . (+1)
83+ "?xml" -> return mempty
84+ _ -> getBlocks e
85+ where sect n = do let headerText = asHtml $ attrValue "text" e
86+ let noteBlocks = asMarkdown $ attrValue "_note" e
87+ modify $ \st -> st{ opmlSectionLevel = n }
88+ bs <- getBlocks e
89+ modify $ \st -> st{ opmlSectionLevel = n - 1 }
90+ let headerText' = case attrValue "type" e of
91+ "link" -> link
92+ (attrValue "url" e) "" headerText
93+ _ -> headerText
94+ return $ header n headerText' <> noteBlocks <> bs
95+parseBlock _ = return mempty
tests/Tests/Old.hs+4
@@ -124,6 +124,10 @@ tests = [ testGroup "markdown"
124124 , test "reader" ["-r", "mediawiki", "-w", "native", "-s"]
125125 "mediawiki-reader.wiki" "mediawiki-reader.native"
126126 ]
127+ , testGroup "opml"
128+ [ test "reader" ["-r", "opml", "-w", "native", "-s"]
129+ "opml-reader.opml" "opml-reader.native"
130+ ]
127131 , testGroup "other writers" $ map (\f -> testGroup f $ writerTests f)
128132 [ "opendocument" , "context" , "texinfo"
129133 , "man" , "plain" , "rtf", "org", "asciidoc"
tests/opml-reader.nativenew file+66
@@ -0,0 +1,66 @@
1+Pandoc (Meta {docTitle = [Str "states.opml"], docAuthors = [[Str "Dave",Space,Str "Winer"]], docDate = [Str "Thu,",Space,Str "14",Space,Str "Jul",Space,Str "2005",Space,Str "23:41:05",Space,Str "GMT"]})
2+[Header 1 ("",[],[]) [Str "United",Space,Str "States"]
3+,Header 2 ("",[],[]) [Str "Far",Space,Str "West"]
4+,Header 3 ("",[],[]) [Str "Alaska"]
5+,Header 3 ("",[],[]) [Str "California"]
6+,Header 3 ("",[],[]) [Str "Hawaii"]
7+,Header 3 ("",[],[]) [Strong [Str "Nevada"]]
8+,Para [Str "I",Space,Str "lived",Space,Str "here",Space,Emph [Str "once"],Str "."]
9+,Para [Str "Loved",Space,Str "it."]
10+,Header 4 ("",[],[]) [Link [Str "Reno"] ("http://www.reno.gov","")]
11+,Header 4 ("",[],[]) [Str "Las",Space,Str "Vegas"]
12+,Header 4 ("",[],[]) [Str "Ely"]
13+,Header 4 ("",[],[]) [Str "Gerlach"]
14+,Header 3 ("",[],[]) [Str "Oregon"]
15+,Header 3 ("",[],[]) [Str "Washington"]
16+,Header 2 ("",[],[]) [Str "Great",Space,Str "Plains"]
17+,Header 3 ("",[],[]) [Str "Kansas"]
18+,Header 3 ("",[],[]) [Str "Nebraska"]
19+,Header 3 ("",[],[]) [Str "North",Space,Str "Dakota"]
20+,Header 3 ("",[],[]) [Str "Oklahoma"]
21+,Header 3 ("",[],[]) [Str "South",Space,Str "Dakota"]
22+,Header 2 ("",[],[]) [Str "Mid",Str "-",Str "Atlantic"]
23+,Header 3 ("",[],[]) [Str "Delaware"]
24+,Header 3 ("",[],[]) [Str "Maryland"]
25+,Header 3 ("",[],[]) [Str "New",Space,Str "Jersey"]
26+,Header 3 ("",[],[]) [Str "New",Space,Str "York"]
27+,Header 3 ("",[],[]) [Str "Pennsylvania"]
28+,Header 2 ("",[],[]) [Str "Midwest"]
29+,Header 3 ("",[],[]) [Str "Illinois"]
30+,Header 3 ("",[],[]) [Str "Indiana"]
31+,Header 3 ("",[],[]) [Str "Iowa"]
32+,Header 3 ("",[],[]) [Str "Kentucky"]
33+,Header 3 ("",[],[]) [Str "Michigan"]
34+,Header 3 ("",[],[]) [Str "Minnesota"]
35+,Header 3 ("",[],[]) [Str "Missouri"]
36+,Header 3 ("",[],[]) [Str "Ohio"]
37+,Header 3 ("",[],[]) [Str "West",Space,Str "Virginia"]
38+,Header 3 ("",[],[]) [Str "Wisconsin"]
39+,Header 2 ("",[],[]) [Str "Mountains"]
40+,Header 3 ("",[],[]) [Str "Colorado"]
41+,Header 3 ("",[],[]) [Str "Idaho"]
42+,Header 3 ("",[],[]) [Str "Montana"]
43+,Header 3 ("",[],[]) [Str "Utah"]
44+,Header 3 ("",[],[]) [Str "Wyoming"]
45+,Header 2 ("",[],[]) [Str "New",Space,Str "England"]
46+,Header 3 ("",[],[]) [Str "Connecticut"]
47+,Header 3 ("",[],[]) [Str "Maine"]
48+,Header 3 ("",[],[]) [Str "Massachusetts"]
49+,Header 3 ("",[],[]) [Str "New",Space,Str "Hampshire"]
50+,Header 3 ("",[],[]) [Str "Rhode",Space,Str "Island"]
51+,Header 3 ("",[],[]) [Str "Vermont"]
52+,Header 2 ("",[],[]) [Str "South"]
53+,Header 3 ("",[],[]) [Str "Alabama"]
54+,Header 3 ("",[],[]) [Str "Arkansas"]
55+,Header 3 ("",[],[]) [Str "Florida"]
56+,Header 3 ("",[],[]) [Str "Georgia"]
57+,Header 3 ("",[],[]) [Str "Louisiana"]
58+,Header 3 ("",[],[]) [Str "Mississippi"]
59+,Header 3 ("",[],[]) [Str "North",Space,Str "Carolina"]
60+,Header 3 ("",[],[]) [Str "South",Space,Str "Carolina"]
61+,Header 3 ("",[],[]) [Str "Tennessee"]
62+,Header 3 ("",[],[]) [Str "Virginia"]
63+,Header 2 ("",[],[]) [Str "Southwest"]
64+,Header 3 ("",[],[]) [Str "Arizona"]
65+,Header 3 ("",[],[]) [Str "New",Space,Str "Mexico"]
66+,Header 3 ("",[],[]) [Str "Texas"]]
tests/opml-reader.opmlnew file+91
@@ -0,0 +1,91 @@
1+<?xml version="1.0" encoding="ISO-8859-1"?>
2+<opml version="2.0">
3+ <head>
4+ <title>states.opml</title>
5+ <dateCreated>Tue, 15 Mar 2005 16:35:45 GMT</dateCreated>
6+ <dateModified>Thu, 14 Jul 2005 23:41:05 GMT</dateModified>
7+ <ownerName>Dave Winer</ownerName>
8+ <ownerEmail>dave@scripting.com</ownerEmail>
9+ <expansionState>1, 6, 13, 16, 18, 20</expansionState>
10+ <vertScrollState>1</vertScrollState>
11+ <windowTop>106</windowTop>
12+ <windowLeft>106</windowLeft>
13+ <windowBottom>558</windowBottom>
14+ <windowRight>479</windowRight>
15+ </head>
16+ <body>
17+ <outline text="United States">
18+ <outline text="Far West">
19+ <outline text="Alaska"/>
20+ <outline text="California"/>
21+ <outline text="Hawaii"/>
22+ <outline text="&lt;strong&gt;Nevada&lt;/strong&gt;" _note="I lived here *once*.&#10;&#10;Loved it.">
23+ <outline text="Reno" created="Tue, 12 Jul 2005 23:56:35 GMT" type="link" url="http://www.reno.gov"/>
24+ <outline text="Las Vegas" created="Tue, 12 Jul 2005 23:56:37 GMT"/>
25+ <outline text="Ely" created="Tue, 12 Jul 2005 23:56:39 GMT"/>
26+ <outline text="Gerlach" created="Tue, 12 Jul 2005 23:56:47 GMT"/>
27+ </outline>
28+ <outline text="Oregon"/>
29+ <outline text="Washington"/>
30+ </outline>
31+ <outline text="Great Plains">
32+ <outline text="Kansas"/>
33+ <outline text="Nebraska"/>
34+ <outline text="North Dakota"/>
35+ <outline text="Oklahoma"/>
36+ <outline text="South Dakota"/>
37+ </outline>
38+ <outline text="Mid-Atlantic">
39+ <outline text="Delaware"/>
40+ <outline text="Maryland"/>
41+ <outline text="New Jersey"/>
42+ <outline text="New York"/>
43+ <outline text="Pennsylvania"/>
44+ </outline>
45+ <outline text="Midwest">
46+ <outline text="Illinois"/>
47+ <outline text="Indiana"/>
48+ <outline text="Iowa"/>
49+ <outline text="Kentucky"/>
50+ <outline text="Michigan"/>
51+ <outline text="Minnesota"/>
52+ <outline text="Missouri"/>
53+ <outline text="Ohio"/>
54+ <outline text="West Virginia"/>
55+ <outline text="Wisconsin"/>
56+ </outline>
57+ <outline text="Mountains">
58+ <outline text="Colorado"/>
59+ <outline text="Idaho"/>
60+ <outline text="Montana"/>
61+ <outline text="Utah"/>
62+ <outline text="Wyoming"/>
63+ </outline>
64+ <outline text="New England">
65+ <outline text="Connecticut"/>
66+ <outline text="Maine"/>
67+ <outline text="Massachusetts"/>
68+ <outline text="New Hampshire"/>
69+ <outline text="Rhode Island"/>
70+ <outline text="Vermont"/>
71+ </outline>
72+ <outline text="South">
73+ <outline text="Alabama"/>
74+ <outline text="Arkansas"/>
75+ <outline text="Florida"/>
76+ <outline text="Georgia"/>
77+ <outline text="Louisiana"/>
78+ <outline text="Mississippi"/>
79+ <outline text="North Carolina"/>
80+ <outline text="South Carolina"/>
81+ <outline text="Tennessee"/>
82+ <outline text="Virginia"/>
83+ </outline>
84+ <outline text="Southwest">
85+ <outline text="Arizona"/>
86+ <outline text="New Mexico"/>
87+ <outline text="Texas"/>
88+ </outline>
89+ </outline>
90+ </body>
91+ </opml>