git.iko.soy/typeable/pandoc
on master help sign in
More simplification of pandoc.hs.

Opt is now set up to contain only the basic content passed through the options -- further processing (lookup of styles, insertion of file contents, etc.) is now done later.

commit2c3eeca8dfb33226ff4d2ef24e389c352b96edaf authorJohn MacFarlane <jgm@berkeley.edu> dateSun 5 Feb 2017, 10:41 (10 years ago) parentde48851
1 file changed+130−151
pandoc.hs+130−151
pandoc.hs+130−151
@@ -115,79 +115,27 @@ addDeprecationNote x =
115115
116116convertWithOpts :: Opt -> [FilePath] -> IO ()
117117convertWithOpts opts args = do
118− let Opt { optTabStop = tabStop
119− , optPreserveTabs = preserveTabs
120− , optStandalone = standalone
121− , optReader = readerName
122− , optWriter = writerName
123− , optParseRaw = parseRaw
124− , optVariables = variables
125− , optMetadata = metadata
126− , optTableOfContents = toc
127− , optBaseHeaderLevel = baseHeaderLevel
128− , optTemplate = templatePath
129− , optOutputFile = outputFile
130− , optNumberSections = numberSections
131− , optNumberOffset = numberFrom
132− , optSectionDivs = sectionDivs
133− , optIncremental = incremental
134− , optSelfContained = selfContained
135− , optHtmlQTags = htmlQTags
136− , optHighlightStyle = mbHighlightStyle
137− , optTopLevelDivision = topLevelDivision
138− , optHTMLMathMethod = mathMethod'
139− , optReferenceDoc = referenceDoc
140− , optEpubStylesheet = mbEpubStylesheet
141− , optEpubMetadata = mbEpubMetadata
142− , optEpubFonts = epubFonts
143− , optEpubChapterLevel = epubChapterLevel
144− , optTOCDepth = epubTOCDepth
145− , optDumpArgs = dumpArgs
146− , optIgnoreArgs = ignoreArgs
147− , optVerbosity = verbosity
148− , optFailIfWarnings = failIfWarnings
149− , optReferenceLinks = referenceLinks
150− , optReferenceLocation = referenceLocation
151− , optDpi = dpi
152− , optWrapText = wrap
153− , optColumns = columns
154− , optFilters = filters
155− , optEmailObfuscation = obfuscationMethod
156− , optIdentifierPrefix = idPrefix
157− , optIndentedCodeClasses = codeBlockClasses
158− , optDataDir = mbDataDir
159− , optCiteMethod = citeMethod
160− , optListings = listings
161− , optLaTeXEngine = latexEngine
162− , optLaTeXEngineArgs = latexEngineArgs
163− , optSlideLevel = slideLevel
164− , optSetextHeaders = setextHeaders
165− , optAscii = ascii
166− , optDefaultImageExtension = defaultImageExtension
167− , optExtractMedia = mbExtractMedia
168− , optTrackChanges = trackChanges
169− , optFileScope = fileScope
170− , optKaTeXStylesheet = katexStylesheet
171− , optKaTeXJS = katexJS
172− } = opts
173−
174− when dumpArgs $
118+ let outputFile = optOutputFile opts
119+ let filters = optFilters opts
120+ let verbosity = optVerbosity opts
121+
122+ when (optDumpArgs opts) $
175123 do UTF8.hPutStrLn stdout outputFile
176124 mapM_ (UTF8.hPutStrLn stdout) args
177125 exitSuccess
178126
179− epubStylesheet <- case mbEpubStylesheet of
127+ epubStylesheet <- case optEpubStylesheet opts of
180128 Nothing -> return Nothing
181129 Just fp -> Just <$> UTF8.readFile fp
182130
183− epubMetadata <- case mbEpubMetadata of
131+ epubMetadata <- case optEpubMetadata opts of
184132 Nothing -> return Nothing
185133 Just fp -> Just <$> UTF8.readFile fp
186134
187135 let csscdn = "https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.6.0/katex.min.css"
188136 let mathMethod =
189− case (katexJS, katexStylesheet) of
190− (Nothing, _) -> mathMethod'
137+ case (optKaTeXJS opts, optKaTeXStylesheet opts) of
138+ (Nothing, _) -> optHTMLMathMethod opts
191139 (Just js, ss) -> KaTeX js (fromMaybe csscdn ss)
192140
193141
@@ -200,30 +148,30 @@ convertWithOpts opts args = do
200148
201149 let sources = case args of
202150 [] -> ["-"]
203− xs | ignoreArgs -> ["-"]
151+ xs | optIgnoreArgs opts -> ["-"]
204152 | otherwise -> xs
205153
206− datadir <- case mbDataDir of
154+ datadir <- case optDataDir opts of
207155 Nothing -> E.catch
208156 (Just <$> getAppUserDataDirectory "pandoc")
209157 (\e -> let _ = (e :: E.SomeException)
210158 in return Nothing)
211− Just _ -> return mbDataDir
159+ Just _ -> return $ optDataDir opts
212160
213161 -- assign reader and writer based on options and filenames
214− let readerName' = case map toLower readerName of
162+ let readerName = case map toLower (optReader opts) of
215163 [] -> defaultReaderName
216164 (if any isURI sources
217165 then "html"
218166 else "markdown") sources
219167 x -> x
220168
221− let writerName' = case map toLower writerName of
169+ let writerName = case map toLower (optWriter opts) of
222170 [] -> defaultWriterName outputFile
223171 "epub2" -> "epub"
224172 x -> x
225173 let format = takeWhile (`notElem` ['+','-'])
226− $ takeFileName writerName' -- in case path to lua script
174+ $ takeFileName writerName -- in case path to lua script
227175
228176 let pdfOutput = map toLower (takeExtension outputFile) == ".pdf"
229177
@@ -235,7 +183,7 @@ convertWithOpts opts args = do
235183 writer <- if ".lua" `isSuffixOf` format
236184 -- note: use non-lowercased version writerName
237185 then error "custom writers disabled for now"
238− else case getWriter writerName' of
186+ else case getWriter writerName of
239187 Left e -> err 9 $
240188 if format == "pdf"
241189 then e ++
@@ -248,20 +196,20 @@ convertWithOpts opts args = do
248196
249197 -- TODO: we have to get the input and the output into the state for
250198 -- the sake of the text2tags reader.
251− reader <- case getReader readerName' of
199+ reader <- case getReader readerName of
252200 Right r -> return (r :: Reader PandocIO)
253201 Left e -> err 7 e'
254− where e' = case readerName' of
202+ where e' = case readerName of
255203 "pdf" -> e ++
256204 "\nPandoc can convert to PDF, but not from PDF."
257205 "doc" -> e ++
258206 "\nPandoc can convert from DOCX, but not from DOC.\nTry using Word to save your DOC file as DOCX, and convert that with pandoc."
259207 _ -> e
260208
261− let standalone' = standalone || not (isTextFormat format) || pdfOutput
209+ let standalone = optStandalone opts || not (isTextFormat format) || pdfOutput
262210
263− templ <- case templatePath of
264− _ | not standalone' -> return Nothing
211+ templ <- case optTemplate opts of
212+ _ | not standalone -> return Nothing
265213 Nothing -> do
266214 deftemp <- getDefaultTemplate datadir format
267215 case deftemp of
@@ -281,13 +229,43 @@ convertWithOpts opts args = do
281229 in throwIO e')
282230 else throwIO e)
283231
284− variables' <- case mathMethod of
285− LaTeXMathML Nothing -> do
286− s <- readDataFileUTF8 datadir "LaTeXMathML.js"
287− return $ ("mathml-script", s) : variables
288− _ -> return variables
289−
290− variables'' <- if format == "dzslides"
232+ let addStringAsVariable varname s vars = return $ (varname, s) : vars
233+
234+ let addContentsAsVariable varname fp vars = do
235+ s <- UTF8.readFile fp
236+ return $ (varname, s) : vars
237+
238+ -- note: this reverses the list constructed in option parsing,
239+ -- which in turn was reversed from the command-line order,
240+ -- so we end up with the correct order in the variable list:
241+ let withList _ [] vars = return vars
242+ withList f (x:xs) vars = f x vars >>= withList f xs
243+
244+ variables <- return (optVariables opts)
245+ >>=
246+ withList (addContentsAsVariable "include-before")
247+ (optIncludeBeforeBody opts)
248+ >>=
249+ withList (addContentsAsVariable "include-after")
250+ (optIncludeAfterBody opts)
251+ >>=
252+ withList (addContentsAsVariable "header-includes")
253+ (optIncludeInHeader opts)
254+ >>=
255+ withList (addStringAsVariable "css") (optCss opts)
256+ >>=
257+ maybe return (addStringAsVariable "title-prefix") (optTitlePrefix opts)
258+ >>=
259+ maybe return (addStringAsVariable "epub-cover-image")
260+ (optEpubCoverImage opts)
261+ >>=
262+ (\vars -> case mathMethod of
263+ LaTeXMathML Nothing -> do
264+ s <- readDataFileUTF8 datadir "LaTeXMathML.js"
265+ return $ ("mathml-script", s) : vars
266+ _ -> return vars)
267+ >>=
268+ (\vars -> if format == "dzslides"
291269 then do
292270 dztempl <- readDataFileUTF8 datadir
293271 ("dzslides" </> "template.html")
@@ -295,8 +273,8 @@ convertWithOpts opts args = do
295273 let dzcore = unlines
296274 $ dropWhile (not . (dzline `isPrefixOf`))
297275 $ lines dztempl
298− return $ ("dzslides-core", dzcore) : variables'
299− else return variables'
276+ return $ ("dzslides-core", dzcore) : vars
277+ else return vars)
300278
301279 let sourceURL = case sources of
302280 [] -> Nothing
@@ -307,50 +285,51 @@ convertWithOpts opts args = do
307285 uriFragment = "" }
308286 _ -> Nothing
309287
310− let readerOpts = def{ readerStandalone = standalone'
311− , readerParseRaw = parseRaw
312− , readerColumns = columns
313− , readerTabStop = tabStop
314− , readerIndentedCodeClasses = codeBlockClasses
288+ let readerOpts = def{ readerStandalone = standalone
289+ , readerParseRaw = optParseRaw opts
290+ , readerColumns = optColumns opts
291+ , readerTabStop = optTabStop opts
292+ , readerIndentedCodeClasses = optIndentedCodeClasses opts
315293 , readerApplyMacros = not laTeXOutput
316− , readerDefaultImageExtension = defaultImageExtension
317− , readerTrackChanges = trackChanges
294+ , readerDefaultImageExtension =
295+ optDefaultImageExtension opts
296+ , readerTrackChanges = optTrackChanges opts
318297 }
319298
320− highlightStyle <- lookupHighlightStyle mbHighlightStyle
299+ highlightStyle <- lookupHighlightStyle $ optHighlightStyle opts
321300
322301 let writerOptions = def { writerTemplate = templ,
323− writerVariables = variables'',
324− writerTabStop = tabStop,
325− writerTableOfContents = toc,
302+ writerVariables = variables,
303+ writerTabStop = optTabStop opts,
304+ writerTableOfContents = optTableOfContents opts,
326305 writerHTMLMathMethod = mathMethod,
327− writerIncremental = incremental,
328− writerCiteMethod = citeMethod,
329− writerNumberSections = numberSections,
330− writerNumberOffset = numberFrom,
331− writerSectionDivs = sectionDivs,
332− writerReferenceLinks = referenceLinks,
333− writerReferenceLocation = referenceLocation,
334− writerDpi = dpi,
335− writerWrapText = wrap,
336− writerColumns = columns,
337− writerEmailObfuscation = obfuscationMethod,
338− writerIdentifierPrefix = idPrefix,
306+ writerIncremental = optIncremental opts,
307+ writerCiteMethod = optCiteMethod opts,
308+ writerNumberSections = optNumberSections opts,
309+ writerNumberOffset = optNumberOffset opts,
310+ writerSectionDivs = optSectionDivs opts,
311+ writerReferenceLinks = optReferenceLinks opts,
312+ writerReferenceLocation = optReferenceLocation opts,
313+ writerDpi = optDpi opts,
314+ writerWrapText = optWrapText opts,
315+ writerColumns = optColumns opts,
316+ writerEmailObfuscation = optEmailObfuscation opts,
317+ writerIdentifierPrefix = optIdentifierPrefix opts,
339318 writerSourceURL = sourceURL,
340319 writerUserDataDir = datadir,
341− writerHtmlQTags = htmlQTags,
342− writerTopLevelDivision = topLevelDivision,
343− writerListings = listings,
344− writerSlideLevel = slideLevel,
320+ writerHtmlQTags = optHtmlQTags opts,
321+ writerTopLevelDivision = optTopLevelDivision opts,
322+ writerListings = optListings opts,
323+ writerSlideLevel = optSlideLevel opts,
345324 writerHighlightStyle = highlightStyle,
346− writerSetextHeaders = setextHeaders,
325+ writerSetextHeaders = optSetextHeaders opts,
347326 writerEpubMetadata = epubMetadata,
348327 writerEpubStylesheet = epubStylesheet,
349− writerEpubFonts = epubFonts,
350− writerEpubChapterLevel = epubChapterLevel,
351− writerTOCDepth = epubTOCDepth,
352− writerReferenceDoc = referenceDoc,
353− writerLaTeXArgs = latexEngineArgs
328+ writerEpubFonts = optEpubFonts opts,
329+ writerEpubChapterLevel = optEpubChapterLevel opts,
330+ writerTOCDepth = optTOCDepth opts,
331+ writerReferenceDoc = optReferenceDoc opts,
332+ writerLaTeXArgs = optLaTeXEngineArgs opts
354333 }
355334
356335
@@ -364,13 +343,13 @@ convertWithOpts opts args = do
364343 "Specify an output file using the -o option."
365344
366345
367− let transforms = if baseHeaderLevel > 1
368− then [headerShift (baseHeaderLevel - 1)]
369− else []
346+ let transforms = case optBaseHeaderLevel opts of
347+ x | x > 1 -> [headerShift (x - 1)]
348+ | otherwise -> []
370349
371− let convertTabs = tabFilter (if preserveTabs || readerName' == "t2t"
350+ let convertTabs = tabFilter (if optPreserveTabs opts || readerName == "t2t"
372351 then 0
373− else tabStop)
352+ else optTabStop opts)
374353
375354 readSources :: MonadIO m => [FilePath] -> m String
376355 readSources srcs = convertTabs . intercalate "\n" <$>
@@ -385,7 +364,7 @@ convertWithOpts opts args = do
385364 return (x, rs)
386365 let isWarning (WARNING, _) = True
387366 isWarning _ = False
388− when (failIfWarnings && any isWarning reports) $
367+ when (optFailIfWarnings opts && any isWarning reports) $
389368 err 3 "Failing because there were warnings."
390369 return res
391370
@@ -393,7 +372,7 @@ convertWithOpts opts args = do
393372 sourceToDoc sources' =
394373 case reader of
395374 StringReader r
396− | fileScope || readerName' == "json" -> do
375+ | optFileScope opts || readerName == "json" -> do
397376 pairs <- mapM
398377 (readSource >=> withMediaBag . r readerOpts) sources
399378 return (mconcat (map fst pairs), mconcat (map snd pairs))
@@ -406,8 +385,8 @@ convertWithOpts opts args = do
406385
407386 runIO' $ do
408387 (doc, media) <- sourceToDoc sources
409− doc' <- (maybe return (extractMedia media) mbExtractMedia >=>
410− adjustMetadata metadata >=>
388+ doc' <- (maybe return (extractMedia media) (optExtractMedia opts) >=>
389+ adjustMetadata (optMetadata opts) >=>
411390 applyTransforms transforms >=>
412391 applyFilters datadir filters' [format]) doc
413392
@@ -424,7 +403,7 @@ convertWithOpts opts args = do
424403 let pdfprog = case () of
425404 _ | conTeXtOutput -> "context"
426405 _ | html5Output -> "wkhtmltopdf"
427− _ -> latexEngine
406+ _ -> optLaTeXEngine opts
428407 -- check for pdf creating program
429408 mbPdfProg <- liftIO $ findExecutable pdfprog
430409 when (isNothing mbPdfProg) $
@@ -441,14 +420,14 @@ convertWithOpts opts args = do
441420 | otherwise -> do
442421 let htmlFormat = format `elem`
443422 ["html","html4","html5","s5","slidy","slideous","dzslides","revealjs"]
444− selfcontain = if selfContained && htmlFormat
423+ selfcontain = if optSelfContained opts && htmlFormat
445424 then makeSelfContained writerOptions media
446425 else return
447− handleEntities = if htmlFormat && ascii
426+ handleEntities = if htmlFormat && optAscii opts
448427 then toEntities
449428 else id
450429 output <- f writerOptions doc'
451− selfcontain (output ++ ['\n' | not standalone']) >>=
430+ selfcontain (output ++ ['\n' | not standalone]) >>=
452431 writerFn outputFile . handleEntities
453432
454433type Transform = Pandoc -> Pandoc
@@ -559,6 +538,7 @@ data Opt = Opt
559538 , optEpubMetadata :: Maybe FilePath -- ^ EPUB metadata
560539 , optEpubFonts :: [FilePath] -- ^ EPUB fonts to embed
561540 , optEpubChapterLevel :: Int -- ^ Header level at which to split chapters
541+ , optEpubCoverImage :: Maybe FilePath -- ^ Cover image for epub
562542 , optTOCDepth :: Int -- ^ Number of levels to include in TOC
563543 , optDumpArgs :: Bool -- ^ Output command-line arguments
564544 , optIgnoreArgs :: Bool -- ^ Ignore command-line arguments
@@ -587,6 +567,11 @@ data Opt = Opt
587567 , optFileScope :: Bool -- ^ Parse input files before combining
588568 , optKaTeXStylesheet :: Maybe String -- ^ Path to stylesheet for KaTeX
589569 , optKaTeXJS :: Maybe String -- ^ Path to js file for KaTeX
570+ , optTitlePrefix :: Maybe String -- ^ Prefix for title
571+ , optCss :: [FilePath] -- ^ CSS files to link to
572+ , optIncludeBeforeBody :: [FilePath] -- ^ Files to include before
573+ , optIncludeAfterBody :: [FilePath] -- ^ Files to include after body
574+ , optIncludeInHeader :: [FilePath] -- ^ Files to include in header
590575 }
591576
592577-- | Defaults for command-line options.
@@ -618,6 +603,7 @@ defaultOpts = Opt
618603 , optEpubMetadata = Nothing
619604 , optEpubFonts = []
620605 , optEpubChapterLevel = 1
606+ , optEpubCoverImage = Nothing
621607 , optTOCDepth = 3
622608 , optDumpArgs = False
623609 , optIgnoreArgs = False
@@ -646,6 +632,11 @@ defaultOpts = Opt
646632 , optFileScope = False
647633 , optKaTeXStylesheet = Nothing
648634 , optKaTeXJS = Nothing
635+ , optTitlePrefix = Nothing
636+ , optCss = []
637+ , optIncludeBeforeBody = []
638+ , optIncludeAfterBody = []
639+ , optIncludeInHeader = []
649640 }
650641
651642-- | A list of functions, each transforming the options data structure
@@ -856,34 +847,25 @@ options =
856847
857848 , Option "H" ["include-in-header"]
858849 (ReqArg
859− (\arg opt -> do
860− text <- UTF8.readFile arg
861− -- add new ones to end, so they're included in order specified
862− let newvars = optVariables opt ++ [("header-includes",text)]
863− return opt { optVariables = newvars,
864− optStandalone = True })
850+ (\arg opt -> return opt{ optIncludeInHeader =
851+ arg : optIncludeInHeader opt,
852+ optStandalone = True })
865853 "FILENAME")
866854 "" -- "File to include at end of header (implies -s)"
867855
868856 , Option "B" ["include-before-body"]
869857 (ReqArg
870− (\arg opt -> do
871− text <- UTF8.readFile arg
872− -- add new ones to end, so they're included in order specified
873− let newvars = optVariables opt ++ [("include-before",text)]
874− return opt { optVariables = newvars,
875− optStandalone = True })
858+ (\arg opt -> return opt{ optIncludeBeforeBody =
859+ arg : optIncludeBeforeBody opt,
860+ optStandalone = True })
876861 "FILENAME")
877862 "" -- "File to include before document body"
878863
879864 , Option "A" ["include-after-body"]
880865 (ReqArg
881− (\arg opt -> do
882− text <- UTF8.readFile arg
883− -- add new ones to end, so they're included in order specified
884− let newvars = optVariables opt ++ [("include-after",text)]
885− return opt { optVariables = newvars,
886− optStandalone = True })
866+ (\arg opt -> return opt{ optIncludeAfterBody =
867+ arg : optIncludeAfterBody opt,
868+ optStandalone = True })
887869 "FILENAME")
888870 "" -- "File to include after document body"
889871
@@ -1015,11 +997,8 @@ options =
1015997
1016998 , Option "c" ["css"]
1017999 (ReqArg
1018− (\arg opt -> do
1019− -- add new link to end, so it is included in proper order
1020− let newvars = optVariables opt ++ [("css",arg)]
1021− return opt { optVariables = newvars,
1022− optStandalone = True })
1000+ (\arg opt -> return opt{ optCss = arg : optCss opt })
1001+ -- add new link to end, so it is included in proper order
10231002 "URL")
10241003 "" -- "Link to CSS style sheet"
10251004