git.iko.soy/typeable/pandoc
on master help sign in
Removed plugin support.

Plugins will probably be added in a later version, but for now we want to avoid the heavy GHC API dependency. Also, plugins are very slow with the current system. git-svn-id: https://pandoc.googlecode.com/svn/trunk@1548 788f1e2b-df1e-0410-8736-df70ead52e1b

commit5f3a147dfdee17a05fba87ece8629fa19e95a1c9 authorfiddlosopher <fiddlosopher@788f1e2b-df1e-0410-8736-df70ead52e1b> dateTue 24 Feb 2009, 22:59 (18 years ago) parentbb639d5
6 files changed+8−332
README−217 changelog+3−13 man/man1/pandoc.1.md−8 pandoc.cabal+2−9 src/Text/Pandoc/Plugins.hs−69 src/pandoc.hs+3−16
README−217
@@ -309,14 +309,6 @@ For further documentation, see the `pandoc(1)` man page.
309309 repeatedly to include multiple files. They will be included in the
310310 order specified.
311311
312−`-P` *MODULE[,MODULE...]*, `--plugins`*=MODULE[,MODULE...]*
313−: specifies plugins to load, by module name or source file pathname.
314− Plugins should export a function `transform` of type `a -> a`
315− or `a -> IO a`, where `a` is `Inline`, `Block`, `Pandoc`,
316− `[Inline]`, or `[Block]`. This function will be used to transform
317− the pandoc document after it is parsed by the reader and before it
318− is written out by the writer. (See below on [Plugins](#plugins).)
319−
320312`-T` or `--title-prefix` *string*
321313: includes *string* as a prefix at the beginning of the title that
322314 appears in the HTML header (but not in the title as it appears at
@@ -1124,212 +1116,3 @@ ordinary HTML (without bird tracks).
11241116writes HTML with the Haskell code in bird tracks, so it can be copied
11251117and pasted as literate Haskell source.
11261118
1127−Plugins
1128−=======
1129−
1130−Pandoc's plugin system allows users to modify pandoc's behavior by writing
1131−short Haskell programs. To how this works, and why it is useful, we
1132− need to understand that pandoc transforms one format (the source
1133−format) into another (the target format) by first converting from the
1134−source format into a Haskell data structure representing the document,
1135−and then converting this data structure into the target format. For
1136−example:
1137−
1138− -------------------------------------------------------------------------------
1139− Document Format Contents
1140− ------------ --------- -----------------------------------------------------
1141− source markdown `Hello *world*.`
1142−
1143− ↓ ↓ ↓
1144−
1145− intermediate native `Pandoc (Meta [] [] "")
1146− [Para [Str "Hello",Space,Emph [Str "world"],Str "."]]`
1147−
1148− ↓ ↓ ↓
1149−
1150− target HTML `<p>Hello <em>world</em>.</p>`
1151− -------------------------------------------------------------------------------
1152−
1153−We can use standard text-processing tools (`perl`, `sed`, `awk`, etc.)
1154−to modify the source or target documents. But what if we want to modify
1155−the intermediate representation -- the parsed document -- before it is
1156−written to the target format? That's where plugins are needed.
1157−A plugin is a Haskell module that exports a function `transform`, which
1158−will be used to transform the native representation, after it is generated
1159−by the reader, but before it has been transformed by the writer.
1160−
1161−An example will help make this clearer. Suppose we want to use pandoc with
1162−the WordPress blog engine. WordPress provides support for LaTeX math, but
1163−instead of `$e = mc^2$`, WordPress wants `$LaTeX e = mc^2$`. Prior to plugins,
1164−there was no good way to make pandoc do this. We could have tried using
1165−regex replacements on the markdown input or HTML output, but this would have
1166−been error-prone: if someone writes `$e = mc^2$` in a code block, for
1167−example, we wouldn't want to insert `LaTeX` there. There's no good way to
1168−identify the math chunks without parsing the whole document. And pandoc
1169−is already doing that, so why not make use of this work? By writing a
1170−plugin, we can. Here's the whole plugin:
1171−
1172−~~~ {.haskell}
1173−-- WordPressPlugin.hs
1174−module WordPressPlugin (transform) where
1175−import Text.Pandoc
1176−
1177−transform :: Inline -> Inline
1178−transform (Math x y) = Math x $ "LaTeX " ++ y
1179−transform x = x
1180−~~~
1181−
1182−This is a Haskell program, but a very short one. The lines
1183−
1184−~~~ {.haskell}
1185−module WordPressPlugin (transform) where
1186−import Text.Pandoc
1187−~~~
1188−
1189−just define the name of the module (`WordPressPlugin`), the names of any
1190−exported functions (for a plugin, this will always just be `transform`),
1191−and the modules that will be used in the program itself (`Text.Pandoc`).
1192−Every plugin must export a function named `transform`.
1193−
1194−The real meat of the program is the three-line definition of `transform`:
1195−
1196−~~~ {.haskell}
1197−transform :: Inline -> Inline
1198−transform (Math x y) = Math x $ "LaTeX " ++ y
1199−transform x = x
1200−~~~
1201−
1202−The first line defines the type of the function: it is a function that
1203−takes an `Inline` element and returns an `Inline` element. (For the definition
1204−of `Inline`, see the module `Text.Pandoc.Definition`.) The `transform`
1205−function in a plugin need not be `Inline -> Inline`, but it must have
1206−type `a -> a` or `a -> IO a`, where `a` is `Pandoc`, `Block`, `Inline`,
1207−`[Block]`, or `[Inline]`.
1208−
1209−The next line says that when the input matches the pattern `Math x y`,
1210−the string `LaTeX ` should be inserted at the beginning of `y`. (The `x`
1211−just specifies whether the math element is inline or display math, so
1212−we leave it alone.) The last line says, in effect, that the `transform`
1213−function has no effect on any other kind of `Inline` element -- it just
1214−passes it through. When the plugin is applied, this transformation will
1215−be used on every `Inline` element in the document, and `LaTeX ` will be
1216−inserted where needed in math elements.
1217−
1218−To use this plugin, we just specify the module (or alternatively the filename)
1219−with the `--plugins` option:
1220−
1221− % echo "Hello, $e=mc^2$." | pandoc -m --plugins=WordPressPlugin.hs
1222− <p
1223− >Hello, <span class="LaTeX"
1224− >$LaTeX e=mc^2$</span
1225− >.</p
1226− >
1227−
1228−Let's look at a more complex example, involving IO. Suppose we want to include
1229−some [graphviz](http://www.graphviz.org/) diagrams in our document.
1230−Of course, we could use a Makefile to generate the diagrams, then use
1231−regular images in our document. But wouldn't it be nicer just to include
1232−the graphviz code in the document itself, perhaps in a specially marked
1233−delimited code block?
1234−
1235− ~~~ {.dot name="diagram1"}
1236− graph G {
1237− e
1238− subgraph clusterA {
1239− a -- b;
1240− subgraph clusterC {
1241− C -- D;
1242− }
1243− }
1244− subgraph clusterB {
1245− d -- f
1246− }
1247− d -- D
1248− e -- clusterB
1249− clusterC -- clusterB
1250− }
1251− ~~~
1252−
1253−This can be accomplished by a plugin:
1254−
1255−~~~ {.haskell}
1256−-- DotPlugin.hs
1257−module DotPlugin (transform) where
1258−import Text.Pandoc
1259−import Text.Pandoc.Shared
1260−import System.Process (readProcess)
1261−import Data.Char (ord)
1262−-- from the utf8-string package on HackageDB:
1263−import Data.ByteString.Lazy.UTF8 (fromString)
1264−-- from the SHA package on HackageDB:
1265−import Data.Digest.Pure.SHA
1266−
1267−transform :: Block -> IO Block
1268−transform (CodeBlock (id, classes, namevals) contents) | "dot" `elem` classes = do
1269− let (name, outfile) = case lookup "name" namevals of
1270− Just fn -> ([Str fn], fn ++ ".png")
1271− Nothing -> ([], uniqueName contents ++ ".png")
1272− result <- readProcess "dot" ["-Tpng"] contents
1273− writeFile outfile result
1274− return $ Para [Image name (outfile, "")]
1275−transform x = return x
1276−
1277−-- | Generate a unique filename given the file's contents.
1278−uniqueName :: String -> String
1279−uniqueName = showDigest . sha1 . fromString
1280−~~~
1281−
1282−The heart of this plugin is the `transform` function, which converts a `Block`
1283−to a `Block`. Again, there are two clauses, one for code blocks that are marked
1284−with the "dot" class, one for all other blocks. Code blocks with ".dot" are
1285−replaced with links to an image file; this file is generated by running
1286−`dot -Tpng` on the contents of the code block.
1287−
1288−Because `transform` performs file reads and writes, it needs to be in the
1289−IO monad, hence the type: `Block -> IO Block`.
1290−
1291−One more example. Suppose we want emphasized text to be CAPITALIZED
1292−instead of italicized. We could use a plugin:
1293−
1294−~~~ {.haskell}
1295−module CapitalizeEmphasisPlugin (transform) where
1296−import Text.Pandoc
1297−import Data.Char (toUpper)
1298−
1299−transform :: [Inline] -> [Inline]
1300−transform (Emph xs : ys) = processWith capStr xs ++ transform ys
1301−transform (x : ys) = x : transform ys
1302−transform [] = []
1303−
1304−capStr :: Inline -> Inline
1305−capStr (Str x) = Str (map toUpper x)
1306−capStr x = x
1307−~~~
1308−
1309−Here `transform` converts a whole list of `Inline` elements to another
1310−such list. The key clause is
1311−
1312−~~~ {.haskell}
1313−transform (Emph xs : ys) = processWith capStr xs ++ transform ys
1314−~~~
1315−
1316−This applies the `capStr` function recursively to all inlines in the
1317−list of emphasized inlines and puts the transformed list in place
1318−of the original. `capStr` is a simple `Inline` transformation that
1319−capitalizes `Str` elements and leaves everything else alone. The
1320−function `processWith`, defined in `Text.Pandoc.Definition`, uses some
1321−`Data.Generics` magic to apply its argument (here `capStr`) to every
1322−`Inline` element in a list, including elements that are deeply buried in
1323−other elements. Thus
1324−
1325− processWith captStr [Str "one", Strong [Str "two", Space]] ==>
1326− [Str "ONE", Strong [Str "TWO", Space]]
1327−
1328−There are other sample plugins in the `plugins` subdirectory of the
1329−pandoc source code.
1330−
1331−**Note:** Do not attempt to use plugins when running pandoc in the
1332−directory containing pandoc's source code. The interpreter will try to
1333−load the files directly from the source code, rather than reading the compiled
1334−versions, and pandoc will hang.
1335−
changelog+3−13
@@ -16,19 +16,9 @@ pandoc (1.2)
1616 + Added tests (run only if highlighting support compiled in).
1717 + Documented lhs features in man page and README.
1818
19− * Added a plugin system, based on hint. This allows users to
20− write small interpreted Haskell programs that transform the
21− AST between the reader and the writer.
22−
23− + In Text.Pandoc.Definition, added processWith, processWithM,
24− and queryWith, and deprecated processPandoc and queryPandoc
25− for these more general functions, which are useful in writing
26− plugins.
27− + Added module Text.Pandoc.Plugins.
28− + Added a --plugins option to pandoc, and code to run the parsed
29− document through all the plugins.
30− + Provided five sample plugin files in the plugins/ directory.
31− + Documented --plugin in the pandoc man page and README.
19+ * In Text.Pandoc.Definition, added processWith, processWithM,
20+ and queryWith, and deprecated processPandoc and queryPandoc
21+ for these more general functions.
3222
3323 * Fixed bug in mediawiki writer: improper closing tags in tables.
3424 Thanks to Benct Philip Jonsson for reporting the bug.
man/man1/pandoc.1.md−8
@@ -181,14 +181,6 @@ to Pandoc. Or use `html2markdown`(1), a wrapper around `pandoc`.
181181 `context`, `docbook`, `man`, `markdown`, `opendocument`,
182182 `rst`, `rtf`).
183183
184−-P *MODULE[,MODULE...]*, \--plugins=*MODULE[,MODULE...]*
185−: Specify plugins to load, by module name or source file pathname.
186− Plugins should export a function `transform` of type `a -> a`
187− or `a -> IO a`, where `a` is `Inline`, `Block`, `Pandoc`,
188− `[Inline]`, or `[Block]`. This function will be used to transform
189− the pandoc document after it is parsed by the reader and before it
190− is written out by the writer.
191−
192184-T *STRING*, \--title-prefix=*STRING*
193185: Specify *STRING* as a prefix to the HTML window title.
194186
pandoc.cabal+2−9
@@ -38,13 +38,7 @@ Data-Files:
3838 -- documentation
3939 README, INSTALL, COPYRIGHT, BUGS, changelog,
4040 -- wrappers
41− markdown2pdf, html2markdown, hsmarkdown,
42− -- sample plugins
43− plugins/WordPressPlugin.hs,
44− plugins/CapitalizeEmphasisPlugin.hs,
45− plugins/IncludeFilePlugin.hs,
46− plugins/DotPlugin.hs,
47− plugins/ListLinksPlugin.hs
41+ markdown2pdf, html2markdown, hsmarkdown
4842Extra-Source-Files:
4943 -- sources for man pages
5044 man/man1/pandoc.1.md, man/man1/markdown2pdf.1.md,
@@ -159,7 +153,7 @@ Library
159153 mtl >= 1.1, network >= 2, filepath >= 1.1,
160154 process >= 1, directory >= 1, template-haskell >= 2.2,
161155 bytestring >= 0.9, zip-archive >= 0.1.1,
162− utf8-string >= 0.3, old-time >= 1, hint >= 0.3.0.0
156+ utf8-string >= 0.3, old-time >= 1
163157 if impl(ghc >= 6.10)
164158 Build-depends: base >= 4, syb
165159 else
@@ -178,7 +172,6 @@ Library
178172 Text.Pandoc.CharacterReferences,
179173 Text.Pandoc.Shared,
180174 Text.Pandoc.ODT,
181− Text.Pandoc.Plugins,
182175 Text.Pandoc.LaTeXMathML,
183176 Text.Pandoc.DefaultHeaders,
184177 Text.Pandoc.Highlighting,
src/Text/Pandoc/Plugins.hsdeleted−69
@@ -1,69 +0,0 @@
1−{-
2−Copyright (C) 2008 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.Pluigns
21− Copyright : Copyright (C) 2008 John MacFarlane
22− License : GNU GPL, version 2 or above
23−
24− Maintainer : John MacFarlane <jgm@berkeley.edu>
25− Stability : alpha
26− Portability : portable
27−
28−Support for plugins.
29−-}
30−
31−module Text.Pandoc.Plugins (getPlugin)
32−where
33−
34−import Language.Haskell.Interpreter
35−import Text.Pandoc
36−import Control.Monad (unless, liftM)
37−import Control.Monad.Error (throwError)
38−import Data.List (isInfixOf)
39−
40−-- | Returns the function named @transform@ in the specified
41−-- module. The module may be identified either by module name
42−-- or by path name. The @transform@ function should have type
43−-- @a -> a@ or @a -> IO a@, where @a@ is an instance of 'Data':
44−-- for example, @Pandoc -> Pandoc@, @Inline -> IO Inline@,
45−-- @Block -> Block@, or @[Inline] -> IO [Inline]@.
46−getPlugin :: String -> IO (Pandoc -> IO Pandoc)
47−getPlugin modsrc = do
48− res <- runInterpreter (evaluatePlugin modsrc)
49− case res of
50− Right func -> return func
51− Left (WontCompile xs) -> error $ "WontCompile error for plugin '" ++ modsrc ++ "'\n" ++ unlines (map errMsg xs)
52− Left (NotAllowed x) -> error $ "NotAllowed error for plugin '" ++ modsrc ++ "'\n" ++ x
53− Left (UnknownError x) -> error $ "UnknownError for plugin '" ++ modsrc ++ "'\n" ++ x
54− Left (GhcException x) -> error $ "GhcException for plugin '" ++ modsrc ++ "'\n" ++ x
55−
56−evaluatePlugin :: String -> Interpreter (Pandoc -> IO Pandoc)
57−evaluatePlugin modsrc = do
58− set [installedModulesInScope := False]
59− loadModules [modsrc]
60− modnames <- getLoadedModules
61− setTopLevelModules modnames
62− setImports ["Prelude", "Text.Pandoc", "Text.Pandoc.Definition"]
63− exports <- liftM concat $ mapM getModuleExports modnames
64− unless ((Fun "transform") `elem` exports) $
65− throwError $ UnknownError $ "The plugin module must define a function 'transform'."
66− transformType <- typeOf "transform"
67− if "-> IO" `isInfixOf` transformType
68− then interpret "processWithM transform" (as :: Pandoc -> IO Pandoc)
69− else interpret "return . (processWith transform)" (as :: Pandoc -> IO Pandoc)
src/pandoc.hs+3−16
@@ -32,7 +32,7 @@ writers.
3232module Main where
3333import Text.Pandoc
3434import Text.Pandoc.ODT
35−import Text.Pandoc.Shared ( HTMLMathMethod (..), splitBy, tabFilter, ObfuscationMethod (..) )
35+import Text.Pandoc.Shared ( HTMLMathMethod (..), tabFilter, ObfuscationMethod (..) )
3636import Text.Pandoc.Highlighting ( languages )
3737import System.Environment ( getArgs, getProgName, getEnvironment )
3838import System.Exit ( exitWith, ExitCode (..) )
@@ -48,8 +48,7 @@ import System.IO.UTF8
4848import Text.CSL
4949import Text.Pandoc.Biblio
5050#endif
51−import Text.Pandoc.Plugins (getPlugin)
52−import Control.Monad (foldM, when, unless)
51+import Control.Monad (when, unless)
5352
5453copyrightMessage :: String
5554copyrightMessage = "\nCopyright (C) 2006-8 John MacFarlane\n" ++
@@ -365,15 +364,6 @@ options =
365364 "FILENAME")
366365 "" -- "File to use for custom header (implies -s)"
367366
368− , Option "P" ["plugins"]
369− (ReqArg
370− (\arg opt -> do
371− let pluginModules = splitBy ',' arg
372− plugins <- mapM getPlugin pluginModules
373− return opt { optPlugins = plugins })
374− "MODULE[,MODULE...]")
375− "" -- "Haskell modules"
376−
377367 , Option "T" ["title-prefix"]
378368 (ReqArg
379369 (\arg opt -> return opt { optTitlePrefix = arg,
@@ -540,7 +530,6 @@ main = do
540530 , optReferenceLinks = referenceLinks
541531 , optWrapText = wrap
542532 , optSanitizeHTML = sanitize
543− , optPlugins = plugins
544533 , optEmailObfuscation = obfuscationMethod
545534#ifdef _CITEPROC
546535 , optBiblioFile = biblioFile
@@ -653,9 +642,7 @@ main = do
653642 return doc
654643#endif
655644
656− doc'' <- foldM (flip ($)) doc' plugins
657−
658− let writerOutput = writer writerOptions doc'' ++ "\n"
645+ let writerOutput = writer writerOptions doc' ++ "\n"
659646
660647 case writerName' of
661648 "odt" -> saveOpenDocumentAsODT outputFile sourceDirRelative writerOutput