packages feed

pandoc 1.19.2.4 → 2.0

raw patch · 1036 files changed

+104942/−75990 lines, 1036 filesdep +Globdep +aeson-prettydep +case-insensitivedep −HUnitdep −ansi-terminaldep −arraydep ~aesondep ~basedep ~binarysetup-changedbinary-addedPVP ok

version bump matches the API change (PVP)

Dependencies added: Glob, aeson-pretty, case-insensitive, cmark-gfm, file-embed, safe, split, tasty, tasty-golden, tasty-hunit, tasty-quickcheck

Dependencies removed: HUnit, ansi-terminal, array, cmark, extensible-exceptions, filemanip, ghc-prim, old-time, test-framework, test-framework-hunit, test-framework-quickcheck2

Dependency ranges changed: aeson, base, binary, bytestring, containers, directory, doctemplates, executable-path, hslua, network, pandoc-types, process, skylighting, texmath, text, time

API changes (from Hackage documentation)

- Text.Pandoc: ByteStringReader :: (ReaderOptions -> ByteString -> IO (Either PandocError (Pandoc, MediaBag))) -> Reader
- Text.Pandoc: IOByteStringWriter :: (WriterOptions -> Pandoc -> IO ByteString) -> Writer
- Text.Pandoc: IOStringWriter :: (WriterOptions -> Pandoc -> IO String) -> Writer
- Text.Pandoc: PureStringWriter :: (WriterOptions -> Pandoc -> String) -> Writer
- Text.Pandoc: StringReader :: (ReaderOptions -> String -> IO (Either PandocError Pandoc)) -> Reader
- Text.Pandoc: class ToJSONFilter a => ToJsonFilter a where toJsonFilter = toJSONFilter
- Text.Pandoc: data Reader
- Text.Pandoc: data Writer
- Text.Pandoc: getDefaultExtensions :: String -> Set Extension
- Text.Pandoc: getReader :: String -> Either String Reader
- Text.Pandoc: getWriter :: String -> Either String Writer
- Text.Pandoc: mkStringReader :: (ReaderOptions -> String -> Either PandocError Pandoc) -> Reader
- Text.Pandoc: readCommonMark :: ReaderOptions -> String -> Either PandocError Pandoc
- Text.Pandoc: readDocBook :: ReaderOptions -> String -> Either PandocError Pandoc
- Text.Pandoc: readDocx :: ReaderOptions -> ByteString -> Either PandocError (Pandoc, MediaBag)
- Text.Pandoc: readEPUB :: ReaderOptions -> ByteString -> Either PandocError (Pandoc, MediaBag)
- Text.Pandoc: readHaddock :: ReaderOptions -> String -> Either PandocError Pandoc
- Text.Pandoc: readHtml :: ReaderOptions -> String -> Either PandocError Pandoc
- Text.Pandoc: readJSON :: ReaderOptions -> String -> Either PandocError Pandoc
- Text.Pandoc: readLaTeX :: ReaderOptions -> String -> Either PandocError Pandoc
- Text.Pandoc: readMarkdown :: ReaderOptions -> String -> Either PandocError Pandoc
- Text.Pandoc: readMediaWiki :: ReaderOptions -> String -> Either PandocError Pandoc
- Text.Pandoc: readNative :: String -> Either PandocError Pandoc
- Text.Pandoc: readOPML :: ReaderOptions -> String -> Either PandocError Pandoc
- Text.Pandoc: readOdt :: ReaderOptions -> ByteString -> Either PandocError (Pandoc, MediaBag)
- Text.Pandoc: readOrg :: ReaderOptions -> String -> Either PandocError Pandoc
- Text.Pandoc: readRST :: ReaderOptions -> String -> Either PandocError Pandoc
- Text.Pandoc: readTWiki :: ReaderOptions -> String -> Either PandocError Pandoc
- Text.Pandoc: readTextile :: ReaderOptions -> String -> Either PandocError Pandoc
- Text.Pandoc: readTxt2Tags :: T2TMeta -> ReaderOptions -> String -> Either PandocError Pandoc
- Text.Pandoc: readTxt2TagsNoMacros :: ReaderOptions -> String -> Either PandocError Pandoc
- Text.Pandoc: readers :: [(String, Reader)]
- Text.Pandoc: toJsonFilter :: ToJsonFilter a => a -> IO ()
- Text.Pandoc: writeAsciiDoc :: WriterOptions -> Pandoc -> String
- Text.Pandoc: writeCommonMark :: WriterOptions -> Pandoc -> String
- Text.Pandoc: writeConTeXt :: WriterOptions -> Pandoc -> String
- Text.Pandoc: writeCustom :: FilePath -> WriterOptions -> Pandoc -> IO String
- Text.Pandoc: writeDocbook :: WriterOptions -> Pandoc -> String
- Text.Pandoc: writeDocx :: WriterOptions -> Pandoc -> IO ByteString
- Text.Pandoc: writeDokuWiki :: WriterOptions -> Pandoc -> String
- Text.Pandoc: writeEPUB :: WriterOptions -> Pandoc -> IO ByteString
- Text.Pandoc: writeFB2 :: WriterOptions -> Pandoc -> IO String
- Text.Pandoc: writeHaddock :: WriterOptions -> Pandoc -> String
- Text.Pandoc: writeHtml :: WriterOptions -> Pandoc -> Html
- Text.Pandoc: writeHtmlString :: WriterOptions -> Pandoc -> String
- Text.Pandoc: writeICML :: WriterOptions -> Pandoc -> IO String
- Text.Pandoc: writeJSON :: WriterOptions -> Pandoc -> String
- Text.Pandoc: writeLaTeX :: WriterOptions -> Pandoc -> String
- Text.Pandoc: writeMan :: WriterOptions -> Pandoc -> String
- Text.Pandoc: writeMarkdown :: WriterOptions -> Pandoc -> String
- Text.Pandoc: writeMediaWiki :: WriterOptions -> Pandoc -> String
- Text.Pandoc: writeNative :: WriterOptions -> Pandoc -> String
- Text.Pandoc: writeODT :: WriterOptions -> Pandoc -> IO ByteString
- Text.Pandoc: writeOPML :: WriterOptions -> Pandoc -> String
- Text.Pandoc: writeOpenDocument :: WriterOptions -> Pandoc -> String
- Text.Pandoc: writeOrg :: WriterOptions -> Pandoc -> String
- Text.Pandoc: writePlain :: WriterOptions -> Pandoc -> String
- Text.Pandoc: writeRST :: WriterOptions -> Pandoc -> String
- Text.Pandoc: writeRTF :: WriterOptions -> Pandoc -> String
- Text.Pandoc: writeTEI :: WriterOptions -> Pandoc -> String
- Text.Pandoc: writeTexinfo :: WriterOptions -> Pandoc -> String
- Text.Pandoc: writeTextile :: WriterOptions -> Pandoc -> String
- Text.Pandoc: writeZimWiki :: WriterOptions -> Pandoc -> String
- Text.Pandoc: writers :: [(String, Writer)]
- Text.Pandoc.CSS: foldOrElse :: Eq a => a -> [a] -> a
- Text.Pandoc.CSS: pickStyleAttrProps :: [String] -> String -> Maybe String
- Text.Pandoc.CSS: pickStylesToKVs :: [String] -> String -> [(String, String)]
- Text.Pandoc.Error: ParseFailure :: String -> PandocError
- Text.Pandoc.Error: ParsecError :: Input -> ParseError -> PandocError
- Text.Pandoc.MediaBag: extractMediaBag :: Bool -> FilePath -> MediaBag -> IO ()
- Text.Pandoc.Options: Ext_abbreviations :: Extension
- Text.Pandoc.Options: Ext_all_symbols_escapable :: Extension
- Text.Pandoc.Options: Ext_angle_brackets_escapable :: Extension
- Text.Pandoc.Options: Ext_ascii_identifiers :: Extension
- Text.Pandoc.Options: Ext_auto_identifiers :: Extension
- Text.Pandoc.Options: Ext_autolink_bare_uris :: Extension
- Text.Pandoc.Options: Ext_backtick_code_blocks :: Extension
- Text.Pandoc.Options: Ext_blank_before_blockquote :: Extension
- Text.Pandoc.Options: Ext_blank_before_header :: Extension
- Text.Pandoc.Options: Ext_bracketed_spans :: Extension
- Text.Pandoc.Options: Ext_citations :: Extension
- Text.Pandoc.Options: Ext_compact_definition_lists :: Extension
- Text.Pandoc.Options: Ext_definition_lists :: Extension
- Text.Pandoc.Options: Ext_east_asian_line_breaks :: Extension
- Text.Pandoc.Options: Ext_emoji :: Extension
- Text.Pandoc.Options: Ext_epub_html_exts :: Extension
- Text.Pandoc.Options: Ext_escaped_line_breaks :: Extension
- Text.Pandoc.Options: Ext_example_lists :: Extension
- Text.Pandoc.Options: Ext_fancy_lists :: Extension
- Text.Pandoc.Options: Ext_fenced_code_attributes :: Extension
- Text.Pandoc.Options: Ext_fenced_code_blocks :: Extension
- Text.Pandoc.Options: Ext_footnotes :: Extension
- Text.Pandoc.Options: Ext_grid_tables :: Extension
- Text.Pandoc.Options: Ext_hard_line_breaks :: Extension
- Text.Pandoc.Options: Ext_header_attributes :: Extension
- Text.Pandoc.Options: Ext_ignore_line_breaks :: Extension
- Text.Pandoc.Options: Ext_implicit_figures :: Extension
- Text.Pandoc.Options: Ext_implicit_header_references :: Extension
- Text.Pandoc.Options: Ext_inline_code_attributes :: Extension
- Text.Pandoc.Options: Ext_inline_notes :: Extension
- Text.Pandoc.Options: Ext_intraword_underscores :: Extension
- Text.Pandoc.Options: Ext_latex_macros :: Extension
- Text.Pandoc.Options: Ext_line_blocks :: Extension
- Text.Pandoc.Options: Ext_link_attributes :: Extension
- Text.Pandoc.Options: Ext_lists_without_preceding_blankline :: Extension
- Text.Pandoc.Options: Ext_literate_haskell :: Extension
- Text.Pandoc.Options: Ext_markdown_attribute :: Extension
- Text.Pandoc.Options: Ext_markdown_in_html_blocks :: Extension
- Text.Pandoc.Options: Ext_mmd_header_identifiers :: Extension
- Text.Pandoc.Options: Ext_mmd_link_attributes :: Extension
- Text.Pandoc.Options: Ext_mmd_title_block :: Extension
- Text.Pandoc.Options: Ext_multiline_tables :: Extension
- Text.Pandoc.Options: Ext_native_divs :: Extension
- Text.Pandoc.Options: Ext_native_spans :: Extension
- Text.Pandoc.Options: Ext_pandoc_title_block :: Extension
- Text.Pandoc.Options: Ext_pipe_tables :: Extension
- Text.Pandoc.Options: Ext_raw_html :: Extension
- Text.Pandoc.Options: Ext_raw_tex :: Extension
- Text.Pandoc.Options: Ext_shortcut_reference_links :: Extension
- Text.Pandoc.Options: Ext_simple_tables :: Extension
- Text.Pandoc.Options: Ext_startnum :: Extension
- Text.Pandoc.Options: Ext_strikeout :: Extension
- Text.Pandoc.Options: Ext_subscript :: Extension
- Text.Pandoc.Options: Ext_superscript :: Extension
- Text.Pandoc.Options: Ext_table_captions :: Extension
- Text.Pandoc.Options: Ext_tex_math_dollars :: Extension
- Text.Pandoc.Options: Ext_tex_math_double_backslash :: Extension
- Text.Pandoc.Options: Ext_tex_math_single_backslash :: Extension
- Text.Pandoc.Options: Ext_yaml_metadata_block :: Extension
- Text.Pandoc.Options: [readerApplyMacros] :: ReaderOptions -> Bool
- Text.Pandoc.Options: [readerFileScope] :: ReaderOptions -> Bool
- Text.Pandoc.Options: [readerOldDashes] :: ReaderOptions -> Bool
- Text.Pandoc.Options: [readerParseRaw] :: ReaderOptions -> Bool
- Text.Pandoc.Options: [readerSmart] :: ReaderOptions -> Bool
- Text.Pandoc.Options: [readerTrace] :: ReaderOptions -> Bool
- Text.Pandoc.Options: [writerBeamer] :: WriterOptions -> Bool
- Text.Pandoc.Options: [writerDocbook5] :: WriterOptions -> Bool
- Text.Pandoc.Options: [writerEpubStylesheet] :: WriterOptions -> Maybe String
- Text.Pandoc.Options: [writerEpubVersion] :: WriterOptions -> Maybe EPUBVersion
- Text.Pandoc.Options: [writerHighlight] :: WriterOptions -> Bool
- Text.Pandoc.Options: [writerHtml5] :: WriterOptions -> Bool
- Text.Pandoc.Options: [writerIgnoreNotes] :: WriterOptions -> Bool
- Text.Pandoc.Options: [writerLaTeXArgs] :: WriterOptions -> [String]
- Text.Pandoc.Options: [writerMediaBag] :: WriterOptions -> MediaBag
- Text.Pandoc.Options: [writerReferenceDocx] :: WriterOptions -> Maybe FilePath
- Text.Pandoc.Options: [writerReferenceODT] :: WriterOptions -> Maybe FilePath
- Text.Pandoc.Options: [writerSlideVariant] :: WriterOptions -> HTMLSlideVariant
- Text.Pandoc.Options: [writerSourceURL] :: WriterOptions -> Maybe String
- Text.Pandoc.Options: [writerTeXLigatures] :: WriterOptions -> Bool
- Text.Pandoc.Options: [writerUserDataDir] :: WriterOptions -> Maybe FilePath
- Text.Pandoc.Options: [writerVerbose] :: WriterOptions -> Bool
- Text.Pandoc.Options: data Extension
- Text.Pandoc.Options: githubMarkdownExtensions :: Set Extension
- Text.Pandoc.Options: instance Data.Data.Data Text.Pandoc.Options.Extension
- Text.Pandoc.Options: instance GHC.Classes.Eq Text.Pandoc.Options.Extension
- Text.Pandoc.Options: instance GHC.Classes.Ord Text.Pandoc.Options.Extension
- Text.Pandoc.Options: instance GHC.Enum.Bounded Text.Pandoc.Options.Extension
- Text.Pandoc.Options: instance GHC.Enum.Enum Text.Pandoc.Options.Extension
- Text.Pandoc.Options: instance GHC.Generics.Generic Text.Pandoc.Options.Extension
- Text.Pandoc.Options: instance GHC.Read.Read Text.Pandoc.Options.Extension
- Text.Pandoc.Options: instance GHC.Show.Show Text.Pandoc.Options.Extension
- Text.Pandoc.Options: multimarkdownExtensions :: Set Extension
- Text.Pandoc.Options: pandocExtensions :: Set Extension
- Text.Pandoc.Options: phpMarkdownExtraExtensions :: Set Extension
- Text.Pandoc.Options: plainExtensions :: Set Extension
- Text.Pandoc.Options: strictExtensions :: Set Extension
- Text.Pandoc.Readers.Docx: readDocxWithWarnings :: ReaderOptions -> ByteString -> Either PandocError (Pandoc, MediaBag, [String])
- Text.Pandoc.Readers.HTML: instance Text.Pandoc.Parsing.HasQuoteContext st (Control.Monad.Trans.Reader.Reader Text.Pandoc.Readers.HTML.HTMLLocal)
- Text.Pandoc.Readers.LaTeX: handleIncludes :: String -> IO (Either PandocError String)
- Text.Pandoc.Readers.Markdown: readMarkdownWithWarnings :: ReaderOptions -> String -> Either PandocError (Pandoc, [String])
- Text.Pandoc.Readers.RST: readRSTWithWarnings :: ReaderOptions -> String -> Either PandocError (Pandoc, [String])
- Text.Pandoc.Readers.TWiki: readTWikiWithWarnings :: ReaderOptions -> String -> Either PandocError (Pandoc, [String])
- Text.Pandoc.Readers.TeXMath: texMathToInlines :: MathType -> String -> [Inline]
- Text.Pandoc.Readers.Txt2Tags: readTxt2TagsNoMacros :: ReaderOptions -> String -> Either PandocError Pandoc
- Text.Pandoc.Shared: compactify' :: [Blocks] -> [Blocks]
- Text.Pandoc.Shared: compactify'DL :: [(Inlines, [Blocks])] -> [(Inlines, [Blocks])]
- Text.Pandoc.Shared: err :: Int -> String -> IO a
- Text.Pandoc.Shared: fetchItem :: Maybe String -> String -> IO (Either SomeException (ByteString, Maybe MimeType))
- Text.Pandoc.Shared: fetchItem' :: MediaBag -> Maybe String -> String -> IO (Either SomeException (ByteString, Maybe MimeType))
- Text.Pandoc.Shared: getDefaultReferenceDocx :: Maybe FilePath -> IO Archive
- Text.Pandoc.Shared: getDefaultReferenceODT :: Maybe FilePath -> IO Archive
- Text.Pandoc.Shared: hush :: Either a b -> Maybe b
- Text.Pandoc.Shared: normalize :: Pandoc -> Pandoc
- Text.Pandoc.Shared: normalizeBlocks :: [Block] -> [Block]
- Text.Pandoc.Shared: normalizeInlines :: [Inline] -> [Inline]
- Text.Pandoc.Shared: normalizeSpaces :: [Inline] -> [Inline]
- Text.Pandoc.Shared: openURL :: String -> IO (Either SomeException (ByteString, Maybe MimeType))
- Text.Pandoc.Shared: readDataFile :: Maybe FilePath -> FilePath -> IO ByteString
- Text.Pandoc.Shared: readDataFileUTF8 :: Maybe FilePath -> FilePath -> IO String
- Text.Pandoc.Shared: warn :: MonadIO m => String -> m ()
- Text.Pandoc.Templates: class TemplateTarget a
- Text.Pandoc.Templates: compileTemplate :: Text -> Either String Template
- Text.Pandoc.Templates: data Template :: *
- Text.Pandoc.Templates: renderTemplate :: (ToJSON a, TemplateTarget b) => Template -> a -> b
- Text.Pandoc.Templates: varListToJSON :: [(String, String)] -> Value
- Text.Pandoc.Writers.Custom: instance (Scripting.Lua.StackValue a, Scripting.Lua.StackValue b) => Scripting.Lua.StackValue (Data.Map.Base.Map a b)
- Text.Pandoc.Writers.Custom: instance (Scripting.Lua.StackValue a, Scripting.Lua.StackValue b) => Scripting.Lua.StackValue (a, b)
- Text.Pandoc.Writers.Custom: instance Scripting.Lua.StackValue Text.Pandoc.Definition.Citation
- Text.Pandoc.Writers.Custom: instance Scripting.Lua.StackValue Text.Pandoc.Definition.Format
- Text.Pandoc.Writers.Custom: instance Scripting.Lua.StackValue Text.Pandoc.Definition.MetaValue
- Text.Pandoc.Writers.Custom: instance Scripting.Lua.StackValue [GHC.Types.Char]
- Text.Pandoc.Writers.Custom: instance Scripting.Lua.StackValue [Text.Pandoc.Definition.Block]
- Text.Pandoc.Writers.Custom: instance Scripting.Lua.StackValue [Text.Pandoc.Definition.Inline]
- Text.Pandoc.Writers.Docbook: writeDocbook :: WriterOptions -> Pandoc -> String
- Text.Pandoc.Writers.EPUB: instance GHC.Show.Show Text.Pandoc.Writers.EPUB.Stylesheet
- Text.Pandoc.Writers.EPUB: writeEPUB :: WriterOptions -> Pandoc -> IO ByteString
- Text.Pandoc.Writers.HTML: writeHtml :: WriterOptions -> Pandoc -> Html
- Text.Pandoc.Writers.HTML: writeHtmlString :: WriterOptions -> Pandoc -> String
- Text.Pandoc.Writers.RTF: writeRTFWithEmbeddedImages :: WriterOptions -> Pandoc -> IO String
+ Text.Pandoc.App: Opt :: Int -> Bool -> Bool -> Maybe String -> Maybe String -> Bool -> Int -> Maybe FilePath -> [(String, String)] -> [(String, String)] -> Maybe FilePath -> [FilePath] -> Bool -> [Int] -> Bool -> Bool -> Bool -> Bool -> Maybe String -> [FilePath] -> TopLevelDivision -> HTMLMathMethod -> Maybe FilePath -> Maybe FilePath -> String -> Maybe FilePath -> [FilePath] -> Int -> Maybe FilePath -> Int -> Bool -> Bool -> Verbosity -> Bool -> Maybe FilePath -> Bool -> Bool -> ReferenceLocation -> Int -> WrapOption -> Int -> [FilePath] -> [FilePath] -> ObfuscationMethod -> String -> [String] -> Maybe FilePath -> CiteMethod -> Bool -> Maybe String -> [String] -> Maybe Int -> Bool -> Bool -> String -> Maybe FilePath -> TrackChanges -> Bool -> Maybe String -> [FilePath] -> [FilePath] -> [FilePath] -> [FilePath] -> [FilePath] -> [(String, String)] -> LineEnding -> Bool -> Opt
+ Text.Pandoc.App: [optAbbreviations] :: Opt -> Maybe FilePath
+ Text.Pandoc.App: [optAscii] :: Opt -> Bool
+ Text.Pandoc.App: [optBaseHeaderLevel] :: Opt -> Int
+ Text.Pandoc.App: [optCiteMethod] :: Opt -> CiteMethod
+ Text.Pandoc.App: [optColumns] :: Opt -> Int
+ Text.Pandoc.App: [optCss] :: Opt -> [FilePath]
+ Text.Pandoc.App: [optDataDir] :: Opt -> Maybe FilePath
+ Text.Pandoc.App: [optDefaultImageExtension] :: Opt -> String
+ Text.Pandoc.App: [optDpi] :: Opt -> Int
+ Text.Pandoc.App: [optDumpArgs] :: Opt -> Bool
+ Text.Pandoc.App: [optEmailObfuscation] :: Opt -> ObfuscationMethod
+ Text.Pandoc.App: [optEol] :: Opt -> LineEnding
+ Text.Pandoc.App: [optEpubChapterLevel] :: Opt -> Int
+ Text.Pandoc.App: [optEpubCoverImage] :: Opt -> Maybe FilePath
+ Text.Pandoc.App: [optEpubFonts] :: Opt -> [FilePath]
+ Text.Pandoc.App: [optEpubMetadata] :: Opt -> Maybe FilePath
+ Text.Pandoc.App: [optEpubSubdirectory] :: Opt -> String
+ Text.Pandoc.App: [optExtractMedia] :: Opt -> Maybe FilePath
+ Text.Pandoc.App: [optFailIfWarnings] :: Opt -> Bool
+ Text.Pandoc.App: [optFileScope] :: Opt -> Bool
+ Text.Pandoc.App: [optFilters] :: Opt -> [FilePath]
+ Text.Pandoc.App: [optHTMLMathMethod] :: Opt -> HTMLMathMethod
+ Text.Pandoc.App: [optHighlightStyle] :: Opt -> Maybe String
+ Text.Pandoc.App: [optHtmlQTags] :: Opt -> Bool
+ Text.Pandoc.App: [optIdentifierPrefix] :: Opt -> String
+ Text.Pandoc.App: [optIgnoreArgs] :: Opt -> Bool
+ Text.Pandoc.App: [optIncludeAfterBody] :: Opt -> [FilePath]
+ Text.Pandoc.App: [optIncludeBeforeBody] :: Opt -> [FilePath]
+ Text.Pandoc.App: [optIncludeInHeader] :: Opt -> [FilePath]
+ Text.Pandoc.App: [optIncremental] :: Opt -> Bool
+ Text.Pandoc.App: [optIndentedCodeClasses] :: Opt -> [String]
+ Text.Pandoc.App: [optInputFiles] :: Opt -> [FilePath]
+ Text.Pandoc.App: [optListings] :: Opt -> Bool
+ Text.Pandoc.App: [optLogFile] :: Opt -> Maybe FilePath
+ Text.Pandoc.App: [optLuaFilters] :: Opt -> [FilePath]
+ Text.Pandoc.App: [optMetadata] :: Opt -> [(String, String)]
+ Text.Pandoc.App: [optNumberOffset] :: Opt -> [Int]
+ Text.Pandoc.App: [optNumberSections] :: Opt -> Bool
+ Text.Pandoc.App: [optOutputFile] :: Opt -> Maybe FilePath
+ Text.Pandoc.App: [optPdfEngineArgs] :: Opt -> [String]
+ Text.Pandoc.App: [optPdfEngine] :: Opt -> Maybe String
+ Text.Pandoc.App: [optPreserveTabs] :: Opt -> Bool
+ Text.Pandoc.App: [optReader] :: Opt -> Maybe String
+ Text.Pandoc.App: [optReferenceDoc] :: Opt -> Maybe FilePath
+ Text.Pandoc.App: [optReferenceLinks] :: Opt -> Bool
+ Text.Pandoc.App: [optReferenceLocation] :: Opt -> ReferenceLocation
+ Text.Pandoc.App: [optRequestHeaders] :: Opt -> [(String, String)]
+ Text.Pandoc.App: [optResourcePath] :: Opt -> [FilePath]
+ Text.Pandoc.App: [optSectionDivs] :: Opt -> Bool
+ Text.Pandoc.App: [optSelfContained] :: Opt -> Bool
+ Text.Pandoc.App: [optSetextHeaders] :: Opt -> Bool
+ Text.Pandoc.App: [optSlideLevel] :: Opt -> Maybe Int
+ Text.Pandoc.App: [optStandalone] :: Opt -> Bool
+ Text.Pandoc.App: [optStripComments] :: Opt -> Bool
+ Text.Pandoc.App: [optSyntaxDefinitions] :: Opt -> [FilePath]
+ Text.Pandoc.App: [optTOCDepth] :: Opt -> Int
+ Text.Pandoc.App: [optTabStop] :: Opt -> Int
+ Text.Pandoc.App: [optTableOfContents] :: Opt -> Bool
+ Text.Pandoc.App: [optTemplate] :: Opt -> Maybe FilePath
+ Text.Pandoc.App: [optTitlePrefix] :: Opt -> Maybe String
+ Text.Pandoc.App: [optTopLevelDivision] :: Opt -> TopLevelDivision
+ Text.Pandoc.App: [optTrace] :: Opt -> Bool
+ Text.Pandoc.App: [optTrackChanges] :: Opt -> TrackChanges
+ Text.Pandoc.App: [optVariables] :: Opt -> [(String, String)]
+ Text.Pandoc.App: [optVerbosity] :: Opt -> Verbosity
+ Text.Pandoc.App: [optWrapText] :: Opt -> WrapOption
+ Text.Pandoc.App: [optWriter] :: Opt -> Maybe String
+ Text.Pandoc.App: applyFilters :: MonadIO m => ReaderOptions -> Maybe FilePath -> [FilePath] -> [String] -> Pandoc -> m Pandoc
+ Text.Pandoc.App: applyLuaFilters :: Maybe FilePath -> [FilePath] -> String -> Pandoc -> PandocIO Pandoc
+ Text.Pandoc.App: convertWithOpts :: Opt -> IO ()
+ Text.Pandoc.App: data Opt
+ Text.Pandoc.App: defaultOpts :: Opt
+ Text.Pandoc.App: instance Data.Aeson.Types.FromJSON.FromJSON Text.Pandoc.App.LineEnding
+ Text.Pandoc.App: instance Data.Aeson.Types.FromJSON.FromJSON Text.Pandoc.App.Opt
+ Text.Pandoc.App: instance Data.Aeson.Types.ToJSON.ToJSON Text.Pandoc.App.LineEnding
+ Text.Pandoc.App: instance Data.Aeson.Types.ToJSON.ToJSON Text.Pandoc.App.Opt
+ Text.Pandoc.App: instance GHC.Generics.Generic Text.Pandoc.App.LineEnding
+ Text.Pandoc.App: instance GHC.Generics.Generic Text.Pandoc.App.Opt
+ Text.Pandoc.App: instance GHC.Show.Show Text.Pandoc.App.LineEnding
+ Text.Pandoc.App: instance GHC.Show.Show Text.Pandoc.App.Opt
+ Text.Pandoc.App: options :: [OptDescr (Opt -> IO Opt)]
+ Text.Pandoc.App: parseOptions :: [OptDescr (Opt -> IO Opt)] -> Opt -> IO Opt
+ Text.Pandoc.Asciify: toAsciiChar :: Char -> Maybe Char
+ Text.Pandoc.BCP47: Lang :: String -> String -> String -> [String] -> Lang
+ Text.Pandoc.BCP47: [langLanguage] :: Lang -> String
+ Text.Pandoc.BCP47: [langRegion] :: Lang -> String
+ Text.Pandoc.BCP47: [langScript] :: Lang -> String
+ Text.Pandoc.BCP47: [langVariants] :: Lang -> [String]
+ Text.Pandoc.BCP47: data Lang
+ Text.Pandoc.BCP47: getLang :: WriterOptions -> Meta -> Maybe String
+ Text.Pandoc.BCP47: instance GHC.Classes.Eq Text.Pandoc.BCP47.Lang
+ Text.Pandoc.BCP47: instance GHC.Classes.Ord Text.Pandoc.BCP47.Lang
+ Text.Pandoc.BCP47: instance GHC.Show.Show Text.Pandoc.BCP47.Lang
+ Text.Pandoc.BCP47: parseBCP47 :: String -> Either String Lang
+ Text.Pandoc.BCP47: renderLang :: Lang -> String
+ Text.Pandoc.Class: CommonState :: [LogMessage] -> Maybe FilePath -> Maybe String -> [(String, String)] -> MediaBag -> Maybe (Lang, Maybe Translations) -> [FilePath] -> Maybe FilePath -> [FilePath] -> Verbosity -> Bool -> CommonState
+ Text.Pandoc.Class: FileInfo :: UTCTime -> ByteString -> FileInfo
+ Text.Pandoc.Class: FileTree :: Map FilePath FileInfo -> FileTree
+ Text.Pandoc.Class: PandocIO :: ExceptT PandocError (StateT CommonState IO) a -> PandocIO a
+ Text.Pandoc.Class: PandocPure :: ExceptT PandocError (StateT CommonState (State PureState)) a -> PandocPure a
+ Text.Pandoc.Class: PureState :: StdGen -> [Word8] -> [Int] -> [(String, String)] -> UTCTime -> TimeZone -> Archive -> Archive -> FileTree -> FileTree -> FileTree -> PureState
+ Text.Pandoc.Class: [infoFileContents] :: FileInfo -> ByteString
+ Text.Pandoc.Class: [infoFileMTime] :: FileInfo -> UTCTime
+ Text.Pandoc.Class: [stCabalDataFiles] :: PureState -> FileTree
+ Text.Pandoc.Class: [stEnv] :: PureState -> [(String, String)]
+ Text.Pandoc.Class: [stFiles] :: PureState -> FileTree
+ Text.Pandoc.Class: [stInputFiles] :: CommonState -> [FilePath]
+ Text.Pandoc.Class: [stLog] :: CommonState -> [LogMessage]
+ Text.Pandoc.Class: [stMediaBag] :: CommonState -> MediaBag
+ Text.Pandoc.Class: [stOutputFile] :: CommonState -> Maybe FilePath
+ Text.Pandoc.Class: [stReferenceDocx] :: PureState -> Archive
+ Text.Pandoc.Class: [stReferenceODT] :: PureState -> Archive
+ Text.Pandoc.Class: [stRequestHeaders] :: CommonState -> [(String, String)]
+ Text.Pandoc.Class: [stResourcePath] :: CommonState -> [FilePath]
+ Text.Pandoc.Class: [stSourceURL] :: CommonState -> Maybe String
+ Text.Pandoc.Class: [stStdGen] :: PureState -> StdGen
+ Text.Pandoc.Class: [stTimeZone] :: PureState -> TimeZone
+ Text.Pandoc.Class: [stTime] :: PureState -> UTCTime
+ Text.Pandoc.Class: [stTrace] :: CommonState -> Bool
+ Text.Pandoc.Class: [stTranslations] :: CommonState -> Maybe (Lang, Maybe Translations)
+ Text.Pandoc.Class: [stUniqStore] :: PureState -> [Int]
+ Text.Pandoc.Class: [stUserDataDir] :: CommonState -> Maybe FilePath
+ Text.Pandoc.Class: [stUserDataFiles] :: PureState -> FileTree
+ Text.Pandoc.Class: [stVerbosity] :: CommonState -> Verbosity
+ Text.Pandoc.Class: [stWord8Store] :: PureState -> [Word8]
+ Text.Pandoc.Class: [unFileTree] :: FileTree -> Map FilePath FileInfo
+ Text.Pandoc.Class: [unPandocIO] :: PandocIO a -> ExceptT PandocError (StateT CommonState IO) a
+ Text.Pandoc.Class: [unPandocPure] :: PandocPure a -> ExceptT PandocError (StateT CommonState (State PureState)) a
+ Text.Pandoc.Class: addToFileTree :: FileTree -> FilePath -> IO FileTree
+ Text.Pandoc.Class: class (Functor m, Applicative m, Monad m, MonadError PandocError m) => PandocMonad m where getsCommonState f = f <$> getCommonState modifyCommonState f = getCommonState >>= putCommonState . f trace msg = do { tracing <- getsCommonState stTrace; when tracing $ trace ("[trace] " ++ msg) (return ()) }
+ Text.Pandoc.Class: data CommonState
+ Text.Pandoc.Class: data FileInfo
+ Text.Pandoc.Class: data PureState
+ Text.Pandoc.Class: data Translations
+ Text.Pandoc.Class: extractMedia :: FilePath -> Pandoc -> PandocIO Pandoc
+ Text.Pandoc.Class: fetchItem :: PandocMonad m => String -> m (ByteString, Maybe MimeType)
+ Text.Pandoc.Class: fetchMediaResource :: PandocMonad m => String -> m (FilePath, Maybe MimeType, ByteString)
+ Text.Pandoc.Class: fileExists :: PandocMonad m => FilePath -> m Bool
+ Text.Pandoc.Class: fillMediaBag :: PandocMonad m => Pandoc -> m Pandoc
+ Text.Pandoc.Class: getCommonState :: PandocMonad m => m CommonState
+ Text.Pandoc.Class: getCurrentTime :: PandocMonad m => m UTCTime
+ Text.Pandoc.Class: getCurrentTimeZone :: PandocMonad m => m TimeZone
+ Text.Pandoc.Class: getDataFileName :: PandocMonad m => FilePath -> m FilePath
+ Text.Pandoc.Class: getInputFiles :: PandocMonad m => m [FilePath]
+ Text.Pandoc.Class: getLog :: PandocMonad m => m [LogMessage]
+ Text.Pandoc.Class: getMediaBag :: PandocMonad m => m MediaBag
+ Text.Pandoc.Class: getModificationTime :: PandocMonad m => FilePath -> m UTCTime
+ Text.Pandoc.Class: getOutputFile :: PandocMonad m => m (Maybe FilePath)
+ Text.Pandoc.Class: getPOSIXTime :: PandocMonad m => m POSIXTime
+ Text.Pandoc.Class: getPureState :: PandocPure PureState
+ Text.Pandoc.Class: getResourcePath :: PandocMonad m => m [FilePath]
+ Text.Pandoc.Class: getUserDataDir :: PandocMonad m => m (Maybe FilePath)
+ Text.Pandoc.Class: getVerbosity :: PandocMonad m => m Verbosity
+ Text.Pandoc.Class: getZonedTime :: PandocMonad m => m ZonedTime
+ Text.Pandoc.Class: getsCommonState :: PandocMonad m => (CommonState -> a) -> m a
+ Text.Pandoc.Class: getsPureState :: (PureState -> a) -> PandocPure a
+ Text.Pandoc.Class: glob :: PandocMonad m => String -> m [FilePath]
+ Text.Pandoc.Class: insertMedia :: PandocMonad m => FilePath -> Maybe MimeType -> ByteString -> m ()
+ Text.Pandoc.Class: instance (Control.Monad.Trans.Class.MonadTrans t, Text.Pandoc.Class.PandocMonad m, GHC.Base.Functor (t m), Control.Monad.Error.Class.MonadError Text.Pandoc.Error.PandocError (t m), GHC.Base.Monad (t m), GHC.Base.Applicative (t m)) => Text.Pandoc.Class.PandocMonad (t m)
+ Text.Pandoc.Class: instance Control.Monad.Error.Class.MonadError Text.Pandoc.Error.PandocError Text.Pandoc.Class.PandocIO
+ Text.Pandoc.Class: instance Control.Monad.Error.Class.MonadError Text.Pandoc.Error.PandocError Text.Pandoc.Class.PandocPure
+ Text.Pandoc.Class: instance Control.Monad.IO.Class.MonadIO Text.Pandoc.Class.PandocIO
+ Text.Pandoc.Class: instance Data.Default.Class.Default Text.Pandoc.Class.CommonState
+ Text.Pandoc.Class: instance Data.Default.Class.Default Text.Pandoc.Class.PureState
+ Text.Pandoc.Class: instance GHC.Base.Applicative Text.Pandoc.Class.PandocIO
+ Text.Pandoc.Class: instance GHC.Base.Applicative Text.Pandoc.Class.PandocPure
+ Text.Pandoc.Class: instance GHC.Base.Functor Text.Pandoc.Class.PandocIO
+ Text.Pandoc.Class: instance GHC.Base.Functor Text.Pandoc.Class.PandocPure
+ Text.Pandoc.Class: instance GHC.Base.Monad Text.Pandoc.Class.PandocIO
+ Text.Pandoc.Class: instance GHC.Base.Monad Text.Pandoc.Class.PandocPure
+ Text.Pandoc.Class: instance GHC.Base.Monoid Text.Pandoc.Class.FileTree
+ Text.Pandoc.Class: instance Text.Pandoc.Class.PandocMonad Text.Pandoc.Class.PandocIO
+ Text.Pandoc.Class: instance Text.Pandoc.Class.PandocMonad Text.Pandoc.Class.PandocPure
+ Text.Pandoc.Class: instance Text.Pandoc.Class.PandocMonad m => Text.Pandoc.Class.PandocMonad (Text.Parsec.Prim.ParsecT s st m)
+ Text.Pandoc.Class: logOutput :: PandocMonad m => LogMessage -> m ()
+ Text.Pandoc.Class: lookupEnv :: PandocMonad m => String -> m (Maybe String)
+ Text.Pandoc.Class: modifyCommonState :: PandocMonad m => (CommonState -> CommonState) -> m ()
+ Text.Pandoc.Class: modifyPureState :: (PureState -> PureState) -> PandocPure ()
+ Text.Pandoc.Class: newStdGen :: PandocMonad m => m StdGen
+ Text.Pandoc.Class: newUniqueHash :: PandocMonad m => m Int
+ Text.Pandoc.Class: newtype FileTree
+ Text.Pandoc.Class: newtype PandocIO a
+ Text.Pandoc.Class: newtype PandocPure a
+ Text.Pandoc.Class: openURL :: PandocMonad m => String -> m (ByteString, Maybe MimeType)
+ Text.Pandoc.Class: putCommonState :: PandocMonad m => CommonState -> m ()
+ Text.Pandoc.Class: putPureState :: PureState -> PandocPure ()
+ Text.Pandoc.Class: readDataFile :: PandocMonad m => FilePath -> m ByteString
+ Text.Pandoc.Class: readDefaultDataFile :: PandocMonad m => FilePath -> m ByteString
+ Text.Pandoc.Class: readFileFromDirs :: PandocMonad m => [FilePath] -> FilePath -> m (Maybe String)
+ Text.Pandoc.Class: readFileLazy :: PandocMonad m => FilePath -> m ByteString
+ Text.Pandoc.Class: readFileStrict :: PandocMonad m => FilePath -> m ByteString
+ Text.Pandoc.Class: report :: PandocMonad m => LogMessage -> m ()
+ Text.Pandoc.Class: runIO :: PandocIO a -> IO (Either PandocError a)
+ Text.Pandoc.Class: runIOorExplode :: PandocIO a -> IO a
+ Text.Pandoc.Class: runPure :: PandocPure a -> Either PandocError a
+ Text.Pandoc.Class: setInputFiles :: PandocMonad m => [FilePath] -> m ()
+ Text.Pandoc.Class: setMediaBag :: PandocMonad m => MediaBag -> m ()
+ Text.Pandoc.Class: setOutputFile :: PandocMonad m => Maybe FilePath -> m ()
+ Text.Pandoc.Class: setRequestHeader :: PandocMonad m => String -> String -> m ()
+ Text.Pandoc.Class: setResourcePath :: PandocMonad m => [FilePath] -> m ()
+ Text.Pandoc.Class: setTrace :: PandocMonad m => Bool -> m ()
+ Text.Pandoc.Class: setTranslations :: PandocMonad m => Lang -> m ()
+ Text.Pandoc.Class: setUserDataDir :: PandocMonad m => Maybe FilePath -> m ()
+ Text.Pandoc.Class: setVerbosity :: PandocMonad m => Verbosity -> m ()
+ Text.Pandoc.Class: toLang :: PandocMonad m => Maybe String -> m (Maybe Lang)
+ Text.Pandoc.Class: trace :: PandocMonad m => String -> m ()
+ Text.Pandoc.Class: translateTerm :: PandocMonad m => Term -> m String
+ Text.Pandoc.Emoji: emojis :: Map String String
+ Text.Pandoc.Error: PandocAppError :: String -> PandocError
+ Text.Pandoc.Error: PandocCouldNotFindDataFileError :: String -> PandocError
+ Text.Pandoc.Error: PandocEpubSubdirectoryError :: String -> PandocError
+ Text.Pandoc.Error: PandocFailOnWarningError :: PandocError
+ Text.Pandoc.Error: PandocFilterError :: String -> String -> PandocError
+ Text.Pandoc.Error: PandocHttpError :: String -> HttpException -> PandocError
+ Text.Pandoc.Error: PandocIOError :: String -> IOError -> PandocError
+ Text.Pandoc.Error: PandocMacroLoop :: String -> PandocError
+ Text.Pandoc.Error: PandocMakePDFError :: String -> PandocError
+ Text.Pandoc.Error: PandocOptionError :: String -> PandocError
+ Text.Pandoc.Error: PandocPDFError :: String -> PandocError
+ Text.Pandoc.Error: PandocPDFProgramNotFoundError :: String -> PandocError
+ Text.Pandoc.Error: PandocParseError :: String -> PandocError
+ Text.Pandoc.Error: PandocParsecError :: Input -> ParseError -> PandocError
+ Text.Pandoc.Error: PandocResourceNotFound :: String -> PandocError
+ Text.Pandoc.Error: PandocShouldNeverHappenError :: String -> PandocError
+ Text.Pandoc.Error: PandocSomeError :: String -> PandocError
+ Text.Pandoc.Error: PandocSyntaxMapError :: String -> PandocError
+ Text.Pandoc.Error: PandocTemplateError :: String -> PandocError
+ Text.Pandoc.Extensions: Ext_abbreviations :: Extension
+ Text.Pandoc.Extensions: Ext_all_symbols_escapable :: Extension
+ Text.Pandoc.Extensions: Ext_angle_brackets_escapable :: Extension
+ Text.Pandoc.Extensions: Ext_ascii_identifiers :: Extension
+ Text.Pandoc.Extensions: Ext_auto_identifiers :: Extension
+ Text.Pandoc.Extensions: Ext_autolink_bare_uris :: Extension
+ Text.Pandoc.Extensions: Ext_backtick_code_blocks :: Extension
+ Text.Pandoc.Extensions: Ext_blank_before_blockquote :: Extension
+ Text.Pandoc.Extensions: Ext_blank_before_header :: Extension
+ Text.Pandoc.Extensions: Ext_bracketed_spans :: Extension
+ Text.Pandoc.Extensions: Ext_citations :: Extension
+ Text.Pandoc.Extensions: Ext_compact_definition_lists :: Extension
+ Text.Pandoc.Extensions: Ext_definition_lists :: Extension
+ Text.Pandoc.Extensions: Ext_east_asian_line_breaks :: Extension
+ Text.Pandoc.Extensions: Ext_emoji :: Extension
+ Text.Pandoc.Extensions: Ext_epub_html_exts :: Extension
+ Text.Pandoc.Extensions: Ext_escaped_line_breaks :: Extension
+ Text.Pandoc.Extensions: Ext_example_lists :: Extension
+ Text.Pandoc.Extensions: Ext_fancy_lists :: Extension
+ Text.Pandoc.Extensions: Ext_fenced_code_attributes :: Extension
+ Text.Pandoc.Extensions: Ext_fenced_code_blocks :: Extension
+ Text.Pandoc.Extensions: Ext_fenced_divs :: Extension
+ Text.Pandoc.Extensions: Ext_footnotes :: Extension
+ Text.Pandoc.Extensions: Ext_four_space_rule :: Extension
+ Text.Pandoc.Extensions: Ext_gfm_auto_identifiers :: Extension
+ Text.Pandoc.Extensions: Ext_grid_tables :: Extension
+ Text.Pandoc.Extensions: Ext_hard_line_breaks :: Extension
+ Text.Pandoc.Extensions: Ext_header_attributes :: Extension
+ Text.Pandoc.Extensions: Ext_ignore_line_breaks :: Extension
+ Text.Pandoc.Extensions: Ext_implicit_figures :: Extension
+ Text.Pandoc.Extensions: Ext_implicit_header_references :: Extension
+ Text.Pandoc.Extensions: Ext_inline_code_attributes :: Extension
+ Text.Pandoc.Extensions: Ext_inline_notes :: Extension
+ Text.Pandoc.Extensions: Ext_intraword_underscores :: Extension
+ Text.Pandoc.Extensions: Ext_latex_macros :: Extension
+ Text.Pandoc.Extensions: Ext_line_blocks :: Extension
+ Text.Pandoc.Extensions: Ext_link_attributes :: Extension
+ Text.Pandoc.Extensions: Ext_lists_without_preceding_blankline :: Extension
+ Text.Pandoc.Extensions: Ext_literate_haskell :: Extension
+ Text.Pandoc.Extensions: Ext_markdown_attribute :: Extension
+ Text.Pandoc.Extensions: Ext_markdown_in_html_blocks :: Extension
+ Text.Pandoc.Extensions: Ext_mmd_header_identifiers :: Extension
+ Text.Pandoc.Extensions: Ext_mmd_link_attributes :: Extension
+ Text.Pandoc.Extensions: Ext_mmd_title_block :: Extension
+ Text.Pandoc.Extensions: Ext_multiline_tables :: Extension
+ Text.Pandoc.Extensions: Ext_native_divs :: Extension
+ Text.Pandoc.Extensions: Ext_native_spans :: Extension
+ Text.Pandoc.Extensions: Ext_old_dashes :: Extension
+ Text.Pandoc.Extensions: Ext_pandoc_title_block :: Extension
+ Text.Pandoc.Extensions: Ext_pipe_tables :: Extension
+ Text.Pandoc.Extensions: Ext_raw_attribute :: Extension
+ Text.Pandoc.Extensions: Ext_raw_html :: Extension
+ Text.Pandoc.Extensions: Ext_raw_tex :: Extension
+ Text.Pandoc.Extensions: Ext_shortcut_reference_links :: Extension
+ Text.Pandoc.Extensions: Ext_simple_tables :: Extension
+ Text.Pandoc.Extensions: Ext_smart :: Extension
+ Text.Pandoc.Extensions: Ext_space_in_atx_header :: Extension
+ Text.Pandoc.Extensions: Ext_spaced_reference_links :: Extension
+ Text.Pandoc.Extensions: Ext_startnum :: Extension
+ Text.Pandoc.Extensions: Ext_strikeout :: Extension
+ Text.Pandoc.Extensions: Ext_subscript :: Extension
+ Text.Pandoc.Extensions: Ext_superscript :: Extension
+ Text.Pandoc.Extensions: Ext_table_captions :: Extension
+ Text.Pandoc.Extensions: Ext_tex_math_dollars :: Extension
+ Text.Pandoc.Extensions: Ext_tex_math_double_backslash :: Extension
+ Text.Pandoc.Extensions: Ext_tex_math_single_backslash :: Extension
+ Text.Pandoc.Extensions: Ext_yaml_metadata_block :: Extension
+ Text.Pandoc.Extensions: data Extension
+ Text.Pandoc.Extensions: data Extensions
+ Text.Pandoc.Extensions: disableExtension :: Extension -> Extensions -> Extensions
+ Text.Pandoc.Extensions: emptyExtensions :: Extensions
+ Text.Pandoc.Extensions: enableExtension :: Extension -> Extensions -> Extensions
+ Text.Pandoc.Extensions: extensionEnabled :: Extension -> Extensions -> Bool
+ Text.Pandoc.Extensions: extensionsFromList :: [Extension] -> Extensions
+ Text.Pandoc.Extensions: getDefaultExtensions :: String -> Extensions
+ Text.Pandoc.Extensions: githubMarkdownExtensions :: Extensions
+ Text.Pandoc.Extensions: instance Data.Aeson.Types.FromJSON.FromJSON Text.Pandoc.Extensions.Extension
+ Text.Pandoc.Extensions: instance Data.Aeson.Types.FromJSON.FromJSON Text.Pandoc.Extensions.Extensions
+ Text.Pandoc.Extensions: instance Data.Aeson.Types.ToJSON.ToJSON Text.Pandoc.Extensions.Extension
+ Text.Pandoc.Extensions: instance Data.Aeson.Types.ToJSON.ToJSON Text.Pandoc.Extensions.Extensions
+ Text.Pandoc.Extensions: instance Data.Data.Data Text.Pandoc.Extensions.Extension
+ Text.Pandoc.Extensions: instance Data.Data.Data Text.Pandoc.Extensions.Extensions
+ Text.Pandoc.Extensions: instance GHC.Base.Monoid Text.Pandoc.Extensions.Extensions
+ Text.Pandoc.Extensions: instance GHC.Classes.Eq Text.Pandoc.Extensions.Extension
+ Text.Pandoc.Extensions: instance GHC.Classes.Eq Text.Pandoc.Extensions.Extensions
+ Text.Pandoc.Extensions: instance GHC.Classes.Ord Text.Pandoc.Extensions.Extension
+ Text.Pandoc.Extensions: instance GHC.Classes.Ord Text.Pandoc.Extensions.Extensions
+ Text.Pandoc.Extensions: instance GHC.Enum.Bounded Text.Pandoc.Extensions.Extension
+ Text.Pandoc.Extensions: instance GHC.Enum.Enum Text.Pandoc.Extensions.Extension
+ Text.Pandoc.Extensions: instance GHC.Generics.Generic Text.Pandoc.Extensions.Extension
+ Text.Pandoc.Extensions: instance GHC.Generics.Generic Text.Pandoc.Extensions.Extensions
+ Text.Pandoc.Extensions: instance GHC.Read.Read Text.Pandoc.Extensions.Extension
+ Text.Pandoc.Extensions: instance GHC.Read.Read Text.Pandoc.Extensions.Extensions
+ Text.Pandoc.Extensions: instance GHC.Show.Show Text.Pandoc.Extensions.Extension
+ Text.Pandoc.Extensions: instance GHC.Show.Show Text.Pandoc.Extensions.Extensions
+ Text.Pandoc.Extensions: multimarkdownExtensions :: Extensions
+ Text.Pandoc.Extensions: pandocExtensions :: Extensions
+ Text.Pandoc.Extensions: parseFormatSpec :: String -> Either ParseError (String, Extensions -> Extensions)
+ Text.Pandoc.Extensions: phpMarkdownExtraExtensions :: Extensions
+ Text.Pandoc.Extensions: plainExtensions :: Extensions
+ Text.Pandoc.Extensions: strictExtensions :: Extensions
+ Text.Pandoc.Highlighting: data Style :: *
+ Text.Pandoc.Highlighting: espresso :: Style
+ Text.Pandoc.Highlighting: formatHtmlBlock :: FormatOptions -> [SourceLine] -> Html
+ Text.Pandoc.Highlighting: formatHtmlInline :: FormatOptions -> [SourceLine] -> Html
+ Text.Pandoc.Highlighting: formatLaTeXBlock :: FormatOptions -> [SourceLine] -> Text
+ Text.Pandoc.Highlighting: formatLaTeXInline :: FormatOptions -> [SourceLine] -> Text
+ Text.Pandoc.Highlighting: fromListingsLanguage :: String -> Maybe String
+ Text.Pandoc.Highlighting: haddock :: Style
+ Text.Pandoc.Highlighting: highlight :: SyntaxMap -> (FormatOptions -> [SourceLine] -> a) -> Attr -> String -> Either String a
+ Text.Pandoc.Highlighting: highlightingStyles :: [(String, Style)]
+ Text.Pandoc.Highlighting: kate :: Style
+ Text.Pandoc.Highlighting: languages :: [String]
+ Text.Pandoc.Highlighting: languagesByExtension :: String -> [String]
+ Text.Pandoc.Highlighting: monochrome :: Style
+ Text.Pandoc.Highlighting: pygments :: Style
+ Text.Pandoc.Highlighting: styleToCss :: Style -> String
+ Text.Pandoc.Highlighting: styleToLaTeX :: Style -> Text
+ Text.Pandoc.Highlighting: tango :: Style
+ Text.Pandoc.Highlighting: toListingsLanguage :: String -> Maybe String
+ Text.Pandoc.Highlighting: zenburn :: Style
+ Text.Pandoc.ImageSize: Centimeter :: Double -> Dimension
+ Text.Pandoc.ImageSize: Em :: Double -> Dimension
+ Text.Pandoc.ImageSize: Eps :: ImageType
+ Text.Pandoc.ImageSize: Gif :: ImageType
+ Text.Pandoc.ImageSize: Height :: Direction
+ Text.Pandoc.ImageSize: Inch :: Double -> Dimension
+ Text.Pandoc.ImageSize: Jpeg :: ImageType
+ Text.Pandoc.ImageSize: Pdf :: ImageType
+ Text.Pandoc.ImageSize: Percent :: Double -> Dimension
+ Text.Pandoc.ImageSize: Pixel :: Integer -> Dimension
+ Text.Pandoc.ImageSize: Png :: ImageType
+ Text.Pandoc.ImageSize: Svg :: ImageType
+ Text.Pandoc.ImageSize: Width :: Direction
+ Text.Pandoc.ImageSize: data Dimension
+ Text.Pandoc.ImageSize: data Direction
+ Text.Pandoc.ImageSize: data ImageType
+ Text.Pandoc.ImageSize: desiredSizeInPoints :: WriterOptions -> Attr -> ImageSize -> (Double, Double)
+ Text.Pandoc.ImageSize: dimension :: Direction -> Attr -> Maybe Dimension
+ Text.Pandoc.ImageSize: imageSize :: WriterOptions -> ByteString -> Either String ImageSize
+ Text.Pandoc.ImageSize: imageType :: ByteString -> Maybe ImageType
+ Text.Pandoc.ImageSize: inEm :: WriterOptions -> Dimension -> Double
+ Text.Pandoc.ImageSize: inInch :: WriterOptions -> Dimension -> Double
+ Text.Pandoc.ImageSize: inPixel :: WriterOptions -> Dimension -> Integer
+ Text.Pandoc.ImageSize: inPoints :: WriterOptions -> Dimension -> Double
+ Text.Pandoc.ImageSize: instance Data.Default.Class.Default Text.Pandoc.ImageSize.ImageSize
+ Text.Pandoc.ImageSize: instance GHC.Classes.Eq Text.Pandoc.ImageSize.ImageSize
+ Text.Pandoc.ImageSize: instance GHC.Classes.Eq Text.Pandoc.ImageSize.TagType
+ Text.Pandoc.ImageSize: instance GHC.Classes.Ord Text.Pandoc.ImageSize.TagType
+ Text.Pandoc.ImageSize: instance GHC.Read.Read Text.Pandoc.ImageSize.ImageSize
+ Text.Pandoc.ImageSize: instance GHC.Show.Show Text.Pandoc.ImageSize.DataFormat
+ Text.Pandoc.ImageSize: instance GHC.Show.Show Text.Pandoc.ImageSize.Dimension
+ Text.Pandoc.ImageSize: instance GHC.Show.Show Text.Pandoc.ImageSize.Direction
+ Text.Pandoc.ImageSize: instance GHC.Show.Show Text.Pandoc.ImageSize.ImageSize
+ Text.Pandoc.ImageSize: instance GHC.Show.Show Text.Pandoc.ImageSize.ImageType
+ Text.Pandoc.ImageSize: instance GHC.Show.Show Text.Pandoc.ImageSize.TagType
+ Text.Pandoc.ImageSize: lengthToDim :: String -> Maybe Dimension
+ Text.Pandoc.ImageSize: numUnit :: String -> Maybe (Double, String)
+ Text.Pandoc.ImageSize: scaleDimension :: Double -> Dimension -> Dimension
+ Text.Pandoc.ImageSize: showFl :: (RealFloat a) => a -> String
+ Text.Pandoc.ImageSize: showInInch :: WriterOptions -> Dimension -> String
+ Text.Pandoc.ImageSize: showInPixel :: WriterOptions -> Dimension -> String
+ Text.Pandoc.ImageSize: sizeInPixels :: ImageSize -> (Integer, Integer)
+ Text.Pandoc.ImageSize: sizeInPoints :: ImageSize -> (Double, Double)
+ Text.Pandoc.Logging: BlockNotRendered :: Block -> LogMessage
+ Text.Pandoc.Logging: CircularReference :: String -> SourcePos -> LogMessage
+ Text.Pandoc.Logging: CouldNotConvertImage :: String -> String -> LogMessage
+ Text.Pandoc.Logging: CouldNotConvertTeXMath :: String -> String -> LogMessage
+ Text.Pandoc.Logging: CouldNotDetermineImageSize :: String -> String -> LogMessage
+ Text.Pandoc.Logging: CouldNotDetermineMimeType :: String -> LogMessage
+ Text.Pandoc.Logging: CouldNotFetchResource :: String -> String -> LogMessage
+ Text.Pandoc.Logging: CouldNotHighlight :: String -> LogMessage
+ Text.Pandoc.Logging: CouldNotLoadIncludeFile :: String -> SourcePos -> LogMessage
+ Text.Pandoc.Logging: CouldNotLoadTranslations :: String -> String -> LogMessage
+ Text.Pandoc.Logging: CouldNotParseCSS :: String -> LogMessage
+ Text.Pandoc.Logging: CouldNotParseYamlMetadata :: String -> SourcePos -> LogMessage
+ Text.Pandoc.Logging: Deprecated :: String -> String -> LogMessage
+ Text.Pandoc.Logging: DocxParserWarning :: String -> LogMessage
+ Text.Pandoc.Logging: DuplicateIdentifier :: String -> SourcePos -> LogMessage
+ Text.Pandoc.Logging: DuplicateLinkReference :: String -> SourcePos -> LogMessage
+ Text.Pandoc.Logging: DuplicateNoteReference :: String -> SourcePos -> LogMessage
+ Text.Pandoc.Logging: ERROR :: Verbosity
+ Text.Pandoc.Logging: Extracting :: String -> LogMessage
+ Text.Pandoc.Logging: Fetching :: String -> LogMessage
+ Text.Pandoc.Logging: INFO :: Verbosity
+ Text.Pandoc.Logging: InlineNotRendered :: Inline -> LogMessage
+ Text.Pandoc.Logging: InvalidLang :: String -> LogMessage
+ Text.Pandoc.Logging: MacroAlreadyDefined :: String -> SourcePos -> LogMessage
+ Text.Pandoc.Logging: MissingCharacter :: String -> LogMessage
+ Text.Pandoc.Logging: NoLangSpecified :: LogMessage
+ Text.Pandoc.Logging: NoTitleElement :: String -> LogMessage
+ Text.Pandoc.Logging: NoTranslation :: String -> LogMessage
+ Text.Pandoc.Logging: NoteDefinedButNotUsed :: String -> SourcePos -> LogMessage
+ Text.Pandoc.Logging: ParsingUnescaped :: String -> SourcePos -> LogMessage
+ Text.Pandoc.Logging: ReferenceNotFound :: String -> SourcePos -> LogMessage
+ Text.Pandoc.Logging: SkippedContent :: String -> SourcePos -> LogMessage
+ Text.Pandoc.Logging: UndefinedToggle :: String -> SourcePos -> LogMessage
+ Text.Pandoc.Logging: WARNING :: Verbosity
+ Text.Pandoc.Logging: data LogMessage
+ Text.Pandoc.Logging: data Verbosity
+ Text.Pandoc.Logging: encodeLogMessages :: [LogMessage] -> ByteString
+ Text.Pandoc.Logging: instance Data.Aeson.Types.FromJSON.FromJSON Text.Pandoc.Logging.Verbosity
+ Text.Pandoc.Logging: instance Data.Aeson.Types.ToJSON.ToJSON Text.Pandoc.Logging.LogMessage
+ Text.Pandoc.Logging: instance Data.Aeson.Types.ToJSON.ToJSON Text.Pandoc.Logging.Verbosity
+ Text.Pandoc.Logging: instance Data.Data.Data Text.Pandoc.Logging.LogMessage
+ Text.Pandoc.Logging: instance Data.Data.Data Text.Pandoc.Logging.Verbosity
+ Text.Pandoc.Logging: instance GHC.Classes.Eq Text.Pandoc.Logging.LogMessage
+ Text.Pandoc.Logging: instance GHC.Classes.Eq Text.Pandoc.Logging.Verbosity
+ Text.Pandoc.Logging: instance GHC.Classes.Ord Text.Pandoc.Logging.LogMessage
+ Text.Pandoc.Logging: instance GHC.Classes.Ord Text.Pandoc.Logging.Verbosity
+ Text.Pandoc.Logging: instance GHC.Enum.Bounded Text.Pandoc.Logging.Verbosity
+ Text.Pandoc.Logging: instance GHC.Enum.Enum Text.Pandoc.Logging.Verbosity
+ Text.Pandoc.Logging: instance GHC.Generics.Generic Text.Pandoc.Logging.LogMessage
+ Text.Pandoc.Logging: instance GHC.Generics.Generic Text.Pandoc.Logging.Verbosity
+ Text.Pandoc.Logging: instance GHC.Read.Read Text.Pandoc.Logging.Verbosity
+ Text.Pandoc.Logging: instance GHC.Show.Show Text.Pandoc.Logging.LogMessage
+ Text.Pandoc.Logging: instance GHC.Show.Show Text.Pandoc.Logging.Verbosity
+ Text.Pandoc.Logging: messageVerbosity :: LogMessage -> Verbosity
+ Text.Pandoc.Logging: showLogMessage :: LogMessage -> String
+ Text.Pandoc.Lua: LuaException :: String -> LuaException
+ Text.Pandoc.Lua: data LuaException :: *
+ Text.Pandoc.Lua: instance Foreign.Lua.Types.FromLuaStack.FromLuaStack Text.Pandoc.Lua.LuaFilter
+ Text.Pandoc.Lua: instance Foreign.Lua.Types.FromLuaStack.FromLuaStack Text.Pandoc.Lua.LuaFilterFunction
+ Text.Pandoc.Lua: instance Foreign.Lua.Types.FromLuaStack.FromLuaStack a => Foreign.Lua.Types.FromLuaStack.FromLuaStack (Data.Functor.Identity.Identity a)
+ Text.Pandoc.Lua: instance Foreign.Lua.Types.ToLuaStack.ToLuaStack Text.Pandoc.Lua.LuaFilterFunction
+ Text.Pandoc.Lua: pushPandocModule :: Maybe FilePath -> Lua ()
+ Text.Pandoc.Lua: runLuaFilter :: Maybe FilePath -> FilePath -> String -> Pandoc -> PandocIO (Either LuaException Pandoc)
+ Text.Pandoc.MIME: extensionFromMimeType :: MimeType -> Maybe String
+ Text.Pandoc.MIME: getMimeType :: FilePath -> Maybe MimeType
+ Text.Pandoc.MIME: getMimeTypeDef :: FilePath -> MimeType
+ Text.Pandoc.MIME: type MimeType = String
+ Text.Pandoc.Options: [readerAbbreviations] :: ReaderOptions -> Set String
+ Text.Pandoc.Options: [readerStripComments] :: ReaderOptions -> Bool
+ Text.Pandoc.Options: [writerEpubSubdirectory] :: WriterOptions -> String
+ Text.Pandoc.Options: [writerReferenceDoc] :: WriterOptions -> Maybe FilePath
+ Text.Pandoc.Options: [writerSyntaxMap] :: WriterOptions -> SyntaxMap
+ Text.Pandoc.Options: instance Data.Aeson.Types.FromJSON.FromJSON Text.Pandoc.Options.CiteMethod
+ Text.Pandoc.Options: instance Data.Aeson.Types.FromJSON.FromJSON Text.Pandoc.Options.HTMLMathMethod
+ Text.Pandoc.Options: instance Data.Aeson.Types.FromJSON.FromJSON Text.Pandoc.Options.HTMLSlideVariant
+ Text.Pandoc.Options: instance Data.Aeson.Types.FromJSON.FromJSON Text.Pandoc.Options.ObfuscationMethod
+ Text.Pandoc.Options: instance Data.Aeson.Types.FromJSON.FromJSON Text.Pandoc.Options.ReaderOptions
+ Text.Pandoc.Options: instance Data.Aeson.Types.FromJSON.FromJSON Text.Pandoc.Options.ReferenceLocation
+ Text.Pandoc.Options: instance Data.Aeson.Types.FromJSON.FromJSON Text.Pandoc.Options.TopLevelDivision
+ Text.Pandoc.Options: instance Data.Aeson.Types.FromJSON.FromJSON Text.Pandoc.Options.TrackChanges
+ Text.Pandoc.Options: instance Data.Aeson.Types.FromJSON.FromJSON Text.Pandoc.Options.WrapOption
+ Text.Pandoc.Options: instance Data.Aeson.Types.ToJSON.ToJSON Text.Pandoc.Options.CiteMethod
+ Text.Pandoc.Options: instance Data.Aeson.Types.ToJSON.ToJSON Text.Pandoc.Options.HTMLMathMethod
+ Text.Pandoc.Options: instance Data.Aeson.Types.ToJSON.ToJSON Text.Pandoc.Options.HTMLSlideVariant
+ Text.Pandoc.Options: instance Data.Aeson.Types.ToJSON.ToJSON Text.Pandoc.Options.ObfuscationMethod
+ Text.Pandoc.Options: instance Data.Aeson.Types.ToJSON.ToJSON Text.Pandoc.Options.ReaderOptions
+ Text.Pandoc.Options: instance Data.Aeson.Types.ToJSON.ToJSON Text.Pandoc.Options.ReferenceLocation
+ Text.Pandoc.Options: instance Data.Aeson.Types.ToJSON.ToJSON Text.Pandoc.Options.TopLevelDivision
+ Text.Pandoc.Options: instance Data.Aeson.Types.ToJSON.ToJSON Text.Pandoc.Options.TrackChanges
+ Text.Pandoc.Options: instance Data.Aeson.Types.ToJSON.ToJSON Text.Pandoc.Options.WrapOption
+ Text.Pandoc.Parsing: (<+?>) :: (Monoid a) => ParserT s st m a -> ParserT s st m a -> ParserT s st m a
+ Text.Pandoc.Parsing: (<?>) :: ParsecT s u m a -> String -> ParsecT s u m a
+ Text.Pandoc.Parsing: (<|>) :: ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
+ Text.Pandoc.Parsing: DoubleHeader :: Char -> HeaderType
+ Text.Pandoc.Parsing: Future :: Reader s a -> Future s a
+ Text.Pandoc.Parsing: InDoubleQuote :: QuoteContext
+ Text.Pandoc.Parsing: InSingleQuote :: QuoteContext
+ Text.Pandoc.Parsing: Key :: String -> Key
+ Text.Pandoc.Parsing: ListItemState :: ParserContext
+ Text.Pandoc.Parsing: NoQuote :: QuoteContext
+ Text.Pandoc.Parsing: NullState :: ParserContext
+ Text.Pandoc.Parsing: ParserState :: ReaderOptions -> ParserContext -> QuoteContext -> Bool -> Int -> Maybe SourcePos -> KeyTable -> KeyTable -> SubstTable -> NoteTable -> NoteTable' -> Set String -> Meta -> F Meta -> Map String String -> [HeaderType] -> Map Inlines String -> Set String -> Int -> Map String Int -> Map Text Macro -> String -> Map String (String, Maybe String, Attr) -> Maybe Inlines -> Maybe String -> Int -> [String] -> [LogMessage] -> Bool -> ParserState
+ Text.Pandoc.Parsing: SingleHeader :: Char -> HeaderType
+ Text.Pandoc.Parsing: [runDelayed] :: Future s a -> Reader s a
+ Text.Pandoc.Parsing: [stateAllowLinks] :: ParserState -> Bool
+ Text.Pandoc.Parsing: [stateCaption] :: ParserState -> Maybe Inlines
+ Text.Pandoc.Parsing: [stateCitations] :: ParserState -> Map String String
+ Text.Pandoc.Parsing: [stateContainers] :: ParserState -> [String]
+ Text.Pandoc.Parsing: [stateExamples] :: ParserState -> Map String Int
+ Text.Pandoc.Parsing: [stateFencedDivLevel] :: ParserState -> Int
+ Text.Pandoc.Parsing: [stateHeaderKeys] :: ParserState -> KeyTable
+ Text.Pandoc.Parsing: [stateHeaderTable] :: ParserState -> [HeaderType]
+ Text.Pandoc.Parsing: [stateHeaders] :: ParserState -> Map Inlines String
+ Text.Pandoc.Parsing: [stateIdentifiers] :: ParserState -> Set String
+ Text.Pandoc.Parsing: [stateInHtmlBlock] :: ParserState -> Maybe String
+ Text.Pandoc.Parsing: [stateKeys] :: ParserState -> KeyTable
+ Text.Pandoc.Parsing: [stateLastStrPos] :: ParserState -> Maybe SourcePos
+ Text.Pandoc.Parsing: [stateLogMessages] :: ParserState -> [LogMessage]
+ Text.Pandoc.Parsing: [stateMacros] :: ParserState -> Map Text Macro
+ Text.Pandoc.Parsing: [stateMarkdownAttribute] :: ParserState -> Bool
+ Text.Pandoc.Parsing: [stateMaxNestingLevel] :: ParserState -> Int
+ Text.Pandoc.Parsing: [stateMeta'] :: ParserState -> F Meta
+ Text.Pandoc.Parsing: [stateMeta] :: ParserState -> Meta
+ Text.Pandoc.Parsing: [stateNextExample] :: ParserState -> Int
+ Text.Pandoc.Parsing: [stateNoteRefs] :: ParserState -> Set String
+ Text.Pandoc.Parsing: [stateNotes'] :: ParserState -> NoteTable'
+ Text.Pandoc.Parsing: [stateNotes] :: ParserState -> NoteTable
+ Text.Pandoc.Parsing: [stateOptions] :: ParserState -> ReaderOptions
+ Text.Pandoc.Parsing: [stateParserContext] :: ParserState -> ParserContext
+ Text.Pandoc.Parsing: [stateQuoteContext] :: ParserState -> QuoteContext
+ Text.Pandoc.Parsing: [stateRstCustomRoles] :: ParserState -> Map String (String, Maybe String, Attr)
+ Text.Pandoc.Parsing: [stateRstDefaultRole] :: ParserState -> String
+ Text.Pandoc.Parsing: [stateSubstitutions] :: ParserState -> SubstTable
+ Text.Pandoc.Parsing: addIncludeFile :: HasIncludeFiles st => String -> st -> st
+ Text.Pandoc.Parsing: addLogMessage :: HasLogMessages st => LogMessage -> st -> st
+ Text.Pandoc.Parsing: alphaNum :: Stream s m Char => ParsecT s u m Char
+ Text.Pandoc.Parsing: anyChar :: Stream s m Char => ParsecT s u m Char
+ Text.Pandoc.Parsing: anyLine :: Monad m => ParserT [Char] st m [Char]
+ Text.Pandoc.Parsing: anyLineNewline :: Monad m => ParserT [Char] st m [Char]
+ Text.Pandoc.Parsing: anyOrderedListMarker :: Stream s m Char => ParserT s ParserState m ListAttributes
+ Text.Pandoc.Parsing: anyToken :: (Stream s m t, Show t) => ParsecT s u m t
+ Text.Pandoc.Parsing: apostrophe :: Stream s m Char => ParserT s st m Inlines
+ Text.Pandoc.Parsing: askF :: Future s s
+ Text.Pandoc.Parsing: asksF :: (s -> a) -> Future s a
+ Text.Pandoc.Parsing: blankline :: Stream s m Char => ParserT s st m Char
+ Text.Pandoc.Parsing: blanklines :: Stream s m Char => ParserT s st m [Char]
+ Text.Pandoc.Parsing: char :: Stream s m Char => Char -> ParsecT s u m Char
+ Text.Pandoc.Parsing: charRef :: Stream s m Char => ParserT s st m Inline
+ Text.Pandoc.Parsing: characterReference :: Stream s m Char => ParserT s st m Char
+ Text.Pandoc.Parsing: charsInBalanced :: Stream s m Char => Char -> Char -> ParserT s st m Char -> ParserT s st m String
+ Text.Pandoc.Parsing: choice :: Stream s m t => [ParsecT s u m a] -> ParsecT s u m a
+ Text.Pandoc.Parsing: citeKey :: (Stream s m Char, HasLastStrPosition st) => ParserT s st m (Bool, String)
+ Text.Pandoc.Parsing: class HasHeaderMap st
+ Text.Pandoc.Parsing: class HasIdentifierList st
+ Text.Pandoc.Parsing: class HasIncludeFiles st
+ Text.Pandoc.Parsing: class HasLastStrPosition st
+ Text.Pandoc.Parsing: class HasLogMessages st
+ Text.Pandoc.Parsing: class HasMacros st
+ Text.Pandoc.Parsing: class HasQuoteContext st m
+ Text.Pandoc.Parsing: class HasReaderOptions st where getOption f = (f . extractReaderOptions) <$> getState
+ Text.Pandoc.Parsing: class Monad m => Stream s (m :: * -> *) t | s -> t
+ Text.Pandoc.Parsing: count :: Stream s m t => Int -> ParsecT s u m a -> ParsecT s u m [a]
+ Text.Pandoc.Parsing: dash :: (HasReaderOptions st, Stream s m Char) => ParserT s st m Inlines
+ Text.Pandoc.Parsing: data HeaderType
+ Text.Pandoc.Parsing: data ParserContext
+ Text.Pandoc.Parsing: data ParserState
+ Text.Pandoc.Parsing: data QuoteContext
+ Text.Pandoc.Parsing: data SourcePos :: *
+ Text.Pandoc.Parsing: defaultParserState :: ParserState
+ Text.Pandoc.Parsing: digit :: Stream s m Char => ParsecT s u m Char
+ Text.Pandoc.Parsing: doubleQuoteEnd :: Stream s m Char => ParserT s st m ()
+ Text.Pandoc.Parsing: doubleQuoteStart :: (HasQuoteContext st m, Stream s m Char) => ParserT s st m ()
+ Text.Pandoc.Parsing: dropLatestIncludeFile :: HasIncludeFiles st => st -> st
+ Text.Pandoc.Parsing: ellipses :: Stream s m Char => ParserT s st m Inlines
+ Text.Pandoc.Parsing: emailAddress :: Stream s m Char => ParserT s st m (String, String)
+ Text.Pandoc.Parsing: enclosed :: (Show end, Stream s m Char) => ParserT s st m t -> ParserT s st m end -> ParserT s st m a -> ParserT s st m [a]
+ Text.Pandoc.Parsing: endBy :: Stream s m t => ParsecT s u m a -> ParsecT s u m sep -> ParsecT s u m [a]
+ Text.Pandoc.Parsing: endBy1 :: Stream s m t => ParsecT s u m a -> ParsecT s u m sep -> ParsecT s u m [a]
+ Text.Pandoc.Parsing: eof :: (Stream s m t, Show t) => ParsecT s u m ()
+ Text.Pandoc.Parsing: escaped :: Stream s m Char => ParserT s st m Char -> ParserT s st m Char
+ Text.Pandoc.Parsing: extractHeaderMap :: HasHeaderMap st => st -> Map Inlines String
+ Text.Pandoc.Parsing: extractIdClass :: Attr -> Attr
+ Text.Pandoc.Parsing: extractIdentifierList :: HasIdentifierList st => st -> Set String
+ Text.Pandoc.Parsing: extractMacros :: HasMacros st => st -> Map Text Macro
+ Text.Pandoc.Parsing: extractReaderOptions :: HasReaderOptions st => st -> ReaderOptions
+ Text.Pandoc.Parsing: getIncludeFiles :: HasIncludeFiles st => st -> [String]
+ Text.Pandoc.Parsing: getInput :: Monad m => ParsecT s u m s
+ Text.Pandoc.Parsing: getLastStrPos :: HasLastStrPosition st => st -> Maybe SourcePos
+ Text.Pandoc.Parsing: getLogMessages :: HasLogMessages st => st -> [LogMessage]
+ Text.Pandoc.Parsing: getOption :: (HasReaderOptions st, Stream s m t) => (ReaderOptions -> b) -> ParserT s st m b
+ Text.Pandoc.Parsing: getPosition :: Monad m => ParsecT s u m SourcePos
+ Text.Pandoc.Parsing: getQuoteContext :: (HasQuoteContext st m, Stream s m t) => ParsecT s st m QuoteContext
+ Text.Pandoc.Parsing: getState :: Monad m => ParsecT s u m u
+ Text.Pandoc.Parsing: gobbleAtMostSpaces :: (HasReaderOptions st, Monad m) => Int -> ParserT [Char] st m Int
+ Text.Pandoc.Parsing: gobbleSpaces :: (HasReaderOptions st, Monad m) => Int -> ParserT [Char] st m ()
+ Text.Pandoc.Parsing: gridTableWith :: (Monad m, HasReaderOptions st, Functor mf, Applicative mf, Monad mf) => ParserT [Char] st m (mf Blocks) -> Bool -> ParserT [Char] st m (mf Blocks)
+ Text.Pandoc.Parsing: gridTableWith' :: (Monad m, HasReaderOptions st, Functor mf, Applicative mf, Monad mf) => ParserT [Char] st m (mf Blocks) -> Bool -> ParserT [Char] st m (TableComponents mf)
+ Text.Pandoc.Parsing: guardDisabled :: (Stream s m a, HasReaderOptions st) => Extension -> ParserT s st m ()
+ Text.Pandoc.Parsing: guardEnabled :: (Stream s m a, HasReaderOptions st) => Extension -> ParserT s st m ()
+ Text.Pandoc.Parsing: indentWith :: Stream s m Char => HasReaderOptions st => Int -> ParserT s st m [Char]
+ Text.Pandoc.Parsing: infix 0 <?>
+ Text.Pandoc.Parsing: infixr 1 <|>
+ Text.Pandoc.Parsing: infixr 5 <+?>
+ Text.Pandoc.Parsing: insertIncludedFile :: (PandocMonad m, HasIncludeFiles st) => ParserT [a] st m Blocks -> (String -> [a]) -> [FilePath] -> FilePath -> ParserT [a] st m Blocks
+ Text.Pandoc.Parsing: insertIncludedFileF :: (PandocMonad m, HasIncludeFiles st) => ParserT String st m (Future st Blocks) -> [FilePath] -> FilePath -> ParserT String st m (Future st Blocks)
+ Text.Pandoc.Parsing: instance Data.Default.Class.Default Text.Pandoc.Parsing.ParserState
+ Text.Pandoc.Parsing: instance GHC.Base.Applicative (Text.Pandoc.Parsing.Future s)
+ Text.Pandoc.Parsing: instance GHC.Base.Functor (Text.Pandoc.Parsing.Future s)
+ Text.Pandoc.Parsing: instance GHC.Base.Monad (Text.Pandoc.Parsing.Future s)
+ Text.Pandoc.Parsing: instance GHC.Base.Monad m => Text.Pandoc.Parsing.HasQuoteContext Text.Pandoc.Parsing.ParserState m
+ Text.Pandoc.Parsing: instance GHC.Base.Monoid a => GHC.Base.Monoid (Text.Pandoc.Parsing.Future s a)
+ Text.Pandoc.Parsing: instance GHC.Classes.Eq Text.Pandoc.Parsing.HeaderType
+ Text.Pandoc.Parsing: instance GHC.Classes.Eq Text.Pandoc.Parsing.Key
+ Text.Pandoc.Parsing: instance GHC.Classes.Eq Text.Pandoc.Parsing.ParserContext
+ Text.Pandoc.Parsing: instance GHC.Classes.Eq Text.Pandoc.Parsing.QuoteContext
+ Text.Pandoc.Parsing: instance GHC.Classes.Ord Text.Pandoc.Parsing.Key
+ Text.Pandoc.Parsing: instance GHC.Read.Read Text.Pandoc.Parsing.Key
+ Text.Pandoc.Parsing: instance GHC.Show.Show Text.Pandoc.Parsing.HeaderType
+ Text.Pandoc.Parsing: instance GHC.Show.Show Text.Pandoc.Parsing.Key
+ Text.Pandoc.Parsing: instance GHC.Show.Show Text.Pandoc.Parsing.ParserContext
+ Text.Pandoc.Parsing: instance GHC.Show.Show Text.Pandoc.Parsing.QuoteContext
+ Text.Pandoc.Parsing: instance Text.Pandoc.Builder.HasMeta Text.Pandoc.Parsing.ParserState
+ Text.Pandoc.Parsing: instance Text.Pandoc.Parsing.HasHeaderMap Text.Pandoc.Parsing.ParserState
+ Text.Pandoc.Parsing: instance Text.Pandoc.Parsing.HasIdentifierList Text.Pandoc.Parsing.ParserState
+ Text.Pandoc.Parsing: instance Text.Pandoc.Parsing.HasIncludeFiles Text.Pandoc.Parsing.ParserState
+ Text.Pandoc.Parsing: instance Text.Pandoc.Parsing.HasLastStrPosition Text.Pandoc.Parsing.ParserState
+ Text.Pandoc.Parsing: instance Text.Pandoc.Parsing.HasLogMessages Text.Pandoc.Parsing.ParserState
+ Text.Pandoc.Parsing: instance Text.Pandoc.Parsing.HasMacros Text.Pandoc.Parsing.ParserState
+ Text.Pandoc.Parsing: instance Text.Pandoc.Parsing.HasReaderOptions Text.Pandoc.Parsing.ParserState
+ Text.Pandoc.Parsing: letter :: Stream s m Char => ParsecT s u m Char
+ Text.Pandoc.Parsing: lineBlockLines :: Monad m => ParserT [Char] st m [String]
+ Text.Pandoc.Parsing: lineClump :: Monad m => ParserT [Char] st m String
+ Text.Pandoc.Parsing: logMessage :: (Stream s m a, HasLogMessages st) => LogMessage -> ParserT s st m ()
+ Text.Pandoc.Parsing: lookAhead :: Stream s m t => ParsecT s u m a -> ParsecT s u m a
+ Text.Pandoc.Parsing: many :: ParsecT s u m a -> ParsecT s u m [a]
+ Text.Pandoc.Parsing: many1 :: Stream s m t => ParsecT s u m a -> ParsecT s u m [a]
+ Text.Pandoc.Parsing: many1Till :: (Show end, Stream s m t) => ParserT s st m a -> ParserT s st m end -> ParserT s st m [a]
+ Text.Pandoc.Parsing: manyTill :: Stream s m t => ParsecT s u m a -> ParsecT s u m end -> ParsecT s u m [a]
+ Text.Pandoc.Parsing: mathDisplay :: (HasReaderOptions st, Stream s m Char) => ParserT s st m String
+ Text.Pandoc.Parsing: mathInline :: (HasReaderOptions st, Stream s m Char) => ParserT s st m String
+ Text.Pandoc.Parsing: nested :: Stream s m a => ParserT s ParserState m a -> ParserT s ParserState m a
+ Text.Pandoc.Parsing: newPos :: SourceName -> Line -> Column -> SourcePos
+ Text.Pandoc.Parsing: newline :: Stream s m Char => ParsecT s u m Char
+ Text.Pandoc.Parsing: newtype Future s a
+ Text.Pandoc.Parsing: newtype Key
+ Text.Pandoc.Parsing: noneOf :: Stream s m Char => [Char] -> ParsecT s u m Char
+ Text.Pandoc.Parsing: nonspaceChar :: Stream s m Char => ParserT s st m Char
+ Text.Pandoc.Parsing: notAfterString :: (Stream s m a, HasLastStrPosition st) => ParserT s st m Bool
+ Text.Pandoc.Parsing: notFollowedBy :: (Stream s m t, Show a) => ParsecT s u m a -> ParsecT s u m ()
+ Text.Pandoc.Parsing: notFollowedBy' :: (Show b, Stream s m a) => ParserT s st m b -> ParserT s st m ()
+ Text.Pandoc.Parsing: oneOf :: Stream s m Char => [Char] -> ParsecT s u m Char
+ Text.Pandoc.Parsing: oneOfStrings :: Stream s m Char => [String] -> ParserT s st m String
+ Text.Pandoc.Parsing: oneOfStringsCI :: Stream s m Char => [String] -> ParserT s st m String
+ Text.Pandoc.Parsing: option :: Stream s m t => a -> ParsecT s u m a -> ParsecT s u m a
+ Text.Pandoc.Parsing: optionMaybe :: Stream s m t => ParsecT s u m a -> ParsecT s u m (Maybe a)
+ Text.Pandoc.Parsing: optional :: Stream s m t => ParsecT s u m a -> ParsecT s u m ()
+ Text.Pandoc.Parsing: orderedListMarker :: Stream s m Char => ListNumberStyle -> ListNumberDelim -> ParserT s ParserState m Int
+ Text.Pandoc.Parsing: parse :: Stream s Identity t => Parsec s () a -> SourceName -> s -> Either ParseError a
+ Text.Pandoc.Parsing: parseFromString :: Monad m => ParserT [Char] st m a -> String -> ParserT [Char] st m a
+ Text.Pandoc.Parsing: parseFromString' :: Monad m => ParserT String ParserState m a -> String -> ParserT String ParserState m a
+ Text.Pandoc.Parsing: readWith :: Parser [Char] st a -> st -> String -> Either PandocError a
+ Text.Pandoc.Parsing: readWithM :: Monad m => ParserT [Char] st m a -> st -> String -> m (Either PandocError a)
+ Text.Pandoc.Parsing: registerHeader :: (Stream s m a, HasReaderOptions st, HasHeaderMap st, HasLogMessages st, HasIdentifierList st) => Attr -> Inlines -> ParserT s st m Attr
+ Text.Pandoc.Parsing: reportLogMessages :: (PandocMonad m, HasLogMessages st) => ParserT s st m ()
+ Text.Pandoc.Parsing: returnF :: Monad m => a -> m (Future s a)
+ Text.Pandoc.Parsing: romanNumeral :: Stream s m Char => Bool -> ParserT s st m Int
+ Text.Pandoc.Parsing: runF :: Future s a -> s -> a
+ Text.Pandoc.Parsing: runParser :: Stream s Identity t => Parsec s u a -> u -> SourceName -> s -> Either ParseError a
+ Text.Pandoc.Parsing: runParserT :: Stream s m t => ParsecT s u m a -> u -> SourceName -> s -> m (Either ParseError a)
+ Text.Pandoc.Parsing: satisfy :: Stream s m Char => (Char -> Bool) -> ParsecT s u m Char
+ Text.Pandoc.Parsing: sepBy :: Stream s m t => ParsecT s u m a -> ParsecT s u m sep -> ParsecT s u m [a]
+ Text.Pandoc.Parsing: sepBy1 :: Stream s m t => ParsecT s u m a -> ParsecT s u m sep -> ParsecT s u m [a]
+ Text.Pandoc.Parsing: sepEndBy :: Stream s m t => ParsecT s u m a -> ParsecT s u m sep -> ParsecT s u m [a]
+ Text.Pandoc.Parsing: sepEndBy1 :: Stream s m t => ParsecT s u m a -> ParsecT s u m sep -> ParsecT s u m [a]
+ Text.Pandoc.Parsing: setInput :: Monad m => s -> ParsecT s u m ()
+ Text.Pandoc.Parsing: setLastStrPos :: HasLastStrPosition st => SourcePos -> st -> st
+ Text.Pandoc.Parsing: setPosition :: Monad m => SourcePos -> ParsecT s u m ()
+ Text.Pandoc.Parsing: setSourceColumn :: SourcePos -> Column -> SourcePos
+ Text.Pandoc.Parsing: setSourceLine :: SourcePos -> Line -> SourcePos
+ Text.Pandoc.Parsing: setState :: Monad m => u -> ParsecT s u m ()
+ Text.Pandoc.Parsing: singleQuoteEnd :: Stream s m Char => ParserT s st m ()
+ Text.Pandoc.Parsing: singleQuoteStart :: (HasLastStrPosition st, HasQuoteContext st m, Stream s m Char) => ParserT s st m ()
+ Text.Pandoc.Parsing: skipMany :: ParsecT s u m a -> ParsecT s u m ()
+ Text.Pandoc.Parsing: skipMany1 :: Stream s m t => ParsecT s u m a -> ParsecT s u m ()
+ Text.Pandoc.Parsing: skipSpaces :: Stream s m Char => ParserT s st m ()
+ Text.Pandoc.Parsing: smartPunctuation :: (HasReaderOptions st, HasLastStrPosition st, HasQuoteContext st m, Stream s m Char) => ParserT s st m Inlines -> ParserT s st m Inlines
+ Text.Pandoc.Parsing: sourceColumn :: SourcePos -> Column
+ Text.Pandoc.Parsing: sourceLine :: SourcePos -> Line
+ Text.Pandoc.Parsing: space :: Stream s m Char => ParsecT s u m Char
+ Text.Pandoc.Parsing: spaceChar :: Stream s m Char => ParserT s st m Char
+ Text.Pandoc.Parsing: spaces :: Stream s m Char => ParsecT s u m ()
+ Text.Pandoc.Parsing: string :: Stream s m Char => String -> ParsecT s u m String
+ Text.Pandoc.Parsing: stringAnyCase :: Stream s m Char => [Char] -> ParserT s st m String
+ Text.Pandoc.Parsing: tableWith :: (Stream s m Char, HasReaderOptions st, Functor mf, Applicative mf, Monad mf) => ParserT s st m (mf [Blocks], [Alignment], [Int]) -> ([Int] -> ParserT s st m (mf [Blocks])) -> ParserT s st m sep -> ParserT s st m end -> ParserT s st m (mf Blocks)
+ Text.Pandoc.Parsing: takeP :: Monad m => Int -> ParserT [Char] st m [Char]
+ Text.Pandoc.Parsing: takeWhileP :: Monad m => (Char -> Bool) -> ParserT [Char] st m [Char]
+ Text.Pandoc.Parsing: testStringWith :: Show a => ParserT [Char] ParserState Identity a -> [Char] -> IO ()
+ Text.Pandoc.Parsing: toKey :: String -> Key
+ Text.Pandoc.Parsing: token :: (Stream s m t) => (t -> String) -> (t -> SourcePos) -> (t -> Maybe a) -> ParsecT s st m a
+ Text.Pandoc.Parsing: tokenPrim :: Stream s m t => (t -> String) -> (SourcePos -> t -> s -> SourcePos) -> (t -> Maybe a) -> ParsecT s u m a
+ Text.Pandoc.Parsing: trimInlinesF :: Future s Inlines -> Future s Inlines
+ Text.Pandoc.Parsing: try :: ParsecT s u m a -> ParsecT s u m a
+ Text.Pandoc.Parsing: type Column = Int
+ Text.Pandoc.Parsing: type F = Future ParserState
+ Text.Pandoc.Parsing: type KeyTable = Map Key (Target, Attr)
+ Text.Pandoc.Parsing: type Line = Int
+ Text.Pandoc.Parsing: type NoteTable = [(String, String)]
+ Text.Pandoc.Parsing: type NoteTable' = Map String (SourcePos, F Blocks)
+ Text.Pandoc.Parsing: type Parser t s = Parsec t s
+ Text.Pandoc.Parsing: type ParserT = ParsecT
+ Text.Pandoc.Parsing: type SubstTable = Map Key Inlines
+ Text.Pandoc.Parsing: unexpected :: Stream s m t => String -> ParsecT s u m a
+ Text.Pandoc.Parsing: updateHeaderMap :: HasHeaderMap st => (Map Inlines String -> Map Inlines String) -> st -> st
+ Text.Pandoc.Parsing: updateIdentifierList :: HasIdentifierList st => (Set String -> Set String) -> st -> st
+ Text.Pandoc.Parsing: updateLastStrPos :: (Stream s m a, HasLastStrPosition st) => ParserT s st m ()
+ Text.Pandoc.Parsing: updateMacros :: HasMacros st => (Map Text Macro -> Map Text Macro) -> st -> st
+ Text.Pandoc.Parsing: updateState :: Monad m => (u -> u) -> ParsecT s u m ()
+ Text.Pandoc.Parsing: uri :: Monad m => ParserT [Char] st m (String, String)
+ Text.Pandoc.Parsing: widthsFromIndices :: Int -> [Int] -> [Double]
+ Text.Pandoc.Parsing: withHorizDisplacement :: Stream s m Char => ParserT s st m a -> ParserT s st m (a, Int)
+ Text.Pandoc.Parsing: withQuoteContext :: HasQuoteContext st m => QuoteContext -> ParsecT s st m a -> ParsecT s st m a
+ Text.Pandoc.Parsing: withRaw :: Monad m => ParsecT [Char] st m a -> ParsecT [Char] st m (a, [Char])
+ Text.Pandoc.Pretty: instance GHC.Classes.Eq Text.Pandoc.Pretty.D
+ Text.Pandoc.Pretty: instance GHC.Classes.Eq Text.Pandoc.Pretty.Doc
+ Text.Pandoc.Readers: ByteStringReader :: (ReaderOptions -> ByteString -> m Pandoc) -> Reader m
+ Text.Pandoc.Readers: TextReader :: (ReaderOptions -> Text -> m Pandoc) -> Reader m
+ Text.Pandoc.Readers: data Reader m
+ Text.Pandoc.Readers: getDefaultExtensions :: String -> Extensions
+ Text.Pandoc.Readers: getReader :: PandocMonad m => String -> Either String (Reader m, Extensions)
+ Text.Pandoc.Readers: readCommonMark :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
+ Text.Pandoc.Readers: readCreole :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
+ Text.Pandoc.Readers: readDocBook :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
+ Text.Pandoc.Readers: readDocx :: PandocMonad m => ReaderOptions -> ByteString -> m Pandoc
+ Text.Pandoc.Readers: readEPUB :: PandocMonad m => ReaderOptions -> ByteString -> m Pandoc
+ Text.Pandoc.Readers: readHaddock :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
+ Text.Pandoc.Readers: readHtml :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
+ Text.Pandoc.Readers: readJSON :: ReaderOptions -> Text -> Either PandocError Pandoc
+ Text.Pandoc.Readers: readLaTeX :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
+ Text.Pandoc.Readers: readMarkdown :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
+ Text.Pandoc.Readers: readMediaWiki :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
+ Text.Pandoc.Readers: readMuse :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
+ Text.Pandoc.Readers: readNative :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
+ Text.Pandoc.Readers: readOPML :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
+ Text.Pandoc.Readers: readOdt :: PandocMonad m => ReaderOptions -> ByteString -> m Pandoc
+ Text.Pandoc.Readers: readOrg :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
+ Text.Pandoc.Readers: readRST :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
+ Text.Pandoc.Readers: readTWiki :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
+ Text.Pandoc.Readers: readTextile :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
+ Text.Pandoc.Readers: readTikiWiki :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
+ Text.Pandoc.Readers: readTxt2Tags :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
+ Text.Pandoc.Readers: readVimwiki :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
+ Text.Pandoc.Readers: readers :: PandocMonad m => [(String, Reader m)]
+ Text.Pandoc.Readers.Creole: readCreole :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
+ Text.Pandoc.Readers.HTML: class NamedTag a
+ Text.Pandoc.Readers.HTML: getTagName :: NamedTag a => a -> Maybe Text
+ Text.Pandoc.Readers.HTML: instance Text.Pandoc.Class.PandocMonad m => Text.Pandoc.Parsing.HasQuoteContext Text.Pandoc.Readers.HTML.HTMLState (Control.Monad.Trans.Reader.ReaderT Text.Pandoc.Readers.HTML.HTMLLocal m)
+ Text.Pandoc.Readers.HTML: instance Text.Pandoc.Parsing.HasLogMessages Text.Pandoc.Readers.HTML.HTMLState
+ Text.Pandoc.Readers.HTML: instance Text.Pandoc.Readers.HTML.NamedTag (Text.HTML.TagSoup.Type.Tag Data.Text.Internal.Text)
+ Text.Pandoc.Readers.HTML: instance Text.Pandoc.Readers.HTML.NamedTag (Text.HTML.TagSoup.Type.Tag GHC.Base.String)
+ Text.Pandoc.Readers.LaTeX: applyMacros :: (PandocMonad m, HasMacros s, HasReaderOptions s) => String -> ParserT String s m String
+ Text.Pandoc.Readers.LaTeX: instance Data.Default.Class.Default Text.Pandoc.Readers.LaTeX.LaTeXState
+ Text.Pandoc.Readers.LaTeX: instance GHC.Show.Show Text.Pandoc.Readers.LaTeX.HeaderNum
+ Text.Pandoc.Readers.LaTeX: instance GHC.Show.Show Text.Pandoc.Readers.LaTeX.LaTeXState
+ Text.Pandoc.Readers.LaTeX: instance Text.Pandoc.Builder.HasMeta Text.Pandoc.Readers.LaTeX.LaTeXState
+ Text.Pandoc.Readers.LaTeX: instance Text.Pandoc.Class.PandocMonad m => Text.Pandoc.Parsing.HasQuoteContext Text.Pandoc.Readers.LaTeX.LaTeXState m
+ Text.Pandoc.Readers.LaTeX: instance Text.Pandoc.Parsing.HasHeaderMap Text.Pandoc.Readers.LaTeX.LaTeXState
+ Text.Pandoc.Readers.LaTeX: instance Text.Pandoc.Parsing.HasIdentifierList Text.Pandoc.Readers.LaTeX.LaTeXState
+ Text.Pandoc.Readers.LaTeX: instance Text.Pandoc.Parsing.HasIncludeFiles Text.Pandoc.Readers.LaTeX.LaTeXState
+ Text.Pandoc.Readers.LaTeX: instance Text.Pandoc.Parsing.HasLogMessages Text.Pandoc.Readers.LaTeX.LaTeXState
+ Text.Pandoc.Readers.LaTeX: instance Text.Pandoc.Parsing.HasMacros Text.Pandoc.Readers.LaTeX.LaTeXState
+ Text.Pandoc.Readers.LaTeX: instance Text.Pandoc.Parsing.HasReaderOptions Text.Pandoc.Readers.LaTeX.LaTeXState
+ Text.Pandoc.Readers.LaTeX.Types: Arg :: Int -> TokType
+ Text.Pandoc.Readers.LaTeX.Types: Comment :: TokType
+ Text.Pandoc.Readers.LaTeX.Types: CtrlSeq :: Text -> TokType
+ Text.Pandoc.Readers.LaTeX.Types: Esc1 :: TokType
+ Text.Pandoc.Readers.LaTeX.Types: Esc2 :: TokType
+ Text.Pandoc.Readers.LaTeX.Types: ExpandWhenDefined :: ExpansionPoint
+ Text.Pandoc.Readers.LaTeX.Types: ExpandWhenUsed :: ExpansionPoint
+ Text.Pandoc.Readers.LaTeX.Types: Macro :: ExpansionPoint -> Int -> (Maybe [Tok]) -> [Tok] -> Macro
+ Text.Pandoc.Readers.LaTeX.Types: Newline :: TokType
+ Text.Pandoc.Readers.LaTeX.Types: Spaces :: TokType
+ Text.Pandoc.Readers.LaTeX.Types: Symbol :: TokType
+ Text.Pandoc.Readers.LaTeX.Types: Tok :: SourcePos -> TokType -> Text -> Tok
+ Text.Pandoc.Readers.LaTeX.Types: Word :: TokType
+ Text.Pandoc.Readers.LaTeX.Types: data ExpansionPoint
+ Text.Pandoc.Readers.LaTeX.Types: data Macro
+ Text.Pandoc.Readers.LaTeX.Types: data SourcePos :: *
+ Text.Pandoc.Readers.LaTeX.Types: data Tok
+ Text.Pandoc.Readers.LaTeX.Types: data TokType
+ Text.Pandoc.Readers.LaTeX.Types: instance GHC.Classes.Eq Text.Pandoc.Readers.LaTeX.Types.ExpansionPoint
+ Text.Pandoc.Readers.LaTeX.Types: instance GHC.Classes.Eq Text.Pandoc.Readers.LaTeX.Types.Tok
+ Text.Pandoc.Readers.LaTeX.Types: instance GHC.Classes.Eq Text.Pandoc.Readers.LaTeX.Types.TokType
+ Text.Pandoc.Readers.LaTeX.Types: instance GHC.Classes.Ord Text.Pandoc.Readers.LaTeX.Types.ExpansionPoint
+ Text.Pandoc.Readers.LaTeX.Types: instance GHC.Classes.Ord Text.Pandoc.Readers.LaTeX.Types.Tok
+ Text.Pandoc.Readers.LaTeX.Types: instance GHC.Classes.Ord Text.Pandoc.Readers.LaTeX.Types.TokType
+ Text.Pandoc.Readers.LaTeX.Types: instance GHC.Show.Show Text.Pandoc.Readers.LaTeX.Types.ExpansionPoint
+ Text.Pandoc.Readers.LaTeX.Types: instance GHC.Show.Show Text.Pandoc.Readers.LaTeX.Types.Macro
+ Text.Pandoc.Readers.LaTeX.Types: instance GHC.Show.Show Text.Pandoc.Readers.LaTeX.Types.Tok
+ Text.Pandoc.Readers.LaTeX.Types: instance GHC.Show.Show Text.Pandoc.Readers.LaTeX.Types.TokType
+ Text.Pandoc.Readers.MediaWiki: instance Text.Pandoc.Parsing.HasLogMessages Text.Pandoc.Readers.MediaWiki.MWState
+ Text.Pandoc.Readers.Muse: readMuse :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
+ Text.Pandoc.Readers.TikiWiki: instance GHC.Classes.Eq Text.Pandoc.Readers.TikiWiki.ListNesting
+ Text.Pandoc.Readers.TikiWiki: instance GHC.Classes.Eq Text.Pandoc.Readers.TikiWiki.ListType
+ Text.Pandoc.Readers.TikiWiki: instance GHC.Classes.Ord Text.Pandoc.Readers.TikiWiki.ListNesting
+ Text.Pandoc.Readers.TikiWiki: instance GHC.Classes.Ord Text.Pandoc.Readers.TikiWiki.ListType
+ Text.Pandoc.Readers.TikiWiki: instance GHC.Show.Show Text.Pandoc.Readers.TikiWiki.ListNesting
+ Text.Pandoc.Readers.TikiWiki: instance GHC.Show.Show Text.Pandoc.Readers.TikiWiki.ListType
+ Text.Pandoc.Readers.TikiWiki: readTikiWiki :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
+ Text.Pandoc.Readers.Vimwiki: readVimwiki :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
+ Text.Pandoc.SelfContained: makeDataURI :: (MimeType, ByteString) -> String
+ Text.Pandoc.Shared: compactifyDL :: [(Inlines, [Blocks])] -> [(Inlines, [Blocks])]
+ Text.Pandoc.Shared: crFilter :: Text -> Text
+ Text.Pandoc.Shared: deNote :: Inline -> Inline
+ Text.Pandoc.Shared: eastAsianLineBreakFilter :: Pandoc -> Pandoc
+ Text.Pandoc.Shared: isURI :: String -> Bool
+ Text.Pandoc.Shared: schemes :: Set String
+ Text.Pandoc.Shared: underlineSpan :: Inlines -> Inlines
+ Text.Pandoc.UTF8: fromText :: Text -> ByteString
+ Text.Pandoc.UTF8: fromTextLazy :: Text -> ByteString
+ Text.Pandoc.UTF8: hPutStrLnWith :: Newline -> Handle -> String -> IO ()
+ Text.Pandoc.UTF8: hPutStrWith :: Newline -> Handle -> String -> IO ()
+ Text.Pandoc.UTF8: putStrLnWith :: Newline -> String -> IO ()
+ Text.Pandoc.UTF8: putStrWith :: Newline -> String -> IO ()
+ Text.Pandoc.UTF8: toText :: ByteString -> Text
+ Text.Pandoc.UTF8: toTextLazy :: ByteString -> Text
+ Text.Pandoc.UTF8: writeFileWith :: Newline -> FilePath -> String -> IO ()
+ Text.Pandoc.Writers: ByteStringWriter :: (WriterOptions -> Pandoc -> m ByteString) -> Writer m
+ Text.Pandoc.Writers: TextWriter :: (WriterOptions -> Pandoc -> m Text) -> Writer m
+ Text.Pandoc.Writers: data Writer m
+ Text.Pandoc.Writers: getWriter :: PandocMonad m => String -> Either String (Writer m, Extensions)
+ Text.Pandoc.Writers: writeAsciiDoc :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers: writeBeamer :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers: writeCommonMark :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers: writeConTeXt :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers: writeCustom :: FilePath -> WriterOptions -> Pandoc -> IO Text
+ Text.Pandoc.Writers: writeDZSlides :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers: writeDocbook4 :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers: writeDocbook5 :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers: writeDocx :: (PandocMonad m) => WriterOptions -> Pandoc -> m ByteString
+ Text.Pandoc.Writers: writeDokuWiki :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers: writeEPUB2 :: PandocMonad m => WriterOptions -> Pandoc -> m ByteString
+ Text.Pandoc.Writers: writeEPUB3 :: PandocMonad m => WriterOptions -> Pandoc -> m ByteString
+ Text.Pandoc.Writers: writeFB2 :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers: writeHaddock :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers: writeHtml4 :: PandocMonad m => WriterOptions -> Pandoc -> m Html
+ Text.Pandoc.Writers: writeHtml4String :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers: writeHtml5 :: PandocMonad m => WriterOptions -> Pandoc -> m Html
+ Text.Pandoc.Writers: writeHtml5String :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers: writeICML :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers: writeJATS :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers: writeJSON :: WriterOptions -> Pandoc -> Text
+ Text.Pandoc.Writers: writeLaTeX :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers: writeMan :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers: writeMarkdown :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers: writeMediaWiki :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers: writeMs :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers: writeMuse :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers: writeNative :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers: writeODT :: PandocMonad m => WriterOptions -> Pandoc -> m ByteString
+ Text.Pandoc.Writers: writeOPML :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers: writeOpenDocument :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers: writeOrg :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers: writePlain :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers: writeRST :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers: writeRTF :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers: writeRevealJs :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers: writeS5 :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers: writeSlideous :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers: writeSlidy :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers: writeTEI :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers: writeTexinfo :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers: writeTextile :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers: writeZimWiki :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers: writers :: PandocMonad m => [(String, Writer m)]
+ Text.Pandoc.Writers.Custom: instance Foreign.Lua.Types.ToLuaStack.ToLuaStack GHC.Types.Double
+ Text.Pandoc.Writers.Custom: instance Foreign.Lua.Types.ToLuaStack.ToLuaStack GHC.Types.Int
+ Text.Pandoc.Writers.Custom: instance Foreign.Lua.Types.ToLuaStack.ToLuaStack Text.Pandoc.Definition.Citation
+ Text.Pandoc.Writers.Custom: instance Foreign.Lua.Types.ToLuaStack.ToLuaStack Text.Pandoc.Definition.Format
+ Text.Pandoc.Writers.Custom: instance Foreign.Lua.Types.ToLuaStack.ToLuaStack Text.Pandoc.Definition.MetaValue
+ Text.Pandoc.Writers.Custom: instance Foreign.Lua.Types.ToLuaStack.ToLuaStack [Text.Pandoc.Definition.Block]
+ Text.Pandoc.Writers.Custom: instance Foreign.Lua.Types.ToLuaStack.ToLuaStack [Text.Pandoc.Definition.Inline]
+ Text.Pandoc.Writers.Docbook: instance GHC.Classes.Eq Text.Pandoc.Writers.Docbook.DocBookVersion
+ Text.Pandoc.Writers.Docbook: instance GHC.Show.Show Text.Pandoc.Writers.Docbook.DocBookVersion
+ Text.Pandoc.Writers.Docbook: writeDocbook4 :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers.Docbook: writeDocbook5 :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers.EPUB: writeEPUB2 :: PandocMonad m => WriterOptions -> Pandoc -> m ByteString
+ Text.Pandoc.Writers.EPUB: writeEPUB3 :: PandocMonad m => WriterOptions -> Pandoc -> m ByteString
+ Text.Pandoc.Writers.HTML: writeDZSlides :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers.HTML: writeHtml4 :: PandocMonad m => WriterOptions -> Pandoc -> m Html
+ Text.Pandoc.Writers.HTML: writeHtml4String :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers.HTML: writeHtml5 :: PandocMonad m => WriterOptions -> Pandoc -> m Html
+ Text.Pandoc.Writers.HTML: writeHtml5String :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers.HTML: writeHtmlStringForEPUB :: PandocMonad m => EPUBVersion -> WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers.HTML: writeRevealJs :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers.HTML: writeS5 :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers.HTML: writeSlideous :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers.HTML: writeSlidy :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers.JATS: instance GHC.Classes.Eq Text.Pandoc.Writers.JATS.JATSVersion
+ Text.Pandoc.Writers.JATS: instance GHC.Show.Show Text.Pandoc.Writers.JATS.JATSVersion
+ Text.Pandoc.Writers.JATS: writeJATS :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers.LaTeX: writeBeamer :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers.Math: convertMath :: PandocMonad m => (DisplayType -> [Exp] -> a) -> MathType -> String -> m (Either Inline a)
+ Text.Pandoc.Writers.Math: defaultKaTeXURL :: String
+ Text.Pandoc.Writers.Math: defaultMathJaxURL :: String
+ Text.Pandoc.Writers.Math: texMathToInlines :: PandocMonad m => MathType -> String -> m [Inline]
+ Text.Pandoc.Writers.Ms: writeMs :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers.Muse: writeMuse :: PandocMonad m => WriterOptions -> Pandoc -> m Text
+ Text.Pandoc.Writers.Shared: addVariablesToJSON :: WriterOptions -> Value -> Value
+ Text.Pandoc.Writers.Shared: defField :: ToJSON a => String -> a -> Value -> Value
+ Text.Pandoc.Writers.Shared: fixDisplayMath :: Block -> Block
+ Text.Pandoc.Writers.Shared: getField :: FromJSON a => String -> Value -> Maybe a
+ Text.Pandoc.Writers.Shared: gridTable :: Monad m => WriterOptions -> (WriterOptions -> [Block] -> m Doc) -> Bool -> [Alignment] -> [Double] -> [[Block]] -> [[[Block]]] -> m Doc
+ Text.Pandoc.Writers.Shared: metaToJSON :: (Functor m, Monad m, ToJSON a) => WriterOptions -> ([Block] -> m a) -> ([Inline] -> m a) -> Meta -> m Value
+ Text.Pandoc.Writers.Shared: metaToJSON' :: (Functor m, Monad m, ToJSON a) => ([Block] -> m a) -> ([Inline] -> m a) -> Meta -> m Value
+ Text.Pandoc.Writers.Shared: resetField :: ToJSON a => String -> a -> Value -> Value
+ Text.Pandoc.Writers.Shared: setField :: ToJSON a => String -> a -> Value -> Value
+ Text.Pandoc.Writers.Shared: tagWithAttrs :: String -> Attr -> Doc
+ Text.Pandoc.Writers.Shared: unsmartify :: WriterOptions -> String -> String
- Text.Pandoc.Error: handleError :: Either PandocError a -> a
+ Text.Pandoc.Error: handleError :: Either PandocError a -> IO a
- Text.Pandoc.Options: KaTeX :: String -> String -> HTMLMathMethod
+ Text.Pandoc.Options: KaTeX :: String -> HTMLMathMethod
- Text.Pandoc.Options: MathML :: (Maybe String) -> HTMLMathMethod
+ Text.Pandoc.Options: MathML :: HTMLMathMethod
- Text.Pandoc.Options: ReaderOptions :: Set Extension -> Bool -> Bool -> Bool -> Int -> Int -> Bool -> Bool -> [String] -> String -> Bool -> TrackChanges -> Bool -> ReaderOptions
+ Text.Pandoc.Options: ReaderOptions :: Extensions -> Bool -> Int -> Int -> [String] -> Set String -> String -> TrackChanges -> Bool -> ReaderOptions
- Text.Pandoc.Options: WriterOptions :: Maybe String -> [(String, String)] -> Int -> Bool -> HTMLSlideVariant -> Bool -> HTMLMathMethod -> Bool -> Bool -> [Int] -> Bool -> Set Extension -> Bool -> Int -> WrapOption -> Int -> ObfuscationMethod -> String -> Maybe String -> Maybe FilePath -> CiteMethod -> Bool -> Bool -> Bool -> Bool -> Maybe Int -> TopLevelDivision -> Bool -> Bool -> Style -> Bool -> Bool -> Maybe EPUBVersion -> String -> Maybe String -> [FilePath] -> Int -> Int -> Maybe FilePath -> Maybe FilePath -> MediaBag -> Bool -> [String] -> ReferenceLocation -> WriterOptions
+ Text.Pandoc.Options: WriterOptions :: Maybe String -> [(String, String)] -> Int -> Bool -> Bool -> HTMLMathMethod -> Bool -> [Int] -> Bool -> Extensions -> Bool -> Int -> WrapOption -> Int -> ObfuscationMethod -> String -> CiteMethod -> Bool -> Maybe Int -> TopLevelDivision -> Bool -> Maybe Style -> Bool -> String -> Maybe String -> [FilePath] -> Int -> Int -> Maybe FilePath -> ReferenceLocation -> SyntaxMap -> WriterOptions
- Text.Pandoc.Options: [readerExtensions] :: ReaderOptions -> Set Extension
+ Text.Pandoc.Options: [readerExtensions] :: ReaderOptions -> Extensions
- Text.Pandoc.Options: [writerEpubMetadata] :: WriterOptions -> String
+ Text.Pandoc.Options: [writerEpubMetadata] :: WriterOptions -> Maybe String
- Text.Pandoc.Options: [writerExtensions] :: WriterOptions -> Set Extension
+ Text.Pandoc.Options: [writerExtensions] :: WriterOptions -> Extensions
- Text.Pandoc.Options: [writerHighlightStyle] :: WriterOptions -> Style
+ Text.Pandoc.Options: [writerHighlightStyle] :: WriterOptions -> Maybe Style
- Text.Pandoc.PDF: makePDF :: String -> (WriterOptions -> Pandoc -> String) -> WriterOptions -> Pandoc -> IO (Either ByteString ByteString)
+ Text.Pandoc.PDF: makePDF :: String -> [String] -> (WriterOptions -> Pandoc -> PandocIO Text) -> WriterOptions -> Pandoc -> PandocIO (Either ByteString ByteString)
- Text.Pandoc.Process: pipeProcess :: Maybe [(String, String)] -> FilePath -> [String] -> ByteString -> IO (ExitCode, ByteString, ByteString)
+ Text.Pandoc.Process: pipeProcess :: Maybe [(String, String)] -> FilePath -> [String] -> ByteString -> IO (ExitCode, ByteString)
- Text.Pandoc.Readers.CommonMark: readCommonMark :: ReaderOptions -> String -> Either PandocError Pandoc
+ Text.Pandoc.Readers.CommonMark: readCommonMark :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
- Text.Pandoc.Readers.DocBook: readDocBook :: ReaderOptions -> String -> Either PandocError Pandoc
+ Text.Pandoc.Readers.DocBook: readDocBook :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
- Text.Pandoc.Readers.Docx: readDocx :: ReaderOptions -> ByteString -> Either PandocError (Pandoc, MediaBag)
+ Text.Pandoc.Readers.Docx: readDocx :: PandocMonad m => ReaderOptions -> ByteString -> m Pandoc
- Text.Pandoc.Readers.EPUB: readEPUB :: ReaderOptions -> ByteString -> Either PandocError (Pandoc, MediaBag)
+ Text.Pandoc.Readers.EPUB: readEPUB :: PandocMonad m => ReaderOptions -> ByteString -> m Pandoc
- Text.Pandoc.Readers.HTML: htmlInBalanced :: (Monad m) => (Tag String -> Bool) -> ParserT String st m String
+ Text.Pandoc.Readers.HTML: htmlInBalanced :: (HasReaderOptions st, Monad m) => (Tag String -> Bool) -> ParserT String st m String
- Text.Pandoc.Readers.HTML: htmlTag :: Monad m => (Tag String -> Bool) -> ParserT [Char] st m (Tag String, String)
+ Text.Pandoc.Readers.HTML: htmlTag :: (HasReaderOptions st, Monad m) => (Tag String -> Bool) -> ParserT [Char] st m (Tag String, String)
- Text.Pandoc.Readers.HTML: isBlockTag :: Tag String -> Bool
+ Text.Pandoc.Readers.HTML: isBlockTag :: NamedTag (Tag a) => Tag a -> Bool
- Text.Pandoc.Readers.HTML: isCommentTag :: Tag String -> Bool
+ Text.Pandoc.Readers.HTML: isCommentTag :: Tag a -> Bool
- Text.Pandoc.Readers.HTML: isInlineTag :: Tag String -> Bool
+ Text.Pandoc.Readers.HTML: isInlineTag :: NamedTag (Tag a) => Tag a -> Bool
- Text.Pandoc.Readers.HTML: isTextTag :: Tag String -> Bool
+ Text.Pandoc.Readers.HTML: isTextTag :: Tag a -> Bool
- Text.Pandoc.Readers.HTML: readHtml :: ReaderOptions -> String -> Either PandocError Pandoc
+ Text.Pandoc.Readers.HTML: readHtml :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
- Text.Pandoc.Readers.Haddock: readHaddock :: ReaderOptions -> String -> Either PandocError Pandoc
+ Text.Pandoc.Readers.Haddock: readHaddock :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
- Text.Pandoc.Readers.LaTeX: inlineCommand :: LP Inlines
+ Text.Pandoc.Readers.LaTeX: inlineCommand :: PandocMonad m => ParserT String ParserState m Inlines
- Text.Pandoc.Readers.LaTeX: rawLaTeXBlock :: LP String
+ Text.Pandoc.Readers.LaTeX: rawLaTeXBlock :: (PandocMonad m, HasMacros s, HasReaderOptions s) => ParserT String s m String
- Text.Pandoc.Readers.LaTeX: rawLaTeXInline :: LP Inline
+ Text.Pandoc.Readers.LaTeX: rawLaTeXInline :: (PandocMonad m, HasMacros s, HasReaderOptions s) => ParserT String s m String
- Text.Pandoc.Readers.LaTeX: readLaTeX :: ReaderOptions -> String -> Either PandocError Pandoc
+ Text.Pandoc.Readers.LaTeX: readLaTeX :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
- Text.Pandoc.Readers.Markdown: readMarkdown :: ReaderOptions -> String -> Either PandocError Pandoc
+ Text.Pandoc.Readers.Markdown: readMarkdown :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
- Text.Pandoc.Readers.MediaWiki: readMediaWiki :: ReaderOptions -> String -> Either PandocError Pandoc
+ Text.Pandoc.Readers.MediaWiki: readMediaWiki :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
- Text.Pandoc.Readers.Native: readNative :: String -> Either PandocError Pandoc
+ Text.Pandoc.Readers.Native: readNative :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
- Text.Pandoc.Readers.OPML: readOPML :: ReaderOptions -> String -> Either PandocError Pandoc
+ Text.Pandoc.Readers.OPML: readOPML :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
- Text.Pandoc.Readers.Odt: readOdt :: ReaderOptions -> ByteString -> Either PandocError (Pandoc, MediaBag)
+ Text.Pandoc.Readers.Odt: readOdt :: PandocMonad m => ReaderOptions -> ByteString -> m Pandoc
- Text.Pandoc.Readers.Org: readOrg :: ReaderOptions -> String -> Either PandocError Pandoc
+ Text.Pandoc.Readers.Org: readOrg :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
- Text.Pandoc.Readers.RST: readRST :: ReaderOptions -> String -> Either PandocError Pandoc
+ Text.Pandoc.Readers.RST: readRST :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
- Text.Pandoc.Readers.TWiki: readTWiki :: ReaderOptions -> String -> Either PandocError Pandoc
+ Text.Pandoc.Readers.TWiki: readTWiki :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
- Text.Pandoc.Readers.Textile: readTextile :: ReaderOptions -> String -> Either PandocError Pandoc
+ Text.Pandoc.Readers.Textile: readTextile :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
- Text.Pandoc.Readers.Txt2Tags: getT2TMeta :: [FilePath] -> FilePath -> IO T2TMeta
+ Text.Pandoc.Readers.Txt2Tags: getT2TMeta :: PandocMonad m => m T2TMeta
- Text.Pandoc.Readers.Txt2Tags: readTxt2Tags :: T2TMeta -> ReaderOptions -> String -> Either PandocError Pandoc
+ Text.Pandoc.Readers.Txt2Tags: readTxt2Tags :: PandocMonad m => ReaderOptions -> Text -> m Pandoc
- Text.Pandoc.SelfContained: makeSelfContained :: WriterOptions -> String -> IO String
+ Text.Pandoc.SelfContained: makeSelfContained :: PandocMonad m => String -> m String
- Text.Pandoc.Shared: compactify :: [[Block]] -> [[Block]]
+ Text.Pandoc.Shared: compactify :: [Blocks] -> [Blocks]
- Text.Pandoc.Shared: tabFilter :: Int -> String -> String
+ Text.Pandoc.Shared: tabFilter :: Int -> Text -> Text
- Text.Pandoc.Templates: getDefaultTemplate :: (Maybe FilePath) -> String -> IO (Either IOException String)
+ Text.Pandoc.Templates: getDefaultTemplate :: PandocMonad m => String -> m String
- Text.Pandoc.Templates: renderTemplate' :: (ToJSON a, TemplateTarget b) => String -> a -> b
+ Text.Pandoc.Templates: renderTemplate' :: (PandocMonad m, ToJSON a, TemplateTarget b) => String -> a -> m b
- Text.Pandoc.Writers.AsciiDoc: writeAsciiDoc :: WriterOptions -> Pandoc -> String
+ Text.Pandoc.Writers.AsciiDoc: writeAsciiDoc :: PandocMonad m => WriterOptions -> Pandoc -> m Text
- Text.Pandoc.Writers.CommonMark: writeCommonMark :: WriterOptions -> Pandoc -> String
+ Text.Pandoc.Writers.CommonMark: writeCommonMark :: PandocMonad m => WriterOptions -> Pandoc -> m Text
- Text.Pandoc.Writers.ConTeXt: writeConTeXt :: WriterOptions -> Pandoc -> String
+ Text.Pandoc.Writers.ConTeXt: writeConTeXt :: PandocMonad m => WriterOptions -> Pandoc -> m Text
- Text.Pandoc.Writers.Custom: writeCustom :: FilePath -> WriterOptions -> Pandoc -> IO String
+ Text.Pandoc.Writers.Custom: writeCustom :: FilePath -> WriterOptions -> Pandoc -> IO Text
- Text.Pandoc.Writers.Docx: writeDocx :: WriterOptions -> Pandoc -> IO ByteString
+ Text.Pandoc.Writers.Docx: writeDocx :: (PandocMonad m) => WriterOptions -> Pandoc -> m ByteString
- Text.Pandoc.Writers.DokuWiki: writeDokuWiki :: WriterOptions -> Pandoc -> String
+ Text.Pandoc.Writers.DokuWiki: writeDokuWiki :: PandocMonad m => WriterOptions -> Pandoc -> m Text
- Text.Pandoc.Writers.FB2: writeFB2 :: WriterOptions -> Pandoc -> IO String
+ Text.Pandoc.Writers.FB2: writeFB2 :: PandocMonad m => WriterOptions -> Pandoc -> m Text
- Text.Pandoc.Writers.Haddock: writeHaddock :: WriterOptions -> Pandoc -> String
+ Text.Pandoc.Writers.Haddock: writeHaddock :: PandocMonad m => WriterOptions -> Pandoc -> m Text
- Text.Pandoc.Writers.ICML: writeICML :: WriterOptions -> Pandoc -> IO String
+ Text.Pandoc.Writers.ICML: writeICML :: PandocMonad m => WriterOptions -> Pandoc -> m Text
- Text.Pandoc.Writers.LaTeX: writeLaTeX :: WriterOptions -> Pandoc -> String
+ Text.Pandoc.Writers.LaTeX: writeLaTeX :: PandocMonad m => WriterOptions -> Pandoc -> m Text
- Text.Pandoc.Writers.Man: writeMan :: WriterOptions -> Pandoc -> String
+ Text.Pandoc.Writers.Man: writeMan :: PandocMonad m => WriterOptions -> Pandoc -> m Text
- Text.Pandoc.Writers.Markdown: writeMarkdown :: WriterOptions -> Pandoc -> String
+ Text.Pandoc.Writers.Markdown: writeMarkdown :: PandocMonad m => WriterOptions -> Pandoc -> m Text
- Text.Pandoc.Writers.Markdown: writePlain :: WriterOptions -> Pandoc -> String
+ Text.Pandoc.Writers.Markdown: writePlain :: PandocMonad m => WriterOptions -> Pandoc -> m Text
- Text.Pandoc.Writers.MediaWiki: writeMediaWiki :: WriterOptions -> Pandoc -> String
+ Text.Pandoc.Writers.MediaWiki: writeMediaWiki :: PandocMonad m => WriterOptions -> Pandoc -> m Text
- Text.Pandoc.Writers.Native: writeNative :: WriterOptions -> Pandoc -> String
+ Text.Pandoc.Writers.Native: writeNative :: PandocMonad m => WriterOptions -> Pandoc -> m Text
- Text.Pandoc.Writers.ODT: writeODT :: WriterOptions -> Pandoc -> IO ByteString
+ Text.Pandoc.Writers.ODT: writeODT :: PandocMonad m => WriterOptions -> Pandoc -> m ByteString
- Text.Pandoc.Writers.OPML: writeOPML :: WriterOptions -> Pandoc -> String
+ Text.Pandoc.Writers.OPML: writeOPML :: PandocMonad m => WriterOptions -> Pandoc -> m Text
- Text.Pandoc.Writers.OpenDocument: writeOpenDocument :: WriterOptions -> Pandoc -> String
+ Text.Pandoc.Writers.OpenDocument: writeOpenDocument :: PandocMonad m => WriterOptions -> Pandoc -> m Text
- Text.Pandoc.Writers.Org: writeOrg :: WriterOptions -> Pandoc -> String
+ Text.Pandoc.Writers.Org: writeOrg :: PandocMonad m => WriterOptions -> Pandoc -> m Text
- Text.Pandoc.Writers.RST: writeRST :: WriterOptions -> Pandoc -> String
+ Text.Pandoc.Writers.RST: writeRST :: PandocMonad m => WriterOptions -> Pandoc -> m Text
- Text.Pandoc.Writers.RTF: writeRTF :: WriterOptions -> Pandoc -> String
+ Text.Pandoc.Writers.RTF: writeRTF :: PandocMonad m => WriterOptions -> Pandoc -> m Text
- Text.Pandoc.Writers.TEI: writeTEI :: WriterOptions -> Pandoc -> String
+ Text.Pandoc.Writers.TEI: writeTEI :: PandocMonad m => WriterOptions -> Pandoc -> m Text
- Text.Pandoc.Writers.Texinfo: writeTexinfo :: WriterOptions -> Pandoc -> String
+ Text.Pandoc.Writers.Texinfo: writeTexinfo :: PandocMonad m => WriterOptions -> Pandoc -> m Text
- Text.Pandoc.Writers.Textile: writeTextile :: WriterOptions -> Pandoc -> String
+ Text.Pandoc.Writers.Textile: writeTextile :: PandocMonad m => WriterOptions -> Pandoc -> m Text
- Text.Pandoc.Writers.ZimWiki: writeZimWiki :: WriterOptions -> Pandoc -> String
+ Text.Pandoc.Writers.ZimWiki: writeZimWiki :: PandocMonad m => WriterOptions -> Pandoc -> m Text
- Text.Pandoc.XML: toEntities :: String -> String
+ Text.Pandoc.XML: toEntities :: Text -> Text

This diff is very large; some files are shown as “too large to diff”. Download the raw patch for the complete diff.

Files

+ AUTHORS.md view
@@ -0,0 +1,195 @@+# Contributors++- Arata Mizuki+- Aaron Wolen+- Albert Krewinkel+- Alex Ivkin+- Alex Vong+- Alexander Kondratskiy+- Alexander Krotov+- Alexander Sulfrian+- Alexander V Vershilov+- Alfred Wechselberger+- Andreas Lööw+- Andrew Dunning+- Antoine Latter+- Arata Mizuki+- Arlo O'Keeffe+- Artyom Kazak+- Agustín Martín Barbero+- B. Scott Michel+- Ben Firshman+- Ben Gamari+- Beni Cherniavsky-Paskin+- Benoit Schweblin+- Bjorn Buckwalter+- Bradley Kuhn+- Brent Yorgey+- Bryan O'Sullivan+- Caleb McDaniel+- Calvin Beck+- Carlos Sosa+- Chris Black+- Christian Conkle+- Christoffer Ackelman+- Christoffer Sawicki+- Clare Macrae+- Clint Adams+- Conal Elliott+- Craig S. Bosma+- Daniel Bergey+- Daniel T. Staal+- Daniele D'Orazio+- David A Roberts+- David Lazar+- David Röthlisberger+- Denis Laxalde+- Douglas Calvert+- Emanuel Evans+- Emily Eisenberg+- Eric Kow+- Eric Seidel+- Felix Yan+- Florian Eitel+- François Gannaz+- Freiric Barral+- Freirich Raabe+- Frerich Raabe+- Fyodor Sheremetyev+- Gabor Pali+- Gavin Beatty+- Gottfried Haider+- Greg Maslov+- Greg Rundlett+- Grégory Bataille+- Gwern Branwen+- Hans-Peter Deifel+- Henrik Tramberend+- Henry de Valence+- Hubert Plociniczak+- Ilya V. Portnov+- Ivo Clarysse+- J. Lewis Muir+- Jaime Marquínez Ferrándiz+- Jakob Voß+- James Aspnes+- Jamie F. Olson+- Jan Larres+- Jan Schulz+- Jason Ronallo+- Jeff Arnold+- Jeff Runningen+- Jens Getreu+- Jens Petersen+- Jesse Rosenthal+- Joe Hillenbrand+- John MacFarlane+- John Muccigrosso+- John Luke Bentley+- Jonas Smedegaard+- Jonathan Daugherty+- Jose Luis Duran+- Josef Svenningsson+- Julien Cretel+- Juliusz Gonera+- Justin Bogner+- Jérémy Bobbio+- Keiichiro Shikano+- Kelsey Hightower+- Kolen Cheung+- Konstantin Zudov+- Kristof Bastiaensen+- Herwig Stuetz+- Lars-Dominik Braun+- Luke Plant+- Marc Schreiber+- Mark Szepieniec+- Mark Wright+- Martin Linn+- Masayoshi Takahashi+- Matej Kollar+- Mathias Schenner+- Mathieu Duponchelle+- Matthew Eddey+- Matthew Pickering+- Matthias C. M. Troffaes+- Mauro Bieg+- Max Bolingbroke+- Max Rydahl Andersen+- Merijn Verstraaten+- Michael Beaumont+- Michael Chladek+- Michael Snoyman+- Michael Thompson+- MinRK+- Morton Fox+- Nathan Gass+- Neil Mayhew+- Nick Bart+- Nicolas Kaiser+- Nikolay Yakimov+- Oliver Matthews+- Ophir Lifshitz+- Or Neeman+- Pablo Rodríguez+- Paul Rivier+- Paulo Tanimoto+- Peter Wang+- Philippe Ombredanne+- Phillip Alday+- Prayag Verma+- Puneeth Chaganti+- Ralf Stephan+- Raniere Silva+- Recai Oktaş+- Roland Hieber+- RyanGlScott+- Sascha Wilde+- Scott Morrison+- Sergei Trofimovich+- Sergey Astanin+- Shahbaz Youssefi+- Shaun Attfield+- Sidarth Kapur+- Sidharth Kapur+- Simon Hengel+- Stefan Dresselhaus+- Sumit Sahrawat+- Thenaesh Elango+- Thomas Hodgson+- Thomas Weißschuh+- Tim Lin+- Timm Albers+- Timothy Humphries+- Tiziano Müller+- Todd Sifleet+- Tom Leese+- Uli Köhler+- Václav Zeman+- Viktor Kronvall+- Vincent+- Václav Haisman+- Václav Zeman+- Wandmalfarbe+- Waldir Pimenta+- Wikiwide+- Xavier Olive+- Yuchen Pei+- bucklereed+- bumper314+- csforste+- d-dorazio+- hftf+- iandol+- infinity0x+- lwolfsonkin+- nkalvi+- qerub+- robabla+- roblabla+- rodja.trappe+- rski+- shreevatsa.public+- takahashim+- tgkokk+- thsutton
CONTRIBUTING.md view
@@ -1,18 +1,24 @@ Contributing to pandoc ====================== +Have a question?+----------------++Ask on [pandoc-discuss].++ Found a bug? ------------  Bug reports are welcome!  Please report all bugs on pandoc's github [issue tracker]. -Before you submit a bug report, search the (open *and* closed) issues to make-sure the issue hasn't come up before. Also, check the [User's Guide] and [FAQs]-for anything relevant.+Before you submit a bug report, search the [open issues] *and* [closed issues]+to make sure the issue hasn't come up before. Also, check the [User's Guide] and+[FAQs] for anything relevant. -Make sure you can reproduce the bug with the latest released version of pandoc-(or, even better, the development version).+Make sure you can reproduce the bug with the [latest released version] of pandoc+(or, even better, the [development version]).  Your report should give detailed, *reproducible* instructions, including @@ -31,25 +37,25 @@ A less than perfect conversion does not necessarily mean there's a bug in pandoc.  Quoting from the MANUAL: -> Because Pandoc's intermediate representation of a document is less+> Because pandoc's intermediate representation of a document is less > expressive than many of the formats it converts between, one should > not expect perfect conversions between every format and every other. > Pandoc attempts to preserve the structural elements of a document, but > not formatting details such as margin size.  And some document elements,-> such as complex tables, may not fit into Pandoc's simple document-> model.  While conversions from Pandoc's Markdown to all formats aspire-> to be perfect, conversions from formats more expressive than Pandoc's+> such as complex tables, may not fit into pandoc's simple document+> model.  While conversions from pandoc's Markdown to all formats aspire+> to be perfect, conversions from formats more expressive than pandoc's > Markdown can be expected to be lossy. -For example, both docx and odt can represent margin size, but because-pandoc's internal document model does not contain a representation of+For example, both `docx` and `odt` formats can represent margin size, but+because pandoc's internal document model does not contain a representation of margin size, this information will be lost on converting from docx-to odt.  (You can, however, customize margin size using `--reference-odt`.)+to `odt`.  (You can, however, customize margin size using `--reference-doc`.)  So before submitting a bug report, consider whether it might be-"out of scope."  If it concerns a feature of documents that isn't+"out of scope." If it concerns a feature of documents that isn't representable in pandoc's Markdown, then it very likely is.-(If in doubt, you can always ask on pandoc-discuss.)+(If in doubt, you can always ask on [pandoc-discuss].)  Fixing bugs from the issue tracker ----------------------------------@@ -57,7 +63,7 @@ Almost all the bugs on the issue tracker have one or more associated tags. These are used to indicate the *complexity* and *nature* of a bug. There is not yet a way to indicate priority. An up to date-summary of issues can be found [here](https://github.com/jgm/pandoc/labels).+summary of issues can be found on [GitHub labels].  * [beginner-friendly] — The perfect starting point for new contributors. The   issue is generic and can be resolved without deep knowledge of the code@@ -71,7 +77,7 @@   knowledge of the code base. * [new:reader] — A request to add a new input format. * [new:writer] — A request to add a new output format.-* [docs] — A discrepency,  or ambiguity in the documentation.+* [docs] — A discrepancy,  or ambiguity in the documentation. * [status:in-progress] — Someone is actively working on or planning to work on the   ticket. * [status:more-discussion-needed] — It is unclear what the correct approach@@ -86,8 +92,8 @@ Have an idea for a new feature? ------------------------------- -First, search [pandoc-discuss] and the issue tracker (both open and closed-issues) to make sure that the idea has not been discussed before.+First, search [pandoc-discuss] and the issue tracker (both [open issues] *and*+[closed issues]) to make sure that the idea has not been discussed before.  Explain the rationale for the feature you're requesting.  Why would this feature be useful?  Consider also any possible drawbacks, including backwards@@ -130,7 +136,7 @@     below under [Tests](#tests).)  If you are adding a new writer or reader,     you must include tests. -7.  If you are adding a new feature, include updates to MANUAL.txt.+7.  If you are adding a new feature, include updates to `MANUAL.txt`.  8.  All code must be released under the general license governing pandoc     (GPL v2).@@ -140,7 +146,7 @@  10. We aim for compatibility with ghc versions from 7.8.3 to the     latest release.  All pull requests and commits are tested-    automatically on travis-ci.org, using GHC versions in the+    automatically on <travis-ci.org>, using GHC versions in the     `Tested-With` stanza of `pandoc.cabal`.  We currently relax     the "`-Wall` clean" requirement for GHC 7.10.x, because     there are so many warnings relating to the addition of type@@ -161,7 +167,7 @@     stack setup     stack test -The test program is `tests/test-pandoc.hs`.+The test program is `test/test-pandoc.hs`.  Benchmarks ----------@@ -176,6 +182,11 @@      stack bench +You can also build pandoc with the `weigh-pandoc` flag and+run `weigh-pandoc` to get some statistics on memory usage.+(Eventually this should be incorporated into the benchmark+suite.)+ Using the REPL -------------- @@ -186,43 +197,60 @@ We recommend using the following `.ghci` file (which can be placed in the source directory): -```-:set -fobject-code-:set -XTypeSynonymInstances-:set -XScopedTypeVariables-:set -XOverloadedStrings-```+	:set -fobject-code+	:set -XTypeSynonymInstances+	:set -XScopedTypeVariables+	:set -XOverloadedStrings -The code---------+Profiling+--------- -Pandoc has a publicly accessible git repository on-github: <http://github.com/jgm/pandoc>.  To get a local copy of the source:+To use the GHC profiler with cabal: -    git clone git://github.com/jgm/pandoc.git+    cabal clean+    cabal install --enable-library-profiling --enable-executable-profiling+    pandoc +RTS -p -RTS [file]...+    less pandoc.prof -Note:  after cloning the repository (and in the future after pulling from it),-you should do+With stack: -    git submodule update --init+    stack clean+    stack install --profile+    pandoc +RTS -p -RTS [file]...+    less pandoc.prof -to pull in changes to the templates (`data/templates/`).  You can automate this-by creating a file `.git/hooks/post-merge` with the contents:+Templates+--------- -    #!/bin/sh-    git submodule update --init+The default templates live in `data/templates`, which is a git+subtree linked to <https://github.com/jgm/pandoc-templates.git>.+The purpose of maintaining a separate repository is to allow+people to maintain variant templates as a fork. -and making it executable:+You can modify the templates and submit patches without worrying+much about this: when these patches are merged, we will+push them to the main templates repository by doing -    chmod +x .git/hooks/post-merge+    git subtree push --prefix=data/templates templates master +where `templates` is a remote pointing to the templates+repository.++The code+--------++Pandoc has a publicly accessible git repository on+github: <http://github.com/jgm/pandoc>.  To get a local copy of the source:++    git clone https://github.com/jgm/pandoc.git+ The source for the main pandoc program is `pandoc.hs`.  The source for the pandoc library is in `src/`, the source for the tests is in-`tests/`, and the source for the benchmarks is in `benchmark/`.+`test/`, and the source for the benchmarks is in `benchmark/`.  The modules `Text.Pandoc.Definition`, `Text.Pandoc.Builder`, and `Text.Pandoc.Generic` are in a separate library `pandoc-types`.  The code can-be found in a <http://github.com/jgm/pandoc-types>.+be found in <http://github.com/jgm/pandoc-types>.  To build pandoc, you will need a working installation of the [Haskell platform].@@ -261,7 +289,7 @@     the needs of pandoc.   - `Text.Pandoc.SelfContained` contains functions for making an HTML     file "self-contained," by importing remotely linked images, CSS,-    and javascript and turning them into `data:` URLs.+    and JavaScript and turning them into `data:` URLs.   - `Text.Pandoc.Shared` is a grab-bag of shared utility functions.   - `Text.Pandoc.Writers.Shared` contains utilities used in writers only.   - `Text.Pandoc.Slides` contains functions for splitting a markdown document@@ -274,6 +302,10 @@   - `Text.Pandoc.UUID` contains functions for generating UUIDs.   - `Text.Pandoc.XML` contains functions for formatting XML. +[open issues]: https://github.com/jgm/pandoc/issues+[closed issues]: https://github.com/jgm/pandoc/issues?q=is%3Aissue+is%3Aclosed+[latest released version]: https://github.com/jgm/pandoc/releases/latest+[development version]: https://github.com/pandoc-extras/pandoc-nightly/releases/latest [pandoc-discuss]: http://groups.google.com/group/pandoc-discuss [issue tracker]: https://github.com/jgm/pandoc/issues [User's Guide]: http://pandoc.org/MANUAL.html@@ -281,6 +313,7 @@ [EditorConfig]: http://editorconfig.org/ [Haskell platform]: http://www.haskell.org/platform/ [hsb2hs]: http://hackage.haskell.org/package/hsb2hs+[GitHub labels]: https://github.com/jgm/pandoc/labels [beginner-friendly]: https://github.com/jgm/pandoc/labels/beginner-friendly [enhancement]: https://github.com/jgm/pandoc/labels/enhancement [bug]: https://github.com/jgm/pandoc/labels/bug
@@ -1,7 +1,8 @@ Pandoc Copyright (C) 2006-2017 John MacFarlane <jgm at berkeley dot edu> -This code is released under the [GPL], version 2 or later:+With the exceptions noted below, this code is released under the [GPL],+version 2 or later:     This program is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by@@ -27,38 +28,100 @@  [Pandoc home page]: http://pandoc.org -Pandoc includes some code from other authors.  The copyright and license-statements for these sources are included below.  All are GPL-compatible-licenses.+Pandoc includes some code with different copyrights, or subject to different+licenses.  The copyright and license statements for these sources are included+below.  All are GPL-compatible licenses.  ----------------------------------------------------------------------+The modules in the `pandoc-types` repository (Text.Pandoc.Definition,+Text.Pandoc.Builder, Text.Pandoc.Generics, Text.Pandoc.JSON,+Text.Pandoc.Walk) are licensed under the BSD 3-clause license:++Copyright (c) 2006-2017, John MacFarlane++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of John MacFarlane nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.++----------------------------------------------------------------------+Pandoc's templates (in `data/templates`) are dual-licensed GPL (v2 or+higher, same as pandoc) and the BSD 3-clause license.++Copyright (c) 2014--2017, John MacFarlane++----------------------------------------------------------------------+src/Text/Pandoc/Writers/Muse.hs+Copyright (C) 2017 Alexander Krotov++Released under the GNU General Public License version 2 or later.++---------------------------------------------------------------------- src/Text/Pandoc/Writers/Texinfo.hs-Copyright (C) 2008-2015 John MacFarlane and Peter Wang+Copyright (C) 2008-2017 John MacFarlane and Peter Wang  Released under the GNU General Public License version 2 or later.  ---------------------------------------------------------------------- src/Text/Pandoc/Writers/OpenDocument.hs-Copyright (C) 2008-2015 Andrea Rossato and John MacFarlane+Copyright (C) 2008-2017 Andrea Rossato and John MacFarlane  Released under the GNU General Public License version 2 or later.  ---------------------------------------------------------------------- src/Text/Pandoc/Writers/Org.hs-Copyright (C) 2010-2015 Puneeth Chaganti and John MacFarlane+Copyright (C) 2010-2017 Puneeth Chaganti, John MacFarlane, and+                        Albert Krewinkel  Released under the GNU General Public License version 2 or later.  ----------------------------------------------------------------------+src/Text/Pandoc/Writers/ZimWiki.hs+Copyright (C) 2017 Alex Ivkin++Released under the GNU General Public License version 2 or later.++----------------------------------------------------------------------+src/Text/Pandoc/Readers/Docx.hs+src/Text/Pandoc/Readers/Docx/*+Copyright (C) 2014-2017 Jesse Rosenthal++Released under the GNU General Public License version 2 or later.++---------------------------------------------------------------------- src/Text/Pandoc/Readers/Textile.hs-Copyright (C) 2010-2015 Paul Rivier and John MacFarlane+Copyright (C) 2010-2017 Paul Rivier and John MacFarlane  Released under the GNU General Public License version 2 or later.  ---------------------------------------------------------------------- src/Text/Pandoc/Readers/Org.hs-tests/Tests/Readers/Org.hs-Copyright (C) 2014-2015 Albert Krewinkel+test/Tests/Readers/Org.hs+Copyright (C) 2014-2017 Albert Krewinkel  Released under the GNU General Public License version 2 or later. @@ -77,7 +140,13 @@ Released under the GNU General Public License version 2 or later.  -------------------------------------------------------------------------The dzslides template contains javascript and CSS from Paul Rouget's+data/pandoc.lua+Copyright (C) 2017 Albert Krewinkel++Released under the GNU General Public License version 2 or later.++----------------------------------------------------------------------+The dzslides template contains JavaScript and CSS from Paul Rouget's dzslides template. http://github.com/paulrouget/dzslides @@ -106,3 +175,12 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.++------------------------------------------------------------------------+The template pandoc.jats is Copyright 2013--15 Martin Fenner,+released under GPL version 2 or later.++The file data/jats.csl is derived from a csl file by Martin Fenner,+revised by Martin Paul Eve and then John MacFarlane.+"This work is licensed under a Creative Commons Attribution-ShareAlike 3.0+License. Originally by Martin Fenner."
INSTALL.md view
@@ -19,7 +19,7 @@         copy /y "%TEMP%\pandoc\pandoc-citeproc.exe" C:\Utils\Console\         rmdir /s /q "%TEMP%\pandoc\" -## Mac OS X+## macOS    - There is a package installer at pandoc's [download page].     If you later want to uninstall the package, you can do so@@ -27,12 +27,12 @@     and running it with `perl uninstall-pandoc.pl`.    - It is possible to extract the pandoc and pandoc-citeproc-    executables from the osx pkg file, if you'd rather not run+    executables from the macOS pkg file, if you'd rather not run     the installer.  To do this (for the version 1.19.1 package):          mkdir pandoc-extract         cd pandoc-extract-        xar -x ../pandoc-1.19.1-osx.pkg+        xar -x ../pandoc-2.0-macOS.pkg         cat pandoc.pkg/Payload | gunzip -dc | cpio -i         # executables are now in ./usr/bin/, man pages in ./usr/share/man @@ -55,21 +55,31 @@     Note, however, that versions in the repositories are often     old. -  - For 64-bit [Debian] and [Ubuntu], we provide a debian package-    on the [download page].+  - We provide a binary package for amd64 architecture on+    the download page.  This provides both pandoc and+    pandoc-citeproc. The executables are statically linked and+    have no dynamic dependencies.  Both a tarball and a deb+    installer are provided.          sudo dpkg -i $DEB      where `$DEB` is the path to the downloaded deb, will     install the `pandoc` and `pandoc-citeproc` executables-    and man pages.  If you use an RPM-based distro, you may be-    able to install this deb using `alien`, or try+    and man pages. +    Note:  because it is statically linked, the pandoc+    binary from this package cannot use lua filters that+    require external lua modules written in C.++  - If you use an RPM-based distro, you may be+    able to install the deb from our download page+    using `alien`. Or try+         ar p $DEB data.tar.gz | sudo tar xvz --strip-components 2 -C /usr/local    - If you'd rather install pandoc in your home directory, say-    in `$HOME/.local`, then you can extract the files manually-    from the deb:+    in `$HOME/.local`, then you can unzip the tarball or+    extract the files manually from the deb:          ar p $DEB data.tar.gz | tar xvz --strip-components 2 -C $HOME/.local/ @@ -110,7 +120,6 @@      git clone https://github.com/jgm/pandoc     cd pandoc-    git submodule update --init   # to fetch the templates  Note:  there may be times when the development code is broken or depends on other libraries which must be installed@@ -157,13 +166,6 @@          cabal install -    Note: If you obtained the source from the git repository (rather-    than a release tarball), you'll need to do--        git submodule update --init--    to fetch the contents of `data/templates` before `cabal install`.- 4.  Make sure the `$CABALDIR/bin` directory is in your path.  You should     now be able to run `pandoc`: @@ -186,7 +188,7 @@      Note that this requires the `text-icu` library, which in turn     depends on the C library `icu4c`.  Installation directions-    vary by platform.  Here is how it might work on OSX with homebrew:+    vary by platform.  Here is how it might work on macOS with homebrew:          brew install icu4c         cabal install --extra-lib-dirs=/usr/local/Cellar/icu4c/51.1/lib \@@ -232,9 +234,6 @@      - `embed_data_files`: embed all data files into the binary (default no).       This is helpful if you want to create a relocatable binary.-      Note:  if this option is selected, you need to install the-      `hsb2hs` preprocessor: `cabal install hsb2hs` (version 0.3.1 or-      higher is required).      - `https`:  enable support for downloading resources over https       (using the `http-client` and `http-client-tls` libraries).@@ -281,16 +280,24 @@ test`.  To run particular tests (pattern-matching on their names), use-the `-t` option:+the `-p` option: -    cabal test --test-options='-t markdown'+    cabal test --test-options='-p markdown' +Or with stack:++    stack test --test-arguments='-p markdown'++It is often helpful to add `-j4` (run tests in parallel)+and `--hide-successes` (don't clutter output with successes)+to the test arguments as well.+ If you add a new feature to pandoc, please add tests as well, following the pattern of the existing tests. The test suite code is in-`tests/test-pandoc.hs`. If you are adding a new reader or writer, it is-probably easiest to add some data files to the `tests` directory, and-modify `tests/Tests/Old.hs`. Otherwise, it is better to modify the module-under the `tests/Tests` hierarchy corresponding to the pandoc module you+`test/test-pandoc.hs`. If you are adding a new reader or writer, it is+probably easiest to add some data files to the `test` directory, and+modify `test/Tests/Old.hs`. Otherwise, it is better to modify the module+under the `test/Tests` hierarchy corresponding to the pandoc module you are changing.  ### Running benchmarks@@ -312,31 +319,7 @@      cabal bench --benchmark-options='markdown' -### Building the whole pandoc ecosystem -Sometimes pandoc's development code depends on unreleased versions-of dependent libraries.  You'll need to build these as well.  A-maximal build method would be--    mkdir pandoc-build-    cd pandoc-build-    git clone https://github.com/jgm/pandoc-types-    git clone https://github.com/jgm/texmath-    git clone https://github.com/jgm/pandoc-citeproc-    git clone https://github.com/jgm/pandoc-    git clone https://github.com/jgm/cmark-hs-    git clone https://github.com/jgm/zip-archive-    cd pandoc-    git submodule update --init-    stack install --test --install-ghc --stack-yaml stack.full.yaml--To pull in the latest changes, after you've done this and there have been-changes in the repositories:  Visit each repository in pandoc-build-(pandoc-types, texmath, pandoc-citeproc, pandoc, zip-archive, cmark-hs) and do-`git pull`.  In the pandoc repo, also do `git submodule update` and `stack-install --test --stack-yaml stack.full.yaml`.-- [Arch]: https://www.archlinux.org/packages/community/x86_64/pandoc/ [Cabal User's Guide]: http://www.haskell.org/cabal/release/latest/doc/users-guide/builders.html#setup-configure-paths [Debian]: http://packages.debian.org/lenny/pandoc@@ -358,4 +341,4 @@ [source tarball]: http://hackage.haskell.org/package/pandoc [stack]: http://docs.haskellstack.org/en/stable/install_and_upgrade.html [cabal-install]: http://hackage.haskell.org/trac/hackage/wiki/CabalInstall-[uninstaller]: https://raw.githubusercontent.com/jgm/pandoc/master/osx/uninstall-pandoc.pl+[uninstaller]: https://raw.githubusercontent.com/jgm/pandoc/master/macos/uninstall-pandoc.pl
MANUAL.txt view
@@ -1,4217 +1,4334 @@ % Pandoc User's Guide % John MacFarlane-% January 29, 2017--Synopsis-========--`pandoc` [*options*] [*input-file*]...--Description-===========--Pandoc is a [Haskell] library for converting from one markup format to-another, and a command-line tool that uses this library. It can read-[Markdown], [CommonMark], [PHP Markdown Extra], [GitHub-Flavored Markdown],-[MultiMarkdown], and (subsets of) [Textile], [reStructuredText], [HTML],-[LaTeX], [MediaWiki markup], [TWiki markup], [Haddock markup], [OPML], [Emacs-Org mode], [DocBook], [txt2tags], [EPUB], [ODT] and [Word docx]; and it can-write plain text, [Markdown], [CommonMark], [PHP Markdown Extra],-[GitHub-Flavored Markdown], [MultiMarkdown], [reStructuredText], [XHTML],-[HTML5], [LaTeX] \(including [`beamer`] slide shows\), [ConTeXt], [RTF], [OPML],-[DocBook], [OpenDocument], [ODT], [Word docx], [GNU Texinfo], [MediaWiki-markup], [DokuWiki markup], [ZimWiki markup], [Haddock markup],-[EPUB] \(v2 or v3\), [FictionBook2], [Textile], [groff man] pages,-[Emacs Org mode], [AsciiDoc], [InDesign ICML], [TEI Simple], and [Slidy],-[Slideous], [DZSlides], [reveal.js] or [S5] HTML slide shows. It can also-produce [PDF] output on systems where LaTeX, ConTeXt, or `wkhtmltopdf` is-installed.--Pandoc's enhanced version of Markdown includes syntax for [footnotes],-[tables], flexible [ordered lists], [definition lists], [fenced code blocks],-[superscripts and subscripts], [strikeout], [metadata blocks], automatic tables of-contents, embedded LaTeX [math], [citations], and [Markdown inside HTML block-elements][Extension: `markdown_in_html_blocks`]. (These enhancements, described-further under [Pandoc's Markdown], can be disabled using the-`markdown_strict` input or output format.)--In contrast to most existing tools for converting Markdown to HTML, which-use regex substitutions, pandoc has a modular design: it consists of a-set of readers, which parse text in a given format and produce a native-representation of the document, and a set of writers, which convert-this native representation into a target format. Thus, adding an input-or output format requires only adding a reader or writer.--Because pandoc's intermediate representation of a document is less-expressive than many of the formats it converts between, one should-not expect perfect conversions between every format and every other.-Pandoc attempts to preserve the structural elements of a document, but-not formatting details such as margin size.  And some document elements,-such as complex tables, may not fit into pandoc's simple document-model.  While conversions from pandoc's Markdown to all formats aspire-to be perfect, conversions from formats more expressive than pandoc's-Markdown can be expected to be lossy.--[Markdown]: http://daringfireball.net/projects/markdown/-[CommonMark]: http://commonmark.org-[PHP Markdown Extra]: https://michelf.ca/projects/php-markdown/extra/-[GitHub-Flavored Markdown]: https://help.github.com/articles/github-flavored-markdown/-[MultiMarkdown]: http://fletcherpenney.net/multimarkdown/-[reStructuredText]: http://docutils.sourceforge.net/docs/ref/rst/introduction.html-[S5]: http://meyerweb.com/eric/tools/s5/-[Slidy]: http://www.w3.org/Talks/Tools/Slidy/-[Slideous]: http://goessner.net/articles/slideous/-[HTML]: http://www.w3.org/html/-[HTML5]: http://www.w3.org/TR/html5/-[XHTML]: http://www.w3.org/TR/xhtml1/-[LaTeX]: http://latex-project.org-[`beamer`]: https://ctan.org/pkg/beamer-[Beamer User's Guide]: http://ctan.math.utah.edu/ctan/tex-archive/macros/latex/contrib/beamer/doc/beameruserguide.pdf-[ConTeXt]: http://www.contextgarden.net/-[RTF]: http://en.wikipedia.org/wiki/Rich_Text_Format-[DocBook]: http://docbook.org-[txt2tags]: http://txt2tags.org-[EPUB]: http://idpf.org/epub-[OPML]: http://dev.opml.org/spec2.html-[OpenDocument]: http://opendocument.xml.org-[ODT]: http://en.wikipedia.org/wiki/OpenDocument-[Textile]: http://redcloth.org/textile-[MediaWiki markup]: https://www.mediawiki.org/wiki/Help:Formatting-[DokuWiki markup]: https://www.dokuwiki.org/dokuwiki-[ZimWiki markup]: http://zim-wiki.org/manual/Help/Wiki_Syntax.html-[TWiki markup]: http://twiki.org/cgi-bin/view/TWiki/TextFormattingRules-[Haddock markup]: https://www.haskell.org/haddock/doc/html/ch03s08.html-[groff man]: http://man7.org/linux/man-pages/man7/groff_man.7.html-[Haskell]: https://www.haskell.org-[GNU Texinfo]: http://www.gnu.org/software/texinfo/-[Emacs Org mode]: http://orgmode.org-[AsciiDoc]: http://www.methods.co.nz/asciidoc/-[DZSlides]: http://paulrouget.com/dzslides/-[Word docx]: https://en.wikipedia.org/wiki/Office_Open_XML-[PDF]: https://www.adobe.com/pdf/-[reveal.js]: http://lab.hakim.se/reveal-js/-[FictionBook2]: http://www.fictionbook.org/index.php/Eng:XML_Schema_Fictionbook_2.1-[InDesign ICML]: https://www.adobe.com/content/dam/Adobe/en/devnet/indesign/cs55-docs/IDML/idml-specification.pdf-[TEI Simple]: https://github.com/TEIC/TEI-Simple--Using `pandoc`-----------------If no *input-file* is specified, input is read from *stdin*.-Otherwise, the *input-files* are concatenated (with a blank-line between each) and used as input.  Output goes to *stdout* by-default (though output to *stdout* is disabled for the `odt`, `docx`,-`epub`, and `epub3` output formats).  For output to a file, use the-`-o` option:--    pandoc -o output.html input.txt--By default, pandoc produces a document fragment, not a standalone-document with a proper header and footer.  To produce a standalone-document, use the `-s` or `--standalone` flag:--    pandoc -s -o output.html input.txt--For more information on how standalone documents are produced, see-[Templates], below.--Instead of a file, an absolute URI may be given.  In this case-pandoc will fetch the content using HTTP:--    pandoc -f html -t markdown http://www.fsf.org--If multiple input files are given, `pandoc` will concatenate them all (with-blank lines between them) before parsing. This feature is disabled for- binary input formats such as `EPUB`, `odt`, and `docx`.--The format of the input and output can be specified explicitly using-command-line options.  The input format can be specified using the-`-r/--read` or `-f/--from` options, the output format using the-`-w/--write` or `-t/--to` options.  Thus, to convert `hello.txt` from-Markdown to LaTeX, you could type:--    pandoc -f markdown -t latex hello.txt--To convert `hello.html` from HTML to Markdown:--    pandoc -f html -t markdown hello.html--Supported output formats are listed below under the `-t/--to` option.-Supported input formats are listed below under the `-f/--from` option. Note-that the `rst`, `textile`, `latex`, and `html` readers are not complete;-there are some constructs that they do not parse.--If the input or output format is not specified explicitly, `pandoc`-will attempt to guess it from the extensions of-the input and output filenames.  Thus, for example,--    pandoc -o hello.tex hello.txt--will convert `hello.txt` from Markdown to LaTeX.  If no output file-is specified (so that output goes to *stdout*), or if the output file's-extension is unknown, the output format will default to HTML.-If no input file is specified (so that input comes from *stdin*), or-if the input files' extensions are unknown, the input format will-be assumed to be Markdown unless explicitly specified.--Pandoc uses the UTF-8 character encoding for both input and output.-If your local character encoding is not UTF-8, you-should pipe input and output through [`iconv`]:--    iconv -t utf-8 input.txt | pandoc | iconv -f utf-8--Note that in some output formats (such as HTML, LaTeX, ConTeXt,-RTF, OPML, DocBook, and Texinfo), information about-the character encoding is included in the document header, which-will only be included if you use the `-s/--standalone` option.--[`iconv`]: http://www.gnu.org/software/libiconv/--Creating a PDF-----------------To produce a PDF, specify an output file with a `.pdf` extension.-By default, pandoc will use LaTeX to convert it to PDF:--    pandoc test.txt -o test.pdf--Production of a PDF requires that a LaTeX engine be installed (see-`--latex-engine`, below), and assumes that the following LaTeX packages-are available: [`amsfonts`], [`amsmath`], [`lm`],-[`ifxetex`], [`ifluatex`], [`eurosym`], [`listings`] (if the-`--listings` option is used), [`fancyvrb`], [`longtable`],-[`booktabs`], [`graphicx`] and [`grffile`] (if the-document contains images), [`hyperref`], [`ulem`],-[`geometry`] (with the `geometry` variable set), [`setspace`] (with-`linestretch`), and [`babel`] (with `lang`). The use of `xelatex` or-`lualatex` as the LaTeX engine requires [`fontspec`]; `xelatex` uses-[`mathspec`], [`polyglossia`] (with `lang`), [`xecjk`], and-[`bidi`] (with the `dir` variable set). The [`upquote`] and-[`microtype`] packages are used if available, and [`csquotes`] will-be used for [smart punctuation] if added to the template or included in-any header file. The [`natbib`], [`biblatex`], [`bibtex`], and [`biber`]-packages can optionally be used for [citation rendering]. These are-included with all recent versions of [TeX Live].--Alternatively, pandoc can use ConTeXt or `wkhtmltopdf` to create a PDF.-To do this, specify an output file with a `.pdf` extension,-as before, but add `-t context` or `-t html5` to the command line.--PDF output can be controlled using [variables for LaTeX] (if-LaTeX is used) and [variables for ConTeXt] (if ConTeXt is used).-If `wkhtmltopdf` is used, then the variables `margin-left`,-`margin-right`, `margin-top`, `margin-bottom`, and `papersize`-will affect the output, as will `--css`.--[`amsfonts`]: https://ctan.org/pkg/amsfonts-[`amsmath`]: https://ctan.org/pkg/amsmath-[`lm`]: https://ctan.org/pkg/lm-[`ifxetex`]: https://ctan.org/pkg/ifxetex-[`ifluatex`]: https://ctan.org/pkg/ifluatex-[`eurosym`]: https://ctan.org/pkg/eurosym-[`listings`]: https://ctan.org/pkg/listings-[`fancyvrb`]: https://ctan.org/pkg/fancyvrb-[`longtable`]: https://ctan.org/pkg/longtable-[`booktabs`]: https://ctan.org/pkg/booktabs-[`graphicx`]: https://ctan.org/pkg/graphicx-[`grffile`]: https://ctan.org/pkg/grffile-[`geometry`]: https://ctan.org/pkg/geometry-[`setspace`]: https://ctan.org/pkg/setspace-[`xecjk`]: https://ctan.org/pkg/xecjk-[`hyperref`]: https://ctan.org/pkg/hyperref-[`ulem`]: https://ctan.org/pkg/ulem-[`babel`]: https://ctan.org/pkg/babel-[`bidi`]: https://ctan.org/pkg/bidi-[`mathspec`]: https://ctan.org/pkg/mathspec-[`polyglossia`]: https://ctan.org/pkg/polyglossia-[`fontspec`]: https://ctan.org/pkg/fontspec-[`upquote`]: https://ctan.org/pkg/upquote-[`microtype`]: https://ctan.org/pkg/microtype-[`csquotes`]: https://ctan.org/pkg/csquotes-[`natbib`]: https://ctan.org/pkg/natbib-[`biblatex`]: https://ctan.org/pkg/biblatex-[`bibtex`]: https://ctan.org/pkg/bibtex-[`biber`]: https://ctan.org/pkg/biber-[TeX Live]: http://www.tug.org/texlive/--Options-=======--General options------------------`-f` *FORMAT*, `-r` *FORMAT*, `--from=`*FORMAT*, `--read=`*FORMAT*--:   Specify input format.  *FORMAT* can be `native` (native Haskell),-    `json` (JSON version of native AST), `markdown` (pandoc's-    extended Markdown), `markdown_strict` (original unextended-    Markdown), `markdown_phpextra` (PHP Markdown Extra), `markdown_github`-    (GitHub-Flavored Markdown), `markdown_mmd` (MultiMarkdown),-    `commonmark` (CommonMark Markdown), `textile` (Textile), `rst`-    (reStructuredText), `html` (HTML), `docbook` (DocBook), `t2t`-    (txt2tags), `docx` (docx), `odt` (ODT), `epub` (EPUB), `opml` (OPML),-    `org` (Emacs Org mode), `mediawiki` (MediaWiki markup), `twiki` (TWiki-    markup), `haddock` (Haddock markup), or `latex` (LaTeX).  If-    `+lhs` is appended to `markdown`, `rst`, `latex`, or `html`, the-    input will be treated as literate Haskell source: see [Literate-    Haskell support], below. Markdown-    syntax extensions can be individually enabled or disabled by-    appending `+EXTENSION` or `-EXTENSION` to the format name. So, for-    example, `markdown_strict+footnotes+definition_lists` is strict-    Markdown with footnotes and definition lists enabled, and-    `markdown-pipe_tables+hard_line_breaks` is pandoc's Markdown-    without pipe tables and with hard line breaks. See [Pandoc's-    Markdown], below, for a list of extensions and-    their names.  See `--list-input-formats` and `--list-extensions`,-    below.--`-t` *FORMAT*, `-w` *FORMAT*, `--to=`*FORMAT*, `--write=`*FORMAT*--:   Specify output format.  *FORMAT* can be `native` (native Haskell),-    `json` (JSON version of native AST), `plain` (plain text),-    `markdown` (pandoc's extended Markdown), `markdown_strict`-    (original unextended Markdown), `markdown_phpextra` (PHP Markdown-    Extra), `markdown_github` (GitHub-Flavored Markdown), `markdown_mmd`-    (MultiMarkdown), `commonmark` (CommonMark Markdown), `rst`-    (reStructuredText), `html` (XHTML), `html5` (HTML5), `latex`-    (LaTeX), `beamer` (LaTeX beamer slide show), `context` (ConTeXt),-    `man` (groff man), `mediawiki` (MediaWiki markup),-    `dokuwiki` (DokuWiki markup), `zimwiki` (ZimWiki markup),-    `textile` (Textile), `org` (Emacs Org mode),-    `texinfo` (GNU Texinfo), `opml` (OPML), `docbook` (DocBook 4),-    `docbook5` (DocBook 5), `opendocument` (OpenDocument), `odt`-    (OpenOffice text document), `docx` (Word docx), `haddock`-    (Haddock markup), `rtf` (rich text format), `epub` (EPUB v2-    book), `epub3` (EPUB v3), `fb2` (FictionBook2 e-book),-    `asciidoc` (AsciiDoc), `icml` (InDesign ICML), `tei` (TEI-    Simple), `slidy` (Slidy HTML and JavaScript slide show),-    `slideous` (Slideous HTML and JavaScript slide show),-    `dzslides` (DZSlides HTML5 + JavaScript slide show),-    `revealjs` (reveal.js HTML5 + JavaScript slide show), `s5`-    (S5 HTML and JavaScript slide show), or the path of a custom-    lua writer (see [Custom writers], below). Note that `odt`,-    `epub`, and `epub3` output will not be directed to *stdout*;-    an output filename must be specified using the `-o/--output`-    option. If `+lhs` is appended to `markdown`, `rst`, `latex`,-    `beamer`, `html`, or `html5`, the output will be rendered as-    literate Haskell source: see [Literate Haskell support],-    below.  Markdown syntax extensions can be individually-    enabled or disabled by appending `+EXTENSION` or-    `-EXTENSION` to the format name, as described above under `-f`.-    See `--list-output-formats` and `--list-extensions`, below.--`-o` *FILE*, `--output=`*FILE*--:   Write output to *FILE* instead of *stdout*.  If *FILE* is-    `-`, output will go to *stdout*.  (Exception: if the output-    format is `odt`, `docx`, `epub`, or `epub3`, output to stdout is disabled.)--`--data-dir=`*DIRECTORY*--:   Specify the user data directory to search for pandoc data files.-    If this option is not specified, the default user data directory-    will be used.  This is, in Unix:--        $HOME/.pandoc--    in Windows XP:--        C:\Documents And Settings\USERNAME\Application Data\pandoc--    and in Windows Vista or later:--        C:\Users\USERNAME\AppData\Roaming\pandoc--    You can find the default user data directory on your system by-    looking at the output of `pandoc --version`.-    A `reference.odt`, `reference.docx`, `epub.css`, `templates`,-    `slidy`, `slideous`, or `s5` directory-    placed in this directory will override pandoc's normal defaults.--`--bash-completion`--:   Generate a bash completion script.  To enable bash completion-    with pandoc, add this to your `.bashrc`:--         eval "$(pandoc --bash-completion)"--`--verbose`--:   Give verbose debugging output.  Currently this only has an effect-    with PDF output.--`--list-input-formats`--:   List supported input formats, one per line.--`--list-output-formats`--:   List supported output formats, one per line.--`--list-extensions`--:   List supported Markdown extensions, one per line, followed-    by a `+` or `-` indicating whether it is enabled by default-    in pandoc's Markdown.--`--list-highlight-languages`--:   List supported languages for syntax highlighting, one per-    line.--`--list-highlight-styles`--:   List supported styles for syntax highlighting, one per line.-    See `--highlight-style`.--`-v`, `--version`--:   Print version.--`-h`, `--help`--:   Show usage message.--Reader options-----------------`-R`, `--parse-raw`--:   Parse untranslatable HTML codes and LaTeX environments as raw HTML-    or LaTeX, instead of ignoring them.  Affects only HTML and LaTeX-    input. Raw HTML can be printed in Markdown, reStructuredText, Emacs Org-    mode, HTML, Slidy, Slideous, DZSlides, reveal.js, and S5 output; raw LaTeX-    can be printed in Markdown, reStructuredText, Emacs Org mode, LaTeX, and-    ConTeXt output.  The default is for the readers to omit untranslatable-    HTML codes and LaTeX environments.  (The LaTeX reader does pass through-    untranslatable LaTeX *commands*, even if `-R` is not specified.)--`-S`, `--smart`--:   Produce typographically correct output, converting straight quotes-    to curly quotes, `---` to em-dashes, `--` to en-dashes, and-    `...` to ellipses. Nonbreaking spaces are inserted after certain-    abbreviations, such as "Mr." (Note: This option is selected automatically-    when the output format is `latex` or `context`, unless `--no-tex-ligatures`-    is used.  It has no effect for `latex` input.)--`--old-dashes`--:   Selects the pandoc <= 1.8.2.1 behavior for parsing smart dashes: `-` before-    a numeral is an en-dash, and `--` is an em-dash.  This option is selected-    automatically for `textile` input.--`--base-header-level=`*NUMBER*--:   Specify the base level for headers (defaults to 1).--`--indented-code-classes=`*CLASSES*--:   Specify classes to use for indented code blocks--for example,-    `perl,numberLines` or `haskell`. Multiple classes may be separated-    by spaces or commas.--`--default-image-extension=`*EXTENSION*--:   Specify a default extension to use when image paths/URLs have no-    extension.  This allows you to use the same source for formats that-    require different kinds of images.  Currently this option only affects-    the Markdown and LaTeX readers.--`--file-scope`--:   Parse each file individually before combining for multifile-    documents. This will allow footnotes in different files with the-    same identifiers to work as expected. If this option is set,-    footnotes and links will not work across files. Reading binary-    files (docx, odt, epub) implies `--file-scope`.--`--filter=`*PROGRAM*--:   Specify an executable to be used as a filter transforming the-    pandoc AST after the input is parsed and before the output is-    written.  The executable should read JSON from stdin and write-    JSON to stdout.  The JSON must be formatted like  pandoc's own-    JSON input and output.  The name of the output format will be-    passed to the filter as the first argument.  Hence,--        pandoc --filter ./caps.py -t latex--    is equivalent to--        pandoc -t json | ./caps.py latex | pandoc -f json -t latex--    The latter form may be useful for debugging filters.--    Filters may be written in any language.  `Text.Pandoc.JSON`-    exports `toJSONFilter` to facilitate writing filters in Haskell.-    Those who would prefer to write filters in python can use the-    module [`pandocfilters`], installable from PyPI. There are also-    pandoc filter libraries in [PHP], [perl], and-    [javascript/node.js].--    In order of preference, pandoc will look for filters in--     1. a specified full or relative path (executable or-     non-executable)--     2. `$DATADIR/filters` (executable or non-executable)--     3. `$PATH` (executable only)--`-M` *KEY*[`=`*VAL*], `--metadata=`*KEY*[`:`*VAL*]--:   Set the metadata field *KEY* to the value *VAL*.  A value specified-    on the command line overrides a value specified in the document.-    Values will be parsed as YAML boolean or string values. If no value is-    specified, the value will be treated as Boolean true.  Like-    `--variable`, `--metadata` causes template variables to be set.-    But unlike `--variable`, `--metadata` affects the metadata of the-    underlying document (which is accessible from filters and may be-    printed in some output formats).--`--normalize`--:   Normalize the document after reading:  merge adjacent-    `Str` or `Emph` elements, for example, and remove repeated `Space`s.--`-p`, `--preserve-tabs`--:   Preserve tabs instead of converting them to spaces (the default).-    Note that this will only affect tabs in literal code spans and code-    blocks; tabs in regular text will be treated as spaces.--`--tab-stop=`*NUMBER*--:   Specify the number of spaces per tab (default is 4).--`--track-changes=accept`|`reject`|`all`--:   Specifies what to do with insertions, deletions, and comments-    produced by the MS Word "Track Changes" feature.  `accept` (the-    default), inserts all insertions, and ignores all-    deletions. `reject` inserts all deletions and ignores-    insertions. Both `accept` and `reject` ignore comments. `all` puts-    in insertions, deletions, and comments, wrapped in spans with-    `insertion`, `deletion`, `comment-start`, and `comment-end`-    classes, respectively. The author and time of change is-    included. `all` is useful for scripting: only accepting changes-    from a certain reviewer, say, or before a certain date. This-    option only affects the docx reader.--`--extract-media=`*DIR*--:   Extract images and other media contained in a docx or epub container-    to the path *DIR*, creating it if necessary, and adjust the images-    references in the document so they point to the extracted files.-    This option only affects the docx and epub readers.--[`pandocfilters`]: https://github.com/jgm/pandocfilters-[PHP]: https://github.com/vinai/pandocfilters-php-[perl]: https://metacpan.org/pod/Pandoc::Filter-[javascript/node.js]: https://github.com/mvhenderson/pandoc-filter-node--General writer options-------------------------`-s`, `--standalone`--:   Produce output with an appropriate header and footer (e.g. a-    standalone HTML, LaTeX, TEI, or RTF file, not a fragment).  This option-    is set automatically for `pdf`, `epub`, `epub3`, `fb2`, `docx`, and `odt`-    output.--`--template=`*FILE*--:   Use *FILE* as a custom template for the generated document. Implies-    `--standalone`. See [Templates], below, for a description-    of template syntax. If no extension is specified, an extension-    corresponding to the writer will be added, so that `--template=special`-    looks for `special.html` for HTML output.  If the template is not-    found, pandoc will search for it in the `templates` subdirectory of-    the user data directory (see `--data-dir`). If this option is not used,-    a default template appropriate for the output format will be used (see-    `-D/--print-default-template`).--`-V` *KEY*[`=`*VAL*], `--variable=`*KEY*[`:`*VAL*]--:   Set the template variable *KEY* to the value *VAL* when rendering the-    document in standalone mode. This is generally only useful when the-    `--template` option is used to specify a custom template, since-    pandoc automatically sets the variables used in the default-    templates.  If no *VAL* is specified, the key will be given the-    value `true`.--`-D` *FORMAT*, `--print-default-template=`*FORMAT*--:   Print the system default template for an output *FORMAT*. (See `-t`-    for a list of possible *FORMAT*s.)  Templates in the user data-    directory are ignored.--`--print-default-data-file=`*FILE*--:   Print a system default data file.  Files in the user data directory-    are ignored.--`--dpi`=*NUMBER*-:   Specify the dpi (dots per inch) value for conversion from pixels-    to inch/centimeters and vice versa. The default is 96dpi.-    Technically, the correct term would be ppi (pixels per inch).--`--wrap=auto`|`none`|`preserve`--:   Determine how text is wrapped in the output (the source-    code, not the rendered version).  With `auto` (the default),-    pandoc will attempt to wrap lines to the column width specified by-    `--columns` (default 72).  With `none`, pandoc will not wrap-    lines at all.  With `preserve`, pandoc will attempt to-    preserve the wrapping from the source document (that is,-    where there are nonsemantic newlines in the source, there-    will be nonsemantic newlines in the output as well).-    Automatic wrapping does not currently work in HTML output.--`--no-wrap`--:   Deprecated synonym for `--wrap=none`.--`--columns=`*NUMBER*--:   Specify length of lines in characters.  This affects text wrapping-    in the generated source code (see `--wrap`).  It also affects-    calculation of column widths for plain text tables (see [Tables] below).--`--toc`, `--table-of-contents`--:   Include an automatically generated table of contents (or, in-    the case of `latex`, `context`, `docx`, and `rst`, an instruction to create-    one) in the output document. This option has no effect on `man`,-    `docbook`, `docbook5`, `slidy`, `slideous`, `s5`, or `odt` output.--`--toc-depth=`*NUMBER*--:   Specify the number of section levels to include in the table-    of contents.  The default is 3 (which means that level 1, 2, and 3-    headers will be listed in the contents).--`--no-highlight`--:   Disables syntax highlighting for code blocks and inlines, even when-    a language attribute is given.--`--highlight-style=`*STYLE*--:   Specifies the coloring style to be used in highlighted source code.-    Options are `pygments` (the default), `kate`, `monochrome`,-    `breezeDark`, `espresso`, `zenburn`, `haddock`, and `tango`.-    For more information on syntax highlighting in pandoc, see-    [Syntax highlighting], below.  See also-    `--list-highlight-styles`.--`-H` *FILE*, `--include-in-header=`*FILE*--:   Include contents of *FILE*, verbatim, at the end of the header.-    This can be used, for example, to include special-    CSS or JavaScript in HTML documents.  This option can be used-    repeatedly to include multiple files in the header.  They will be-    included in the order specified.  Implies `--standalone`.--`-B` *FILE*, `--include-before-body=`*FILE*--:   Include contents of *FILE*, verbatim, at the beginning of the-    document body (e.g. after the `<body>` tag in HTML, or the-    `\begin{document}` command in LaTeX). This can be used to include-    navigation bars or banners in HTML documents. This option can be-    used repeatedly to include multiple files. They will be included in-    the order specified.  Implies `--standalone`.--`-A` *FILE*, `--include-after-body=`*FILE*--:   Include contents of *FILE*, verbatim, at the end of the document-    body (before the `</body>` tag in HTML, or the-    `\end{document}` command in LaTeX). This option can be used-    repeatedly to include multiple files. They will be included in the-    order specified.  Implies `--standalone`.--Options affecting specific writers-------------------------------------`--self-contained`--:   Produce a standalone HTML file with no external dependencies, using-    `data:` URIs to incorporate the contents of linked scripts, stylesheets,-    images, and videos. The resulting file should be "self-contained,"-    in the sense that it needs no external files and no net access to be-    displayed properly by a browser. This option works only with HTML output-    formats, including `html`, `html5`, `html+lhs`, `html5+lhs`, `s5`,-    `slidy`, `slideous`, `dzslides`, and `revealjs`. Scripts, images, and-    stylesheets at absolute URLs will be downloaded; those at relative URLs-    will be sought relative to the working directory (if the first source-    file is local) or relative to the base URL (if the first source-    file is remote).  Limitation: resources that are loaded dynamically-    through JavaScript cannot be incorporated; as a result, `--self-contained`-    does not work with `--mathjax`, and some advanced features (e.g.-    zoom or speaker notes) may not work in an offline "self-contained"-    `reveal.js` slide show.--`--html-q-tags`--:   Use `<q>` tags for quotes in HTML.--`--ascii`--:   Use only ASCII characters in output.  Currently supported only-    for HTML output (which uses numerical entities instead of-    UTF-8 when this option is selected).--`--reference-links`--:   Use reference-style links, rather than inline links, in writing Markdown-    or reStructuredText.  By default inline links are used.  The-    placement of link references is affected by the-    `--reference-location` option.--`--reference-location = block`|`section`|`document`--:   Specify whether footnotes (and references, if `reference-links` is-    set) are placed at the end of the current (top-level) block, the-    current section, or the document. The default is-    `document`. Currently only affects the markdown writer.--`--atx-headers`--:   Use ATX-style headers in Markdown and AsciiDoc output. The default is-    to use setext-style headers for levels 1-2, and then ATX headers.--`--chapters`--:   Deprecated synonym for `--top-level-division=chapter`.--`--top-level-division=[default|section|chapter|part]`--:   Treat top-level headers as the given division type in LaTeX, ConTeXt,-    DocBook, and  TEI output. The hierarchy order is part, chapter, then section;-    all headers are shifted such that the top-level header becomes the specified-    type. The default behavior is to determine the best division type via-    heuristics: unless other conditions apply, `section` is chosen. When the-    LaTeX document class is set to `report`, `book`, or `memoir` (unless the-    `article` option is specified), `chapter` is implied as the setting for this-    option. If `beamer` is the output format, specifying either `chapter` or-    `part` will cause top-level headers to become `\part{..}`, while-    second-level headers remain as their default type.--`-N`, `--number-sections`--:   Number section headings in LaTeX, ConTeXt, HTML, or EPUB output.-    By default, sections are not numbered.  Sections with class-    `unnumbered` will never be numbered, even if `--number-sections`-    is specified.--`--number-offset=`*NUMBER*[`,`*NUMBER*`,`*...*]--:   Offset for section headings in HTML output (ignored in other-    output formats).  The first number is added to the section number for-    top-level headers, the second for second-level headers, and so on.-    So, for example, if you want the first top-level header in your-    document to be numbered "6", specify `--number-offset=5`.-    If your document starts with a level-2 header which you want to-    be numbered "1.5", specify `--number-offset=1,4`.-    Offsets are 0 by default.  Implies `--number-sections`.--`--no-tex-ligatures`--:   Do not use the TeX ligatures for quotation marks, apostrophes,-    and dashes (`` `...' ``, ` ``..'' `, `--`, `---`) when-    writing or reading LaTeX or ConTeXt.  In reading LaTeX,-    parse the characters `` ` ``, `'`, and `-` literally, rather-    than parsing ligatures for quotation marks and dashes.  In-    writing LaTeX or ConTeXt, print unicode quotation mark and-    dash characters literally, rather than converting them to-    the standard ASCII TeX ligatures.  Note: normally `--smart`-    is selected automatically for LaTeX and ConTeXt output, but-    it must be specified explicitly if `--no-tex-ligatures` is-    selected. If you use literal curly quotes, dashes, and-    ellipses in your source, then you may want to use-    `--no-tex-ligatures` without `--smart`.--`--listings`--:   Use the [`listings`] package for LaTeX code blocks--`-i`, `--incremental`--:   Make list items in slide shows display incrementally (one by one).-    The default is for lists to be displayed all at once.--`--slide-level=`*NUMBER*--:   Specifies that headers with the specified level create-    slides (for `beamer`, `s5`, `slidy`, `slideous`, `dzslides`).  Headers-    above this level in the hierarchy are used to divide the-    slide show into sections; headers below this level create-    subheads within a slide.  The default is to set the slide level-    based on the contents of the document; see-    [Structuring the slide show].--`--section-divs`--:   Wrap sections in `<div>` tags (or `<section>` tags in HTML5),-    and attach identifiers to the enclosing `<div>` (or `<section>`)-    rather than the header itself. See-    [Header identifiers], below.--`--email-obfuscation=none`|`javascript`|`references`--:   Specify a method for obfuscating `mailto:` links in HTML documents.-    `none` leaves `mailto:` links as they are.  `javascript` obfuscates-    them using JavaScript. `references` obfuscates them by printing their-    letters as decimal or hexadecimal character references.  The default-    is `none`.--`--id-prefix=`*STRING*--:   Specify a prefix to be added to all automatically generated identifiers-    in HTML and DocBook output, and to footnote numbers in Markdown output.-    This is useful for preventing duplicate identifiers when generating-    fragments to be included in other pages.--`-T` *STRING*, `--title-prefix=`*STRING*--:   Specify *STRING* as a prefix at the beginning of the title-    that appears in the HTML header (but not in the title as it-    appears at the beginning of the HTML body).  Implies-    `--standalone`.--`-c` *URL*, `--css=`*URL*--:   Link to a CSS style sheet. This option can be used repeatedly to-    include multiple files. They will be included in the order specified.--`--reference-odt=`*FILE*--:   Use the specified file as a style reference in producing an ODT.-    For best results, the reference ODT should be a modified version-    of an ODT produced using pandoc.  The contents of the reference ODT-    are ignored, but its stylesheets are used in the new ODT. If no-    reference ODT is specified on the command line, pandoc will look-    for a file `reference.odt` in the user data directory (see-    `--data-dir`). If this is not found either, sensible defaults will be-    used.--    To produce a custom `reference.odt`, first get a copy of-    the default `reference.odt`: `pandoc-    --print-default-data-file reference.odt >-    custom-reference.odt`.  Then open `custom-reference.docx` in-    LibreOffice, modify the styles as you wish, and save the-    file.--`--reference-docx=`*FILE*--:   Use the specified file as a style reference in producing a docx file.-    For best results, the reference docx should be a modified version-    of a docx file produced using pandoc.  The contents of the reference docx-    are ignored, but its stylesheets and document properties (including-    margins, page size, header, and footer) are used in the new docx. If no-    reference docx is specified on the command line, pandoc will look-    for a file `reference.docx` in the user data directory (see-    `--data-dir`). If this is not found either, sensible defaults will be-    used.--    To produce a custom `reference.docx`, first get a copy of-    the default `reference.docx`: `pandoc-    --print-default-data-file reference.docx >-    custom-reference.docx`.  Then open `custom-reference.docx`-    in Word, modify the styles as you wish, and save the file.-    For best results, do not make changes to this file other-    than modifying the styles used by pandoc: [paragraph] Normal,-    Body Text, First Paragraph, Compact, Title, Subtitle,-    Author, Date, Abstract, Bibliography, Heading 1, Heading 2,-    Heading 3, Heading 4, Heading 5, Heading 6, Block Text,-    Footnote Text, Definition Term, Definition, Caption, Table-    Caption, Image Caption, Figure, Figure With Caption, TOC-    Heading; [character] Default Paragraph Font, Body Text Char,-    Verbatim Char, Footnote Reference, Hyperlink; [table] Normal-    Table.--`--epub-stylesheet=`*FILE*--:   Use the specified CSS file to style the EPUB.  If no stylesheet-    is specified, pandoc will look for a file `epub.css` in the-    user data directory (see `--data-dir`).  If it is not-    found there, sensible defaults will be used.--`--epub-cover-image=`*FILE*--:   Use the specified image as the EPUB cover.  It is recommended-    that the image be less than 1000px in width and height. Note that-    in a Markdown source document you can also specify `cover-image`-    in a YAML metadata block (see [EPUB Metadata], below).--`--epub-metadata=`*FILE*--:   Look in the specified XML file for metadata for the EPUB.-    The file should contain a series of [Dublin Core elements].-    For example:--         <dc:rights>Creative Commons</dc:rights>-         <dc:language>es-AR</dc:language>--    By default, pandoc will include the following metadata elements:-    `<dc:title>` (from the document title), `<dc:creator>` (from the-    document authors), `<dc:date>` (from the document date, which should-    be in [ISO 8601 format]), `<dc:language>` (from the `lang`-    variable, or, if is not set, the locale), and `<dc:identifier-    id="BookId">` (a randomly generated UUID). Any of these may be-    overridden by elements in the metadata file.--    Note: if the source document is Markdown, a YAML metadata block-    in the document can be used instead.  See below under-    [EPUB Metadata].--`--epub-embed-font=`*FILE*--:   Embed the specified font in the EPUB. This option can be repeated-    to embed multiple fonts.  Wildcards can also be used: for example,-    `DejaVuSans-*.ttf`.  However, if you use wildcards on the command-    line, be sure to escape them or put the whole filename in single quotes,-    to prevent them from being interpreted by the shell. To use the-    embedded fonts, you will need to add declarations like the following-    to your CSS (see `--epub-stylesheet`):--        @font-face {-        font-family: DejaVuSans;-        font-style: normal;-        font-weight: normal;-        src:url("DejaVuSans-Regular.ttf");-        }-        @font-face {-        font-family: DejaVuSans;-        font-style: normal;-        font-weight: bold;-        src:url("DejaVuSans-Bold.ttf");-        }-        @font-face {-        font-family: DejaVuSans;-        font-style: italic;-        font-weight: normal;-        src:url("DejaVuSans-Oblique.ttf");-        }-        @font-face {-        font-family: DejaVuSans;-        font-style: italic;-        font-weight: bold;-        src:url("DejaVuSans-BoldOblique.ttf");-        }-        body { font-family: "DejaVuSans"; }--`--epub-chapter-level=`*NUMBER*--:   Specify the header level at which to split the EPUB into separate-    "chapter" files. The default is to split into chapters at level 1-    headers. This option only affects the internal composition of the-    EPUB, not the way chapters and sections are displayed to users. Some-    readers may be slow if the chapter files are too large, so for large-    documents with few level 1 headers, one might want to use a chapter-    level of 2 or 3.--`--latex-engine=pdflatex`|`lualatex`|`xelatex`--:   Use the specified LaTeX engine when producing PDF output.-    The default is `pdflatex`.  If the engine is not in your PATH,-    the full path of the engine may be specified here.--`--latex-engine-opt=`*STRING*--:   Use the given string as a command-line argument to the `latex-engine`.-    If used multiple times, the arguments are provided with spaces between-    them. Note that no check for duplicate options is done.--[Dublin Core elements]: http://dublincore.org/documents/dces/-[ISO 8601 format]: http://www.w3.org/TR/NOTE-datetime--Citation rendering---------------------`--bibliography=`*FILE*--:   Set the `bibliography` field in the document's metadata to *FILE*,-    overriding any value set in the metadata, and process citations-    using `pandoc-citeproc`. (This is equivalent to-    `--metadata bibliography=FILE --filter pandoc-citeproc`.)-    If `--natbib` or `--biblatex` is also supplied, `pandoc-citeproc` is not-    used, making this equivalent to `--metadata bibliography=FILE`.-    If you supply this argument multiple times, each *FILE* will be added-    to bibliography.--`--csl=`*FILE*--:   Set the `csl` field in the document's metadata to *FILE*,-    overriding any value set in the metadata.  (This is equivalent to-    `--metadata csl=FILE`.)-    This option is only relevant with `pandoc-citeproc`.--`--citation-abbreviations=`*FILE*--:   Set the `citation-abbreviations` field in the document's metadata to-    *FILE*, overriding any value set in the metadata.  (This is equivalent to-    `--metadata citation-abbreviations=FILE`.)-    This option is only relevant with `pandoc-citeproc`.--`--natbib`--:   Use [`natbib`] for citations in LaTeX output.  This option is not for use-    with the `pandoc-citeproc` filter or with PDF output.  It is intended for-    use in producing a LaTeX file that can be processed with [`bibtex`].--`--biblatex`--:   Use [`biblatex`] for citations in LaTeX output.  This option is not for use-    with the `pandoc-citeproc` filter or with PDF output. It is intended for-    use in producing a LaTeX file that can be processed with [`bibtex`] or [`biber`].--Math rendering in HTML-------------------------`-m` [*URL*], `--latexmathml`[`=`*URL*]--:   Use the [LaTeXMathML] script to display embedded TeX math in HTML output.-    To insert a link to a local copy of the `LaTeXMathML.js` script,-    provide a *URL*. If no *URL* is provided, the contents of the-    script will be inserted directly into the HTML header, preserving-    portability at the price of efficiency. If you plan to use math on-    several pages, it is much better to link to a copy of the script,-    so it can be cached.--`--mathml`[`=`*URL*]--:   Convert TeX math to [MathML] (in `docbook`, `docbook5`, `html` and `html5`).-    In standalone `html` output, a small JavaScript (or a link to such a-    script if a *URL* is supplied) will be inserted that allows the MathML to-    be viewed on some browsers.--`--jsmath`[`=`*URL*]--:   Use [jsMath] to display embedded TeX math in HTML output.-    The *URL* should point to the jsMath load script (e.g.-    `jsMath/easy/load.js`); if provided, it will be linked to in-    the header of standalone HTML documents. If a *URL* is not provided,-    no link to the jsMath load script will be inserted; it is then-    up to the author to provide such a link in the HTML template.--`--mathjax`[`=`*URL*]--:   Use [MathJax] to display embedded TeX math in HTML output.-    The *URL* should point to the `MathJax.js` load script.-    If a *URL* is not provided, a link to the MathJax CDN will-    be inserted.--`--gladtex`--:   Enclose TeX math in `<eq>` tags in HTML output.  These can then-    be processed by [gladTeX] to produce links to images of the typeset-    formulas.--`--mimetex`[`=`*URL*]--:   Render TeX math using the [mimeTeX] CGI script.  If *URL* is not-    specified, it is assumed that the script is at `/cgi-bin/mimetex.cgi`.--`--webtex`[`=`*URL*]--:   Render TeX formulas using an external script that converts TeX-    formulas to images. The formula will be concatenated with the URL-    provided. If *URL* is not specified, the CodeCogs will be used.-    Note:  the `--webtex` option will affect Markdown output-    as well as HTML, which is useful if you're targeting a-    version of Markdown without native math support.--`--katex`[`=`*URL*]--:   Use [KaTeX] to display embedded TeX math in HTML output.-    The *URL* should point to the `katex.js` load script. If a *URL* is-    not provided, a link to the KaTeX CDN will be inserted.-    Note: [KaTeX] seems to work best with `html5` output.--`--katex-stylesheet=`*URL*--:   The *URL* should point to the `katex.css` stylesheet. If this option is-    not specified, a link to the KaTeX CDN will be inserted. Note that this-    option does not imply `--katex`.--[MathML]: http://www.w3.org/Math/-[LaTeXMathML]: http://math.etsu.edu/LaTeXMathML/-[jsMath]: http://www.math.union.edu/~dpvc/jsmath/-[MathJax]: https://www.mathjax.org-[gladTeX]: http://ans.hsh.no/home/mgg/gladtex/-[mimeTeX]: http://www.forkosh.com/mimetex.html-[KaTeX]: https://github.com/Khan/KaTeX--Options for wrapper scripts------------------------------`--dump-args`--:   Print information about command-line arguments to *stdout*, then exit.-    This option is intended primarily for use in wrapper scripts.-    The first line of output contains the name of the output file specified-    with the `-o` option, or `-` (for *stdout*) if no output file was-    specified.  The remaining lines contain the command-line arguments,-    one per line, in the order they appear.  These do not include regular-    pandoc options and their arguments, but do include any options appearing-    after a `--` separator at the end of the line.--`--ignore-args`--:   Ignore command-line arguments (for use in wrapper scripts).-    Regular pandoc options are not ignored.  Thus, for example,--        pandoc --ignore-args -o foo.html -s foo.txt -- -e latin1--    is equivalent to--        pandoc -o foo.html -s--Templates-=========--When the `-s/--standalone` option is used, pandoc uses a template to-add header and footer material that is needed for a self-standing-document.  To see the default template that is used, just type--    pandoc -D *FORMAT*--where *FORMAT* is the name of the output format. A custom template-can be specified using the `--template` option.  You can also override-the system default templates for a given output format *FORMAT*-by putting a file `templates/default.*FORMAT*` in the user data-directory (see `--data-dir`, above). *Exceptions:*--- For `odt` output, customize the `default.opendocument`-  template.-- For `pdf` output, customize the `default.latex` template-  (or the `default.beamer` template, if you use `-t beamer`,-  or the `default.context` template, if you use `-t context`).-- `docx` has no template (however, you can use-  `--reference-docx` to customize the output).--Templates contain *variables*, which allow for the inclusion of-arbitrary information at any point in the file. Variables may be set-within the document using [YAML metadata blocks][Extension:-`yaml_metadata_block`].  They may also be set at the-command line using the `-V/--variable` option: variables set in this-way override metadata fields with the same name.--Variables set by pandoc--------------------------Some variables are set automatically by pandoc.  These vary somewhat-depending on the output format, but include metadata fields as well-as the following:--`title`, `author`, `date`-:   allow identification of basic aspects of the document.  Included-    in PDF metadata through LaTeX and ConTeXt.  These can be set-    through a [pandoc title block][Extension: `pandoc_title_block`],-    which allows for multiple authors, or through a YAML metadata block:--        ----        author:-        - Aristotle-        - Peter Abelard-        ...--`subtitle`-:   document subtitle, included in HTML, EPUB, LaTeX, ConTeXt, and Word docx;-    renders in LaTeX only when using a document class that supports-    `\subtitle`, such as `beamer` or the [KOMA-Script] series (`scrartcl`,-    `scrreprt`, `scrbook`).[^subtitle]--`institute`-:   author affiliations (in LaTeX and Beamer only).  Can be a-    list, when there are multiple authors.--`abstract`-:   document summary, included in LaTeX, ConTeXt, AsciiDoc, and Word docx--`keywords`-:   list of keywords to be included in HTML, PDF, and AsciiDoc metadata;-    may be repeated as for `author`, above--`header-includes`-:   contents specified by `-H/--include-in-header` (may have multiple-    values)--`toc`-:   non-null value if `--toc/--table-of-contents` was specified--`toc-title`-:   title of table of contents (works only with EPUB and docx)--`include-before`-:   contents specified by `-B/--include-before-body` (may have-    multiple values)--`include-after`-:   contents specified by `-A/--include-after-body` (may have-    multiple values)--`body`-:   body of document--`meta-json`-:   JSON representation of all of the document's metadata--[^subtitle]: To make `subtitle` work with other LaTeX-    document classes, you can add the following to `header-includes`:--        \providecommand{\subtitle}[1]{%-          \usepackage{titling}-          \posttitle{%-            \par\large#1\end{center}}-        }--Language variables---------------------`lang`-:   identifies the main language of the document,-    using a code according to [BCP 47] (e.g. `en` or `en-GB`).-    For some output formats, pandoc will convert it to an appropriate-    format stored in the additional variables `babel-lang`,-    `polyglossia-lang` (LaTeX) and `context-lang` (ConTeXt).--    Native pandoc `span`s and `div`s with the lang attribute-    (value in BCP 47) can be used to switch the language in-    that range.--`otherlangs`-:   a list of other languages used in the document-    in the YAML metadata, according to [BCP 47]. For example:-    `otherlangs: [en-GB, fr]`.-    This is automatically generated from the `lang` attributes-    in all `span`s and `div`s but can be overridden.-    Currently only used by LaTeX through the generated-    `babel-otherlangs` and `polyglossia-otherlangs` variables.-    The LaTeX writer outputs polyglossia commands in the text but-    the `babel-newcommands` variable contains mappings for them-    to the corresponding babel.--`dir`-:   the base direction of the document, either `rtl` (right-to-left)-    or `ltr` (left-to-right).--    For bidirectional documents, native pandoc `span`s and `div`s-    with the `dir` attribute (value `rtl` or `ltr`) can be used to-    override the base direction in some output formats.-    This may not always be necessary if the final renderer-    (e.g. the browser, when generating HTML) supports the-    [Unicode Bidirectional Algorithm].--    When using LaTeX for bidirectional documents, only the `xelatex` engine-    is fully supported (use `--latex-engine=xelatex`).--[BCP 47]: https://tools.ietf.org/html/bcp47-[Unicode Bidirectional Algorithm]: http://www.w3.org/International/articles/inline-bidi-markup/uba-basics--Variables for slides-----------------------Variables are available for [producing slide shows with pandoc],-including all [reveal.js configuration options].--`slidy-url`-:   base URL for Slidy documents (defaults to-    `http://www.w3.org/Talks/Tools/Slidy2`)--`slideous-url`-:   base URL for Slideous documents (defaults to `slideous`)--`s5-url`-:   base URL for S5 documents (defaults to `s5/default`)--`revealjs-url`-:   base URL for reveal.js documents (defaults to `reveal.js`)--`theme`, `colortheme`, `fonttheme`, `innertheme`, `outertheme`-:   themes for LaTeX [`beamer`] documents--`themeoptions`-:   options for LaTeX beamer themes (a list).--`navigation`-:   controls navigation symbols in `beamer` documents-    (default is `empty` for no navigation symbols; other valid values-    are `frame`, `vertical`, and `horizontal`).--`section-titles`-:   enables on "title pages" for new sections in `beamer`-    documents (default = true).--`beamerarticle`-:   when true, the `beamerarticle` package is loaded (for-    producing an article from beamer slides).--`colorlinks`-:   add color to link text; automatically enabled if any of `linkcolor`, `citecolor`,-    `urlcolor`, or `toccolor` are set (for beamer only).--`linkcolor`, `citecolor`, `urlcolor`, `toccolor`-:   color for internal links, citation links, external links, and links in table-    of contents: uses any of the [predefined LaTeX colors] (for beamer only).--[reveal.js configuration options]: https://github.com/hakimel/reveal.js#configuration--Variables for LaTeX----------------------LaTeX variables are used when [creating a PDF].--`papersize`-:   paper size, e.g. `letter`, `A4`--`fontsize`-:   font size for body text (e.g. `10pt`, `12pt`)--`documentclass`-:   document class, e.g. [`article`], [`report`], [`book`], [`memoir`]--`classoption`-:   option for document class, e.g. `oneside`; may be repeated-    for multiple options--`geometry`-:   option for [`geometry`] package, e.g. `margin=1in`;-    may be repeated for multiple options--`margin-left`, `margin-right`, `margin-top`, `margin-bottom`-:   sets margins, if `geometry` is not used (otherwise `geometry`-    overrides these)--`linestretch`-:   adjusts line spacing using the [`setspace`]-    package, e.g. `1.25`, `1.5`--`fontfamily`-:   font package for use with `pdflatex`:-    [TeX Live] includes many options, documented in the [LaTeX Font Catalogue].-    The default is [Latin Modern][`lm`].--`fontfamilyoptions`-:   options for package used as `fontfamily`: e.g. `osf,sc` with-    `fontfamily` set to [`mathpazo`] provides Palatino with old-style-    figures and true small caps; may be repeated for multiple options--`mainfont`, `sansfont`, `monofont`, `mathfont`, `CJKmainfont`-:   font families for use with `xelatex` or-    `lualatex`: take the name of any system font, using the-    [`fontspec`] package.  Note that if `CJKmainfont` is used,-    the [`xecjk`] package must be available.--`mainfontoptions`, `sansfontoptions`, `monofontoptions`, `mathfontoptions`, `CJKoptions`-:   options to use with `mainfont`, `sansfont`, `monofont`, `mathfont`,-    `CJKmainfont` in `xelatex` and `lualatex`.  Allow for any choices-    available through [`fontspec`], such as the OpenType features-    `Numbers=OldStyle,Numbers=Proportional`. May be repeated for multiple options.--`fontenc`-:   allows font encoding to be specified through `fontenc` package (with `pdflatex`);-    default is `T1` (see guide to [LaTeX font encodings])--`microtypeoptions`-:    options to pass to the microtype package--`colorlinks`-:   add color to link text; automatically enabled if any of `linkcolor`, `citecolor`,-    `urlcolor`, or `toccolor` are set--`linkcolor`, `citecolor`, `urlcolor`, `toccolor`-:   color for internal links, citation links, external links, and links in table of contents:-    uses any of the [predefined LaTeX colors]--`links-as-notes`-:   causes links to be printed as footnotes--`indent`-:   uses document class settings for indentation (the default LaTeX template-    otherwise removes indentation and adds space between paragraphs)--`subparagraph`-:   disables default behavior of LaTeX template that redefines (sub)paragraphs-    as sections, changing the appearance of nested headings in some classes--`thanks`-:   specifies contents of acknowledgments footnote after document title.--`toc`-:   include table of contents (can also be set using `--toc/--table-of-contents`)--`toc-depth`-:   level of section to include in table of contents--`secnumdepth`-:   numbering depth for sections, if sections are numbered--`lof`, `lot`-:   include list of figures, list of tables--`bibliography`-:   bibliography to use for resolving references--`biblio-style`-:   bibliography style, when used with `--natbib` and `--biblatex`.--`biblio-title`-:   bibliography title, when used with `--natbib` and `--biblatex`.--`biblatexoptions`-:   list of options for biblatex.--[`article`]: https://ctan.org/pkg/article-[`report`]: https://ctan.org/pkg/report-[`book`]: https://ctan.org/pkg/book-[KOMA-Script]: https://ctan.org/pkg/koma-script-[`memoir`]: https://ctan.org/pkg/memoir-[predefined LaTeX colors]: https://en.wikibooks.org/wiki/LaTeX/Colors#Predefined_colors-[LaTeX Font Catalogue]: http://www.tug.dk/FontCatalogue/-[`mathpazo`]: https://ctan.org/pkg/mathpazo-[LaTeX font encodings]: https://ctan.org/pkg/encguide--Variables for ConTeXt------------------------`papersize`-:   paper size, e.g. `letter`, `A4`, `landscape` (see [ConTeXt Paper Setup]);-    may be repeated for multiple options--`layout`-:   options for page margins and text arrangement (see [ConTeXt Layout]);-    may be repeated for multiple options--`margin-left`, `margin-right`, `margin-top`, `margin-bottom`-:   sets margins, if `layout` is not used (otherwise `layout`-    overrides these)--`fontsize`-:   font size for body text (e.g. `10pt`, `12pt`)--`mainfont`, `sansfont`, `monofont`, `mathfont`-:   font families: take the name of any system font (see [ConTeXt Font Switching])--`linkcolor`, `contrastcolor`-:   color for links outside and inside a page, e.g. `red`, `blue` (see [ConTeXt Color])--`linkstyle`-:   typeface style for links, e.g. `normal`, `bold`, `slanted`, `boldslanted`, `type`, `cap`, `small`--`indenting`-:   controls indentation of paragraphs, e.g. `yes,small,next` (see [ConTeXt Indentation]);-    may be repeated for multiple options--`whitespace`-:   spacing between paragraphs, e.g. `none`, `small` (using [`setupwhitespace`])--`interlinespace`-:   adjusts line spacing, e.g. `4ex` (using [`setupinterlinespace`]);-    may be repeated for multiple options--`headertext`, `footertext`-:   text to be placed in running header or footer (see [ConTeXt Headers and Footers]);-    may be repeated up to four times for different placement--`pagenumbering`-:   page number style and location (using [`setuppagenumbering`]);-    may be repeated for multiple options--`toc`-:   include table of contents (can also be set using `--toc/--table-of-contents`)--`lof`, `lot`-:   include list of figures, list of tables--[ConTeXt Paper Setup]: http://wiki.contextgarden.net/PaperSetup-[ConTeXt Layout]: http://wiki.contextgarden.net/Layout-[ConTeXt Font Switching]: http://wiki.contextgarden.net/Font_Switching-[ConTeXt Color]: http://wiki.contextgarden.net/Color-[ConTeXt Headers and Footers]: http://wiki.contextgarden.net/Headers_and_Footers-[ConTeXt Indentation]: http://wiki.contextgarden.net/Indentation-[`setupwhitespace`]: http://wiki.contextgarden.net/Command/setupwhitespace-[`setupinterlinespace`]: http://wiki.contextgarden.net/Command/setupinterlinespace-[`setuppagenumbering`]: http://wiki.contextgarden.net/Command/setuppagenumbering--Variables for man pages--------------------------`section`-:   section number in man pages--`header`-:   header in man pages--`footer`-:   footer in man pages--`adjusting`-:   adjusts text to left (`l`), right (`r`), center (`c`),-    or both (`b`) margins--`hyphenate`-:   if `true` (the default), hyphenation will be used--Using variables in templates-------------------------------Variable names are sequences of alphanumerics, `-`, and `_`,-starting with a letter.  A variable name surrounded by `$` signs-will be replaced by its value.  For example, the string `$title$` in--    <title>$title$</title>--will be replaced by the document title.--To write a literal `$` in a template, use `$$`.--Templates may contain conditionals.  The syntax is as follows:--    $if(variable)$-    X-    $else$-    Y-    $endif$--This will include `X` in the template if `variable` has a non-null-value; otherwise it will include `Y`. `X` and `Y` are placeholders for-any valid template text, and may include interpolated variables or other-conditionals. The `$else$` section may be omitted.--When variables can have multiple values (for example, `author` in-a multi-author document), you can use the `$for$` keyword:--    $for(author)$-    <meta name="author" content="$author$" />-    $endfor$--You can optionally specify a separator to be used between-consecutive items:--    $for(author)$$author$$sep$, $endfor$--A dot can be used to select a field of a variable that takes-an object as its value.  So, for example:--    $author.name$ ($author.affiliation$)--If you use custom templates, you may need to revise them as pandoc-changes.  We recommend tracking the changes in the default templates,-and modifying your custom templates accordingly. An easy way to do this-is to fork the [pandoc-templates] repository and merge in changes after each-pandoc release.--[pandoc-templates]: https://github.com/jgm/pandoc-templates--Pandoc's Markdown-=================--Pandoc understands an extended and slightly revised version of-John Gruber's [Markdown] syntax.  This document explains the syntax,-noting differences from standard Markdown. Except where noted, these-differences can be suppressed by using the `markdown_strict` format instead-of `markdown`.  An extensions can be enabled by adding `+EXTENSION`-to the format name and disabled by adding `-EXTENSION`. For example,-`markdown_strict+footnotes` is strict Markdown with footnotes-enabled, while `markdown-footnotes-pipe_tables` is pandoc's-Markdown without footnotes or pipe tables.--Philosophy-------------Markdown is designed to be easy to write, and, even more importantly,-easy to read:--> A Markdown-formatted document should be publishable as-is, as plain-> text, without looking like it's been marked up with tags or formatting-> instructions.-> -- [John Gruber](http://daringfireball.net/projects/markdown/syntax#philosophy)--This principle has guided pandoc's decisions in finding syntax for-tables, footnotes, and other extensions.--There is, however, one respect in which pandoc's aims are different-from the original aims of Markdown.  Whereas Markdown was originally-designed with HTML generation in mind, pandoc is designed for multiple-output formats.  Thus, while pandoc allows the embedding of raw HTML,-it discourages it, and provides other, non-HTMLish ways of representing-important document elements like definition lists, tables, mathematics, and-footnotes.--Paragraphs-------------A paragraph is one or more lines of text followed by one or more blank lines.-Newlines are treated as spaces, so you can reflow your paragraphs as you like.-If you need a hard line break, put two or more spaces at the end of a line.--#### Extension: `escaped_line_breaks` ####--A backslash followed by a newline is also a hard line break.-Note:  in multiline and grid table cells, this is the only way-to create a hard line break, since trailing spaces in the cells-are ignored.--Headers----------There are two kinds of headers: Setext and ATX.--### Setext-style headers ###--A setext-style header is a line of text "underlined" with a row of `=` signs-(for a level one header) or `-` signs (for a level two header):--    A level-one header-    ==================--    A level-two header-    --------------------The header text can contain inline formatting, such as emphasis (see-[Inline formatting], below).---### ATX-style headers ###--An ATX-style header consists of one to six `#` signs and a line of-text, optionally followed by any number of `#` signs.  The number of-`#` signs at the beginning of the line is the header level:--    ## A level-two header--    ### A level-three header ###--As with setext-style headers, the header text can contain formatting:--    # A level-one header with a [link](/url) and *emphasis*--#### Extension: `blank_before_header` ####--Standard Markdown syntax does not require a blank line before a header.-Pandoc does require this (except, of course, at the beginning of the-document). The reason for the requirement is that it is all too easy for a-`#` to end up at the beginning of a line by accident (perhaps through line-wrapping). Consider, for example:--    I like several of their flavors of ice cream:-    #22, for example, and #5.---### Header identifiers ###--#### Extension: `header_attributes` ####--Headers can be assigned attributes using this syntax at the end-of the line containing the header text:--    {#identifier .class .class key=value key=value}--Thus, for example, the following headers will all be assigned the identifier-`foo`:--    # My header {#foo}--    ## My header ##    {#foo}--    My other header   {#foo}-    -----------------(This syntax is compatible with [PHP Markdown Extra].)--Note that although this syntax allows assignment of classes and key/value-attributes, writers generally don't use all of this information.  Identifiers,-classes, and key/value attributes are used in HTML and HTML-based formats such-as EPUB and slidy.  Identifiers are used for labels and link anchors in the-LaTeX, ConTeXt, Textile, and AsciiDoc writers.--Headers with the class `unnumbered` will not be numbered, even if-`--number-sections` is specified.  A single hyphen (`-`) in an attribute-context is equivalent to `.unnumbered`, and preferable in non-English-documents.  So,--    # My header {-}--is just the same as--    # My header {.unnumbered}--#### Extension: `auto_identifiers` ####--A header without an explicitly specified identifier will be-automatically assigned a unique identifier based on the header text.-To derive the identifier from the header text,--  - Remove all formatting, links, etc.-  - Remove all footnotes.-  - Remove all punctuation, except underscores, hyphens, and periods.-  - Replace all spaces and newlines with hyphens.-  - Convert all alphabetic characters to lowercase.-  - Remove everything up to the first letter (identifiers may-    not begin with a number or punctuation mark).-  - If nothing is left after this, use the identifier `section`.--Thus, for example,--  Header                            Identifier-  -------------------------------   -----------------------------  `Header identifiers in HTML`      `header-identifiers-in-html`-  `*Dogs*?--in *my* house?`         `dogs--in-my-house`-  `[HTML], [S5], or [RTF]?`         `html-s5-or-rtf`-  `3. Applications`                 `applications`-  `33`                              `section`--These rules should, in most cases, allow one to determine the identifier-from the header text. The exception is when several headers have the-same text; in this case, the first will get an identifier as described-above; the second will get the same identifier with `-1` appended; the-third with `-2`; and so on.--These identifiers are used to provide link targets in the table of-contents generated by the `--toc|--table-of-contents` option. They-also make it easy to provide links from one section of a document to-another. A link to this section, for example, might look like this:--    See the section on-    [header identifiers](#header-identifiers-in-html-latex-and-context).--Note, however, that this method of providing links to sections works-only in HTML, LaTeX, and ConTeXt formats.--If the `--section-divs` option is specified, then each section will-be wrapped in a `div` (or a `section`, if `--html5` was specified),-and the identifier will be attached to the enclosing `<div>`-(or `<section>`) tag rather than the header itself. This allows entire-sections to be manipulated using JavaScript or treated differently in-CSS.--#### Extension: `implicit_header_references` ####--Pandoc behaves as if reference links have been defined for each header.-So, to link to a header--    # Header identifiers in HTML--you can simply write--    [Header identifiers in HTML]--or--    [Header identifiers in HTML][]--or--    [the section on header identifiers][header identifiers in-    HTML]--instead of giving the identifier explicitly:--    [Header identifiers in HTML](#header-identifiers-in-html)--If there are multiple headers with identical text, the corresponding-reference will link to the first one only, and you will need to use explicit-links to link to the others, as described above.--Like regular reference links, these references are case-insensitive.--Explicit link reference definitions always take priority over-implicit header references.  So, in the following example, the-link will point to `bar`, not to `#foo`:--    # Foo--    [foo]: bar--    See [foo]--Block quotations-------------------Markdown uses email conventions for quoting blocks of text.-A block quotation is one or more paragraphs or other block elements-(such as lists or headers), with each line preceded by a `>` character-and an optional space. (The `>` need not start at the left margin, but-it should not be indented more than three spaces.)--    > This is a block quote. This-    > paragraph has two lines.-    >-    > 1. This is a list inside a block quote.-    > 2. Second item.--A "lazy" form, which requires the `>` character only on the first-line of each block, is also allowed:--    > This is a block quote. This-    paragraph has two lines.--    > 1. This is a list inside a block quote.-    2. Second item.--Among the block elements that can be contained in a block quote are-other block quotes. That is, block quotes can be nested:--    > This is a block quote.-    >-    > > A block quote within a block quote.--If the `>` character is followed by an optional space, that space-will be considered part of the block quote marker and not part of-the indentation of the contents.  Thus, to put an indented code-block in a block quote, you need five spaces after the `>`:--    >     code--#### Extension: `blank_before_blockquote` ####--Standard Markdown syntax does not require a blank line before a block-quote.  Pandoc does require this (except, of course, at the beginning of the-document). The reason for the requirement is that it is all too easy for a-`>` to end up at the beginning of a line by accident (perhaps through line-wrapping). So, unless the `markdown_strict` format is used, the following does-not produce a nested block quote in pandoc:--    > This is a block quote.-    >> Nested.---Verbatim (code) blocks-------------------------### Indented code blocks ###--A block of text indented four spaces (or one tab) is treated as verbatim-text: that is, special characters do not trigger special formatting,-and all spaces and line breaks are preserved.  For example,--        if (a > 3) {-          moveShip(5 * gravity, DOWN);-        }--The initial (four space or one tab) indentation is not considered part-of the verbatim text, and is removed in the output.--Note: blank lines in the verbatim text need not begin with four spaces.---### Fenced code blocks ###--#### Extension: `fenced_code_blocks` ####--In addition to standard indented code blocks, pandoc supports-*fenced* code blocks.  These begin with a row of three or more-tildes (`~`) and end with a row of tildes that must be at least as long as-the starting row. Everything between these lines is treated as code. No-indentation is necessary:--    ~~~~~~~-    if (a > 3) {-      moveShip(5 * gravity, DOWN);-    }-    ~~~~~~~--Like regular code blocks, fenced code blocks must be separated-from surrounding text by blank lines.--If the code itself contains a row of tildes or backticks, just use a longer-row of tildes or backticks at the start and end:--    ~~~~~~~~~~~~~~~~-    ~~~~~~~~~~-    code including tildes-    ~~~~~~~~~~-    ~~~~~~~~~~~~~~~~--#### Extension: `backtick_code_blocks` ####--Same as `fenced_code_blocks`, but uses backticks (`` ` ``) instead of tildes-(`~`).--#### Extension: `fenced_code_attributes` ####--Optionally, you may attach attributes to fenced or backtick code block using-this syntax:--    ~~~~ {#mycode .haskell .numberLines startFrom="100"}-    qsort []     = []-    qsort (x:xs) = qsort (filter (< x) xs) ++ [x] ++-                   qsort (filter (>= x) xs)-    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--Here `mycode` is an identifier, `haskell` and `numberLines` are classes, and-`startFrom` is an attribute with value `100`. Some output formats can use this-information to do syntax highlighting. Currently, the only output formats-that uses this information are HTML and LaTeX. If highlighting is supported-for your output format and language, then the code block above will appear-highlighted, with numbered lines. (To see which languages are supported, type-`pandoc --list-highlight-languages`.) Otherwise, the code block above will-appear as follows:--    <pre id="mycode" class="haskell numberLines" startFrom="100">-      <code>-      ...-      </code>-    </pre>--A shortcut form can also be used for specifying the language of-the code block:--    ```haskell-    qsort [] = []-    ```--This is equivalent to:--    ``` {.haskell}-    qsort [] = []-    ```--If the `fenced_code_attributes` extension is disabled, but-input contains class attribute(s) for the code block, the first-class attribute will be printed after the opening fence as a bare-word.--To prevent all highlighting, use the `--no-highlight` flag.-To set the highlighting style, use `--highlight-style`.-For more information on highlighting, see [Syntax highlighting],-below.--Line blocks--------------#### Extension: `line_blocks` ####--A line block is a sequence of lines beginning with a vertical bar (`|`)-followed by a space.  The division into lines will be preserved in-the output, as will any leading spaces; otherwise, the lines will-be formatted as Markdown.  This is useful for verse and addresses:--    | The limerick packs laughs anatomical-    | In space that is quite economical.-    |    But the good ones I've seen-    |    So seldom are clean-    | And the clean ones so seldom are comical--    | 200 Main St.-    | Berkeley, CA 94718--The lines can be hard-wrapped if needed, but the continuation-line must begin with a space.--    | The Right Honorable Most Venerable and Righteous Samuel L.-      Constable, Jr.-    | 200 Main St.-    | Berkeley, CA 94718--This syntax is borrowed from [reStructuredText].--Lists--------### Bullet lists ###--A bullet list is a list of bulleted list items.  A bulleted list-item begins with a bullet (`*`, `+`, or `-`).  Here is a simple-example:--    * one-    * two-    * three--This will produce a "compact" list. If you want a "loose" list, in which-each item is formatted as a paragraph, put spaces between the items:--    * one--    * two--    * three--The bullets need not be flush with the left margin; they may be-indented one, two, or three spaces. The bullet must be followed-by whitespace.--List items look best if subsequent lines are flush with the first-line (after the bullet):--    * here is my first-      list item.-    * and my second.--But Markdown also allows a "lazy" format:--    * here is my first-    list item.-    * and my second.--### The four-space rule ###--A list item may contain multiple paragraphs and other block-level-content. However, subsequent paragraphs must be preceded by a blank line-and indented four spaces or a tab. The list will look better if the first-paragraph is aligned with the rest:--      * First paragraph.--        Continued.--      * Second paragraph. With a code block, which must be indented-        eight spaces:--            { code }--List items may include other lists.  In this case the preceding blank-line is optional.  The nested list must be indented four spaces or-one tab:--    * fruits-        + apples-            - macintosh-            - red delicious-        + pears-        + peaches-    * vegetables-        + broccoli-        + chard--As noted above, Markdown allows you to write list items "lazily," instead of-indenting continuation lines. However, if there are multiple paragraphs or-other blocks in a list item, the first line of each must be indented.--    + A lazy, lazy, list-    item.--    + Another one; this looks-    bad but is legal.--        Second paragraph of second-    list item.--**Note:**  Although the four-space rule for continuation paragraphs-comes from the official [Markdown syntax guide], the reference implementation,-`Markdown.pl`, does not follow it. So pandoc will give different results than-`Markdown.pl` when authors have indented continuation paragraphs fewer than-four spaces.--The [Markdown syntax guide] is not explicit whether the four-space-rule applies to *all* block-level content in a list item; it only-mentions paragraphs and code blocks.  But it implies that the rule-applies to all block-level content (including nested lists), and-pandoc interprets it that way.--  [Markdown syntax guide]:-    http://daringfireball.net/projects/markdown/syntax#list--### Ordered lists ###--Ordered lists work just like bulleted lists, except that the items-begin with enumerators rather than bullets.--In standard Markdown, enumerators are decimal numbers followed-by a period and a space.  The numbers themselves are ignored, so-there is no difference between this list:--    1.  one-    2.  two-    3.  three--and this one:--    5.  one-    7.  two-    1.  three--#### Extension: `fancy_lists` ####--Unlike standard Markdown, pandoc allows ordered list items to be marked-with uppercase and lowercase letters and roman numerals, in addition to-Arabic numerals. List markers may be enclosed in parentheses or followed by a-single right-parentheses or period. They must be separated from the-text that follows by at least one space, and, if the list marker is a-capital letter with a period, by at least two spaces.[^2]--[^2]:  The point of this rule is to ensure that normal paragraphs-    starting with people's initials, like--        B. Russell was an English philosopher.--    do not get treated as list items.--    This rule will not prevent--        (C) 2007 Joe Smith--    from being interpreted as a list item.  In this case, a backslash-    escape can be used:--        (C\) 2007 Joe Smith--The `fancy_lists` extension also allows '`#`' to be used as an-ordered list marker in place of a numeral:--    #. one-    #. two--#### Extension: `startnum` ####--Pandoc also pays attention to the type of list marker used, and to the-starting number, and both of these are preserved where possible in the-output format. Thus, the following yields a list with numbers followed-by a single parenthesis, starting with 9, and a sublist with lowercase-roman numerals:--     9)  Ninth-    10)  Tenth-    11)  Eleventh-           i. subone-          ii. subtwo-         iii. subthree--Pandoc will start a new list each time a different type of list-marker is used.  So, the following will create three lists:--    (2) Two-    (5) Three-    1.  Four-    *   Five--If default list markers are desired, use `#.`:--    #.  one-    #.  two-    #.  three---### Definition lists ###--#### Extension: `definition_lists` ####--Pandoc supports definition lists, using the syntax of-[PHP Markdown Extra] with some extensions.[^3]--    Term 1--    :   Definition 1--    Term 2 with *inline markup*--    :   Definition 2--            { some code, part of Definition 2 }--        Third paragraph of definition 2.--Each term must fit on one line, which may optionally be followed by-a blank line, and must be followed by one or more definitions.-A definition begins with a colon or tilde, which may be indented one-or two spaces.--A term may have multiple definitions, and each definition may consist of one or-more block elements (paragraph, code block, list, etc.), each indented four-spaces or one tab stop.  The body of the definition (including the first line,-aside from the colon or tilde) should be indented four spaces. However,-as with other Markdown lists, you can "lazily" omit indentation except-at the beginning of a paragraph or other block element:--    Term 1--    :   Definition-    with lazy continuation.--        Second paragraph of the definition.--If you leave space before the definition (as in the example above),-the text of the definition will be treated as a paragraph.  In some-output formats, this will mean greater spacing between term/definition-pairs. For a more compact definition list, omit the space before the-definition:--    Term 1-      ~ Definition 1--    Term 2-      ~ Definition 2a-      ~ Definition 2b--Note that space between items in a definition list is required.-(A variant that loosens this requirement, but disallows "lazy"-hard wrapping, can be activated with `compact_definition_lists`: see-[Non-pandoc extensions], below.)--[^3]:  I have been influenced by the suggestions of [David Wheeler](http://www.justatheory.com/computers/markup/modest-markdown-proposal.html).--### Numbered example lists ###--#### Extension: `example_lists` ####--The special list marker `@` can be used for sequentially numbered-examples. The first list item with a `@` marker will be numbered '1',-the next '2', and so on, throughout the document. The numbered examples-need not occur in a single list; each new list using `@` will take up-where the last stopped. So, for example:--    (@)  My first example will be numbered (1).-    (@)  My second example will be numbered (2).--    Explanation of examples.--    (@)  My third example will be numbered (3).--Numbered examples can be labeled and referred to elsewhere in the-document:--    (@good)  This is a good example.--    As (@good) illustrates, ...--The label can be any string of alphanumeric characters, underscores,-or hyphens.---### Compact and loose lists ###--Pandoc behaves differently from `Markdown.pl` on some "edge-cases" involving lists.  Consider this source:--    +   First-    +   Second:-    	-   Fee-    	-   Fie-    	-   Foe--    +   Third--Pandoc transforms this into a "compact list" (with no `<p>` tags around-"First", "Second", or "Third"), while Markdown puts `<p>` tags around-"Second" and "Third" (but not "First"), because of the blank space-around "Third". Pandoc follows a simple rule: if the text is followed by-a blank line, it is treated as a paragraph. Since "Second" is followed-by a list, and not a blank line, it isn't treated as a paragraph. The-fact that the list is followed by a blank line is irrelevant. (Note:-Pandoc works this way even when the `markdown_strict` format is specified. This-behavior is consistent with the official Markdown syntax description,-even though it is different from that of `Markdown.pl`.)---### Ending a list ###--What if you want to put an indented code block after a list?--    -   item one-    -   item two--        { my code block }--Trouble! Here pandoc (like other Markdown implementations) will treat-`{ my code block }` as the second paragraph of item two, and not as-a code block.--To "cut off" the list after item two, you can insert some non-indented-content, like an HTML comment, which won't produce visible output in-any format:--    -   item one-    -   item two--    <!-- end of list -->--        { my code block }--You can use the same trick if you want two consecutive lists instead-of one big list:--    1.  one-    2.  two-    3.  three--    <!-- -->--    1.  uno-    2.  dos-    3.  tres--Horizontal rules-------------------A line containing a row of three or more `*`, `-`, or `_` characters-(optionally separated by spaces) produces a horizontal rule:--    *  *  *  *--    ------------------Tables---------Four kinds of tables may be used. The first three kinds presuppose the use of-a fixed-width font, such as Courier. The fourth kind can be used with-proportionally spaced fonts, as it does not require lining up columns.--#### Extension: `table_captions` ####--A caption may optionally be provided with all 4 kinds of tables (as-illustrated in the examples below). A caption is a paragraph beginning-with the string `Table:` (or just `:`), which will be stripped off.-It may appear either before or after the table.--#### Extension: `simple_tables` ####--Simple tables look like this:--      Right     Left     Center     Default-    -------     ------ ----------   --------         12     12        12            12-        123     123       123          123-          1     1          1             1--    Table:  Demonstration of simple table syntax.--The headers and table rows must each fit on one line.  Column-alignments are determined by the position of the header text relative-to the dashed line below it:[^4]--  - If the dashed line is flush with the header text on the right side-    but extends beyond it on the left, the column is right-aligned.-  - If the dashed line is flush with the header text on the left side-    but extends beyond it on the right, the column is left-aligned.-  - If the dashed line extends beyond the header text on both sides,-    the column is centered.-  - If the dashed line is flush with the header text on both sides,-    the default alignment is used (in most cases, this will be left).--[^4]:  This scheme is due to Michel Fortin, who proposed it on the-       [Markdown discussion list](http://six.pairlist.net/pipermail/markdown-discuss/2005-March/001097.html).--The table must end with a blank line, or a line of dashes followed by-a blank line.--The column headers may be omitted, provided a dashed line is used-to end the table. For example:--    -------     ------ ----------   --------         12     12        12             12-        123     123       123           123-          1     1          1              1-    -------     ------ ----------   ---------When headers are omitted, column alignments are determined on the basis-of the first line of the table body. So, in the tables above, the columns-would be right, left, center, and right aligned, respectively.--#### Extension: `multiline_tables` ####--Multiline tables allow headers and table rows to span multiple lines-of text (but cells that span multiple columns or rows of the table are-not supported).  Here is an example:--    --------------------------------------------------------------     Centered   Default           Right Left-      Header    Aligned         Aligned Aligned-    ----------- ------- --------------- --------------------------       First    row                12.0 Example of a row that-                                        spans multiple lines.--      Second    row                 5.0 Here's another one. Note-                                        the blank line between-                                        rows.-    ---------------------------------------------------------------    Table: Here's the caption. It, too, may span-    multiple lines.--These work like simple tables, but with the following differences:--  - They must begin with a row of dashes, before the header text-    (unless the headers are omitted).-  - They must end with a row of dashes, then a blank line.-  - The rows must be separated by blank lines.--In multiline tables, the table parser pays attention to the widths of-the columns, and the writers try to reproduce these relative widths in-the output. So, if you find that one of the columns is too narrow in the-output, try widening it in the Markdown source.--Headers may be omitted in multiline tables as well as simple tables:--    ----------- ------- --------------- --------------------------       First    row                12.0 Example of a row that-                                        spans multiple lines.--      Second    row                 5.0 Here's another one. Note-                                        the blank line between-                                        rows.-    ----------- ------- --------------- ---------------------------    : Here's a multiline table without headers.--It is possible for a multiline table to have just one row, but the row-should be followed by a blank line (and then the row of dashes that ends-the table), or the table may be interpreted as a simple table.--#### Extension: `grid_tables` ####--Grid tables look like this:--    : Sample grid table.--    +---------------+---------------+--------------------+-    | Fruit         | Price         | Advantages         |-    +===============+===============+====================+-    | Bananas       | $1.34         | - built-in wrapper |-    |               |               | - bright color     |-    +---------------+---------------+--------------------+-    | Oranges       | $2.10         | - cures scurvy     |-    |               |               | - tasty            |-    +---------------+---------------+--------------------+--The row of `=`s separates the header from the table body, and can be-omitted for a headerless table. The cells of grid tables may contain-arbitrary block elements (multiple paragraphs, code blocks, lists,-etc.). Cells that span multiple columns or rows are not-supported. Grid tables can be created easily using [Emacs table mode].--[Emacs table mode]: http://table.sourceforge.net/--Alignments can be specified as with pipe tables, by putting-colons at the boundaries of the separator line after the-header:--    +---------------+---------------+--------------------+-    | Right         | Left          | Centered           |-    +==============:+:==============+:==================:+-    | Bananas       | $1.34         | built-in wrapper   |-    +---------------+---------------+--------------------+--For headerless tables, the colons go on the top line instead:--    +--------------:+:--------------+:------------------:+-    | Right         | Left          | Centered           |-    +---------------+---------------+--------------------+---#### Extension: `pipe_tables` ####--Pipe tables look like this:--    | Right | Left | Default | Center |-    |------:|:-----|---------|:------:|-    |   12  |  12  |    12   |    12  |-    |  123  |  123 |   123   |   123  |-    |    1  |    1 |     1   |     1  |--      : Demonstration of pipe table syntax.--The syntax is identical to [PHP Markdown Extra tables].  The beginning and-ending pipe characters are optional, but pipes are required between all-columns.  The colons indicate column alignment as shown.  The header-cannot be omitted.  To simulate a headerless table, include a header-with blank cells.--Since the pipes indicate column boundaries, columns need not be vertically-aligned, as they are in the above example.  So, this is a perfectly-legal (though ugly) pipe table:--    fruit| price-    -----|-----:-    apple|2.05-    pear|1.37-    orange|3.09--The cells of pipe tables cannot contain block elements like paragraphs-and lists, and cannot span multiple lines.  If a pipe table contains a-row whose printable content is wider than the column width (see-`--columns`), then the cell contents will wrap, with the-relative cell widths determined by the widths of the separator-lines.--Note:  pandoc also recognizes pipe tables of the following-form, as can be produced by Emacs' orgtbl-mode:--    | One | Two   |-    |-----+-------|-    | my  | table |-    | is  | nice  |--The difference is that `+` is used instead of `|`. Other orgtbl features-are not supported. In particular, to get non-default column alignment,-you'll need to add colons as above.--[PHP Markdown Extra tables]: https://michelf.ca/projects/php-markdown/extra/#table--Metadata blocks------------------#### Extension: `pandoc_title_block` ####--If the file begins with a title block--    % title-    % author(s) (separated by semicolons)-    % date--it will be parsed as bibliographic information, not regular text.  (It-will be used, for example, in the title of standalone LaTeX or HTML-output.)  The block may contain just a title, a title and an author,-or all three elements. If you want to include an author but no-title, or a title and a date but no author, you need a blank line:--    %-    % Author--    % My title-    %-    % June 15, 2006--The title may occupy multiple lines, but continuation lines must-begin with leading space, thus:--    % My title-      on multiple lines--If a document has multiple authors, the authors may be put on-separate lines with leading space, or separated by semicolons, or-both.  So, all of the following are equivalent:--    % Author One-      Author Two--    % Author One; Author Two--    % Author One;-      Author Two--The date must fit on one line.--All three metadata fields may contain standard inline formatting-(italics, links, footnotes, etc.).--Title blocks will always be parsed, but they will affect the output only-when the `--standalone` (`-s`) option is chosen. In HTML output, titles-will appear twice: once in the document head -- this is the title that-will appear at the top of the window in a browser -- and once at the-beginning of the document body. The title in the document head can have-an optional prefix attached (`--title-prefix` or `-T` option). The title-in the body appears as an H1 element with class "title", so it can be-suppressed or reformatted with CSS. If a title prefix is specified with-`-T` and no title block appears in the document, the title prefix will-be used by itself as the HTML title.--The man page writer extracts a title, man page section number, and-other header and footer information from the title line. The title-is assumed to be the first word on the title line, which may optionally-end with a (single-digit) section number in parentheses. (There should-be no space between the title and the parentheses.)  Anything after-this is assumed to be additional footer and header text. A single pipe-character (`|`) should be used to separate the footer text from the header-text.  Thus,--    % PANDOC(1)--will yield a man page with the title `PANDOC` and section 1.--    % PANDOC(1) Pandoc User Manuals--will also have "Pandoc User Manuals" in the footer.--    % PANDOC(1) Pandoc User Manuals | Version 4.0--will also have "Version 4.0" in the header.--#### Extension: `yaml_metadata_block` ####--A YAML metadata block is a valid YAML object, delimited by a line of three-hyphens (`---`) at the top and a line of three hyphens (`---`) or three dots-(`...`) at the bottom.  A YAML metadata block may occur anywhere in the-document, but if it is not at the beginning, it must be preceded by a blank-line.  (Note that, because of the way pandoc concatenates input files when-several are provided, you may also keep the metadata in a separate YAML file-and pass it to pandoc as an argument, along with your Markdown files:--    pandoc chap1.md chap2.md chap3.md metadata.yaml -s -o book.html--Just be sure that the YAML file begins with `---` and ends with `---` or-`...`.)--Metadata will be taken from the fields of the YAML object and added to any-existing document metadata.  Metadata can contain lists and objects (nested-arbitrarily), but all string scalars will be interpreted as Markdown.  Fields-with names ending in an underscore will be ignored by pandoc.  (They may be-given a role by external processors.)--A document may contain multiple metadata blocks.  The metadata fields will-be combined through a *left-biased union*:  if two metadata blocks attempt-to set the same field, the value from the first block will be taken.--When pandoc is used with `-t markdown` to create a Markdown document,-a YAML metadata block will be produced only if the `-s/--standalone`-option is used.  All of the metadata will appear in a single block-at the beginning of the document.--Note that YAML escaping rules must be followed. Thus, for example,-if a title contains a colon, it must be quoted.  The pipe character-(`|`) can be used to begin an indented block that will be interpreted-literally, without need for escaping.  This form is necessary-when the field contains blank lines:--    ----    title:  'This is the title: it contains a colon'-    author:-    - Author One-    - Author Two-    tags: [nothing, nothingness]-    abstract: |-      This is the abstract.--      It consists of two paragraphs.-    ...--Template variables will be set automatically from the metadata.  Thus, for-example, in writing HTML, the variable `abstract` will be set to the HTML-equivalent of the Markdown in the `abstract` field:--    <p>This is the abstract.</p>-    <p>It consists of two paragraphs.</p>--Variables can contain arbitrary YAML structures, but the template must match-this structure.  The `author` variable in the default templates expects a-simple list or string, but can be changed to support more complicated-structures.  The following combination, for example, would add an affiliation-to the author if one is given:--    ----    title: The document title-    author:-    - name: Author One-      affiliation: University of Somewhere-    - name: Author Two-      affiliation: University of Nowhere-    ...--To use the structured authors in the example above, you would need a custom-template:--    $for(author)$-    $if(author.name)$-    $author.name$$if(author.affiliation)$ ($author.affiliation$)$endif$-    $else$-    $author$-    $endif$-    $endfor$---Backslash escapes--------------------#### Extension: `all_symbols_escapable` ####--Except inside a code block or inline code, any punctuation or space-character preceded by a backslash will be treated literally, even if it-would normally indicate formatting.  Thus, for example, if one writes--    *\*hello\**--one will get--    <em>*hello*</em>--instead of--    <strong>hello</strong>--This rule is easier to remember than standard Markdown's rule,-which allows only the following characters to be backslash-escaped:--    \`*_{}[]()>#+-.!--(However, if the `markdown_strict` format is used, the standard Markdown rule-will be used.)--A backslash-escaped space is parsed as a nonbreaking space.  It will-appear in TeX output as `~` and in HTML and XML as `\&#160;` or-`\&nbsp;`.--A backslash-escaped newline (i.e. a backslash occurring at the end of-a line) is parsed as a hard line break.  It will appear in TeX output as-`\\` and in HTML as `<br />`.  This is a nice alternative to-Markdown's "invisible" way of indicating hard line breaks using-two trailing spaces on a line.--Backslash escapes do not work in verbatim contexts.--Smart punctuation--------------------#### Extension ####--If the `--smart` option is specified, pandoc will produce typographically-correct output, converting straight quotes to curly quotes, `---` to-em-dashes, `--` to en-dashes, and `...` to ellipses. Nonbreaking spaces-are inserted after certain abbreviations, such as "Mr."--Note:  if your LaTeX template or any included header file call for the-[`csquotes`] package, pandoc will detect this automatically and use-`\enquote{...}` for quoted text.--Inline formatting--------------------### Emphasis ###--To *emphasize* some text, surround it with `*`s or `_`, like this:--    This text is _emphasized with underscores_, and this-    is *emphasized with asterisks*.--Double `*` or `_` produces **strong emphasis**:--    This is **strong emphasis** and __with underscores__.--A `*` or `_` character surrounded by spaces, or backslash-escaped,-will not trigger emphasis:--    This is * not emphasized *, and \*neither is this\*.--#### Extension: `intraword_underscores` ####--Because `_` is sometimes used inside words and identifiers,-pandoc does not interpret a `_` surrounded by alphanumeric-characters as an emphasis marker.  If you want to emphasize-just part of a word, use `*`:--    feas*ible*, not feas*able*.---### Strikeout ###--#### Extension: `strikeout` ####--To strikeout a section of text with a horizontal line, begin and end it-with `~~`. Thus, for example,--    This ~~is deleted text.~~---### Superscripts and subscripts ###--#### Extension: `superscript`, `subscript` ####--Superscripts may be written by surrounding the superscripted text by `^`-characters; subscripts may be written by surrounding the subscripted-text by `~` characters.  Thus, for example,--    H~2~O is a liquid.  2^10^ is 1024.--If the superscripted or subscripted text contains spaces, these spaces-must be escaped with backslashes.  (This is to prevent accidental-superscripting and subscripting through the ordinary use of `~` and `^`.)-Thus, if you want the letter P with 'a cat' in subscripts, use-`P~a\ cat~`, not `P~a cat~`.---### Verbatim ###--To make a short span of text verbatim, put it inside backticks:--    What is the difference between `>>=` and `>>`?--If the verbatim text includes a backtick, use double backticks:--    Here is a literal backtick `` ` ``.--(The spaces after the opening backticks and before the closing-backticks will be ignored.)--The general rule is that a verbatim span starts with a string-of consecutive backticks (optionally followed by a space)-and ends with a string of the same number of backticks (optionally-preceded by a space).--Note that backslash-escapes (and other Markdown constructs) do not-work in verbatim contexts:--    This is a backslash followed by an asterisk: `\*`.--#### Extension: `inline_code_attributes` ####--Attributes can be attached to verbatim text, just as with-[fenced code blocks]:--    `<$>`{.haskell}--### Small caps ###--To write small caps, you can use an HTML span tag:--    <span style="font-variant:small-caps;">Small caps</span>--(The semicolon is optional and there may be space after the-colon.) This will work in all output formats that support small caps.--Alternatively, you can also use the new `bracketed_spans` syntax:--    [Small caps]{style="font-variant:small-caps;"}--Math-------#### Extension: `tex_math_dollars` ####--Anything between two `$` characters will be treated as TeX math.  The-opening `$` must have a non-space character immediately to its right,-while the closing `$` must have a non-space character immediately to its-left, and must not be followed immediately by a digit.  Thus,-`$20,000 and $30,000` won't parse as math.  If for some reason-you need to enclose text in literal `$` characters, backslash-escape-them and they won't be treated as math delimiters.--TeX math will be printed in all output formats. How it is rendered-depends on the output format:--Markdown, LaTeX, Emacs Org mode, ConTeXt, ZimWiki-  ~ It will appear verbatim between `$` characters.--reStructuredText-  ~ It will be rendered using an [interpreted text role `:math:`].--AsciiDoc-  ~ It will be rendered as `latexmath:[...]`.--Texinfo-  ~ It will be rendered inside a `@math` command.--groff man-  ~ It will be rendered verbatim without `$`'s.--MediaWiki, DokuWiki-  ~ It will be rendered inside `<math>` tags.--Textile-  ~ It will be rendered inside `<span class="math">` tags.--RTF, OpenDocument, ODT-  ~ It will be rendered, if possible, using Unicode characters,-    and will otherwise appear verbatim.--DocBook-  ~ If the `--mathml` flag is used, it will be rendered using MathML-    in an `inlineequation` or `informalequation` tag.  Otherwise it-    will be rendered, if possible, using Unicode characters.--Docx-  ~ It will be rendered using OMML math markup.--FictionBook2-  ~ If the `--webtex` option is used, formulas are rendered as images-    using CodeCogs or other compatible web service, downloaded-    and embedded in the e-book. Otherwise, they will appear verbatim.--HTML, Slidy, DZSlides, S5, EPUB-  ~ The way math is rendered in HTML will depend on the-    command-line options selected:--    1.  The default is to render TeX math as far as possible using Unicode-        characters, as with RTF, DocBook, and OpenDocument output. Formulas-        are put inside a `span` with `class="math"`, so that they may be-        styled differently from the surrounding text if needed.--    2.  If the `--latexmathml` option is used, TeX math will be displayed-        between `$` or `$$` characters and put in `<span>` tags with class `LaTeX`.-        The [LaTeXMathML] script will be used to render it as formulas.-        (This trick does not work in all browsers, but it works in Firefox.-        In browsers that do not support LaTeXMathML, TeX math will appear-        verbatim between `$` characters.)--    3.  If the `--jsmath` option is used, TeX math will be put inside-        `<span>` tags (for inline math) or `<div>` tags (for display math)-        with class `math`.  The [jsMath] script will be used to render-        it.--    4.  If the `--mimetex` option is used, the [mimeTeX] CGI script will-        be called to generate images for each TeX formula. This should-        work in all browsers. The `--mimetex` option takes an optional URL-        as argument. If no URL is specified, it will be assumed that the-        mimeTeX CGI script is at `/cgi-bin/mimetex.cgi`.--    5.  If the `--gladtex` option is used, TeX formulas will be enclosed-        in `<eq>` tags in the HTML output.  The resulting `htex` file may then-        be processed by [gladTeX], which will produce image files for each-        formula and an HTML file with links to these images.  So, the-        procedure is:--            pandoc -s --gladtex myfile.txt -o myfile.htex-            gladtex -d myfile-images myfile.htex-            # produces myfile.html and images in myfile-images--    6.  If the `--webtex` option is used, TeX formulas will be converted-        to `<img>` tags that link to an external script that converts-        formulas to images. The formula will be URL-encoded and concatenated-        with the URL provided. If no URL is specified, the CodeCogs-        will be used (`https://latex.codecogs.com/png.latex?`).--    7.  If the `--mathjax` option is used, TeX math will be displayed-        between `\(...\)` (for inline math) or `\[...\]` (for display-        math) and put in `<span>` tags with class `math`.-        The [MathJax] script will be used to render it as formulas.--[interpreted text role `:math:`]: http://docutils.sourceforge.net/docs/ref/rst/roles.html#math--Raw HTML-----------#### Extension: `raw_html` ####--Markdown allows you to insert raw HTML (or DocBook) anywhere in a document-(except verbatim contexts, where `<`, `>`, and `&` are interpreted-literally).  (Technically this is not an extension, since standard-Markdown allows it, but it has been made an extension so that it can-be disabled if desired.)--The raw HTML is passed through unchanged in HTML, S5, Slidy, Slideous,-DZSlides, EPUB, Markdown, Emacs Org mode, and Textile output, and suppressed-in other formats.--#### Extension: `markdown_in_html_blocks` ####--Standard Markdown allows you to include HTML "blocks":  blocks-of HTML between balanced tags that are separated from the surrounding text-with blank lines, and start and end at the left margin.  Within-these blocks, everything is interpreted as HTML, not Markdown;-so (for example), `*` does not signify emphasis.--Pandoc behaves this way when the `markdown_strict` format is used; but-by default, pandoc interprets material between HTML block tags as Markdown.-Thus, for example, pandoc will turn--    <table>-    <tr>-    <td>*one*</td>-    <td>[a link](http://google.com)</td>-    </tr>-    </table>--into--    <table>-    <tr>-    <td><em>one</em></td>-    <td><a href="http://google.com">a link</a></td>-    </tr>-    </table>--whereas `Markdown.pl` will preserve it as is.--There is one exception to this rule:  text between `<script>` and-`<style>` tags is not interpreted as Markdown.--This departure from standard Markdown should make it easier to mix-Markdown with HTML block elements.  For example, one can surround-a block of Markdown text with `<div>` tags without preventing it-from being interpreted as Markdown.--#### Extension: `native_divs` ####--Use native pandoc `Div` blocks for content inside `<div>` tags.-For the most part this should give the same output as-`markdown_in_html_blocks`, but it makes it easier to write pandoc-filters to manipulate groups of blocks.--#### Extension: `native_spans` ####--Use native pandoc `Span` blocks for content inside `<span>` tags.-For the most part this should give the same output as `raw_html`,-but it makes it easier to write pandoc filters to manipulate groups-of inlines.--Raw TeX----------#### Extension: `raw_tex` ####--In addition to raw HTML, pandoc allows raw LaTeX, TeX, and ConTeXt to be-included in a document. Inline TeX commands will be preserved and passed-unchanged to the LaTeX and ConTeXt writers. Thus, for example, you can use-LaTeX to include BibTeX citations:--    This result was proved in \cite{jones.1967}.--Note that in LaTeX environments, like--    \begin{tabular}{|l|l|}\hline-    Age & Frequency \\ \hline-    18--25  & 15 \\-    26--35  & 33 \\-    36--45  & 22 \\ \hline-    \end{tabular}--the material between the begin and end tags will be interpreted as raw-LaTeX, not as Markdown.--Inline LaTeX is ignored in output formats other than Markdown, LaTeX,-Emacs Org mode, and ConTeXt.--LaTeX macros---------------#### Extension: `latex_macros` ####--For output formats other than LaTeX, pandoc will parse LaTeX `\newcommand` and-`\renewcommand` definitions and apply the resulting macros to all LaTeX-math.  So, for example, the following will work in all output formats,-not just LaTeX:--    \newcommand{\tuple}[1]{\langle #1 \rangle}--    $\tuple{a, b, c}$--In LaTeX output, the `\newcommand` definition will simply be passed-unchanged to the output.---Links--------Markdown allows links to be specified in several ways.--### Automatic links ###--If you enclose a URL or email address in pointy brackets, it-will become a link:--    <http://google.com>-    <sam@green.eggs.ham>--### Inline links ###--An inline link consists of the link text in square brackets,-followed by the URL in parentheses. (Optionally, the URL can-be followed by a link title, in quotes.)--    This is an [inline link](/url), and here's [one with-    a title](http://fsf.org "click here for a good time!").--There can be no space between the bracketed part and the parenthesized part.-The link text can contain formatting (such as emphasis), but the title cannot.--Email addresses in inline links are not autodetected, so they have to be-prefixed with `mailto`:--    [Write me!](mailto:sam@green.eggs.ham)--### Reference links ###--An *explicit* reference link has two parts, the link itself and the link-definition, which may occur elsewhere in the document (either-before or after the link).--The link consists of link text in square brackets, followed by a label in-square brackets. (There can be space between the two.) The link definition-consists of the bracketed label, followed by a colon and a space, followed by-the URL, and optionally (after a space) a link title either in quotes or in-parentheses.  The label must not be parseable as a citation (assuming-the `citations` extension is enabled):  citations take precedence over-link labels.--Here are some examples:--    [my label 1]: /foo/bar.html  "My title, optional"-    [my label 2]: /foo-    [my label 3]: http://fsf.org (The free software foundation)-    [my label 4]: /bar#special  'A title in single quotes'--The URL may optionally be surrounded by angle brackets:--    [my label 5]: <http://foo.bar.baz>--The title may go on the next line:--    [my label 3]: http://fsf.org-      "The free software foundation"--Note that link labels are not case sensitive.  So, this will work:--    Here is [my link][FOO]--    [Foo]: /bar/baz--In an *implicit* reference link, the second pair of brackets is-empty:--    See [my website][].--    [my website]: http://foo.bar.baz--Note:  In `Markdown.pl` and most other Markdown implementations,-reference link definitions cannot occur in nested constructions-such as list items or block quotes.  Pandoc lifts this arbitrary-seeming restriction.  So the following is fine in pandoc, though-not in most other implementations:--    > My block [quote].-    >-    > [quote]: /foo--#### Extension: `shortcut_reference_links` ####--In a *shortcut* reference link, the second pair of brackets may-be omitted entirely:--    See [my website].--    [my website]: http://foo.bar.baz--### Internal links ###--To link to another section of the same document, use the automatically-generated identifier (see [Header identifiers]). For example:--    See the [Introduction](#introduction).--or--    See the [Introduction].--    [Introduction]: #introduction--Internal links are currently supported for HTML formats (including-HTML slide shows and EPUB), LaTeX, and ConTeXt.--Images---------A link immediately preceded by a `!` will be treated as an image.-The link text will be used as the image's alt text:--    ![la lune](lalune.jpg "Voyage to the moon")--    ![movie reel]--    [movie reel]: movie.gif--#### Extension: `implicit_figures` ####--An image occurring by itself in a paragraph will be rendered as-a figure with a caption.[^5] (In LaTeX, a figure environment will be-used; in HTML, the image will be placed in a `div` with class-`figure`, together with a caption in a `p` with class `caption`.)-The image's alt text will be used as the caption.--    ![This is the caption](/url/of/image.png)--[^5]: This feature is not yet implemented for RTF, OpenDocument, or-    ODT. In those formats, you'll just get an image in a paragraph by-    itself, with no caption.--If you just want a regular inline image, just make sure it is not-the only thing in the paragraph. One way to do this is to insert a-nonbreaking space after the image:--    ![This image won't be a figure](/url/of/image.png)\ --#### Extension: `link_attributes` ####--Attributes can be set on links and images:--    An inline ![image](foo.jpg){#id .class width=30 height=20px}-    and a reference ![image][ref] with attributes.--    [ref]: foo.jpg "optional title" {#id .class key=val key2="val 2"}--(This syntax is compatible with [PHP Markdown Extra] when only `#id`-and `.class` are used.)--For HTML and EPUB, all attributes except `width` and `height` (but-including `srcset` and `sizes`) are passed through as is. The other-writers ignore attributes that are not supported by their output-format.--The `width` and `height` attributes on images are treated specially. When-used without a unit, the unit is assumed to be pixels. However, any of-the following unit identifiers can be used: `px`, `cm`, `mm`, `in`, `inch`-and `%`. There must not be any spaces between the number and the unit.-For example:--```-![](file.jpg){ width=50% }-```--- Dimensions are converted to inches for output in page-based formats like-  LaTeX. Dimensions are converted to pixels for output in HTML-like-  formats.  Use the `--dpi` option to specify the number of pixels per-  inch.  The default is 96dpi.-- The `%` unit is generally relative to some available space.-  For example the above example will render to-  `<img href="file.jpg" style="width: 50%;" />` (HTML),-  `\includegraphics[width=0.5\textwidth]{file.jpg}` (LaTeX), or-  `\externalfigure[file.jpg][width=0.5\textwidth]` (ConTeXt).-- Some output formats have a notion of a class-  ([ConTeXt](http://wiki.contextgarden.net/Using_Graphics#Multiple_Image_Settings))-  or a unique identifier (LaTeX `\caption`), or both (HTML).-- When no `width` or `height` attributes are specified, the fallback-  is to look at the image resolution and the dpi metadata embedded in-  the image file.--Spans--------#### Extension: `bracketed_spans` ####--A bracketed sequence of inlines, as one would use to begin-a link, will be treated as a span with attributes if it is-followed immediately by attributes:--    [This is *some text*]{.class key="val"}--Footnotes------------#### Extension: `footnotes` ####--Pandoc's Markdown allows footnotes, using the following syntax:--    Here is a footnote reference,[^1] and another.[^longnote]--    [^1]: Here is the footnote.--    [^longnote]: Here's one with multiple blocks.--        Subsequent paragraphs are indented to show that they-    belong to the previous footnote.--            { some.code }--        The whole paragraph can be indented, or just the first-        line.  In this way, multi-paragraph footnotes work like-        multi-paragraph list items.--    This paragraph won't be part of the note, because it-    isn't indented.--The identifiers in footnote references may not contain spaces, tabs,-or newlines.  These identifiers are used only to correlate the-footnote reference with the note itself; in the output, footnotes-will be numbered sequentially.--The footnotes themselves need not be placed at the end of the-document.  They may appear anywhere except inside other block elements-(lists, block quotes, tables, etc.).  Each footnote should be-separated from surrounding content (including other footnotes)-by blank lines.--#### Extension: `inline_notes` ####--Inline footnotes are also allowed (though, unlike regular notes,-they cannot contain multiple paragraphs).  The syntax is as follows:--    Here is an inline note.^[Inlines notes are easier to write, since-    you don't have to pick an identifier and move down to type the-    note.]--Inline and regular footnotes may be mixed freely.---Citations------------#### Extension: `citations` ####--Using an external filter, `pandoc-citeproc`, pandoc can automatically generate-citations and a bibliography in a number of styles.  Basic usage is--    pandoc --filter pandoc-citeproc myinput.txt--In order to use this feature, you will need to specify a bibliography file-using the `bibliography` metadata field in a YAML metadata section, or-`--bibliography` command line argument. You can supply multiple `--bibliography`-arguments or set `bibliography` metadata field to YAML array, if you want to-use multiple bibliography files.  The bibliography may have any of these-formats:--  Format            File extension-  ------------      ---------------  BibLaTeX          .bib-  BibTeX            .bibtex-  Copac             .copac-  CSL JSON          .json-  CSL YAML          .yaml-  EndNote           .enl-  EndNote XML       .xml-  ISI               .wos-  MEDLINE           .medline-  MODS              .mods-  RIS               .ris--Note that `.bib` can be used with both BibTeX and BibLaTeX files;-use `.bibtex` to force BibTeX.--Note that `pandoc-citeproc --bib2json` and `pandoc-citeproc --bib2yaml`-can produce `.json` and `.yaml` files from any of the supported formats.--In-field markup: In BibTeX and BibLaTeX databases, pandoc-citeproc parses-a subset of LaTeX markup; in CSL YAML databases, pandoc Markdown; and in CSL JSON databases, an [HTML-like markup][CSL markup specs]:--`<i>...</i>`-:   italics--`<b>...</b>`-:   bold--`<span style="font-variant:small-caps;">...</span>` or `<sc>...</sc>`-:   small capitals--`<sub>...</sub>`-:   subscript--`<sup>...</sup>`-:   superscript--`<span class="nocase">...</span>`-:   prevent a phrase from being capitalized as title case--`pandoc-citeproc -j` and `-y` interconvert the CSL JSON-and CSL YAML formats as far as possible.--As an alternative to specifying a bibliography file using `--bibliography`-or the YAML metadata field `bibliography`, you can include-the citation data directly in the `references` field of the-document's YAML metadata. The field should contain an array of-YAML-encoded references, for example:--    ----    references:-    - type: article-journal-      id: WatsonCrick1953-      author:-      - family: Watson-        given: J. D.-      - family: Crick-        given: F. H. C.-      issued:-        date-parts:-        - - 1953-          - 4-          - 25-      title: 'Molecular structure of nucleic acids: a structure for deoxyribose-        nucleic acid'-      title-short: Molecular structure of nucleic acids-      container-title: Nature-      volume: 171-      issue: 4356-      page: 737-738-      DOI: 10.1038/171737a0-      URL: http://www.nature.com/nature/journal/v171/n4356/abs/171737a0.html-      language: en-GB-    ...--(`pandoc-citeproc --bib2yaml` can produce these from a bibliography file in one-of the supported formats.)--Citations and references can be formatted using any style supported by the-[Citation Style Language], listed in the [Zotero Style Repository].-These files are specified using the `--csl` option or the `csl` metadata field.-By default, `pandoc-citeproc` will use the [Chicago Manual of Style] author-date-format.  The CSL project provides further information on [finding and editing styles].--To make your citations hyperlinks to the corresponding bibliography-entries, add `link-citations: true` to your YAML metadata.--Citations go inside square brackets and are separated by semicolons.-Each citation must have a key, composed of '@' + the citation-identifier from the database, and may optionally have a prefix,-a locator, and a suffix.  The citation key must begin with a letter, digit,-or `_`, and may contain alphanumerics, `_`, and internal punctuation-characters (`:.#$%&-+?<>~/`).  Here are some examples:--    Blah blah [see @doe99, pp. 33-35; also @smith04, chap. 1].--    Blah blah [@doe99, pp. 33-35, 38-39 and *passim*].--    Blah blah [@smith04; @doe99].--`pandoc-citeproc` detects locator terms in the [CSL locale files].-Either abbreviated or unabbreviated forms are accepted. In the `en-US`-locale, locator terms can be written in either singular or plural forms,-as `book`, `bk.`/`bks.`; `chapter`, `chap.`/`chaps.`; `column`,-`col.`/`cols.`; `figure`, `fig.`/`figs.`; `folio`, `fol.`/`fols.`;-`number`, `no.`/`nos.`; `line`, `l.`/`ll.`; `note`, `n.`/`nn.`; `opus`,-`op.`/`opp.`; `page`, `p.`/`pp.`; `paragraph`, `para.`/`paras.`; `part`,-`pt.`/`pts.`; `section`, `sec.`/`secs.`; `sub verbo`, `s.v.`/`s.vv.`;-`verse`, `v.`/`vv.`; `volume`, `vol.`/`vols.`; `¶`/`¶¶`; `§`/`§§`. If no-locator term is used, "page" is assumed.--A minus sign (`-`) before the `@` will suppress mention of-the author in the citation.  This can be useful when the-author is already mentioned in the text:--    Smith says blah [-@smith04].--You can also write an in-text citation, as follows:--    @smith04 says blah.--    @smith04 [p. 33] says blah.--If the style calls for a list of works cited, it will be placed-at the end of the document.  Normally, you will want to end your-document with an appropriate header:--    last paragraph...--    # References--The bibliography will be inserted after this header.  Note that-the `unnumbered` class will be added to this header, so that the-section will not be numbered.--If you want to include items in the bibliography without actually-citing them in the body text, you can define a dummy `nocite` metadata-field and put the citations there:--    ----    nocite: |-      @item1, @item2-    ...--    @item3--In this example, the document will contain a citation for `item3`-only, but the bibliography will contain entries for `item1`, `item2`, and-`item3`.--It is possible to create a bibliography with all the citations,-whether or not they appear in the document, by using a wildcard:--    ----    nocite: |-      @*-    ...--For LaTeX or PDF output, you can also use [`natbib`] or [`biblatex`]-to render bibliography. In order to do so, specify bibliography files as-outlined above, and add `--natbib` or `--biblatex` argument to `pandoc`-invocation. Bear in mind that bibliography files have to be in respective-format (either BibTeX or BibLaTeX).--For more information, see the [pandoc-citeproc man page].--[CSL markup specs]: http://docs.citationstyles.org/en/1.0/release-notes.html#rich-text-markup-within-fields-[Chicago Manual of Style]: http://chicagomanualofstyle.org-[Citation Style Language]: http://citationstyles.org-[Zotero Style Repository]: https://www.zotero.org/styles-[finding and editing styles]: http://citationstyles.org/styles/-[CSL locale files]: https://github.com/citation-style-language/locales-[pandoc-citeproc man page]: https://github.com/jgm/pandoc-citeproc/blob/master/man/pandoc-citeproc.1.md--Non-pandoc extensions------------------------The following Markdown syntax extensions are not enabled by default-in pandoc, but may be enabled by adding `+EXTENSION` to the format-name, where `EXTENSION` is the name of the extension.  Thus, for-example, `markdown+hard_line_breaks` is Markdown with hard line breaks.--#### Extension: `angle_brackets_escapable` ####--Allow `<` and `>` to be backslash-escaped, as they can be in-GitHub flavored Markdown but not original Markdown.  This is-implied by pandoc's default `all_symbols_escapable`.--#### Extension: `lists_without_preceding_blankline` ####--Allow a list to occur right after a paragraph, with no intervening-blank space.--#### Extension: `hard_line_breaks` ####--Causes all newlines within a paragraph to be interpreted as hard line-breaks instead of spaces.--#### Extension: `ignore_line_breaks` ####--Causes newlines within a paragraph to be ignored, rather than being-treated as spaces or as hard line breaks.  This option is intended for-use with East Asian languages where spaces are not used between words,-but text is divided into lines for readability.--#### Extension: `east_asian_line_breaks` ####--Causes newlines within a paragraph to be ignored, rather than-being treated as spaces or as hard line breaks, when they occur-between two East Asian wide characters.  This is a better choice-than `ignore_line_breaks` for texts that include a mix of East-Asian wide characters and other characters.--##### Extension: `emoji` ####--Parses textual emojis like `:smile:` as Unicode emoticons.--#### Extension: `tex_math_single_backslash` ####--Causes anything between `\(` and `\)` to be interpreted as inline-TeX math, and anything between `\[` and `\]` to be interpreted-as display TeX math.  Note: a drawback of this extension is that-it precludes escaping `(` and `[`.--#### Extension: `tex_math_double_backslash` ####--Causes anything between `\\(` and `\\)` to be interpreted as inline-TeX math, and anything between `\\[` and `\\]` to be interpreted-as display TeX math.--#### Extension: `markdown_attribute` ####--By default, pandoc interprets material inside block-level tags as Markdown.-This extension changes the behavior so that Markdown is only parsed-inside block-level tags if the tags have the attribute `markdown=1`.--#### Extension: `mmd_title_block` ####--Enables a [MultiMarkdown] style title block at the top of-the document, for example:--    Title:   My title-    Author:  John Doe-    Date:    September 1, 2008-    Comment: This is a sample mmd title block, with-             a field spanning multiple lines.--See the MultiMarkdown documentation for details.  If `pandoc_title_block` or-`yaml_metadata_block` is enabled, it will take precedence over-`mmd_title_block`.--#### Extension: `abbreviations` ####--Parses PHP Markdown Extra abbreviation keys, like--    *[HTML]: Hypertext Markup Language--Note that the pandoc document model does not support-abbreviations, so if this extension is enabled, abbreviation keys are-simply skipped (as opposed to being parsed as paragraphs).--#### Extension: `autolink_bare_uris` ####--Makes all absolute URIs into links, even when not surrounded by-pointy braces `<...>`.--#### Extension: `ascii_identifiers` ####--Causes the identifiers produced by `auto_identifiers` to be pure ASCII.-Accents are stripped off of accented Latin letters, and non-Latin-letters are omitted.--#### Extension: `mmd_link_attributes` ####--Parses multimarkdown style key-value attributes on link-and image references. This extension should not be confused with the-[`link_attributes`](#extension-link_attributes) extension.--    This is a reference ![image][ref] with multimarkdown attributes.--    [ref]: http://path.to/image "Image title" width=20px height=30px-           id=myId class="myClass1 myClass2"--#### Extension: `mmd_header_identifiers` ####--Parses multimarkdown style header identifiers (in square brackets,-after the header but before any trailing `#`s in an ATX header).--#### Extension: `compact_definition_lists` ####--Activates the definition list syntax of pandoc 1.12.x and earlier.-This syntax differs from the one described above under [Definition lists]-in several respects:--  - No blank line is required between consecutive items of the-    definition list.-  - To get a "tight" or "compact" list, omit space between consecutive-    items; the space between a term and its definition does not affect-    anything.-  - Lazy wrapping of paragraphs is not allowed:  the entire definition must-    be indented four spaces.[^6]--[^6]:  To see why laziness is incompatible with relaxing the requirement-    of a blank line between items, consider the following example:--        bar-        :    definition-        foo-        :    definition--    Is this a single list item with two definitions of "bar," the first of-    which is lazily wrapped, or two list items?  To remove the ambiguity-    we must either disallow lazy wrapping or require a blank line between-    list items.--Markdown variants--------------------In addition to pandoc's extended Markdown, the following Markdown-variants are supported:--`markdown_phpextra` (PHP Markdown Extra)-:   `footnotes`, `pipe_tables`, `raw_html`, `markdown_attribute`,-    `fenced_code_blocks`, `definition_lists`, `intraword_underscores`,-    `header_attributes`, `link_attributes`, `abbreviations`,-    `shortcut_reference_links`.--`markdown_github` (GitHub-Flavored Markdown)-:   `pipe_tables`, `raw_html`, `fenced_code_blocks`, `auto_identifiers`,-    `ascii_identifiers`, `backtick_code_blocks`, `autolink_bare_uris`,-    `intraword_underscores`, `strikeout`, `hard_line_breaks`, `emoji`,-    `shortcut_reference_links`, `angle_brackets_escapable`.--`markdown_mmd` (MultiMarkdown)-:   `pipe_tables`, `raw_html`, `markdown_attribute`, `mmd_link_attributes`,-    `tex_math_double_backslash`, `intraword_underscores`,-    `mmd_title_block`, `footnotes`, `definition_lists`,-    `all_symbols_escapable`, `implicit_header_references`,-    `auto_identifiers`, `mmd_header_identifiers`,-    `shortcut_reference_links`.--`markdown_strict` (Markdown.pl)-:   `raw_html`--Extensions with formats other than Markdown----------------------------------------------Some of the extensions discussed above can be used with formats-other than Markdown:--* `auto_identifiers` can be used with `latex`, `rst`, `mediawiki`,-  and `textile` input (and is used by default).--* `tex_math_dollars`, `tex_math_single_backslash`, and-  `tex_math_double_backslash` can be used with `html` input.-  (This is handy for reading web pages formatted using MathJax,-  for example.)--Producing slide shows with pandoc-=================================--You can use pandoc to produce an HTML + JavaScript slide presentation-that can be viewed via a web browser.  There are five ways to do this,-using [S5], [DZSlides], [Slidy], [Slideous], or [reveal.js].-You can also produce a PDF slide show using LaTeX [`beamer`].--Here's the Markdown source for a simple slide show, `habits.txt`:--    % Habits-    % John Doe-    % March 22, 2005--    # In the morning--    ## Getting up--    - Turn off alarm-    - Get out of bed--    ## Breakfast--    - Eat eggs-    - Drink coffee--    # In the evening--    ## Dinner--    - Eat spaghetti-    - Drink wine--    --------------------    ![picture of spaghetti](images/spaghetti.jpg)--    ## Going to sleep--    - Get in bed-    - Count sheep--To produce an HTML/JavaScript slide show, simply type--    pandoc -t FORMAT -s habits.txt -o habits.html--where `FORMAT` is either `s5`, `slidy`, `slideous`, `dzslides`, or `revealjs`.--For Slidy, Slideous, reveal.js, and S5, the file produced by pandoc with the-`-s/--standalone` option embeds a link to JavaScript and CSS files, which are-assumed to be available at the relative path `s5/default` (for S5), `slideous`-(for Slideous), `reveal.js` (for reveal.js), or at the Slidy website at-`w3.org` (for Slidy).  (These paths can be changed by setting the `slidy-url`,-`slideous-url`, `revealjs-url`, or `s5-url` variables; see [Variables for slides],-above.) For DZSlides, the (relatively short) JavaScript and CSS are included in-the file by default.--With all HTML slide formats, the `--self-contained` option can be used to-produce a single file that contains all of the data necessary to display the-slide show, including linked scripts, stylesheets, images, and videos.--To produce a PDF slide show using beamer, type--    pandoc -t beamer habits.txt -o habits.pdf--Note that a reveal.js slide show can also be converted to a PDF-by printing it to a file from the browser.--Structuring the slide show-----------------------------By default, the *slide level* is the highest header level in-the hierarchy that is followed immediately by content, and not another-header, somewhere in the document. In the example above, level 1 headers-are always followed by level 2 headers, which are followed by content,-so 2 is the slide level.  This default can be overridden using-the `--slide-level` option.--The document is carved up into slides according to the following-rules:--  * A horizontal rule always starts a new slide.--  * A header at the slide level always starts a new slide.--  * Headers *below* the slide level in the hierarchy create-    headers *within* a slide.--  * Headers *above* the slide level in the hierarchy create-    "title slides," which just contain the section title-    and help to break the slide show into sections.--  * A title page is constructed automatically from the document's title-    block, if present.  (In the case of beamer, this can be disabled-    by commenting out some lines in the default template.)--These rules are designed to support many different styles of slide show. If-you don't care about structuring your slides into sections and subsections,-you can just use level 1 headers for all each slide. (In that case, level 1-will be the slide level.) But you can also structure the slide show into-sections, as in the example above.--Note:  in reveal.js slide shows, if slide level is 2, a two-dimensional-layout will be produced, with level 1 headers building horizontally-and level 2 headers building vertically.  It is not recommended that-you use deeper nesting of section levels with reveal.js.--Incremental lists--------------------By default, these writers produce lists that display "all at once."-If you want your lists to display incrementally (one item at a time),-use the `-i` option. If you want a particular list to depart from the-default (that is, to display incrementally without the `-i` option and-all at once with the `-i` option), put it in a block quote:--    > - Eat spaghetti-    > - Drink wine--In this way incremental and nonincremental lists can be mixed in-a single document.--Inserting pauses-------------------You can add "pauses" within a slide by including a paragraph containing-three dots, separated by spaces:--    # Slide with a pause--    content before the pause--    . . .--    content after the pause--Styling the slides---------------------You can change the style of HTML slides by putting customized CSS files-in `$DATADIR/s5/default` (for S5), `$DATADIR/slidy` (for Slidy),-or `$DATADIR/slideous` (for Slideous),-where `$DATADIR` is the user data directory (see `--data-dir`, above).-The originals may be found in pandoc's system data directory (generally-`$CABALDIR/pandoc-VERSION/s5/default`). Pandoc will look there for any-files it does not find in the user data directory.--For dzslides, the CSS is included in the HTML file itself, and may-be modified there.--All [reveal.js configuration options] can be set through variables.-For example, themes can be used by setting the `theme` variable:--    -V theme=moon--Or you can specify a custom stylesheet using the `--css` option.--To style beamer slides, you can specify a `theme`, `colortheme`,-`fonttheme`, `innertheme`, and `outertheme`, using the `-V` option:--    pandoc -t beamer habits.txt -V theme:Warsaw -o habits.pdf--Note that header attributes will turn into slide attributes-(on a `<div>` or `<section>`) in HTML slide formats, allowing you-to style individual slides.  In beamer, the only header attribute-that affects slides is the `allowframebreaks` class, which sets the-`allowframebreaks` option, causing multiple slides to be created-if the content overfills the frame.  This is recommended especially for-bibliographies:--    # References {.allowframebreaks}--Speaker notes----------------reveal.js has good support for speaker notes.  You can add notes to your-Markdown document thus:--    <div class="notes">-    This is my note.--    - It can contain Markdown-    - like this list--    </div>--To show the notes window, press `s` while viewing the presentation.-Notes are not yet supported for other slide formats, but the notes-will not appear on the slides themselves.--Frame attributes in beamer-----------------------------Sometimes it is necessary to add the LaTeX `[fragile]` option to-a frame in beamer (for example, when using the `minted` environment).-This can be forced by adding the `fragile` class to the header-introducing the slide:--    # Fragile slide {.fragile}--All of the other frame attributes described in Section 8.1 of-the [Beamer User's Guide] may also be used: `allowdisplaybreaks`,-`allowframebreaks`, `b`, `c`, `t`, `environment`, `label`, `plain`,-`shrink`.--Creating EPUBs with pandoc-==========================--EPUB Metadata----------------EPUB metadata may be specified using the `--epub-metadata` option, but-if the source document is Markdown, it is better to use a [YAML metadata-block][Extension: `yaml_metadata_block`].  Here is an example:--    ----    title:-    - type: main-      text: My Book-    - type: subtitle-      text: An investigation of metadata-    creator:-    - role: author-      text: John Smith-    - role: editor-      text: Sarah Jones-    identifier:-    - scheme: DOI-      text: doi:10.234234.234/33-    publisher:  My Press-    rights: © 2007 John Smith, CC BY-NC-    ...--The following fields are recognized:--`identifier`-  ~ Either a string value or an object with fields `text` and-    `scheme`.  Valid values for `scheme` are `ISBN-10`,-    `GTIN-13`, `UPC`, `ISMN-10`, `DOI`, `LCCN`, `GTIN-14`,-    `ISBN-13`, `Legal deposit number`, `URN`, `OCLC`,-    `ISMN-13`, `ISBN-A`, `JP`, `OLCC`.--`title`-  ~ Either a string value, or an object with fields `file-as` and-    `type`, or a list of such objects.  Valid values for `type` are-    `main`, `subtitle`, `short`, `collection`, `edition`, `extended`.--`creator`-  ~ Either a string value, or an object with fields `role`, `file-as`,-    and `text`, or a list of such objects.  Valid values for `role` are-    [MARC relators], but-    pandoc will attempt to translate the human-readable versions-    (like "author" and "editor") to the appropriate marc relators.--`contributor`-  ~ Same format as `creator`.--`date`-  ~ A string value in `YYYY-MM-DD` format.  (Only the year is necessary.)-    Pandoc will attempt to convert other common date formats.--`lang` (or legacy: `language`)-  ~ A string value in [BCP 47] format.  Pandoc will default to the local-    language if nothing is specified.--`subject`-  ~ A string value or a list of such values.--`description`-  ~ A string value.--`type`-  ~ A string value.--`format`-  ~ A string value.--`relation`-  ~ A string value.--`coverage`-  ~ A string value.--`rights`-  ~ A string value.--`cover-image`-  ~ A string value (path to cover image).--`stylesheet`-  ~ A string value (path to CSS stylesheet).--`page-progression-direction`-  ~ Either `ltr` or `rtl`. Specifies the `page-progression-direction`-    attribute for the [`spine` element].--[MARC relators]: http://loc.gov/marc/relators/relaterm.html-[`spine` element]: http://idpf.org/epub/301/spec/epub-publications.html#sec-spine-elem--Linked media---------------By default, pandoc will download linked media (including audio and-video) and include it in the EPUB container, yielding a completely-self-contained EPUB.  If you want to link to external media resources-instead, use raw HTML in your source and add `data-external="1"` to the tag-with the `src` attribute.  For example:--    <audio controls="1">-      <source src="http://example.com/music/toccata.mp3"-              data-external="1" type="audio/mpeg">-      </source>-    </audio>--Literate Haskell support-========================--If you append `+lhs` (or `+literate_haskell`) to an appropriate input or output-format (`markdown`, `markdown_strict`, `rst`, or `latex` for input or output;-`beamer`, `html` or `html5` for output only), pandoc will treat the document as-literate Haskell source. This means that--  - In Markdown input, "bird track" sections will be parsed as Haskell-    code rather than block quotations.  Text between `\begin{code}`-    and `\end{code}` will also be treated as Haskell code.  For-    ATX-style headers the character '=' will be used instead of '#'.--  - In Markdown output, code blocks with classes `haskell` and `literate`-    will be rendered using bird tracks, and block quotations will be-    indented one space, so they will not be treated as Haskell code.-    In addition, headers will be rendered setext-style (with underlines)-    rather than ATX-style (with '#' characters). (This is because ghc-    treats '#' characters in column 1 as introducing line numbers.)--  - In restructured text input, "bird track" sections will be parsed-    as Haskell code.--  - In restructured text output, code blocks with class `haskell` will-    be rendered using bird tracks.--  - In LaTeX input, text in `code` environments will be parsed as-    Haskell code.--  - In LaTeX output, code blocks with class `haskell` will be rendered-    inside `code` environments.--  - In HTML output, code blocks with class `haskell` will be rendered-    with class `literatehaskell` and bird tracks.--Examples:--    pandoc -f markdown+lhs -t html--reads literate Haskell source formatted with Markdown conventions and writes-ordinary HTML (without bird tracks).--    pandoc -f markdown+lhs -t html+lhs--writes HTML with the Haskell code in bird tracks, so it can be copied-and pasted as literate Haskell source.--Syntax highlighting-===================--Pandoc will automatically highlight syntax in [fenced code blocks] that-are marked with a language name.  The Haskell library [highlighting-kate] is-used for highlighting, which works in HTML, Docx, and LaTeX/PDF output.-To see a list of language names that pandoc will recognize, type-`pandoc --list-highlight-languages`.--The color scheme can be selected using the `--highlight-style` option.-The default color scheme is `pygments`, which imitates the default color-scheme used by the Python library pygments (though pygments is not actually-used to do the highlighting).  To see a list of highlight styles,-type `pandoc --list-highlight-styles`.--To disable highlighting, use the `--no-highlight` option.--[highlighting-kate]: https://github.com/jgm/highlighting-kate--Custom Styles in Docx Output-============================--By default, pandoc's docx output applies a predefined set of styles for-blocks such as paragraphs and block quotes, and uses largely default-formatting (italics, bold) for inlines. This will work for most-purposes, especially alongside a `reference.docx` file. However, if you-need to apply your own styles to blocks, or match a preexisting set of-styles, pandoc allows you to define custom styles for blocks and text-using `div`s and `span`s, respectively.--If you define a `div` or `span` with the attribute `custom-style`,-pandoc will apply your specified style to the contained elements. So,-for example,--    <span custom-style="Emphatically">Get out,</span> he said.--would produce a docx file with "Get out," styled with character-style `Emphatically`. Similarly,--    Dickinson starts the poem simply:--    <div custom-style="Poetry">-    | A Bird came down the Walk----    | He did not know I saw----    </div>--would style the two contained lines with the `Poetry` paragraph style.--If the styles are not yet in your reference.docx, they will be defined-in the output file as inheriting from normal text. If they are already-defined, pandoc will not alter the definition.--This feature allows for greatest customization in conjunction with-[pandoc filters]. If you want all paragraphs after block quotes to be-indented, you can write a filter to apply the styles necessary. If you-want all italics to be transformed to the `Emphasis` character style-(perhaps to change their color), you can write a filter which will-transform all italicized inlines to inlines within an `Emphasis`-custom-style `span`.--[pandoc filters]: http://pandoc.org/scripting.html--Custom writers-==============--Pandoc can be extended with custom writers written in [lua].  (Pandoc-includes a lua interpreter, so lua need not be installed separately.)--To use a custom writer, simply specify the path to the lua script-in place of the output format. For example:--    pandoc -t data/sample.lua--Creating a custom writer requires writing a lua function for each-possible element in a pandoc document.  To get a documented example-which you can modify according to your needs, do--    pandoc --print-default-data-file sample.lua--[lua]: http://www.lua.org--Authors-=======--© 2006-2016 John MacFarlane (jgm@berkeley.edu). Released under the-[GPL], version 2 or greater.  This software carries no warranty of-any kind.  (See COPYRIGHT for full copyright and warranty notices.)--Contributors include-Arata Mizuki,-Aaron Wolen,-Albert Krewinkel,-Alex Ivkin,-Alex Vong,-Alexander Kondratskiy,-Alexander Sulfrian,-Alexander V Vershilov,-Alfred Wechselberger,-Andreas Lööw,-Andrew Dunning,-Antoine Latter,-Arata Mizuki,-Arlo O'Keeffe,-Artyom Kazak,-B. Scott Michel,-Ben Gamari,-Beni Cherniavsky-Paskin,-Benoit Schweblin,-Bjorn Buckwalter,-Bradley Kuhn,-Brent Yorgey,-Bryan O'Sullivan,-Caleb McDaniel,-Calvin Beck,-Carlos Sosa,-Chris Black,-Christian Conkle,-Christoffer Ackelman,-Christoffer Sawicki,-Clare Macrae,-Clint Adams,-Conal Elliott,-Craig S. Bosma,-Daniel Bergey,-Daniel T. Staal,-Daniele D'Orazio,-David Lazar,-David Röthlisberger,-Denis Laxalde,-Douglas Calvert,-Emanuel Evans,-Emily Eisenberg,-Eric Kow,-Eric Seidel,-Felix Yan,-Florian Eitel,-François Gannaz,-Freiric Barral,-Freirich Raabe,-Frerich Raabe,-Fyodor Sheremetyev,-Gabor Pali,-Gavin Beatty,-Gottfried Haider,-Greg Maslov,-Greg Rundlett,-Grégory Bataille,-Gwern Branwen,-Hans-Peter Deifel,-Henrik Tramberend,-Henry de Valence,-Hubert Plociniczak,-Ilya V. Portnov,-Ivo Clarysse,-J. Lewis Muir,-Jaime Marquínez Ferrándiz,-Jakob Voß,-James Aspnes,-Jamie F. Olson,-Jan Larres,-Jan Schulz,-Jason Ronallo,-Jeff Arnold,-Jeff Runningen,-Jens Petersen,-Jesse Rosenthal,-Joe Hillenbrand,-John MacFarlane,-John Muccigrosso,-Jonas Smedegaard,-Jonathan Daugherty,-Jose Luis Duran,-Josef Svenningsson,-Julien Cretel,-Juliusz Gonera,-Justin Bogner,-Jérémy Bobbio,-Kelsey Hightower,-Kolen Cheung,-Konstantin Zudov,-Kristof Bastiaensen,-Lars-Dominik Braun,-Luke Plant,-Mark Szepieniec,-Mark Wright,-Martin Linn,-Masayoshi Takahashi,-Matej Kollar,-Mathias Schenner,-Mathieu Duponchelle,-Matthew Eddey,-Matthew Pickering,-Matthias C. M. Troffaes,-Mauro Bieg,-Max Bolingbroke,-Max Rydahl Andersen,-Merijn Verstraaten,-Michael Beaumont,-Michael Chladek,-Michael Snoyman,-Michael Thompson,-MinRK,-Morton Fox,-Nathan Gass,-Neil Mayhew,-Nick Bart,-Nicolas Kaiser,-Nikolay Yakimov,-Oliver Matthews,-Ophir Lifshitz,-Pablo Rodríguez,-Paul Rivier,-Paulo Tanimoto,-Peter Wang,-Philippe Ombredanne,-Phillip Alday,-Prayag Verma,-Puneeth Chaganti,-Ralf Stephan,-Raniere Silva,-Recai Oktaş,-RyanGlScott,-Scott Morrison,-Sergei Trofimovich,-Sergey Astanin,-Shahbaz Youssefi,-Shaun Attfield,-Sidarth Kapur,-Sidharth Kapur,-Simon Hengel,-Sumit Sahrawat,-Thomas Hodgson,-Thomas Weißschuh,-Tim Lin,-Timothy Humphries,-Tiziano Müller,-Todd Sifleet,-Tom Leese,-Uli Köhler,-Václav Zeman,-Viktor Kronvall,-Vincent,-Václav Haisman,-Václav Zeman,-Wandmalfarbe,-Waldir Pimenta,-Wikiwide,-Xavier Olive,-bumper314,-csforste,-infinity0x,-nkalvi,-qerub,-robabla,-roblabla,-rodja.trappe,-rski,-shreevatsa.public,-takahashim,-tgkokk,-thsutton.+% October 27, 2017++Synopsis+========++`pandoc` [*options*] [*input-file*]...++Description+===========++Pandoc is a [Haskell] library for converting from one markup format to+another, and a command-line tool that uses this library. It can read+[Markdown], [CommonMark], [PHP Markdown Extra], [GitHub-Flavored+Markdown], [MultiMarkdown], and (subsets of) [Textile],+[reStructuredText], [HTML], [LaTeX], [MediaWiki markup], [TWiki markup],+[TikiWiki markup], [Creole 1.0], [Haddock markup], [OPML], [Emacs Org mode],+[DocBook], [Muse], [txt2tags], [Vimwiki], [EPUB], [ODT], and [Word docx];+and it can write plain text, [Markdown], [CommonMark], [PHP Markdown+Extra], [GitHub-Flavored Markdown], [MultiMarkdown],+[reStructuredText], [XHTML], [HTML5], [LaTeX] \(including+[`beamer`] slide shows\), [ConTeXt], [RTF], [OPML], [DocBook],+[OpenDocument], [ODT], [Word docx], [GNU Texinfo], [MediaWiki+markup], [DokuWiki markup], [ZimWiki markup], [Haddock markup],+[EPUB] \(v2 or v3\), [FictionBook2], [Textile], [groff man],+[groff ms], [Emacs Org mode], [AsciiDoc], [InDesign ICML], [TEI+Simple], [Muse] and [Slidy], [Slideous], [DZSlides], [reveal.js]+or [S5] HTML slide shows. It can also produce [PDF] output on+systems where LaTeX, ConTeXt, `pdfroff`, `wkhtmltopdf`,+`prince`, or `weasyprint` is installed.++Pandoc's enhanced version of Markdown includes syntax for [footnotes],+[tables], flexible [ordered lists], [definition lists], [fenced code+blocks], [superscripts and subscripts], [strikeout], [metadata blocks],+automatic tables of contents, embedded LaTeX [math], [citations], and+[Markdown inside HTML block elements][Extension:+`markdown_in_html_blocks`]. (These enhancements, described further under+[Pandoc's Markdown], can be disabled using the `markdown_strict` input+or output format.)++In contrast to most existing tools for converting Markdown to HTML, which+use regex substitutions, pandoc has a modular design: it consists of a+set of readers, which parse text in a given format and produce a native+representation of the document, and a set of writers, which convert+this native representation into a target format. Thus, adding an input+or output format requires only adding a reader or writer.++Because pandoc's intermediate representation of a document is less+expressive than many of the formats it converts between, one should+not expect perfect conversions between every format and every other.+Pandoc attempts to preserve the structural elements of a document, but+not formatting details such as margin size.  And some document elements,+such as complex tables, may not fit into pandoc's simple document+model.  While conversions from pandoc's Markdown to all formats aspire+to be perfect, conversions from formats more expressive than pandoc's+Markdown can be expected to be lossy.++[Markdown]: http://daringfireball.net/projects/markdown/+[CommonMark]: http://commonmark.org+[PHP Markdown Extra]: https://michelf.ca/projects/php-markdown/extra/+[GitHub-Flavored Markdown]: https://help.github.com/articles/github-flavored-markdown/+[MultiMarkdown]: http://fletcherpenney.net/multimarkdown/+[reStructuredText]: http://docutils.sourceforge.net/docs/ref/rst/introduction.html+[S5]: http://meyerweb.com/eric/tools/s5/+[Slidy]: http://www.w3.org/Talks/Tools/Slidy/+[Slideous]: http://goessner.net/articles/slideous/+[HTML]: http://www.w3.org/html/+[HTML5]: http://www.w3.org/TR/html5/+[polyglot markup]: https://www.w3.org/TR/html-polyglot/+[XHTML]: http://www.w3.org/TR/xhtml1/+[LaTeX]: http://latex-project.org+[`beamer`]: https://ctan.org/pkg/beamer+[Beamer User's Guide]: http://ctan.math.utah.edu/ctan/tex-archive/macros/latex/contrib/beamer/doc/beameruserguide.pdf+[ConTeXt]: http://www.contextgarden.net/+[RTF]: http://en.wikipedia.org/wiki/Rich_Text_Format+[DocBook]: http://docbook.org+[txt2tags]: http://txt2tags.org+[EPUB]: http://idpf.org/epub+[OPML]: http://dev.opml.org/spec2.html+[OpenDocument]: http://opendocument.xml.org+[ODT]: http://en.wikipedia.org/wiki/OpenDocument+[Textile]: http://redcloth.org/textile+[MediaWiki markup]: https://www.mediawiki.org/wiki/Help:Formatting+[DokuWiki markup]: https://www.dokuwiki.org/dokuwiki+[ZimWiki markup]: http://zim-wiki.org/manual/Help/Wiki_Syntax.html+[TWiki markup]: http://twiki.org/cgi-bin/view/TWiki/TextFormattingRules+[TikiWiki markup]: https://doc.tiki.org/Wiki-Syntax-Text#The_Markup_Language_Wiki-Syntax+[Haddock markup]: https://www.haskell.org/haddock/doc/html/ch03s08.html+[Creole 1.0]: http://www.wikicreole.org/wiki/Creole1.0+[groff man]: http://man7.org/linux/man-pages/man7/groff_man.7.html+[groff ms]: http://man7.org/linux/man-pages/man7/groff_ms.7.html+[Haskell]: https://www.haskell.org+[GNU Texinfo]: http://www.gnu.org/software/texinfo/+[Emacs Org mode]: http://orgmode.org+[AsciiDoc]: http://www.methods.co.nz/asciidoc/+[DZSlides]: http://paulrouget.com/dzslides/+[Word docx]: https://en.wikipedia.org/wiki/Office_Open_XML+[PDF]: https://www.adobe.com/pdf/+[reveal.js]: http://lab.hakim.se/reveal-js/+[FictionBook2]: http://www.fictionbook.org/index.php/Eng:XML_Schema_Fictionbook_2.1+[InDesign ICML]: https://www.adobe.com/content/dam/Adobe/en/devnet/indesign/cs55-docs/IDML/idml-specification.pdf+[TEI Simple]: https://github.com/TEIC/TEI-Simple+[Muse]: https://amusewiki.org/library/manual+[Vimwiki]: https://vimwiki.github.io++Using `pandoc`+--------------++If no *input-file* is specified, input is read from *stdin*.+Otherwise, the *input-files* are concatenated (with a blank+line between each) and used as input.  Output goes to *stdout* by+default (though output to the terminal is disabled for the+`odt`, `docx`, `epub2`, and `epub3` output formats, unless it is+forced using `-o -`).  For output to a file, use the `-o`+option:++    pandoc -o output.html input.txt++By default, pandoc produces a document fragment, not a standalone+document with a proper header and footer.  To produce a standalone+document, use the `-s` or `--standalone` flag:++    pandoc -s -o output.html input.txt++For more information on how standalone documents are produced, see+[Templates], below.++Instead of a file, an absolute URI may be given.  In this case+pandoc will fetch the content using HTTP:++    pandoc -f html -t markdown http://www.fsf.org++It is possible to supply a custom User-Agent string or other+header when requesting a document from a URL:++    pandoc -f html -t markdown --request-header User-Agent:"Mozilla/5.0" \+      http://www.fsf.org++If multiple input files are given, `pandoc` will concatenate them all (with+blank lines between them) before parsing. This feature is disabled for+ binary input formats such as `EPUB`, `odt`, and `docx`.++The format of the input and output can be specified explicitly using+command-line options.  The input format can be specified using the+`-r/--read` or `-f/--from` options, the output format using the+`-w/--write` or `-t/--to` options.  Thus, to convert `hello.txt` from+Markdown to LaTeX, you could type:++    pandoc -f markdown -t latex hello.txt++To convert `hello.html` from HTML to Markdown:++    pandoc -f html -t markdown hello.html++Supported output formats are listed below under the `-t/--to` option.+Supported input formats are listed below under the `-f/--from` option. Note+that the `rst`, `textile`, `latex`, and `html` readers are not complete;+there are some constructs that they do not parse.++If the input or output format is not specified explicitly, `pandoc`+will attempt to guess it from the extensions of+the input and output filenames.  Thus, for example,++    pandoc -o hello.tex hello.txt++will convert `hello.txt` from Markdown to LaTeX.  If no output file+is specified (so that output goes to *stdout*), or if the output file's+extension is unknown, the output format will default to HTML.+If no input file is specified (so that input comes from *stdin*), or+if the input files' extensions are unknown, the input format will+be assumed to be Markdown unless explicitly specified.++Pandoc uses the UTF-8 character encoding for both input and output.+If your local character encoding is not UTF-8, you+should pipe input and output through [`iconv`]:++    iconv -t utf-8 input.txt | pandoc | iconv -f utf-8++Note that in some output formats (such as HTML, LaTeX, ConTeXt,+RTF, OPML, DocBook, and Texinfo), information about+the character encoding is included in the document header, which+will only be included if you use the `-s/--standalone` option.++[`iconv`]: http://www.gnu.org/software/libiconv/++Creating a PDF+--------------++To produce a PDF, specify an output file with a `.pdf` extension.+By default, pandoc will use LaTeX to create the PDF:++    pandoc test.txt -o test.pdf++Production of a PDF requires that a LaTeX engine be installed (see+`--pdf-engine`, below), and assumes that the following LaTeX packages+are available: [`amsfonts`], [`amsmath`], [`lm`], [`unicode-math`],+[`ifxetex`], [`ifluatex`], [`listings`] (if the+`--listings` option is used), [`fancyvrb`], [`longtable`],+[`booktabs`], [`graphicx`] and [`grffile`] (if the document+contains images), [`hyperref`], [`xcolor`] (with `colorlinks`), [`ulem`], [`geometry`] (with the+`geometry` variable set), [`setspace`] (with `linestretch`), and+[`babel`] (with `lang`).  The use of `xelatex` or `lualatex` as+the LaTeX engine requires [`fontspec`].  `xelatex` uses+[`polyglossia`] (with `lang`), [`xecjk`], and [`bidi`] (with the+`dir` variable set). If the `mathspec` variable is set,+`xelatex` will use [`mathspec`] instead of [`unicode-math`].+The [`upquote`] and [`microtype`] packages are used if+available, and [`csquotes`] will be used for [smart punctuation]+if added to the template or included in any header file. The+[`natbib`], [`biblatex`], [`bibtex`], and [`biber`] packages can+optionally be used for [citation rendering]. These are included+with all recent versions of [TeX Live].++Alternatively, pandoc can use [ConTeXt], `pdfroff`, or any of the+following HTML/CSS-to-PDF-engines, to create a PDF: [`wkhtmltopdf`],+[`weasyprint`] or [`prince`].+To do this, specify an output file with a `.pdf` extension, as before,+but add the `--pdf-engine` option or `-t context`, `-t html`, or `-t ms`+to the command line (`-t html` defaults to `--pdf-engine=wkhtmltopdf`).++PDF output can be controlled using [variables for LaTeX] (if+LaTeX is used) and [variables for ConTeXt] (if ConTeXt is used).+When using an HTML/CSS-to-PDF-engine, `--css` affects the output.+If `wkhtmltopdf` is used, then the variables `margin-left`,+`margin-right`, `margin-top`, `margin-bottom`, and `papersize`+will affect the output.++[`amsfonts`]: https://ctan.org/pkg/amsfonts+[`amsmath`]: https://ctan.org/pkg/amsmath+[`lm`]: https://ctan.org/pkg/lm+[`ifxetex`]: https://ctan.org/pkg/ifxetex+[`ifluatex`]: https://ctan.org/pkg/ifluatex+[`listings`]: https://ctan.org/pkg/listings+[`fancyvrb`]: https://ctan.org/pkg/fancyvrb+[`longtable`]: https://ctan.org/pkg/longtable+[`booktabs`]: https://ctan.org/pkg/booktabs+[`graphicx`]: https://ctan.org/pkg/graphicx+[`grffile`]: https://ctan.org/pkg/grffile+[`geometry`]: https://ctan.org/pkg/geometry+[`setspace`]: https://ctan.org/pkg/setspace+[`xecjk`]: https://ctan.org/pkg/xecjk+[`hyperref`]: https://ctan.org/pkg/hyperref+[`ulem`]: https://ctan.org/pkg/ulem+[`babel`]: https://ctan.org/pkg/babel+[`bidi`]: https://ctan.org/pkg/bidi+[`mathspec`]: https://ctan.org/pkg/mathspec+[`unicode-math`]: https://ctan.org/pkg/unicode-math+[`polyglossia`]: https://ctan.org/pkg/polyglossia+[`fontspec`]: https://ctan.org/pkg/fontspec+[`upquote`]: https://ctan.org/pkg/upquote+[`microtype`]: https://ctan.org/pkg/microtype+[`csquotes`]: https://ctan.org/pkg/csquotes+[`natbib`]: https://ctan.org/pkg/natbib+[`biblatex`]: https://ctan.org/pkg/biblatex+[`bibtex`]: https://ctan.org/pkg/bibtex+[`biber`]: https://ctan.org/pkg/biber+[TeX Live]: http://www.tug.org/texlive/+[`wkhtmltopdf`]: https://wkhtmltopdf.org+[`weasyprint`]: http://weasyprint.org+[`prince`]: https://www.princexml.com/++Options+=======++General options+---------------++`-f` *FORMAT*, `-r` *FORMAT*, `--from=`*FORMAT*, `--read=`*FORMAT*++:   Specify input format.  *FORMAT* can be `native` (native Haskell),+    `json` (JSON version of native AST), `markdown` (pandoc's+    extended Markdown), `markdown_strict` (original unextended+    Markdown), `markdown_phpextra` (PHP Markdown Extra),+    `markdown_mmd` (MultiMarkdown), `gfm` (GitHub-Flavored Markdown),+    `commonmark` (CommonMark Markdown), `textile` (Textile), `rst`+    (reStructuredText), `html` (HTML), `docbook` (DocBook), `t2t`+    (txt2tags), `docx` (docx), `odt` (ODT), `epub` (EPUB), `opml` (OPML),+    `org` (Emacs Org mode), `mediawiki` (MediaWiki markup), `twiki` (TWiki+    markup), `tikiwiki` (TikiWiki markup), `creole` (Creole 1.0),+    `haddock` (Haddock markup), or `latex` (LaTeX).+    (`markdown_github` provides deprecated and less accurate suppport+    for Github-Flavored Markdown; please use `gfm` instead, unless you+    need to use extensions other than `smart`.)+    If `+lhs` is appended to `markdown`, `rst`, `latex`, or+    `html`, the input will be treated as literate Haskell source: see+    [Literate Haskell support], below. Markdown+    syntax extensions can be individually enabled or disabled by+    appending `+EXTENSION` or `-EXTENSION` to the format name. So, for+    example, `markdown_strict+footnotes+definition_lists` is strict+    Markdown with footnotes and definition lists enabled, and+    `markdown-pipe_tables+hard_line_breaks` is pandoc's Markdown+    without pipe tables and with hard line breaks. See [Pandoc's+    Markdown], below, for a list of extensions and+    their names.  See `--list-input-formats` and `--list-extensions`,+    below.++`-t` *FORMAT*, `-w` *FORMAT*, `--to=`*FORMAT*, `--write=`*FORMAT*++:   Specify output format.  *FORMAT* can be `native` (native Haskell),+    `json` (JSON version of native AST), `plain` (plain text),+    `markdown` (pandoc's extended Markdown), `markdown_strict`+    (original unextended Markdown), `markdown_phpextra` (PHP Markdown+    Extra), `markdown_mmd` (MultiMarkdown), `gfm` (GitHub-Flavored+    Markdown), `commonmark` (CommonMark Markdown), `rst`+    (reStructuredText), `html4` (XHTML 1.0 Transitional), `html`+    or `html5` (HTML5/XHTML [polyglot markup]), `latex`+    (LaTeX), `beamer` (LaTeX beamer slide show), `context` (ConTeXt),+    `man` (groff man), `mediawiki` (MediaWiki markup),+    `dokuwiki` (DokuWiki markup), `zimwiki` (ZimWiki markup),+    `textile` (Textile), `org` (Emacs Org mode), `texinfo` (GNU Texinfo),+    `opml` (OPML), `docbook` or `docbook4` (DocBook 4), `docbook5`+    (DocBook 5), `jats` (JATS XML), `opendocument` (OpenDocument),+    `odt` (OpenOffice text document), `docx` (Word docx), `haddock`+    (Haddock markup), `rtf` (rich text format), `epub2` (EPUB v2 book),+    `epub` or `epub3` (EPUB v3), `fb2` (FictionBook2 e-book),+    `asciidoc` (AsciiDoc), `icml` (InDesign ICML), `tei` (TEI+    Simple), `slidy` (Slidy HTML and JavaScript slide show),+    `slideous` (Slideous HTML and JavaScript slide show),+    `dzslides` (DZSlides HTML5 + JavaScript slide show),+    `revealjs` (reveal.js HTML5 + JavaScript slide show), `s5`+    (S5 HTML and JavaScript slide show), or the path of a custom+    lua writer (see [Custom writers], below). (`markdown_github`+    provides deprecated and less accurate suppport for+    Github-Flavored Markdown; please use `gfm` instead, unless+    you use extensions that do not work with `gfm`.) Note that `odt`,+    `epub`, and `epub3` output will not be directed to *stdout*;+    an output filename must be specified using the `-o/--output`+    option. If `+lhs` is appended to `markdown`, `rst`, `latex`,+    `beamer`, `html4`, or `html5`, the output will be rendered as+    literate Haskell source: see [Literate Haskell support],+    below.  Markdown syntax extensions can be individually+    enabled or disabled by appending `+EXTENSION` or+    `-EXTENSION` to the format name, as described above under `-f`.+    See `--list-output-formats` and `--list-extensions`, below.++`-o` *FILE*, `--output=`*FILE*++:   Write output to *FILE* instead of *stdout*.  If *FILE* is+    `-`, output will go to *stdout*, even if a non-textual format+    (`docx`, `odt`, `epub2`, `epub3`) is specified.++`--data-dir=`*DIRECTORY*++:   Specify the user data directory to search for pandoc data files.+    If this option is not specified, the default user data directory+    will be used.  This is, in UNIX:++        $HOME/.pandoc++    in Windows XP:++        C:\Documents And Settings\USERNAME\Application Data\pandoc++    and in Windows Vista or later:++        C:\Users\USERNAME\AppData\Roaming\pandoc++    You can find the default user data directory on your system by+    looking at the output of `pandoc --version`.+    A `reference.odt`, `reference.docx`, `epub.css`, `templates`,+    `slidy`, `slideous`, or `s5` directory+    placed in this directory will override pandoc's normal defaults.++`--bash-completion`++:   Generate a bash completion script.  To enable bash completion+    with pandoc, add this to your `.bashrc`:++         eval "$(pandoc --bash-completion)"++`--verbose`++:   Give verbose debugging output.  Currently this only has an effect+    with PDF output.++`--quiet`++:   Suppress warning messages.++`--fail-if-warnings`++:   Exit with error status if there are any warnings.++`--log=`*FILE*++:   Write log messages in machine-readable JSON format to+    *FILE*.  All messages above DEBUG level will be written,+    regardless of verbosity settings (`--verbose`, `--quiet`).++`--list-input-formats`++:   List supported input formats, one per line.++`--list-output-formats`++:   List supported output formats, one per line.++`--list-extensions`++:   List supported Markdown extensions, one per line, followed+    by a `+` or `-` indicating whether it is enabled by default+    in pandoc's Markdown.++`--list-highlight-languages`++:   List supported languages for syntax highlighting, one per+    line.++`--list-highlight-styles`++:   List supported styles for syntax highlighting, one per line.+    See `--highlight-style`.++`-v`, `--version`++:   Print version.++`-h`, `--help`++:   Show usage message.++Reader options+--------------++`--base-header-level=`*NUMBER*++:   Specify the base level for headers (defaults to 1).++`--indented-code-classes=`*CLASSES*++:   Specify classes to use for indented code blocks--for example,+    `perl,numberLines` or `haskell`. Multiple classes may be separated+    by spaces or commas.++`--default-image-extension=`*EXTENSION*++:   Specify a default extension to use when image paths/URLs have no+    extension.  This allows you to use the same source for formats that+    require different kinds of images.  Currently this option only affects+    the Markdown and LaTeX readers.++`--file-scope`++:   Parse each file individually before combining for multifile+    documents. This will allow footnotes in different files with the+    same identifiers to work as expected. If this option is set,+    footnotes and links will not work across files. Reading binary+    files (docx, odt, epub) implies `--file-scope`.++`--filter=`*PROGRAM*++:   Specify an executable to be used as a filter transforming the+    pandoc AST after the input is parsed and before the output is+    written.  The executable should read JSON from stdin and write+    JSON to stdout.  The JSON must be formatted like  pandoc's own+    JSON input and output.  The name of the output format will be+    passed to the filter as the first argument.  Hence,++        pandoc --filter ./caps.py -t latex++    is equivalent to++        pandoc -t json | ./caps.py latex | pandoc -f json -t latex++    The latter form may be useful for debugging filters.++    Filters may be written in any language.  `Text.Pandoc.JSON`+    exports `toJSONFilter` to facilitate writing filters in Haskell.+    Those who would prefer to write filters in python can use the+    module [`pandocfilters`], installable from PyPI. There are also+    pandoc filter libraries in [PHP], [perl], and+    [JavaScript/node.js].++    In order of preference, pandoc will look for filters in++     1. a specified full or relative path (executable or+     non-executable)++     2. `$DATADIR/filters` (executable or non-executable)+     where `$DATADIR` is the user data directory (see+     `--data-dir`, above).++     3. `$PATH` (executable only)++`--lua-filter=`*SCRIPT*++:   Transform the document in a similar fashion as JSON filters (see+    `--filter`), but use pandoc's build-in lua filtering system.  The given+    lua script is expected to return a list of lua filters which will be+    applied in order.  Each lua filter must contain element-transforming+    functions indexed by the name of the AST element on which the filter+    function should be applied.++    The `pandoc` lua module provides helper functions for element+    creation.  It is always loaded into the script's lua environment.++    The following is an example lua script for macro-expansion:++        function expand_hello_world(inline)+          if inline.c == '{{helloworld}}' then+            return pandoc.Emph{ pandoc.Str "Hello, World" }+          else+            return inline+          end+        end++        return {{Str = expand_hello_world}}+++`-M` *KEY*[`=`*VAL*], `--metadata=`*KEY*[`:`*VAL*]++:   Set the metadata field *KEY* to the value *VAL*.  A value specified+    on the command line overrides a value specified in the document.+    Values will be parsed as YAML boolean or string values. If no value is+    specified, the value will be treated as Boolean true.  Like+    `--variable`, `--metadata` causes template variables to be set.+    But unlike `--variable`, `--metadata` affects the metadata of the+    underlying document (which is accessible from filters and may be+    printed in some output formats).++`-p`, `--preserve-tabs`++:   Preserve tabs instead of converting them to spaces (the default).+    Note that this will only affect tabs in literal code spans and code+    blocks; tabs in regular text will be treated as spaces.++`--tab-stop=`*NUMBER*++:   Specify the number of spaces per tab (default is 4).++`--track-changes=accept`|`reject`|`all`++:   Specifies what to do with insertions, deletions, and comments+    produced by the MS Word "Track Changes" feature.  `accept` (the+    default), inserts all insertions, and ignores all+    deletions. `reject` inserts all deletions and ignores+    insertions. Both `accept` and `reject` ignore comments. `all` puts+    in insertions, deletions, and comments, wrapped in spans with+    `insertion`, `deletion`, `comment-start`, and `comment-end`+    classes, respectively. The author and time of change is+    included. `all` is useful for scripting: only accepting changes+    from a certain reviewer, say, or before a certain date. This+    option only affects the docx reader.++`--extract-media=`*DIR*++:   Extract images and other media contained in or linked from+    the source document to the path *DIR*, creating it if+    necessary, and adjust the images references in the document+    so they point to the extracted files.  If the source format is+    a binary container (docx, epub, or odt), the media is+    extracted from the container and the original+    filenames are used. Otherwise the media is read from the+    file system or downloaded, and new filenames are constructed+    based on SHA1 hashes of the contents.++`--abbreviations=`*FILE*++:   Specifies a custom abbreviations file, with abbreviations+    one to a line.  If this option is not specified, pandoc will+    read the data file `abbreviations` from the user data+    directory or fall back on a system default.  To see the+    system default, use+    `pandoc --print-default-data-file=abbreviations`.  The only+    use pandoc makes of this list is in the Markdown reader.+    Strings ending in a period that are found in this list will+    be followed by a nonbreaking space, so that the period will+    not produce sentence-ending space in formats like LaTeX.++[`pandocfilters`]: https://github.com/jgm/pandocfilters+[PHP]: https://github.com/vinai/pandocfilters-php+[perl]: https://metacpan.org/pod/Pandoc::Filter+[JavaScript/node.js]: https://github.com/mvhenderson/pandoc-filter-node++General writer options+----------------------++`-s`, `--standalone`++:   Produce output with an appropriate header and footer (e.g. a+    standalone HTML, LaTeX, TEI, or RTF file, not a fragment).  This option+    is set automatically for `pdf`, `epub`, `epub3`, `fb2`, `docx`, and `odt`+    output.++`--template=`*FILE*++:   Use *FILE* as a custom template for the generated document. Implies+    `--standalone`. See [Templates], below, for a description+    of template syntax. If no extension is specified, an extension+    corresponding to the writer will be added, so that `--template=special`+    looks for `special.html` for HTML output.  If the template is not+    found, pandoc will search for it in the `templates` subdirectory of+    the user data directory (see `--data-dir`). If this option is not used,+    a default template appropriate for the output format will be used (see+    `-D/--print-default-template`).++`-V` *KEY*[`=`*VAL*], `--variable=`*KEY*[`:`*VAL*]++:   Set the template variable *KEY* to the value *VAL* when rendering the+    document in standalone mode. This is generally only useful when the+    `--template` option is used to specify a custom template, since+    pandoc automatically sets the variables used in the default+    templates.  If no *VAL* is specified, the key will be given the+    value `true`.++`-D` *FORMAT*, `--print-default-template=`*FORMAT*++:   Print the system default template for an output *FORMAT*. (See `-t`+    for a list of possible *FORMAT*s.)  Templates in the user data+    directory are ignored.++`--print-default-data-file=`*FILE*++:   Print a system default data file.  Files in the user data directory+    are ignored.++`--eol=crlf`|`lf`|`native`++:   Manually specify line endings: `crlf` (Windows), `lf`+    (macOS/Linux/UNIX), or `native` (line endings appropriate+    to the OS on which pandoc is being run).  The default is+    `native`.++`--dpi`=*NUMBER*++:   Specify the dpi (dots per inch) value for conversion from pixels+    to inch/centimeters and vice versa. The default is 96dpi.+    Technically, the correct term would be ppi (pixels per inch).++`--wrap=auto`|`none`|`preserve`++:   Determine how text is wrapped in the output (the source+    code, not the rendered version).  With `auto` (the default),+    pandoc will attempt to wrap lines to the column width specified by+    `--columns` (default 72).  With `none`, pandoc will not wrap+    lines at all.  With `preserve`, pandoc will attempt to+    preserve the wrapping from the source document (that is,+    where there are nonsemantic newlines in the source, there+    will be nonsemantic newlines in the output as well).+    Automatic wrapping does not currently work in HTML output.++`--columns=`*NUMBER*++:   Specify length of lines in characters.  This affects text wrapping+    in the generated source code (see `--wrap`).  It also affects+    calculation of column widths for plain text tables (see [Tables] below).++`--toc`, `--table-of-contents`++:   Include an automatically generated table of contents (or, in+    the case of `latex`, `context`, `docx`, `odt`,+    `opendocument`, `rst`, or `ms`, an instruction to create+    one) in the output document. This option has no effect on+    `man`, `docbook4`, `docbook5`, or `jats` output.++`--toc-depth=`*NUMBER*++:   Specify the number of section levels to include in the table+    of contents.  The default is 3 (which means that level 1, 2, and 3+    headers will be listed in the contents).++`--strip-comments`++:   Strip out HTML comments in the Markdown or Textile source,+    rather than passing them on to Markdown, Textile or HTML+    output as raw HTML.  This does not apply to HTML comments+    inside raw HTML blocks when the `markdown_in_html_blocks`+    extension is not set.++`--no-highlight`++:   Disables syntax highlighting for code blocks and inlines, even when+    a language attribute is given.++`--highlight-style=`*STYLE*|*FILE*++:   Specifies the coloring style to be used in highlighted source code.+    Options are `pygments` (the default), `kate`, `monochrome`,+    `breezeDark`, `espresso`, `zenburn`, `haddock`, and `tango`.+    For more information on syntax highlighting in pandoc, see+    [Syntax highlighting], below.  See also+    `--list-highlight-styles`.++    Instead of a *STYLE* name, a JSON file with extension+    `.theme` may be supplied.  This will be parsed as a KDE+    syntax highlighting theme and (if valid) used as the+    highlighting style.  To see a sample theme that can be+    modified, `pandoc --print-default-data-file default.theme`.++`--syntax-definition=`*FILE*++:   Instructs pandoc to load a KDE XML syntax definition file,+    which will be used for syntax highlighting of appropriately+    marked code blocks.  This can be used to add support for+    new languages or to use altered syntax definitions for+    existing languages.++`-H` *FILE*, `--include-in-header=`*FILE*++:   Include contents of *FILE*, verbatim, at the end of the header.+    This can be used, for example, to include special+    CSS or JavaScript in HTML documents.  This option can be used+    repeatedly to include multiple files in the header.  They will be+    included in the order specified.  Implies `--standalone`.++`-B` *FILE*, `--include-before-body=`*FILE*++:   Include contents of *FILE*, verbatim, at the beginning of the+    document body (e.g. after the `<body>` tag in HTML, or the+    `\begin{document}` command in LaTeX). This can be used to include+    navigation bars or banners in HTML documents. This option can be+    used repeatedly to include multiple files. They will be included in+    the order specified.  Implies `--standalone`.++`-A` *FILE*, `--include-after-body=`*FILE*++:   Include contents of *FILE*, verbatim, at the end of the document+    body (before the `</body>` tag in HTML, or the+    `\end{document}` command in LaTeX). This option can be used+    repeatedly to include multiple files. They will be included in the+    order specified.  Implies `--standalone`.++`--resource-path=`*SEARCHPATH*++:   List of paths to search for images and other resources.+    The paths should be separated by `:` on Linux, UNIX, and+    macOS systems, and by `;` on Windows.  If `--resource-path`+    is not specified, the default resource path is the working+    directory. Note that, if `--resource-path` is specified,+    the working directory must be explicitly listed or it+    will not be searched.  For example:+    `--resource-path=.:test` will search the working directory+    and the `test` subdirectory, in that order.++`--request-header=`*NAME*`:`*VAL*++:   Set the request header *NAME* to the value *VAL* when making+    HTTP requests (for example, when a URL is given on the+    command line, or when resources used in a document must be+    downloaded).++Options affecting specific writers+----------------------------------++`--self-contained`++:   Produce a standalone HTML file with no external dependencies, using+    `data:` URIs to incorporate the contents of linked scripts, stylesheets,+    images, and videos. The resulting file should be "self-contained,"+    in the sense that it needs no external files and no net access to be+    displayed properly by a browser. This option works only with HTML output+    formats, including `html4`, `html5`, `html+lhs`, `html5+lhs`, `s5`,+    `slidy`, `slideous`, `dzslides`, and `revealjs`. Scripts, images, and+    stylesheets at absolute URLs will be downloaded; those at relative URLs+    will be sought relative to the working directory (if the first source+    file is local) or relative to the base URL (if the first source+    file is remote).  Elements with the attribute+    `data-external="1"` will be left alone; the documents they+    link to will not be incorporated in the document.+    Limitation: resources that are loaded dynamically through+    JavaScript cannot be incorporated; as a result,+    `--self-contained` does not work with `--mathjax`, and some+    advanced features (e.g.  zoom or speaker notes) may not work+    in an offline "self-contained" `reveal.js` slide show.++`--html-q-tags`++:   Use `<q>` tags for quotes in HTML.++`--ascii`++:   Use only ASCII characters in output.  Currently supported only for+    HTML and DocBook output (which uses numerical entities instead of+    UTF-8 when this option is selected).++`--reference-links`++:   Use reference-style links, rather than inline links, in writing Markdown+    or reStructuredText.  By default inline links are used.  The+    placement of link references is affected by the+    `--reference-location` option.++`--reference-location = block`|`section`|`document`++:   Specify whether footnotes (and references, if `reference-links` is+    set) are placed at the end of the current (top-level) block, the+    current section, or the document. The default is+    `document`. Currently only affects the markdown writer.++`--atx-headers`++:   Use ATX-style headers in Markdown and AsciiDoc output. The default is+    to use setext-style headers for levels 1-2, and then ATX headers.++`--top-level-division=[default|section|chapter|part]`++:   Treat top-level headers as the given division type in LaTeX, ConTeXt,+    DocBook, and  TEI output. The hierarchy order is part, chapter, then section;+    all headers are shifted such that the top-level header becomes the specified+    type. The default behavior is to determine the best division type via+    heuristics: unless other conditions apply, `section` is chosen. When the+    LaTeX document class is set to `report`, `book`, or `memoir` (unless the+    `article` option is specified), `chapter` is implied as the setting for this+    option. If `beamer` is the output format, specifying either `chapter` or+    `part` will cause top-level headers to become `\part{..}`, while+    second-level headers remain as their default type.++`-N`, `--number-sections`++:   Number section headings in LaTeX, ConTeXt, HTML, or EPUB output.+    By default, sections are not numbered.  Sections with class+    `unnumbered` will never be numbered, even if `--number-sections`+    is specified.++`--number-offset=`*NUMBER*[`,`*NUMBER*`,`*...*]++:   Offset for section headings in HTML output (ignored in other+    output formats).  The first number is added to the section number for+    top-level headers, the second for second-level headers, and so on.+    So, for example, if you want the first top-level header in your+    document to be numbered "6", specify `--number-offset=5`.+    If your document starts with a level-2 header which you want to+    be numbered "1.5", specify `--number-offset=1,4`.+    Offsets are 0 by default.  Implies `--number-sections`.++`--listings`++:   Use the [`listings`] package for LaTeX code blocks++`-i`, `--incremental`++:   Make list items in slide shows display incrementally (one by one).+    The default is for lists to be displayed all at once.++`--slide-level=`*NUMBER*++:   Specifies that headers with the specified level create+    slides (for `beamer`, `s5`, `slidy`, `slideous`, `dzslides`).  Headers+    above this level in the hierarchy are used to divide the+    slide show into sections; headers below this level create+    subheads within a slide.  Note that content that is+    not contained under slide-level headers will not appear in+    the slide show.  The default is to set the slide level based+    on the contents of the document; see [Structuring the slide+    show].++`--section-divs`++:   Wrap sections in `<div>` tags (or `<section>` tags in HTML5),+    and attach identifiers to the enclosing `<div>` (or `<section>`)+    rather than the header itself. See+    [Header identifiers], below.++`--email-obfuscation=none`|`javascript`|`references`++:   Specify a method for obfuscating `mailto:` links in HTML documents.+    `none` leaves `mailto:` links as they are.  `javascript` obfuscates+    them using JavaScript. `references` obfuscates them by printing their+    letters as decimal or hexadecimal character references.  The default+    is `none`.++`--id-prefix=`*STRING*++:   Specify a prefix to be added to all identifiers and internal links+    in HTML and DocBook output, and to footnote numbers in Markdown+    and Haddock output. This is useful for preventing duplicate+    identifiers when generating fragments to be included in other pages.++`-T` *STRING*, `--title-prefix=`*STRING*++:   Specify *STRING* as a prefix at the beginning of the title+    that appears in the HTML header (but not in the title as it+    appears at the beginning of the HTML body).  Implies+    `--standalone`.++`-c` *URL*, `--css=`*URL*++:   Link to a CSS style sheet. This option can be used repeatedly to+    include multiple files. They will be included in the order specified.++    A stylesheet is required for generating EPUB.  If none is+    provided using this option (or the `stylesheet` metadata+    field), pandoc will look for a file `epub.css` in the+    user data directory (see `--data-dir`).  If it is not+    found there, sensible defaults will be used.++`--reference-doc=`*FILE*++:   Use the specified file as a style reference in producing a+    docx or ODT file.++    Docx++    :   For best results, the reference docx should be a modified+        version of a docx file produced using pandoc.  The contents+        of the reference docx are ignored, but its stylesheets and+        document properties (including margins, page size, header,+        and footer) are used in the new docx. If no reference docx+        is specified on the command line, pandoc will look for a+        file `reference.docx` in the user data directory (see+        `--data-dir`). If this is not found either, sensible+        defaults will be used.++        To produce a custom `reference.docx`, first get a copy of+        the default `reference.docx`: `pandoc+        --print-default-data-file reference.docx >+        custom-reference.docx`.  Then open `custom-reference.docx`+        in Word, modify the styles as you wish, and save the file.+        For best results, do not make changes to this file other+        than modifying the styles used by pandoc: [paragraph]+        Normal, Body Text, First Paragraph, Compact, Title,+        Subtitle, Author, Date, Abstract, Bibliography, Heading 1,+        Heading 2, Heading 3, Heading 4, Heading 5, Heading 6,+        Heading 7, Heading 8, Heading 9, Block Text, Footnote Text,+        Definition Term, Definition, Caption, Table Caption,+        Image Caption, Figure, Captioned Figure, TOC Heading;+        [character] Default Paragraph Font, Body Text Char,+        Verbatim Char, Footnote Reference, Hyperlink; [table]+        Table.++    ODT++    :   For best results, the reference ODT should be a modified+        version of an ODT produced using pandoc.  The contents of+        the reference ODT are ignored, but its stylesheets are used+        in the new ODT. If no reference ODT is specified on the+        command line, pandoc will look for a file `reference.odt` in+        the user data directory (see `--data-dir`). If this is not+        found either, sensible defaults will be used.++        To produce a custom `reference.odt`, first get a copy of+        the default `reference.odt`: `pandoc+        --print-default-data-file reference.odt >+        custom-reference.odt`.  Then open `custom-reference.odt` in+        LibreOffice, modify the styles as you wish, and save the+        file.++`--epub-cover-image=`*FILE*++:   Use the specified image as the EPUB cover.  It is recommended+    that the image be less than 1000px in width and height. Note that+    in a Markdown source document you can also specify `cover-image`+    in a YAML metadata block (see [EPUB Metadata], below).++`--epub-metadata=`*FILE*++:   Look in the specified XML file for metadata for the EPUB.+    The file should contain a series of [Dublin Core elements].+    For example:++         <dc:rights>Creative Commons</dc:rights>+         <dc:language>es-AR</dc:language>++    By default, pandoc will include the following metadata elements:+    `<dc:title>` (from the document title), `<dc:creator>` (from the+    document authors), `<dc:date>` (from the document date, which should+    be in [ISO 8601 format]), `<dc:language>` (from the `lang`+    variable, or, if is not set, the locale), and `<dc:identifier+    id="BookId">` (a randomly generated UUID). Any of these may be+    overridden by elements in the metadata file.++    Note: if the source document is Markdown, a YAML metadata block+    in the document can be used instead.  See below under+    [EPUB Metadata].++`--epub-embed-font=`*FILE*++:   Embed the specified font in the EPUB. This option can be repeated+    to embed multiple fonts.  Wildcards can also be used: for example,+    `DejaVuSans-*.ttf`.  However, if you use wildcards on the command+    line, be sure to escape them or put the whole filename in single quotes,+    to prevent them from being interpreted by the shell. To use the+    embedded fonts, you will need to add declarations like the following+    to your CSS (see `--css`):++        @font-face {+        font-family: DejaVuSans;+        font-style: normal;+        font-weight: normal;+        src:url("DejaVuSans-Regular.ttf");+        }+        @font-face {+        font-family: DejaVuSans;+        font-style: normal;+        font-weight: bold;+        src:url("DejaVuSans-Bold.ttf");+        }+        @font-face {+        font-family: DejaVuSans;+        font-style: italic;+        font-weight: normal;+        src:url("DejaVuSans-Oblique.ttf");+        }+        @font-face {+        font-family: DejaVuSans;+        font-style: italic;+        font-weight: bold;+        src:url("DejaVuSans-BoldOblique.ttf");+        }+        body { font-family: "DejaVuSans"; }++`--epub-chapter-level=`*NUMBER*++:   Specify the header level at which to split the EPUB into separate+    "chapter" files. The default is to split into chapters at level 1+    headers. This option only affects the internal composition of the+    EPUB, not the way chapters and sections are displayed to users. Some+    readers may be slow if the chapter files are too large, so for large+    documents with few level 1 headers, one might want to use a chapter+    level of 2 or 3.++`--epub-subdirectory=`*DIRNAME*++:   Specify the subdirectory in the OCF container that is to hold+    the EPUB-specific contents.  The default is `EPUB`.  To put+    the EPUB contents in the top level, use an empty string.++`--pdf-engine=pdflatex`|`lualatex`|`xelatex`|`wkhtmltopdf`|`weasyprint`|`prince`|`context`|`pdfroff`++:   Use the specified engine when producing PDF output.+    The default is `pdflatex`.  If the engine is not in your PATH,+    the full path of the engine may be specified here.++`--pdf-engine-opt=`*STRING*++:   Use the given string as a command-line argument to the `pdf-engine`.+    If used multiple times, the arguments are provided with spaces between+    them. Note that no check for duplicate options is done.++[Dublin Core elements]: http://dublincore.org/documents/dces/+[ISO 8601 format]: http://www.w3.org/TR/NOTE-datetime++Citation rendering+------------------++`--bibliography=`*FILE*++:   Set the `bibliography` field in the document's metadata to *FILE*,+    overriding any value set in the metadata, and process citations+    using `pandoc-citeproc`. (This is equivalent to+    `--metadata bibliography=FILE --filter pandoc-citeproc`.)+    If `--natbib` or `--biblatex` is also supplied, `pandoc-citeproc` is not+    used, making this equivalent to `--metadata bibliography=FILE`.+    If you supply this argument multiple times, each *FILE* will be added+    to bibliography.++`--csl=`*FILE*++:   Set the `csl` field in the document's metadata to *FILE*,+    overriding any value set in the metadata.  (This is equivalent to+    `--metadata csl=FILE`.)+    This option is only relevant with `pandoc-citeproc`.++`--citation-abbreviations=`*FILE*++:   Set the `citation-abbreviations` field in the document's metadata to+    *FILE*, overriding any value set in the metadata.  (This is equivalent to+    `--metadata citation-abbreviations=FILE`.)+    This option is only relevant with `pandoc-citeproc`.++`--natbib`++:   Use [`natbib`] for citations in LaTeX output.  This option is not for use+    with the `pandoc-citeproc` filter or with PDF output.  It is intended for+    use in producing a LaTeX file that can be processed with [`bibtex`].++`--biblatex`++:   Use [`biblatex`] for citations in LaTeX output.  This option is not for use+    with the `pandoc-citeproc` filter or with PDF output. It is intended for+    use in producing a LaTeX file that can be processed with [`bibtex`] or [`biber`].++Math rendering in HTML+----------------------++`-m` [*URL*], `--latexmathml`[`=`*URL*]++:   Use the [LaTeXMathML] script to display embedded TeX math in HTML output.+    To insert a link to a local copy of the `LaTeXMathML.js` script,+    provide a *URL*. If no *URL* is provided, the contents of the+    script will be inserted directly into the HTML header, preserving+    portability at the price of efficiency. If you plan to use math on+    several pages, it is much better to link to a copy of the script,+    so it can be cached.++`--mathml`++:   Convert TeX math to [MathML] (in `docbook4`, `docbook5`, `jats`,+    `html4` and `html5`).  This is the default in `odt` output.++`--jsmath`[`=`*URL*]++:   Use [jsMath] to display embedded TeX math in HTML output.+    The *URL* should point to the jsMath load script (e.g.+    `jsMath/easy/load.js`); if provided, it will be linked to in+    the header of standalone HTML documents. If a *URL* is not provided,+    no link to the jsMath load script will be inserted; it is then+    up to the author to provide such a link in the HTML template.++`--mathjax`[`=`*URL*]++:   Use [MathJax] to display embedded TeX math in HTML output.+    The *URL* should point to the `MathJax.js` load script.+    If a *URL* is not provided, a link to the MathJax CDN will+    be inserted.++`--gladtex`++:   Enclose TeX math in `<eq>` tags in HTML output.  These can then+    be processed by [gladTeX] to produce links to images of the typeset+    formulas.++`--mimetex`[`=`*URL*]++:   Render TeX math using the [mimeTeX] CGI script.  If *URL* is not+    specified, it is assumed that the script is at `/cgi-bin/mimetex.cgi`.++`--webtex`[`=`*URL*]++:   Render TeX formulas using an external script that converts TeX+    formulas to images. The formula will be concatenated with the URL+    provided. If *URL* is not specified, the CodeCogs will be used.+    Note:  the `--webtex` option will affect Markdown output+    as well as HTML, which is useful if you're targeting a+    version of Markdown without native math support.++`--katex`[`=`*URL*]++:   Use [KaTeX] to display embedded TeX math in HTML output.+    The *URL* is the base URL for the KaTeX library. If a *URL* is+    not provided, a link to the KaTeX CDN will be inserted.+    Note: [KaTeX] seems to work best with `html5` output.++`--katex-stylesheet=`*URL*++:   The *URL* should point to the `katex.css` stylesheet. If this option is+    not specified, a link to the KaTeX CDN will be inserted. Note that this+    option does not imply `--katex`.++[MathML]: http://www.w3.org/Math/+[LaTeXMathML]: http://math.etsu.edu/LaTeXMathML/+[jsMath]: http://www.math.union.edu/~dpvc/jsmath/+[MathJax]: https://www.mathjax.org+[gladTeX]: http://ans.hsh.no/home/mgg/gladtex/+[mimeTeX]: http://www.forkosh.com/mimetex.html+[KaTeX]: https://github.com/Khan/KaTeX++Options for wrapper scripts+---------------------------++`--dump-args`++:   Print information about command-line arguments to *stdout*, then exit.+    This option is intended primarily for use in wrapper scripts.+    The first line of output contains the name of the output file specified+    with the `-o` option, or `-` (for *stdout*) if no output file was+    specified.  The remaining lines contain the command-line arguments,+    one per line, in the order they appear.  These do not include regular+    pandoc options and their arguments, but do include any options appearing+    after a `--` separator at the end of the line.++`--ignore-args`++:   Ignore command-line arguments (for use in wrapper scripts).+    Regular pandoc options are not ignored.  Thus, for example,++        pandoc --ignore-args -o foo.html -s foo.txt -- -e latin1++    is equivalent to++        pandoc -o foo.html -s++Templates+=========++When the `-s/--standalone` option is used, pandoc uses a template to+add header and footer material that is needed for a self-standing+document.  To see the default template that is used, just type++    pandoc -D *FORMAT*++where *FORMAT* is the name of the output format. A custom template+can be specified using the `--template` option.  You can also override+the system default templates for a given output format *FORMAT*+by putting a file `templates/default.*FORMAT*` in the user data+directory (see `--data-dir`, above). *Exceptions:*++- For `odt` output, customize the `default.opendocument`+  template.+- For `pdf` output, customize the `default.latex` template+  (or the `default.beamer` template, if you use `-t beamer`,+  or the `default.context` template, if you use `-t context`).+- `docx` has no template (however, you can use+  `--reference-doc` to customize the output).++Templates contain *variables*, which allow for the inclusion of+arbitrary information at any point in the file. Variables may be set+within the document using [YAML metadata blocks][Extension:+`yaml_metadata_block`].  They may also be set at the+command line using the `-V/--variable` option: variables set in this+way override metadata fields with the same name.++Variables set by pandoc+-----------------------++Some variables are set automatically by pandoc.  These vary somewhat+depending on the output format, but include metadata fields as well+as the following:++`sourcefile`, `outputfile`+:   source and destination filenames, as given on the command line.+    `sourcefile` can also be a list if input comes from multiple files, or empty+    if input is from stdin. You can use the following snippet in your template+    to distinguish them:++        $if(sourcefile)$+        $for(sourcefile)$+        $sourcefile$+        $endfor$+        $else$+        (stdin)+        $endif$++    Similarly, `outputfile` can be `-` if output goes to the terminal.++`title`, `author`, `date`+:   allow identification of basic aspects of the document.  Included+    in PDF metadata through LaTeX and ConTeXt.  These can be set+    through a [pandoc title block][Extension: `pandoc_title_block`],+    which allows for multiple authors, or through a YAML metadata block:++        ---+        author:+        - Aristotle+        - Peter Abelard+        ...++`subtitle`+:   document subtitle, included in HTML, EPUB, LaTeX, ConTeXt, and Word docx;+    renders in LaTeX only when using a document class that supports+    `\subtitle`, such as `beamer` or the [KOMA-Script] series (`scrartcl`,+    `scrreprt`, `scrbook`).[^subtitle]++`institute`+:   author affiliations (in LaTeX and Beamer only).  Can be a+    list, when there are multiple authors.++`abstract`+:   document summary, included in LaTeX, ConTeXt, AsciiDoc, and Word docx++`keywords`+:   list of keywords to be included in HTML, PDF, and AsciiDoc metadata;+    may be repeated as for `author`, above++`header-includes`+:   contents specified by `-H/--include-in-header` (may have multiple+    values)++`toc`+:   non-null value if `--toc/--table-of-contents` was specified++`toc-title`+:   title of table of contents (works only with EPUB,+    opendocument, odt, docx)++`include-before`+:   contents specified by `-B/--include-before-body` (may have+    multiple values)++`include-after`+:   contents specified by `-A/--include-after-body` (may have+    multiple values)++`body`+:   body of document++`meta-json`+:   JSON representation of all of the document's metadata. Field+    values are transformed to the selected output format.++[^subtitle]: To make `subtitle` work with other LaTeX+    document classes, you can add the following to `header-includes`:++        \providecommand{\subtitle}[1]{%+          \usepackage{titling}+          \posttitle{%+            \par\large#1\end{center}}+        }++Language variables+------------------++`lang`+:   identifies the main language of the document,+    using a code according to [BCP 47] (e.g. `en` or `en-GB`).+    For some output formats, pandoc will convert it to an appropriate+    format stored in the additional variables `babel-lang`,+    `polyglossia-lang` (LaTeX) and `context-lang` (ConTeXt).++    Native pandoc `span`s and `div`s with the lang attribute+    (value in BCP 47) can be used to switch the language in+    that range.++`otherlangs`+:   a list of other languages used in the document+    in the YAML metadata, according to [BCP 47]. For example:+    `otherlangs: [en-GB, fr]`.+    This is automatically generated from the `lang` attributes+    in all `span`s and `div`s but can be overridden.+    Currently only used by LaTeX through the generated+    `babel-otherlangs` and `polyglossia-otherlangs` variables.+    The LaTeX writer outputs polyglossia commands in the text but+    the `babel-newcommands` variable contains mappings for them+    to the corresponding babel.++`dir`+:   the base direction of the document, either `rtl` (right-to-left)+    or `ltr` (left-to-right).++    For bidirectional documents, native pandoc `span`s and `div`s+    with the `dir` attribute (value `rtl` or `ltr`) can be used to+    override the base direction in some output formats.+    This may not always be necessary if the final renderer+    (e.g. the browser, when generating HTML) supports the+    [Unicode Bidirectional Algorithm].++    When using LaTeX for bidirectional documents, only the `xelatex` engine+    is fully supported (use `--pdf-engine=xelatex`).++[BCP 47]: https://tools.ietf.org/html/bcp47+[Unicode Bidirectional Algorithm]: http://www.w3.org/International/articles/inline-bidi-markup/uba-basics++Variables for slides+--------------------++Variables are available for [producing slide shows with pandoc],+including all [reveal.js configuration options].++`titlegraphic`+:   title graphic for Beamer documents++`logo`+:   logo for Beamer documents++`slidy-url`+:   base URL for Slidy documents (defaults to+    `https://www.w3.org/Talks/Tools/Slidy2`)++`slideous-url`+:   base URL for Slideous documents (defaults to `slideous`)++`s5-url`+:   base URL for S5 documents (defaults to `s5/default`)++`revealjs-url`+:   base URL for reveal.js documents (defaults to `reveal.js`)++`theme`, `colortheme`, `fonttheme`, `innertheme`, `outertheme`+:   themes for LaTeX [`beamer`] documents++`themeoptions`+:   options for LaTeX beamer themes (a list).++`navigation`+:   controls navigation symbols in `beamer` documents+    (default is `empty` for no navigation symbols; other valid values+    are `frame`, `vertical`, and `horizontal`).++`section-titles`+:   enables on "title pages" for new sections in `beamer`+    documents (default = true).++`beamerarticle`+:   when true, the `beamerarticle` package is loaded (for+    producing an article from beamer slides).++`aspectratio`+:   aspect ratio of slides (for beamer only, `1610` for 16:10, `169` for 16:9,+    `149` for 14:9, `141` for 1.41:1, `54` for 5:4, `43` for 4:3 which is the+    default, and `32` for 3:2).++[reveal.js configuration options]: https://github.com/hakimel/reveal.js#configuration++Variables for LaTeX+-------------------++LaTeX variables are used when [creating a PDF].++`papersize`+:   paper size, e.g. `letter`, `a4`++`fontsize`+:   font size for body text (e.g. `10pt`, `12pt`)++`documentclass`+:   document class, e.g. [`article`], [`report`], [`book`], [`memoir`]++`classoption`+:   option for document class, e.g. `oneside`; may be repeated+    for multiple options++`geometry`+:   option for [`geometry`] package, e.g. `margin=1in`;+    may be repeated for multiple options++`margin-left`, `margin-right`, `margin-top`, `margin-bottom`+:   sets margins, if `geometry` is not used (otherwise `geometry`+    overrides these)++`linestretch`+:   adjusts line spacing using the [`setspace`]+    package, e.g. `1.25`, `1.5`++`fontfamily`+:   font package for use with `pdflatex`:+    [TeX Live] includes many options, documented in the [LaTeX Font Catalogue].+    The default is [Latin Modern][`lm`].++`fontfamilyoptions`+:   options for package used as `fontfamily`: e.g. `osf,sc` with+    `fontfamily` set to [`mathpazo`] provides Palatino with old-style+    figures and true small caps; may be repeated for multiple options++`mainfont`, `sansfont`, `monofont`, `mathfont`, `CJKmainfont`+:   font families for use with `xelatex` or+    `lualatex`: take the name of any system font, using the+    [`fontspec`] package.  Note that if `CJKmainfont` is used,+    the [`xecjk`] package must be available.++`mainfontoptions`, `sansfontoptions`, `monofontoptions`, `mathfontoptions`, `CJKoptions`+:   options to use with `mainfont`, `sansfont`, `monofont`, `mathfont`,+    `CJKmainfont` in `xelatex` and `lualatex`.  Allow for any choices+    available through [`fontspec`], such as the OpenType features+    `Numbers=OldStyle,Numbers=Proportional`. May be repeated for multiple options.++`fontenc`+:   allows font encoding to be specified through `fontenc` package (with `pdflatex`);+    default is `T1` (see guide to [LaTeX font encodings])++`microtypeoptions`+:    options to pass to the microtype package++`colorlinks`+:   add color to link text; automatically enabled if any of `linkcolor`, `citecolor`,+    `urlcolor`, or `toccolor` are set++`linkcolor`, `citecolor`, `urlcolor`, `toccolor`+:   color for internal links, citation links, external links, and links in table of contents:+    uses options allowed by [`xcolor`], including the `dvipsnames`, `svgnames`, and `x11names` lists++`links-as-notes`+:   causes links to be printed as footnotes++`indent`+:   uses document class settings for indentation (the default LaTeX template+    otherwise removes indentation and adds space between paragraphs)++`subparagraph`+:   disables default behavior of LaTeX template that redefines (sub)paragraphs+    as sections, changing the appearance of nested headings in some classes++`thanks`+:   specifies contents of acknowledgments footnote after document title.++`toc`+:   include table of contents (can also be set using `--toc/--table-of-contents`)++`toc-depth`+:   level of section to include in table of contents++`secnumdepth`+:   numbering depth for sections, if sections are numbered++`lof`, `lot`+:   include list of figures, list of tables++`bibliography`+:   bibliography to use for resolving references++`biblio-style`+:   bibliography style, when used with `--natbib` and `--biblatex`.++`biblio-title`+:   bibliography title, when used with `--natbib` and `--biblatex`.++`biblatexoptions`+:   list of options for biblatex.++`natbiboptions`+:   list of options for natbib.++[`article`]: https://ctan.org/pkg/article+[`report`]: https://ctan.org/pkg/report+[`book`]: https://ctan.org/pkg/book+[KOMA-Script]: https://ctan.org/pkg/koma-script+[`memoir`]: https://ctan.org/pkg/memoir+[`xcolor`]: https://ctan.org/pkg/xcolor+[LaTeX Font Catalogue]: http://www.tug.dk/FontCatalogue/+[`mathpazo`]: https://ctan.org/pkg/mathpazo+[LaTeX font encodings]: https://ctan.org/pkg/encguide++Variables for ConTeXt+---------------------++`papersize`+:   paper size, e.g. `letter`, `A4`, `landscape` (see [ConTeXt Paper Setup]);+    may be repeated for multiple options++`layout`+:   options for page margins and text arrangement (see [ConTeXt Layout]);+    may be repeated for multiple options++`margin-left`, `margin-right`, `margin-top`, `margin-bottom`+:   sets margins, if `layout` is not used (otherwise `layout`+    overrides these)++`fontsize`+:   font size for body text (e.g. `10pt`, `12pt`)++`mainfont`, `sansfont`, `monofont`, `mathfont`+:   font families: take the name of any system font (see [ConTeXt Font Switching])++`linkcolor`, `contrastcolor`+:   color for links outside and inside a page, e.g. `red`, `blue` (see [ConTeXt Color])++`linkstyle`+:   typeface style for links, e.g. `normal`, `bold`, `slanted`, `boldslanted`, `type`, `cap`, `small`++`indenting`+:   controls indentation of paragraphs, e.g. `yes,small,next` (see [ConTeXt Indentation]);+    may be repeated for multiple options++`whitespace`+:   spacing between paragraphs, e.g. `none`, `small` (using [`setupwhitespace`])++`interlinespace`+:   adjusts line spacing, e.g. `4ex` (using [`setupinterlinespace`]);+    may be repeated for multiple options++`headertext`, `footertext`+:   text to be placed in running header or footer (see [ConTeXt Headers and Footers]);+    may be repeated up to four times for different placement++`pagenumbering`+:   page number style and location (using [`setuppagenumbering`]);+    may be repeated for multiple options++`toc`+:   include table of contents (can also be set using `--toc/--table-of-contents`)++`lof`, `lot`+:   include list of figures, list of tables++[ConTeXt Paper Setup]: http://wiki.contextgarden.net/PaperSetup+[ConTeXt Layout]: http://wiki.contextgarden.net/Layout+[ConTeXt Font Switching]: http://wiki.contextgarden.net/Font_Switching+[ConTeXt Color]: http://wiki.contextgarden.net/Color+[ConTeXt Headers and Footers]: http://wiki.contextgarden.net/Headers_and_Footers+[ConTeXt Indentation]: http://wiki.contextgarden.net/Indentation+[`setupwhitespace`]: http://wiki.contextgarden.net/Command/setupwhitespace+[`setupinterlinespace`]: http://wiki.contextgarden.net/Command/setupinterlinespace+[`setuppagenumbering`]: http://wiki.contextgarden.net/Command/setuppagenumbering++Variables for man pages+-----------------------++`section`+:   section number in man pages++`header`+:   header in man pages++`footer`+:   footer in man pages++`adjusting`+:   adjusts text to left (`l`), right (`r`), center (`c`),+    or both (`b`) margins++`hyphenate`+:   if `true` (the default), hyphenation will be used++Variables for ms+----------------++`pointsize`+:    point size (e.g. `10p`)++`lineheight`+:    line height (e.g. `12p`)++`fontfamily`+:    font family (e.g. `T` or `P`)++`indent`+:    paragraph indent (e.g. `2m`)++Using variables in templates+----------------------------++Variable names are sequences of alphanumerics, `-`, and `_`,+starting with a letter.  A variable name surrounded by `$` signs+will be replaced by its value.  For example, the string `$title$` in++    <title>$title$</title>++will be replaced by the document title.++To write a literal `$` in a template, use `$$`.++Templates may contain conditionals.  The syntax is as follows:++    $if(variable)$+    X+    $else$+    Y+    $endif$++This will include `X` in the template if `variable` has a non-null+value; otherwise it will include `Y`. `X` and `Y` are placeholders for+any valid template text, and may include interpolated variables or other+conditionals. The `$else$` section may be omitted.++When variables can have multiple values (for example, `author` in+a multi-author document), you can use the `$for$` keyword:++    $for(author)$+    <meta name="author" content="$author$" />+    $endfor$++You can optionally specify a separator to be used between+consecutive items:++    $for(author)$$author$$sep$, $endfor$++A dot can be used to select a field of a variable that takes+an object as its value.  So, for example:++    $author.name$ ($author.affiliation$)++If you use custom templates, you may need to revise them as pandoc+changes.  We recommend tracking the changes in the default templates,+and modifying your custom templates accordingly. An easy way to do this+is to fork the [pandoc-templates] repository and merge in changes after each+pandoc release.++Templates may contain comments:  anything on a line after `$--`+will be treated as a comment and ignored.++[pandoc-templates]: https://github.com/jgm/pandoc-templates++Pandoc's Markdown+=================++Pandoc understands an extended and slightly revised version of+John Gruber's [Markdown] syntax.  This document explains the syntax,+noting differences from standard Markdown. Except where noted, these+differences can be suppressed by using the `markdown_strict` format instead+of `markdown`.  An extensions can be enabled by adding `+EXTENSION`+to the format name and disabled by adding `-EXTENSION`. For example,+`markdown_strict+footnotes` is strict Markdown with footnotes+enabled, while `markdown-footnotes-pipe_tables` is pandoc's+Markdown without footnotes or pipe tables.++Philosophy+----------++Markdown is designed to be easy to write, and, even more importantly,+easy to read:++> A Markdown-formatted document should be publishable as-is, as plain+> text, without looking like it's been marked up with tags or formatting+> instructions.+> -- [John Gruber](http://daringfireball.net/projects/markdown/syntax#philosophy)++This principle has guided pandoc's decisions in finding syntax for+tables, footnotes, and other extensions.++There is, however, one respect in which pandoc's aims are different+from the original aims of Markdown.  Whereas Markdown was originally+designed with HTML generation in mind, pandoc is designed for multiple+output formats.  Thus, while pandoc allows the embedding of raw HTML,+it discourages it, and provides other, non-HTMLish ways of representing+important document elements like definition lists, tables, mathematics, and+footnotes.++Paragraphs+----------++A paragraph is one or more lines of text followed by one or more blank lines.+Newlines are treated as spaces, so you can reflow your paragraphs as you like.+If you need a hard line break, put two or more spaces at the end of a line.++#### Extension: `escaped_line_breaks` ####++A backslash followed by a newline is also a hard line break.+Note:  in multiline and grid table cells, this is the only way+to create a hard line break, since trailing spaces in the cells+are ignored.++Headers+-------++There are two kinds of headers: Setext and ATX.++### Setext-style headers ###++A setext-style header is a line of text "underlined" with a row of `=` signs+(for a level one header) or `-` signs (for a level two header):++    A level-one header+    ==================++    A level-two header+    ------------------++The header text can contain inline formatting, such as emphasis (see+[Inline formatting], below).+++### ATX-style headers ###++An ATX-style header consists of one to six `#` signs and a line of+text, optionally followed by any number of `#` signs.  The number of+`#` signs at the beginning of the line is the header level:++    ## A level-two header++    ### A level-three header ###++As with setext-style headers, the header text can contain formatting:++    # A level-one header with a [link](/url) and *emphasis*++#### Extension: `blank_before_header` ####++Standard Markdown syntax does not require a blank line before a header.+Pandoc does require this (except, of course, at the beginning of the+document). The reason for the requirement is that it is all too easy for a+`#` to end up at the beginning of a line by accident (perhaps through line+wrapping). Consider, for example:++    I like several of their flavors of ice cream:+    #22, for example, and #5.++#### Extension: `space_in_atx_header` ####++Many Markdown implementations do not require a space between the+opening `#`s of an ATX header and the header text, so that+`#5 bolt` and `#hashtag` count as headers.  With this extension,+pandoc does require the space.++### Header identifiers ###++#### Extension: `header_attributes` ####++Headers can be assigned attributes using this syntax at the end+of the line containing the header text:++    {#identifier .class .class key=value key=value}++Thus, for example, the following headers will all be assigned the identifier+`foo`:++    # My header {#foo}++    ## My header ##    {#foo}++    My other header   {#foo}+    ---------------++(This syntax is compatible with [PHP Markdown Extra].)++Note that although this syntax allows assignment of classes and key/value+attributes, writers generally don't use all of this information.  Identifiers,+classes, and key/value attributes are used in HTML and HTML-based formats such+as EPUB and slidy.  Identifiers are used for labels and link anchors in the+LaTeX, ConTeXt, Textile, and AsciiDoc writers.++Headers with the class `unnumbered` will not be numbered, even if+`--number-sections` is specified.  A single hyphen (`-`) in an attribute+context is equivalent to `.unnumbered`, and preferable in non-English+documents.  So,++    # My header {-}++is just the same as++    # My header {.unnumbered}++#### Extension: `auto_identifiers` ####++A header without an explicitly specified identifier will be+automatically assigned a unique identifier based on the header text.+To derive the identifier from the header text,++  - Remove all formatting, links, etc.+  - Remove all footnotes.+  - Remove all punctuation, except underscores, hyphens, and periods.+  - Replace all spaces and newlines with hyphens.+  - Convert all alphabetic characters to lowercase.+  - Remove everything up to the first letter (identifiers may+    not begin with a number or punctuation mark).+  - If nothing is left after this, use the identifier `section`.++Thus, for example,++  Header                            Identifier+  -------------------------------   ----------------------------+  `Header identifiers in HTML`      `header-identifiers-in-html`+  `*Dogs*?--in *my* house?`         `dogs--in-my-house`+  `[HTML], [S5], or [RTF]?`         `html-s5-or-rtf`+  `3. Applications`                 `applications`+  `33`                              `section`++These rules should, in most cases, allow one to determine the identifier+from the header text. The exception is when several headers have the+same text; in this case, the first will get an identifier as described+above; the second will get the same identifier with `-1` appended; the+third with `-2`; and so on.++These identifiers are used to provide link targets in the table of+contents generated by the `--toc|--table-of-contents` option. They+also make it easy to provide links from one section of a document to+another. A link to this section, for example, might look like this:++    See the section on+    [header identifiers](#header-identifiers-in-html-latex-and-context).++Note, however, that this method of providing links to sections works+only in HTML, LaTeX, and ConTeXt formats.++If the `--section-divs` option is specified, then each section will+be wrapped in a `div` (or a `section`, if `html5` was specified),+and the identifier will be attached to the enclosing `<div>`+(or `<section>`) tag rather than the header itself. This allows entire+sections to be manipulated using JavaScript or treated differently in+CSS.++#### Extension: `implicit_header_references` ####++Pandoc behaves as if reference links have been defined for each header.+So, to link to a header++    # Header identifiers in HTML++you can simply write++    [Header identifiers in HTML]++or++    [Header identifiers in HTML][]++or++    [the section on header identifiers][header identifiers in+    HTML]++instead of giving the identifier explicitly:++    [Header identifiers in HTML](#header-identifiers-in-html)++If there are multiple headers with identical text, the corresponding+reference will link to the first one only, and you will need to use explicit+links to link to the others, as described above.++Like regular reference links, these references are case-insensitive.++Explicit link reference definitions always take priority over+implicit header references.  So, in the following example, the+link will point to `bar`, not to `#foo`:++    # Foo++    [foo]: bar++    See [foo]++Block quotations+----------------++Markdown uses email conventions for quoting blocks of text.+A block quotation is one or more paragraphs or other block elements+(such as lists or headers), with each line preceded by a `>` character+and an optional space. (The `>` need not start at the left margin, but+it should not be indented more than three spaces.)++    > This is a block quote. This+    > paragraph has two lines.+    >+    > 1. This is a list inside a block quote.+    > 2. Second item.++A "lazy" form, which requires the `>` character only on the first+line of each block, is also allowed:++    > This is a block quote. This+    paragraph has two lines.++    > 1. This is a list inside a block quote.+    2. Second item.++Among the block elements that can be contained in a block quote are+other block quotes. That is, block quotes can be nested:++    > This is a block quote.+    >+    > > A block quote within a block quote.++If the `>` character is followed by an optional space, that space+will be considered part of the block quote marker and not part of+the indentation of the contents.  Thus, to put an indented code+block in a block quote, you need five spaces after the `>`:++    >     code++#### Extension: `blank_before_blockquote` ####++Standard Markdown syntax does not require a blank line before a block+quote.  Pandoc does require this (except, of course, at the beginning of the+document). The reason for the requirement is that it is all too easy for a+`>` to end up at the beginning of a line by accident (perhaps through line+wrapping). So, unless the `markdown_strict` format is used, the following does+not produce a nested block quote in pandoc:++    > This is a block quote.+    >> Nested.+++Verbatim (code) blocks+----------------------++### Indented code blocks ###++A block of text indented four spaces (or one tab) is treated as verbatim+text: that is, special characters do not trigger special formatting,+and all spaces and line breaks are preserved.  For example,++        if (a > 3) {+          moveShip(5 * gravity, DOWN);+        }++The initial (four space or one tab) indentation is not considered part+of the verbatim text, and is removed in the output.++Note: blank lines in the verbatim text need not begin with four spaces.+++### Fenced code blocks ###++#### Extension: `fenced_code_blocks` ####++In addition to standard indented code blocks, pandoc supports+*fenced* code blocks.  These begin with a row of three or more+tildes (`~`) and end with a row of tildes that must be at least as long as+the starting row. Everything between these lines is treated as code. No+indentation is necessary:++    ~~~~~~~+    if (a > 3) {+      moveShip(5 * gravity, DOWN);+    }+    ~~~~~~~++Like regular code blocks, fenced code blocks must be separated+from surrounding text by blank lines.++If the code itself contains a row of tildes or backticks, just use a longer+row of tildes or backticks at the start and end:++    ~~~~~~~~~~~~~~~~+    ~~~~~~~~~~+    code including tildes+    ~~~~~~~~~~+    ~~~~~~~~~~~~~~~~++#### Extension: `backtick_code_blocks` ####++Same as `fenced_code_blocks`, but uses backticks (`` ` ``) instead of tildes+(`~`).++#### Extension: `fenced_code_attributes` ####++Optionally, you may attach attributes to fenced or backtick code block using+this syntax:++    ~~~~ {#mycode .haskell .numberLines startFrom="100"}+    qsort []     = []+    qsort (x:xs) = qsort (filter (< x) xs) ++ [x] +++                   qsort (filter (>= x) xs)+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~++Here `mycode` is an identifier, `haskell` and `numberLines` are classes, and+`startFrom` is an attribute with value `100`. Some output formats can use this+information to do syntax highlighting. Currently, the only output formats+that uses this information are HTML, LaTeX, Docx, and Ms. If highlighting+is supported for your output format and language, then the code block above+will appear highlighted, with numbered lines. (To see which languages are+supported, type `pandoc --list-highlight-languages`.) Otherwise, the code+block above will appear as follows:++    <pre id="mycode" class="haskell numberLines" startFrom="100">+      <code>+      ...+      </code>+    </pre>++A shortcut form can also be used for specifying the language of+the code block:++    ```haskell+    qsort [] = []+    ```++This is equivalent to:++    ``` {.haskell}+    qsort [] = []+    ```++If the `fenced_code_attributes` extension is disabled, but+input contains class attribute(s) for the code block, the first+class attribute will be printed after the opening fence as a bare+word.++To prevent all highlighting, use the `--no-highlight` flag.+To set the highlighting style, use `--highlight-style`.+For more information on highlighting, see [Syntax highlighting],+below.++Line blocks+-----------++#### Extension: `line_blocks` ####++A line block is a sequence of lines beginning with a vertical bar (`|`)+followed by a space.  The division into lines will be preserved in+the output, as will any leading spaces; otherwise, the lines will+be formatted as Markdown.  This is useful for verse and addresses:++    | The limerick packs laughs anatomical+    | In space that is quite economical.+    |    But the good ones I've seen+    |    So seldom are clean+    | And the clean ones so seldom are comical++    | 200 Main St.+    | Berkeley, CA 94718++The lines can be hard-wrapped if needed, but the continuation+line must begin with a space.++    | The Right Honorable Most Venerable and Righteous Samuel L.+      Constable, Jr.+    | 200 Main St.+    | Berkeley, CA 94718++This syntax is borrowed from [reStructuredText].++Lists+-----++### Bullet lists ###++A bullet list is a list of bulleted list items.  A bulleted list+item begins with a bullet (`*`, `+`, or `-`).  Here is a simple+example:++    * one+    * two+    * three++This will produce a "compact" list. If you want a "loose" list, in which+each item is formatted as a paragraph, put spaces between the items:++    * one++    * two++    * three++The bullets need not be flush with the left margin; they may be+indented one, two, or three spaces. The bullet must be followed+by whitespace.++List items look best if subsequent lines are flush with the first+line (after the bullet):++    * here is my first+      list item.+    * and my second.++But Markdown also allows a "lazy" format:++    * here is my first+    list item.+    * and my second.++### Block content in list items ###++A list item may contain multiple paragraphs and other block-level+content. However, subsequent paragraphs must be preceded by a blank line+and indented to line up with the first non-space content after+the list marker.++      * First paragraph.++        Continued.++      * Second paragraph. With a code block, which must be indented+        eight spaces:++            { code }++Exception: if the list marker is followed by an indented code+block, which must begin 5 spaces after the list marker, then+subsequent paragraphs must begin two columns after the last+character of the list marker:++    *     code++      continuation paragraph++List items may include other lists.  In this case the preceding blank+line is optional.  The nested list must be indented to line up with+the first non-space character after the list marker of the+containing list item.++    * fruits+      + apples+        - macintosh+        - red delicious+      + pears+      + peaches+    * vegetables+      + broccoli+      + chard++As noted above, Markdown allows you to write list items "lazily," instead of+indenting continuation lines. However, if there are multiple paragraphs or+other blocks in a list item, the first line of each must be indented.++    + A lazy, lazy, list+    item.++    + Another one; this looks+    bad but is legal.++        Second paragraph of second+    list item.++### Ordered lists ###++Ordered lists work just like bulleted lists, except that the items+begin with enumerators rather than bullets.++In standard Markdown, enumerators are decimal numbers followed+by a period and a space.  The numbers themselves are ignored, so+there is no difference between this list:++    1.  one+    2.  two+    3.  three++and this one:++    5.  one+    7.  two+    1.  three++#### Extension: `fancy_lists` ####++Unlike standard Markdown, pandoc allows ordered list items to be marked+with uppercase and lowercase letters and roman numerals, in addition to+Arabic numerals. List markers may be enclosed in parentheses or followed by a+single right-parentheses or period. They must be separated from the+text that follows by at least one space, and, if the list marker is a+capital letter with a period, by at least two spaces.[^2]++[^2]:  The point of this rule is to ensure that normal paragraphs+    starting with people's initials, like++        B. Russell was an English philosopher.++    do not get treated as list items.++    This rule will not prevent++        (C) 2007 Joe Smith++    from being interpreted as a list item.  In this case, a backslash+    escape can be used:++        (C\) 2007 Joe Smith++The `fancy_lists` extension also allows '`#`' to be used as an+ordered list marker in place of a numeral:++    #. one+    #. two++#### Extension: `startnum` ####++Pandoc also pays attention to the type of list marker used, and to the+starting number, and both of these are preserved where possible in the+output format. Thus, the following yields a list with numbers followed+by a single parenthesis, starting with 9, and a sublist with lowercase+roman numerals:++     9)  Ninth+    10)  Tenth+    11)  Eleventh+           i. subone+          ii. subtwo+         iii. subthree++Pandoc will start a new list each time a different type of list+marker is used.  So, the following will create three lists:++    (2) Two+    (5) Three+    1.  Four+    *   Five++If default list markers are desired, use `#.`:++    #.  one+    #.  two+    #.  three+++### Definition lists ###++#### Extension: `definition_lists` ####++Pandoc supports definition lists, using the syntax of+[PHP Markdown Extra] with some extensions.[^3]++    Term 1++    :   Definition 1++    Term 2 with *inline markup*++    :   Definition 2++            { some code, part of Definition 2 }++        Third paragraph of definition 2.++Each term must fit on one line, which may optionally be followed by+a blank line, and must be followed by one or more definitions.+A definition begins with a colon or tilde, which may be indented one+or two spaces.++A term may have multiple definitions, and each definition may consist of one or+more block elements (paragraph, code block, list, etc.), each indented four+spaces or one tab stop.  The body of the definition (including the first line,+aside from the colon or tilde) should be indented four spaces. However,+as with other Markdown lists, you can "lazily" omit indentation except+at the beginning of a paragraph or other block element:++    Term 1++    :   Definition+    with lazy continuation.++        Second paragraph of the definition.++If you leave space before the definition (as in the example above),+the text of the definition will be treated as a paragraph.  In some+output formats, this will mean greater spacing between term/definition+pairs. For a more compact definition list, omit the space before the+definition:++    Term 1+      ~ Definition 1++    Term 2+      ~ Definition 2a+      ~ Definition 2b++Note that space between items in a definition list is required.+(A variant that loosens this requirement, but disallows "lazy"+hard wrapping, can be activated with `compact_definition_lists`: see+[Non-pandoc extensions], below.)++[^3]:  I have been influenced by the suggestions of [David Wheeler](http://www.justatheory.com/computers/markup/modest-markdown-proposal.html).++### Numbered example lists ###++#### Extension: `example_lists` ####++The special list marker `@` can be used for sequentially numbered+examples. The first list item with a `@` marker will be numbered '1',+the next '2', and so on, throughout the document. The numbered examples+need not occur in a single list; each new list using `@` will take up+where the last stopped. So, for example:++    (@)  My first example will be numbered (1).+    (@)  My second example will be numbered (2).++    Explanation of examples.++    (@)  My third example will be numbered (3).++Numbered examples can be labeled and referred to elsewhere in the+document:++    (@good)  This is a good example.++    As (@good) illustrates, ...++The label can be any string of alphanumeric characters, underscores,+or hyphens.+++### Compact and loose lists ###++Pandoc behaves differently from `Markdown.pl` on some "edge+cases" involving lists.  Consider this source:++    +   First+    +   Second:+    	-   Fee+    	-   Fie+    	-   Foe++    +   Third++Pandoc transforms this into a "compact list" (with no `<p>` tags around+"First", "Second", or "Third"), while Markdown puts `<p>` tags around+"Second" and "Third" (but not "First"), because of the blank space+around "Third". Pandoc follows a simple rule: if the text is followed by+a blank line, it is treated as a paragraph. Since "Second" is followed+by a list, and not a blank line, it isn't treated as a paragraph. The+fact that the list is followed by a blank line is irrelevant. (Note:+Pandoc works this way even when the `markdown_strict` format is specified. This+behavior is consistent with the official Markdown syntax description,+even though it is different from that of `Markdown.pl`.)+++### Ending a list ###++What if you want to put an indented code block after a list?++    -   item one+    -   item two++        { my code block }++Trouble! Here pandoc (like other Markdown implementations) will treat+`{ my code block }` as the second paragraph of item two, and not as+a code block.++To "cut off" the list after item two, you can insert some non-indented+content, like an HTML comment, which won't produce visible output in+any format:++    -   item one+    -   item two++    <!-- end of list -->++        { my code block }++You can use the same trick if you want two consecutive lists instead+of one big list:++    1.  one+    2.  two+    3.  three++    <!-- -->++    1.  uno+    2.  dos+    3.  tres++Horizontal rules+----------------++A line containing a row of three or more `*`, `-`, or `_` characters+(optionally separated by spaces) produces a horizontal rule:++    *  *  *  *++    ---------------+++Tables+------++Four kinds of tables may be used. The first three kinds presuppose the use of+a fixed-width font, such as Courier. The fourth kind can be used with+proportionally spaced fonts, as it does not require lining up columns.++#### Extension: `table_captions` ####++A caption may optionally be provided with all 4 kinds of tables (as+illustrated in the examples below). A caption is a paragraph beginning+with the string `Table:` (or just `:`), which will be stripped off.+It may appear either before or after the table.++#### Extension: `simple_tables` ####++Simple tables look like this:++      Right     Left     Center     Default+    -------     ------ ----------   -------+         12     12        12            12+        123     123       123          123+          1     1          1             1++    Table:  Demonstration of simple table syntax.++The headers and table rows must each fit on one line.  Column+alignments are determined by the position of the header text relative+to the dashed line below it:[^4]++  - If the dashed line is flush with the header text on the right side+    but extends beyond it on the left, the column is right-aligned.+  - If the dashed line is flush with the header text on the left side+    but extends beyond it on the right, the column is left-aligned.+  - If the dashed line extends beyond the header text on both sides,+    the column is centered.+  - If the dashed line is flush with the header text on both sides,+    the default alignment is used (in most cases, this will be left).++[^4]:  This scheme is due to Michel Fortin, who proposed it on the+       [Markdown discussion list](http://six.pairlist.net/pipermail/markdown-discuss/2005-March/001097.html).++The table must end with a blank line, or a line of dashes followed by+a blank line.++The column headers may be omitted, provided a dashed line is used+to end the table. For example:++    -------     ------ ----------   -------+         12     12        12             12+        123     123       123           123+          1     1          1              1+    -------     ------ ----------   -------++When headers are omitted, column alignments are determined on the basis+of the first line of the table body. So, in the tables above, the columns+would be right, left, center, and right aligned, respectively.++#### Extension: `multiline_tables` ####++Multiline tables allow headers and table rows to span multiple lines+of text (but cells that span multiple columns or rows of the table are+not supported).  Here is an example:++    -------------------------------------------------------------+     Centered   Default           Right Left+      Header    Aligned         Aligned Aligned+    ----------- ------- --------------- -------------------------+       First    row                12.0 Example of a row that+                                        spans multiple lines.++      Second    row                 5.0 Here's another one. Note+                                        the blank line between+                                        rows.+    -------------------------------------------------------------++    Table: Here's the caption. It, too, may span+    multiple lines.++These work like simple tables, but with the following differences:++  - They must begin with a row of dashes, before the header text+    (unless the headers are omitted).+  - They must end with a row of dashes, then a blank line.+  - The rows must be separated by blank lines.++In multiline tables, the table parser pays attention to the widths of+the columns, and the writers try to reproduce these relative widths in+the output. So, if you find that one of the columns is too narrow in the+output, try widening it in the Markdown source.++Headers may be omitted in multiline tables as well as simple tables:++    ----------- ------- --------------- -------------------------+       First    row                12.0 Example of a row that+                                        spans multiple lines.++      Second    row                 5.0 Here's another one. Note+                                        the blank line between+                                        rows.+    ----------- ------- --------------- -------------------------++    : Here's a multiline table without headers.++It is possible for a multiline table to have just one row, but the row+should be followed by a blank line (and then the row of dashes that ends+the table), or the table may be interpreted as a simple table.++#### Extension: `grid_tables` ####++Grid tables look like this:++    : Sample grid table.++    +---------------+---------------+--------------------++    | Fruit         | Price         | Advantages         |+    +===============+===============+====================++    | Bananas       | $1.34         | - built-in wrapper |+    |               |               | - bright color     |+    +---------------+---------------+--------------------++    | Oranges       | $2.10         | - cures scurvy     |+    |               |               | - tasty            |+    +---------------+---------------+--------------------+++The row of `=`s separates the header from the table body, and can be+omitted for a headerless table. The cells of grid tables may contain+arbitrary block elements (multiple paragraphs, code blocks, lists,+etc.). Cells that span multiple columns or rows are not+supported. Grid tables can be created easily using [Emacs table mode].++[Emacs table mode]: http://table.sourceforge.net/++Alignments can be specified as with pipe tables, by putting+colons at the boundaries of the separator line after the+header:++    +---------------+---------------+--------------------++    | Right         | Left          | Centered           |+    +==============:+:==============+:==================:++    | Bananas       | $1.34         | built-in wrapper   |+    +---------------+---------------+--------------------+++For headerless tables, the colons go on the top line instead:++    +--------------:+:--------------+:------------------:++    | Right         | Left          | Centered           |+    +---------------+---------------+--------------------+++##### Grid Table Limitations #####++Pandoc does not support grid tables with row spans or column spans.+This means that neither variable numbers of columns across rows nor+variable numbers of rows across columns are supported by Pandoc.+All grid tables must have the same number of columns in each row,+and the same number of rows in each column.  For example, the+Docutils [sample grid tables] will not render as expected with+Pandoc.++[sample grid tables]: http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html#grid-tables+++#### Extension: `pipe_tables` ####++Pipe tables look like this:++    | Right | Left | Default | Center |+    |------:|:-----|---------|:------:|+    |   12  |  12  |    12   |    12  |+    |  123  |  123 |   123   |   123  |+    |    1  |    1 |     1   |     1  |++      : Demonstration of pipe table syntax.++The syntax is identical to [PHP Markdown Extra tables].  The beginning and+ending pipe characters are optional, but pipes are required between all+columns.  The colons indicate column alignment as shown.  The header+cannot be omitted.  To simulate a headerless table, include a header+with blank cells.++Since the pipes indicate column boundaries, columns need not be vertically+aligned, as they are in the above example.  So, this is a perfectly+legal (though ugly) pipe table:++    fruit| price+    -----|-----:+    apple|2.05+    pear|1.37+    orange|3.09++The cells of pipe tables cannot contain block elements like paragraphs+and lists, and cannot span multiple lines.  If a pipe table contains a+row whose printable content is wider than the column width (see+`--columns`), then the cell contents will wrap, with the+relative cell widths determined by the widths of the separator+lines.++Note:  pandoc also recognizes pipe tables of the following+form, as can be produced by Emacs' orgtbl-mode:++    | One | Two   |+    |-----+-------|+    | my  | table |+    | is  | nice  |++The difference is that `+` is used instead of `|`. Other orgtbl features+are not supported. In particular, to get non-default column alignment,+you'll need to add colons as above.++[PHP Markdown Extra tables]: https://michelf.ca/projects/php-markdown/extra/#table++Metadata blocks+---------------++#### Extension: `pandoc_title_block` ####++If the file begins with a title block++    % title+    % author(s) (separated by semicolons)+    % date++it will be parsed as bibliographic information, not regular text.  (It+will be used, for example, in the title of standalone LaTeX or HTML+output.)  The block may contain just a title, a title and an author,+or all three elements. If you want to include an author but no+title, or a title and a date but no author, you need a blank line:++    %+    % Author++    % My title+    %+    % June 15, 2006++The title may occupy multiple lines, but continuation lines must+begin with leading space, thus:++    % My title+      on multiple lines++If a document has multiple authors, the authors may be put on+separate lines with leading space, or separated by semicolons, or+both.  So, all of the following are equivalent:++    % Author One+      Author Two++    % Author One; Author Two++    % Author One;+      Author Two++The date must fit on one line.++All three metadata fields may contain standard inline formatting+(italics, links, footnotes, etc.).++Title blocks will always be parsed, but they will affect the output only+when the `--standalone` (`-s`) option is chosen. In HTML output, titles+will appear twice: once in the document head -- this is the title that+will appear at the top of the window in a browser -- and once at the+beginning of the document body. The title in the document head can have+an optional prefix attached (`--title-prefix` or `-T` option). The title+in the body appears as an H1 element with class "title", so it can be+suppressed or reformatted with CSS. If a title prefix is specified with+`-T` and no title block appears in the document, the title prefix will+be used by itself as the HTML title.++The man page writer extracts a title, man page section number, and+other header and footer information from the title line. The title+is assumed to be the first word on the title line, which may optionally+end with a (single-digit) section number in parentheses. (There should+be no space between the title and the parentheses.)  Anything after+this is assumed to be additional footer and header text. A single pipe+character (`|`) should be used to separate the footer text from the header+text.  Thus,++    % PANDOC(1)++will yield a man page with the title `PANDOC` and section 1.++    % PANDOC(1) Pandoc User Manuals++will also have "Pandoc User Manuals" in the footer.++    % PANDOC(1) Pandoc User Manuals | Version 4.0++will also have "Version 4.0" in the header.++#### Extension: `yaml_metadata_block` ####++A YAML metadata block is a valid YAML object, delimited by a line of three+hyphens (`---`) at the top and a line of three hyphens (`---`) or three dots+(`...`) at the bottom.  A YAML metadata block may occur anywhere in the+document, but if it is not at the beginning, it must be preceded by a blank+line.  (Note that, because of the way pandoc concatenates input files when+several are provided, you may also keep the metadata in a separate YAML file+and pass it to pandoc as an argument, along with your Markdown files:++    pandoc chap1.md chap2.md chap3.md metadata.yaml -s -o book.html++Just be sure that the YAML file begins with `---` and ends with `---` or+`...`.)++Metadata will be taken from the fields of the YAML object and added to any+existing document metadata.  Metadata can contain lists and objects (nested+arbitrarily), but all string scalars will be interpreted as Markdown.  Fields+with names ending in an underscore will be ignored by pandoc.  (They may be+given a role by external processors.)++A document may contain multiple metadata blocks.  The metadata fields will+be combined through a *left-biased union*:  if two metadata blocks attempt+to set the same field, the value from the first block will be taken.++When pandoc is used with `-t markdown` to create a Markdown document,+a YAML metadata block will be produced only if the `-s/--standalone`+option is used.  All of the metadata will appear in a single block+at the beginning of the document.++Note that YAML escaping rules must be followed. Thus, for example,+if a title contains a colon, it must be quoted.  The pipe character+(`|`) can be used to begin an indented block that will be interpreted+literally, without need for escaping.  This form is necessary+when the field contains blank lines or block-level formatting:++    ---+    title:  'This is the title: it contains a colon'+    author:+    - Author One+    - Author Two+    tags: [nothing, nothingness]+    abstract: |+      This is the abstract.++      It consists of two paragraphs.+    ...++Template variables will be set automatically from the metadata.  Thus, for+example, in writing HTML, the variable `abstract` will be set to the HTML+equivalent of the Markdown in the `abstract` field:++    <p>This is the abstract.</p>+    <p>It consists of two paragraphs.</p>++Variables can contain arbitrary YAML structures, but the template must match+this structure.  The `author` variable in the default templates expects a+simple list or string, but can be changed to support more complicated+structures.  The following combination, for example, would add an affiliation+to the author if one is given:++    ---+    title: The document title+    author:+    - name: Author One+      affiliation: University of Somewhere+    - name: Author Two+      affiliation: University of Nowhere+    ...++To use the structured authors in the example above, you would need a custom+template:++    $for(author)$+    $if(author.name)$+    $author.name$$if(author.affiliation)$ ($author.affiliation$)$endif$+    $else$+    $author$+    $endif$+    $endfor$+++Backslash escapes+-----------------++#### Extension: `all_symbols_escapable` ####++Except inside a code block or inline code, any punctuation or space+character preceded by a backslash will be treated literally, even if it+would normally indicate formatting.  Thus, for example, if one writes++    *\*hello\**++one will get++    <em>*hello*</em>++instead of++    <strong>hello</strong>++This rule is easier to remember than standard Markdown's rule,+which allows only the following characters to be backslash-escaped:++    \`*_{}[]()>#+-.!++(However, if the `markdown_strict` format is used, the standard Markdown rule+will be used.)++A backslash-escaped space is parsed as a nonbreaking space.  It will+appear in TeX output as `~` and in HTML and XML as `\&#160;` or+`\&nbsp;`.++A backslash-escaped newline (i.e. a backslash occurring at the end of+a line) is parsed as a hard line break.  It will appear in TeX output as+`\\` and in HTML as `<br />`.  This is a nice alternative to+Markdown's "invisible" way of indicating hard line breaks using+two trailing spaces on a line.++Backslash escapes do not work in verbatim contexts.++Inline formatting+-----------------++### Emphasis ###++To *emphasize* some text, surround it with `*`s or `_`, like this:++    This text is _emphasized with underscores_, and this+    is *emphasized with asterisks*.++Double `*` or `_` produces **strong emphasis**:++    This is **strong emphasis** and __with underscores__.++A `*` or `_` character surrounded by spaces, or backslash-escaped,+will not trigger emphasis:++    This is * not emphasized *, and \*neither is this\*.++#### Extension: `intraword_underscores` ####++Because `_` is sometimes used inside words and identifiers,+pandoc does not interpret a `_` surrounded by alphanumeric+characters as an emphasis marker.  If you want to emphasize+just part of a word, use `*`:++    feas*ible*, not feas*able*.+++### Strikeout ###++#### Extension: `strikeout` ####++To strikeout a section of text with a horizontal line, begin and end it+with `~~`. Thus, for example,++    This ~~is deleted text.~~+++### Superscripts and subscripts ###++#### Extension: `superscript`, `subscript` ####++Superscripts may be written by surrounding the superscripted text by `^`+characters; subscripts may be written by surrounding the subscripted+text by `~` characters.  Thus, for example,++    H~2~O is a liquid.  2^10^ is 1024.++If the superscripted or subscripted text contains spaces, these spaces+must be escaped with backslashes.  (This is to prevent accidental+superscripting and subscripting through the ordinary use of `~` and `^`.)+Thus, if you want the letter P with 'a cat' in subscripts, use+`P~a\ cat~`, not `P~a cat~`.+++### Verbatim ###++To make a short span of text verbatim, put it inside backticks:++    What is the difference between `>>=` and `>>`?++If the verbatim text includes a backtick, use double backticks:++    Here is a literal backtick `` ` ``.++(The spaces after the opening backticks and before the closing+backticks will be ignored.)++The general rule is that a verbatim span starts with a string+of consecutive backticks (optionally followed by a space)+and ends with a string of the same number of backticks (optionally+preceded by a space).++Note that backslash-escapes (and other Markdown constructs) do not+work in verbatim contexts:++    This is a backslash followed by an asterisk: `\*`.++#### Extension: `inline_code_attributes` ####++Attributes can be attached to verbatim text, just as with+[fenced code blocks]:++    `<$>`{.haskell}++### Small caps ###++To write small caps, you can use an HTML span tag:++    <span style="font-variant:small-caps;">Small caps</span>++(The semicolon is optional and there may be space after the+colon.) This will work in all output formats that support small caps.++Alternatively, you can also use the new `bracketed_spans` syntax:++    [Small caps]{style="font-variant:small-caps;"}++Math+----++#### Extension: `tex_math_dollars` ####++Anything between two `$` characters will be treated as TeX math.  The+opening `$` must have a non-space character immediately to its right,+while the closing `$` must have a non-space character immediately to its+left, and must not be followed immediately by a digit.  Thus,+`$20,000 and $30,000` won't parse as math.  If for some reason+you need to enclose text in literal `$` characters, backslash-escape+them and they won't be treated as math delimiters.++TeX math will be printed in all output formats. How it is rendered+depends on the output format:++Markdown, LaTeX, Emacs Org mode, ConTeXt, ZimWiki+  ~ It will appear verbatim between `$` characters.++reStructuredText+  ~ It will be rendered using an [interpreted text role `:math:`].++AsciiDoc+  ~ It will be rendered as `latexmath:[...]`.++Texinfo+  ~ It will be rendered inside a `@math` command.++groff man+  ~ It will be rendered verbatim without `$`'s.++MediaWiki, DokuWiki+  ~ It will be rendered inside `<math>` tags.++Textile+  ~ It will be rendered inside `<span class="math">` tags.++RTF, OpenDocument+  ~ It will be rendered, if possible, using Unicode characters,+    and will otherwise appear verbatim.++ODT+  ~ It will be rendered, if possible, using MathML.++DocBook+  ~ If the `--mathml` flag is used, it will be rendered using MathML+    in an `inlineequation` or `informalequation` tag.  Otherwise it+    will be rendered, if possible, using Unicode characters.++Docx+  ~ It will be rendered using OMML math markup.++FictionBook2+  ~ If the `--webtex` option is used, formulas are rendered as images+    using CodeCogs or other compatible web service, downloaded+    and embedded in the e-book. Otherwise, they will appear verbatim.++HTML, Slidy, DZSlides, S5, EPUB+  ~ The way math is rendered in HTML will depend on the+    command-line options selected:++    1.  The default is to render TeX math as far as possible using Unicode+        characters, as with RTF, DocBook, and OpenDocument output. Formulas+        are put inside a `span` with `class="math"`, so that they may be+        styled differently from the surrounding text if needed.++    2.  If the `--latexmathml` option is used, TeX math will be displayed+        between `$` or `$$` characters and put in `<span>` tags with class `LaTeX`.+        The [LaTeXMathML] script will be used to render it as formulas.+        (This trick does not work in all browsers, but it works in Firefox.+        In browsers that do not support LaTeXMathML, TeX math will appear+        verbatim between `$` characters.)++    3.  If the `--jsmath` option is used, TeX math will be put inside+        `<span>` tags (for inline math) or `<div>` tags (for display math)+        with class `math`.  The [jsMath] script will be used to render+        it.++    4.  If the `--mimetex` option is used, the [mimeTeX] CGI script will+        be called to generate images for each TeX formula. This should+        work in all browsers. The `--mimetex` option takes an optional URL+        as argument. If no URL is specified, it will be assumed that the+        mimeTeX CGI script is at `/cgi-bin/mimetex.cgi`.++    5.  If the `--gladtex` option is used, TeX formulas will be enclosed+        in `<eq>` tags in the HTML output.  The resulting `htex` file may then+        be processed by [gladTeX], which will produce image files for each+        formula and an HTML file with links to these images.  So, the+        procedure is:++            pandoc -s --gladtex myfile.txt -o myfile.htex+            gladtex -d myfile-images myfile.htex+            # produces myfile.html and images in myfile-images++    6.  If the `--webtex` option is used, TeX formulas will be converted+        to `<img>` tags that link to an external script that converts+        formulas to images. The formula will be URL-encoded and concatenated+        with the URL provided. For SVG images you can for example use+        `--webtex https://latex.codecogs.com/svg.latex?`.+        If no URL is specified, the CodeCogs URL generating PNGs+        will be used (`https://latex.codecogs.com/png.latex?`).++    7.  If the `--mathjax` option is used, TeX math will be displayed+        between `\(...\)` (for inline math) or `\[...\]` (for display+        math) and put in `<span>` tags with class `math`.+        The [MathJax] script will be used to render it as formulas.++[interpreted text role `:math:`]: http://docutils.sourceforge.net/docs/ref/rst/roles.html#math++Raw HTML+--------++#### Extension: `raw_html` ####++Markdown allows you to insert raw HTML (or DocBook) anywhere in a document+(except verbatim contexts, where `<`, `>`, and `&` are interpreted+literally).  (Technically this is not an extension, since standard+Markdown allows it, but it has been made an extension so that it can+be disabled if desired.)++The raw HTML is passed through unchanged in HTML, S5, Slidy, Slideous,+DZSlides, EPUB, Markdown, Emacs Org mode, and Textile output, and suppressed+in other formats.++#### Extension: `markdown_in_html_blocks` ####++Standard Markdown allows you to include HTML "blocks":  blocks+of HTML between balanced tags that are separated from the surrounding text+with blank lines, and start and end at the left margin.  Within+these blocks, everything is interpreted as HTML, not Markdown;+so (for example), `*` does not signify emphasis.++Pandoc behaves this way when the `markdown_strict` format is used; but+by default, pandoc interprets material between HTML block tags as Markdown.+Thus, for example, pandoc will turn++    <table>+    <tr>+    <td>*one*</td>+    <td>[a link](http://google.com)</td>+    </tr>+    </table>++into++    <table>+    <tr>+    <td><em>one</em></td>+    <td><a href="http://google.com">a link</a></td>+    </tr>+    </table>++whereas `Markdown.pl` will preserve it as is.++There is one exception to this rule:  text between `<script>` and+`<style>` tags is not interpreted as Markdown.++This departure from standard Markdown should make it easier to mix+Markdown with HTML block elements.  For example, one can surround+a block of Markdown text with `<div>` tags without preventing it+from being interpreted as Markdown.++#### Extension: `native_divs` ####++Use native pandoc `Div` blocks for content inside `<div>` tags.+For the most part this should give the same output as+`markdown_in_html_blocks`, but it makes it easier to write pandoc+filters to manipulate groups of blocks.++#### Extension: `native_spans` ####++Use native pandoc `Span` blocks for content inside `<span>` tags.+For the most part this should give the same output as `raw_html`,+but it makes it easier to write pandoc filters to manipulate groups+of inlines.++#### Extension: `fenced_divs` ####++Allow special fenced syntax for native `Div` blocks.  A Div+starts with a fence containing at least three consecutive+colons plus some attributes. The attributes may optionally+be followed by another string of consecutive colons.+The attribute syntax is exactly as in fenced code blocks (see+[Extension-fenced_code_attributes], above).  As with fenced+code blocks, one can use either attributes in curly braces+or a single unbraced word, which will be treated as a class+name.  The Div ends with another line containing a string of at+least three consecutive colons.  The fenced Div should be+separated by blank lines from preceding and following blocks.++Example:++    ::::: {#special .sidebar}+    Here is a paragraph.++    And another.+    :::::++Fenced divs can be nested.  Opening fences are distinguished+because they *must* have attributes:++    ::: Warning ::::::+    This is a warning.++    ::: Danger+    This is a warning within a warning.+    :::+    ::::::::::::::::::++#### Extension: `raw_tex` ####++In addition to raw HTML, pandoc allows raw LaTeX, TeX, and ConTeXt to be+included in a document. Inline TeX commands will be preserved and passed+unchanged to the LaTeX and ConTeXt writers. Thus, for example, you can use+LaTeX to include BibTeX citations:++    This result was proved in \cite{jones.1967}.++Note that in LaTeX environments, like++    \begin{tabular}{|l|l|}\hline+    Age & Frequency \\ \hline+    18--25  & 15 \\+    26--35  & 33 \\+    36--45  & 22 \\ \hline+    \end{tabular}++the material between the begin and end tags will be interpreted as raw+LaTeX, not as Markdown.++Inline LaTeX is ignored in output formats other than Markdown, LaTeX,+Emacs Org mode, and ConTeXt.++### Generic raw attribute ###++#### Extension: `raw_attribute` ####++Inline spans and fenced code blocks with a special+kind of attribute will be parsed as raw content with the+designated format.  For example, the following produces a raw+groff `ms` block:++    ```{=ms}+    .MYMACRO+    blah blah+    ```+And the following produces a raw `html` inline element:++    This is `<a>html</a>`{=html}++The format name should match the target format name (see+`-t/--to`, above, for a list, or use `pandoc+--list-output-formats`).++This extension presupposes that the relevant kind of+inline code or fenced code block is enabled.  Thus, for+example, to use a raw attribute with a backtick code block,+`backtick_code_blocks` must be enabled.++The raw attribute cannot be combined with regular attributes.++LaTeX macros+------------++#### Extension: `latex_macros` ####++For output formats other than LaTeX, pandoc will parse LaTeX `\newcommand` and+`\renewcommand` definitions and apply the resulting macros to all LaTeX+math.  So, for example, the following will work in all output formats,+not just LaTeX:++    \newcommand{\tuple}[1]{\langle #1 \rangle}++    $\tuple{a, b, c}$++In LaTeX output, the `\newcommand` definition will simply be passed+unchanged to the output.+++Links+-----++Markdown allows links to be specified in several ways.++### Automatic links ###++If you enclose a URL or email address in pointy brackets, it+will become a link:++    <http://google.com>+    <sam@green.eggs.ham>++### Inline links ###++An inline link consists of the link text in square brackets,+followed by the URL in parentheses. (Optionally, the URL can+be followed by a link title, in quotes.)++    This is an [inline link](/url), and here's [one with+    a title](http://fsf.org "click here for a good time!").++There can be no space between the bracketed part and the parenthesized part.+The link text can contain formatting (such as emphasis), but the title cannot.++Email addresses in inline links are not autodetected, so they have to be+prefixed with `mailto`:++    [Write me!](mailto:sam@green.eggs.ham)++### Reference links ###++An *explicit* reference link has two parts, the link itself and the link+definition, which may occur elsewhere in the document (either+before or after the link).++The link consists of link text in square brackets, followed by a label in+square brackets. (There cannot be space between the two unless the+`spaced_reference_links` extension is enabled.) The link definition+consists of the bracketed label, followed by a colon and a space, followed by+the URL, and optionally (after a space) a link title either in quotes or in+parentheses.  The label must not be parseable as a citation (assuming+the `citations` extension is enabled):  citations take precedence over+link labels.++Here are some examples:++    [my label 1]: /foo/bar.html  "My title, optional"+    [my label 2]: /foo+    [my label 3]: http://fsf.org (The free software foundation)+    [my label 4]: /bar#special  'A title in single quotes'++The URL may optionally be surrounded by angle brackets:++    [my label 5]: <http://foo.bar.baz>++The title may go on the next line:++    [my label 3]: http://fsf.org+      "The free software foundation"++Note that link labels are not case sensitive.  So, this will work:++    Here is [my link][FOO]++    [Foo]: /bar/baz++In an *implicit* reference link, the second pair of brackets is+empty:++    See [my website][].++    [my website]: http://foo.bar.baz++Note:  In `Markdown.pl` and most other Markdown implementations,+reference link definitions cannot occur in nested constructions+such as list items or block quotes.  Pandoc lifts this arbitrary+seeming restriction.  So the following is fine in pandoc, though+not in most other implementations:++    > My block [quote].+    >+    > [quote]: /foo++#### Extension: `shortcut_reference_links` ####++In a *shortcut* reference link, the second pair of brackets may+be omitted entirely:++    See [my website].++    [my website]: http://foo.bar.baz++### Internal links ###++To link to another section of the same document, use the automatically+generated identifier (see [Header identifiers]). For example:++    See the [Introduction](#introduction).++or++    See the [Introduction].++    [Introduction]: #introduction++Internal links are currently supported for HTML formats (including+HTML slide shows and EPUB), LaTeX, and ConTeXt.++Images+------++A link immediately preceded by a `!` will be treated as an image.+The link text will be used as the image's alt text:++    ![la lune](lalune.jpg "Voyage to the moon")++    ![movie reel]++    [movie reel]: movie.gif++#### Extension: `implicit_figures` ####++An image with nonempty alt text, occurring by itself in a+paragraph, will be rendered as a figure with a caption.  The+image's alt text will be used as the caption.++    ![This is the caption](/url/of/image.png)++How this is rendered depends on the output format. Some output+formats (e.g. RTF) do not yet support figures.  In those+formats, you'll just get an image in a paragraph by itself, with+no caption.++If you just want a regular inline image, just make sure it is not+the only thing in the paragraph. One way to do this is to insert a+nonbreaking space after the image:++    ![This image won't be a figure](/url/of/image.png)\ ++Note that in reveal.js slide shows, an image in a paragraph+by itself that has the `stretch` class will fill the screen,+and the caption and figure tags will be omitted.++#### Extension: `link_attributes` ####++Attributes can be set on links and images:++    An inline ![image](foo.jpg){#id .class width=30 height=20px}+    and a reference ![image][ref] with attributes.++    [ref]: foo.jpg "optional title" {#id .class key=val key2="val 2"}++(This syntax is compatible with [PHP Markdown Extra] when only `#id`+and `.class` are used.)++For HTML and EPUB, all attributes except `width` and `height` (but+including `srcset` and `sizes`) are passed through as is. The other+writers ignore attributes that are not supported by their output+format.++The `width` and `height` attributes on images are treated specially. When+used without a unit, the unit is assumed to be pixels. However, any of+the following unit identifiers can be used: `px`, `cm`, `mm`, `in`, `inch`+and `%`. There must not be any spaces between the number and the unit.+For example:++```+![](file.jpg){ width=50% }+```++- Dimensions are converted to inches for output in page-based formats like+  LaTeX. Dimensions are converted to pixels for output in HTML-like+  formats.  Use the `--dpi` option to specify the number of pixels per+  inch.  The default is 96dpi.+- The `%` unit is generally relative to some available space.+  For example the above example will render to+  `<img href="file.jpg" style="width: 50%;" />` (HTML),+  `\includegraphics[width=0.5\textwidth]{file.jpg}` (LaTeX), or+  `\externalfigure[file.jpg][width=0.5\textwidth]` (ConTeXt).+- Some output formats have a notion of a class+  ([ConTeXt](http://wiki.contextgarden.net/Using_Graphics#Multiple_Image_Settings))+  or a unique identifier (LaTeX `\caption`), or both (HTML).+- When no `width` or `height` attributes are specified, the fallback+  is to look at the image resolution and the dpi metadata embedded in+  the image file.++Spans+-----++#### Extension: `bracketed_spans` ####++A bracketed sequence of inlines, as one would use to begin+a link, will be treated as a span with attributes if it is+followed immediately by attributes:++    [This is *some text*]{.class key="val"}++Footnotes+---------++#### Extension: `footnotes` ####++Pandoc's Markdown allows footnotes, using the following syntax:++    Here is a footnote reference,[^1] and another.[^longnote]++    [^1]: Here is the footnote.++    [^longnote]: Here's one with multiple blocks.++        Subsequent paragraphs are indented to show that they+    belong to the previous footnote.++            { some.code }++        The whole paragraph can be indented, or just the first+        line.  In this way, multi-paragraph footnotes work like+        multi-paragraph list items.++    This paragraph won't be part of the note, because it+    isn't indented.++The identifiers in footnote references may not contain spaces, tabs,+or newlines.  These identifiers are used only to correlate the+footnote reference with the note itself; in the output, footnotes+will be numbered sequentially.++The footnotes themselves need not be placed at the end of the+document.  They may appear anywhere except inside other block elements+(lists, block quotes, tables, etc.).  Each footnote should be+separated from surrounding content (including other footnotes)+by blank lines.++#### Extension: `inline_notes` ####++Inline footnotes are also allowed (though, unlike regular notes,+they cannot contain multiple paragraphs).  The syntax is as follows:++    Here is an inline note.^[Inlines notes are easier to write, since+    you don't have to pick an identifier and move down to type the+    note.]++Inline and regular footnotes may be mixed freely.++Typography+----------++#### Extension: `smart` ####++Interpret straight quotes as curly quotes, `---` as em-dashes,+`--` as en-dashes, and `...` as ellipses. Nonbreaking spaces are+inserted after certain abbreviations, such as "Mr."  This+option currently affects the input formats `markdown`,+`commonmark`, `latex`, `mediawiki`, `org`, `rst`, and `twiki`,+and the output formats `markdown`, `latex`, and `context`.++Note: If you are *writing* Markdown, then the `smart` extension+has the reverse effect: what would have been curly quotes comes+out straight.++In LaTeX, `smart` means to use the standard TeX ligatures+for quotation marks (` `` ` and ` '' ` for double quotes,+`` ` `` and `` ' `` for single quotes) and dashes (`--` for+en-dash and `---` for em-dash).  If `smart` is disabled,+then in reading LaTeX pandoc will parse these characters+literally.  In writing LaTeX, enabling `smart` tells pandoc+to use the ligatures when possible; if `smart` is disabled+pandoc will use unicode quotation mark and dash characters.++Citations+---------++#### Extension: `citations` ####++Using an external filter, `pandoc-citeproc`, pandoc can automatically generate+citations and a bibliography in a number of styles.  Basic usage is++    pandoc --filter pandoc-citeproc myinput.txt++In order to use this feature, you will need to specify a bibliography file+using the `bibliography` metadata field in a YAML metadata section, or+`--bibliography` command line argument. You can supply multiple `--bibliography`+arguments or set `bibliography` metadata field to YAML array, if you want to+use multiple bibliography files.  The bibliography may have any of these+formats:++  Format            File extension+  ------------      --------------+  BibLaTeX          .bib+  BibTeX            .bibtex+  Copac             .copac+  CSL JSON          .json+  CSL YAML          .yaml+  EndNote           .enl+  EndNote XML       .xml+  ISI               .wos+  MEDLINE           .medline+  MODS              .mods+  RIS               .ris++Note that `.bib` can be used with both BibTeX and BibLaTeX files;+use `.bibtex` to force BibTeX.++Note that `pandoc-citeproc --bib2json` and `pandoc-citeproc --bib2yaml`+can produce `.json` and `.yaml` files from any of the supported formats.++In-field markup: In BibTeX and BibLaTeX databases, pandoc-citeproc parses+a subset of LaTeX markup; in CSL YAML databases, pandoc Markdown; and in CSL JSON databases, an [HTML-like markup][CSL markup specs]:++`<i>...</i>`+:   italics++`<b>...</b>`+:   bold++`<span style="font-variant:small-caps;">...</span>` or `<sc>...</sc>`+:   small capitals++`<sub>...</sub>`+:   subscript++`<sup>...</sup>`+:   superscript++`<span class="nocase">...</span>`+:   prevent a phrase from being capitalized as title case++`pandoc-citeproc -j` and `-y` interconvert the CSL JSON+and CSL YAML formats as far as possible.++As an alternative to specifying a bibliography file using `--bibliography`+or the YAML metadata field `bibliography`, you can include+the citation data directly in the `references` field of the+document's YAML metadata. The field should contain an array of+YAML-encoded references, for example:++    ---+    references:+    - type: article-journal+      id: WatsonCrick1953+      author:+      - family: Watson+        given: J. D.+      - family: Crick+        given: F. H. C.+      issued:+        date-parts:+        - - 1953+          - 4+          - 25+      title: 'Molecular structure of nucleic acids: a structure for deoxyribose+        nucleic acid'+      title-short: Molecular structure of nucleic acids+      container-title: Nature+      volume: 171+      issue: 4356+      page: 737-738+      DOI: 10.1038/171737a0+      URL: http://www.nature.com/nature/journal/v171/n4356/abs/171737a0.html+      language: en-GB+    ...++(`pandoc-citeproc --bib2yaml` can produce these from a bibliography file in one+of the supported formats.)++Citations and references can be formatted using any style supported by the+[Citation Style Language], listed in the [Zotero Style Repository].+These files are specified using the `--csl` option or the `csl` metadata field.+By default, `pandoc-citeproc` will use the [Chicago Manual of Style] author-date+format.  The CSL project provides further information on [finding and editing styles].++To make your citations hyperlinks to the corresponding bibliography+entries, add `link-citations: true` to your YAML metadata.++Citations go inside square brackets and are separated by semicolons.+Each citation must have a key, composed of '@' + the citation+identifier from the database, and may optionally have a prefix,+a locator, and a suffix.  The citation key must begin with a letter, digit,+or `_`, and may contain alphanumerics, `_`, and internal punctuation+characters (`:.#$%&-+?<>~/`).  Here are some examples:++    Blah blah [see @doe99, pp. 33-35; also @smith04, chap. 1].++    Blah blah [@doe99, pp. 33-35, 38-39 and *passim*].++    Blah blah [@smith04; @doe99].++`pandoc-citeproc` detects locator terms in the [CSL locale files].+Either abbreviated or unabbreviated forms are accepted. In the `en-US`+locale, locator terms can be written in either singular or plural forms,+as `book`, `bk.`/`bks.`; `chapter`, `chap.`/`chaps.`; `column`,+`col.`/`cols.`; `figure`, `fig.`/`figs.`; `folio`, `fol.`/`fols.`;+`number`, `no.`/`nos.`; `line`, `l.`/`ll.`; `note`, `n.`/`nn.`; `opus`,+`op.`/`opp.`; `page`, `p.`/`pp.`; `paragraph`, `para.`/`paras.`; `part`,+`pt.`/`pts.`; `section`, `sec.`/`secs.`; `sub verbo`, `s.v.`/`s.vv.`;+`verse`, `v.`/`vv.`; `volume`, `vol.`/`vols.`; `¶`/`¶¶`; `§`/`§§`. If no+locator term is used, "page" is assumed.++A minus sign (`-`) before the `@` will suppress mention of+the author in the citation.  This can be useful when the+author is already mentioned in the text:++    Smith says blah [-@smith04].++You can also write an in-text citation, as follows:++    @smith04 says blah.++    @smith04 [p. 33] says blah.++If the style calls for a list of works cited, it will be placed+at the end of the document.  Normally, you will want to end your+document with an appropriate header:++    last paragraph...++    # References++The bibliography will be inserted after this header.  Note that+the `unnumbered` class will be added to this header, so that the+section will not be numbered.++If you want to include items in the bibliography without actually+citing them in the body text, you can define a dummy `nocite` metadata+field and put the citations there:++    ---+    nocite: |+      @item1, @item2+    ...++    @item3++In this example, the document will contain a citation for `item3`+only, but the bibliography will contain entries for `item1`, `item2`, and+`item3`.++It is possible to create a bibliography with all the citations,+whether or not they appear in the document, by using a wildcard:++    ---+    nocite: |+      @*+    ...++For LaTeX or PDF output, you can also use [`natbib`] or [`biblatex`]+to render bibliography. In order to do so, specify bibliography files as+outlined above, and add `--natbib` or `--biblatex` argument to `pandoc`+invocation. Bear in mind that bibliography files have to be in respective+format (either BibTeX or BibLaTeX).++For more information, see the [pandoc-citeproc man page].++[CSL markup specs]: http://docs.citationstyles.org/en/1.0/release-notes.html#rich-text-markup-within-fields+[Chicago Manual of Style]: http://chicagomanualofstyle.org+[Citation Style Language]: http://citationstyles.org+[Zotero Style Repository]: https://www.zotero.org/styles+[finding and editing styles]: http://citationstyles.org/styles/+[CSL locale files]: https://github.com/citation-style-language/locales+[pandoc-citeproc man page]: https://github.com/jgm/pandoc-citeproc/blob/master/man/pandoc-citeproc.1.md++Non-pandoc extensions+---------------------++The following Markdown syntax extensions are not enabled by default+in pandoc, but may be enabled by adding `+EXTENSION` to the format+name, where `EXTENSION` is the name of the extension.  Thus, for+example, `markdown+hard_line_breaks` is Markdown with hard line breaks.++#### Extension: `old_dashes` ####++Selects the pandoc <= 1.8.2.1 behavior for parsing smart dashes:+`-` before a numeral is an en-dash, and `--` is an em-dash.+This option only has an effect if `smart` is enabled. It is+selected automatically for `textile` input.++#### Extension: `angle_brackets_escapable` ####++Allow `<` and `>` to be backslash-escaped, as they can be in+GitHub flavored Markdown but not original Markdown.  This is+implied by pandoc's default `all_symbols_escapable`.++#### Extension: `lists_without_preceding_blankline` ####++Allow a list to occur right after a paragraph, with no intervening+blank space.++#### Extension: `four_space_rule` ####++Selects the pandoc <= 2.0 behavior for parsing lists, so that+four spaces indent are needed for list item continuation+paragraphs.++#### Extension: `spaced_reference_links` ####++Allow whitespace between the two components of a reference link,+for example,++    [foo] [bar].++#### Extension: `hard_line_breaks` ####++Causes all newlines within a paragraph to be interpreted as hard line+breaks instead of spaces.++#### Extension: `ignore_line_breaks` ####++Causes newlines within a paragraph to be ignored, rather than being+treated as spaces or as hard line breaks.  This option is intended for+use with East Asian languages where spaces are not used between words,+but text is divided into lines for readability.++#### Extension: `east_asian_line_breaks` ####++Causes newlines within a paragraph to be ignored, rather than+being treated as spaces or as hard line breaks, when they occur+between two East Asian wide characters.  This is a better choice+than `ignore_line_breaks` for texts that include a mix of East+Asian wide characters and other characters.++##### Extension: `emoji` ####++Parses textual emojis like `:smile:` as Unicode emoticons.++#### Extension: `tex_math_single_backslash` ####++Causes anything between `\(` and `\)` to be interpreted as inline+TeX math, and anything between `\[` and `\]` to be interpreted+as display TeX math.  Note: a drawback of this extension is that+it precludes escaping `(` and `[`.++#### Extension: `tex_math_double_backslash` ####++Causes anything between `\\(` and `\\)` to be interpreted as inline+TeX math, and anything between `\\[` and `\\]` to be interpreted+as display TeX math.++#### Extension: `markdown_attribute` ####++By default, pandoc interprets material inside block-level tags as Markdown.+This extension changes the behavior so that Markdown is only parsed+inside block-level tags if the tags have the attribute `markdown=1`.++#### Extension: `mmd_title_block` ####++Enables a [MultiMarkdown] style title block at the top of+the document, for example:++    Title:   My title+    Author:  John Doe+    Date:    September 1, 2008+    Comment: This is a sample mmd title block, with+             a field spanning multiple lines.++See the MultiMarkdown documentation for details.  If `pandoc_title_block` or+`yaml_metadata_block` is enabled, it will take precedence over+`mmd_title_block`.++#### Extension: `abbreviations` ####++Parses PHP Markdown Extra abbreviation keys, like++    *[HTML]: Hypertext Markup Language++Note that the pandoc document model does not support+abbreviations, so if this extension is enabled, abbreviation keys are+simply skipped (as opposed to being parsed as paragraphs).++#### Extension: `autolink_bare_uris` ####++Makes all absolute URIs into links, even when not surrounded by+pointy braces `<...>`.++#### Extension: `ascii_identifiers` ####++Causes the identifiers produced by `auto_identifiers` to be pure ASCII.+Accents are stripped off of accented Latin letters, and non-Latin+letters are omitted.++#### Extension: `mmd_link_attributes` ####++Parses multimarkdown style key-value attributes on link+and image references. This extension should not be confused with the+[`link_attributes`](#extension-link_attributes) extension.++    This is a reference ![image][ref] with multimarkdown attributes.++    [ref]: http://path.to/image "Image title" width=20px height=30px+           id=myId class="myClass1 myClass2"++#### Extension: `mmd_header_identifiers` ####++Parses multimarkdown style header identifiers (in square brackets,+after the header but before any trailing `#`s in an ATX header).++#### Extension: `compact_definition_lists` ####++Activates the definition list syntax of pandoc 1.12.x and earlier.+This syntax differs from the one described above under [Definition lists]+in several respects:++  - No blank line is required between consecutive items of the+    definition list.+  - To get a "tight" or "compact" list, omit space between consecutive+    items; the space between a term and its definition does not affect+    anything.+  - Lazy wrapping of paragraphs is not allowed:  the entire definition must+    be indented four spaces.[^6]++[^6]:  To see why laziness is incompatible with relaxing the requirement+    of a blank line between items, consider the following example:++        bar+        :    definition+        foo+        :    definition++    Is this a single list item with two definitions of "bar," the first of+    which is lazily wrapped, or two list items?  To remove the ambiguity+    we must either disallow lazy wrapping or require a blank line between+    list items.++Markdown variants+-----------------++In addition to pandoc's extended Markdown, the following Markdown+variants are supported:++`markdown_phpextra` (PHP Markdown Extra)+:   `footnotes`, `pipe_tables`, `raw_html`, `markdown_attribute`,+    `fenced_code_blocks`, `definition_lists`, `intraword_underscores`,+    `header_attributes`, `link_attributes`, `abbreviations`,+    `shortcut_reference_links`, `spaced_reference_links`.++`markdown_github` (deprecated GitHub-Flavored Markdown)+:   `pipe_tables`, `raw_html`, `fenced_code_blocks`, `gfm_auto_identifiers`,+    `ascii_identifiers`, `backtick_code_blocks`, `autolink_bare_uris`,+    `space_in_atx_header`, `intraword_underscores`, `strikeout`,+    `emoji`, `shortcut_reference_links`, `angle_brackets_escapable`,+    `lists_without_preceding_blankline`.++`markdown_mmd` (MultiMarkdown)+:   `pipe_tables`, `raw_html`, `markdown_attribute`, `mmd_link_attributes`,+    `tex_math_double_backslash`, `intraword_underscores`,+    `mmd_title_block`, `footnotes`, `definition_lists`,+    `all_symbols_escapable`, `implicit_header_references`,+    `auto_identifiers`, `mmd_header_identifiers`,+    `shortcut_reference_links`, `implicit_figures`,+    `superscript`, `subscript`, `backtick_code_blocks`,+    `spaced_reference_links`, `raw_attribute`.++`markdown_strict` (Markdown.pl)+:   `raw_html`, `shortcut_reference_links`,+    `spaced_reference_links`.++We also support `gfm` (GitHub-Flavored Markdown) as a set of+extensions on `commonmark`:++:   `pipe_tables`, `raw_html`, `fenced_code_blocks`, `auto_identifiers`,+    `ascii_identifiers`, `backtick_code_blocks`, `autolink_bare_uris`,+    `intraword_underscores`, `strikeout`, `hard_line_breaks`, `emoji`,+    `shortcut_reference_links`, `angle_brackets_escapable`.++    These can all be individually disabled. Note, however, that+    `commonmark` and `gfm` have limited support for extensions:+    extensions other than those listed above (and `smart`) will have+    no effect on `commonmark` or `gfm`.++Extensions with formats other than Markdown+-------------------------------------------++Some of the extensions discussed above can be used with formats+other than Markdown:++* `auto_identifiers` can be used with `latex`, `rst`, `mediawiki`,+  and `textile` input (and is used by default).++* `tex_math_dollars`, `tex_math_single_backslash`, and+  `tex_math_double_backslash` can be used with `html` input.+  (This is handy for reading web pages formatted using MathJax,+  for example.)++Producing slide shows with pandoc+=================================++You can use pandoc to produce an HTML + JavaScript slide presentation+that can be viewed via a web browser.  There are five ways to do this,+using [S5], [DZSlides], [Slidy], [Slideous], or [reveal.js].+You can also produce a PDF slide show using LaTeX [`beamer`].++Here's the Markdown source for a simple slide show, `habits.txt`:++    % Habits+    % John Doe+    % March 22, 2005++    # In the morning++    ## Getting up++    - Turn off alarm+    - Get out of bed++    ## Breakfast++    - Eat eggs+    - Drink coffee++    # In the evening++    ## Dinner++    - Eat spaghetti+    - Drink wine++    ------------------++    ![picture of spaghetti](images/spaghetti.jpg)++    ## Going to sleep++    - Get in bed+    - Count sheep++To produce an HTML/JavaScript slide show, simply type++    pandoc -t FORMAT -s habits.txt -o habits.html++where `FORMAT` is either `s5`, `slidy`, `slideous`, `dzslides`, or `revealjs`.++For Slidy, Slideous, reveal.js, and S5, the file produced by pandoc with the+`-s/--standalone` option embeds a link to JavaScript and CSS files, which are+assumed to be available at the relative path `s5/default` (for S5), `slideous`+(for Slideous), `reveal.js` (for reveal.js), or at the Slidy website at+`w3.org` (for Slidy).  (These paths can be changed by setting the `slidy-url`,+`slideous-url`, `revealjs-url`, or `s5-url` variables; see [Variables for slides],+above.) For DZSlides, the (relatively short) JavaScript and CSS are included in+the file by default.++With all HTML slide formats, the `--self-contained` option can be used to+produce a single file that contains all of the data necessary to display the+slide show, including linked scripts, stylesheets, images, and videos.++To produce a PDF slide show using beamer, type++    pandoc -t beamer habits.txt -o habits.pdf++Note that a reveal.js slide show can also be converted to a PDF+by printing it to a file from the browser.++Structuring the slide show+--------------------------++By default, the *slide level* is the highest header level in+the hierarchy that is followed immediately by content, and not another+header, somewhere in the document. In the example above, level 1 headers+are always followed by level 2 headers, which are followed by content,+so 2 is the slide level.  This default can be overridden using+the `--slide-level` option.++The document is carved up into slides according to the following+rules:++  * A horizontal rule always starts a new slide.++  * A header at the slide level always starts a new slide.++  * Headers *below* the slide level in the hierarchy create+    headers *within* a slide.++  * Headers *above* the slide level in the hierarchy create+    "title slides," which just contain the section title+    and help to break the slide show into sections.++  * Content *above* the slide level will not appear in the slide+    show.++  * A title page is constructed automatically from the document's title+    block, if present.  (In the case of beamer, this can be disabled+    by commenting out some lines in the default template.)++These rules are designed to support many different styles of slide show. If+you don't care about structuring your slides into sections and subsections,+you can just use level 1 headers for all each slide. (In that case, level 1+will be the slide level.) But you can also structure the slide show into+sections, as in the example above.++Note:  in reveal.js slide shows, if slide level is 2, a two-dimensional+layout will be produced, with level 1 headers building horizontally+and level 2 headers building vertically.  It is not recommended that+you use deeper nesting of section levels with reveal.js.++Incremental lists+-----------------++By default, these writers produce lists that display "all at once."+If you want your lists to display incrementally (one item at a time),+use the `-i` option. If you want a particular list to depart from the+default (that is, to display incrementally without the `-i` option and+all at once with the `-i` option), put it in a block quote:++    > - Eat spaghetti+    > - Drink wine++In this way incremental and nonincremental lists can be mixed in+a single document.++Inserting pauses+----------------++You can add "pauses" within a slide by including a paragraph containing+three dots, separated by spaces:++    # Slide with a pause++    content before the pause++    . . .++    content after the pause++Styling the slides+------------------++You can change the style of HTML slides by putting customized CSS files+in `$DATADIR/s5/default` (for S5), `$DATADIR/slidy` (for Slidy),+or `$DATADIR/slideous` (for Slideous),+where `$DATADIR` is the user data directory (see `--data-dir`, above).+The originals may be found in pandoc's system data directory (generally+`$CABALDIR/pandoc-VERSION/s5/default`). Pandoc will look there for any+files it does not find in the user data directory.++For dzslides, the CSS is included in the HTML file itself, and may+be modified there.++All [reveal.js configuration options] can be set through variables.+For example, themes can be used by setting the `theme` variable:++    -V theme=moon++Or you can specify a custom stylesheet using the `--css` option.++To style beamer slides, you can specify a `theme`, `colortheme`,+`fonttheme`, `innertheme`, and `outertheme`, using the `-V` option:++    pandoc -t beamer habits.txt -V theme:Warsaw -o habits.pdf++Note that header attributes will turn into slide attributes+(on a `<div>` or `<section>`) in HTML slide formats, allowing you+to style individual slides.  In beamer, the only header attribute+that affects slides is the `allowframebreaks` class, which sets the+`allowframebreaks` option, causing multiple slides to be created+if the content overfills the frame.  This is recommended especially for+bibliographies:++    # References {.allowframebreaks}++Speaker notes+-------------++reveal.js has good support for speaker notes.  You can add notes to your+Markdown document thus:++    <div class="notes">+    This is my note.++    - It can contain Markdown+    - like this list++    </div>++To show the notes window, press `s` while viewing the presentation.+Notes are not yet supported for other slide formats, but the notes+will not appear on the slides themselves.++Frame attributes in beamer+--------------------------++Sometimes it is necessary to add the LaTeX `[fragile]` option to+a frame in beamer (for example, when using the `minted` environment).+This can be forced by adding the `fragile` class to the header+introducing the slide:++    # Fragile slide {.fragile}++All of the other frame attributes described in Section 8.1 of+the [Beamer User's Guide] may also be used: `allowdisplaybreaks`,+`allowframebreaks`, `b`, `c`, `t`, `environment`, `label`, `plain`,+`shrink`.++Creating EPUBs with pandoc+==========================++EPUB Metadata+-------------++EPUB metadata may be specified using the `--epub-metadata` option, but+if the source document is Markdown, it is better to use a [YAML metadata+block][Extension: `yaml_metadata_block`].  Here is an example:++    ---+    title:+    - type: main+      text: My Book+    - type: subtitle+      text: An investigation of metadata+    creator:+    - role: author+      text: John Smith+    - role: editor+      text: Sarah Jones+    identifier:+    - scheme: DOI+      text: doi:10.234234.234/33+    publisher:  My Press+    rights: © 2007 John Smith, CC BY-NC+    ibooks:+      version: 1.3.4+    ...++The following fields are recognized:++`identifier`+  ~ Either a string value or an object with fields `text` and+    `scheme`.  Valid values for `scheme` are `ISBN-10`,+    `GTIN-13`, `UPC`, `ISMN-10`, `DOI`, `LCCN`, `GTIN-14`,+    `ISBN-13`, `Legal deposit number`, `URN`, `OCLC`,+    `ISMN-13`, `ISBN-A`, `JP`, `OLCC`.++`title`+  ~ Either a string value, or an object with fields `file-as` and+    `type`, or a list of such objects.  Valid values for `type` are+    `main`, `subtitle`, `short`, `collection`, `edition`, `extended`.++`creator`+  ~ Either a string value, or an object with fields `role`, `file-as`,+    and `text`, or a list of such objects.  Valid values for `role` are+    [MARC relators], but+    pandoc will attempt to translate the human-readable versions+    (like "author" and "editor") to the appropriate marc relators.++`contributor`+  ~ Same format as `creator`.++`date`+  ~ A string value in `YYYY-MM-DD` format.  (Only the year is necessary.)+    Pandoc will attempt to convert other common date formats.++`lang` (or legacy: `language`)+  ~ A string value in [BCP 47] format.  Pandoc will default to the local+    language if nothing is specified.++`subject`+  ~ A string value or a list of such values.++`description`+  ~ A string value.++`type`+  ~ A string value.++`format`+  ~ A string value.++`relation`+  ~ A string value.++`coverage`+  ~ A string value.++`rights`+  ~ A string value.++`cover-image`+  ~ A string value (path to cover image).++`stylesheet`+  ~ A string value (path to CSS stylesheet).++`page-progression-direction`+  ~ Either `ltr` or `rtl`. Specifies the `page-progression-direction`+    attribute for the [`spine` element].++`ibooks`+  ~ iBooks-specific metadata, with the following fields:++    - `version`: (string)+    - `specified-fonts`: `true`|`false` (default `false`)+    - `ipad-orientation-lock`: `portrait-only`|`landscape-only`+    - `iphone-orientation-lock`: `portrait-only`|`landscape-only`+    - `binding`: `true`|`false` (default `true`)+    - `scroll-axis`: `vertical`|`horizontal`|`default`++[MARC relators]: http://loc.gov/marc/relators/relaterm.html+[`spine` element]: http://idpf.org/epub/301/spec/epub-publications.html#sec-spine-elem++Linked media+------------++By default, pandoc will download linked media (including audio and+video) and include it in the EPUB container, yielding a completely+self-contained EPUB.  If you want to link to external media resources+instead, use raw HTML in your source and add `data-external="1"` to the tag+with the `src` attribute.  For example:++    <audio controls="1">+      <source src="http://example.com/music/toccata.mp3"+              data-external="1" type="audio/mpeg">+      </source>+    </audio>++Literate Haskell support+========================++If you append `+lhs` (or `+literate_haskell`) to an appropriate input or output+format (`markdown`, `markdown_strict`, `rst`, or `latex` for input or output;+`beamer`, `html4` or `html5` for output only), pandoc will treat the document as+literate Haskell source. This means that++  - In Markdown input, "bird track" sections will be parsed as Haskell+    code rather than block quotations.  Text between `\begin{code}`+    and `\end{code}` will also be treated as Haskell code.  For+    ATX-style headers the character '=' will be used instead of '#'.++  - In Markdown output, code blocks with classes `haskell` and `literate`+    will be rendered using bird tracks, and block quotations will be+    indented one space, so they will not be treated as Haskell code.+    In addition, headers will be rendered setext-style (with underlines)+    rather than ATX-style (with '#' characters). (This is because ghc+    treats '#' characters in column 1 as introducing line numbers.)++  - In restructured text input, "bird track" sections will be parsed+    as Haskell code.++  - In restructured text output, code blocks with class `haskell` will+    be rendered using bird tracks.++  - In LaTeX input, text in `code` environments will be parsed as+    Haskell code.++  - In LaTeX output, code blocks with class `haskell` will be rendered+    inside `code` environments.++  - In HTML output, code blocks with class `haskell` will be rendered+    with class `literatehaskell` and bird tracks.++Examples:++    pandoc -f markdown+lhs -t html++reads literate Haskell source formatted with Markdown conventions and writes+ordinary HTML (without bird tracks).++    pandoc -f markdown+lhs -t html+lhs++writes HTML with the Haskell code in bird tracks, so it can be copied+and pasted as literate Haskell source.++Note that GHC expects the bird tracks in the first column, so indentend literate+code blocks (e.g. inside an itemized environment) will not be picked up by the+Haskell compiler.++Syntax highlighting+===================++Pandoc will automatically highlight syntax in [fenced code blocks] that+are marked with a language name.  The Haskell library [skylighting] is+used for highlighting, which works in HTML, Docx, Ms, and LaTeX/PDF output.+To see a list of language names that pandoc will recognize, type+`pandoc --list-highlight-languages`.++The color scheme can be selected using the `--highlight-style` option.+The default color scheme is `pygments`, which imitates the default color+scheme used by the Python library pygments (though pygments is not actually+used to do the highlighting).  To see a list of highlight styles,+type `pandoc --list-highlight-styles`.++To disable highlighting, use the `--no-highlight` option.++[skylighting]: https://github.com/jgm/skylighting++Custom Styles in Docx Output+============================++By default, pandoc's docx output applies a predefined set of styles for+blocks such as paragraphs and block quotes, and uses largely default+formatting (italics, bold) for inlines. This will work for most+purposes, especially alongside a `reference.docx` file. However, if you+need to apply your own styles to blocks, or match a preexisting set of+styles, pandoc allows you to define custom styles for blocks and text+using `div`s and `span`s, respectively.++If you define a `div` or `span` with the attribute `custom-style`,+pandoc will apply your specified style to the contained elements. So,+for example,++    <span custom-style="Emphatically">Get out,</span> he said.++would produce a docx file with "Get out," styled with character+style `Emphatically`. Similarly,++    Dickinson starts the poem simply:++    <div custom-style="Poetry">+    | A Bird came down the Walk---+    | He did not know I saw---+    </div>++would style the two contained lines with the `Poetry` paragraph style.++If the styles are not yet in your reference.docx, they will be defined+in the output file as inheriting from normal text. If they are already+defined, pandoc will not alter the definition.++This feature allows for greatest customization in conjunction with+[pandoc filters]. If you want all paragraphs after block quotes to be+indented, you can write a filter to apply the styles necessary. If you+want all italics to be transformed to the `Emphasis` character style+(perhaps to change their color), you can write a filter which will+transform all italicized inlines to inlines within an `Emphasis`+custom-style `span`.++[pandoc filters]: http://pandoc.org/filters.html++Custom writers+==============++Pandoc can be extended with custom writers written in [lua].  (Pandoc+includes a lua interpreter, so lua need not be installed separately.)++To use a custom writer, simply specify the path to the lua script+in place of the output format. For example:++    pandoc -t data/sample.lua++Creating a custom writer requires writing a lua function for each+possible element in a pandoc document.  To get a documented example+which you can modify according to your needs, do++    pandoc --print-default-data-file sample.lua++[lua]: http://www.lua.org++Authors+=======++Copyright 2006-2017 John MacFarlane (jgm@berkeley.edu). Released+under the [GPL], version 2 or greater.  This software carries no+warranty of any kind.  (See COPYRIGHT for full copyright and+warranty notices.) For a full list of contributors, see the file+AUTHORS.md in the pandoc source code.  [GPL]: http://www.gnu.org/copyleft/gpl.html "GNU General Public License"
README.md view
@@ -16,28 +16,32 @@  Pandoc is a [Haskell] library for converting from one markup format to another, and a command-line tool that uses this library. It can read-[Markdown], [CommonMark], [PHP Markdown Extra], [GitHub-Flavored Markdown],-[MultiMarkdown], and (subsets of) [Textile], [reStructuredText], [HTML],-[LaTeX], [MediaWiki markup], [TWiki markup], [Haddock markup], [OPML], [Emacs-Org mode], [DocBook], [txt2tags], [EPUB], [ODT] and [Word docx]; and it can-write plain text, [Markdown], [CommonMark], [PHP Markdown Extra],-[GitHub-Flavored Markdown], [MultiMarkdown], [reStructuredText], [XHTML],-[HTML5], [LaTeX] \(including [`beamer`] slide shows\), [ConTeXt], [RTF], [OPML],-[DocBook], [OpenDocument], [ODT], [Word docx], [GNU Texinfo], [MediaWiki+[Markdown], [CommonMark], [PHP Markdown Extra], [GitHub-Flavored+Markdown], [MultiMarkdown], and (subsets of) [Textile],+[reStructuredText], [HTML], [LaTeX], [MediaWiki markup], [TWiki markup],+[TikiWiki markup], [Creole 1.0], [Haddock markup], [OPML], [Emacs Org mode],+[DocBook], [Muse], [txt2tags], [Vimwiki], [EPUB], [ODT], and [Word docx];+and it can write plain text, [Markdown], [CommonMark], [PHP Markdown+Extra], [GitHub-Flavored Markdown], [MultiMarkdown],+[reStructuredText], [XHTML], [HTML5], [LaTeX] \(including+[`beamer`] slide shows\), [ConTeXt], [RTF], [OPML], [DocBook],+[OpenDocument], [ODT], [Word docx], [GNU Texinfo], [MediaWiki markup], [DokuWiki markup], [ZimWiki markup], [Haddock markup],-[EPUB] \(v2 or v3\), [FictionBook2], [Textile], [groff man] pages,-[Emacs Org mode], [AsciiDoc], [InDesign ICML], [TEI Simple], and [Slidy],-[Slideous], [DZSlides], [reveal.js] or [S5] HTML slide shows. It can also-produce [PDF] output on systems where LaTeX, ConTeXt, or `wkhtmltopdf` is-installed.+[EPUB] \(v2 or v3\), [FictionBook2], [Textile], [groff man],+[groff ms], [Emacs Org mode], [AsciiDoc], [InDesign ICML], [TEI+Simple], [Muse] and [Slidy], [Slideous], [DZSlides], [reveal.js]+or [S5] HTML slide shows. It can also produce [PDF] output on+systems where LaTeX, ConTeXt, `pdfroff`, `wkhtmltopdf`,+`prince`, or `weasyprint` is installed.  Pandoc's enhanced version of Markdown includes syntax for [footnotes],-[tables], flexible [ordered lists], [definition lists], [fenced code blocks],-[superscripts and subscripts], [strikeout], [metadata blocks], automatic tables of-contents, embedded LaTeX [math], [citations], and [Markdown inside HTML block-elements]. (These enhancements, described-further under [Pandoc's Markdown], can be disabled using the-`markdown_strict` input or output format.)+[tables], flexible [ordered lists], [definition lists], [fenced code+blocks], [superscripts and subscripts], [strikeout], [metadata blocks],+automatic tables of contents, embedded LaTeX [math], [citations], and+[Markdown inside HTML block elements][Extension:+`markdown_in_html_blocks`]. (These enhancements, described further under+[Pandoc's Markdown], can be disabled using the `markdown_strict` input+or output format.)  In contrast to most existing tools for converting Markdown to HTML, which use regex substitutions, pandoc has a modular design: it consists of a@@ -73,6 +77,7 @@ [Beamer User's Guide]: http://ctan.math.utah.edu/ctan/tex-archive/macros/latex/contrib/beamer/doc/beameruserguide.pdf [ConTeXt]: http://www.contextgarden.net/ [RTF]: http://en.wikipedia.org/wiki/Rich_Text_Format+[Creole 1.0]: http://www.wikicreole.org/wiki/Creole1.0 [DocBook]: http://docbook.org [txt2tags]: http://txt2tags.org [EPUB]: http://idpf.org/epub@@ -97,6 +102,8 @@ [FictionBook2]: http://www.fictionbook.org/index.php/Eng:XML_Schema_Fictionbook_2.1 [InDesign ICML]: https://www.adobe.com/content/dam/Adobe/en/devnet/indesign/cs55-docs/IDML/idml-specification.pdf [TEI Simple]: https://github.com/TEIC/TEI-Simple+[Muse]: https://amusewiki.org/library/manual+[Vimwiki]: https://vimwiki.github.io   @@ -139,7 +146,7 @@ License ------- -© 2006-2016 John MacFarlane (jgm@berkeley.edu). Released under the+© 2006-2017 John MacFarlane (jgm@berkeley.edu). Released under the [GPL], version 2 or greater.  This software carries no warranty of any kind.  (See COPYRIGHT for full copyright and warranty notices.) 
Setup.hs view
@@ -1,10 +1,5 @@-{-# LANGUAGE CPP #-}-#if !defined(MIN_VERSION_Cabal)-# define MIN_VERSION_Cabal(a,b,c) 0-#endif- {--Copyright (C) 2006-2015 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2006-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -22,57 +17,15 @@ -}  import Distribution.Simple-import Distribution.Simple.PreProcess-import Distribution.Simple.Setup (ConfigFlags(..), CopyFlags(..), fromFlag)+import Distribution.Simple.Setup (CopyFlags(..), fromFlag) import Distribution.PackageDescription (PackageDescription(..))-import Distribution.Simple.Utils ( rawSystemExitCode, findProgramVersion )-import System.Exit-import Distribution.Simple.Utils (info, notice, installOrdinaryFiles)-import Distribution.Simple.Program (simpleProgram, Program(..))+import Distribution.Simple.Utils (notice, installOrdinaryFiles) import Distribution.Simple.LocalBuildInfo-import Control.Monad (when) -#if MIN_VERSION_Cabal(2,0,0)-import Distribution.PackageDescription (mkFlagName)-#else-import Distribution.PackageDescription (FlagName(..))-#endif- main :: IO () main = defaultMainWithHooks $ simpleUserHooks {-      -- enable hsb2hs preprocessor for .hsb files-      hookedPreProcessors = [ppBlobSuffixHandler]-    , hookedPrograms = [(simpleProgram "hsb2hs"){-                           programFindVersion = \verbosity fp ->-                             findProgramVersion "--version" id verbosity fp }]-    , postCopy = installManPage+      postCopy = installManPage     }--ppBlobSuffixHandler :: PPSuffixHandler-#if MIN_VERSION_Cabal(2,0,0)-ppBlobSuffixHandler = ("hsb", \_ lbi _ ->-#else-ppBlobSuffixHandler = ("hsb", \_ lbi ->-#endif-  PreProcessor {-    platformIndependent = True,-    runPreProcessor = mkSimplePreProcessor $ \infile outfile verbosity ->-#if MIN_VERSION_Cabal(2,0,0)-      do let embedData = case lookup (mkFlagName "embed_data_files")-#else-      do let embedData = case lookup (FlagName "embed_data_files")-#endif-                              (configConfigurationsFlags (configFlags lbi)) of-                              Just True -> True-                              _         -> False-         when embedData $-            do info verbosity $ "Preprocessing " ++ infile ++ " to " ++ outfile-               ec <- rawSystemExitCode verbosity "hsb2hs"-                          [infile, infile, outfile]-               case ec of-                    ExitSuccess   -> return ()-                    ExitFailure _ -> error "hsb2hs is needed to build this program"-  })  installManPage :: Args -> CopyFlags                -> PackageDescription -> LocalBuildInfo -> IO ()
benchmark/benchmark-pandoc.hs view
@@ -1,5 +1,5 @@ {--Copyright (C) 2012-2014 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2012-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -16,37 +16,72 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA -} import Text.Pandoc+import qualified Text.Pandoc.UTF8 as UTF8+import Data.Text (Text)+import Data.Time (getCurrentTime)+import qualified Data.ByteString as B+import qualified Data.Map as Map import Criterion.Main import Criterion.Types (Config(..)) import Data.Maybe (mapMaybe) import Debug.Trace (trace)+import System.Environment (getArgs)  readerBench :: Pandoc-            -> (String, ReaderOptions -> String -> IO (Either PandocError Pandoc))+            -> (String, ReaderOptions -> Text -> Pandoc)             -> Maybe Benchmark readerBench doc (name, reader) =   case lookup name writers of-       Just (PureStringWriter writer) ->-         let inp = writer def{ writerWrapText = WrapAuto} doc-         in return $ bench (name ++ " reader") $ nfIO $-                 (fmap handleError <$> reader def{ readerSmart = True }) inp-       _ -> trace ("\nCould not find writer for " ++ name ++ "\n") Nothing+       Just (TextWriter writer) ->+         let inp = either (error . show) id $ runPure+                       $ writer def{ writerWrapText = WrapAuto} doc+         in return $ bench (name ++ " reader") $ nf+                 (reader def) inp+       _ -> Debug.Trace.trace+             ("\nCould not find writer for " ++ name ++ "\n") Nothing  writerBench :: Pandoc-            -> (String, WriterOptions -> Pandoc -> String)+            -> (String, WriterOptions -> Pandoc -> Text)             -> Benchmark writerBench doc (name, writer) = bench (name ++ " writer") $ nf     (writer def{ writerWrapText = WrapAuto }) doc  main :: IO () main = do-  inp <- readFile "tests/testsuite.txt"-  let opts = def{ readerSmart = True }-  let doc = handleError $ readMarkdown opts inp-  let readers' = [(n,r) | (n, StringReader r) <- readers]+  args <- getArgs+  let matchReader (n, TextReader _) =+        case args of+             [] -> True+             [x] -> x == n+             (x:y:_) -> x == n && y == "reader"+      matchReader (_, _) = False+  let matchWriter (n, TextWriter _) =+        case args of+             [] -> True+             [x] -> x == n+             (x:y:_) -> x == n && y == "writer"+      matchWriter (_, _) = False+  let matchedReaders = filter matchReader readers+  let matchedWriters = filter matchWriter writers+  inp <- UTF8.toText <$> B.readFile "test/testsuite.txt"+  lalune <- B.readFile "test/lalune.jpg"+  movie <- B.readFile "test/movie.jpg"+  time <- Data.Time.getCurrentTime+  let setupFakeFiles = modifyPureState $ \st -> st{ stFiles =+                        FileTree $ Map.fromList [+                           ("lalune.jpg", FileInfo time lalune),+                           ("movie.jpg", FileInfo time movie)+                           ]}+  let opts = def+  let doc = either (error . show) id $ runPure $ readMarkdown opts inp+  let readers' = [(n, \o d ->+             either (error . show) id $ runPure $ r o d)+                        | (n, TextReader r) <- matchedReaders]   let readerBs = mapMaybe (readerBench doc)                  $ filter (\(n,_) -> n /="haddock") readers'-  let writers' = [(n,w) | (n, PureStringWriter w) <- writers]+  let writers' = [(n, \o d ->+                   either (error . show) id $ runPure $ setupFakeFiles >> w o d)+                        | (n, TextWriter w) <- matchedWriters]   let writerBs = map (writerBench doc)                  $ writers'   defaultMainWith defaultConfig{ timeLimit = 6.0 }
benchmark/weigh-pandoc.hs view
@@ -1,13 +1,14 @@ import Weigh import Text.Pandoc+import Data.Text (Text)  main :: IO () main = do-  doc <- read <$> readFile "tests/testsuite.native"+  doc <- read <$> readFile "test/testsuite.native"   mainWith $ do     func "Pandoc document" id doc     mapM_-      (\(n,r) -> weighReader doc n (handleError . r def{ readerSmart = True }))+      (\(n,r) -> weighReader doc n (either (error . show) id . runPure . r def{readerExtensions = pandocExtensions}))       [("markdown", readMarkdown)       ,("html", readHtml)       ,("docbook", readDocBook)@@ -15,22 +16,22 @@       ,("commonmark", readCommonMark)       ]     mapM_-      (\(n,w) -> weighWriter doc n (w def))+      (\(n,w) -> weighWriter doc n (either (error . show) id . runPure . w def))       [("markdown", writeMarkdown)-      ,("html", writeHtmlString)-      ,("docbook", writeDocbook)+      ,("html", writeHtml5String)+      ,("docbook", writeDocbook5)       ,("latex", writeLaTeX)       ,("commonmark", writeCommonMark)       ] -weighWriter :: Pandoc -> String -> (Pandoc -> String) -> Weigh ()+weighWriter :: Pandoc -> String -> (Pandoc -> Text) -> Weigh () weighWriter doc name writer = func (name ++ " writer") writer doc -weighReader :: Pandoc -> String -> (String -> Pandoc) -> Weigh ()+weighReader :: Pandoc -> String -> (Text -> Pandoc) -> Weigh () weighReader doc name reader = do   case lookup name writers of-       Just (PureStringWriter writer) ->-         let inp = writer def{ writerWrapText = WrapAuto} doc+       Just (TextWriter writer) ->+         let inp = either (error . show) id $ runPure $ writer def{ writerWrapText = WrapAuto} doc          in func (name ++ " reader") reader inp        _ -> return () -- no writer for reader 
changelog view
@@ -1,10780 +1,12560 @@-pandoc (1.19.2.4)--  * Add dependencies on texmath and skylighting to the executable.-    This is needed for dependency version numbers to be available,-    with Cabal > 2.--pandoc (1.19.2.3)--  * Add CPP to Setup.hs so it works with Cabal >= 2 and < 2.--pandoc (1.19.2.2)--  * Fix build with GHC 8.2.1 (#3876, Peter Simons).  Setup.hs does not-    compile with Cabal 2.x, so we require an earlier version via-    setup-depends.  The following packages need newer versions with-    GHC 8.2.1 and had their constraints relaxed accordingly:-    executable-path, process, syb, and time.--pandoc (1.19.2.1)--  * Require skylighting >= 0.1.1.4.-  * Adjust test output for skylighting version.-  * Relax upper bounds on blaze-html and blaze-markup.--pandoc (1.19.2)--  * Use skylighting library instead of highlighting-kate for syntax-    highlighting. Skylighting is faster and more accurate (#3363).-    Later we'll be able to add features like warning messages, dynamic-    loading of xml syntax definitions, and dynamic loading of themes.--  * Added a new highlight style, `breezeDark`.--  * Text.Pandoc.Highlighting: Update list of `listings` languages (#3374).-    This allows more languages to be used when using the `--listings`-    option.--  * OpenDocument writer:--    + Small refactoring.  Removed separate 'parent' parameter in paraStyle.-    + Don't profilerate text styles unnecessarily (#3371).-      This change makes the writer create only as many temporary-      text styles as are absolutely necessary. It also consolidates-      adjacent nodes with the same style.--  * Org reader (Albert Krewinkel):--    + Allow short hand for single-line raw blocks (Albert Krewinkel,-      #3366).  Single-line raw blocks can be given via `#+FORMAT: raw line`,-      where `FORMAT` must be one of `latex`, `beamer`, `html`, or `texinfo`.-    + Accept org-ref citations followed by commas (Albert Krewinkel).-      Bugfix for an issue which, whenever the citation was immediately-      followed by a comma, prevented correct parsing of org-ref citations.-    + Ensure emphasis markup can be nested.  Nested emphasis markup (e.g.-      `/*strong and emphasized*/`) was interpreted incorrectly in that the-      inner markup was not recognized.-    + Remove pipe char irking the haddock coverage tool (Albert Krewinkel).--  * Docx reader: Empty header should be list of lists (Jesse Rosenthal).-    In the past, the docx reader wrote an empty header as an empty list. It-    should have the same width as a row (and be filled with empty cells).--  * MediaWiki reader:--    + Improved handling of display math (#3362).  Sometimes display math is-      indented with more than one colon.  Previously we handled these cases-      badly, generating definition lists and missing the math.-    + Fix quotation mark parsing (#3336, tgkokk).  Change MediaWiki reader's-      behavior when the smart option is parsed to match other readers'-      behavior.--  * Markdown reader:--    + Fixed `-f markdown_github-hard_line_breaks+escaped_line_breaks`-      (#3341).  Previously this did not properly enable escaped line breaks.-    + Disallow space between inline code and attributes (#3326, #3323,-      Mauro Bieg).--  * DocBook5 writer: make id attribute xml:id, fixes #3329 (#3330, Mauro Bieg).--  * Added some test cases for ODT reader (#3306, #3308, Hubert Plociniczak).--  * LaTeX writer: allow tables with empty cells to count as "plain."-    This addresses a problem of too-wide tables when empty cells-    are used.  Thanks to Joost Kremers for reporting the issue.--  * Org writer: prefix footnote numbers with `fn:` (Albert Krewinkel).-    Unprefixed numbers where used by older org-mode versions, but are no-    longer supported.--  * HTML writer: don't process pars with empty RawInline, (#1040, #3327,-    Mauro Bieg).--  * Markdown writer: Fix display math with `--webtex` (#3298).--  * Fix sample.lua so it properly handles raw blocks/inlines (#3358,-    bumper314).--  * Templates:--    + default.latex: Moved geometry after hyperref (Václav Haisman).-      Otherwise PDF sizes can be wrong in some circumstances.-    + Copied a few changes from default.latex to default.beamer-      (Wandmalfarbe).-    + default.latex, default.beamer: Changed position of `\VerbatimNotes`-      and `fancyvrb`.  This fixes hyperlinks on footnotes in documents-      that contain verbatim in notes (#3361).  (Note: the beamer template-      was updated to match the LaTeX template, but at this point verbatim-      in notes seems not to work in beamer.)-    + default.latex: Allow passing `microtypeoptions` to microtype-      (Václav Haisman).-    + default.latex: Add hyphen option to url package.-    + default.docbook5: Fix namespace declarations (Mauro Bieg).--  * Moved `make_osx_package.sh` to `osx/` directory.--  * Travis continuous integration:--    + Fix false positives with dist build.-    + Speed improvements (Kolen Cheung, #3304, #3357).--  * MANUAL.txt:--    + Clarify that blank space is needed around footnotes (#3352).-    + Fixed typo (#3351, Alexey Rogechev).-    + Note that `--wrap=auto` does not work in HTML output.-    + Default `--columns` width is 72, not 80.-    + Fixed broken links (#3316, Kolen Cheung).-    + Document usage of `@*` in nocite section (#3333, John Muccigrosso).--  * INSTALL.md:--    + Indent code so it's properly formatted (#3335, Bheesham Persaud).-    + Added instructions for extracting binary from OSX, Windows packages.--  * CONTRIBUTING.md: Describe labels currently used in issue tracker-    (Albert Krewinkel).  The labels have changed over time, the list of-    labels is updated to reflect the current set of labels used in the-    issue tracker.--  * Rearrange and extend badges in README (Albert Krewinkel, #3354)--  * Bumped version bounds for dependencies.---pandoc (1.19.1)--  * Set `PANDOC_VERSION` environment variable for filters (#2640).-    This allows filters to check the pandoc version that produced-    the JSON they are receiving.--  * Docx reader: Ensure one-row tables don't have header (#3285,-    Jesse Rosenthal).  Tables in MS Word are set by default to have-    special first-row formatting, which pandoc uses to determine whether-    or not they have a header. This means that one-row tables will, by-    default, have only a header -- which we imagine is not what people-    want. This change ensures that a one-row table is not understood to-    be a header only.  Note that this means that it is impossible to-    produce a header-only table from docx, even though it is legal-    pandoc. But we believe that in nearly all cases, it will be an-    accidental (and unwelcome) result--  * HTML reader:--    + Fixed some bad regressions in HTML table parser (#3280).-      This regression leads to the introduction of empty rows-      in some circumstances.-    + Understand `style=width:` as well as `width` in `col` (#3286).--  * RST reader:--    + Print warnings when keys, substitition, notes not found.-      Previously the parsers failed and we got raw text.  Now we get a-      link with an empty URL, or empty inlines in the case of a note or-      substitution.--    + Fix hyperlink aliases (#3283).--  * Man writer: Ensure that periods are escaped at beginning of line-    (#3270).--  * LaTeX writer: Fix unnumbered headers when used with `--top-level`-    (#3272, Albert Krewinkel).  Fix interaction of top-level divisions-    `part` or `chapter` with unnumbered headers when emitting LaTeX.  Headers-    are ensured to be written using stared commands (like `\subsection*{}`).--  * LaTeX template: use comma not semicolon to separate keywords for-    `pdfkeywords`.  Thanks to Wandmalfarbe.--  * Markdown writer: Fixed incorrect word wrapping (#3277).  Previously pandoc-    would sometimes wrap lines too early due to this bug.--  * Text.Pandoc.Pretty:  Added `afterBreak` [API change].  This makes it-    possible to insert escape codes for content that needs escaping at the-    beginning of a line.--  * Removed old MathMLInHTML.js from 2004, which should no longer-    be needed for MathML with modern browsers.--  * Fixed tests with dynamic linking (#2709).--  * Makefile: Use stack instead of cabal for targets.  This is just-    a convenience for developers.--  * Fixed bash completion of filenames with space (#2749).--  * MANUAL: improved documentation on how to create a custom `reference.docx`.--  * Fix minor spelling typos in the manual (#3273, Anthony Geoghegan)--pandoc (1.19)--  * Changed resolution of filter paths.--    + We now first treat the argument of `--filter` as a full (absolute-      or relative) path, looking for a program there. If it's found, we-      run it.-    + If not, and if it is a simple program name or a relative path, we-      try resolving it relative to `$DATADIR/filters`.-    + If this fails, then we treat it as a program name and look in the-      user's PATH.-    + Removed a hardcoded '/' that may have caused problems with-      Windows paths.--    Previously if you did `--filter foo` and you had `foo` in your path and-    also an executable `foo` in your working directory, the one in the path-    would be used. Now the one in the working directory is used.--    In addition, when you do `--filter foo/bar.hs`, pandoc will now find a-    filter `$DATADIR/filters/foo/bar.hs` -- assuming there isn't a-    `foo/bar.hs` relative to the working directory.--  * Allow `file://` URIs as arguments (#3196). Also improved default reader-    format detection. Previously with a URI ending in .md or .markdown,-    pandoc would assume HTML input. Now it treats these as markdown.--  * Allow to overwrite top-level division type heuristics (#3258,-    Albert Krewinkel). Pandoc uses heuristics to determine the most-    reasonable top-level division type when emitting LaTeX or-    Docbook markup. It is now possible to overwrite this implicitly set-    top-level division via the `top-level-division` command line parameter.--  * Text.Pandoc.Options \[API changes\]:--    + Removed `writerStandalone` field in `WriterOptions`, made-      `writerTemplate` a `Maybe` value. Previously setting-      `writerStandalone = True` did nothing unless a template was provided-      in writerTemplate. Now a fragment will be generated if-      `writerTemplate` is `Nothing`; otherwise, the specified template-      will be used and standalone output generated.-    + `Division` has been renamed `TopLevelDivision` (#3197). The-      `Section`, `Chapter`, and `Part` constructors were renamed to-      `TopLevelSection`, `TopLevelChapter`, and-      `TopLevelPart`, respectively. An additional `TopLevelDefault`-      constructor was added, which is now also the new default value of-      the `writerTopLevelDivision` field in `WriterOptions`.--  * Improved error if they give wrong arg to `--top-level-division`.--  * Use new module from texmath to lookup MS font codepoints in Docx reader.-    Removed unexported module Text.Pandoc.Readers.Docx.Fonts. Its code now-    lives in texmath (0.9).--  * DocBook reader: Fixed xref lookup (#3243). It previously only worked-    when the qnames lacked the docbook namespace URI.--  * HTML reader:--    + Improved table parsing (#3027). We now check explicitly for non-1-      rowspan or colspan attributes, and fail when we encounter them.-      Previously we checked that each row had the same number of cells,-      but that could be true even with rowspans/colspans. And there are-      cases where it isn't true in tables that we can handle fine -- e.g.-      when a tr element is empty. So now we just pad rows with empty cells-      when needed.-    + Treat `<math>` as MathML by default unless something else is-      explicitly specified in xmlns. Provided it parses as MathML,-      of course. Also fixed default which should be to inline math if no-      display attribute is used.-    + Only treat "a" element as link if it has href (#3226). Otherwise-      treat as span.--  * Docx reader (Jesse Rosenthal):--    + Add a placeholder value for CHART. We wrap `[CHART]` in a-      `<span class="chart">`. Note that it maps to inlines because, in-      docx, anything in a drawing tag can be part of a larger paragraph.-    + Be more specific in parsing images We not only want `w:drawing`,-      because that could also include charts. Now we specify-      `w:drawing/pic:pic`. This shouldn't change behavior at all, but it's-      a first step toward allowing other sorts of drawing data as well.-    + Abstract out function to avoid code repetition.-    + Update tests for img title and alt (#3204).-    + Handle Alt text and titles in images. We use the "description" field-      as alt text and the "title" field as title. These can be accessed-      through the "Format Picture" dialog in Word.-    + Docx reader utils: handle empty namespace in `elemName`. Previously,-      if given an empty namespace `(elemName ns "" "foo")` `elemName`-      would output a QName with a `Just ""` namespace. This is never what-      we want. Now we output a `Nothing`. If someone *does* want a-      `Just ""` in the namespace, they can enter the QName-      value explicitly.--  * ODT reader/writer:--    + Inline code when text has a special style (Hubert Plociniczak). When-      a piece of text has a text `Source_Text` then we assume that this is-      a piece of the document that represents a code that needs to-      be inlined. Adapted the writer to also reflect that change.-      Previously it was just writing a 'preformatted' text using a-      non-distinguishable font style. Code blocks are still not recognized-      by the ODT reader. That's a separate issue.-    + Infer table's caption from the paragraph (#3224,-      Hubert Plociniczak). ODT's reader always put empty captions for the-      parsed tables. This commit--        1.  checks paragraphs that follow the table definition-        2.  treats specially a paragraph with a style named 'Table'-        3.  does some postprocessing of the paragraphs that combines tables-            followed immediately by captions--	The ODT writer used the `TableCaption` style for the caption-	paragraph.  This commit follows the OpenOffice approach which allows-	for appending captions to table but uses a built-in style named-	`Table` instead of `TableCaption`. Users of a custom `reference.odt`-	should change the style's name from `TableCaption` to `Table`.--  * ODT reader: Infer tables' header props from rows (#3199,-    Hubert Plociniczak). ODT reader simply provided an empty header list-    which meant that the contents of the whole table, even if not empty, was-    simply ignored. While we still do not infer headers we at least have to-    provide default properties of columns.--  * Markdown reader:--    +   Allow reference link labels starting with `@...` if `citations`-        extension disabled (#3209). Example: in--            \[link text\]\[@a\]--        `link text` isn't hyperlinked because `[@a]` is parsed as-        a citation. Previously this happened whether or not the `citations`-        extension was enabled. Now it happens only if the `citations`-        extension is enabled.-    +   Allow alignments to be specified in Markdown grid tables. For-        example,--            +-------+---------------+--------------------+-            | Right    | Left                 | Centered |-            +=========:+:=================+:=============:+-            | Bananas | $1.34         | built-in wrapper |-            +-------+---------------+--------------------+--    +   Allow Small Caps elements to be created using bracketed spans (as-        they already can be using HTML-syntax spans) (#3191, Kolen Cheung).--  * LaTeX reader:--    + Don't treat `\vspace` and `\hspace` as block commands (#3256).-      Fixed an error which came up, for example, with `\vspace` inside-      a caption. (Captions expect inlines.)-    + Improved table handling. We can now parse all of the tables emitted-      by pandoc in our tests. The only thing we don't get yet are-      alignments and column widths in more complex tables. See #2669.-    + Limited support for minipage.-    + Allow for `[]`s inside LaTeX optional args. Fixes cases like:-    + Handle BVerbatim from fancyvrb (#3203).-    + Handle hungarumlaut (#3201).-    + Allow beamer-style `<...>` options in raw LaTeX (also in Markdown)-      (#3184). This allows use of things like `\only<2,3>{my content}` in-      Markdown that is going to be converted to beamer.--  * Use pre-wrap for code in dzslides template (Nicolas Porcel). Otherwise-    overly long code will appear on every slide.--  * Org reader (Albert Krewinkel):--    +   Respect column width settings (#3246). Table column properties can-        optionally specify a column's width with which it is displayed in-        the buffer. Some exporters, notably the ODT exporter in org-mode-        v9.0, use these values to calculate relative column widths. The org-        reader now implements the same behavior. Note that the org-mode-        LaTeX and HTML exporters in Emacs don't support this feature yet,-        which should be kept in mind by users who use the column-        widths parameters.-    +   Allow HTML attribs on non-figure images (#3222). Images which are-        the only element in a paragraph can still be given HTML attributes,-        even if the image does not have a caption and is hence not a figure.-        The following will add set the `width` attribute of the image to-        `50%`:--            +ATTR\_HTML: :width 50%-            =======================--            \[\[file:image.jpg\]\]--    +   Support `ATTR_HTML` for special blocks (#3182). Special-        blocks (i.e. blocks with unrecognized names) can be prefixed with an-        `ATTR_HTML` block attribute. The attributes defined in that-        meta-directive are added to the `Div` which is used to represent the-        special block.-    +   Support the `todo` export option. The `todo` export option allows to-        toggle the inclusion of TODO keywords in the output. Setting this to-        `nil` causes TODO keywords to be dropped from headlines. The default-        is to include the keywords.-    +   Add support for todo-markers. Headlines can have optional-        todo-markers which can be controlled via the `#+TODO`, `#+SEQ_TODO`,-        or `#+TYP_TODO` meta directive. Multiple such directives can be-        given, each adding a new set of recognized todo-markers. If no-        custom todo-markers are defined, the default `TODO` and `DONE`-        markers are used. Todo-markers are conceptually separate from-        headline text and are hence excluded when autogenerating-        headline IDs. The markers are rendered as spans and labelled with-        two classes: One class is the markers name, the other signals the-        todo-state of the marker (either `todo` or `done`).--  * LaTeX writer:--    + Use `\autocites*` when "suppress-author" citation used.-    + Ensure that simple tables have simple cells (#2666). If cells-      contain more than a single Plain or Para, then we need to set-      nonzero widths and put contents into minipages.-    + Remove invalid inlines in sections (#3218, Hubert Plociniczak).--  * Markdown writer:--    + Fix calculation of column widths for aligned multiline tables-      (#1911, Björn Peemöller). This also fixes excessive CPU and memory-      usage for tables when `--columns` is set in such a way that cells-      must be very tiny. Now cells are guaranteed to be big enough so that-      single words don't need to line break, even if this pushes the line-      length above the column width.-    + Use bracketed form for native spans when `bracketed_spans`-      enabled (#3229).-    + Fixed inconsistent spacing issue (#3232). Previously a tight bullet-      sublist got rendered with a blank line after, while a tight ordered-      sublist did not. Now we don't get the blank line in either case.-    + Fix escaping of spaces in super/subscript (#3225). Previously two-      backslashes were inserted, which gave a literal backslash.-    + Adjust widths in Markdown grid tables so that they match-      on round-trip.--  * Docx writer:--    + Give full detail when there are errors converting tex math.-    + Handle title text in images (Jesse Rosenthal). We already handled-      alt text. This just puts the image "title" into the docx-      "title" attr.-    + Fixed XML markup for empty cells (#3238). Previously the Compact-      style wasn't being applied properly to empty cells.--  * HTML writer:--    + Updated `renderHtml` import from blaze-html.--  * Text.Pandoc.Pretty:--    + Fixed some bugs that caused blank lines in tables (#3251). The bugs-      caused spurious blank lines in grid tables when we had things like-      `blankline $$ blankline`.-    + Add exported function `minOffet` \[API change\] (Björn Peemöller).-    + Added error message for illegal call to `block` (Björn Peemöller).--  * Text.Pandoc.Shared:--    + Put `warn` in MonadIO.-    + `fetchItem`: Better handling of protocol-relative URL (#2635). If-      URL starts with `//` and there is no "base URL" (as there would be-      if a URL were used on the command line), then default to http:.--  * Export Text.Pandoc.getDefaultExtensions \[API change\] (#3178).--  * In --version, trap error in `getAppUserDataDirectory` (#3241). This-    fixes a crash with `pandoc --version` on unusual systems with no real-    user (e.g. SQL Server 2016).--  * Added weigh-pandoc for memory usage diagnostics (#3169).--  * Use correct mime types for woff and woff2 (#3228).--  * Remove make\_travis\_yml.hs (#3235, Kolen Cheung).--  * changelog: Moved an item that was misplaced in the 1.17.2 section to the-    1.18 section where it belongs.--  * CONTRIBUTING.md: minor change in wording and punctuation (#3252,-    Kolen Cheung).--  * Further revisions to manual for `--version` changes (#3244).---pandoc (1.18)--  * Added `--list-input-formats`, `--list-output-formats`,-    `--list-extensions`, `--list-highlight-languages`, and-    `--list-highlight-styles` (#3173).  Removed list of highlighting-    languages from `--version` output.  Removed list of input and output-    formats from default `--help` output.--  * Added `--reference-location=block|section|document` option-    (Jesse Rosenthal).  This determines whether Markdown link references-    and footnotes are placed at the end of the document, the end of the-    section, or the end of the top-level block.--  * Added `--top-level-division=section|chapter|part` (Albert Krewinkel).-    This determines what a level-1 header corresponds to in LaTeX,-    ConTeXt, DocBook, and TEI output.  The default is `section`.-    The `--chapters` option has been deprecated in favor of-    `--top-level-division=chapter`.--  * Added `LineBlock` constructor for `Block` (Albert Krewinkel).  This-    is now used in parsing RST and Markdown line blocks, DocBook-    `linegroup`/`line` combinations, and Org-mode `VERSE` blocks.-    Previously `Para` blocks with hard linebreaks were used.  `LineBlock`s-    are handled specially in the following ouput formats: AsciiDoc-    (as `[verse]` blocks), ConTeXt (`\startlines`/`\endlines`),-    HTML (`div` with a style), Markdown (line blocks if `line_blocks`-    is enabled), Org-mode (`VERSE` blocks), RST (line blocks). In-    other output formats, a paragraph with hard linebreaks is emitted.--  * Allow binary formats to be written to stdout (but not to tty) (#2677).-    Only works on posix, since we use the unix library to check whether-    output is to tty.  On Windows, pandoc works as before and always requires-    an output file parameter for binary formats.--  * Changed JSON output format (Jesse Rosenthal).  Previously we used-    generically generated JSON, but this was subject to change depending-    on the version of aeson pandoc was compiled with.  To ensure stability,-    we switched to using manually written ToJSON and FromJSON-    instances, and encoding the API version.  **Note:**  pandoc filter-    libraries will need to be revised to handle the format change.-    Here is a summary of the essential changes:--    + The toplevel JSON format is now `{"pandoc-api-version" :-      [MAJ, MIN, REV], "meta" : META, "blocks": BLOCKS}`-      instead of `[{"unMeta": META}, [BLOCKS]]`.-      Decoding fails if the major and minor version numbers don't-      match.-    + Leaf nodes no longer have an empty array for their "c" value.-      Thus, for example, a `Space` is encoded as `{"t":"Space"}`-      rather than `{"t":"Space","c":[]}` as before.--  * Removed `tests/Tests/Arbitrary.hs` and added a `Text.Pandoc.Arbitrary`-    module to pandoc-types (Jesse Rosenthal).  This makes it easier-    to use QuickCheck with pandoc types outside of pandoc itself.--  * Add `bracketed_spans` Markdown extension, enabled by default-    in pandoc `markdown`.  This allows you to create a native span-    using this syntax:  `[Here is my span]{#id .class key="val"}`.--  * Added `angle_brackets_escapable` Markdown extension (#2846).-    This is needed because github flavored Markdown has a slightly-    different set of escapable symbols than original Markdown;-    it includes angle brackets.--  * Export `Text.Pandoc.Error` in `Text.Pandoc` [API change].--  * Print highlighting-kate version in `--version`.--  * `Text.Pandoc.Options`:--    + `Extension` has new constructors `Ext_brackted_spans` and-      `Ext_angle_brackets_escapable` [API change].-    + Added `ReferenceLocation` type [API change] (Jesse Rosenthal).-    + Added `writerReferenceLocation` field to `WriterOptions` (Jesse-      Rosenthal).--  * `--filter`:  we now check `$DATADIR/filters` for filters before-    looking in the path (#3127, Jesse Rosenthal, thanks to Jakob-    Voß for the idea).  Filters placed in this directory need not-    be executable; if the extension is `.hs`, `.php`, `.pl`, `.js`,-    or `.rb`, pandoc will run the right interpreter.--  * For `--webtex`, replace deprecated Google Chart API by CodeCogs as-    default (Kolen Cheung).--  * Removed `raw_tex` extension from `markdown_mmd` defaults (Kolen Cheung).--  * Execute .js filters with node (Jakob Voß).--  * Textile reader:--    + Support `bc..` extended code blocks (#3037).  Also, remove trailing-      newline in code blocks (consistently with Markdown reader).-    + Improve table parsing.  We now handle cell and row attributes, mostly-      by skipping them.  However, alignments are now handled properly.-      Since in pandoc alignment is per-column, not per-cell, we-      try to devine column alignments from cell alignments.-      Table captions are also now parsed, and textile indicators-      for thead and tfoot no longer cause parse failure.  (However,-      a row designated as tfoot will just be a regular row in pandoc.)-    + Improve definition list parsing.  We now allow multiple terms-      (which we concatenate with linebreaks).  An exponential parsing-      bug (#3020) is also fixed.-    + Disallow empty URL in explicit link (#3036).--  * RST reader:--    + Use Div instead of BlockQuote for admonitions (#3031).-      The Div has class `admonition` and (if relevant) one of the-      following:  `attention`, `caution`, `danger`, `error`, `hint`,-      `important`, `note`, `tip`, `warning`.  **Note:** This will change-      the rendering of some RST documents!  The word ("Warning", "Attention",-      etc.) is no longer added; that must be done with CSS or a filter.-    + A Div is now used for `sidebar` as well.-    + Skip whitespace before note (Jesse Rosenthal, #3163).  RST requires a-      space before a footnote marker. We discard those spaces so that footnotes-      will be adjacent to the text that comes before it. This is in line with-      what rst2latex does.-    + Allow empty lines when parsing line blocks (Albert Krewinkel).--  * Markdown reader:--    + Allow empty lines when parsing line blocks (Albert Krewinkel).-    + Allow attributes on autolinks (#3183, Daniele D'Orazio).--  * LaTeX reader:--    + More robust parsing of unknown environments (#3026).-      We no longer fail on things like `^` inside options for tikz.-    + Be more forgiving of non-standard characters, e.g. `^` outside of math.-      Some custom environments give these a meaning, so we should try not to-      fall over when we encounter them.-    + Drop duplicate `*` in bibtexKeyChars (Albert Krewinkel)--  * MediaWiki reader:--    + Fix for unquoted attribute values in mediawiki tables (#3053).-      Previously an unquoted attribute value in a table row-      could cause parsing problems.-    + Improved treatment of verbatim constructions (#3055).-      Previously these yielded strings of alternating Code and Space-      elements; we now incorporate the spaces into the Code.  Emphasis-      etc. is still possible inside these.-    + Properly interpret XML tags in pre environments (#3042).  They are meant-      to be interpreted as literal text.--  * EPUB reader:  don't add root path to data: URIs (#3150).-    Thanks to @lep for the bug report and patch.--  * Org reader (Albert Krewinkel):--    + Preserve indentation of verse lines (#3064).  Leading spaces in verse-      lines are converted to non-breaking spaces, so indentation is preserved.-    + Ensure image sources are proper links.  Image sources as those in plain-      images, image links, or figures, must be proper URIs or relative file-      paths to be recognized as images.  This restriction is now enforced-      for all image sources.  This also fixes the reader's usage of uncleaned-      image sources, leading to `file:` prefixes not being deleted from-      figure images.  Thanks to @bsag for noticing this bug.-    + Trim verse lines properly (Albert Krewinkel).-    + Extract meta parsing code to module.  Parsing of meta-data is well-      separable from other block parsing tasks.  Moving into new module to-      get small files and clearly arranged code.-    + Read markup only for special meta keys.  Most meta-keys should be read-      as normal string values, only a few are interpreted as marked-up text.-    + Allow multiple, comma-separated authors.  Multiple authors can be-      specified in the `#+AUTHOR` meta line if they are given as a-      comma-separated list.-    + Give precedence to later meta lines.  The last meta-line of any given-      type is the significant line.  Previously the value of the first line-      was kept, even if more lines of the same type were encounterd.-    + Read LaTeX_header as header-includes.  LaTeX-specific header commands-      can be defined in `#+LaTeX_header` lines.  They are parsed as-      format-specific inlines to ensure that they will only show up in LaTeX-      output.-    + Set documentclass meta from LaTeX_class.-    + Set classoption meta from LaTeX_class_options.-    + Read HTML_head as header-includes.  HTML-specific head content can be-      defined in `#+HTML_head` lines.  They are parsed as format-specific-      inlines to ensure that they will only show up in HTML output.-    + Respect `author` export option.  The `author` option controls whether-      the author should be included in the final markup.  Setting-      `#+OPTIONS: author:nil` will drop the author from the final meta-data-      output.-    + Respect `email` export option.  The `email` option controls whether the-      email meta-field should be included in the final markup. Setting-      `#+OPTIONS: email:nil` will drop the email field from the final-      meta-data output.-    + Respect `creator` export option.  The `creator` option controls whether-      the creator meta-field should be included in the final markup.  Setting-      `#+OPTIONS: creator:nil` will drop the creator field from the final-      meta-data output.  Org-mode recognizes the special value `comment` for-      this field, causing the creator to be included in a comment.  This is-      difficult to translate to Pandoc internals and is hence interpreted the-      same as other truish values (i.e. the meta field is kept if it's-      present).-    + Respect unnumbered header property (#3095).  Sections the `unnumbered`-      property should, as the name implies, be excluded from the automatic-      numbering of section provided by some output formats.  The Pandoc-      convention for this is to add an "unnumbered" class to the header.  The-      reader treats properties as key-value pairs per default, so a special-      case is added to translate the above property to a class instead.-    + Allow figure with empty caption (Albert Krewinkel, #3161).-      A `#+CAPTION` attribute before an image is enough to turn an image into-      a figure. This wasn't the case because the `parseFromString` function,-      which processes the caption value, would fail on empty values. Adding-      a newline character to the caption value fixes this.--  * Docx reader:--    + Use XML convenience functions (Jesse Rosenthal).-      The functions `isElem` and `elemName` (defined in Docx/Util.hs) make-      the code a lot cleaner than the original XML.Light functions, but they-      had been used inconsistently. This puts them in wherever applicable.-    + Handle anchor spans with content in headers.  Previously, we would only-      be able to figure out internal links to a header in a docx if the-      anchor span was empty. We change that to read the inlines out of the-      first anchor span in a header.-    + Let headers use exisiting id.  Previously we always generated an id for-      headers (since they wouldn't bring one from Docx). Now we let it use an-      existing one if possible. This should allow us to recurs through anchor-      spans.-    + Use all anchor spans for header ids.  Previously we only used the first-      anchor span to affect header ids. This allows us to use all the anchor-      spans in a header, whether they're nested or not (#3088).-    + Test for nested anchor spans in header.  This ensures that anchor spans-      in header with content (or with other anchor spans inside) will resolve-      to links to a header id properly.--  * ODT reader (Hubert Plociniczak)--    + Include list's starting value.  Previously the starting value of-      the lists' items has been hardcoded to 1. In reality ODT's list-      style definition can provide a new starting value in one of its-      attributes.-    + Infer caption from the text following the image.-      Frame can contain other frames with the text boxes.-    + Add `fig:` to title for Image with a caption (as expected-      by pandoc's writers).-    + Basic support for images in ODT documents.-    + Don't duplicate text for anchors (#3143).  When creating an anchor-      element we were adding its representation as well as the original-      content, leading to text duplication.--  * DocBook writer:--    + Include an anchor element when a div or span has an id (#3102).-      Note that DocBook does not have a class attribute, but at least this-      provides an anchor for internal links.--  * LaTeX writer:--    + Don't use * for unnumbered paragraph, subparagraph.  The starred-      variants don't exist.  This helps with part of #3058...it gets rid of-      the spurious `*`s.  But we still have numbers on the 4th and 5th level-      headers.-    + Properly escape backticks in verbatim (#3121, Jesse Rosenthal).-      Otherwise they can cause unintended ligatures like `` ?` ``.-    + Handle NARRAOW NO-BREAK SPACE into LaTeX (Vaclav Zeman) as `\,`.-    + Don't include `[htbp]` placement for figures (#3103, Václav Haisman).-      This allows figure placement defaults to be changed by the user-      in the template.--  * HTML writer (slide show formats): In slide shows, don't change slide title-    to level 1 header (#2221).--  * TEI writer: remove heuristic to detect book template (Albert Krewinkel).-    TEI doesn't have `<book>` elements but only generic `<divN>` division-    elements. Checking the template for a trailing `</book>` is nonsensical.--  * MediaWiki writer:  transform filename with underscores in images (#3052).-    `foo bar.jpg` becomes `foo_bar.jpg`. This was already done-    for internal links, but it also needs to happen for images.--  * ICML writer: replace partial function (!!) in table handling (#3175,-    Mauro Bieg).--  * Man writer: allow section numbers that are not a single digit (#3089).--  * AsciiDoc writer: avoid unnecessary use of "unconstrained" emphasis-    (#3068).  In AsciiDoc, you must use a special form of emphasis-    (double `__`) for intraword emphasis.  Pandoc was previously using-    this more than necessary.--  * EPUB writer:  use stringify instead of plain writer for metadata-    (#3066).  This means that underscores won't be used for emphasis,-    or CAPS for bold.  The metadata fields will just have unadorned-    text.--  * Docx Writer:--    + Implement user-defined styles (Jesse Rosenthal).  Divs and Spans-      with a `custom-style` key in the attributes will apply the corresponding-      key to the contained blocks or inlines.-    + Add ReaderT env to the docx writer (Jesse Rosenthal).-    + Clean up and streamline RTL behavior (Jesse Rosenthal, #3140).-      You can set `dir: rtl` in YAML metadata, or use `-M dir=rtl`-      on the command line.  For finer-grained control, you can set-      the `dir` attribute in Div or Span elements.--  * Org writer (Albert Krewinkel):--    + Remove blank line after figure caption.  Org-mode only treats an image-      as a figure if it is directly preceded by a caption.-    + Ensure blank line after figure.  An Org-mode figure should be surrounded-      by blank lines.  The figure would be recognized regardless, but images-      in the following line would unintentionally be treated as figures as-      well.-    + Ensure link targets are paths or URLs.  Org-mode treats links as-      document internal searches unless the link target looks like a URL or-      file path, either relative or absolute.  This change ensures that this-      is always the case.-    + Translate language identifiers.  Pandoc and Org-mode use different-      programming language identifiers.  An additional translation between-      those identifiers is added to avoid unexpected behavior.  This fixes a-      problem where language specific source code would sometimes be output-      as example code.-    + Drop space before footnote markers (Albert Krewinkel, #3162).-      The writer no longer adds an extra space before footnote markers.--  * Markdown writer:--    + Don't emit HTML for tables unless `raw_html` extension is set (#3154).-      Emit `[TABLE]` if no suitable table formats are enabled and raw HTML-      is disabled.-    + Check for the `raw_html` extension before emiting a raw HTML block.-    + Abstract out note/ref function (Jesse Rosenthal).-    + Add ReaderT monad for environment variables (Jesse Rosenthal).--  * HTML, EPUB, slidy, revealjs templates: Use `<p>` instead of `<h1>` for-    subtitle, author, date (#3119).  Note that, as a result of this change,-    authors may need to update CSS.--  * revealjs template:  Added `notes-server` option-    (jgm/pandoc-templates#212, Yoan Blanc).--  * Beamer template:--    + Restore whitespace between paragraphs. This was-      a regression in the last release (jgm/pandoc-templates#207).-    + Added `themeoptions` variable (Carsten Gips).-    + Added `beamerarticle` variable.  This causes the `beamerarticle`-      package to be loaded in beamer, to produce an article from beamer-      slides.  (Carsten Gips)-    + Added support for `fontfamilies` structured variable-      (Artem Klevtsov).-    + Added hypersetup options (Jake Zimmerman).--  * LaTeX template:--    + Added dummy definition for `\institute`.-      This isn't a standard command, and we want to avoid a crash when-      `institute` is used with the default template.-    + Define default figure placement (Václav Haisman), since pandoc-      no longer includes `[htbp]` for figures.  Users with custom templates-      will want to add this. See #3103.-    + Use footnote package to fix notes in tables (jgm/pandoc-templates#208,-      Václav Haisman).--  * Moved template compiling/rendering code to a separate library.-    `doctemplates`.  This allows the pandoc templating system to be-    used independently.--  * Text.Pandoc.Error: Fix out of index error in `handleError`-    (Matthew Pickering).  The fix is to not try to show the exact line when-    it would cause an out-of-bounds error as a result of included files.--  * Text.Pandoc.Shared: Add `linesToBlock` function (Albert Krewinkel).--  * Text.Pandoc.Parsing.emailAddress: tighten up parsing of email-    addresses.  Technically `**@user` is a valid email address, but if we-    allow things like this, we get bad results in markdown flavors-    that autolink raw email addresses (see #2940).  So we exclude a few-    valid email addresses in order to avoid these more common bad cases.--  * Text.Pandoc.PDF:  Don't crash with nonexistent image (#3100).  Instead,-    emit the alt text, emphasized.  This accords with what the ODT writer-    currently does.  The user will still get a warning about a nonexistent-    image.--  * Fix example in API documentation (#3176, Thomas Weißschuh).--  * Tell where to get tarball in INSTALL (#3062).--  * Rename README to MANUAL.txt and add GitHub-friendly README.md-    (Albert Krewinkel, Kolen Cheung).--  * Replace COPYING with Markdown version COPYING.md from GNU (Kolen Cheung).--  * MANUAL.txt:--    + Put note on structured vars in separate paragraph (#2148, Albert-      Krewinkel).  Make it clearer that structured author variables require a-      custom template-    + Note that `--katex` works best with `html5` (#3077).-    + Fix the LaTeX and EPUB links in manual (Morton Fox).-    + Document `biblio-title` variable.--  * Improve spacing of footnotes in `--help` output (Waldir Pimenta).--  * Update KaTeX to v0.6.0 (Kolen Cheung).--  * Allow latest dependencies.--  * Use texmath 0.8.6.6 (#3040).--  * Allow http-client 0.4.30, which is the version in stackage lts.-    Previously we required 0.5.-    Remove CPP conditionals for earlier versions.--  * Remove support for GHC < 7.8 (Jesse Rosenthal).--    + Remove Compat.Monoid.-    + Remove an inline monad compatibility macro.-    + Remove Text.Pandoc.Compat.Except.-    + Remove directory compat.-    + Change constraint on mtl.-    + Remove unnecessary CPP condition in UTF8.-    + Bump base lower bound to 4.7.-    + Remove 7.6 build from .travis.yaml.-    + Bump supported ghc version in CONTRIBUTING.md.-    + Add note about GHC version support to INSTALL.-    + Remove GHC 7.6 from list of tested versions (Albert Krewinkel).-    + Remove TagSoup compat.-    + Add EOL note to time compat module.  Because time 1.4 is a boot library-      for GHC 7.8, we will support the compatibility module as long as we-      support 7.8. But we should be clear about when we will no longer need-      it.-    + Remove blaze-html CPP conditional.-    + Remove unnecessary CPP in custom Prelude.--pandoc (1.17.2)--  * Added Zim Wiki writer, template and tests. `zimwiki` is now-    a valid output format. (Alex Ivkin)--  * Changed email-obfuscation default to no obfuscation (#2988).-    + `writerEmailObfuscation` in `defaultWriterOptions` is now-      `NoObfuscation`.-    + the default for the command-line `--email-obfuscation` option is-      now `none`.--  * Docbook writer: Declare xlink namespace in Docbook5 output (Ivo Clarysse).--  * Org writer:--    + Support arbitrary raw inlines (Albert Krewinkel).-      Org mode allows arbitrary raw inlines ("export snippets" in Emacs-      parlance) to be included as `@@format:raw foreign format text@@`.-    + Improve Div handling (Albert Krewinkel).  Div blocks handling is-      changed to make the output look more like idiomatic org mode:-        - Div-wrapped content is output as-is if the div's attribute is the-          null attribute.-        - Div containers with an id but neither classes nor key-value pairs-          are unwrapped and the id is added as an anchor.-        - Divs with classes associated with greater block elements are-          wrapped in a `#+BEGIN`...`#+END` block.-        - The old behavior for Divs with more complex attributes is kept.--  * HTML writer:--    + Better support for raw LaTeX environments (#2758).-      Previously we just passed all raw TeX through when MathJax was used for-      HTML math.  This passed through too much.  With this patch, only raw-      LaTeX environments that MathJax can handle get passed through.-      This patch also causes raw LaTeX environments to be treated-      as math, when possible, with MathML and WebTeX output.--  * Markdown writer:  use raw HTML for simple, pipe tables with linebreaks-    (#2993).  Markdown line breaks involve a newline, and simple and pipe-    tables can't contain one.--  * Make --webtex work with the Markdown writer (#1177).-    This is a convenient option for people using-    websites whose Markdown flavors don't provide for math.--  * Docx writer:--    + Set paragraph to FirstPara after display math (Jesse Rosenthal).-      We treat display math like block quotes, and apply FirstParagraph style-      to paragraphs that follow them. These can be styled as the user-      wishes. (But, when the user is using indentation, this allows for-      paragraphs to continue after display math without indentation.)-    + Use actual creation time as doc prop (Jesse Rosenthal).-      Previously, we had used the user-supplied date, if available, for Word's-      document creation metadata. This could lead to weird results, as in-      cases where the user post-dates a document (so the modification might be-      prior to the creation). Here we use the actual computer time to set the-      document creation.--  * LaTeX writer:--    + Don't URI-escape image source (#2825).  Usually this is a local file,-      and replacing spaces with `%20` ruins things.-    + Allow 'standout' as a beamer frame option (#3007).-      `## Slide title {.standout}`.--  * RST reader: Fixed links with no explicit link text.  The link-    `` `<foo>`_ `` should have `foo` as both its link text and its URL.-    See RST spec at <http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html#embedded-uris-and-aliases>-    Closes Debian #828167 -- reported by Christian Heller.--  * Textile reader:--    + Fixed attributes (#2984).  Attributes can't be followed by-      a space.  So, `_(class)emph_` but `_(noclass) emph_`.-    + Fixed exponential parsing bug (#3020).-    + Fix overly aggressive interpretation as images (#2998).-      Spaces are not allowed in the image URL in textile.--  * LaTeX reader:--    + Fix `\cite` so it is a NormalCitation not AuthorInText.-    + Strip off double quotes around image source if present (#2825).-      Avoids interpreting these as part of the literal filename.--  * Org reader:--    + Add semicolon to list of special chars (Albert Krewinkel)-      Semicolons are used as special characters in citations syntax.  This-      ensures the correct parsing of Pandoc-style citations: `[prefix; @key;-      suffix]`.  Previously, parsing would have failed unless there was a space-      or other special character as the last <prefix> character.-    + Add support for "Berkeley-style" cites (Albert Krewinkel, #1978).-      A specification for an official Org-mode citation syntax was drafted by-      Richard Lawrence and enhanced with the help of others on the orgmode-      mailing list.  Basic support for this citation style is added to the-      reader.-    + Support arbitrary raw inlines (Albert Krewinkel).-      Org mode allows arbitrary raw inlines ("export snippets" in Emacs-      parlance) to be included as `@@format:raw foreign format text@@`.-    + Remove partial functions (Albert Krewinkel, #2991).-      Partial functions like `head` lead to avoidable errors and should be-      avoided.  They are replaced with total functions.-    + Support figure labels (Albert Krewinkel, #2496, #2999).-      Figure labels given as `#+LABEL: thelabel` are used as the ID of the-      respective image.  This allows e.g. the LaTeX to add proper `\label`-      markup.-    + Improve tag and properties type safety (Albert Krewinkel).-      Specific newtype definitions are used to replace stringly typing of tags-      and properties.  Type safety is increased while readability is improved.-    + Parse as headlines, convert to blocks (Albert Krewinkel).-      Emacs org-mode is based on outline-mode, which treats documents as trees-      with headlines are nodes.  The reader is refactored to parse into a-      similar tree structure.  This simplifies transformations acting on-      document (sub-)trees.-    * Refactor comment tree handling (Albert Krewinkel).-      Comment trees were handled after parsing, as pattern matching on lists-      is easier than matching on sequences.  The new method of reading-      documents as trees allows for more elegant subtree removal.-    * Support archived trees export options (Albert Krewinkel).-      Handling of archived trees can be modified using the `arch` option.-      Archived trees are either dropped, exported completely, or collapsed to-      include just the header when the `arch` option is nil, non-nil, or-      `headline`, respectively.-    * Put export setting parser into module (Albert Krewinkel).-      Export option parsing is distinct enough from general block parsing to-      justify putting it into a separate module.-    * Support headline levels export setting (Albert Krewinkel).-      The depths of headlines can be modified using the `H` option.  Deeper-      headlines will be converted to lists.-    * Replace ugly code with view pattern (Albert Krewinkel).-      Some less-than-smart code required a pragma switching of overlapping-      pattern warnings in order to compile seamlessly.  Using view patterns-      makes the code easier to read and also doesn't require overlapping-      pattern checks to be disabled.-    * Fix parsing of verbatim inlines (Albert Krewinkel, #3016).-      Org rules for allowed characters before or after markup chars were not-      checked for verbatim text.  This resultet in wrong parsing outcomes of-      if the verbatim text contained e.g. space enclosed markup characters as-      part of the text (`=is_substr = True=`).  Forcing the parser to update-      the positions of allowed/forbidden markup border characters fixes this.--  * LaTeX template: fix for obscure hyperref/xelatex issue.-    Here's a minimal case:--        \documentclass[]{article}-        \usepackage{hyperref}-        \begin{document}-        \section{\%á}-        \end{document}--    Without this change, this fails on the second invocation of xelatex.-    This affects inputs this like `# %á` with pdf output via xelatex.--  * trypandoc:  call results 'html' instead of 'result'.-    This is for better compatibility with babelmark2.--  * Document MultiMarkdown as input/output format (Albert Krewinkel, #2973).-    MultiMarkdown was only mentioned as a supported Markdown dialect but not-    as a possible input or output format.  A brief mention is added-    everywhere the other supported markdown dialects are mentioned.--  * Document Org mode as a format containing raw HTML (Albert Krewinkel)-    Raw HTML is kept when the output format is Emacs Org mode.--  * Implement `RawInline` and `RawBlock` in sample lua custom writer (#2985).--  * Text.Pandoc.Shared:--    + Introduce blocksToInlines function (Jesse Rosenthal).-      This is a lossy function for converting `[Block] -> [Inline]`. Its main-      use, at the moment, is for docx comments, which can contain arbitrary-      blocks (except for footnotes), but which will be converted to spans.-      This is, at the moment, pretty useless for everything but the basic-      `Para` and `Plain` comments. It can be improved, but the docx reader-      should probably emit a warning if the comment contains more than this.-    + Add BlockQuote to blocksToInlines (Jesse Rosenthal).-    + Add further formats for `normalizeDate` (Jesse Rosenthal).-      We want to avoid illegal dates -- in particular years with greater than-      four digits. We attempt to parse series of digits first as `%Y%m%d`, then-      `%Y%m`, and finally `%Y`.-    + `normalizeDate` should reject illegal years (Jesse Rosenthal).-      We only allow years between 1601 and 9999, inclusive. The ISO 8601-      actually says that years are supposed to start with 1583, but MS Word-      only allows 1601-9999. This should stop corrupted word files if the date-      is out of that range, or is parsed incorrectly.-    + Improve year sanity check in normalizeDate (Jesse Rosenthal).-      Previously we parsed a list of dates, took the first one, and then-      tested its year range. That meant that if the first one failed, we-      returned nothing, regardless of what the others did. Now we test for-      sanity before running `msum` over the list of Maybe values. Anything-      failing the test will be Nothing, so will not be a candidate.--  * Docx reader:--    + Add simple comment functionality. (Jesse Rosenthal).-      This adds simple track-changes comment parsing to the docx reader. It is-      turned on with `--track-changes=all`. All comments are converted to-      inlines, which can list some information. In the future a warning will be-      added for comments with formatting that seems like it will be excessively-      denatured.  Note that comments can extend across blocks. For that reason-      there are two spans: `comment-start` and `comment-end`.  `comment-start`-      will contain the comment. `comment-end` will always be empty.  The two-      will be associated by a numeric id.-    + Enable warnings in top-level reader (Jesse Rosenthal).-      Previously we had only allowed for warnings in the parser. Now we allow-      for them in the `Docx.hs` as well. The warnings are simply concatenated.-    + Add warning for advanced comment formatting. (Jesse Rosenthal).-      We can't guarantee we'll convert every comment correctly, though we'll-      do the best we can. This warns if the comment includes something other-      than Para or Plain.-    + Add tests for warnings. (Jesse Rosenthal).-    + Add tests for comments (Jesse Rosenthal).-      We test for comments, using all track-changes options. Note that we-      should only output comments if `--track-changes=all`. We also test for-      emitting warnings if there is complicated formatting.--  * README: update to include track-changes comments. (Jesse Rosenthal)--  * Improved Windows installer - don't ignore properties set on command-line.-    See #2708.  Needs testing to see if this resolves the issue.-    Thanks to @nkalvi.--  * Process markdown extensions on command line in L->R order (#2995).-    Previously they were processed, very unintuitively, in R->L-    order, so that `markdown-tex_math_dollars+tex_math_dollars`-    had `tex_math_dollars` disabled.--  * Added `secnumdepth` variable to LaTeX template (#2920).--  * Include table of contents in README.html in Windows package.--  * Writers: treat SoftBreak as space for stripping (Jesse Rosenthal)-    In Writers.Shared, we strip leading and trailing spaces for display-    math. Since SoftBreak's are treated as spaces, we should strip those-    too.--  * beamer, latex templates:  pass biblatexoptions directly in package load.-    This allows runtime optinos to be used.  Fixes jgm/pandoc-citeproc#201--  * CPP workaround for deprecation of `parseUrl` in http-client.--  * Removed some redundant class constraints.--  * make_oxs_package.sh - use OSX env variable.--  * Replaced INSTALL with INSTALL.md, incorporating INSTALL and the-    old installing page from website.--  * Added `winpkg` target to Makefile.  This downloads the windows package-    from appveyor and signs it using the key.--  * Document Org mode as a format containing raw TeX (Albert Krewinkel).-    Raw TeX is kept verbatim when the output format is Emacs Org mode.--  * Support math with haddock-library >= 1.4.--  * Removed `-rtsopts` from library stanza.  It has no effect, and Hackage-    wouldn't accept the package.--  * Update library dependency versions.--pandoc (1.17.1)--  * New output format: `docbook5` (Ivo Clarysse).--  * `Text.Pandoc.Options`: Add `writerDocBook5` to `WriterOptions`-    (API change).--  * Org writer:--    + Add :PROPERTIES: drawer support (Albert Krewinkel, #1962).-      This allows header attributes to be added to org documents in the form-      of `:PROPERTIES:` drawers.  All available attributes are stored as-      key/value pairs.  This reflects the way the org reader handles-      `:PROPERTIES:` blocks.-    + Add drawer capability (Carlos Sosa).  For the implementation of the-      Drawer element in the Org Writer, we make use of a generic Block-      container with attributes.  The presence of a `drawer` class defines-      that the `Div` constructor is a drawer. The first class defines the-      drawer name to use.  The key-value list in the attributes defines-      the keys to add inside the Drawer.  Lastly, the list of Block elements-      contains miscellaneous blocks elements to add inside of the Drawer.-    + Use `CUSTOM_ID` in properties (Albert Krewinkel).  The `ID` property is-      reserved for internal use by Org-mode and should not be used.-      The `CUSTOM_ID` property is to be used instead, it is converted to the-      `ID` property for certain export format.--  * LaTeX writer:--    + Ignore `--incremental` unless output format is beamer (#2843).-    + Fix polyglossia to babel env mapping (Mauro Bieg, #2728).-      Allow for optional argument in square brackets.-    + Recognize `la-x-classic` as Classical Latin (Andrew Dunning).-      This allows one to access the hyphenation patterns in CTAN's-      hyph-utf8.-    + Add missing languages from hyph-utf8 (Andrew Dunning).-    + Improve use of `\strut` with `\minipage` inside tables-      (Jose Luis Duran).  This improves spacing in multiline-      tables.-    + Use `{}` around options containing special chars (#2892).-    + Avoid lazy `foldl`.-    + Don't escape underscore in labels (#2921).  Previously they were-      escaped as `ux5f`.-    + brazilian -> brazil for polyglossia (#2953).--  * HTML writer: Ensure mathjax link is added when math appears in footnote-    (#2881).  Previously if a document only had math in a footnote, the-    MathJax link would not be added.--  * EPUB writer: set `navpage` variable on nav page.-    This allows templates to treat it differently.--  * DocBook writer:--    + Use docbook5 if `writerDocbook5` is set (Ivo Clarysse).-    + Properly handle `ulink`/`link` (Ivo Clarysse).--  * EPUB reader:--    + Unescape URIs in spine (#2924).-    + EPUB reader:  normalise link id (Mauro Bieg).--  * Docx Reader:--    + Parse `moveTo` and `moveFrom` (Jesse Rosenthal).-      `moveTo` and `moveFrom` are track-changes tags that are used when a-      block of text is moved in the document. We now recognize these tags and-      treat them the same as `insert` and `delete`, respectively. So,-      `--track-changes=accept` will show the moved version, while-      `--track-changes=reject` will show the original version.-    + Tests for track-changes moving (Jesse Rosenthal).--  * ODT, EPUB, Docx readers: throw `PandocError` on unzip failure-    (Jesse Rosenthal) Previously, `readDocx`, `readEPUB`, and `readOdt`-    would error out if zip-archive failed. We change the archive extraction-    step from `toArchive` to `toArchiveOrFail`, which returns an Either value.--  * Markdown, HTML readers:  be more forgiving about unescaped `&` in-    HTML (#2410).  We are now more forgiving about parsing invalid HTML with-    unescaped `&` as raw HTML.  (Previously any unescaped `&`-    would cause pandoc not to recognize the string as raw HTML.)--  * Markdown reader:--    + Added bracket syntax for native spans (#168).-    + Fix pandoc title blocks with lines ending in 2 spaces (#2799).-    + Added `-s` to markdown-reader-more test.--  * HTML reader: fixed bug in `pClose`.  This caused exponential parsing-    behavior in documnets with unclosed tags in `dl`, `dd`, `dt`.--  * MediaWiki reader: Allow spaces before `!` in MediaWiki table header-    (roblabla).--  * RST reader: Support `:class:` option for code block in RST reader-    (Sidharth Kapur).--  * Org reader (all Albert Krewinkel, except where noted otherwise):--    + Stop padding short table rows.-      Emacs Org-mode doesn't add any padding to table rows.  The first-      row (header or first body row) is used to determine the column count,-      no other magic is performed.-    + Refactor rows-to-table conversion.  This refactors-      the codes conversing a list table lines to an org table ADT.-      The old code was simplified and is now slightly less ugly.-    + Fix handling of empty table cells, rows (Albert Krewinkel, #2616).-      This fixes Org mode parsing of some corner cases regarding empty cells-      and rows.  Empty cells weren't parsed correctly, e.g. `|||` should be-      two empty cells, but would be parsed as a single cell containing a pipe-      character.  Empty rows where parsed as alignment rows and dropped from-      the output.-    + Fix spacing after LaTeX-style symbols.-      The org-reader was droping space after unescaped LaTeX-style symbol-      commands: `\ForAll \Auml` resulted in `∀Ä` but should give `∀ Ä`-      instead.  This seems to be because the LaTeX-reader treats the-      command-terminating space as part of the command.  Dropping the trailing-      space from the symbol-command fixes this issue.-    + Print empty table rows.  Empty table rows should not-      be dropped from the output, so row-height is always set to be at least 1.-    + Move parser state into separate module.-      The org reader code has become large and confusing.  Extracting smaller-      parts into submodules should help to clean things up.-    + Add support for sub/superscript export options.-      Org-mode allows to specify export settings via `#+OPTIONS` lines.-      Disabling simple sub- and superscripts is one of these export options,-      this options is now supported.-    + Support special strings export option Parsing of special strings-      (like `...` as ellipsis or `--` as en dash) can be toggled using the `-`-      option.-    + Support emphasized text export option.  Parsing of emphasized text can-      be toggled using the `*` option.  This influences parsing of text marked-      as emphasized, strong, strikeout, and underline.  Parsing of inline math,-      code, and verbatim text is not affected by this option.-    + Support smart quotes export option.  Reading of smart quotes can be-      toggled using the `'` option.-    + Parse but ignore export options. All known export options are parsed-      but ignored.-    + Refactor block attribute handling.  A parser state attribute was used-      to keep track of block attributes defined in meta-lines.  Global state-      is undesirable, so block attributes are no longer saved as part of the-      parser state.  Old functions and the respective part of the parser state-      are removed.-    + Use custom `anyLine`.  Additional state changes need to be made after-      a newline is parsed, otherwise markup may not be recognized correctly.-      This fixes a bug where markup after certain block-types would not be-      recognized.-    + Add support for `ATTR_HTML` attributes (#1906).-      Arbitrary key-value pairs can be added to some block types using a-      `#+ATTR_HTML` line before the block.  Emacs Org-mode only includes these-      when exporting to HTML, but since we cannot make this distinction here,-      the attributes are always added.  The functionality is now supported-      for figures.-    + Add `:PROPERTIES:` drawer support (#1877).-      Headers can have optional `:PROPERTIES:` drawers associated with them.-      These drawers contain key/value pairs like the header's `id`.  The-      reader adds all listed pairs to the header's attributes; `id` and-      `class` attributes are handled specially to match the way `Attr` are-      defined.  This also changes behavior of how drawers of unknown type-      are handled.  Instead of including all unknown drawers, those are not-      read/exported, thereby matching current Emacs behavior.-    + Use `CUSTOM_ID` in properties.  See above on Org writer changes.-    + Respect drawer export setting.  The `d` export option can be used-      to control which drawers are exported and which are discarded.-      Basic support for this option is added here.-    + Ignore leading space in org code blocks (Emanuel Evans, #2862).-      Also fix up tab handling for leading whitespace in code blocks.-    + Support new syntax for export blocks.  Org-mode version 9-      uses a new syntax for export blocks.  Instead of `#+BEGIN_<FORMAT>`,-      where `<FORMAT>` is the format of the block's content, the new-      format uses `#+BEGIN_export <FORMAT>` instead.  Both types are-      supported.-    + Refactor `BEGIN...END` block parsing.-    + Fix handling of whitespace in blocks, allowing content to be indented-      less then the block header.-    + Support org-ref style citations.  The *org-ref* package is an-      org-mode extension commonly used to manage citations in org-      documents.  Basic support for the `cite:citeKey` and-      `[[cite:citeKey][prefix text::suffix text]]` syntax is added.-    + Split code into separate modules, making for cleaner code and-      better decoupling.--  * Added `docbook5` template.--  * `--mathjax` improvements:--    + Use new CommonHTML output for MathJax (updated default MathJax URL,-      #2858).-    + Change default mathjax setup to use `TeX-AMS_CHTML` configuration.-      This is designed for cases where the input is always TeX and maximal-      conformity with TeX is desired.  It seems to be smaller and load faster-      than what we used before.  See #2858.-    + Load the full MathJax config to maximize loading speed (KolenCheung).--  * Bumped upper version bounds to allow use of latest packages-    and compilation with ghc 8.--  * Require texmath 0.8.6.2.  Closes several texmath-related bugs (#2775,-    #2310, #2310, #2824).  This fixes behavior of roots, e.g.-    `\sqrt[3]{x}`, and issues with sub/superscript positioning-    and matrix column alignment in docx.--  * README:--    + Clarified documentation of `implicit_header_references` (#2904).-    + Improved documentation of `--columns` option.--  * Added appveyor setup, with artefacts (Jan Schulz).--  * stack.yaml versions: Use proper flags used for texmath, pandoc-citeproc.--  * LaTeX template: support for custom font families (vladipus).-    Needed for correct polyglossia operation with Cyrillic fonts and perhaps-    can find some other usages.  Example usage in YAML metadata:--          fontfamilies:-          - name: \cyrillicfont-            font: Liberation Serif-          - name: \cyrillicfonttt-            options: Scale=MatchLowercase-            font: Liberation--  * Create unsigned msi as build artifact in appveyor build.--  * On travis, test with ghc 8.0.1; drop testing for ghc 7.4.1.--pandoc (1.17.0.3)--  * LaTeX writer: Fixed position of label in figures (#2813).-    Previously the label wasn't in the right place, and `\ref`-    wouldn't work properly.-  * Added .tei test files to pandoc.cabal so they'll be included-    in tarball (#2811).-  * Updated copyright dates.--pandoc (1.17.0.2)--  * Fixed serious regression in `htmlInBalanced`, which caused-    newlines to be omitted in some raw HTML blocks in Markdown-    (#2804).--pandoc (1.17.0.1)--  * File scope is no longer used when there are no input files (i.e.,-    when input comes from stdin).  Previously file scope was triggered-    when the `json` reader was specified and input came from `stdin`,-    and this caused no output to be produced.  (Fix due to Jesse Rosenthal;-    thanks to Fedor Sheremetyev for calling the bug to our attention.)-  * Improved documentation of templates (#2797).--pandoc (1.17)--  * Added `--file-scope` option (Jesse Rosenthal).-    By default pandoc operates on multiple files by first concatenating-    them (around extra line breaks) and then processing the joined file. So-    it only parses a multi-file document at the document scope. This has the-    benefit that footnotes and links can be in different files, but for-    some purposes it is useful to parse the individual files first-    and then combine their outputs (e.g. when the files use footnotes-    or links with the same labels).  The `--file-scope` option causes-    pandoc to parse the files first, and then combine the parsed output,-    instead of combining before parsing. `--file-scope` is selected-    automatically for binary input files (which cannot be concatenated)-    and for pandoc json.--  * Add TEI Writer (Chris Forster) and `tei` output format.--  * Added a general `ByteStringReader` with warnings, used by the docx-    reader (API change, Jesse Rosenthal).--  * Add `readDocxWithWarnings` (API change, Jesse Rosenthal).--  * Changed type of `Shared.uniqueIdent`'s argument from `[String]`-    to `Set String.` This avoids performance problems in documents with-    many identically named headers (API change, #2671).--  * Removed `tex_math_single_backslash` from `markdown_github` options-    (#2707).--  * Make language extensions as well as full language names-    trigger syntax highlighting.  For example, `py` will now work as-    well as `python` (jgm/highlighting-kate#83).--  * Added `institute` variable to latex, beamer templates (Fraser-    Tweedale, Josef Svenningsson).--  * Docx reader (Jesse Rosenthal):--    + Handle alternate content.  Some word functions (especially graphics)-      give various choices for content so there can be backwards compatibility.-    + Don't turn numbered headers into lists.-    + Docx Reader: Add state to the parser, for warnings-    + Update feature checklist in source code.-    + Get rid of `Modifiable` typeclass.-    + Add tests for adjacent hyperlinks.-    + Add a "Link" modifier to `Reducible`. We want to make sure that-      links have their spaces removed, and are appropriately smushed-      together (#2689).--  * HTML reader:--    + Fixed behavior of base tag (#2777).-      If the base path does not end with slash, the last component-      will be replaced.  E.g. base = `http://example.com/foo`-      combines with `bar.html` to give `http://example.com/bar.html`.-      If the href begins with a slash, the whole path of the base-      is replaced.  E.g. base = `http://example.com/foo/` combines-      with `/bar.html` to give `http://example.com/bar.html`.-    + Rewrote `htmlInBalanced`.  This version avoids an exponential-      performance problem with `<script>` tags, and it should be faster-      in general (#2730).-    + Properly handle an empty cell in a simple table (#2718).-    + Handle multiple `<meta>` tags with same name.  Put them in a list-      in the metadata so they are all preserved, rather than (as before)-      throwing out all but one..--  * Markdown reader:--    + Improved pipe table parsing (#2765).-    + Allow `+` separators in pipe table cells.  We already allowed-      them in the header, but not in the body rows, for some reason.-      This gives compatibility with org-mode tables.-    + Don't cross line boundary parsing pipe table row.-      Previously an Emph element could be parsed across the newline-      at the end of the pipe table row.-    + Use `htmlInBalanced` for `rawVerbatimBlock`, for better-      performance (#2730).-    + Fixed bug with smart quotes around tex math.--  * LaTeX reader:--    + Handle interior `$` characters in math (#2743).  For example,-      `$$\hbox{$i$}$$`.-    + `inlineCommand` now gobbles an empty `{}` after any command (#2687).-      This gives better results when people write e.g. `\TeX{}` in Markdown.-    + Properly handle LaTeX "math" environment as inline math (#2171).--  * Textile reader: Support `>`, `<`, `=`, `<>` text alignment attributes.-    Closes #2674.--  * Org reader (Albert Krewinkel):--    + Prefix even empty figure names with "fig:" (#2643).  The-      convention used by pandoc for figures is to mark them by prefixing-      the name with `fig:`.  The org reader failed to do this if a figure-      had no name.-    + Refactor link-target processing (#2684).--  * ConTeXt writer: Fix whitespace at line beginning in line blocks (#2744).-    Thanks to @c-foster.--  * HTML writer: Don't include alignment attribute for default table columns.-    Previously these were given "left" alignment.  Better to leave off-    alignment attributes altogether (#2694).--  * Markdown writer: Use hyphens for YAML metadata block bottom line, for-    better compatibility with other Markdown flavors (Henrik Tramberend).--  * LaTeX writer:--    + Use image identifier to create a label and hypertarget for-      figures (Mauro Bieg).-    + Avoid double toprule in headerless table with caption (#2742).-    + Clean up options parser (Jesse Rosenthal).-    + Treat `memoir` template with `article` option as article, instead-      of treating all `memoir` templates as books.-    + Allow more flexible table alignment (Henrik Tramberend, #2665).-      New default is not to include `[c]` option (which is the default-      anyway if no positioning is specified).  Now LaTeX emplates can-      control the overall table alignment in a document by setting the-      longtable length variables `LTleft` and `LTright`.  For example,-      `\setlength\LTleft\parindent\setlength\LTright\fill`-      will create left-aligned tables that respect paragraph indentation.--  * Docx writer: Handle image alt text (#2754, Mauro Bieg).--  * Org writer - pass through RawInline with format "org".--  * DokuWiki writer: use `$$` for display math.--  * Custom writer: Pass attributes parameter to CaptionedImage (#2697).--  * Make protocol-relative URIs work again (#2737).--  * make_osx_package.sh:  Use env variable for developer id certs.--  * Raise `tagsoup` lower bound to 0.13.7 to fix entity-related-    problems (#2734).--  * Allow `zip-archive` 0.3.--  * Allow `aeson` 0.11.--pandoc (1.16.0.2)--  * Depend on deepseq rather than deepseq-generics (fpco/stackage#1096).--  * Fixed regression in latex smart quote parsing (#2645).-    In cases where a match was not found for a quote, everything-    from the open quote to the end of the paragraph was being dropped.--pandoc (1.16.0.1)--  * Fixed regression with `--latex-engine` (#2618).  In 1.16 `--latex-engine`-    raises an error if a full path is given.--  * Org reader: Fix function dropping subtrees tagged `:noexport`-    (Albert Krewinkel, #2628):--  * Markdown reader: renormalize table column widths if they exceed 100%-    (#2626).--  * Textile reader:  don't allow block HTML tags in inline contexts.-    The reader previously did allow this, following redcloth,-    which happily parses--        Html blocks can be <div>inlined</div> as well.--    as--        <p>Html blocks can be <div>inlined</div> as well.</p>--    This is invalid HTML.  The above sample now produces;--        <p>Html blocks can be</p>-        <div>-        <p>inlined</p>-        </div>-        <p>as well.</p>--  * Improved default template lookup for custom lua scripts (#2625).-    Previously, if you tried to do `pandoc -s -t /path/to/lua/script.lua`,-    pandoc would look for the template in-    `~/.pandoc/templates/default./path/to/lua/script.lua`.-    With this change it will look in the more reasonable-    `~/.pandoc/templates/default.script.lua`.  This makes it possible to-    store default templates for custom writers.--  * RST, Markdown writers: Fixed rendering of grid tables with blank rows-    (#2615).--  * LaTeX writer: restore old treatment of Span (#2624).  A Span is-    now rendered with surrounding `{}`, as it was before 1.16.--  * Entity handling fixes: improved handling of entities like-    `&lang;` that require a trailing semicolon.  Allow uppercase-    `x` in numerical hexidecimal character references, working-    around a tagsoup bug.--  * `stack.yaml` - use lts-4.0, but with older aeson to avoid excessive-    memory use on compile.  With aeson 0.10 we were getting an out of-    memory error on a 2GB Ubuntu 64-bit VM.--  * Improved deb package creation script. Made `DPKGVER` work.-    Renamed `COMMIT` to `TREE`.  You should now be able to do-    `TREE=1.16.0.1 DPKGVER=2 make deb`.---pandoc (1.16)--  * Added `Attr` field to `Link` and `Image` (Mauro Bieg, #261, API change).--    + Added syntax for link and image attributes to pandoc's Markdown.-    + Updated readers and writers to use link and image attributes-      when appropriate.-    + Support image attributes in Docx, Textile, RST readers.--  * Renamed link attribute extensions.  The old `link_attributes` is-    now `mmd_link_attributes`, and `link_attributes` now enables the-    new pandoc-style link and image attributes (API change).-    Note: this change could break some existing workflows.--  * Implemented `SoftBreak` and new `--wrap` option (#1701, API change).-    Added threefold wrapping option.--    + Command line option: deprecated `--no-wrap`, added-      `--wrap=[auto|none|preserve]`-    + Added `WrapOption`, exported from `Text.Pandoc.Options`-    + Changed type of `writerWrapText` in `WriterOptions` from-      `Bool` to `WrapOption`.-    + Modified `Text.Pandoc.Shared` functions to allow `SoftBreak`.-    + Supported `SoftBreak` in readers and writers.--  * Text.Pandoc.Options:  Added `writerDpi` to `WriterOptions` (API-    change, Mauro Bieg).--  * Added `--dpi` command-line option (Mauro Bieg).--  * Rationalized behavior of `--no-tex-ligatures` and `--smart` (#2541).-    This change makes `--no-tex-ligatures` affect the LaTeX reader-    as well as the LaTeX and ConTeXt writers.  If it is used,-    the LaTeX reader will parse characters `` ` ``, `'`, and `-`-    literally, rather than parsing ligatures for quotation marks-    and dashes.  And the LaTeX writer will print unicode quotation-    mark and dash characters literally, rather than converting-    them to the standard ASCII ligatures.  Note that `--smart` has-    no effect on the LaTeX reader.  `--smart` is still the default-    for all input formats when LaTeX or ConTeXt is the output format,-    *unless* `--no-tex-ligatures` is used.--    Some examples to illustrate the logic:--    ```-    % echo "'hi'" | pandoc -t latex-    `hi'-    % echo "'hi'" | pandoc -t latex --no-tex-ligatures-    'hi'-    % echo "'hi'" | pandoc -t latex --no-tex-ligatures --smart-    ‘hi’-    % echo "'hi'" | pandoc -f latex --no-tex-ligatures-    <p>'hi'</p>-    % echo "'hi'" | pandoc -f latex-    <p>’hi’</p>-    ```--  * Removed deprecated options `--offline` and `--html5`.--  * Fixed language code for Czech (`cs` not `cz`) (#2597).--  * Implemented `east_asian_line_breaks` extension (#2586).-    In `Text.Pandoc.Options`, added `Ext_east_asian_line_breaks` constructor-    to `Extension` (API change).  This extension is like-    `ignore_line_breaks`, but smarter -- it only ignores line breaks-    between two East Asian wide characters.  This makes it better suited-    for writing with a mix of East Asian and non-East Asian scripts.--  * Added support for PDF creation via `wkhtmltopdf`.-    To use this: `pandoc -t html5 -o result.pdf` (and add `--mathjax`-    if you have math.) Margins can be set using the variables-    `margin-top`, `margin-bottom`, `margin-left`, `margin-right`.-    Other styling can be done through CSS.--  * Fixed cite key parsing regression (jgm/pandoc-citeproc#201).-    We were capturing final colons as in `[@foo: bar]`; the citation id-    was being parsed as `@foo:`.--  * ICML writer:--    + Fixed image syntax for local files (#2589).-    + Changed type of `writeICML` (Mauro Bieg).-      API change:  It is now `WriterOptions -> Pandoc -> IO String`.-      Also handle new image attributes.-    + Intersperse line breaks instead of appending them to-      every `ParagraphStyleRange` (Mauro Bieg, #2501).-    + Add `Cite` style to citations (Mauro Bieg).-    + Added figure handling (#2590, Mauro Bieg).-    + Better handling of math.  Instead of just printing the raw tex,-      we now try to fake it with unicode characters.--  * HTML writer: Include `example` class for example lists (#2524).--  * ODT/OpenDocument writer: improved image attributes (Mauro Bieg).--    + Support for percentage widths/heights-    + Use `Attr` instead of title to get dimensions from ODT walker-      to `writeOpenDocument`.--  * AsciiDoc writer:--    + Support anchors in spans and divs with id elements-      (jgm/pandoc-citeproc#143).-    + Fixed code blocks (#1861).--  * Haddock writer:  omit formatting inside links, which isn't supported-    by Haddock (#2515).--  * MediaWiki writer:  Fixed spacing issues in table cells.--    + Start cell on new line unless it's a single Para or Plain-      (#2606).-    + For single Para or Plain, insert a space after the `|` to-      avoid problems when the text begins with a character like-      `-` (#2604).--  * Beamer writer: mark frame as fragile when it contains verbatim (#1613).--  * LaTeX writer:--    + Add support for GAP highlighting using listings (Raniere Silva).-    + Consider `header-includes` content as well as templates-      when determining whether to use csquotes (Andreas Lööw).-    + Create defaults for geometry using `margin-left` etc.-      If `geometry` has no value, but `margin-left`, `margin-right`,-      `margin-top`, and/or `-margin-bottom` are given, a default value-      for `geometry` is created from these.  Note that these variables-      already affect PDF production via HTML5 with `wkhtmltopdf`.--  * ConTeXt writer: set default layout based on `margin-left`, etc.-    This sets up `\setuplayout` based on the variables `margin-left`,-    `margin-right`, `margin-bottom`, and `margin-top`, if no layout-    is given.--  * Docx writer:  better handling of PDF images.  Previously we tried-    to get the image size from the image even if an explicit size was-    specified.  Since we still can't get image size for PDFs, this made-    it impossible to use PDF images in docx.  Now we don't try to get-    the image size when a size is already explicitly specified.--  * Markdown writer:  use raw HTML for link/image attributes when-    the `link_attributes` extension is unset and `raw_html` is set (#2554).--  * MediaWiki reader: interpret markup inside `<tt>`, `<code>` (#2607).--  * LaTeX reader:--    + Improved smart quote parsing (#2555). This fixes redering of-      unmatched quotes.-    + Use curly quotes for unmatched ` (#2555).-    + Allow blank space between braced arguments of commands (#2592).--  * Markdown reader:--    + Improved pipe table relative widths.  Previously pipe table-      columns got relative widths (based on the header underscore lines)-      when the source of one of the rows was greater in width than the-      column width.  This gave bad results in some cases where much of-      the width of the row was due to nonprinting material (e.g. link-      URLs).  Now pandoc only looks at printable width (the width of a-      plain string version of the source), which should give better results.-      Thanks to John Muccigrosso for bringing up the issue.-    + Fixed parsing bug with macros.  Previously macro definitions in-      indented code blocks were being parsed as macro definitions, not code.--  * Textile reader:  skip over attribute in image source (#2515).-    We don't have a place yet for styles or sizes on images, but-    we can skip the attributes rather than incorrectly taking them-    to be part of the filename.--  * Docx reader: Handle dummy list items (Jesse Rosenthal).-    These come up when people create a list item and then delete the-    bullet. It doesn't refer to any real list item, and we used to ignore-    it.--  * CommonMark reader/writer rewritten to use latest `cmark`.--  * Fixed Emoji character definitions (#2523).  There were many bugs in the-    definitions.--  * `Text.Pandoc.CSS`:--    + Added `pickStylesToKVs` function to extract multiple properties at-      once (API change, Mauro Bieg).-    + Parse CSS that doesn't contain the optional semicolon (Mauro Bieg).--  * `trypandoc`: sort drop-down lists.--  * Beamer template:--    + Made `\euro` conditional on presence of character.-      for xelatex and lualatex, as it is for pdflatex (Andrew Dunning).-    + Moved `header-includes` before setting of title (Thomas Hodgson),-      to match the LaTeX template (jgm/pandoc-templates#168).-    + Added `section-titles` variable (defaults to true)-      to enable/suppress section title pages in beamer-      slide shows (Thomas Hodgson).-    + Moved beamer themes after fonts, so that themes can-      change fonts.  (Previously the fonts set were being-      clobbered by lmodern.sty.) (Thomas Hodgson).--  * Beamer/LaTeX template changes (Thomas Hodgson):-    + Added `thanks` variable-    + Use `parskip.sty` when `indent` isn't set (fall back to using-      `setlength` as before if `parskip.sty` isn't available).-    + Use `biblio-style` with biblatex.-    + Added `biblatexoptions` variable.--  * LaTeX template changes:--    + Added `paper` after `$papersize$` variable in latex template.-      Thus you can say `papersize: a4` and the latex will contain-      `a4paper`.  This change may break some existing workflows; if-      you currently specify `a4paper`, you'll get `a4paperpaper` which-      is meaningless.  However, the change seems worth it, as it will-      make the `papersize` variable work uniformly across ConTeXt, LaTeX,-      and html->pdf via wkhtmltopdf.-    + Only pass options to color package if `colorlinks` is set-      (Andrew Dunning).-    + Make definition of `\euro` conditional in xelatex/lualatex,-      as it is already for pdflatex (Andrew Dunning).-    + Removed setting of `subject` in PDF metadata.-      This used to be set to the subtitle, but really the subtitle-      need not give the subject.  Also, `subtitle` can contain formatting,-      so we'd need, at least, a plain text version for this.-    + Moved `header-includes` before setting of `\title`, `\author`,-      etc.  This allows these macros to be redefined.-    + Use `\subtitle` command for `subtitle`, instead of tacking it-      on to the title as before.  We give a no-op fallback definition if it-      is not defined.  This change should produce much better results-      in classes that support `\subtitle`.  With the default article-      class, which does not define `\subtitle`, subtitles will no-      longer be printed unless the user defines `\subtitle` and-      redefines `\maketitle`.-    + Moved redefinitions of `\paragraph` and `\subparagraph` to-      before header-includes.--  * Context template:--    + Use `simplefonts` for font loading (Paolo Rodríguez).  This is-      needed for things to work on ConTeXt stable from TeXLive 2015.-    + Revert use of `\setuphead` in title block (Andrew Dunning,-      Rik Kabel).--  * Update LaTeX/ConTeXt link colour usage (Andrew Dunning).--  * Fixed man template so disabling hyphenation actually works.-    The command needs to come after .TH.--  * Added 'navigation' variable to beamer template (#2543).-    Valid values are `empty` (the default), `horizontal`, `vertical`,-    and `frame`.  Note that this changes the default behavior from-    `horizontal` to `empty`.  Closes #2543.--  * Added `toc` to HTML slide format templates (Andrew Dunning),-    so that `--toc` creates a contents slide.--  * Added `stack.full.yaml` to build `pandoc-citeproc` as well.--  * Allow pipe tables with no body rows (#2556).-    Previously this raised a runtime error.--  * Shared: Improved `fetchItem` so that `C:/Blah/Blah.jpg` isn't treated-    as URL.  The Haskell URI parsing routines will accept "C:" as a-    scheme, so we rule that out manually.  This helps with-    `--self-contained` and absolute Windows paths.--  * Define a `meta-json` variable for all writers (#2019).  This contains-    a JSON version of all the metadata, in the format selected for the-    writer.  So, for example, to get just the YAML metadata, you can run-    pandoc with the following custom template: `$meta-json$`.  The intent-    is to make it easier for static site generators and other tools to get-    at the metadata.--  * Document limitations of --self-contained (#2553).--  * Improved Citations section of README (#2551).  Added information-    about `link-citations` and a link to the pandoc-citeproc man page.--  * `ImageSize`: use `safeRead` instead of `readMaybe`, which isn't-    in base < 4.6.--  * Allow .adoc file extension for AsciiDoc (Andrew Dunning).--  * Improved implicit pandoc-citeproc inclusion.-    The filter pandoc-citeproc is automatically used when-    `--bibliography` is specified on the command line, unless-    `--natbib` or `--biblatex` is used.  However, previously this-    only worked if `--bibliography` was spelled out in full, and not-    if `--biblio` was used.--  * reveal.js: Interpret pauses correctly for all headers (#2530).-    Previously, when using headers below the slide level, pauses are left-    uninterpreted into pauses. In my opinion, unexpected behavior but-    intentional looking at the code.--  * Remove redundant `center` variable for reveal.js (Andrew Dunning).--  * Parsing: Add `extractIdClass`, modified type of `KeyTable` (Mauro-    Bieg, API change).--  * ImageSize:  Added functions for converting between image dimensions-    (Mauro Bieg).--  * Use lts-3.18 in stack.yaml.  This avoids Windows build-    issues with the HTTP library.--  * Bump version bounds for dependencies.--pandoc (1.15.2.1)--  * Added two missing test files, and `stack.yaml`, to-    `extra-source-files` so they're included in the source tarball.--  * reveal.js template: Fixed parallaxBackground options.-    `parallaxBackgroundHorizontal` and `parallaxBackgroundVertical`-    need integer values, not strings.  (Vaughn Iverson)--pandoc (1.15.2)--  * `pandoc my.md -t context -o my.pdf` will now create a PDF using-    ConTeXt rather than LaTeX (#2463).--  * Fixed omitted `url(...)` in CSS data-uri with `--self-contained` (#2489).--  * Added `emoji` Markdown extension, enabled by default in `markdown_github`-    (#2523).  Added `Ext_emoji` to `Extension` in `Text.Pandoc.Options`-    (API change).--  * `Text.Pandoc.Readers.HTML.parseTags`: Fixed over-eager raw HTML inline-    parsing (#2469).  Tightened up the inline HTML parser so it disallows-    TagWarnings.--  * Derive `Generic` instances for the types in `Text.Pandoc.Options`.--  * Org reader:--    + Fix paragraph/list interaction (Albert Krewinkel, #2464).-      Paragraphs can be followed by lists, even if there is no blank line-      between the two blocks.  However, this should only be true if the-      paragraph is not within a list, were the preceding block should be-      parsed as a plain instead of paragraph (to allow for compact lists).-      Thanks to @rgaiacs for bringing this up.-    + Allow toggling header args (Albert Krewinkel, #2269).-      Org-mode allows to skip the argument of a code block header argument if-      it's toggling a value.  Argument-less headers are now recognized,-      avoiding weird parsing errors.-    + Fix markup parsing in headers (Albert Krewinkel, #2504).-      Markup as the very first item in a header wasn't recognized.  This was-      caused by an incorrect parser state: positions at which inline markup-      can start need to be marked explicitly by changing the parser state.-      This wasn't done for headers.  The proper function to update the state-      is now called at the beginning of the header parser, fixing this issue.-    + Fix emphasis rules for smart parsing (Albert Krewinkel, #2513).-      Smart quotes, ellipses, and dashes should behave like normal quotes,-      single dashes, and dots with respect to text markup parsing.-    + Require whitespace around definition list markers (#2518).-      This rule was not checked before, resulting in bugs with footnotes-      and some link types.--  * Markdown reader:--    + Pipe tables with long lines now get relative cell widths (#2471).-      If a pipe table contains a line longer than the column width (as set by-      `--columns` or 80 by default), relative widths are computed based on the-      widths of the separator lines relative to the column width.  This should-      solve persistent problems with long pipe tables in LaTeX/PDF output, and-      give more flexibility for determining relative column widths in other-      formats, too.  For narrower pipe tables, column widths of 0 are used,-      telling pandoc not to specify widths explicitly in output formats that-      permit this.-    + Improved parser for `mmd_title_block`.  We now allow blank metadata-      fields.  These were explicitly disallowed before.-    + Citation keys can now contain `://`, so URLs and DOIs can be used-      as citation keys (jgm/pandoc-citeproc#166).--  * Beamer template:  fix incompatibility of section slides with natbib.-    Natbib (and presumably biblatex) bibliography commands create-    their own section.  Since these are in frame environments,-    we have an incompatibility with the `\AtBeginSection` macro-    which creates a special frame when a new section occurs.-    (We can't have a frame inside another frame.) This change disables-    `\AtBeginSection` inside bibliography slides.  Thinks to Yihui Xie for-    bringing the problem to my attention.  This supersedes #145.  See-    discussion there.--  * Textile reader:  don't do smart punctuation unless explicitly asked-    (#2480).  Note that although smart punctuation is part of the textile-    spec, it's not always wanted when converting from textile-    to, say, Markdown.  So it seems better to make this an option.--  * LaTeX reader: Handle `comment` environment (Arata Mizuki).-    The `comment` environment is handled in a similar way to the-    `verbatim` environment, except that its content is discarded.--  * Docx reader:  Follow relationships correctly in foot/endnotes (#2258,-    Jesse Rosenthal).  This fixes a problem with links in notes.--  * LaTeX and ConTeXt writers: support `lang` attribute on divs and spans-    (Mauro Bieg).  For LaTeX, also collect `lang` and `dir` attributes on-    spans and divs to set the `lang`, `otherlangs` and `dir` variables if-    they aren’t set already.  See #895.--  * LaTeX writer:--    + Use proper command for `\textarabic` (Mauro Bieg).-    + Added `de-CH-1901`, fixed `el-polyton` in `toPloyglossia` (Nick Bart).-    + Use `\hypertarget` and `\hyperlink` for links.  This works correctly-      to link to Div or Span elements.  We now don't bother defining `\label`-      for Div or Span elements.  Closes jgm/pandoc-citeproc#174.-    + Avoid footnotes in list of figures (#1506).-    + Properly handle footnotes in captions (#1506).-    + Add `\protect` to `\hyperlink` (#2490).  Thanks to Hadrien Mary.-    + Set `colorlinks` if `linkcolor`, `urlcolor`, `citecolor`, or-      `toccolor` is set (#2508).--  * Textile writer: support start number in ordered lists (#2465).--  * OpenDocument writer:  Allow customization of opendocument-    automatic styles.  Automatic styles can now be inserted in the-    template, which now provides the enclosing `<office:automatic-styles>`-    tags (#2520).--  * Docx writer:  insert space between footnote reference and note (#2527).-    This matches Word's default behavior.--  * EPUB writer:  don't download linked media when `data-external` attribute-    set (#2473).  By default pandoc downloads all linked media and includes it-    in the EPUB container.  This can be disabled by setting `data-external` on-    the tags linking to media that should not be downloaded.  Example:--        <audio controls="1">-          <source src="http://example.com/music/toccata.mp3"-                  data-external="1" type="audio/mpeg">-          </source>-        </audio>--  * HTML writer:  use width on whole table if col widths sum to < 100%.-    Otherwise some browsers display the table with the columns-    separated far apart.--  * AsciiDoc template:  Fix `author` and `date`; add `keywords`,-    `abstract` (Andrew Dunning).--  * HTML-based templates (Andrew Dunning):--    + Use en dash instead of hyphen between title prefix and title.-    + Add `keywords` to metadata.-    + Add `lang`, `dir`, `quotes` where missing.-    + Always make author and date display conditional.-    + Updated dzslides template from source.--  * Man template: make "generated by" comment conditional.--  * LaTeX, Beamer templates:--    + Add `babel-otherlangs` for language divs/spans; `babel-newcommands`,-      filled by commands that make babel understand the polyglossia-style-      language directives (Mauro Bieg, #137).-    + Improved formatting of conditionals; `$for$` is always provided to allow-      multiple options (Andrew Dunning, #141).-    + Use `Ligatures=TeX` rather than `Mapping=tex-text` with `fontspec`-      to improve support for LuaTeX (Andrew Dunning, #135).-    + Revise `hyperref` usage (Andrew Dunning, #139, #141):-        - use same options for all LaTeX engines;-        - add `subtitle` and `keywords` to PDF metadata;-        - do not override `hyperref` link coloring without user input, effectively making-          the `hidelinks` option the default (removed as a separate variable);-        - link colors can be enabled (using a slightly darker version of the old-          defaults) using a new `colorlinks` variable, automatically used by-          the LaTeX writer when custom colors are specified;-        - `pdfborder={0 0 0}` is automatically set by `hyperref` with-          `colorlinks`, and is only applied if `colorlinks` is disabled.--  * ConTeXt template (Andrew Dunning):--    + New variables for controlling styles: `linkstyle`, `linkcolor`,-      `linkcontrastcolor`, `layout`, `pagenumbering`, `whitespace`, `indenting`,-      `interlinespace`, `headertext`, `footertext`, `mainfont`, `sansfont`,-      `monofont`, `mathfont`, `fontsize`.-    + Default template no longer supports MkII.-    + Improve writing of title block (suppressing numbering of first page).-    + Add `title` `subtitle`, `author`, `date`, `keywords` to PDF metadata.-    + Support `subtitle`, `abstract`.-    + Support list of figures (`lof`), list of tables (`lot`).-    + Disable link styling by default.-    + Define styles for all section types.-    + Enable microtype.-    + Improved formatting of conditionals.--  * Beamer template:  added code to prevent slide breaks inside paragraphs-    (#2422, thanks to Nick Bart).  This will matter, in practice, only when-    `allowframebreaks` is used.  It is especially helpful for bibliography-    slides.--  * OpenDocument template:  Add `<office:automatic-styles>` tag around-    automatic styles.  The writer now longer provides this (see #2520).--  * Restored Text.Pandoc.Compat.Monoid.--  * Do not export (<>) from custom Prelude.  The Prelude now matches-    base 4.8 Prelude's API.--  * Don't use custom prelude with ghc 7.10.  Use the custom prelude-    only for earlier versions.  This change makes `stack ghci` and-    `cabal repl` work (#2503), at least with ghc 7.10.--  * Changed § to % in operators from Odt.Arrows.Utils (#2457).-    This prevents problems building haddocks with "C" locale.--  * Change default for old-locale flag to False.--  * Use stack in deb, osx, and Windows package generators.--  * Added Vagrantfile for building deb in vm.-    This should help in automating binary package creation.  'make package'-    will make the package.  'make package COMMIT=blah' will make the package-    from commit blah.--  * README:--    + Consistent capitalization for pandoc and Markdown.-    + Fixed `auto_identifiers` examples (Benoit Schweblin).-    + Improved documentation of template variables (Andrew Dunning).--pandoc (1.15.1.1)--  * `Text.Pandoc.Data`:  store paths in dataFiles using posix separators.-    This way we have uniform separators, whether on Windows or Linux.-    This should solve a problem where on some Windows versions-    the data files weren't being found (#2459).--pandoc (1.15.1)--  * `pandocVersion` is now defined in `Text.Pandoc.Shared`-    and reexported from `Text.Pandoc` (Alex Vong).  This allows-    writers to access it.  (Alex Vong) (API change)--  * For `markdown_mmd`, add: `implicit_figures`, `superscripts`,-    `subscripts` (#2401).--  * Added `odt` as input format (Martin Linnemann).  Added new module-    `Text.Pandoc.Reader.ODT` (API change). Fully implemented features:-    Paragraphs, Headers, Basic styling, Unordered lists, Ordered lists,-    External Links, Internal Links, Footnotes, Endnotes, Blockquotes.-    Partly implemented features: Citations, Tables.--  * Markdown Reader:--    + Add basic tests for each header style (Ophir Lifshitz).-    + Add implicit header ref tests for headers with spaces (Ophir Lifshitz).-    + Skip spaces in headers (Ophir Lifshitz).-    + Handle 'id' and 'class' in parsing key/value attributes (#2396).-      `# Header {id="myid" class="foo bar"}`-      is now equivalent to `# Header {#myid .foo .bar}`.-    + Use '=' instead of '#' for atx-style headers in markdown+lhs.-      (Kristof Bastiaensen)-    + Pipe tables: allow indented columns.  Previously the left-hand column-      could not start with 4 or more spaces indent.  This was inconvenient-      for right-aligned left columns.  Note that the first (header column)-      must still have 3 or fewer spaces indentation, or the table will be-      treated as an indented code  block.-    + Fix regression:  allow HTML comments containing `--`.-      Technically this isn't allowed in an HTML comment, but-      we've always allowed it, and so do most other implementations.-      It is handy if e.g. you want to put command line arguments-      in HTML comments.--  * LaTeX reader:--    + Don't eat excess whitespace after macros with only optional-      arguments (#2446).-    + Support longtable (#2411).-    + Implement `\Cite` (#2335).-    + Support abstract environment.  The abstract populates an-      `abstract` metadata field.-    + Properly handle booktabs lines.  Lines aren't part of the-      pandoc table model, so we just ignore them (#2307).--  * HTML reader:--    + Handle type attribute on ol, e.g. `<ol type="i">` (#2313).-    + Updated for new automatic header attributes.-    + Add auto identifiers if not present on headers.  This makes-      TOC linking work properly.-    + Detect `font-variant` with `pickStyleAttrProps` (Ophir Lifshitz).-    + Test `<ol>` type, class, and inline list-style(-type) CSS-      (Ophir Lifshitz).-    + Better handling of "section" elements (#2438).  Previously-      `<section>` tags were just parsed as raw HTML blocks.  With-      this change, section elements are parsed as Div elements with-      the class "section".--  * MediaWiki reader:  handle unquoted table attributes (#2355).--  * DocBook reader:--    + Added proper support for DocBook `xref` elements (Frerich Raabe).-      Added `dbContent` field to reader state, so we can lookup-      cross refs.-    + Handle `informalexample` (#2319).--  * Docx Reader:--    + Create special punctuation test (Ophir Lifshitz).-    + Parse soft, no-break hyphen elements (Ophir Lifshitz).-    + Updated headers test (Ophir Lifshitz). Replaced `styles.xml`-      in `headers.docx` with pandoc's current `styles.xml`, which-      contains styles for Heading 1 through 6. Added Heading 4-      through 7 to the test document. Note that Heading 7 is not-      parsed as a Heading because there is no Heading 7 style.--  * RST reader:  better handling of indirect roles.-    Previously the parser failed on this kind of case--        .. role:: indirect(code)--        .. role:: py(indirect)-           :language: python--        :py:`hi`--    Now it correctly recognizes `:py:` as a code role.--  * Org reader:--    + Add auto identifiers if not present on headers-      (#2354, Juliusz Gonera).-    + Allow verse blocks to contain empty lines (#2402,-      Albert Krewinkel).--  * EPUB reader:  stop mangling external URLs (#2284).--  * RST writer:--    + Don't insert `\ ` when complex expression in matched pairs.-      E.g. `` [:sup:`3`] `` is okay; you don't need `` [:sup:`3`\ ] ``.-    + Ensure that `\ ` is inserted when needed before Cite and Span-      elements that begin with a "complex" element (jgm/pandoc-citeproc#157).-    + Normalize headers only in "standalone" mode (#2394).--  * Haddock writer: escape `*` and `^` (G. Bataille).--  * Markdown writer:--    + In TOC, add links to headers (#829).-    + Use unicode super/subscripts for digits in plain output-      (when the `superscripts` and `subscripts` extensions are-      not enabled).--  * Docx writer:--    + Moved invalid character stripping to `formattedString`.-      This avoids an inefficient generic traversal (#2356).-    + Use user data directory for `reference.docx` archive.-      This allows the test suite to work without installing pandoc first.-      It also brings the docx writer in line with the odt writer.-    + Tests:  docx writer tests now use `../data` for data directory.-      This allows tests to be run without installing first.-    + Tests: Use real jpg (not empty) for docx tests to avoid warning.--  * LaTeX writer:--    + Fixed detection of 'chapters' from template.-      If a documentclass isn't specified in metadata, but the-      template has a hardwired bookish documentclass, act as if-      `--chapters` was used.  This was the default in earlier-      versions, but it has been broken for a little while.-    + Correctly recognize book documentclass in metadata (#2395).-    + Set language-related variables automatically, depending-      on the value of the `lang` field, which is now always-      assumed to be in BCP47 format (Mauro Bieg, #1614, #2437).-    + Add `\protect` to `\hyperdef` in inline context.  This way we-      don't get an error when this is used as a moveable argument (#2136).-    + Support all frame attributes in Beamer.-    + Percent-encode more special characters in URLs (#1640, #2377).-      The special characters are '<','>','|','"','{','}','[',']','^', '`'.--  * HTML writer:--    + Update KaTeX JS and CSS versions (Emily Eisenberg).-    + For dzslides, add `role="note"` for speaker notes (#1693).-    + Percent-encode more special characters in URLs (#1640, #2377).-      The special characters are '<','>','|','"','{','}','[',']','^', '`'.-    + Render Div with class `section` as `<section>` in HTML5.--  * EPUB writer:--    + In TOC, replace literal `<br/>` with space (#2105).-    + With `--webtex`, include image file rather than `data:` URI (#2363).--  * Native writer: format Div properly, with blocks separated.--  * Support bidirectional text output with XeLaTeX, ConTeXt and HTML-    (#2191, Mauro Bieg).--  * Reference Docx:--    + Add missing Header 6 style (steel blue) (Ophir Lifshitz).-    + Correct `outlineLvl` for Header styles (Ophir Lifshitz).--  * Templates--    + Beamer:  Add `innertheme`, `outertheme` variables-      (Guilhem Bonnefille, #121). Add space after colon in figure caption.-      Integrate recent font and language updates from LaTeX template;-      allow use of `mainfont` variable for changing the slide text-      in XeTeX and LuaTeX (Andrew Dunning, #131).-    + LaTeX:  Add `mainfontoptions`, `sansfontoptions`,-      `monofontoptions`, `mathfontoptions`, `fontfamilyoptions`-      (Andrew Dunning, #122).  Support handling of bidirectional-      text (Mauro Bieg, #120). Improve reliability of superscripts/subscripts-      under XeTeX and prevent letters and numbers from appearing on a-      different baseline by removing use of the `realscripts` package-      (via `xltxtra`).  To restore use of OpenType characters for these-      features under XeTeX or LuaTeX, add `\usepackage{realscripts}` to-      `header-includes` (Andrew Dunning, #130).  Remove redundant-      reference to `xunicode` (Andrew Dunning, #130).  Add `fontenc`,-      `indent`, `subparagraph` variables (Andrew Dunning).-      Allow use of `hidelinks` variable for `hyperref` package (Hugo Roy,-      #113).  Prevent package clash with `tufte-latex` and other classes that-      include `hyperref` or `color` (Xavier Olive, #115).-    + ConTeXt:  Support handling of bidirectional text (Mauro Bieg, #120).-    + LaTeX and ConTeXt: Use more specific language variables.-      Instead of directly using `lang`, we now use `babel-lang` and-      `polyglossia-lang` and `context-lang`.  These variables are set by-      the writers to the necessary values, based on the `lang` variable-      (which now always takes a value in BCP47 format). (Mauro Bieg, #114,-      #129).-    + HTML:  Support handling of bidirectional text (Mauro Bieg, #120).-      Move HTML5 shiv after CSS and fix URL (Andrew Dunning).-      Add dir attribute in html5 (Andrew Dunning).-    + reveal.js: Add `controls`, `progress` variables (Grégoire Pineau, #127).-      Add `width`, `height` variables (Andrew Dunning).  Update template-      from 3.1 source (Andrew Dunning).  All configuration options are now-      available as variables, but are only be included if set (reveal.js-      uses defaults otherwise).-    + man: Added comment stating that the page is autogenerated by pandoc,-      giving version.  Added `adjusting` and `hyphenate` variables-      (Alex Vong, #123).--  * epub.css: added selectors for nested emphasis (Pablo Rodriguez).--  * MediaBag:  ensure that `/` is always used as path separator.--  * `sample.lua`: define `CaptionedImage`, add newline at end (#2393).--  * Added `--bash-completion` option.  This generates a bash completion-    script.  To use: `eval "$(pandoc --bash-completion)"`.--  * Text.Pandoc.Error: Define Typeable and Exception instances-    for PandocError (#2386).--  * Text.Pandoc.Parsing: `toKey`: strip off outer brackets.-    This makes keys with extra space at the beginning and end-    work:  e.g.--        [foo]: bar--        [ foo ]--    will now be a link to bar (it wasn't before).--  * Text.Pandoc: disable `auto_identifiers` for epub.-    The epub writer inserts its own auto identifiers;-    this is more complex due to splitting into "chapter" files.--  * Renamed Text.Pandoc.Compat.Locale -> Text.Pandoc.Compat.Time.-    It now reexports Data.Time.--  * Use custom Prelude to avoid compiler warnings.--    + The (non-exported) prelude is in prelude/Prelude.hs.-    + It exports Monoid and Applicative, like base 4.8 prelude,-      but works with older base versions.-    + It exports (<>) for mappend.-    + It hides 'catch' on older base versions.--  * Added a `stack.ymal` and stack install instructions to INSTALL.--  * Clarified what is "out of scope" in README and CONTRIBUTING.md.--  * Added note to CONTRIBUTING.md about ghc versions and travis.--  * Clarify docs on block quotes.  The space after `>` is optional (#2346).--  * Removed obsolete reference to default.csl (#2372).--  * List all styles in manual for `--reference-docx` (Chris Black)--  * Don't capitalize header links in man page.--  * Added section on repl to CONTRIBUTING.md.--  * README:  Added space after backslash in image example (#2329).--  * Document details of citation locator terms (Nick Bart).--  * Fixed some internal links in README (#2309).--  * Improve CSL documentation, variables documentations,-    links, and cross-references in README. (Andrew Dunning)--  * Fix build failure with `--flags=-https` (Sergei Trofimovich).--  * Use `newManager` instead of `withManager` in recent `http-client`.-    This avoids a deprecation warning.--  * Allow building with latest versions of http-types,-    HUnit, criterion, syb, aeson.--  * Updated benchmark program for new criterion API.--  * Setup.hs: rewrite so as not to use process, directory, filepath.-    Using anything outside base is dangerous, since older-    versions of ghc may link against two different versions.--  * Added appveyor (Windows continuous integration) builds.--  * New `.travis.yml`.  Autgenerated using `make_travis_yml.hs`.-    This script has been modified in a few ways, e.g. to add `GHCOPTS`.-    `make .travis.yml` regenerates it based on the tested-with-    field of the cabal file.--pandoc (1.15.0.6)--  * `--self-contained`:  Fixed overaggressive CSS minimization (#2301, 2286).-    Previously `--self-contained` wiped out all spaces in CSS,-    including semantically significant spaces.  This was a regression-    from 1.14.x.--  * Markdown reader: don't allow bare URI links or autolinks in link-    label (#2300).  Added test cases.--  * `Text.Pandoc.Parsing`, `uri`: Improved bare autolink detection (#2299).-    Previously we disallowed `-` at the end of an autolink,-    and disallowed the combination `=-`.  This commit liberalizes the-    rules for allowing punctuation in a bare URI, and adds test cases.-    One potential drawback is that you can no longer put a bare-    URI in em dashes like this:-    `this uri---http://example.com---is an example.`-    But in this respect we now match github's treatment of bare URIs.--  * HTML writer:  support speaker notes in dzslides.-    With this change `<div class="notes">` and also `<div class="notes"-    role="note">` will be output if `-t dzslides` is used. So we can-    have speaker notes in dzslides too.  Thanks to maybegeek.--  * Updated dzslides template.--  * Improved documentation of options to print system default files (#2298).-    `--print-default-data-file` and `--print-default-template`.--  * DokuWiki writer: use `$..$` for Math instead of `<math>..</math>`-    (Tiziano Müller).  MathJax seems currently to be the only maintained-    math rendering extension for DokuWiki.--  * `Text.Pandoc.Shared`: Changed `hierarchicalize` so it treats references-    div as top-level header (#2294).  This fixes a bug with `--section-divs`,-    where the final references section added by pandoc-citeproc, enclosed in-    its own div, got nested in the div for the section previous to it.--  * Allow vector 0.11.--  * Require cmark > 0.4.--pandoc (1.15.0.5)--  * HTML writer: Fixed email javascript obfuscation with `mailto:`-    URLs (#2280).  This fixes a potential security issue.  Because-    single quotes weren't being escaped in the link portion, a-    specially crafted email address could allow javascript code injection.--  * Markdown/HTML readers:  Avoid parsing partial URLs like-    `<www.pandoc.org/blah#foo>` as HTML tags (#2277).--  * RST reader:  allow inline formatting in definition list field-    names (Lars-Dominik Braun).--  * PDF:  Make sure `--latex-engine-opt` goes before the filename-    on the command line.  LaTeX needs the argument to come after-    the options (#1779).--  * CommonMark writer: fixed tags used for super/subscript.--  * ConTeXt template:  activate hanging indent for definition lists-    (Mauro Bieg).--  * Make cabal require `hsb2hs` >= 0.3.1 if `embed_data_files` specified.-    This is done by adding `hookedPrograms` in `Setup.hs`, which allows us-    to include `hsb2hs` in Build-Tools in cabal.--  * Improved Windows installer (thanks to nkalvi).--    + When per-machine installation is chosen, the system path-      is updated instead of the user's.-    + An appropriate default is used for per-machine installation-      directory.-    + Admin privileges are no longer required for a per-user install--  * Travis:  unpack sdist for build to catch packaging bugs.--  * Improved documentation on where user templates go (#2272).--pandoc (1.15.0.4)--  * Added pandoc.1 man page to the repository.  It is no longer-    built as part of the cabal build process. (This proved too-    fragile.)  pandoc.1 can be regenerated (`make man/pandoc.1`)-    when `README` is changed.--  * Copying of the man page now respects `--destdir` (#2262).--  * Improved error messages for filters.  User is now informed if-    the filter requires an interpreter that isn't found in the path,-    or if the filter returns an error status.--pandoc (1.15.0.3)--  * Ensure target directory is created when installing man page.--pandoc (1.15.0.2)--  * Added files needed for building man page to Extra-Source-Files.--pandoc (1.15.0.1)--  * Man page is now built and installed as part of the cabal build-    process. Removed Makefile target for man page.--pandoc (1.15)--  * Man page changes:--    + Removed `--man1`, `--man5` options (breaking change).-    + Removed `Text.Pandoc.ManPages` module (breaking API change).-    + Makefile target for `man/man1/pandoc.1`.  This uses pandoc to-      create the man page from README using a custom template and filters.-    + Added `man/` directory with template and filters needed to build-      man page.-    + We no longer have two man pages: `pandoc.1` and `pandoc_markdown.5`.-      Now there is just pandoc.1, which has all the content from README.-      This change was needed because of the extensive cross-references-      between parts of the README.-    + Removed old `data/pandoc.1.template` and-      `data/pandoc_markdown.5.template`.--  * OpenDocument writer: Do not add a carriage return after a hard-    line break (Michael Chladek).--  * ConTeXt writer:--    + use `\goto` for internal links.-    + Added a `%` at end for `\reference` to avoid spurious space.--  * Ignore sandbox on 'make quick'--pandoc (1.14.1)--  * Added `--man1` and `--man5` options to pandoc, allowing pandoc-    to generate its own man pages.  Man pages are no longer automatically-    generated in the build process (the process for this was too complex-    and prone to failure, #2190).  The `make-pandoc-man-pages` executable-    has been removed.  The `man/` directory has been removed, and man page-    templates have been moved to `data/`.  NOTE TO PACKAGERS:  You will no-    longer find pandoc's man pages in `man/`, but you can generate them using-    `pandoc --man1 > pandoc.1` and `pandoc --man5 > pandoc_markdown.5`.--  * Added new unexported module:  `Text.Pandoc.ManPages`.--  * `README` now acts like a data file (even though it isn't in-    `data/`).  So, for example, `pandoc --print-default-data-file README`-    will produce the README.)  This change was required for the `--man1`-    and `--man5` options, since the man pages are produced from the-    README, but it may be useful for other purposes as well.--  * Allow `reference.docx` and `reference.odt` to be used with-    `--print-default-data-file` and to shadow defaults if placed in-    the user data directory.  Note that as of 1.14, we no longer-    include these files as data files; instead, we include their-    components.  This change causes pandoc to behave as if it has-    these data files; they are constructed on demand when needed-    using `getDefaultReferenceDocx` and `getDefaultReferenceODT`.--  * Fixed regression in CSS parsing with `--self-contained` (#2224).-    Pandoc 1.14.0.x used css-text to parse the CSS, but its parser-    silently drops big sections of CSS.  This commit replaces the-    use of css-text with a small but principled CSS preprocessor,-    which removes whitespace and comments and replaces `url()` with-    base 64 data when possible.--  * Use `https://` instead of `//` for MathJax and KaTeX CDN URLs (#1920).-    This will allow math to work when pages are being viewed locally.--  * `Text.Pandoc.Options`:  Export `plainExtensions`.-    These are the extensions used in `plain` output.--  * LaTeX reader: Don't parse `_` and `^` as sub/superscript outside of-    math mode; treat them as regular inline text.  Normally these will-    cause an error in LaTeX, but there are contexts (e.g. `alltt`-    environments) where they are allowed.--  * HTML reader:  allow `<body>` to close `<head>`.--  * DocBook reader: support `mediaobject`s and `figures` (#2184, Mauro Bieg).--  * RST reader: Fix reference names with special characters-    (Lars-Dominik Braun).--  * Textile writer:  escape `+` and `-` as entities (#2225).--  * DokuWiki writer: Use proper `<code>` tags for code blocks (#2213).--  * Plain writer:  don't use symbols for super/subscript (#2237).-    Simplified code by using `plainExtensions`.--  * InDesign writer: Properly escape URLs containing more than one-    colon character (gohai).--  * Docx writer: Make sure we use dist version of `reference.docx`-    (and not the user's version) for certain settings.  Taking some-    settings values from a user-supplied reference.docx can lead to-    corruption.  This fixes a regression from the last release (#2249).--  * `Text.Pandoc.Shared`: exports `getDefaultReferenceDocx` and-    `getDefaultReferenceODT` (API change).  These functions have been-    removed from the Docx and ODT writers.--  * LaTeX template (Xavier Olive):-    + Added `CJKmainfont` and `CJKoptions` variables.-    + Allow dvipsnames (e.g. `MidnightBlue`) for colors (Xavier Olive).--  * Epub templates:  use `author.role`, not `author.type`.--  * Bump cmark version to >= 0.3.4.--  * Improved Windows installer (#2205, thanks to nkalvi).-    Users can now select a per-user or systemwide install, and can set-    the installation path.  At the end of installation, the install location-    is given.  The install location is also now given in the list of-    installed programs in Control Panel.  Cleaner WiX syntax is used for-    setting the path.--  * Added `download_stats` target to Makefile.--pandoc (1.14.0.4)--  * Added missing commonmark template.--  * Improved try pandoc (moved button, show raw command).--pandoc (1.14.0.3)--  * Allow compilation with syb 0.5.*.--  * Custom writer:  fixed some compiler warnings for ghc < 7.10.--pandoc (1.14.0.2)--  * Allow building with hslua 0.4.--pandoc (1.14.0.1)--  * Fixed problem with building of `reference.docx` and `reference.odt`-    when the `embed_data_files` flag is used.  Instead of having a phase-    of the build where `reference.docx` and `reference.odt` are created-    from their constituent data files, we now construct these archives-    from their constituents when a `docx` or `odt` is built.  The-    constituent files have been moved from `extra-source-files` to-    `data-files`, and `reference.docx` and `reference.odt` have been-    removed. Users can create their own `reference.docx` or-    `reference.odt` by using pandoc to create a simple `docx` or `odt`.-    `make-reference-files.hs` has been removed, simplifying the build-    process (#2187)--  * Don't include generated man pages in extra-source-files (#2189).--  * Bumped upper bound for aeson.--  * ConTeXt writer:  create internal link anchors for Div elements with-    identifiers.  (This is needed for linked citations to work.)--pandoc (1.14)--  [new features]--  * Added `commonmark` as input and output format.--  * Added `--verbose` flag for debugging output in PDF production (#1840,-    #1653).--  * Allow wildcards in `--epub-embed-font` arguments (#1939).--  * Added `--latex-engine-opt` option (#969, #1779, Sumit Sahrawat).--  * Added `shortcut_reference_links` extension (Konstantin Zudov, #1977).-    This is enabled by default for those markdown flavors that-    support reading shortcut reference links, namely: `markdown`,-    `markdown_strict`, `markdown_github`, `markdown_php`.-    If the extension is enabled, the reader parses shortcut reference-    links like `[foo]`, and the writer creates such links unless doing-    so would cause problems.  Users of markdown flavors that support-    shortcut reference links should not notice a difference in reading-    markdown, but the markdown pandoc produces may differ.-    If shortcut links are not desired, the extension can be disabled-    in the normal way.--  [behavior changes]--  * `--toc` is now supported for `docx` output (#458, Nikolay Yakimov).-    A "dirty" TOC is created at the beginning of document.-    It can be regenerated after the document has been opened.--  * An implicit `--filter pandoc-citeproc` is now triggered only when the-    `--bibliography` option is used, and not when the `bibliography`-    field in metadata is specified (#1849).--  * Markdown reader:--    + Reference links with `implicit_header_references` are no longer-      case-sensitive (#1606).-    + Definition lists no longer require indentation for first line (#2087).-      Previously the body of the definition (after the `:` or `~` marker)-      needed to be in column 4.  This commit relaxes that requirement,-      to better match the behavior of PHP Markdown Extra.  So, now-      this is a valid definition list:--            foo-            : bar-    + Resolve a potentially ambiguity with table captions:--            foo--              : bar--              ------              table-              -------      Is "bar" a definition, or the caption for the table?  We'll count-      it as a caption for the table.-    + Disallow headerless pipe tables (#1996), to conform to GFM and PHP-      Markdown Extra.  Note:  If you have been using headerless pipe tables,-      this change may cause existing tables to break.-    + Allow pipe tables with header but no body (#2017).-    + Allow a digit as first character of a citation key (Matthias Troffaes).-      See https://github.com/jgm/pandoc-citeproc/issues/97--  * LaTeX reader:--    + Don't limit includes to `.tex` extension (#1882).-      If the extension is not `.tex`, it must be given explicitly in-      the `\input` or `\include`.--  * Docx reader:--    + Allow numbering in the style file.  This allows inherited styles-      with numbering (lists) (Jesse Rosenthal).--  * Org reader:--    + Support smart punctuation (Craig Bosma).-    + Drop trees with a :noexport: tag (Albert Krewinkel). Trees having a-      `:noexport:` tag set are not exported.  This mirrors org-mode.-    + Put header tags into empty spans (Albert Krewinkel, #2160).-      Org mode allows headers to be tagged: `* Headline  :TAG1:TAG2`.-      Instead of being interpreted as part of the headline, the tags are now-      put into the attributes of empty spans.  Spans without textual content-      won't be visible by default, but they are detectable by filters.  They-      can also be styled using CSS when written as HTML.-    + Generalize code block result parsing (Albert Krewinkel).-      Previously, only code blocks were recognized as result blocks;-      now, any kind of block can be the result.--  * Append newline to the LineBreak in Dokuwiki, HTML, EPUB,-    LaTeX, MediaWiki, OpenDocument, Texinfo writers (#1924, Tim Lin).--  * HTML writer:--    + Add "inline" or "display" class to math spans (#1914).-      This allows inline and display math to be styled differently.-    + Include raw latex blocks if `--mathjax` specified (#1938).-    + Require highlighting-kate >= 0.5.14 (#1903).-      This ensures that all code blocks will be wrapped in a `div`-      with class `sourceCode`.  Also, the default highlighting CSS-      now adds `div.sourceCode { x-overflow: auto; }`, which means-      that code blocks (even with line numbers) will acquire a scroll-      bar on screens too small to display them (e.g. mobile phones).-      See also jgm/highlighting-kate#65.--  * LaTeX writer:--    + Use a declaration for tight lists (Jose Luis Duran, Joseph-      Harriott). Previously, pandoc hard-coded some commands to make-      tight lists in LaTeX.  Now we use a custom command instead,-      allowing the styling to be changed in a macro in the header.-      (Note:  existing templates may need to be modified to include-      the definition of this macro.  See the current template.)-    + Beamer output: if the header introducing a slide has the-      class `fragile`, add the `[fragile]` option to the slide (#2119).--  * MediaWiki writer:--    + Use `File:` instead of the deprecated `Image:` for images and-      other media files (Greg Rundlett).--  * DocBook writer:--    + Render a `Div (id,_,_) [Para _]` element as a `para` element-      with an `id` attribute.  This makes links to citations work in-      DocBook with pandoc-citeproc.--  * RST writer:--    + Normalize headings to sequential levels (Nikolay Yakimov).-      This is pretty much required by docutils.-    + Treat headings in block quotes, etc as rubrics (Nikolay Yakimov).-    + Better handling of raw latex inline (#1961).  We use-      `` :raw-latex:`...` `` and add a definition for this role to-      the template.--  * EPUB writer:--    + Remove `linear=no` from cover `itemref` (#1609).-    + Don't use `sup` element for epub footnotes (#1995).-      Instead, just use an a element with class `footnoteRef`.-      This allows more styling options, and provides better results-      in some readers (e.g. iBooks, where anything inside the a-      tag breaks popup footnotes).-    + Take TOC title from `toc-title` metadata field.--  * Docx writer:--    + Implemented `FirstParagraph` style (Jesse Rosenthal).-      Following the ODT writer, we add the `FirstParagraph` style to the-      first text paragraph following an image, blockquote, table, heading,-      or beginning of document.  This allows it to be styled differently.-      The default is for it to be the same as `Normal`.-    + Added `BodyText` style (Jesse Rosenthal).-      We apply a `BodyText` style to all unstyled paragraphs. This is,-      essentially, the same as `Normal`, except that since not everything-      inherits from `BodyText` (the metadata won't, for example, or-      the headers or footnote numbers), we can change the text in the body-      without having to make exceptions for everything.  If we do want to-      change *everything*, we can still do it through `Normal`.-    + Altered `Blockquote` style slightly (Jesse Rosenthal).-      Since `BlockQuote` derives from `BodyText`, we just want to specify-      by default that it won't indent, regardless of what `BodyText` does.-      Note that this will not produce any visible difference in the default-      configuration.-    + Take TOC title from `toc-title` metadata field (Nikolay Yakimov).-    + Added a style to figure images (Nikolay Yakimov).-      Figures with empty captions use style `Figure`.-      Figures with nonempty captions use style `Figure with Caption`, which-      is based on `Figure`, and additionally has `keepNext` set.--  * ODT writer:--    + Added figure captions (Nikolay Yakimov). The following styles are-      used for figures:-      `Figure` -- for figure with empty caption),-      `FigureWithCaption` (based on `Figure`) -- for figure with caption,-      `FigureCaption` (based on `Caption`) -- for figure captions.-      Also, `TableCaption` (based on `Caption`) is used for table captions.--  [API changes]--  * New `Text.Pandoc.Error` module with `PandocError` type-    (Matthew Pickering).--  * All readers now return `Either PandocError Pandoc` instead of `Pandoc`-    (Matthew Pickering).  This allows better handling of errors.--  * Added `Text.Pandoc.Writers.CommonMark`, exporting `writeCommonMark`.--  * Added `Text.Pandoc.Readers.CommonMark`, exporting `readCommonMark`.--  * Derive `Data` and `Typeable` instances for `MediaBag`, `Extension`,-    `ReaderOptions`, `EPUBVersion`, `CiteMethod`, `ObfuscationMethod`,-    `HTMLSlideVariant`, `TrackChanges`, `WriterOptions` (Shabbaz-    Youssefi).--  * New `Ext_shortcut_reference_links` constructor for `Extension`-    (Konstantin Zudov).--  [bug fixes]--  * Markdown reader:--    + Allow smart `'` after inline math (#1909, Nikolay Yakimov).-    + Check for tex macros after indented code (#1973).-    + Rewrote `charsInBalancedBrackets` for efficiency.-    + Make sure a closing `</div>` doesn't get included in a-      definition list item (#2127).-    + Don't parse bracketed text as citation if it might be a link,-      image, or footnote (Nikolay Yakimov).-    + Require space after key in mmd title block (#2026, Nikolay-      Yakimov).  Require space after key-value delimiter colon in mmd title-      block.-    + Require nonempty value in mmd title block (Nikolay Yakimov).-    + Disable all metadata block extensions when parsing-      metadata field values (#2026, Nikolay Yakimov).  Otherwise we-      could get a mmd title block inside YAML metadata, for example.--  * HTML reader:--    + Improve self-closing tag detection in `htmlInBalanced` (#2146).-    + Handle tables with `<th>` in body rows (#1859, Mauro Bieg).-    + Fixed `htmlTag` (#1820).  If the tag parses as a comment, we check-      to see if the input starts with `<!--`. If not, it's bogus comment-      mode and we fail `htmlTag`.-    + Handle `base` tag; if it has an `href` value, this is added to-      all relative URLs in links and images.--  * DocBook reader:--    + Look inside "info" elements for section titles (#1931).--  * Docx reader:--    + Parse images in deprecated vml format (Jesse Rosenthal).-    + Allow sub/superscript verbatims (Jesse Rosenthal).-      Verbatim usually shuts off all other run styles, but we don't want it-      to shut off sub/superscript.--  * LaTeX reader:--    + Handle `tabular*` environment (#1850).-      Note that the table width is not actually parsed or taken into-      account, but pandoc no longer chokes on it.-    + Ignore options in `\lstinline` rather than raising error (#1997).-    + Add some test cases for simple tables (Mathias Schenner).-    + Handle valign argument in tables (Mathias Schenner) (currently-      we just ignore this).-    + Allow non-empty colsep in tables (Mathias Schenner).-      The `tabular` environment allows non-empty column separators-      with the "@{...}" syntax. Previously, pandoc would fail to-      parse tables if a non-empty colsep was present. With this-      commit, these separators are still ignored, but the table gets-      parsed. A test case is included.-    + Recognize `\newpage` as a block command.-    + Allow block content in \title{} (#2001).-    + Check for block-level newcommand aliases in blockCommand (Nikolay-      Yakimov).-    + Guard against paragraph starting with inline macro (Nikolay Yakimov).-    + Properly gobble spaces after `\\` (#2007).--  * Textile reader:--    +  Handle newlines in table cells, and empty cells (#1919).--  * Org reader:--    + Allow image links with non-image targets (Hans-Peter Deifel).-      This matches behavior of Org-Mode for links like-      `[[http://example.com][https://www.haskell.org/static/img/logo.png]]`.--  * Docbook writer:--    + Don't print empty id attributes (thanks to Steve Horne).--  * HTML writer:--    + Fixed list-style-type for numbered example lists.-      Should be "decimal," not "example" (#1902).-    + Do not omit missing `alt` attribute on `img` tag (#1131,-      Konstantin Zudov).-    + Allow multiple colgroups in table (#2122).-    + In revealjs, ensure that lists in speaker notes don't add "fragment"-      classes, which can cause additional keypresses to be needed to-      advance a slide (#1394).--  * LaTeX writer:--    + Don't escape `$` in URL (#1913).-    + Don't use listings in headers (Matthew Pickering, #1963).-    + Recognize book documentclass if set in metadata (#1971).-      This sets `--chapters` implicitly if the documentclass in metadata-      is a book documentclass.  Previously this was done only if a book-      documentclass was set in a variable.-    + Add a `\label` in `\hyperdef` for Div, Span (or links don't work).-    + Make `mainlang` work when `lang` is in metadata (#2174).--  * Texinfo writer:--    + Fix wrapping by using breakable spaces (Tim Lin).--  * RST writer:--    + Fixed toc depth in RST writer.  Previously the depth was being-      rendered as a floating point number with a decimal point.--  * Markdown writer:--    + Improved escaping (#2086).  `<` should not be escaped as `\<`, for-      compatibility with original Markdown.  We now escape `<` and `>`-      with entities.  Also, we now backslash-escape square brackets.-    + Avoid introducing spurious list items through wrapping (#1946).-    + Don't emit span tags if plain or raw HTML disabled.--  * MediaWiki writer:--    + Convert spaces to underscores in wikilink URL (#1982), like MediaWiki.--  * AsciiDoc writer:--    + Insert some needed blank lines (#1860).-    + Avoid wrapping after list marker (#1858).--  * EPUB writer:--    + Properly handle internal links to IDs in spans, divs (#1884).-    + Use plain writer for metadata dc: fields (#2121).-      This gives better results when we have, e.g. multiple paragraphs.-      Note that tags aren't allowed in these fields.-    + Properly handle image links without an extension (#1855).-    + Improved chapter splitting and internal link rewriting (#1887,-      #2162, #2163).  This will ensure that internal links work and-      that the references section produced by pandoc-citeproc is-      in its own chapter.-    + Fixed handling of svg images (#2183).--  * ICML writer:--    + Better handling of raw blocks and inlines (#1951).-      Previously these were always escaped and printed verbatim.-      Now they are ignored unless the format is `icml`, in which-      case they are passed through unescaped.-    + Fixed image URIs in ICML output (gohai).--  * Custom writer:--    + Raise error if loadstring returns an error status.-    + Raise `PandocLuaException` instead of using 'error'.-      Eventually we'll change the return type so that no exception-      is involved, but at least this can be trapped.-    + Use UTF-8 aware bytestring conversion.-    + Set foreign encoding to UTF-8 (Nikolay Yakimov, #2101, #1634).-      Also factored out ByteString, since it's only used as an intermediate-      representation.--  * Docx writer:--    + Copy hyphenation settings from reference.docx (Nikolay Yakimov).-    + Filter out illegal XML characters (#1992, Matthew Pickering).-    + Added `noProof` to docx syntax highlighting `SourceCode` style.-    + Added footnotes id -1 and 0 (Jesse Rosenthal).-      Word uses, by default, footnotes with id -1 and 0 for separators. If a-      user modifies `reference.docx`, they will end up with a `settings.xml`-      file that references these footnotes, but no such footnotes in the-      document. This will produce a corruption error. Here we add these to the-      document and `settings.xml` file, so future modifications won't break-      the file.-    + Handle lists correctly inside table cells (Jesse Rosenthal).-      Previously we didn't transform lists inside table cells.-    + Set firstRow information in tables (Nikolay Yakimov).-    + Don't replace `SourceCode` style in `reference.docx` if it is defined-      there (Nikolay Yakimov, #1872).  If `--no-highlight` specified, remove-      any `SourceCode` and `*Tok` styles in `reference.docx`.-    + Attempt to match international style names (#1607, Nikolay Yakimov).-    + Set these styles as custom (Nikolay Yakimov): `Author`, `Abstract`,-      `Compact`, `Image Caption`, `Table Caption`, `Definition Term`,-      `Definition`, `First Paragraph`.-    + Rename these styles to correspond with Word `Normal.dotm` (Nikolay-      Yakimov): `Block Quote -> Block Text`, `Link -> Hyperlink`,-      `Footnote Ref -> Footnote Reference`.-    + Added `Caption` style (Nikolay Yakimov).-    + Changed these styles' inheritance (Nikolay Yakimov):-      `Image Caption <- Caption`, `Table Caption <- Caption`.-    + Remove `SourceCode` style from `reference.docx` (#1872).-      This is added automatically by the docx writer.-    + Added toc heading style to `reference.docx` (Nikolay Yakimov).--  * `Text.Pandoc.PDF`--    + Don't suggest "Try xelatex" if xelatex already in use (Mauro Bieg,-      #1832).-    + More comprehensible errors on image conversion (#2067).-      EPS can't be supported without shelling out to something like-      ImageMagick, but at least we can avoid mysterious error messages.--  * `Text.Pandoc.Shared`:--    + Make safeRead safe (#1801, Matthew Pickering).-    + Addded `mapLeft`, `hush` (Matthew Pickering).--  * `Text.Pandoc.Pretty`:--    + Remove partial function (Matthew Pickering).--  * `Text.Pandoc.SelfContained`:--    + Add `;charset=utf-8` to script mime type if missing (#1842).-    + Improved building of data URIs (#1940).  Now base64 is used except-      for `text/*` mime types.-    + `cssURLs` no longer tries to fetch fragment URLs (#2121).-    + Properly handle data URIs in css urls (#2129).-      Use a proper CSS parser (adds dependency on `text-css`).--  * `Text.Pandoc.UTF8`:--    + Better handling of bare CRs in input files (#2132).-      Previously we just stripped them out; now we convert-      other line ending styles to LF line endings.--  * `Text.Pandoc.ImageSize`:--    + Fixed some exif header parsing bugs (#1834).-    + Make imageSize return an Either, not a Maybe (#1834).-      Use `runGetOrFail` (with `binary >= 0.7`) to return `Left` on-      parse failure (rather than `error`).-    + Improved warnings when image size can't be determined.-    + Removed error landmines (Matthew Pickering).--  * Added woff2 to MIME types (Alfred Wechselberger).--  * pandoc:  When a binary input format is used, warn that file-    arguments past the first one are being ignored (Matthew Pickering).--  [template changes]--  * LaTeX template:--    + Degrade gracefully if `\paragraph` not defined.-    + Include `grffile` together with `graphicx` (#2074).-      This properly handles filenames containing spaces and dots.-    + Redefine `\paragraph`, `\subparagraph`...  to behave more-      like section headers (#1658).-    + Import hyperref before polyglossia to avoid an error with xelatex,-      "please load package hyperref before bidi package" (Nick Bart).-    + Added `toccolor` variable to control link color in toc (Kaixhin).--  * LaTeX, Beamer templates:--    + Provide `\tightlist`, which is now used by the LaTeX writer.-    + Use polyglossia in beamer (#85).-    + Use `bibliography` instead of `biblio-files`-      (#1661).  Also use `\addbibresource` instead of `\bibliography` for-      biblatex.-    + Added `setotherlanguages` in polyglossia. This uses an `otherlang`-      variable that is derived from a comma-separated list in `lang`;-      the last language is `mainlang` and the others are `otherlang`.--  * EPUB templates:--    + Use `div`, not `p`, for "rights" on title page.-    + Added header-includes, include-before, include-after (#1987).--  * OpenDocument template:--    + Use `text:p` instead of `text:h` for title.-      Using `text:h` causes problems with numbering.  Closes #2059.-      Thansk to @nkalvi for diagnosing this.--  * reveal.js template:--    + Link to non-minified css, js.  The minified versions no longer-      ship with the library.-    + Correctly include style CSS (#1949).-    + New configurable options options: `center`, `maxScale`, `slideNuber`-      (Dmitry Smirnov, pandoc-templates#89).-    + Moved custom CSS after theme.  This allows custom CSS to modify-      themes, instead of being replaced by them.-    + Allow `center` to be set to false.--  [under the hood improvements]--  * Removed pre-built `reference.docx` and `reference.odt` (Nikolay-    Yakimov).  Instead the repository now includes the component text files,-    and the zipped binaries are built from these using a helper-    program, `make-reference-files`.  This should make maintenance of-    these components easier going forward.--  * `Text.Pandoc.Parsing`:--    + Added new `<+?>` combinator (Nikolay Yakimov).-    + Added `stateHeaderKeys` to `ParserState`.--  * `make_deb.sh` fixes:--    + Detect architecture.-    + Add Installed-Size to debian package control file (#1900).-    + Use `fakeroot` to get permissions right.-    + Use `mkdir` and `cp` instead of `install`.-    + Set permissions of directories to 755.-    + Install in `/usr` rather than `/usr/local`.-    + Compress man pages.-    + Combine copyright files for `pandoc`, `pandoc-citeproc`.--  * Added `Text.Pandoc.Compat.Locale` and `old-locale` flag-    to assist with transition to `time` 1.5.--  * Updated CONTRIBUTING.md with information about issue tags (Matthew-    Pickering).--  * Updated travis installs to the new sudo-less syntax (Tim Lin).--  * Updated dependency version bounds.--  * EPUB tests:  don't use `joinPath`, which varies across platforms.-    Instead, use a forward-slash to join paths, regardless of the-    platform. This matches the way `MediaBag` now works.--  * Clarify JSON input and output in usage message (Caleb McDaniel).--  * Improved INSTALL instructions.--  * Always build man pages.  Removed make-pandoc-man-pages flag.--  * Makefile:  removed man target, now that we generate man pages by default.--  * README:--    + Fixed typos (J. Lewis Muir).-    + Added documentation on backtick_code_blocks (#2135, Nikolay Yakimov).-    + Added note on in-field markup in biblio databases (Nick Bart).-    + Fixed misleading example of raw HTML block.-    + Various minor formatting and consistency fixes for the program-      options (Andreas Lööw).-    + Made definition lists for options all "loose" for consistency.-    + Added YAML biblio format to table, and note on `pandoc-citeproc`'s-      `--bib2json` and `--bib2yaml` options (Nick Bart).-    + Removed obsolete reference to `mods2yaml` (Nick Bart).-    + Added section on syntax highlighting.-    + Documented `toccolor` variable.--pandoc (1.13.2.1)--  * Updated to build with ghc 7.10.1.--  * Bumped package upper bounds for filepath, blaze-html,-    blaze-markup.--pandoc (1.13.2)--  * TWiki Reader: add new new twiki reader (API chaneg, Alexander Sulfrian).--  * Markdown reader:--    + Better handling of paragraph in div (#1591).-      Previously text that ended a div would be parsed as Plain-      unless there was a blank line before the closing div tag.-    + Don't treat a citation as a reference link label (#1763).-    + Fix autolinks with following punctuation (#1811).-      The price of this is that autolinked bare URIs can no longer-      contain `>` characters, but this is not a big issue.-    + Fix `Ext_lists_without_preceding_blankline` bug (#1636, Artyom).-    + Allow `startnum` to work without `fancy_lists`. Formerly-      `pandoc -f markdown-fancy_lists+startnum` did not work properly.--  * RST reader (all Daniel Bergey):--    + Parse quoted literal blocks (#65).  RST quoted literal blocks are-      the same as indented literal blocks (which pandoc already supports)-      except that the quote character is preserved in each line.-    + Parse RST class directives. The class directive accepts one or more-      class names, and creates a Div value with those classes.  If the-      directive has an indented body, the body is parsed as the children of-      the Div.  If not, the first block folowing the directive is made a-      child of the Div. This differs from the behavior of rst2xml, which-      does not create a Div element.  Instead, the specified classes are-      applied to each child of the directive.  However, most Pandoc Block-      constructors to not take an Attr argument, so we can't duplicate this-      behavior.-    + Warn about skipped directives.-    + Literal role now produces Code. Code role should have "code" class.-    + Improved support for custom roles--        - Added `sourceCode` to classes for `:code:` role, and anything-          inheriting from it.-        - Add the name of the custom role to classes if the Inline-          constructor supports Attr.-        - If the custom role directive does not specify a parent role,-          inherit from the `:span:` role.--      This differs somewhat from the `rst2xml.py` behavior.  If a custom-      role inherits from another custom role, Pandoc will attach both-      roles' names as classes.  `rst2xml.py` will only use the class of-      the directly invoked role (though in the case of inheriting from a-      `:code:` role with a `:language:` defined, it will also provide the-      inherited language as a class).-    + Warn about ignored fields in role directives.--  * LaTeX reader:--    + Parse label after caption into a span instead of-     inserting an additional paragraph of bracketed text (#1747).-    + Parse math environments as inline when possible (#1821).-    + Better handling of `\noindent` and `\greektext` (#1783).-    + Handle `\texorpdfstring` more gracefully.-    + Handle `\cref` and `\sep` (Wikiwide).-    + Support `\smartcite` and `\Smartcite` from biblatex.--  * HTML reader:--    + Retain display type of MathML output (#1719, Matthew Pickering).-    + Recognise `<br>` tags inside `<pre>` blocks (#1620, Matthew Pickering).-    + Make `embed` tag either block or inline (#1756).--  * DocBook reader:--    + Handle `keycombo`, `keycap` (#1815).-    + Get string content in inner tags for literal elements (#1816).-    + Handle `menuchoice` elements better, with a `>` between (#1817).-    + Include `id` on section headers (#1818).-    + Document/test "type" as implemented (Brian O'Sullivan).-    + Add support for calloutlist and callout (Brian O'Sullivan).-      We treat a calloutlist as a bulleted list. This works well in practice.-    + Add support for `classname` (Bryan O'Sullivan).--  * Docx reader:--    + Fix window path for image lookup (Jesse Rosenthal).-      Don't use os-sensitive "combine", since we always want the paths in our-      zip-archive to use forward-slashes.-    + Single-item headers in ordered lists are headers (Jesse Rosenthal).-      When users number their headers, Word understands that as a single item-      enumerated list. We make the assumption that such a list is, in fact,-      a header.-    + Rewrite rewriteLink to work with new headers (Jesse Rosenthal).-      There could be new top-level headers after making lists, so we have to-      rewrite links after that.-    + Use polyglot header list (Jesse Rosenthal).-      We're just keeping a list of header formats that different languages-      use as their default styles. At the moment, we have English, German,-      Danish, and French. We can continue to add to this.-      This is simpler than parsing the styles file, and perhaps less-      error-prone, since there seems to be some variations, even within a-      language, of how a style file will define headers.-    + Remove header class properly in other langs (Jesse Rosenthal).-      When we encounter one of the polyglot header styles, we want to remove-      that from the par styles after we convert to a header. To do that, we-      have to keep track of the style name, and remove it appropriately.-    + Account for external link URLs with anchors. Previously, if a URL-      had an anchor, the reader would incorrectly identify it as an-      internal link and return only the anchor as URL. (Caleb McDaniel)-    + Fix for Issue #1692 (i18n styles) (Nikolay Yakimov).--  * Org reader:--    + Added state changing blanklines (Jesse Rosenthal).-      This allows us to emphasize at the beginning of a new paragraph (or, in-      general, after blank lines).-    + Fixed bug with bulleted lists:--        - a-        - b-        * c--      was being parsed as a list, even though an unindented `*`-      should make a heading.  See-      <http://orgmode.org/manual/Plain-lists.html#fn-1>.-    + Org reader: absolute, relative paths in link (#1741, Albert-      Krewinkel). The org reader was too restrictive when parsing links;-      some relative links and links to files given as absolute paths-      were not recognized correctly.-    + Org reader:  allow empty links (jgm/gitit#471, Albert Krewinkel).-      This is important for use in gitit, which uses empty links-      for wikilinks.-    + Respect indent when parsing Org bullet lists (#1650, Timothy-      Humphries).  Fixes issue with top-level bullet list parsing.-    + Fix indent issue for definition lists (Timothy Humphries,-      see #1650, #1698, #1680).-    + Parse multi-inline terms correctly in definition list (#1649,-      Matthew Pickering).-    + Fix rules for emphasis recognition (Albert Krewinkel).-      Things like `/hello,/` or `/hi'/` were falsy recognized as emphasised-      strings.  This is wrong, as `,` and `'` are forbidden border chars and-      may not occur on the inner border of emphasized text.-    + Drop COMMENT document trees (Albert Krewinkel).-      Document trees under a header starting with the word `COMMENT` are-      comment trees and should not be exported.  Those trees are dropped-      silently (#1678).-    + Properly handle links to `file:target` (Albert Krewinkel).-      Org links like `[[file:target][title]]` were not handled correctly,-      parsing the link target verbatim.  The org reader is changed such that-      the leading `file:` is dropped from the link target (see #756, #1812).-    + Parse LaTeX-style MathML entities (#1657, Albert Krewinkel).-      Org supports special symbols which can be included using LaTeX syntax,-      but are actually MathML entities.  Examples for this are-      `\nbsp` (non-breaking space), `\Aacute` (the letter A with accent acute)-      or `\copy` (the copyright sign ©)--  * EPUB reader:--    + URI handling improvements. Now we outsource most of the work to-      `fetchItem'`. Also, do not include queries in file extensions (#1671).--  * LaTeX writer:--    + Use `\texorpdfstring` for section captions when needed (Vaclav Zeman).-    + Handle consecutive linebreaks (#1733).-    + Protect graphics in headers (Jesse Rosenthal).-      Graphics in `\section`/`\subsection` etc titles need to be `\protect`ed.-    + Put `~` before header in list item text (Jesse Rosenthal).-      Because of the built-in line skip, LaTeX can't handle a section header-      as the first element in a list item.-    + Avoid using reserved characters as `\lstinline` delimiters (#1595).-    + Better handling of display math in simple tables (#1754).-      We convert display math to inline math in simple tables,-      since LaTeX can't deal with display math in simple tables.-    + Escape spaces in code (#1694, Bjorn Buckwalter).--  * MediaWiki writer:--    + Fixed links with URL = text. Previously these were rendered as bare-      words, even if the URL was not an absolute URL (#1825).--  * ICML writer:--    + Don't force all citations into footnotes.--  * RTF writer:--    + Add blankline at end of output (#1732, Matthew Pickering).--  * RST writer:--    + Ensure blank line after figure.-    + Avoid exces whitespace after last list item (#1777).-    + Wrap line blocks with spaces before continuations (#1656).-    + Fixed double-rendering of footnotes in RST tables (#1769).--  * DokuWiki writer:--    + Better handling of block quotes. This change ensures that-      multiple paragraph blockquotes are rendered using native `>`-      rather than as HTML (#1738).-    + Fix external images (#1739). Preface relative links with ":",-      absolute URIs without. (Timothy Humphries)--  * HTML writer:--    + Use protocol-relative URL for mathjax.-    + Put newline btw img and caption paragraph.-    + MathML now outputted with tex annotation (#1635, Matthew Pickering).-    + Add support for KaTeX HTML math (#1626, Matthew Pickering).-      This adds `KaTeX` to `HTMLMathMethod` (API change).-    + Don't double render when `email-obfuscation=none` (#1625, Matthew-      Pickering).-    + Make header attributes work outside top level (#1711).-      Previously they only appeared on top level header elements.-      Now they work e.g. in blockquotes.--  * ODT writer:--    + Correctly handle images without extensions (#1729).-    + Strip querystring in ODT write (#1682, Todd Sifleet).--  * FB2 writer:--    + Add newline to output.--  * EPUB writer:--    + Don't add `sourceURL` to absolute URIs (#1669).-    + Don't use unsupported `opf:title-type` for epub2.-    + Include "landmarks" section in nav document for epub3 (#1757).-    + Removed playOrder from navpoint elements in ncx file (#1760).-      These aren't required, and they make manual modification of epubs-      difficult.-    + Extract title even from structured title.-    + Don't include nav node in spine unless `--toc` was requested.-      Previously we included it in the spine with `linear="no"`, leading-      to odd results in some readers (#1593).-    + Fixed absolute URI detection (#1672).-    + Correctly resolve relative URIs (#1671).-    + Use regular page template for `nav.xhtml`, including doctype (#1759).--  * Docx writer:--    + Put docx table captions above tables (#1641, Nikolay Yakimov).-    + Get the page width from the reference docx file, and use-      it to scale images that are too large to fit (Grégory Bataille).-    + Partial fix for #1607 (Nikolay Yakimov). International heading styles-      are inferred based on `<w:name val="heading #">` fallback, if there-      are no en-US "Heading#" styles-    + Look in user data dir for archive `reference.docx`.-    + Renumber header and footer relationships to avoid collisions (Jesse-      Rosenthal). We previously took the old relationship names of the-      headers and footer in secptr. That led to collisions. We now make-      a map of availabl names in the relationships file, and then rename-     in secptr.--  * ConTeXt writer:--    + Add function toLabel (Mark Szepieniec).-      This function can be used to sanitize reference labels so that-      they do not contain any of the illegal characters \#[]",{}%()|= .-      Currently only Links have their labels sanitized, because they-      are the only Elements that use passed labels.--  * `Text.Pandoc.Shared`:--    + Moved import of `toChunks` outside of CPP conditional (#1590).-    + Fix `inDirectory` to reset to the original directory in case-      an exception occurs (Freiric Barral).--  * Templates:--    + LaTeX template: load polyglossia before bibtex (jgm/pandoc-templates#70).-      Thanks to bluebirch.-    + LaTeX template: Added `\VerbatimFootnotes` if there is verbatim in notes-      (#1616).-    + LaTeX template:  Add shorthands=off to babel options (#1648).-    + EPUB, EPUB3 templates: Added `id="cover"` to body of cover page.-      This aids styling, making it possible for example to set 0 margins-      on the title page (#1758).-    + EPUB, EPUB3 templates:  Handle structured metadata on titlepage.-      Previously we just expected 'title', 'subtitle', 'author', 'date'.-      Now we still support those, but also support the format recommended-      for epub metadata in the pandoc README:--        ----        title:-        - type: main-          text: My Book-        - type: subtitle-          text: An investigation of metadata-        creator:-        - role: author-          text: John Smith-        - role: editor-          text: Sarah Jones-        identifier:-        - scheme: DOI-          text: doi:10.234234.234/33-        publisher:  My Press-        rights:  (c) 2007 John Smith, CC BY-NC-        ...--  * `Text.Pandoc.Templates.getDefaultTemplate`:-    don't fail when called with "fb2" (#1660).--  * `Text.Pandoc.Parsing`:--    + Fixed `inlineMath` so it handles `\text{..}` containing `$`.-      For example: `$x = \text{the $n$th root of $y$}` (#1677).-    + Change `parseFromString` to fail if not all input is consumed.-      (Matthew Pickering)-    + Moved `addWarning` from Markdown reader to `Parsing`, so it can be-      used by more readers (API change, Daniel Bergey).--  * `Text.Pandoc.Pretty`:--    +  Improve performance of `realLength` (Matthew Pickering).-    +  Make CR + BLANKLINE = BLANKLINE. This fixes an extra blank line we-       were getting at the end of markdown fragments (as well as rst, org,-       etc.) (#1705).--  * `Text.Pandoc.MIME`:--    + Add mime type for WebVTT (Jason Ronallo).-    + Changed mime type for `otf` to `application/vnd.ms-opentype` (#1761).-      This is needed for epub3 validation.--  * `Text.Pandoc.MediaBag`:--    + Fix Windows specific path problems (#1597).--  * `Text.Pandoc.Shared`:--    + Make `collapseFilePath` OS-agnostic (Matthew Pickering).--  * Link the test suite using `-threaded`.-    This allows the test suite to be run using `+RTS -N`.--  * Added `network` dependency under `network-uri` flag in test section.--  * Give better error messages when someone tries to convert from-    pdf, doc, odt (#1683).--  * Added `track` to list of tags treated by `--self-contained` (#1664).--pandoc (1.13.1)--  * Fixed `--self-contained` with Windows paths (#1558).-    Previously `C:\foo.js` was being wrongly interpreted as a URI.--  * HTML reader:  improved handling of tags that can be block or inline.-    Previously a section like this would be enclosed in a paragraph,-    with RawInline for the video tags (since video is a tag that can-    be either block or inline):--        <video controls="controls">-           <source src="../videos/test.mp4" type="video/mp4" />-           <source src="../videos/test.webm" type="video/webm" />-           <p>-              The videos can not be played back on your system.<br/>-              Try viewing on Youtube (requires Internet connection):-              <a href="http://youtu.be/etE5urBps_w">Relative Velocity on-        Youtube</a>.-           </p>-        </video>--    This change will cause the video and source tags to be parsed-    as RawBlock instead, giving better output.-    The general change is this:  when we're parsing a "plain" sequence-    of inlines, we don't parse anything that COULD be a block-level tag.--  * Docx reader:--    + Be sensitive to user styles.  Note that "Hyperlink" is-      "blacklisted," as we don't want the default underline styling to be-      inherited by all links by default (Jesse Rosenthal).-    + Read single paragraph in table cell as `Plain` (Jesse Rosenthal).-      This makes to docx reader's native output fit with the way the markdown-      reader understands its markdown output.--  * Textile writer:  Extended the range of cases where native textile-    tables will be used (as opposed to raw HTML):  we now handle any-    alignment type, but only for simple tables with no captions.--  * Txt2Tags reader:--    + Header is now parsed only if standalone flag is set (Matthew Pickering).-    + The header is now parsed as meta information. The first line is the-      `title`, the second is the `author` and third line is the `date`-      (Matthew Pickering).-    + Corrected formatting of `%%mtime` macro (Matthew Pickering).-    + Fixed crash when reading from stdin.--  * EPUB writer:  Don't use page-progression-direction in EPUB2, which-    doesn't support it.  Also, if page-progression-direction not specified-    in metadata, don't include the attribute even in EPUB3; not including it-    is the same as including it with the value "default", as we did before.-    (#1550)--  * Org writer: Accept example lines with indentation at the beginning-    (Calvin Beck).--  * DokuWiki writer:--    + Refactor to use Reader monad (Matthew Pickering).-    + Avoid using raw HTML in table cells; instead, use `\\`-      instead of newlines (Jesse Rosenthal).-    + Properly handle HTML table cell alignments, and use spacing-      to make the tables look prettier (#1566).--  * Docx writer:--    + Bibliography entries get `Bibliography` style (#1559).-    + Implement change tracking (Jesse Rosenthal).--  * LaTeX writer:--    + Fixed a bug that caused a table caption to repeat across all pages-      (Jose Luis Duran).-    + Improved vertical spacing in tables and made it customizable using-      standard lengths set by booktab.  See-      <https://groups.google.com/forum/#!msg/pandoc-discuss/qMu6_5lYy0o/ZAU7lzAIKw0J>-      (Jose Luis Duran).-    + Added `\strut` to fix spacing in multiline tables (Jose Luis Duran).-    + Use `\tabularnewline` instead of `\\` in table cells (Jose Luis Duran).-    + Made horizontal rules more flexible (Jose Luis Duran).--  * Text.Pandoc.MIME:--    + Added `MimeType` (type synonym for `String`) and `getMimeTypeDef`.-      Code cleanups (Artyom Kazak).--  * Templates:--    + LaTeX template: disable microtype protrusion for typewriter font (#1549,-      thanks lemzwerg).--  * Improved OSX build procedure.--  * Added `network-uri` flag, to deal with split of `network-uri` from-    `network`.--  * Fix build dependencies for the `trypandoc` flag, so that they are-    ignored if `trypandoc` flag is set to False (Gabor Pali).--  * Updated README to remove outdated claim that `--self-contained`-    looks in the user data directory for missing files.--pandoc (1.13.0.1)--  * Docx writer:--    + Fixed regression which bungled list numbering (#1544), causing-      all lists to appear as basic ordered lists.-    + Include row width in table rows (Christoffer Ackelman, Viktor Kronvall).-      Added a property to all table rows where the sum of column widths-      is specified in pct (fraction of 5000).  This helps persuade Word-      to lay out the table with the widths we specify.--  * Fixed a bug in Windows 8 which caused pandoc not to find the-    `pandoc-citeproc` filter (#1542).--  * Docx reader: miscellaneous under-the-hood improvements (Jesse Rosenthal).-    Most significantly, the reader now uses Builder, leading to some-    performance improvements.--  * HTML reader:  Parse appropriately styled span as SmallCaps.--  * Markdown writer: don't escape `$`, `^`, `~` when `tex_math_dollars`,-    `superscript`, and `subscript` extensions, respectively, are-    deactivated (#1127).--  * Added `trypandoc` flag to build CGI executable used in the online-    demo.--  * Makefile:  Added 'quick', 'osxpkg' targets.--  * Updated README in templates to indicate templates license.-    The templates are dual-licensed, BSD3 and GPL2+.--pandoc (1.13)--  [new features]--  * Added `docx` as an input format (Jesse Rosenthal).  The docx-    reader includes conversion of native Word equations to pandoc-    LaTeX `Math` elements.  Metadata is taken from paragraphs at the-    beginning of the document with styles `Author`, `Title`, `Subtitle`,-    `Date`, and `Abstract`.--  * Added `epub` as an input format (Matthew Pickering).  The epub-    reader includes conversion of MathML to pandoc LaTeX `Math`-    elements.--  * Added `t2t` (Txt2Tags) as an input format (Matthew Pickering).-    Txt2tags is a lightweight markup format described at-    <http://txt2tags.org/>.--  * Added `dokuwiki` as an output format (Clare Macrae).--  * Added `haddock` as an output format.--  * Added `--extract-media` option to extract media contained in a zip-    container (docx or epub) while adjusting image paths to point to the-    extracted images.--  * Added a new markdown extension, `compact_definition_lists`, that-    restores the syntax for definition lists of pandoc 1.12.x, allowing-    tight definition lists with no blank space between items, and-    disallowing lazy wrapping.  (See below under behavior changes.)--  * Added an extension `epub_html_exts` for parsing HTML in EPUBs.--  * Added extensions `native_spans` and `native_divs` to activate-    parsing of material in HTML span or div tags as Pandoc Span-    inlines or Div blocks.--  * `--trace` now works with the Markdown, HTML, Haddock, EPUB,-    Textile, and MediaWiki readers.  This is an option intended-    for debugging parsing problems; ordinary users should not need-    to use it.--  [behavior changes]--  * Changed behavior of the `markdown_attribute` extension, to bring-    it in line with PHP markdown extra and multimarkdown.  Setting-    `markdown="1"` on an outer tag affects all contained tags,-    recursively, until it is reversed with `markdown="0"` (#1378).--  * Revised markdown definition list syntax (#1429).  Both the reader-    and writer are affected.  This change brings pandoc's definition list-    syntax into alignment with that used in PHP markdown extra and-    multimarkdown (with the exception that pandoc is more flexible about-    the definition markers, allowing tildes as well as colons).  Lazily-    wrapped definitions are now allowed.  Blank space is required-    between list items.  The space before a definition is used to determine-    whether it is a paragraph or a "plain" element.  **WARNING: This change-    may break existing documents!**  Either check your documents for-    definition lists without blank space between items, or use-    `markdown+compact_definition_lists` for the old behavior.--  * `.numberLines` now works in fenced code blocks even if no language-    is given (#1287, jgm/highlighting-kate#40).--  * Improvements to `--filter`:--    + Don't search PATH for a filter with an explicit path.-      This fixed a bug wherein `--filter ./caps.py` would run `caps.py` from-      the system path, even if there was a `caps.py` in the working directory.-    + Respect shebang if filter is executable (#1389).-    + Don't print misleading error message.-      Previously pandoc would say that a filter was not found,-      even in a case where the filter had a syntax error.--  * HTML reader:--    + Parse `div` and `span` elements even without `--parse-raw`,-      provided `native_divs` and `native_spans` extensions are set.-      Motivation:  these now generate native pandoc Div and Span-      elements, not raw HTML.-    + Parse EPUB-specific elements if the `epub_html_exts`-      extension is enabled.  These include `switch`, `footnote`,-      `rearnote`, `noteref`.--  * Org reader:--    + Support for inline LaTeX.  Inline LaTeX is now accepted and parsed by the-      org-mode reader.  Both math symbols (like `\tau`) and LaTeX commands (like-      `\cite{Coffee}`), can be used without any further escaping (Albert-      Krewinkel).--  * Textile reader and writer:--    + The `raw_tex` extension is no longer set by default.  You can-      enable it with `textile+raw_tex`.--  * DocBook reader:--    + Support `equation`, `informalequation`, `inlineequation` elements with-      `mml:math` content.  This is converted into LaTeX and put into a Pandoc-      Math inline.--  * Revised `plain` output, largely following the style of Project-    Gutenberg:--    + Emphasis is rendered with `_underscores_`, strong emphasis-      with ALL CAPS.-    + Headings are rendered differently, with space to set them off,-      not with setext style underlines. Level 1 headers are ALL CAPS.-    + Math is rendered using unicode when possible, but without the-      distracting emphasis markers around variables.-    + Footnotes use a regular `[n]` style.--  * Markdown writer:--    + Horizontal rules are now a line across the whole page.-    + Prettier pipe tables.  Columns are now aligned  (#1323).-    + Respect the `raw_html` extension.  `pandoc -t markdown-raw_html`-      no longer emits any raw HTML, including span and div tags-      generated by Span and Div elements.-    + Use span with style for `SmallCaps` (#1360).--  * HTML writer:--    + Autolinks now have class `uri`, and email autolinks have class-      `email`, so they can be styled.--  * Docx writer:--    + Document formatting is carried over from `reference.docx`.-      This includes margins, page size, page orientation, header,-      and footer, including images in headers and footers.-    + Include abstract (if present) with `Abstract` style (#1451).-    + Include subtitle (if present) with `Subtitle` style, rather-      than tacking it on to the title (#1451).--  * Org writer:--    + Write empty span elements with an id attribute as org anchors.-      For example `Span ("uid",[],[]) []` becomes `<<uid>>`.--  * LaTeX writer:--    + Put table captions above tables, to match the conventional-      standard.  (Previously they appeared below tables.)-    + Use `\(..\)` instead of `$..$` for inline math (#1464).-    + Use `\nolinkurl` in email autolinks.  This allows them to be styled-      using `\urlstyle{tt}`.  Thanks to Ulrike Fischer for the solution.-    + Use `\textquotesingle` for `'` in inline code.  Otherwise we get-      curly quotes in the PDF output (#1364).-    + Use `\footnote<.>{..}` for notes in beamer, so that footnotes-      do not appear before the overlays in which their markers appear-      (#1525).-    + Don't produce a `\label{..}` for a Div or Span element.  Do produce-      a `\hyperdef{..}` (#1519).--  * EPUB writer:--    + If the metadata includes `page-progression-direction` (which can be-      `ltr` or `rtl`, the `page-progression-direction` attribute will-      be set in the EPUB spine (#1455).--  * Custom lua writers:--    + Custom writers now work with `--template`.-    + Removed HTML header scaffolding from `sample.lua`.-    + Made citation information available in lua writers.--  * `--normalize` and `Text.Pandoc.Shared.normalize` now consolidate-    adjacent `RawBlock`s when possible.--  [API changes]--  * Added `Text.Pandoc.Readers.Docx`, exporting `readDocx` (Jesse Rosenthal).--  * Added `Text.Pandoc.Readers.EPUB`, exporting `readEPUB` (Matthew-    Pickering).--  * Added `Text.Pandoc.Readers.Txt2Tags`, exporting `readTxt2Tags` (Matthew-    Pickering).--  * Added `Text.Pandoc.Writers.DokuWiki`, exporting `writeDokuWiki`-    (Clare Macrae).--  * Added `Text.Pandoc.Writers.Haddock`, exporting `writeHaddock`.--  * Added `Text.Pandoc.MediaBag`, exporting `MediaBag`, `lookupMedia`,-    `insertMedia`, `mediaDirectory`, `extractMediaBag`.  The docx and epub-    readers return a pair of a `Pandoc` document and a `MediaBag` with-    the media resources they contain.  This can be extracted using-    `--extract-media`.  Writers that incorporate media (PDF, Docx,-    ODT, EPUB, RTF, or HTML formats with `--self-contained`) will look-    for resources in the `MediaBag` generated by the reader, in addition to-    the file system or web.--  * `Text.Pandoc.Readers.TexMath`: Removed deprecated `readTeXMath`.-    Renamed `readTeXMath'` to `texMathToInlines`.--  * `Text.Pandoc`: Added `Reader` data type (Matthew Pickering).-    `readers` now associates names of readers with `Reader`-     structures.  This allows inclusion of readers, like the docx-     reader, that take binary rather than textual input.--  * `Text.Pandoc.Shared`:--    + Added `capitalize` (Artyom Kazak), and replaced uses of-      `map toUpper` (which give bad results for many languages).-    + Added `collapseFilePath`, which removes intermediate `.` and-      `..` from a path (Matthew Pickering).-    + Added `fetchItem'`, which works like `fetchItem` but searches-      a `MediaBag` before looking on the net or file system.-    + Added `withTempDir`.-    + Added `removeFormatting`.-    + Added `extractSpaces` (from HTML reader) and generalized its type-      so that it can be used by the docx reader (Matthew Pickering).-    + Added `ordNub`.-    + Added `normalizeInlines`, `normalizeBlocks`.-    + `normalize` is now `Pandoc -> Pandoc` instead of-      `Data a :: a -> a`.  Some users may need to change their uses of-      `normalize` to the newly exported `normalizeInlines` or-      `normalizeBlocks`.--  * `Text.Pandoc.Options`:--    + Added `writerMediaBag` to `WriterOptions`.-    + Removed deprecated and no longer used `readerStrict` in-      `ReaderOptions`.  This is handled by `readerExtensions` now.-    + Added `Ext_compact_definition_lists`.-    + Added `Ext_epub_html_exts`.-    + Added `Ext_native_divs` and `Ext_native_spans`.-      This allows users to turn off the default pandoc behavior of-      parsing contents of div and span tags in markdown and HTML-      as native pandoc Div blocks and Span inlines.--  * `Text.Pandoc.Parsing`:--    + Generalized `readWith` to `readWithM` (Matthew Pickering).-    + Export `runParserT` and `Stream` (Matthew Pickering).-    + Added `HasQuoteContext` type class (Matthew Pickering).-    + Generalized types of `mathInline`, `smartPunctuation`, `quoted`,-      `singleQuoted`, `doubleQuoted`, `failIfInQuoteContext`,-      `applyMacros` (Matthew Pickering).-    + Added custom `token` (Matthew Pickering).-    + Added `stateInHtmlBlock` to `ParserState`.  This is used to keep-      track of the ending tag we're waiting for when we're parsing inside-      HTML block tags.-    + Added `stateMarkdownAttribute` to `ParserState`. This is used-      to keep track of whether the markdown attribute has been set in-      an enclosing tag.-    + Generalized type of `registerHeader`, using new type classes-      `HasReaderOptions`, `HasIdentifierList`, `HasHeaderMap` (Matthew-      Pickering).  These allow certain common functions to be reused-      even in parsers that use custom state (instead of `ParserState`),-      such as the MediaWiki reader.-    + Moved `inlineMath`, `displayMath` from Markdown reader to Parsing,-      and generalized their types (Matthew Pickering).--  * `Text.Pandoc.Pretty`:--    + Added `nestle`.-    + Added `blanklines`, which guarantees a certain number of blank lines-      (and no more).--  [bug fixes]--  * Markdown reader:--    + Fixed parsing of indented code in list items.  Indented code-      at the beginning of a list item must be indented eight spaces-      from the margin (or edge of the container), or four spaces-      from the list marker, whichever is greater.-    + Fixed small bug in HTML parsing with `markdown_attribute`, which-      caused incorrect tag nesting for input like-      `<aside markdown="1">*hi*</aside>`.-    + Fixed regression with intraword underscores (#1121).-    + Improved parsing of inline links containing quote characters (#1534).-    + Slight rewrite of `enclosure`/`emphOrStrong` code.-    + Revamped raw HTML block parsing in markdown (#1330).-      We no longer include trailing spaces and newlines in the-      raw blocks.  We look for closing tags for elements (but without-      backtracking).  Each block-level tag is its own `RawBlock`;-      we no longer try to consolidate them (though `--normalize` will do so).-    + Combine consecutive latex environments.  This helps when you have-      two minipages which can't have blank lines between them (#690, #1196).-    + Support smallcaps through span.-      `<span style="font-variant:small-caps;">foo</span>` will be-      parsed as a `SmallCaps` inline, and will work in all output-      formats that support small caps (#1360).-    + Prevent spurious line breaks after list items (#1137).  When the-      `hard_line_breaks` option was specified, pandoc would formerly-      produce a spurious line break after a tight list item.-    + Fixed table parsing bug (#1333).-    + Handle `c++` and `objective-c` as language identifiers in-      github-style fenced blocks (#1318).-    + Inline math must have nonspace before final `$` (#1313).--  * LaTeX reader:--    + Handle comments at the end of tables.  This resolves the issue-      illustrated in <http://stackoverflow.com/questions/24009489>.-    + Correctly handle table rows with too few cells.  LaTeX seems to-      treat them as if they have empty cells at the end  (#241).-    + Handle leading/trailing spaces in `\emph` better.-      `\emph{ hi }` gets parsed as `[Space, Emph [Str "hi"], Space]`-      so that we don't get things like `* hi *` in markdown output.-      Also applies to `\textbf` and some other constructions (#1146).-    + Don't assume preamble doesn't contain environments (#1338).-    + Allow (and discard) optional argument for `\caption` (James Aspnes).--  * HTML reader:--    + Fixed major parsing problem with HTML tables.  Table cells were-      being combined into one cell (#1341).-    + Fixed performance issue with malformed HTML tables.-      We let a `</table>` tag close an open `<tr>` or `<td>` (#1167).-    + Allow space between `<col>` and `</col>`.-    + Added `audio` and `source` in `eitherBlockOrInline`.-    + Moved `video`, `svg`, `progress`, `script`, `noscript`, `svg` from-      `blockTags` to `eitherBlockOrInline`.-    + `map` and `object` were mistakenly in both lists; they have been removed-      from `blockTags`.-    + Ignore `DOCTYPE` and `xml` declarations.--  * MediaWiki reader:--    + Don't parse backslash escapes inside `<source>` (#1445).-    + Tightened up template parsing.-      The opening `{{` must be followed by an alphanumeric or `:`.-      This prevents the exponential slowdown in #1033.-    + Support "Bild" for images.--  * DocBook reader:--    + Better handle elements inside code environments.  Pandoc's document-      model does not allow structure inside code blocks, but at least this way-      we preserve the text (#1449).-    + Support `<?asciidoc-br?>` (#1236).--  * Textile reader:--    + Fixed list parsing. Lists can now start without an intervening-      blank line (#1513).-    + HTML block-level tags that do not start a line are parsed as-      inline HTML and do not interrupt paragraphs (as in RedCloth).--  * Org reader:--    + Make tildes create inline code (#1345).  Also relabeled `code` and-      `verbatim` parsers to accord with the org-mode manual.-    + Respect `:exports` header argument in code blocks (Craig Bosma).-    + Fixed tight lists with sublists (#1437).--  * EPUB writer:--    + Avoid excess whitespace in `nav.xhtml`.  This should improve-      TOC view in iBooks (#1392).-    + Fixed regression on cover image.-      In 1.12.4 and 1.12.4.2, the cover image would not appear properly,-      because the metadata id was not correct.  Now we derive the id from the-      actual cover image filename, which we preserve rather than using-      "cover-image."-    + Keep newlines between block elements.  This allows-      easier diff-ability (#1424).-    + Use `stringify` instead of custom `plainify`.-    + Use `renderTags'` for all tag rendering.  This properly handles tags-      that should be self-closing.  Previously `<hr/>` would appear in EPUB-      output as `<hr></hr>` (#1420).-    + Better handle HTML media tags.-    + Handle multiple dates with OPF `event` attributes.  Note: in EPUB3 we-      can have only one dc:date, so only the first one is used.--  * LaTeX writer:--    + Correctly handle figures in notes.  Notes can't contain figures in-      LaTeX, so we fake it to avoid an error  (#1053).-    + Fixed strikeout + highlighted code (#1294).-      Previously strikeout highlighted code caused an error.--  * ConTeXt writer:--    + Improved detection of autolinks with URLs containing escapes.--  * RTF writer:--    + Improved image embedding: `fetchItem'` is now used to get the-      images, and calculated image sizes are indicated in the RTF.-    + Avoid extra paragraph tags in metadata (#1421).--  * HTML writer:--    + Deactivate "incremental" inside slide speaker notes (#1394).-    + Don't include empty items in the table of contents for-      slide shows.  (These would result from creating a slide-      using a horizontal rule.)--  * MediaWiki writer:--    + Minor renaming of `st` prefixed names.--  * AsciiDoc writer:--    + Double up emphasis and strong emphasis markers in intraword-      contexts, as required by asciidoc (#1441).--  * Markdown writer:--    + Avoid wrapping that might start a list, blockquote, or header (#1013).-    + Use Span instead of (hackish) `SmallCaps` in `plainify`.-    + Don't use braced attributes for fenced code (#1416).-      If `Ext_fenced_code_attributes` is not set, the first class-      attribute will be printed after the opening fence as a bare word.-    + Separate adjacent lists of the same kind with an HTML comment (#1458).--  * PDF writer:--    + Fixed treatment of data uris for images (#1062).--  * Docx writer:--    + Use Compact style for empty table cells (#1353).-      Otherwise we get overly tall lines when there are empty-      table cells and the other cells are compact.-    + Create overrides per-image for `media/` in reference docx.-      This should be somewhat more robust and cover more types of images.-    + Improved `entryFromArchive` to avoid an unneeded parse.-    + Section numbering carries over from reference.docx (#1305).-    + Simplified `abstractNumId` numbering.  Instead of sequential numbering,-      we assign numbers based on the list marker styles.--  * `Text.Pandoc.Options`:--    + Removed `Ext_fenced_code_attributes` from `markdown_github`-      extensions.--  * `Text.Pandoc.ImageSize`:--    + Use default instead of failing if image size not found-      in exif header (#1358).-    + ignore unknown exif header tag rather than crashing.-      Some images seem to have tag type of 256, which was causing-      a runtime error.--  * `Text.Pandoc.Shared`:--    + `fetchItem`:  unescape URI encoding before reading local file (#1427).-    + `fetchItem`:  strip a fragment like `?#iefix` from the extension before-      doing mime lookup, to improve mime type guessing.-    + Improved logic of `fetchItem`:  absolute URIs are fetched from the net;-      other things are treated as relative URIs if `sourceURL` is `Just _`,-      otherwise as file paths on the local file system.-    + `fetchItem` now properly handles links without a protocol (#1477).-    + `fetchItem` now escapes characters not allowed in URIs before trying-      to parse the URIs.-    + Fixed runtime error with `compactify'DL` on certain lists (#1452).--  * `pandoc.hs`: Don't strip path off of `writerSourceURL`: the path is-    needed to resolve relative URLs when we fetch resources (#750).--  * `Text.Pandoc.Parsing`--    + Simplified `dash` and `ellipsis` (#1419).-    + Removed `(>>~)` in favor of the equivalent `(<*)` (Matthew Pickering).-    + Generalized functions to use `ParsecT` (Matthew Pickering).-    + Added `isbn` and `pmid` to list of recognized schemes (Matthew-      Pickering).--  [template changes]--  * Added haddock template.-  * EPUB3:  Added `type` attribute to `link` tags.  They are supposed to-    be "advisory" in HTML5, but kindlegen seems to require them.-  * EPUB3:  Put title page in section with `epub:type="titlepage"`.-  * LaTeX: Made `\subtitle` work properly (#1327).-  * LaTeX/Beamer: remove conditional around date (#1321).-  * LaTeX:  Added `lot` and `lof` variables, which can be set to-    get `\listoftables` and `\listoffigures` (#1407).  Note that-    these variables can be set at the command line with `-Vlot -Vlof`-    or in YAML metadata.--  [under the hood improvements]--  * Rewrote normalize for efficiency (#1385).--  * Rewrote Haddock reader to use `haddock-library` (#1346).--    + This brings pandoc's rendering of haddock markup in line-      with the new haddock.-    + Fixed line breaks in `@` code blocks.-    + alex and happy are no longer build-depends.--  * Added `Text.Pandoc.Compat.Directory` to allow building against-    different versions of the `directory` library.--  + Added `Text.Pandoc.Compat.Except` to allow building against-    different verions of `mtl`.--  * Code cleanup in some writers, using Reader monad to avoid-    passing options parameter around (Matej Kollar).--  * Improved readability in `pandoc.hs`.--  * Miscellaneous code cleanups (Artyom Kazak).--  * Avoid `import Prelude hiding (catch)` (#1309, thanks to Michael-    Thompson).--  * Changed `http-conduit` flag to `https`.  Depend on `http-client`-    and `http-client-tls` instead of `http-conduit`.  (Note:  pandoc still-    depends on `conduit` via `yaml`.)--  * Require `highlighting-kate >= 0.5.8.5` (#1271, #1317, Debian #753299).-    This change to highlighting-kate means that PHP fragments no longer need-    to start with `<?php`.  It also fixes a serious bug causing failures with-    ocaml and fsharp.--  * Require latest `texmath`.  This fixes `\tilde{E}` and allows-    `\left` to be used with `]`, `)` etc. (#1319), among many other-    improvements.--  * Require latest `zip-archive`.  This has fixes for unicode path names.--  * Added tests for plain writer.--  * `Text.Pandoc.Templates`:--    + Fail informatively on template syntax errors.-      With the move from parsec to attoparsec, we lost good error-      reporting.  In fact, since we weren't testing for end of input,-      malformed templates would fail silently.  Here we revert back to-      Parsec for better error messages.-    + Use `ordNub` (#1022).--  * Benchmarks:--    + Made benchmarks compile again (Artyom Kazak).-    + Fixed so that the failure of one benchmark does not prevent others-      from running (Artyom Kazak).-    + Use `nfIO` instead of the `getLength` trick to force full evaluation.-    + Changed benchmark to use only the test suite, so that benchmarks-      run more quickly.--  * Windows build script:--    + Add `-windows` to file name.-    + Use one install command for pandoc, pandoc-citeproc.-    + Force install of pandoc-citeproc.--  * `make_osx_package`:  Call zip file `pandoc-VERSION-osx.zip`.-    The zip should not be named `SOMETHING.pkg.zip`, or OSX finder-    will extract it into a folder named `SOMETHING.pkg`, which it-    will interpret as a defective package (#1308).--  * `README`:--    + Made headers for all extensions so they have IDs and can be-      linked to (Beni Cherniavsky-Paskin).-    + Fixed typos (Phillip Alday).-    + Fixed documentation of attributes (#1315).-    + Clarified documentation on small caps (#1360).-    + Better documentation for `fenced_code_attributes` extension-      (Caleb McDaniel).-    + Documented fact that you can put YAML metadata in a separate file-      (#1412).---pandoc (1.12.4.2)--  * Require highlighting-kate >= 0.5.8.  Fixes a performance regression.--  * Shared:  `addMetaValue` now behaves slightly differently:-    if both the new and old values are lists, it concatenates their-    contents to form a new list.--  * LaTeX reader:--    + Set `bibliography` in metadata from `\bibliography` or-      `\addbibresource` command.-    + Don't error on `%foo` with no trailing newline.--  * Org reader:--    + Support code block headers (`#+BEGIN_SRC ...`) (Albert Krewinkel).-    + Fix parsing of blank lines within blocks (Albert Krewinkel).-    + Support pandoc citation extension (Albert Krewinkel).  This can-      be turned off by specifying `org-citations` as the input format.--  * Markdown reader:--    + `citeKey` moved to `Text.Pandoc.Parsing` so it can be used by-      other readers (Albert Krewinkel).--  * `Text.Pandoc.Parsing`:--    + Added `citeKey` (see above).-    + Added `HasLastStrPosition` type class and `updateLastStrPos`-      and `notAfterString` functions.--  * Updated copyright notices (Albert Krewinkel).--  * Added default.icml to data files so it installs with the package.--  * OSX package:--    + The binary is now built with options to ensure that it can be-      used with OSX 10.6+.-    + Moved OSX package materials to osx directory.-    + Added OSX package uninstall script, included in the zip container-      (thanks to Daniel T. Staal).--pandoc (1.12.4)--  * Made it possible to run filters that aren't executable (#1096).-    Pandoc first tries to find the executable (searching the path-    if path isn't given).  If it fails, but the file exists and has-    a `.py`, `.pl`, `.rb`, `.hs`, or `.php` extension, pandoc runs the filter-    using the appropriate interpreter.  This should make it easier to-    use filters on Windows, and make it more convenient for everyone.--  * Added Emacs org-mode reader (Albert Krewinkel).--  * Added InDesign ICML Writer (Mauro Bieg).--  * MediaWiki reader:--    + Accept image links in more languages (Jaime Marquínez Ferrándiz).-    + Fixed bug in certain nested lists (#1213).  If a level 2 list was-      followed by a level 1 list, the first item of the level 1 list-      would be lost.-    + Handle table rows containing just an HTML comment (#1230).--  * LaTeX reader:--    + Give better location information on errors, pointing to line-      numbers within included files (#1274).-    + LaTeX reader:  Better handling of `table` environment (#1204).-      Positioning options no longer rendered verbatim.-    + Better handling of figure and table with caption (#1204).-    + Handle `@{}` and `p{length}` in tabular.  The length is not actually-      recorded, but at least we get a table (#1180).-    + Properly handle `\nocite`.  It now adds a `nocite` metadata-      field.  Citations there will appear in the bibliography but not-      in the text (unless you explicitly put a `$nocite$` variable-      in your template).--  * Markdown reader:--    + Ensure that whole numbers in YAML metadata are rendered without-      decimal points.  (This became necessary with changes to aeson-      and yaml libraries.  aeson >= 0.7 and yaml >= 0.8.8.2 are now required.)-    + Fixed regression on line breaks in strict mode (#1203).-    + Small efficiency improvements.-    + Improved parsing of nested `div`s.  Formerly a closing `div` tag-      would be missed if it came right after other block-level tags.-    + Avoid backtracking when closing `</div>` not found.-    + Fixed bug in reference link parsing in `markdown_mmd`.-    + Fixed a bug in list parsing (#1154).  When reading a raw list-      item, we now strip off up to 4 spaces.-    + Fixed parsing of empty reference link definitions (#1186).-    + Made one-column pipe tables work (#1218).--  * Textile reader:--    + Better support for attributes.  Instead of being ignored, attributes-      are now parsed and included in Span inlines.  The output will be a bit-      different from stock textile: e.g. for `*(foo)hi*`, we'll get-      `<em><span class="foo">hi</span></em>` instead of-      `<em class="foo">hi</em>`.  But at least the data is not lost.-    + Improved treatment of HTML spans (%) (#1115).-    + Improved link parsing.  In particular we now pick up on attributes.-      Since pandoc links can't have attributes, we enclose the whole link in-      a span if there are attributes (#1008).-    + Implemented correct parsing rules for inline markup (#1175, Matthew-      Pickering).-    + Use Builder (Matthew Pickering).-    + Fixed list parsing bug (#1500).-    + Don't allow inline formatting to extend over newlines.-      This matches the behavior of RedCarpet, avoids some ugly bugs,-      and improves performance.--  * DocBook reader:--    + Better treatment of `formalpara`.  We now emit the title (if present)-      as a separate paragraph with boldface text (#1215).-    + Set metadata `author` not `authors`.-    + Added recognition of `authorgroup` and `releaseinfo` elements (#1214,-      Matthew Pickering).-    + Converted current meta information parsing in DocBook to a more-      extensible version which is aware of the more recent meta-      representation (Matthew Pickering).--  * HTML reader:--    + Require tagsoup 0.13.1, to fix a bug with parsing of script tags-      (#1248).-    + Treat processing instructions & declarations as block.  Previously-      these were treated as inline, and included in paragraph tags in HTML-      or DocBook output, which is generally not what is wanted (#1233).-    + Updated `closes` with rules from HTML5 spec.-    + Use Builder (Matthew Pickering, #1162).--  * RST reader:--    + Remove duplicate `http` in PEP links (Albert Krewinkel).-    + Make rst figures true figures (#1168, CasperVector)-    + Enhanced Pandoc's support for rST roles (Merijn Verstaaten).-      rST parser now supports: all built-in rST roles, new role definition,-      role inheritance, though with some limitations.-    + Use `author` rather than `authors` in metadata.-    + Better handling of directives.  We now correctly handle field-      lists that are indented more than three spaces.  We treat an-      `aafig` directive as a code block with attributes, so it can be-      processed in a filter (#1212).--  * LaTeX writer:--    + Mark span contents with label if span has an ID (Albert Krewinkel).-    + Made `--toc-depth` work well with books in latex/pdf output (#1210).-    + Handle line breaks in simple table cells (#1217).-    + Workaround for level 4-5 headers in quotes.  These previously produced-      invalid LaTeX: `\paragraph` or `\subparagraph` in a `quote` environment.-      This adds an `mbox{}` in these contexts to work around the problem.-      See <http://tex.stackexchange.com/a/169833/22451> (#1221).-    + Use `\/` to avoid en-dash ligature instead of `-{}-` (Vaclav Zeman).-      This is to fix LuaLaTeX output. The `-{}-` sequence does not avoid the-      ligature with LuaLaTeX but `\/` does.-    + Fixed string escaping in `hyperref` and `hyperdef` (#1130).--  * ConTeXt writer:  Improved autolinks (#1270).--  * DocBook writer:--    + Improve handling of hard line breaks in Docbook writer-      (Neil Mayhew).  Use a `<literallayout>` for the entire paragraph, not-      just for the newline character.-    + Don't let line breaks inside footnotes influence the enclosing-      paragraph (Neil Mayhew).-    + Distinguish tight and loose lists in DocBook output, using-      `spacing="compact"` (Neil Mayhew, #1250).--  * Docx writer:  When needed files are not present in the user's-    `reference.docx`, fall back on the versions in the `reference.docx`-    in pandoc's data files. This fixes a bug that occurs when a-    `reference.docx` saved by LibreOffice is used. (#1185)--  * EPUB writer:--    + Include extension in epub ids.  This fixes a problem with duplicate-      extensions for fonts and images with the same base name but different-      extensions (#1254).-    + Handle files linked in raw `img` tags (#1170).-    + Handle media in `audio` source tags (#1170).-      Note that we now use a `media` directory rather than `images`.-    + Incorporate files linked in `video` tags (#1170).  `src` and `poster`-      will both be incorporated into `content.opf` and the epub container.--  * HTML writer:--    + Add colgroup around col tags (#877).  Also affects EPUB writer.-    + Fixed bug with unnumbered section headings.  Unnumbered section-      headings (with class `unnumbered`) were getting numbers.-    + Improved detection of image links. Previously image links with-      queries were not recognized, causing `<embed>` to be used instead-      of `<img>`.--  * Man writer:  Ensure that terms in definition lists aren't line wrapped-    (#1195).--  * Markdown writer:--    + Use proper escapes to avoid unwanted lists (#980).  Previously we used-      0-width spaces, an ugly hack.-    + Use longer backtick fences if needed (#1206).  If the content contains a-      backtick fence and there are attributes, make sure longer fences are-      used to delimit the code.  Note:  This works well in pandoc, but github-      markdown is more limited, and will interpret the first string of three-      or more backticks as ending the code block.--  * RST writer:  Avoid stack overflow with certain tables (#1197).--  * RTF writer:  Fixed table cells containing paragraphs.--  * Custom writer:--    + Correctly handle UTF-8 in custom lua scripts (#1189).-    + Fix bugs with lua scripts with mixed-case filenames and-      paths containing `+` or `-` (#1267).  Note that `getWriter`-      in `Text.Pandoc` no longer returns a custom writer on input-      `foo.lua`.--  * AsciiDoc writer:  Handle multiblock and empty table cells-    (#1245, #1246).  Added tests.--  * `Text.Pandoc.Options`: Added `readerTrace` to `ReaderOptions`--  * `Text.Pandoc.Shared`:--    + Added `compactify'DL` (formerly in markdown reader) (Albert Krewinkel).-    + Fixed bug in `toRomanNumeral`:  numbers ending with '9' would-      be rendered as Roman numerals ending with 'IXIV' (#1249).  Thanks to-      Jesse Rosenthal.-    + `openURL`: set proxy with value of http_proxy env variable (#1211).-      Note:  proxies with non-root paths are not supported, due to-      limitations in `http-conduit`.--  * `Text.Pandoc.PDF`:--    + Ensure that temp directories deleted on Windows (#1192).  The PDF is-      now read as a strict bytestring, ensuring that process ownership will-      be terminated, so the temp directory can be deleted.-    + Use `/` as path separators in a few places, even on Windows.-      This seems to be necessary for texlive (#1151, thanks to Tim Lin).-    + Use `;` for `TEXINPUTS` separator on Windows (#1151).-    + Changes to error reporting, to handle non-UTF8 error output.--  * `Text.Pandoc.Templates`:--    + Removed unneeded datatype context (Merijn Verstraaten).--    + YAML objects resolve to "true" in conditionals (#1133).-      Note:  If `address` is a YAML object and you just have `$address$`-      in your template, the word `true` will appear, which may be-      unexpected.  (Previously nothing would appear.)--  * `Text.Pandoc.SelfContained`:--    + `mkSelfContained` now takes just two arguments, `WriterOptions` and-      the string.-    * It no longer looks in data files.  This only made sense when we-      had copies of slidy and S5 code there.-    * `fetchItem'` is used instead of the nearly duplicate `getItem`.-    + Handle `poster` attribute in `video` tags (#1188).--  * `Text.Pandoc.Parsing`:--    + Made `F` an instance of Applicative (#1138).-    + Added `stateCaption`.-    + Added `HasMacros`, simplified other typeclasses.-      Removed `updateHeaderMap`, `setHeaderMap`, `getHeaderMap`,-      `updateIdentifierList`, `setIdentifierList`, `getIdentifierList`.-    + Changed the smart punctuation parser to return `Inlines`-      rather than `Inline` (Matthew Pickering).-    + Changed `HasReaderOptions`, `HasHeaderMap`, `HasIdentifierList`-      from typeclasses of monads to typeclasses of states.  This simplifies-      the instance definitions and provides more flexibility.  Generalized-      type of `getOption` and added a default definition.  Removed-      `askReaderOption`.  Added `extractReaderOption`.  Added-      `extractHeaderMap` and `updateHeaderMap` in `HasHeaderMap`.-      Gave default definitions for `getHeaderMap`, `putHeaderMap`,-      `modifyHeaderMap`.  Added `extractIdentifierList` and-      `updateIdentifierList` in `HasIdentifierList`.  Gave defaults-      for `getIdentifierList`, `putIdentifierList`, and-      `modifyIdentifierList`.  The ultimate goal here is to allow different-      parsers to use their own, tailored parser states (instead of-      `ParserState`) while still using shared functions.--  * Template changes:--    + LaTeX template: Use `fontenc` package only with `pdflatex` (#1164).-    + LaTeX template:  Add `linestretch` and `fontfamily` variables.-    + LaTeX template:  Conditionalize author and date commands.-    + Beamer template: Consistent styles for figure and table captions-      (aaronwolen).-    + LaTeX and beamer template:  Adjust widths correctly for oversized-      images.  Use `\setkeys{Gin}{}` to set appropriate defaults for-      `\includegraphics` (Yihui Xie, Garrick Aden-Buie).  Load-      `upquote` only after `fontenc` (Yihui Xie).-    + Beamer template: Added caption package (#1200).-    + Beamer template:  changes for better unicode handling (KarolS).-    + DocBook template:  use `authorgroup` if there are authors.-    + revealjs template: Move `include-after` to end (certainlyakey).-    + revealjs template: Fixed PDF print function (#1220, kevinkenan).--  * Bumped version bounds of dependencies.--  * Added a `--trace` command line option, for debugging backtracking-    bugs.  So far this only works with the markdown reader.--  * MathMLinHTML:  Fixed deprecation warning (#362, gwern, Albert Krewinkel).--  * Updated travis script to test with multiple GHC versions.--  * Force failure of a Travis build if GHC produces warnings (Albert-    Krewinkel).--  * Add `.editorconfig` (Albert Krewinkel).-    See <http://editorconfig.org/> for details.--  * Give more useful error message if '-t pdf' is specified (#1155).--  * Added `Cite`, `SmallCaps` to `Arbitrary` instance (#1269).--  * Allow `html4` as a synonym of `html` as a reader (it already works-    as a writer).--  * README:--    + Added an explanation of how to use YAML metadata to-      force items to appear in the bibliography without citations in-      the text (like LaTeX `\nocite`).-    + Added note to `--bibtex/--natbib`: not for use in making PDF-      (#1194, thanks to nahoj).-    + Added explanatory notes about `--natbib` and `--biblatex`.-    + Added specification of legal syntax for citation keys.-    + Fixed variable defaults documentation (Albert Krewinkel).--  * Removed copyright statements for files that have been removed-    (Albert Krewinkel).--  * Moved some doc files from `data-files` to `extra-source-files` (#1123).-    They aren't needed at runtime.  We keep README and COPYRIGHT in data-    to ensure that they'll be available on all systems on which pandoc-    is installed.--  * Use cabal sandboxes in Windows build script.--pandoc (1.12.3.3)--  * To changes to source; recompiled tarball with latest alex and-    happy, so they will work with GHC 7.8.--pandoc (1.12.3.2)--  * Bumped version bounds for blaze-html, blaze-markup.--  * ImageSize:  Avoid use of lookAhead, which is not in binary >= 0.6-    (#1124).--  * Fixed mediawiki ordered list parsing (#1122).--  * HTML reader:  Fixed bug reading inline math with `$$` (#225).--  * Added support for LaTeX style literate Haskell code blocks in rST-    (Merijn Verstraaten).--pandoc (1.12.3.1)--  * Relaxed version constraint on binary, allowing the use of binary 0.5.--pandoc (1.12.3)--  * The `--bibliography` option now sets the `biblio-files` variable.-    So, if you're using `--natbib` or `--biblatex`, you can just use-    `--bibliography=foo.bib` instead of `-V bibliofiles=foo`.--  * Don't run pandoc-citeproc filter if `--bibliography` is-    used together with `--natbib` or `--biblatex` (Florian Eitel).--  * Template changes:--    + Updated beamer template to include booktabs.-    + Added `abstract` variable to LaTeX template.-    + Put `header-includes` after `title` in LaTeX template (#908).-    + Allow use of `\includegraphics[size]` in beamer.-      This just required porting a macro definition from the default-      LaTeX template to the default beamer template.--  * `reference.docx`:  Include `FootnoteText` style.-    Otherwise Word ignores the style, even when specified in the `pPr`.-    (#901)--  * `reference.odt`:  Tidied `styles.xml`.--  * Relaxed version bounds for dependencies.--  * Added `withSocketsDo` around http conduit code in `openURL`,-    so it works on Windows (#1080).--  * Added `Cite` function to `sample.lua`.--  * Markdown reader:--    + Fixed regression in title blocks (#1089).-      If author field was empty, date was being ignored.-    + Allow backslash-newline hard line breaks in grid and-      multiline table cells.-    + Citation keys may now start with underscores, and may contain-      underscores adjacent to internal punctuation.--  * LaTeX reader:--    + Add support for `Verb` macro (jrnold) (#1090).-    + Support babel-style quoting: `` "`..."' ``.--  * Properly handle script blocks in strict mode.  (That is,-    `markdown-markdown_in_html_blocks`.) Previously a spurious-    `<p>` tag was being added (#1093).--  * Docbook reader: Avoid failure if `tbody` contains no `tr` or `row`-    elements.--  * LaTeX writer:--    + Factored out function for table cell creation.-    + Better treatment of footnotes in tables.-      Notes now appear in the regular sequence, rather than in the-      table cell.  (This was a regression in 1.10.)--  * HTML reader: Parse name/content pairs from meta tags as metadata.-    Closes #1106.--  * Moved `fixDisplayMath` from Docx writer to `Writer.Shared`.--  * OpenDocument writer:  Fixed `RawInline`, `RawBlock` so they don't escape.--  * ODT writer:  Use mathml for proper rendering of formulas.-    Note:  LibreOffice's support for this seems a bit buggy.  But-    it should be better than what we had before.--  * RST writer: Ensure no blank line after def in definition list (#992).--  * Markdown writer: Don't use tilde code blocks with braced attributes in-    `markdown_github` output.  A consequence of this change is that the-    backtick form will be preferred in general if both are enabled.  That-    is good, as it is much more widespread than the tilde form.  (#1084)--  * Docx writer:  Fixed problem with some modified reference docx files.-    Include `word/_rels/settings.xml.rels` if it exists, as well as other-    `rels` files besides the ones pandoc generates explicitly.--  * HTML writer:--    + With `--toc`, headers no longer link to themselves (#1081).-    + Omit footnotes from TOC entries.  Otherwise we get doubled-      footnotes when headers have notes!--  * EPUB writer:--    + Avoid duplicate notes when headings contain notes.-      This arose because the headings are copied into the metadata-      "title" field, and the note gets rendered twice.  We strip the-      note now before putting the heading in "title".-    + Strip out footnotes from toc entries.-    + Fixed bug with `--epub-stylesheet`.  Now the contents of-      `writerEpubStylesheet` (set by `--epub-stylesheet`)-      should again work, and take precedence over a stylesheet specified-      in the metadata.--  * `Text.Pandoc.MIME`: Added `wmf`, `emf`.--  * `Text.Pandoc.Shared`:  `fetchItem` now handles image URLs beginning-    with `//`.--  * `Text.Pandoc.ImageSize`:  Parse EXIF format JPEGs.  Previously-    we could only get size information for JFIF format, which led-    to squished images in Word documents. Closes #976.--  * Removed old `MarkdownTest_1.0.3` directory (#1104).--pandoc (1.12.2.1)--  * Markdown reader:  Fixed regression in list parser, involving-    continuation lines containing raw HTML (or even verbatim raw HTML).--pandoc (1.12.2)--  * Metadata may now be included in YAML blocks in a markdown document.-    For example,--        ----        title:-        - type: main-          text: My Book-        - type: subtitle-          text: An investigation of metadata-        creator:-        - role: author-          text: John Smith-        - role: editor-          text: Sarah Jones-        identifier:-        - scheme: DOI-          text: doi:10.234234.234/33-        publisher:  My Press-        rights:  (c) 2007 John Smith, CC BY-NC-        cover-image: img/mypic.jpg-        ...--    Metadata may still be provided using `--epub-metadata`; it will-    be merged with the metadata in YAML blocks.--  * EPUB writer:--    + `meta` tags are now used instead of `opf` attributes for EPUB3.-    + Insert "svg" property as needed in opf (EPUB 3).-    + Simplify `imageTypeOf` using `getMimeType`.-    + Add properties attribute to `cover-image` item for EPUB 3.-    + Don't include node for `cover.xhtml` if no cover!-    + Ensure that same identifier is used throughout (#1044).-      If an identifier is given in metadata, we use that; otherwise-      we generate a random uuid.-    + Add cover reference to guide element (EPUB 2) (Shaun Attfield).-      Fixes an issue with Calibre putting the cover at the end of the book-      if the spine has `linear="no"`.  Apparently this is best practice-      for other converters as well:-      <http://www.idpf.org/epub/20/spec/OPF_2.0.1_draft.htm#Section2.6>.-    + Allow `stylesheet` in metadata.  The value is a path to the stylesheet.-    + Allow partial dates:  `YYYY`, `YYYY-MM`.--  * Markdown writer:  Fix rendering of tight sublists (#1050).-    Previously a spurious blank line was included after a tight sublist.--  * ODT writer:  Add `draw:name` attribute to `draw:frame` elements (#1069).-    This is reported to be necessary to avoid an error from recent-    versions of Libre Office when files contain more than one image-    Thanks to wmanley for reporting and diagnosing the problem.--  * ConTeXt writer:  Don't hardcode figure/table placement and numbering.-    Instead, let this be set in the template, using `\setupfloat`.-    Thanks to on4aa and Aditya Mahajan for the suggestion (#1067).--  * Implemented CSL flipflopping spans in DOCX, LaTeX, and HTML writers.--  * Fixed bug with markdown intraword emphasis.  Closes #1066.--  * Docbook writer:  Hierarchicalize block content in metadata.-    Previously headers just disappeared from block-level metadata-    when it was used in templates.  Now we apply the 'hierarchicalize'-    transformation.  Note that a block headed by a level-2 header will-    turn into a `<sect1>` element.--  * OpenDocument writer:  Skip raw HTML (#1035).-    Previously it was erroneously included as verbatim text.--  * HTML/EPUB writer, footnotes:  Put `<sup>` tag inside `<a>` tags.-    This allows better control of formatting, since the `<a>`-    tags have a distinguishing class (#1049).--  * Docx writer:--    + Use mime type info returned by fetchItem.-    + Fixed core metadata (#1046).-      Don't create empty date nodes if no date given.-      Don't create multiple `dc:creator` nodes; instead separate by-      semicolons.-    + Fix URL for core-properties in `_rels/.rels` (#1046).--  * Plain writer: don't print `<span>` tags.--  * LaTeX writer:--    + Fix definition lists with internal links in terms (#1032).-      This fix puts braces around a term that contains an internal-      link, to avoid problems with square brackets.-    + Properly escape pdftitle, pdfauthor (#1059).-    + Use booktabs package for tables (thanks to Jose Luis Duran).--  * Updated beamer template.  Now references should work properly-    (in a slide) when `--biblatex` or `--natbib` is used.--  * LaTeX reader:--    + Parse contents of curly quotes or matched `"` as quotes.-    + Support `\textnormal` as span with class `nodecor`.-      This is needed for pandoc-citeproc.-    + Improved citation parsing.  This fixes a run-time error that occured-      with `\citet{}` (empty list of keys).  It also ensures that empty keys-      don't get produced.--  * MediaWiki reader:  Add automatic header identifiers.--  * HTML reader:--    + Use pandoc `Div` and `Span` for raw `<div>`, `<span>` when-      `--parse-raw`.-    + Recognize `svg` tags as block level content (thanks to MinRK).-    + Parse LaTeX math if appropriate options are set.--  * Markdown reader:--    + Yaml block must start immediately after `---`.  If there's a blank-      line after `---`, we interpreted it as a horizontal rule.-    + Correctly handle empty bullet list items.-    + Stop parsing "list lines" when we hit a block tag.-      This fixes exponential slowdown in certain input, e.g.-      a series of lists followed by `</div>`.--  * Slides:  Preserve `<div class="references">` in references slide.--  * `Text.Pandoc.Writer.Shared`:--    + Fixed bug in `tagWithAttrs`.  A space was omitted before key-value-      attributes, leading to invalid HTML.-    + `normalizeDate`: Allow dates with year only (thanks to Shaun Attfield).-    + Fixed bug in `openURL` with `data:` URIs.  Previously the base-64-      encoded bytestring was returned.  We now decode it so it's a proper-      image!--  * DocBook reader:  Handle numerical attributes starting with decimal.-    Also use `safeRead` instead of `read`.--  * `Text.Pandoc.Readers.TexMath`: Export `readTeXMath'`, which attends-    to display/inline.  Deprecate `readTeXMath`, and use `readTeXMath'`-    in all the writers.  Require `texmath >= 0.6.5.2`.--  * `Text.Pandoc.MIME`:--    + Add entry for `jfif`.-    + In looking up extensions, drop the encoding info.-      E.g. for 'image/jpg;base64' we should lookup 'image/jpg'.--  * Templates:  Changed how array variables are resolved.  Previously if-    `foo` is an array (which might be because multiple values were set on-    the command line), `$foo$` would resolve to the concatenation of the-    elements of foo.  This is rarely useful behavior.  It has been changed-    so that the first value is rendered.  Of course, you can still iterate-    over the values using `$for(foo)$`.  This has the result that you can-    override earlier settings using `-V` by putting new values later on the-    command line, which is useful for many purposes.--  * `Text.Pandoc`:  Don't default to `pandocExtensions` for all writers.--  * Allow "epub2" as synonym for "epub", "html4" for "html".--  * Don't look for slidy files in data files with `--self-contained`.--  * Allow `https:` command line arguments to be downloaded.--  * Fixed `make_osx_package.sh` so data files embedded in `pandoc-citeproc`.--pandoc (1.12.1)--  * `Text.Pandoc.Definition`:  Changed default JSON serialization format.-    Instead of `{"Str": "foo"}`, for example, we now have `{"t": "Str",-    "c": "foo"}`.  This new format is easier to work with outside of Haskell.-    Incidentally, "t" stands for "tag", "c" for "contents".--  * MediaWiki reader: Trim contents of `<math>` tags, to avoid problems-    when converting to markdown (#1027).--  * LaTeX reader:--    + Ensure that preamble doesn't contribute to the text of-      the document.-    + Fixed character escaping in \url{}.  Previously `\~` wasn't handled-      properly, among others.-    + Parse `{groups}` as `Span`.  This is needed for accurate conversion of-      bibtex titles, since we need to know what was protected from-      titlecase conversions.--  * LaTeX writer:--    + Specially escape non-ascii characters in labels.-      Otherwise we can get compile errors and other bugs when-      compiled with pdflatex (#1007).  Thanks to begemotv2718 for the fix.-    + Add link anchors for code blocks with identifiers (#1025).--  * Throughout the code, use `isURI` instead of `isAbsoluteURI`.-    It allows fragments identifiers.--  * Slide formats:--    + A Div element with class "notes" is treated as speaker-      notes.  Currently beamer goes to `\note{}`, revealjs to-      `<aside class="notes">`, and the notes are simply suppressed in-      other formats  (#925).-    + Fixed `. . .` (pause) on HTML slide formats.  Closes #1029.-      The old version caused a pause to be inserted before the first-      material on a slide. This has been fixed.-    + Removed data files for s5, slideous, slidy.-      Users of s5 and slideous will have to download the needed-      files, as has been documented for some time in the README.-      By default, slidy code will be sought on the web, as before.--  * HTML writer: Insert command to typeset mathjax only in slideous output-    (#966, #1012).--  * RST writer:  Skip spaces after display math.  Otherwise we get indentation-    problems, and part of the next paragraph may be rendered as part of the-    math.--  * OpenDocument writer:  Fix formatting of strikeout code (#995),-    thanks to wilx.  don't use `font-face-decls` variable.--  * Fixed test suite so it works with cabal sandboxes.--pandoc (1.12.0.2)--  * Removed `stringable` dependency.--pandoc (1.12.0.1)--  * Allow `--metadata` to be repeated for the same key to form a list.-    This also has the effect that `--bibliography` can be repeated,-    as before.--  * Handle boolean values in `--metadata`.  Note that anything not parseable-    as a YAML boolean or string is treated as a literal string.-    You can get a string value with "yes", or any of the strings interpretable-    as booleans, by quoting it:--        -M boolvalue=yes -M stringvalue='"yes"'--  * LaTeX writer: Don't print references if `--natbib` or `--biblatex`-    option used.--  * DOCX writer: Add `settings.xml` to the zip container.  Fixes a bug-    in which docx files could not be read by some versions of Word-    and LibreOffice (#990).--  * Fixed a regression involving slide shows with bibliographies.-    The Div container around references messed up the procedure for carving-    a document into slides.  So we now remove the surrounding Div in-    `prepSlides`.--  * More informative error message when a filter is not found in path.--  * Depend on pandoc-types 1.12.1.  This provide `ToJSONFilter`-    instances for `Data a => a -> [a]` and `Data a => a -> IO [a]`.--  * Don't use unicode_collation in building OSX package:-    it adds something like 50MB of dependencies to the package.--  * Declare alex and happy as build-tools (#986).--pandoc (1.12)--  [new features]--  * Much more flexible metadata, including arbitrary fields and structured-    values.  Metadata can be specified flexibly in pandoc markdown using-    YAML metadata blocks, which may occur anywhere in the document:--        ----        title: Here is my title.-        abstract: |-          This is the abstract.--          1. It can contain-          2. block content-             and *inline markup*--        tags: [cat, dog, animal]-        ...--    Metadata fields automatically populate template variables.--  * Added `opml` (OPML) as input and output format.  The `_note` attribute,-    used in OmniOutliner and supported by multimarkdown, is supported.-    We treat the contents as markdown blocks under a section header.--  * Added `haddock` (Haddock markup) as input format (David Lazar).--  * Added `revealjs` output format, for reveal.js HTML 5 slide shows.-    (Thanks to Jamie F. Olson for the initial patch.)-    Nested vertical stacks are used for hierarchical structure.-    Results for more than one level of nesting may be odd.--  * Custom writers can now be written in lua.--        pandoc -t data/sample.lua--    will load the script sample.lua and use it as a custom writer.-    (For a sample, do `pandoc --print-default-data-file sample.lua`.)-    Note that pandoc embeds a lua interpreter, so lua need not be-    installed separately.--  * New `--filter/-F` option to make it easier to run "filters"-    (Pandoc AST transformations that operate on JSON serializations).-    Filters are always passed the name of the output format, so their-    behavior can be tailored to it.  The repository-    <https://github.com/jgm/pandocfilters> contains-    a python module for writing pandoc filters in python, with-    a number of examples.--  * Added `--metadata/-M` option.-    This is like `--variable/-V`, but actually adds to metadata, not-    just variables.--  * Added `--print-default-data-file` option, which allows printing-    of any of pandoc's data files. (For example,-    `pandoc --print-default-data-file reference.odt` will print-    `reference.odt`.)--  * Added syntax for "pauses" in slide shows:--        This gives--        . . .--        me pause.--  * New markdown extensions:--    + `ignore_line_breaks`:  causes intra-paragraph line breaks to be ignored,-      rather than being treated as hard line breaks or spaces.  This is useful-      for some East Asian languages, where spaces aren't used between words,-      but text is separated into lines for readability.-    + `yaml_metadata_block`:  Parse YAML metadata blocks.  (Default.)-    + `ascii_identifiers`: This will force `auto_identifiers` to use ASCII-       only. (Default for `markdown_github`.) (#807)-    + `lists_without_preceding_blankline`:  Allow lists to start without-      preceding blank space.  (Default for `markdown_github`.) (#972)--  [behavior changes]--  * `--toc-level` no longer implies `--toc`.-    Reason: EPUB users who don't want a visible TOC may still want-    to set the TOC level for in the book navigation.--  * `--help` now prints in and out formats in alphabetical order, and-    says something about PDF output (#720).--  * `--self-contained` now returns less verbose output (telling you-    which URLs it is fetching, but not giving the full header).  In-    addition, there are better error messages when fetching a URL fails.--  * Citation support is no longer baked in to core pandoc. Users who-    need citations will need to install and use a separate filter-    (`--filter pandoc-citeproc`).  This filter will take `bibliography`,-    `csl`, and `citation-abbreviations` from the metadata, though it-    may still be specified on the command line as before.--  * A `Cite` element is now created in parsing markdown whether or not-    there is a matching reference.--  * The `pandoc-citeproc` script will put the bibliography at the-    end of the document, as before.  However, it will be put inside a `Div`-    element with class "references", allowing users some control-    over the styling of references.  A final header, if any, will-    be included in the `Div`.--  * The markdown writer will not print a bibliography if the-    `citations` extension is enabled.  (If the citations are formatted-    as markdown citations, it is redundant to have a bibliography,-    since one will be generated automatically.)--  * Previously we used to store the directory of the first input file,-    even if it was local, and used this as a base directory for finding-    images in ODT, EPUB, Docx, and PDF.  This has been confusing to many-    users.  So we now look for images relative to the current-    working directory, even if the first file argument is in another-    directory.   Note that this change may break some existing workflows.-    If you have been assuming that relative links will be interpreted-    relative to the directory of the first file argument, you'll need-    to make that the current directory before running pandoc. (#942)--  * Better error reporting in some readers, due to changes in `readWith`:-    the line in which the error occured is printed, with a caret pointing-    to the column.--  * All slide formats now support incremental slide view for definition lists.--  * Parse `\(..\)` and `\[..\]` as math in MediaWiki reader.-    Parse `:<math>...</math>` as display math.  These notations are used with-    the MathJax MediaWiki extension.--  * All writers: template variables are set automatically from metadata-    fields.  However, variables specified on the command line with-    `--variable` will completely shadow metadata fields.--  * If `--variable` is used to set many variables with the same name,-    a list is created.--  * Man writer:  The `title`, `section`, `header`, and `footer` can now-    all be set individually in metadata.  The `description` variable has been-    removed.  Quotes have been added so that spaces are allowed in the-    title.  If you have a title that begins--        COMMAND(1) footer here | header here--    pandoc will still parse it into a title, section, header, and-    footer.  But you can also specify these elements explicitly (#885).--  * Markdown reader--    + Added support for YAML metadata blocks, which can come anywhere-      in the document (not just at the beginning).  A document can contain-      multiple YAML metadata blocks.-    + HTML span and div tags are parsed as pandoc Span and Div elements.--  * Markdown writer--    + Allow simple tables to be printed as grid tables,-      if other table options are disabled.  This means you can do-      `pandoc -t markdown-pipe_tables-simple_tables-multiline_tables`-      and all tables will render as grid tables.-    + Support YAML title block (render fields in alphabetical order-      to make output predictable).--  [API changes]--  * `Meta` in `Text.Pandoc.Definition` has been changed to allow-    structured metadata.  (Note:  existing code that pattern-matches-    on `Meta` will have to be revised.)  Metadata can now contain-    indefinitely many fields, with content that can be a string,-    a Boolean, a list of `Inline` elements, a list of `Block`-    elements, or a map or list of these.--  * A new generic block container (`Div`) has been added to `Block`,-    and a generic inline container (`Span`) has been added to `Inline`.-    These can take attributes.  They will render in HTML, Textile,-    MediaWiki, Org, RST and and Markdown (with `markdown_in_html`-    extension) as HTML `<div>` and `<span>` elements; in other formats-    they will simply pass through their contents.  But they can be-    targeted by scripts.--  * `Format` is now a newtype, not an alias for String.-    Equality comparisons are case-insensitive.--  * Added `Text.Pandoc.Walk`, which exports hand-written tree-walking-    functions that are much faster than the SYB functions from-    `Text.Pandoc.Generic`.  These functions are now used where possible-    in pandoc's code.  (`Tests.Walk` verifies that `walk` and `query`-    match the generic traversals `bottomUp` and `queryWith`.)--  * Added `Text.Pandoc.JSON`, which provides `ToJSON` and `FromJSON`-    instances for the basic pandoc types. They use GHC generics and-    should be faster than the old JSON serialization using-    `Data.Aeson.Generic`.--  * Added `Text.Pandoc.Process`, exporting `pipeProcess`.-    This is a souped-up version of `readProcessWithErrorcode` that-    uses lazy bytestrings instead of strings and allows setting-    environment variables.  (Used in `Text.Pandoc.PDF`.)--  * New module `Text.Pandoc.Readers.OPML`.--  * New module `Text.Pandoc.Writers.OPML`.--  * New module `Text.Pandoc.Readers.Haddock` (David Lazar).-    This is based on Haddock's own lexer/parser.--  * New module `Text.Pandoc.Writers.Custom`.--  * In `Text.Pandoc.Shared`, `openURL` and `fetchItem` now return an-    Either, for better error handling.--  * Made `stringify` polymorphic in `Text.Pandoc.Shared`.--  * Removed `stripTags` from `Text.Pandoc.XML`.--  * `Text.Pandoc.Templates`:--    + Simplified `Template` type to a newtype.-    + Removed `Empty`.-    + Changed type of `renderTemplate`: it now takes a JSON context-      and a compiled template.-    + Export `compileTemplate`.-    + Export `renderTemplate'` that takes a string instead of a compiled-      template.-    + Export `varListToJSON`.--  * `Text.Pandoc.PDF` exports `makePDF` instead of `tex2pdf`.--  * `Text.Pandoc`:--    + Made `toJsonFilter` an alias for `toJSONFilter` from `Text.Pandoc.JSON`.-    + Removed `ToJsonFilter` typeclass.  `ToJSONFilter` from-      `Text.Pandoc.JSON` should be used instead.  (Compiling against-      pandoc-types instead of pandoc will also produce smaller executables.)-    * Removed the deprecated `jsonFilter` function.-    + Added `readJSON`, `writeJSON` to the API (#817).--  * `Text.Pandoc.Options`:--    + Added `Ext_lists_without_preceding_blankline`,-      `Ext_ascii_identifiers`, `Ext_ignore_line_breaks`,-      `Ext_yaml_metadataBlock` to `Extension`.-    + Changed `writerSourceDirectory` to `writerSourceURL` and changed the-      type to a `Maybe`.  `writerSourceURL` is set to 'Just url' when the-      first command-line argument is an absolute URL.  (So, relative links-      will be resolved in relation to the first page.)  Otherwise, 'Nothing'.-    + All bibliography-related fields have been removed from-      `ReaderOptions` and `WriterOptions`: `writerBiblioFiles`,-      `readerReferences`, `readerCitationStyle`.--  * The `Text.Pandoc.Biblio` module has been removed.  Users of the-    pandoc library who want citation support will need to use-    `Text.CSL.Pandoc` from `pandoc-citeproc`.---  [bug fixes]--  * In markdown, don't autolink a bare URI that is followed by `</a>`-    (#937).--  * `Text.Pandoc.Shared`--    + `openURL` now follows redirects (#701), properly handles `data:`-      URIs, and prints diagnostic output to stderr rather than stdout.-    + `readDefaultDataFile`: normalize the paths.  This fixes bugs in-      `--self-contained` on pandoc compiled with `embed_data_files` (#833).-    + Fixed `readDefaultDataFile` so it works on Windows.-    + Better error messages for `readDefaultDataFile`.  Instead of-      listing the last path tried, which can confuse people who are-      using `--self-contained`, so now we just list the data file name.-    + URL-escape pipe characters.  Even though these are legal, `Network.URI`-      doesn't regard them as legal in URLs.  So we escape them first (#535).--  * Mathjax in HTML slide shows:  include explicit "Typeset" call.-    This seems to be needed for some formats (e.g. slideous) and won't-    hurt in others (#966).--  * `Text.Pandoc.PDF`--    + On Windows, create temdir in working directory, since the system-      temp directory path may contain tildes, which can cause-      problems in LaTeX (#777).-    + Put temporary output directory in `TEXINPUTS` (see #917).-    + `makePDF` tries to download images that are not found locally,-      if the first argument is a URL (#917).-    + If compiling with `pdflatex` yields an encoding error, offer-      the suggestion to use `--latex-engine=xelatex`.--  * Produce automatic header identifiers in parsing textile, RST,-    and LaTeX, unless `auto_identifiers` extension is disabled (#967).--  * `Text.Pandoc.SelfContained`:  Strip off fragment, query of relative URL-     before treating as a filename.  This fixes `--self-contained` when used-     with CSS files that include web fonts using the method described here:-      <http://paulirish.com/2009/bulletproof-font-face-implementation-syntax/>-      (#739).  Handle `src` in `embed`, `audio`, `source`, `input` tags.--  * `Text.Pandoc.Parsing`: `uri` parser no longer treats punctuation before-    percent-encoding, or a `+` character, as final punctuation.--  * `Text.Pandoc.ImageSize`:  Handle EPS (#903).  This change will make-    EPS images properly sized on conversion to Word.--  * Slidy:  Use slidy.js rather than slidy.js.gz.-    Reason:  some browsers have trouble with the gzipped js file,-    at least on the local file system (#795).--  * Markdown reader--    + Properly handle blank line at beginning of input (#882).-    + Fixed bug in unmatched reference links.  The input-      `[*infile*] [*outfile*]` was getting improperly parsed:-      "infile" was emphasized, but "*outfile*" was literal (#883).-    + Allow internal `+` in citation identifiers (#856).-    + Allow `.` or `)` after `#` in ATX headers if no `fancy_lists`.-    + Do not generate blank title, author, or date metadata elements.-      Leave these out entirely if they aren't present.-    + Allow backtick code blocks not to be preceded by blank line (#975).--  * Textile reader:--    + Correctly handle entities.-    + Improved handling of `<pre>` blocks (#927). Remove internal HTML tags-      in code blocks, rather than printing them verbatim. Parse attributes-      on `<pre>` tag for code blocks.--  * HTML reader: Handle non-simple tables (#893).  Column widths are read from-    `col` tags if present, otherwise divided equally.--  * LaTeX reader--    + Support alltt environment (#892).-    + Support `\textasciitilde`, `\textasciicircum` (#810).-    + Treat `\textsl` as emphasized text reader (#850).-    + Skip positional options after `\begin{figure}`.-    + Support `\v{}` for hacek (#926).-    + Don't add spurious ", " to citation suffixes.-      This is added when needed in pandoc-citeproc.-    + Allow spaces in alignment spec in tables, e.g. `{ l r c }`.-    + Improved support for accented characters (thanks to Scott Morrison).-    + Parse label after section command and set id (#951).--  * RST reader:--    + Don't insert paragraphs where docutils doesn't.-      `rst2html` doesn't add `<p>` tags to list items (even when they are-      separated by blank lines) unless there are multiple paragraphs in the-      list.  This commit changes the RST reader to conform more closely to-      what docutils does (#880).-    + Improved metadata.  Treat initial field list as metadata when-      standalone specified.  Previously ALL fields "title", "author",-      "date" in field lists were treated as metadata, even if not at-      the beginning.  Use `subtitle` metadata field for subtitle.-    + Fixed 'authors' metadata parsing in reST.  Semicolons separate-      different authors.--  * MediaWiki reader--    + Allow space before table rows.-    + Fixed regression for `<ref>URL</ref>`.-      `<` is no longer allowed in URLs, according to the uri parser-      in `Text.Pandoc.Parsing`.  Added a test case.-    + Correctly handle indented preformatted text without preceding-      or following blank line.-    + Fixed `|` links inside table cells.  Improved attribute parsing.-    + Skip attributes on table rows.  Previously we just crashed if-      rows had attributes, now we ignore them.-    + Ignore attributes on headers.-    + Allow `Image:` for images (#971).-    + Parse an image with caption in a paragraph by itself as a figure.--  * LaTeX writer--    + Don't use ligatures in escaping inline code.-    + Fixed footnote numbers in LaTeX/PDF tables.  This fixes a bug-      wherein notes were numbered incorrectly in tables (#827).-    + Always create labels for sections.  Previously the labels were only-      created when there were links to the section in the document (#871).-    + Stop escaping `|` in LaTeX math.-      This caused problems with array environments (#891).-    + Change `\` to `/` in paths.  `/` works even on Windows in LaTeX.-      `\` will cause major problems if unescaped.-    + Write id for code block to label attribute in LaTeX when listings-      is used (thanks to Florian Eitel).-    + Scale LaTeX tables so they don't exceed columnwidth.-    + Avoid problem with footnotes in unnumbered headers (#940).--  * Beamer writer: when creating beamer slides, add `allowframebreaks` option-      to the slide if it is one of the header classes.  It is recommended-      that your bibliography slide have this attribute:--        # References {.allowframebreaks}--    This causes multiple slides to be created if necessary, depending-    on the length of the bibliography.--  * ConTeXt writer: Properly handle tables without captions.  The old output-    only worked in MkII. This should work in MkIV as well (#837).--  * MediaWiki writer: Use native mediawiki tables instead of HTML (#720).--  * HTML writer:--    + Fixed `--no-highlight` (Alexander Kondratskiy).-    + Don't convert to lowercase in email obfuscation (#839).-    + Ensure proper escaping in `<title>` and `<meta>` fields.--  * AsciiDoc writer:--    + Support `--atx-headers` (Max Rydahl Andersen).-    + Don't print empty identifier blocks `([[]])` on headers (Max-      Rydahl Andersen).--  * ODT writer:--    + Fixing wrong numbered-list indentation in open document format-      (Alexander Kondratskiy) (#369).-    + `reference.odt`: Added pandoc as "generator" in `meta.xml`.-    + Minor changes for ODF 1.2 conformance (#939). We leave the-      nonconforming `contextual-spacing` attribute, which is provided by-      LibreOffice itself and seems well supported.--  * Docx writer:--    + Fixed rendering of display math in lists.-      In 1.11 and 1.11.1, display math in lists rendered as a new list-      item.  Now it always appears centered, just as outside of lists,-      and in proper display math style, no matter how far indented the-      containing list item is (#784).-    + Use `w:br` with `w:type` `textWrapping` for linebreaks.-      Previously we used `w:cr` (#873).-    + Use Compact style for Plain block elements, to-      differentiate between tight and loose lists (#775).-    + Ignore most components of `reference.docx`.-      We take the `word/styles.xml`, `docProps/app.xml`,-      `word/theme/theme1.xml`, and `word/fontTable.xml` from-      `reference.docx`, ignoring everything else.  This should help-      with the corruption problems caused when different versions of-      Word resave the reference.docx and reorganize things.-    +  Made `--no-highlight` work properly.--  * EPUB writer--    + Don't add `dc:creator` tags if present in EPUB metadata.-    + Add `id="toc-title"` to `h1` in `nav.xhtml` (#799).-    + Don't put blank title page in reading sequence.-      Set `linear="no"` if no title block.  Addresses #797.-    + Download webtex images and include as data URLs.-      This allows you to use `--webtex` in creating EPUBs.-      Math with `--webtex` is automatically made self-contained.-    + In `data/epub.css`, removed highlighting styles (which-      are no longer needed, since styles are added by the HTML-      writer according to `--highlighting-style`).  Simplified-      margin fields.-    + If resource not found, skip it, as in Docx writer (#916).--  * RTF writer:--    + Properly handle characters above the 0000-FFFF range.-      Uses surrogate pairs.  Thanks to Hiromi Ishii for the patch.-    + Fixed regression with RTF table of contents.-    + Only autolink absolute URIs.  This fixes a regression, #830.--  * Markdown writer:--    + Only autolink absolute URIs.  This fixes a regression, #830.-    + Don't wrap attributes in fenced code blocks.-    + Write full metadata in MMD style title blocks.-    + Put multiple authors on separate lines in pandoc titleblock.-      Also, don't wrap long author entries, as new lines get treated-      as new authors.--  * `Text.Pandoc.Templates`:--    + Fixed bug retrieving default template for markdown variants.-    + Templates can now contain "record lookups" in variables;-      for example, `author.institution` will retrieve the `institution`-      field of the `author` variable.-    + More consistent behavior of `$for$`.  When `foo` is not a list,-      `$for(foo)$...$endfor$` should behave like $if(foo)$...$endif$.-      So if `foo` resolves to "", no output should be produced.-      See pandoc-templates#39.--  * Citation processing improvements (now part of pandoc-citeproc):--    + Fixed `endWithPunct` The new version correctly sees a sentence-      ending in '.)' as ending with punctuation.  This fixes a bug which-      led such sentences to receive an extra period at the end: '.).'.-      Thanks to Steve Petersen for reporting.-    + Don't interfere with Notes that aren't citation notes.-      This fixes a bug in which notes not generated from citations were-      being altered (e.g. first letter capitalized) (#898).-    + Only capitalize footnote citations when they have a prefix.-    + Changes in suffix parsing.  A suffix beginning with a digit gets 'p'-      inserted before it before passing to citeproc-hs, so that bare numbers-      are treated as page numbers by default.  A suffix not beginning with-      punctuation has a space added at the beginning (rather than a comma and-      space, as was done before for not-author-in-text citations).-      The result is that `\citep[23]{item1}` in LaTeX will be interpreted-      properly, with '23' treated as a locator of type 'page'.-    + Many improvements to citation rendering, due to fixes in citeproc-hs-      (thanks to Andrea Rossato).-    + Warnings are issued for undefined citations, which are rendered-      as `???`.-    + Fixed hanging behavior when locale files cannot be found.--  [template changes]--  * DocBook:  Use DocBook 4.5 doctype.--  * Org: '#+TITLE:' is inserted before the title.-    Previously the writer did this.--  * LaTeX:  Changes to make mathfont work with xelatex.-    We need the mathspec library, not just fontspec, for this.-    We also need to set options for setmathfont (#734).--  * LaTeX: Use `tex-ansi` mapping for `monofont`.-    This ensures that straight quotes appear as straight, rather than-    being treated as curly.  See #889.--  * Made `\includegraphics` more flexible in LaTeX template.-    Now it can be used with options, if needed.  Thanks to Bernhard Weichel.--  * LaTeX/Beamer: Added `classoption` variable.-    This is intended for class options like `oneside`; it may-    be repeated with different options.  (Thanks to Oliver Matthews.)--  * Beamer: Added `fonttheme` variable.  (Thanks to Luis Osa.)--  * LaTeX: Added `biblio-style` variable (#920).--  * DZSlides: title attribute on title section.--  * HTML5: add meta tag to allow scaling by user (Erik Evenson)--  [under-the-hood improvements]--  * Markdown reader:Improved strong/emph parsing, using the strategy of-    <https://github.com/jgm/Markdown>.  The new parsing algorithm requires-    no backtracking, and no keeping track of nesting levels.  It will give-    different results in some edge cases, but these should not affect normal-    uses.--  * Added `Text.Pandoc.Compat.Monoid`.-    This allows pandoc to compile with `base` < 4.5, where `Data.Monoid`-    doesn't export `<>`.  Thanks to Dirk Ullirch for the patch.--  * Added `Text.Pandoc.Compat.TagSoupEntity`.-    This allows pandoc to compile with `tagsoup` 0.13.x.-    Thanks to Dirk Ullrich for the patch.--  * Most of `Text.Pandoc.Readers.TeXMath` has been moved to the-    `texmath` module (0.6.4).  (This allows `pandoc-citeproc` to-    handle simple math in bibliography fields.)--  * Added `Text.Pandoc.Writers.Shared` for shared functions used-    only in writers.  `metaToJSON` is used in writers to create a-    JSON object for use in the templates from the pandoc metadata-    and variables.  `getField`, `setField`, and `defField` are-    for working with JSON template contexts.--  * Added `Text.Pandoc.Asciify` utility module.-    This exports functions to create ASCII-only versions of identifiers.--  * `Text.Pandoc.Parsing`--    + Generalized state type on `readWith` (API change).-    + Specialize readWith to `String` input. (API change).-    + In `ParserState`, replace `stateTitle`, `stateAuthors`, `stateDate`-      with `stateMeta` and `stateMeta'`.--  * `Text.Pandoc.UTF8`: use strict bytestrings in reading.  The use of lazy-     bytestrings seemed to cause problems using pandoc on 64-bit Windows-     7/8 (#874).--  * Factored out `registerHeader` from markdown reader, added to-    `Text.Pandoc.Parsing`.--  * Removed `blaze_html_0_5` flag, require `blaze-html` >= 0.5.-    Reason:  < 0.5 does not provide a monoid instance for Attribute,-    which is now needed by the HTML writer (#803).--  * Added `http-conduit` flag, which allows fetching https resources.-    It also brings in a large number of dependencies (`http-conduit`-    and its dependencies), which is why for now it is an optional flag-    (#820).--  * Added CONTRIBUTING.md.--  * Improved INSTALL instructions.--  * `make-windows-installer.bat`: Removed explicit paths for executables.--  * `aeson` is now used instead of `json` for JSON.--  * Set default stack size to 16M.  This is needed for some large-    conversions, esp. if pandoc is compiled with 64-bit ghc.--  * Various small documentation improvements.-    Thanks to achalddave and drothlis for patches.--  * Removed comment that chokes recent versions of CPP (#933).--  * Removed support for GHC version < 7.2, since pandoc-types now-    requires at least GHC 7.2 for GHC generics.---pandoc (1.11.1)--  * Markdown reader:--    + Fixed regression in which parentheses were lost in link URLs.-      Added tests.  Closes #786.-    + Better handling of unmatched double quotes in `--smart` mode.-      These occur frequently in fiction, since it is customary not to-      close quotes in dialogue if the speaker does not change between-      paragraphs.  The unmatched quotes now get turned into literal-      left double quotes. (No `Quoted` inline is generated, however.)-      Closes #99 (again).--  * HTML writer: Fixed numbering mismatch between TOC and sections.-    `--number-offset` now affects TOC numbering as well-    as section numbering, as it should have all along.  Closes #789.--  * Markdown writer: Reverted 1.11 change that caused citations to be rendered-    as markdown citations, even if `--bibliography` was specified, unless-    `citation` extension is disabled.  Now, formatted citations are always-    printed if `--bibliography` was specified.  If you want to reformat-    markdown keeping pandoc markdown citations intact, don't use-    `--bibliography`.  Note that citations parsed from LaTeX documents will-    be rendered as pandoc markdown citations when `--bibliography` is not-    specified.--  * ODT writer: Fixed regression leading to corrupt ODTs.-    This was due to a change in the `Show` instance for-    `Text.Pandoc.Pretty.Doc`.  Closes #780.--  * Fixed spacing bugs involving code block attributes in-    RST reader and Markdown writer. Closes #763.--  * Windows package:  Various improvements due to Fyodor Sheremetyev.--    + Automatically set installation path (Program Files or Local App Data).-    + Set system PATH environment variable when installing for all users.-    + Pandoc can installed for all users using the following command.-      `msiexec /i pandoc-1.11.msi ALLUSERS=1`.--  * Bumped QuickCheck version bound.--pandoc (1.11)--  * Added `--number-offset` option.  (See README for description.)--  * Added `--default-image-extension` option.  (See README for description.)--  * `--number-sections` behavior change: headers with class `unnumbered`-    will not be numbered.--  * `--version` now reports the default data directory.--  * `Text.Pandoc.Parsing` is no longer exposed. (API change.)--  * `Text.Pandoc.Highlighting` is no longer exposed. (API change.)--  * `Text.Pandoc.Shared`:  Changed type of `Element`.  `Sec` now includes-    a field for `Attr` rather than just `String`.  (API change.)--  * Added `markdown_github` as input format.  This was an accidental-    omission in 1.10.--  * Added `readerDefaultImageExtension` field to `ReaderOptions`.  (API-    change.)--  * Added `writerNumberOffset` field in `WriterOptions`. (API change.)--  * Beamer template:--    + Fixed captions with longtable.  Thanks to Joost Kremers.-    + Provide `\Oldincludegraphics` as in LaTeX template (Benjamin Bannier).--  * LaTeX template:--    + Load microtype after fonts.  Microtype needs to know-      what fonts are being used.  Thanks to dfc for the patch.-    + Set `secnumdepth` to 5 if `--number-sections` specified.-      This yields behavior equivalent to the other writers, numbering-      level 4 and 5 headers too.  Closes #753.--  * HTML reader:--    + Handle `<colgroup>` tag.-    + Preserve all header attributes.--  * LaTeX reader:--    + Parse `\hrule` as `HorizontalRule`.  Closes #746.-    + Parse starred variants of `\section` etc. as headers with-      attribute `unnumbered`.-    + Read optional attributes in `lstlisting` and `Verbatim` environments.-      We convert these to pandoc standard names, e.g. `numberLines`-      for `numbers=left`, `startFrom=100` from `firstnumber=100`.-    + Handle language attribute for lstlistings.-    + Better support for Verbatim and minted environments.  Closes #763.--  * Markdown reader:--    + `-` in an attribute context = `.unnumbered`.  The point of this-      is to provide a way to specify unnumbered headers in non-English-      documents.-    + Fixed bug parsing key/value attributes.  Parsing failed if you-      had an unquoted attribute immediately before the final '}'.-    + Make backslash escape work in attributes.-    + Fix title block parsing.  Now if `mmd_title_blocks` is specified,-      pandoc will parse a MMD title block if it sees one, even if-      `pandoc_title_blocks` is enabled.-    + Refactoring: `litChar` now includes entities, so we don't need-      to use `fromEntities` e.g. on titles.-    + Allow spaces around borders in pipe tables.  Closes #772.-    + Allow all punctuation in angle-bracket autolinks.  Previously-      things like `----` were disallowed, because the uri parser-      treated them as trailing punctuation.  Closes #768.-    + Make `implicit_header_references` work properly when-      headers are given explicit identifiers.-    + Check for tables before line blocks.  Otherwise some pipe-      tables get treated as line blocks.-    + Allow `&` in emails (for entities).-    + Properly handle entities in titles and links.  A markdown link-      `<http://g&ouml;ogle.com>` should be a link to `http://göogle.com`.-      Closes #723.--  * Textile reader:--    + Handle attributes on headers.--  * LaTeX reader:--    + Add `fig:` as title for images with captions.-      This is needed for them to be rendered as figures.  Closes #766.-    + Never emit an empty paragraph.  See #761.-    + Handle `\caption` for images in figures.  Closes #766.-    + Parse `\section*`, etc. as unnumbered sections.--  * HTML writer:--    + Support header attributes.  The attributes go on-      the enclosing `section` or `div` tag if `--section-divs` is specified.-    + Fixed a regression (only now noticed) in html+lhs output.-      Previously the bird tracks were being omitted.--  * LaTeX writer:--    + Omit lists with no items to avoid LaTeX errors.-    + Support line numbering with `--listings`.-      If `numberLines` class is present, we add `numbers=left`;-      if `startFrom` is present, we add `firstnumber=`. (#763)--  * ConTeXt writer:--    + Removed `\placecontent`.  This produced a duplicate toc,-      in conjunction with `\placelist`.-    + Use `\title`, `\subject` etc. for headers with-      `unnumbered` class.--  * Textile writer:--    + Support header attributes.--  * Markdown writer:--    + Use grid tables when needed, and if enabled.  Closes #740.-    + Render citations as pandoc-markdown citations.-      Previously citations were rendered as citeproc-formatted citations-      by default.  Now we render them as pandoc citations, e.g. `[@item1]`,-      unless the `citations` extension is disabled.-      If you still want formatted citations in your markdown output,-      use `pandoc -t markdown-citations`.--  * RST writer:--    + Support `:number-lines:` in code blocks.--  * Docx writer:--    + Better treatment of display math.  Display math inside a-      paragraph is now put in a separate paragraph, so it will render-      properly (centered and without extra blank lines around it).-      Partially addresses #742.-    + Content types and document rels xml files are now created from-      scratch, rather than being taken over from `reference.docx`.-      This fixes problems that arise when you edit the `reference.docx`-      with Word.-    + We also now encode mime types for each individual image rather-      than using defaults.  This should allow us to handle a wider-      range of image types (including PDF).   Closes #414.-    + Changed style names in `reference docx`.-      `FootnoteReference` -> `FootnoteRef`, `Hyperlink` -> `Link`.-      The old names got changed by Word when the `reference.docx` was-      edited.  Closes #414.--  * EPUB writer:--    + Fix section numbering.  Previously the numbering restarted from 1-      in each chapter (with `--number-sections`), though the numbers in-      the table of contents were correct.-    + Headers with "unnumbered" attribute are not numbered.  (Nor do they-      cause an increment in running numbering.) Section numbers now work-      properly, even when there is material before the first numbered section.-    + Include HTML TOC, even in epub2.  The TOC is included in `<spine>`,-      but `linear` is set to `no` unless the `--toc` option is specified.-      Include `<guide>` element in OPF.  This should allow the TOC to-      be useable in Kindles when converted with kindlegen. Closes #773.--  * `Text.Pandoc.Parsing`: Optimized `oneOfStringsCI`.-    This dramatically reduces the speed penalty that comes from enabling the-    `autolink_bare_uris` extension.  The penalty is still substantial (in one-    test, from 0.33s to 0.44s), but nowhere near what it used to be.-    The RST reader is also much faster now, as it autodetects URIs.--  * `Text.Pandoc.Shared`:  `hierarchicalize` will not number section-    with class "unnumbered".  Unnumbered sections get `[]` for their-    section number.--  * `Text.Pandoc.Pretty`:--    + Fixed `chomp` so it works inside `Prefixed` elements.-    + Changed `Show` instance so it is better for debugging.--  * `Text.Pandoc.ImageSize`:  Added `Pdf` to `ImageType`.--  * `Text.Pandoc.UTF8`:  Strip off BOM if present.  Closes #743.--  * Windows installer improvements:--    + The installer is now signed with a certificate (thanks to-      Fyodor Sheremetyev).-    + WiX is used instead of InnoSetup.  The installer is now a-      standard msi file.-    + The version number is now auto-detected, and need not be-      updated separately.--  * OSX installer improvements:--    + The package and pandoc executable are now signed with a-      certificate (thanks to Fyodor Sheremetyev).-    + RTF version of license is used.-    + Use full path for sysctl in `InstallationCheck` script (jonahbull).-      Closes #580.--  * Converted COPYING to markdown.--  * pandoc.cabal:  Require latest versions of highlighting-kate,-    texmath, citeproc-hs, zip-archive.--pandoc (1.10.1)--  * Markdown reader:  various optimizations, leading to a-    significant performance boost.--  * RST reader:  Allow anonymous form of inline links:-    `` `hello <url>`__ `` Closes #724.--  * Mediawiki reader: Don't require newlines after tables.-    Thanks to jrunningen for the patch. Closes #733.--  * Fixed LaTeX macro parsing.  Now LaTeX macro definitions are preserved-    when output is LaTeX, and applied when it is another format.-    Partially addresses #730.--  * Markdown and RST readers:  Added parser to `block` that skips blank-    lines.  This fixes a subtle regression involving grid tables with-    empty cells.  Also added test for grid table with empty cells.-    Closes #732.--  * RST writer:  Use `.. code:: language` for code blocks with language.-    Closes #721.--  * DocBook writer:  Fixed output for hard line breaks, adding a newline-    between `<literallayout>` tags.--  * Markdown writer:  Use an autolink when link text matches url.-    Previously we also checked for a null title, but this-    test fails for links produced by citeproc-hs in bibliographies.-    So, if the link has a title, it will be lost on conversion-    to an autolink, but that seems okay.--  * Markdown writer:  Set title, author, date variables as before.-    These are no longer used in the default template, since we use-    titleblock, but we set them anyway for those who use custom templates.--  * LaTeX writer:  Avoid extra space at start/end of table cell.-    Thanks to Nick Bart for the suggestion of using @{}.--  * `Text.Pandoc.Parsing`:--    + More efficient version of `anyLine`.-    + Type of `macro` has changed; the parser now returns `Blocks`-      instead of `Block`.--  * Relaxed old-time version bound, allowing 1.0.*.--  * Removed obsolete `hsmarkdown` script.  Those who need `hsmarkdown`-    should create a symlink as described in the README.--pandoc (1.10.0.5)--  * Markdown reader: Try `lhsCodeBlock` before `rawTeXBlock`.  Otherwise-    `\begin{code}...\end{code}` isn't handled properly in markdown+lhs.-    Thanks to Daniel Miot for noticing the bug and suggesting the fix.--  * Markdown reader: Fixed bug with headerless grid tables.-    The 1.10 code assumed that each table header cell contains exactly one-    block. That failed for headerless tables (0) and also for tables with-    multiple blocks in a header cell.  The code is fixed and tests provided.-    Thanks to Andrew Lee for pointing out the bug.--  * Markdown reader: Fixed regressions in fenced code blocks. Closes #722.--    + Tilde code fences can again take a bare language string-      (`~~~ haskell`), not just curly-bracketed attributes-      (`~~~ {.haskell}`).-    + Backtick code blocks can take the curly-bracketed attributes.-    + Backtick code blocks don't *require* a language.-    + Consolidated code for the two kinds of fenced code blocks.--  * LaTeX template: Use `\urlstyle{same}` to avoid monospace URLs.--  * Markdown writer: Use proportional font for email autolinks with-    obfuscation.  Closes #714.--  * Corrected name of `blank_before_blockquote` in README.  Closes #718.--  * `Text.Pandoc.Shared`: Fixed bug in `uri` parser.-    The bug prevented an autolink at the end of a string (e.g.-    at the end of a line block line) from counting as a link.  Closes #711.--  * Use the `hsb2hs` preprocessor instead of TH for embed_data_files.-    This should work on Windows, unlike the TH solution with-    file-embed.--  * Eliminated use of TH in test suite.--  * Added `Text.Pandoc.Data` (non-exported) to hold the association-    list of embedded data files, if the `embed_data_files` flag is selected.-    This isolates the code that needs special treatment with file-embed or-    `hsb2hs`.--  * Changes to `make-windows-installer.bat`.--    + Exit batch file if any of the cabal-dev installs fail.-    + There's no longer any need to reinstall `highlighting-kate`.-    + Don't start with a `cabal update`; leave that to the user.-    + Force reinstall of pandoc.--  * Fixed EPUB writer so it builds with blaze-html 0.4.x. Thanks to-    Jens Petersen.--pandoc (1.10.0.4)--  * Fixed bug with escaped % in LaTeX reader. Closes #710.--pandoc (1.10.0.3)--  * Added further missing fb2 tests to cabal file.--pandoc (1.10.0.2)--  * Added fb2 tests to cabal file's extra-source-files.--pandoc (1.10.0.1)--  * Bump version bounds on test-framework packages.--pandoc (1.10)--  [new features]--  * New input formats:  `mediawiki` (MediaWiki markup).--  * New output formats:  `epub3` (EPUB v3 with MathML),-    `fb2` (FictionBook2 ebooks).--  * New `--toc-depth` option, specifying how many levels of-    headers to include in a table of contents.--  * New `--epub-chapter-level` option, specifying the header-    level at which to divide EPUBs into separate files.-    Note that this normally affects only performance, not the-    visual presentation of the EPUB in a reader.--  * Removed the `--strict` option.  Instead of using `--strict`,-    one can now use the format name `markdown_strict` for either input-    or output.  This gives more fine-grained control that `--strict`-    did, allowing one to convert from pandoc's markdown to strict-    markdown or vice versa.--  * It is now possible to enable or disable specific syntax-    extensions by appending them (with `+` or `-`) to the writer-    or reader name.  For example,--        pandoc -f markdown-footnotes+hard_line_breaks--    disables footnotes and enables treating newlines as hard-    line breaks.  The literate Haskell extensions are now implemented-    this way as well, using either `+lhs` or `+literate_haskell`.-    For a list of extension names, see the README under-    "Pandoc's Markdown."--  * The following aliases have been introduced for specific-    combinations of markdown extensions:  `markdown_phpextra`,-    `markdown_github`, `markdown_mmd`, `markdown_strict`.  These aliases-    work just like regular reader and writer names, and can be modified-    with extension modifiers as described above. (Note that conversion-    from one markdown dialect to another does not work perfectly,-    because there are differences in markdown parsers besides-    just the extensions, and because pandoc's internal document model is-    not rich enough to capture all of the extensions.)--  * New `--html-q-tags` option.  The previous default was to use `<q>`-    tags for smart quotes in HTML5.  But `<q>` tags are also valid HTML4.-    Moreover, they are not a robust way of typesetting quotes, since-    some user agents don't support them, and some CSS resets (e.g.-    bootstrap) prevent pandoc's quotes CSS from working properly.-    We now just insert literal quote characters by default in both-    `html` and `html5` output, but this option is provided for-    those who still want `<q>` tags.--  * The markdown reader now prints warnings (to stderr) about-    duplicate link and note references.  Closes #375.--  * Markdown syntax extensions:--    + Added pipe tables.  Thanks to François Gannaz for the initial patch.-      These conform to PHP Markdown Extra's pipe table syntax. A subset-      of org-mode table syntax is also supported, which means that you can-      use org-mode's nice table editor to create tables.--    + Added support for RST-style line blocks. These are-      useful for verse and addresses.--    + Attributes can now be specified for headers, using the same-      syntax as in code blocks.  (However, currently only the-      identifier has any effect in most writers.)  For example,--            # My header {#foo}--            See [the header above](#foo).--    + Pandoc will now act as if link references have been defined-      for all headers without explicit identifiers.-      So, you can do this:--            # My header--            Link to [My header].-            Another link to [it][My header].--      Closes #691.--  * LaTeX reader:--    + Command macros now work everywhere, including non-math.-      Environment macros still not supported.-    + `\input` now works, as well as `\include`.  TEXINPUTS is used.-      Pandoc looks recursively into included files for more included files.--  [behavior changes]--  * The Markdown reader no longer puts the text of autolinks in a-    `Code` inline.  This means that autolinks will no longer appear-    in a monospace font.--  * The character `/` can now appear in markdown citation keys.--  * HTML blocks in strict_markdown are no longer required to begin-    at the left margin.  Technically this is required, according to-    the markdown syntax document, but `Markdown.pl` and other markdown-    processors are more liberal.--  * The `-V` option has been changed so that if there are duplicate-    variables, those specified later on the command line take precedence.--  * Tight lists now work in LaTeX and ConTeXt output.--  * The LaTeX writer no longer relien on the `enumerate` package.-    Instead, it uses standard LaTeX commands to change the list numbering-    style.--  * The LaTeX writer now uses `longtable` instead of `ctable`. This allows-    tables to be split over page boundaries.--  * The RST writer now uses a line block to render paragraphs containing-    linebreaks (which previously weren't supported at all).--  * The markdown writer now applies the `--id-prefix` to footnote IDs.-    Closes #614.--  * The plain writer no longer uses backslash-escaped line breaks-    (which are not very "plain").--  * `Text.Pandoc.UTF8`: Better error message for invalid UTF8.-    Read bytestring and use `Text`'s decodeUtf8 instead of using-    `System.IO.hGetContents`.  This way you get a message saying-    "invalid UTF-8 stream" instead of "invalid byte sequence."-    You are also told which byte caused the problem.--  * Docx, ODT, and EPUB writers now download images specified by a URL-    instead of skipping them or raising an error.--  * EPUB writer:--    + The default CSS now left-aligns headers by default, instead of-      centering.  This is more consistent with the rest of the writers.-    + A proper multi-level table of contents is now used in `toc.ncx`.-      There is no longer a subsidiary table of contents at the beginning-      of each chapter.-    + Code highlighting now works by default.-    + Section divs are used by default for better semantic markup.-    + The title is used instead of "Title Page" in the table of contents.-      Otherwise we have a hard-coded English string, which looks-      strange in ebooks written in other languages.  Closes #572.--  * HTML writer:--    + Put mathjax in span with class "math".  Closes #562.-    + Put citations in a span with class "citation." In HTML5, also include-      a `data-cite` attribute with a space-separated list of citation-      keys.--  * `Text.Pandoc.UTF8`:  use universalNewlineMode in reading.-    This treats both `\r\n` and `\n` as `\n` on input, no matter-    what platform we're running on.--  * Citation processing is now done in the Markdown and LaTeX-    readers, not in `pandoc.hs`.  This makes it easier for library users-    to use citations.--  [template changes]--  * HTML: Added css to template to preserve spaces in `<code>` tags.-    Thanks to Dirk Laurie.--  * Beamer:  Remove English-centric strings in section pages.-    Section pages used to have "Section" and a number as well as the-    section title. Now they just have the title.  Similarly for part-    and subsection.  Closes #566.--  * LaTeX, ConTeXt: Added papersize variable.--  * LaTeX, Beamer templates: Use longtable instead of ctable.--  * LaTeX, Beamer templates: Don't require 'float' package for tables.-    We don't actually seem to use the '[H]' option.--  * LaTeX:  Use `upquote` package if it is available.  This fixes-    straight quotes in verbatim environments.--  * Markdown, plain: Fixed titleblock so it is just a single string.-    Previously separate title, author, and date variables were used,-    but this didn't allow different kinds of title blocks.--  * EPUB:--    + Rationalized templates.  Previously there were three different-      templates involved in epub production. There is now just one-      template, `default.epub` or `default.epub3`. It can now be-      overridden using `--template`, just like other templates.-      The titlepage is now folded into the default template.-      A `titlepage` variable selects it.-    + UTF-8, lang tag, meta tags, title element.--  * Added scale-to-width feature to beamer template--  [API changes]--  * `Text.Pandoc.Definition`: Added `Attr` field to `Header`.-    Previously header identifers were autogenerated by the writers.-    Now they are added in the readers (either automatically or explicitly).--  * `Text.Pandoc.Builder`:--    + `Inlines` and `Blocks` are now synonyms for `Many Inline` and-      `Many Block`.  `Many` is a newtype wrapper around `Seq`, with-      custom Monoid instances for `Many Inline` and `Many Block.  This-      allows `Many` to be made an instance of `Foldable` and `Traversable`.-    + The old `Listable` class has been removed.-    + The module now exports `isNull`, `toList`, `fromList`.-    + The old `Read` and `Show` instances have been removed; derived-      instances are now used.-    + Added `headerWith`.--  * The readers now take a `ReaderOptions` rather than a `ParserState`-    as a parameter.  Indeed, not all parsers use the `ParserState` type;-    some have a custom state.  The motivation for this change was to separate-    user-specifiable options from the accounting functions of parser state.--  * New module `Text.Pandoc.Options`.  This includes the `WriterOptions`-    formerly in `Text.Pandoc.Shared`, and its associated-    data types.  It also includes a new type `ReaderOptions`, which-    contains many options formerly in `ParserState`, and its associated-    data types:--    + `ParserState.stateParseRaw` -> `ReaderOptions.readerParseRaw`.-    + `ParserState.stateColumns` -> `ReaderOptions.readerColumns`.-    + `ParserState.stateTabStop` -> `ReaderOptions.readerTabStop`.-    + `ParserState.stateOldDashes` -> `ReaderOptions.readerOldDashes`.-    + `ParserState.stateLiterateHaskell` -> `ReaderOptions.readerLiterateHaskell`.-    + `ParserState.stateCitations` -> `ReaderOptions.readerReferences`.-    + `ParserState.stateApplyMacros` -> `ReaderOptions.readerApplyMacros`.-    + `ParserState.stateIndentedCodeClasses` ->-      `ReaderOptions.readerIndentedCodeClasses`.-    + Added `ReaderOptions.readerCitationStyle`.--  * `WriterOptions` now includes `writerEpubVersion`, `writerEpubChapterLevel`,-    `writerEpubStylesheet`, `writerEpubFonts`, `writerReferenceODT`,-    `writerReferenceDocx`, and `writerTOCDepth`.  `writerEPUBMetadata` has-    been renamed `writerEpubMetadata` for consistency.--  * Changed signatures of `writeODT`, `writeDocx`, `writeEPUB`, since they no-    longer stylesheet, fonts, reference files as separate parameters.--  * Removed `writerLiterateHaskell` from `WriterOptions`, and-    `readerLiterateHaskell` from `ReaderOptions`.  LHS is now handled-    by an extension (`Ext_literate_haskell`).--  * Removed deprecated `writerXeTeX`.--  * Removed `writerStrict` from `WriterOptions`.  Added `writerExtensions`.-    Strict is now handled through extensions.--  * `Text.Pandoc.Options` exports `pandocExtensions`, `strictExtensions`,-    `phpMarkdownExtraExtensions`, `githubMarkdownExtensions`,-    and `multimarkdownExtensions`, as well as the `Extensions` type.--  * New `Text.Pandoc.Readers.MediaWiki` module, exporting-    `readMediaWiki`.--  * New `Text.Pandoc.Writers.FB2` module, exporting `writeFB2`-    (thanks to Sergey Astanin).--  * `Text.Pandoc`:--    + Added `getReader`, `getWriter` to `Text.Pandoc`.-    + `writers` is now an association list `(String, Writer)`.-      A `Writer` can be a `PureStringWriter`, an `IOStringWriter`, or-      an `IOByteStringWriter`.  ALL writers are now in the 'writers'-      list, including the binary writers and FB2 writer.  This allows-      code in `pandoc.hs` to be simplified.-    + Changed type of `readers`, so all readers are in IO.-      Users who want pure readers can still get them form the reader-      modules; this just affects the function `getReader` that looks up-      a reader based on the format name.  The point of this change is to-      make it possible to print warnings from the parser.--  * `Text.Pandoc.Parsing`:--    + `Text.Parsec` now exports all Parsec functions used in pandoc code.-      No other module directly imports Parsec.  This will make it easier-      to change the parsing backend in the future, if we want to.-    + `Text.Parsec` is used instead of `Text.ParserCombinators.Parsec`.-    + Export the type synonym `Parser`.-    + Export `widthsFromIndices`, `NoteTable'`, `KeyTable'`, `Key'`, `toKey'`,-     `withQuoteContext`, `singleQuoteStart`, `singleQuoteEnd`,-     `doubleQuoteStart`, `doubleQuoteEnd`, `ellipses`, `apostrophe`,-     `dash`, `nested`, `F(..)`, `askF`, `asksF`, `runF`, `lineBlockLines`.-    + `ParserState` is no longer an instance of `Show`.-    + Added `stateSubstitutions` and `stateWarnings` to `ParserState`.-    + Generalized type of `withQuoteContext`.-    + Added `guardEnabled`, `guardDisabled`, `getOption`.-    + Removed `failIfStrict`.-    + `lookupKeySrc` and `fromKey` are no longer exported.--  * `Data.Default` instances are now provided for `ReaderOptions`,-    `WriterOptions`, and `ParserState`.  `Text.Pandoc` re-exports `def`.-    Now you can use `def` (which is re-exported by `Text.Pandoc`) instead-    of `defaultWriterOptions` (which is still defined).  Closes #546.--  * `Text.Pandoc.Shared`:--    + Added `safeRead`.-    + Renamed `removedLeadingTrailingSpace` to `trim`,-      `removeLeadingSpace` to `triml`, and `removeTrailingSpace` to `trimr`.-    + Count `\r` as space in `trim` functions.-    + Moved `renderTags'` from HTML reader and `Text.Pandoc.SelfContained`-      to `Shared`.-    + Removed `failUnlessLHS`.-    + Export `compactify'`, formerly in Markdown reader.-    + Export `isTightList`.-    + Do not export `findDataFile`.-    + `readDataFile` now returns a strict ByteString.-    + Export `readDataFileUTF8` which returns a String, like the-      old `readDataFile`.-    + Export `fetchItem` and `openURL`.--  * `Text.Pandoc.ImageSize`: Use strict, not lazy bytestrings.-    Removed `readImageSize`.--  * `Text.Pandoc.UTF8`: Export `encodePath`, `decodePath`,-     `decodeArg`, `toString`, `fromString`, `toStringLazy`,-     `fromStringLazy`.--  * `Text.Pandoc.UTF8` is now an exposed module.--  * `Text.Pandoc.Biblio`:--    + csl parameter now a `String` rather than a `FilePath`.-    + Changed type of `processBiblio`.  It is no longer in the IO monad.-      It now takes a `Maybe Style` argument rather than parameters for CSL-      and abbrev filenames.  (`pandoc.hs` now calls the functions to parse-      the style file and add abbreviations.)--  * Markdown reader now exports `readMarkdownWithWarnings`.--  * `Text.Pandoc.RTF` now exports `writeRTFWithEmbeddedImages` instead of-    `rtfEmbedImage`.--  [bug fixes]--  * Make `--ascii` work properly with `--self-contained`.  Closes #568.--  * Markdown reader:--    + Fixed link parser to avoid exponential slowdowns.  Closes #620.-      Previously the parser would hang on input like this:--            [[[[[[[[[[[[[[[[[[hi--      We fixed this by making the link parser parser characters-      between balanced brackets (skipping brackets in inline code spans),-      then parsing the result as an inline list.  One change is that--            [hi *there]* bud](/url)--      is now no longer parsed as a link.  But in this respect pandoc behaved-      differently from most other implementations anyway, so that seems okay.--    + Look for raw html/latex blocks before tables.-      Otherwise the following gets parsed as a table:--            \begin{code}-            ---------------            -- My comment.-            \end{code}--      Closes #578.--  * RST reader:--    + Added support for `:target:` on `.. image::` blocks-      and substitutions.-    + Field list fixes:--        - Fixed field lists items with body beginning after a new line-          (Denis Laxalde).-        - Allow any char but ':' in names of field lists in RST reader-          (Denis Laxalde).-        - Don't allow line breaks in field names.-        - Require whitespace after field list field names.-        - Don't create empty definition list for metadata field lists.-          Previously a field list consisting only of metadata fields (author,-          title, date) would be parsed as an empty DefinitionList, which is-          not legal in LaTeX and not needed in any format.--    + Don't recognize inline-markup starts inside words.-      For example, `2*2 = 4*1` should not contain an emphasized-      section.  Added test case for "Literal symbols".  Closes #569.-    + Allow dashes as separator in simple tables.  Closes #555.-    + Added support for `container`, `compound`, `epigraph`,-      `rubric`, `highlights`, `pull-quote`.-    + Added support for `.. code::`.-    + Made directive labels case-insensitive.-    + Removed requirement that directives begin at left margin.-      This was (correctly) not in earlier releases; docutils doesn't-      make the requirement.-    + Added support for `replace::` and `unicode::` substitutions.-    + Ignore unknown interpreted roles.-    + Renamed image parser to `subst`, since it now handles all-      substitution references.--  * Textile reader:--    + Allow newlines before pipes in table.  Closes #654.-    + Fixed bug with list items containing line breaks.-      Now pandoc correctly handles hard line breaks inside list items.-      Previously they broke list parsing.-    + Implemented comment blocks.-    + Fixed bug affected words ending in hyphen.-    + Properly handle links with surrounding brackets.-      Square brackets need to be used when the link isn't surrounded by-      spaces or punctuation, or when the URL ending may be ambiguous.-      Closes #564.-    + Removed nullBlock.  Better to know about parsing problems than-      to skip stuff when we get stuck.-    + Allow ID attributes on headers.-    + Textile reader:  Avoid parsing dashes as strikeout.-      Previously the input--            text---            text---            text---            text----      would be parsed with strikeouts rather than dashes. This fixes-      the problem by requiring that a strikeout delimiting - not be-      followed by a -.  Closes #631.-    + Expanded list of `stringBreakers`.-      This fixes a bug on input like "(_hello_)" which should-      be a parenthesized emphasized "hello".-      The new list is taken from the PHP source of textile 2.4.-    + Fixed autolinks.  Previously the textile reader and writer-      incorrectly implented RST-style autolinks for URLs and email-      addresses.  This has been fixed.  Now an autolink is done this way:-      `"$":http://myurl.com`.-    + Fixed footnotes bug in textile.  This affected notes occuring-      before punctuation, e.g. `foo[1].`.  Closes #518.--  * LaTeX reader:--    + Better handling of citation commands.-    + Better handling of `\noindent`.-    + Added a 'try' in rawLaTeXBlock, so we can handle `\begin` without `{`.-      Closes #622.-    + Made `rawLaTeXInline` try to parse block commands as well.  This-      is usually what we want, given how `rawLaTeXInline` is used in-      the markdown and textile readers.  If a block-level LaTeX command-      is used in the middle of a paragraph (e.g. `\subtitle` inside a title),-      we can treat it as raw inline LaTeX.-    + Handle \slash command.  Closes #605.-    + Basic `\enquote` support.-    + Fixed parsing of paragraphs beginning with a group.  Closes #606.-    + Use curly quotes for bare straight quotes.-    + Support obeylines environment.  Closes #604.-    + Guard against "begin", "end" in inlineCommand and-      blockCommand.-    + Better error messages for environments.  Now it should tell you that-      it was looking for \end{env}, instead of giving "unknown parse error."--  * HTML reader:--    + Added HTML 5 tags to list of block-level tags.-    + HTML reader: Fixed bug in `htmlBalanced`, which-      caused hangs in parsing certain markdown input using-      strict mode.-    + Parse `<q>` as `Quoted DoubleQuote`.-    + Handle nested `<q>` tags properly.-    + Modified `htmlTag` for fewer false positives.-      A tag must start with `<` followed by `!`,`?`, `/`, or a letter.-      This makes it more useful in the wikimedia and markdown parsers.--  * DocBook reader: Support title in "figure" element.  Closes #650.--  * MediaWiki writer:--    + Remove newline after `<br/>` in translation of `LineBreak`-      There's no particular need for a newline (other than making the-      generated MediaWiki source look nice to a human), and in fact-      sometimes it is incorrect: in particular, inside an enumeration, list-      items cannot have embedded newline characters. (Brent Yorgey)-    + Use `<code>` not `<tt>` for Code.--  * Man writer: Escape `-` as `\-`.-    Unescaped `-`'s become hyphens, while `\-`'s are left as ascii minus-    signs.  That is preferable for use with command-line options.  See-    <http://lintian.debian.org/tags/hyphen-used-as-minus-sign.html>.  Thanks-    to Andrea Bolognani for bringing the issue to our attention.--  * RST writer:--    + Improved line block output. Use nonbreaking spaces for-      initial indent (otherwise lost in HTML and LaTeX).-      Allow multiple paragraphs in a single line block.-      Allow soft breaks w continuations in line blocks.-    + Properly handle images with no alt text.  Closes #678.-    + Fixed bug with links with duplicate text.  We now (a) use anonymous-      links for links with inline URLs, and (b) use an inline link instead-      of a reference link if the reference link would require a label that-      has already been used for a different link.  Closes #511.-    + Fixed hyperlinked images. Closes #611. Use `:target:`-      field when you have a simple linked image.-    + Don't add `:align: center` to figures.--  * Texinfo writer:  Fixed internal cross-references.-    Now we insert anchors after each header, and use `@ref` instead of `@uref`-    for links.  Commas are now escaped as `@comma{}` only when needed;-    previously all commas were escaped.  (This change is needed, in part,-    because `@ref` commands must be followed by a real comma or period.) Also-    insert a blank line in from of `@verbatim` environments.--  * DocBook writer:--    + Made --id-prefix work in DocBook as well as HTML.-      Closes #607.-    + Don't include empty captions in figures.  Closes #581.--  * LaTeX writer:--    + Use `\hspace*` for nonbreaking space after line break,-      since `~` spaces after a line break are just ignored.-      Closes #687.-    + Don't escape `_` in URLs or hyperref identifiers.-    + Properly escape strings inside \url{}.  Closes #576.-    + Use `[fragile]` only for slides containing code rendered-      using listings. Closes #649.-    + Escape `|` as `\vert` in LaTeX math.  This avoids a clash with-      highlighting-kate's macros, which redefine `|` as a short verbatim-      delimiter.  Thanks to Björn Peemöller for raising this issue.-    + Use minipage rather than parbox for block containers in tables.-      This allows verbatim code to be included in grid tables.-      Closes #663.-    + Prevent paragraphs containing only linebreaks or spaces.--  * HTML writer:--    + Included `highlighting-css` for code spans, too.-      Previously it was only included if used in a code block.  Closes #653.-    + Improved line breaks with `<dd>` tags.  We now put a newline between-      `</dd>` and `<dd>` when there are multiple definitions.-    + Changed mathjax cdn url so it doesn't use https.  (This caused-      problems when used with `--self-contained`.) See #609.--  * EPUB writer:--    + `--number-sections` now works properly.-    + Don't strip meta and link elements in epub metadata.-      Patch from aberrancy. Closes #589.-    + Fixed a couple validation bugs.-    + Use ch001, ch002, etc. for chapter filenames.  This improves sorting-      of chapters in some readers, which apparently sort ch2 after ch10.-      Closes #610.--  * ODT writer: properly set title property (Arlo O'Keeffe).--  * Docx writer:--    + Fixed bug with nested lists.  Previously a list like--            1. one-                - a-                - b-            2. two--      would come out with a bullet instead of "2."-      Thanks to Russell Allen for reporting the bug.-    + Use `w:cr` in `w:r` instead of `w:br` for linebreaks.-      This seems to fix a problem viewing pandoc-generated-      docx files in LibreOffice.-    + Use integer ids for bookmarks.  Closes #626.-    + Added nsid to abstractNum elements.  This helps when merging-      word documents with numbered or bulleted lists.  Closes #627.-    + Use separate footnotes.xml for notes.-      This seems to help LibreOffice convert the file, even though-      it was valid docx before.  Closes #637.-    + Use rIdNN identifiers for r:embed in images.-    + Avoid reading image files again when we've already processed them.-    + Fixed typo in `referenc.docx` that prevented image captions from-      working. Thanks to Huashan Chen.--  * `Text.Pandoc.Parsing`:--    + Fixed bug in `withRaw`, which didn't correctly handle the case-      where nothing is parsed.-    + Made `emailAddress` parser more correct.  Now it is based on RFC 822,-      though it still doesn't implement quoted strings in email addresses.-    + Revised URI parser.  It now allows many more schemes, allows-      uppercase URIs, and better handles trailing punctuation and-      trailing slashes in bare URIs.  Added many tests.-    + Simplified and improved singleQuoteStart.  This makes `'s'`, `'l'`,-      etc. parse properly.  Formerly we had some English-centric heuristics,-      but they are no longer needed. Closes #698.--  * `Text.Pandoc.Pretty`:  Added wide punctuation range to `charWidth`.-    This fixes bug with Chinese commas in markdown and reST tables, and-    a bug that caused combining characters to be dropped.--  * `Text.Pandoc.MIME`: Added MIME types for .wof and .eot.  Closes #640.--  * `Text.Pandoc.Biblio`:--    + Run `mvPunc` and `deNote` on metadata too.-      This fixed a bug with notes on titles using footnote styles.-    + Fixed bug in fetching CSL files from CSL data directory.--  * `pandoc.hs`:  Give correct value to `writerSourceDirectory` when a URL-    is provided.  It should be the URL up to the path.--  * Fixed/simplified diff output for tests.-    Biblio: Make sure mvPunc and deNote run on metadata too.-    This fixed a bug with notes on titles using footnote styles.--  [under the hood improvements]--  * We no longer depend on `utf8-string`.  Instead we use functions-    defined in `Text.Pandoc.UTF8` that use `Data.Text`'s conversions.--  * Use `safeRead` instead of using `reads` directly (various modules).--  * "Implicit figures" (images alone in a paragraph) are now handled-    differently.  The markdown reader gives their titles the prefix `fig:`; the-    writers look for this before treating the image as a figure.  Though this-    is a bit of a hack, it has two advantages: (i) implicit figures can be-    limited to the markdown reader, and (ii) they can be deactivated by turning-    off the `implicit_figures` extension.--  * `catch` from `Control.Exception` is now used instead of the-    old Preface `catch`.--  * `Text.Pandoc.Shared`:  Improved algorithm for `normalizeSpaces`-    and `oneOfStrings` (which is now non-backtracking).--  * `Text.Pandoc.Biblio`: Remove workaround for `toCapital`.-    Now citeproc-hs is fixed upstream, so this is no longer needed.-    Closes #531.--  * Textile reader: Improved speed of `hyphenedWords`.-    This speeds up the textile  reader by about a factor of 4.--  * Use `Text.Pandoc.Builder` in RST reader, for more flexibility,-    better performance, and automatic normalization.--  * Major rewrite of markdown reader:--    + Use `Text.Pandoc.Builder` instead of lists.  This also-      means that everything is normalized automatically.-    + Move to a one-pass parsing strategy, returning values in the reader-      monad, which are then run (at the end of parsing) against the final-      parser state.--  * In HTML writer, we now use `toHtml` instead of pre-escaping.-    We work around the problem that blaze-html unnecessarily escapes `'`-    by pre-escaping just the `'` characters, instead of the whole string.-    If blaze-html later stops escaping `'` characters, we can simplify-    `strToHtml` to `toHtml`.  Closes #629.--  * Moved code for embedding images in RTFs from `pandoc.hs` to the-    RTF writer (which now exports `writeRTFWithEmbeddedImages`).--  * Moved citation processing from `pandoc.hs` into the readers.-    This makes things more convenient for library users.--  * The man pages are now built by an executable `make-pandoc-man-pages`,-    which has its own stanza in the cabal file so that dependencies can be-    handled by Cabal. Special treatment in `Setup.hs` ensures that this-    executable never gets installed; it is only used to create the man pages.--  * The cabal file has been modified so that the pandoc library is used-    in building the pandoc executable.  (This required moving `pandoc.hs`-    from `src` to `.`.)  This cuts compile time in half.--  * `-O2` is no longer used in building pandoc.  The performance improvement-    it yields is so slight that it is not worth it.  (Measured with-    benchmarks on ghc 7.4.)--  * The `executable` and `library` flags have been removed.--  * `-threaded` has been removed from ghc-options.--  * Version bounds of dependencies have been raised, and the-    `blaze_html_0_5` flag now defaults to True.  Pandoc now compiles on-    GHC 7.6.--  * We now require base >= 4.2.--  * Integrated the benchmark program into cabal.  One can now do:--        cabal configure --enable-benchmarks && cabal build-        cabal bench --benchmark-option='markdown' --benchmark-option='-s 20'--    The benchmark now uses README + testsuite, so benchmark results-    from older versions aren't comparable.--  * Integrated test suite with cabal.-    To run tests, configure with `--enable-tests`, then `cabal test`.-    You can specify particular tests using `--test-options='-t markdown'`.-    No output is shown unless tests fail.  The Haskell test modules-    have been moved from `src/` to `tests/`.--  * Moved all data files and templates to the `data/` subdirectory.--  * Added an `embed_data_files` cabal flag.  This causes all-    data files to be embedded in the binary, so that the binary-    is self-sufficient and can be relocated anywhere, copied on-    a USB key, etc.  The Windows installer now uses this.-    (Since we no longer have the option to build the executable-    without the library, this is the only way to get a relocatable-    binary on Windows.)--  * Removed pcre3.dll from windows package.-    It isn't needed unless highlighting-kate is compilled with the-    `pcre-light` flag. By default, regex-prce-builtin is used.---pandoc (1.9.4.2)--  * Don't encode/decode file paths if base >= 4.4.-    Prior to base 4.4, filepaths and command line arguments were treated-    as unencoded lists of bytes, not unicode strings, so we had to work-    around that by encoding and decoding them. This commit adds CPP-    checks for the base version that intelligibly enable encoding/decoding-    when needed. Fixes a bug with multilingual filenames when pandoc was-    compiled with ghc 7.4 (#540).--  * Don't generate an empty H1 after hrule slide breaks.-    We now use a slide-level header with contents `[Str "\0"]` to mark-    an hrule break.  This avoids creation of an empty H1 in these-    contexts.  Closes #484.--  * Docbook reader: Added support for "bold" emphasis.  Thanks to Mauro Bieg.--  * In make_osx_package.sh, ensure citeproc-hs is built with the-    embed_data_files flag.--  * MediaWiki writer: Avoid extra blank lines after sublists (Gavin Beatty).--  * ConTeXt writer: Don't escape `&`, `^`, `<`, `>`, `_`,-    simplified escapes for `}` and `{` to `\{` and `\}` (Aditya Mahajan).--  * Fixed handling of absolute URLs in CSS imports with `--self-contained`.-    Closes #535.--  * Added webm to mime types. Closes #543.--  * Added some missing exports and tests to the cabal file-    (Alexander V Vershilov).--  * Compile with `-rtsopts` and `-threaded` by default.--pandoc (1.9.4.1)--  * Markdown reader: Added `cf.` and `cp.` to list of likely abbreviations.--  * LaTeX template: Added `linkcolor`, `urlcolor` and `links-as-notes`-    variables.  Make TOC links black.--  * LaTeX template improvements.--    + Don't print date unless one is given explicitly in the document.-    + Simplified templates.-    + Use fontenc [T1] by default, and lmodern.-    + Use microtype if available.--  * Biblio:--    + Add comma to beginning of bare suffix, e.g. `@item1 [50]`.-      Motivation: `@item1 [50]` should be as close as possible to-      `[@item1, 50]`.-    + Added workaround for a bug in citeproc-hs 0.3.4 that causes footnotes-      beginning with a citation to be empty.  Closes #531.--  * Fixed documentation on mixed lists.  Closes #533.--pandoc (1.9.4)--  * Simplified `Text.Pandoc.Biblio` and fixed bugs with citations inside-    footnotes and captions.  We now handle note citations by inserting-    footnotes during initial citation processing, and doing a separate-    pass later to remove notes inside notes.--  * Added 'zenburn' highlight style from highlighting-kate.--  * Added Slideous writer. Slideous is an HTML + javascript slide show-    format, similar to Slidy, but works with IE 7. (Jonas Smedegaard)--  * LaTeX writer:--    + Ensure we don't have extra blank lines at ends of cells.-      This can cause LaTeX errors, as they are interpreted as new paragraphs.-    + More consistent interblock spacing.-    + Require highlighting-kate >= 0.5.1, for proper highlighted inline-      code in LaTeX.  Closes #527.-    + Ensure that a Verbatim at the end of a footnote is followed by-      a newline. (Fixes a regression in the previous version.)-    + In default template, use black for internal links and TOC.-      Added commented-out code to use footnotes for links, as would-      be suitable in print output.--  * Beamer writer:  When `--incremental` is used, lists inside-    a block quote should appear all at once.  (This makes Beamer-    output consistent with the HTML slide show formats.)--  * ConTeXt writer:--    + Escape `%` as `\letterpercent{}` not `\letterpercent `,-      to avoid gobbling spaces after the `%` sign.-    + Ensure space after `\stopformula`.--  * Markdown writer:--    + Use `:` form instead of `~` in definition lists, for better-      compatibility with other markdown implementations.-    + Don't wrap the term, because it breaks definition lists.-    + Use a nonzero space to prevent false recognition-      of list marker in ordered lists.  Closes #516.--  * Org writer: Add space before language name.  Closes #523.--  * Docx writer: Simplified bullet characters so they work properly-    with Word 2007. Closes #520.--  * LaTeX reader: Support `\centerline`.--  * RST reader:  handle figures.  Closes #522.--  * Textile reader: fix for `<notextile>` and `==`.  Closes #517.-    (Paul Rivier)--pandoc (1.9.3)--  * Fixed bug in `fromEntities`.  The previous version would turn-    `hi & low you know;` into `hi &`.--  * HTML reader:--    + Don't skip nonbreaking spaces.-      Previously a paragraph containing just `&nbsp;` would be rendered-      as an empty paragraph. Thanks to Paul Vorbach for pointing out the bug.-    + Support `<col>` and `<caption>` in tables. Closes #486.--  * Markdown reader:--    + Don't recognize references inside delimited code blocks.-    + Allow list items to begin with lists.--  * Added basic docbook reader (John MacFarlane and Mauro Bieg).--  * LaTeX reader:--    + Handle `\bgroup`, `\egroup`, `\begingroup`, `\endgroup`.-    + Control sequences can't be followed by a letter.-      This fixes a bug where `\begingroup` was parsed as `\begin`-      followed by `group`.-    + Parse 'dimension' arguments to unknown commands.  e.g. `\parindent0pt`-    + Make `\label` and `\ref` sensitive to `--parse-raw`.-      If `--parse-raw` is selected, these will be parsed as raw latex-      inlines, rather than bracketed text.-    + Don't crash on unknown block commands (like `\vspace{10pt}`)-      inside `\author`; just skip them.  Closes #505.--  * Textile reader:--    + Implemented literal escapes with `==` and `<notextile>`.  Closes #473.-    + Added support for LaTeX blocks and inlines (Paul Rivier).-    + Better conformance to RedCloth inline parsing (Paul Rivier).-    + Parse '+text+' as emphasized (should be underlined, but this-      is better than leaving literal plus characters in the output.--  * Docx writer: Fixed multi-paragraph list items.  Previously they each-    got a list marker.  Closes #457.--  * LaTeX writer:--    + Added `--no-tex-ligatures` option to avoid replacing-      quotation marks and dashes with TeX ligatures.-    + Use `fixltx2e` package to provide '\textsubscript'.-    + Improve spacing around LaTeX block environments:-      quote, verbatim, itemize, description, enumerate.-      Closes #502.-    + Use blue instead of pink for URL links in latex/pdf output.--  * ConTeXt writer: Fixed escaping of `%`.-    In text, `%` needs to be escaped as `\letterpercent`, not `\%`-    Inside URLs, `%` needs to be escaped as `\%`-    Thanks to jmarca and adityam for the fix.  Closes #492.--  * Texinfo writer:  Escape special characters in node titles.-    This fixes a problem pointed out by Joost Kremers.  Pandoc used-    to escape an '@' in a chapter title, but not in the corresponding-    node title, leading to invalid texinfo.--  * Fixed document encoding in texinfo template.-    Resolves Debian Bug #667816.--  * Markdown writer:--    + Don't force delimited code blocks to be flush left.-      Fixes bug with delimited code blocks inside lists etc.-    + Escape `<` and `$`.--  * LaTeX writer: Use `\hyperref[ident]{text}` for internal links.-    Previously we used `\href{\#ident}{text}`, which didn't work on-    all systems. Thanks to Dirk Laurie.--  * RST writer: Don't wrap link references.  Closes #487.--  * Updated to use latest versions of blaze-html, mtl.---pandoc (1.9.2)--  * LaTeX reader:--    + Made `lstlisting` work as a proper verbatim environment.-    + Fixed bug parsing LaTeX tables with one column.--  * LaTeX writer:--    + Use `{}` around `ctable` caption, so that formatting can be used.-    + Don't require eurosym package unless document has a €.--  * LaTeX template: Added variables for `geometry`, `romanfont`,-    `sansfont`, `mathfont`, `mainfont` so users can more easily-    customize fonts.--  * PDF writer:--    + Run latex engine at least two times, to ensure-      that PDFs will have hyperlinked bookmarks.-    + Added PDF metadata (title,author) in LaTeX standalone + PDF output.--  * Texinfo writer: retain directories in image paths.  (Peter Wang)--  * RST writer:  Better handling of inline formatting, in accord-    with docutils' "inline markup recognition rules" (though we don't-    implement the unicode rules fully). Now `hi*there*hi` gets-    rendered properly as `hi\ *there*\ hi`, and unnecessary-    `\ ` are avoided around `:math:`, `:sub:`, `:sup:`.--  * RST reader:--    + Parse `\ ` as null, not escaped space.-    + Allow `` :math:`...` `` even when not followed by blank-      or `\`.  This does not implement the complex rule docutils follows,-      but it should be good enough for most purposes.-    + Add support for the rST default-role directive. (Greg Maslov)--  * Text.Pandoc.Parsing: Added `stateRstDefaultRole` field to `ParserState`.-    (Greg Maslov)--  * Markdown reader: Properly handle citations nested in other inline-    elements.--  * Markdown writer:  don't replace empty alt in image with "image".--  * DZSlides:  Updated template.html and styles in default template.-    Removed bizarre CSS for `q` in dzslides template.--  * Avoid repeated `id` attribute in section and header in HTML slides.--  * README improvements:  new instructions on internal links,-    removed misleading note on reST math.--  * Build system:--    + Fixed Windows installer so that dzslides works.-    + Removed stripansi.sh.-    + Added .travis.yml for Travis continuous integration support..-    + Fixed upper bound for zlib (Sergei Trofimovich).-    + Fixed upper bound for test-framework.-    + Updated haddocks for haddock-2.10 (Sergei Trofimovich).--pandoc (1.9.1.2)--  * Added `beamer+lhs` as output format.--  * Don't escape `<` in `<style>` tags with `--self-contained`.-    This fixes a bug which prevented highlighting from working-    when using `--self-contained`.--  * PDF: run latex engine three times if `--toc` specified.-    This fixes page numbers in the table of contents.--  * Docx writer: Added TableNormal style to tables.--  * LaTeX math environment fixes. `aligned` is now used instead of-    the nonexistent `aligned*`. `multline` instead of the nonexistent-    `multiline`.--  * LaTeX writer: Use `\textasciitilde` for literal `~`.--  * HTML writer: Don't escape contents of EQ tags with --gladtex.-    This fixes a regression from 1.8.--  * Use `<q>` tags for Quoted items for HTML5 output.-    The quote style can be changed by modifying the template-    or including a css file. A default quote style is included.--  * LaTeX reader: Fixed accents (\~{a}, `\c{c}`).-    Correctly handle \^{}. Support "minted" as a LaTeX verbatim block.--  * Updated LaTeX template for better language support.-    Use `polyglossia` instead of `babel` with xetex.-    Set `lang` as documentclass option.-    `\setmainlanguage` will use the last of a comma-separated-    list of languages. Thanks to François Gannaz.--  * Fixed default LaTeX template so `\euro` and `€` work.  The-    `eurosym` package is needed if you are using pdflatex.--  * Fixed escaping of period in man writer (thanks to Michael Thompson).--  * Fixed list label positions in beamer.--  * Set `mainlang` variable in context writer.-    This parallels behavior of latex writer.  `mainlang` is the last-    of a comma-separated list of languages in lang.--  * EPUB language metadat: convert e.g. `en_US` from locale to `en-US`.--  * Changed `-V` so that you can specify a key without a value.-    Such keys get the value `true`.--  * Fixed permissions on installed man pages - thanks Magnus Therning.--  * Windows installer: require XP or higher.  The installer is-    now compiled on a Windows 7 machine, which fixes a problem-    using citation functions on Windows 7.--  * OSX package: Check for 64-bit Intel CPU before installing.--pandoc (1.9.1.1)--  * Better handling of raw latex environments in markdown.  Now--        \begin{equation}-        a_1-        \end{equation}--    turns into a raw latex block as expected.--  * Improvements to LaTeX reader:--    + Skip options after block commands.-    + Correctly handle `{\\}` in braced.-    + Added a needed 'try'.-    + Citations: add `, ` to suffix if it doesn't start with space or-      punctuation. Otherwise we get no space between the year and the-      suffix in author-date styles.--  * Added two needed data files for S5.  This fixes a problem with-    `pandoc -t s5 --self-contained`.  Also removed `slides.min.js`,-    which was no longer being used.--  * Fixed some minor problems in `reference.docx`:-    name on "Date" style, `xCs` instead of `xIs`.--  * Fixed a problem creating docx files using a reference docx-    modified using Word.  The problem seems to be that Word-    modifies `_rels/.rels`, changing the Type of the Relationship to-    `docProps/core.xml`. Pandoc now changes this back to the correct-    value if it has been altered, fixing the problem.--  * Fixed html5 template so it works properly with highlighting.--pandoc (1.9.1)--  * LaTeX reader:--    + Fixed regression in 1.9; properly handle escaped $ in latex math.-    + Put LaTeX verse environments in blockquotes.--  * Markdown reader:--    + Limit nesting of strong/emph.  This avoids exponential lookahead-      in parasitic cases, like `a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**`.-    + Improved attributes syntax (inn code blocks/spans):-      (1) Attributes can contain line breaks. (2) Values in key-value-      attributes can be surrounded by either double or single quotes, or-      left unquoted if they contain no spaces.--  * Don't wrap headers in markdown or RST writers.--  * Added `stateMaxNestingLevel` to `ParserState`.-    We set this to 6, so you can still have `Emph` inside `Emph`,-    just not indefinitely.--  * More efficient implementation of `nowrap` in `Text.Pandoc.Pretty`.--  * `Text.Pandoc.PDF`:  Only run latex twice if `\tableofcontents`-    is present.--  * Require highlighting-kate >= 0.5.0.2, texmath >= 0.6.0.2.--pandoc (1.9.0.5)--  * Changed cabal file so that build-depends for the test program-    are not required unless the tests flag is used.--  * LaTeX writer:  insert `{}` between adjacent hyphens so they don't-    form ligatures (dashes) in code spans.--pandoc (1.9.0.4)--  * Raised version bound on test-framework to avoid problems-    compiling tests on GHC 7.4.1.--  * LaTeX reader: Use raw LaTeX as fallback inline text for Cites,-    so citations don't just disappear unless you process with-    citeproc.  Ignore `\bibliographystyle`, `\nocite`.--  * Simplified tex2pdf; it will always run latex twice to-    resolve table of contents and hyperrefs.--pandoc (1.9.0.3)--  * Require Cabal >= 1.10.-  * Tweaked cabal file to meet Cabal 1.10 requirements.--pandoc (1.9.0.2)--  * Allow build with json 0.4 or 0.5.  Otherwise we can't build with-    ghc 6.12.--pandoc (1.9)--  [new features]--  * Added a Microsoft Word `docx` writer. The writer includes support-    for highlighted code and for math (which is converted from TeX to OMML,-    Office's native math markup language, using texmath's new OMML module).-    A new option `--reference-docx` allows the user to customize the-    styles.--  * Added an `asciidoc` writer (<http://www.methods.co.nz/asciidoc/>).--  * Better support for slide shows:--    + Added a `dzslides` writer. DZSlides is a lightweight HTML5/javascript-      slide show format due to Paul Rouget (<http://paulrouget.com/dzslides/>).--    + Added a LaTeX `beamer` writer. Beamer is a LaTeX package for creating-      slide presentations.--    + New, flexible rules for dividing documents into sections and slides-      (see the "Structuring the slide show" in the User's Guide).  These-      are backward-compatible with the old rules, but they allow slide-      shows to be organized into sections and subsections containing-      multiple slides.--    + A new `--slide-level` option allows users to override defaults-      and select a slide level below the first header level with content.--  * A new `--self-contained` option produces HTML output that does not-    depend on an internet connection or the presence of any external-    files. Linked images, CSS, and javascript is downloaded (or fetched-    locally) and encoded in `data:` URIs. This is useful for making portable-    `HTML slide shows. The --offline` option has been deprecated and is now-    `treated as a synonym or --self-contained`.--  * Support for PDF output:--    + Removed the old `markdown2pdf`.-    + `pandoc` can now create PDFs (assuming you have latex and a set of-      appropriate packages installed): just specify an output file with the-      `.pdf` extension.-    + A new option `--latex-engine` allows you to specify `pdflatex`,-      `xelatex`, or `lualatex` as the processor.--  * Highlighting changes:--    + Syntax highlighting is now a standard feature; the `highlighting`-      flag is no longer needed when compiling.-    + A new `--no-highlight` option allows highlighting to be disabled.-    + Highlighting now works in `docx`, `latex`, and `epub`, as well as-      `html`, `html5`, `dzslides`, `s5`, and `slidy`.-    + A new `--highlight-style` option selects between various highlighting-      color themes.--  * Internal links to sections now work in ConTeXt and LaTeX as well as HTML.--  * LaTeX `\include` and `\usepackage` commands are now processed,-    provided the files are in the working directory.--  * EPUB improvements:--    + Internal and external links now work in EPUB.-    + Raw HTML is allowed.-    + New `--epub-embed-font` option.-    + Customizable templates for EPUB pages offer more control over-      formatting: `epub-page.html`, `epub-coverimage.html`,-      `epub-titlepage.html`.--  * `--mathml` now works with DocBook.--  * Added support for math in RST reader and writer.  Inline math uses the-    `` :math:`...` `` construct.  Display math uses--        .. math:: ...--    or if the math is multiline,--        .. math::--           ...--    These constructions are now supported now by `rst2latex.py`.--  * GitHub syntax for fenced code blocks is supported in pandoc's-    markdown.  You can now write--        ```ruby-        x = 2-        ```--    instead of--        ~~~ {.ruby}-        x = 2-        ~~~~--  * Easier scripting:  a new `toJsonFilter` function makes it easier to-    write Haskell scripts to manipulate the Pandoc AST.--  [behavior changes]--  * Fixed parsing of consecutive lists in markdown.-    Pandoc previously behaved like Markdown.pl for consecutive-    lists of different styles. Thus, the following would be parsed-    as a single ordered list, rather than an ordered list followed-    by an unordered list:--        1. one-        2. two--        - one-        - two--    This change makes pandoc behave more sensibly, parsing this as-    two lists.  Any change in list type (ordered/unordered) or in-    list number style will trigger a new list. Thus, the following-    will also be parsed as two lists:--        1. one-        2. two--        a. one-        b. two--    Since we regard this as a bug in Markdown.pl, and not something-    anyone would ever rely on, we do not preserve the old behavior-    even when `--strict` is selected.--  * Dashes work differently with `--smart`: `---` is always em-dash,-    and `--` is always en-dash.  Pandoc no longer tries to guess when-    `-` should be en-dash.  *Note:* This may change how existing documents-    look when processed with pandoc. A new option, `--old-dashes`,-    is provided for legacy documents.--  * The markdown writer now uses setext headers for levels 1-2.-    The old behavior (ATX headers for all levels) can be restored-    using the new `--atx-headers` option.--  * Links are now allowed in markdown image captions.  They are also-    allowed in links, but will appear there as regular text. So,--        [link with [link](/url)](/url)--    will turn into--        <p><a href="/url">link with link</a></p>--  * Improved handling of citations using `citeproc-hs-0.3.4`.-    Added `--citation-abbreviations` option.--  * Citation keys can no longer end with a punctuation character.-    This means that `@item1.` will be parsed as a citation with key-    'item1', followed by a period, instead of a citation with key-    'item1.', as was the case previously.--  * In HTML output, citations are now put in a span with class `citation`.--  * The markdown reader now recognizes DocBook block and inline tags.-    It was always possible to include raw DocBook tags in a markdown-    document, but now pandoc will be able to distinguish block from-    inline tags and behave accordingly. Thus, for example,--        <sidebar>-        hello-        </sidebar>--    will not be wrapped in `<para>` tags.--  * The LaTeX parser has been completely rewritten; it is now much more-    accurate, robust, and extensible. However, there are two important-    changes in how it treats unknown LaTeX. (1) Previously, unknown-    environments became BlockQuote elements; now, they are treated-    as "transparent", so `\begin{unknown}xyz\end{unknown}` is the-    same as `xyz`.  (2) Previously, arguments of unknown commands-    were passed through with their braces; now the braces are stripped-    off.--  * `--smart` is no longer selected automatically with `man` output.--  * The deprecated `--xetex` option has been removed.--  * The `--html5`/`-5` option has been deprecated. Use `-t html5`-    instead. `html5` and `html5+lhs` are now separate output formats.--  * Single quotes are no longer escaped in HTML output.  They do not-    need to be escaped outside of attributes.--  * Pandoc will no longer transform leading newlines in code-    blocks to `<br/>` tags.--  * The ODT writer now sizes images appropriately, using the image-    size and DPI information embedded in the image.--  * `--standalone` is once again implicitly for a non-text output format-    (ODT, EPUB).  You can again do `pandoc test.txt -o test.odt`-    and get a standalone ODT file.--  * The Docbook writer now uses `<sect1>`, `<sect2>`, etc. instead of-    `<section>`.--  * The HTML writer now uses `<del>` for strikeout.--  * In HTML output with `--section-divs`, the classes `section` and-    `level[1,2,..6]` are put on the `div` tags so they can be styled.-    In HTML 5 output with `--section-divs`, the classes-    `level[1,2,...6]` are put on `section` tags.--  * EPUB writer changes:--    + The `lang` variable now sets the language-      in the metadata (if it is not set, we default to the locale).-    + EPUB:  UTF-8 is used rather than decimal entities.--  * Added `titleslide` class to title slide in S5 template.--  * In HTML, EPUB, and docx metadata, the date is normalized into-    YYYY-MM-DD format if possible. (This is required for validation.)--  * Attributes in highlighted code blocks are now preserved in HTML.-    The container element will have the classes, id, and key-value attributes-    you specified in the delimited code block. Previously these were stripped-    off.--  * The reference backlink in the HTML writer no longer has a special-    `footnoteBacklink` class.--  * The HTML template has been split into `html` and `html5` templates.--  * Author and date are treated more consistently in HTML templates.-    Authors are now `<h2>`, date `<h3>`.--  * URLs are hyphenated in the ConTeXt writer (B. Scott Michel).--  * In `Text.Pandoc.Builder`, `+++` has been replaced by `<>`.--  [bug fixes]--  * Better support for combining characters and East Asian wide characters-    in markdown and reST.--  * Better handling of single quotes with `--smart`.-    Previously `D'oh l'*aide*` would be parsed with left and right single-    quotes instead of apostrophes. This kind of error is now fixed.--  * Highlighting: Use `reads` instead of `read` for better error handling.-    Fixes crash on `startNum="abc"`.--  * Added blank comment after directives in rst template.--  * Unescape entities in citation `refId`. The `refId`s coming-    from citeproc contain XML numeric entities, and these don't match with the-    citation keys parsed by pandoc. Solution is to unescape them.--  * HTML reader: Fixed bug parsing tables with both thead and tbody.--  * Markdown reader:--    + Better handling of escapes in link URLs and titles.-    + Fixed backslash escapes in reference links.-    + Fixed bug in table/hrule parsing, by checking that the top-      line of a table is not followed by a blank line. This bug caused-      slowdowns on some files with hrules and tables, as pandoc tried to-      interpret the hrules as the tops of multiline tables.-    + Fixed bug in code block attribute parser. Previously the ID attribute-      got lost if it didn't come first. Now attributes can come in any order.--  * RST reader: allow footnotes followed by newline without space characters.--  * LaTeX reader:--    + Ignore empty groups {}, { }.-    + LaTeX reader: Handle \@.-    + LaTeX reader:  Don't crash on commands like `\itemsep`.-    + LaTeX reader:  Better handling of letter environments.--  * RST writer: Fixed bug involving empty table cells. isSimple was being-    calculated in a way that assumed there were no non-empty cells.--  * ConTeXt writer:--    + Made `--toc` work even without `--number-sections`.-    + Escape # in link URLs.-    + Use buffering for footnotes containing code blocks.-    + Changed 'descr' to 'description', fixed alignment.--  * LaTeX writer:--    + Escape euro character.-    + Don't escape ~ inside href{...}.-    + Escape # in href URLs.-    + Improved detection of book classes.  We now check the-      `documentclass` variable, and if that is not set, we look through-      the template itself.  Also, we have added the KOMA classes scrreprt-      and scrbook.  You can now make a book using-      `pandoc -V documentclass:book mybook.txt -o mybook.pdf`-    + LHS files now set the "listings" variable, so that the definition-      of the `code` environment will be included in the template.-    + Links are colored blue by default (this can be changed by-      modifying `hyperref` settings in the template).-    + Added `lang` variable to LaTeX template.--  * HTML writer:--    + Fixed bug in HTML template with html5 and mathml.-    + Don't use self-closing img, br, hr tags for HTML5.-    + Use `<section>` for footnotes if HTML5.-    + Update HTML templates to use Content-Style-Type meta tag.-    + Use separate variables for meta-date, meta-author.-      This makes footnotes work in author and date fields.-    + Use 'vertical-align:middle' in WebTeX math for better alignment.--  * S5/slidy writer:  Make footnotes appear on separate slide at end.--  * MIME: Added 'layout-cache' to getMimeType. This ensures that the-    META-INF/manifest.xml for ODT files will have everything it needs, so-    that ODT files modified by LibreOffice can be used as `--reference-odt`.--  * `Text.Pandoc.Templates`: Return empty string for json template.--  * `Text.Pandoc.Biblio`:--    + Expand citations recursively inside nested inlines.-    + Treat `\160` as space when parsing locator and suffix.-      This fixes a bug with "p. 33" when `--smart` is used. Previously-      the whole "p. 33" would be included in the suffix, with no locator.-    + Put whole author-in-text citation in a Cite.  Previously just the-      date and other info went in the Cite.-    + Don't add comma+space to prefix if it ends in punctuation.--  * Updated chicago-author-date.csl.  The old version did not work-    properly for edited volumes with no author.--  * EPUB writer:--    + Add date to EPUB titlepage and metadata.-    + Added TOC identifier in EPUB page template.-    + Don't generate superfluous file `cover-image.jpg`.--  [under the hood improvements]--  * Modified `make_osx_package.sh` to use cabal-dev.-    Items are no longer installed as root.-    Man pages are zipped and given proper permissions.--  * Modified windows installer generater to use cabal-dev.--  * Setup: Making man pages now works with cabal-dev (at least on OSX). In-    Setup.hs we now invoke 'runghc' in a way that points it to the correct-    package databases, instead of always falling back to the default user-    package db.--  * Updated to work with GHC 7.4.1.--  * Removed dependency on old-time.--  * Removed dependency on dlist.--  * New slidy directory for "self-contained."--  * TeXMath writer:  Use unicode thin spaces for thin spaces.--  * Markdown citations: don't strip off initial space in locator.--  [API changes]--  * Removed `Apostrophe`, `EmDash`, `EnDash`, and `Ellipses`-    from the native `Inline` type in pandoc-types.  Now we use `Str`-    elements with unicode.--  * Improvements to `Text.Pandoc.Builder`:--    + `Inlines` and `Blocks` are now newtypes (not synonyms for-      sequences).-    + Instances are defined for `IsString`, `Show`, `Read`, `Monoid`,-      and a new `Listable` class, which allows these to be manipulated-      to some extent like lists. Monoid append includes automatic-      normalization.-    + `+++` has been replaced by `<>` (mappend).--  * Use blaze-html instead of xhtml for HTML generation.-    This changes the type of `writeHtml`.--  * `Text.Pandoc.Shared`:--    + Added `warn` and `err`.-    + Removed `unescapeURI`, modified `escapeURI`.-      (See under [behavior changes], above.)--  * Changes in URI escaping:  Previously the readers escaped URIs by-    converting unicode characters to octets and then percent encoding.-    Now unicode characters are left as they are, and `escapeURI` only-    percent-encodes space characters.  This gives more readable-    URIs, and works well with modern user agents. URIs are no longer unescaped-    at all on conversion to `markdown`, `asciidoc`, `rst`, `org`.--  * New module `Text.Pandoc.SelfContained`.--  * New module `Text.Pandoc.Docx`.--  * New module `Text.Pandoc.PDF`.--  * Added `writerBeamer` to `WriterOptions`.--  * Added `normalizeDate` to `Text.Pandoc.Shared`.--  * Added `splitStringWithIndices` in `Text.Pandoc.Shared`.-    This is like `splitWithIndices`, but it is sensitive to distinctions-    between wide, combining, and regular characters.--  * `Text.Pandoc.Pretty`:--    + Added `chomp` combinator.-    + Added `beforeNonBreak` combinator.  This allows you to include-      something conditionally on it being before a nonblank.-      Used for RST inline math.-    + Added `charWidth` function. All characters marked W or F in the unicode-      spec EastAsianWidth.txt get width 2.-    + Added `realLength`, based on `charWidth`. `realLength` is now-      used in calculating offsets.--  * New module `Text.Pandoc.Slides`, for common functions for breaking-    a document into slides.--  * Removed `Text.Pandoc.S5`, which is no longer needed.--  * Removed `Text.Pandoc.CharacterReferences`.  Moved-    `characterReference` to `Text.Pandoc.Parsing`.-    `decodeCharacterReferences` is replaced by `fromEntities`-    in `Text.Pandoc.XML`.--  * Added `Text.Pandoc.ImageSize`.  This is intened for use-    in `docx` and `odt` writers, so the size and dpi of images-    can be calculated.--  * Removed `writerAscii` in `WriterOptions`.--  * Added `writerHighlight` to `WriterOptions`.--  * Added `DZSlides` to `HTMLSlideVariant`.--  * `writeEPUB` has a new argument for font files to embed.--  * Added `stateLastStrPos` to `ParserState`. This lets us keep track-    of whether we're parsing the position immediately after a regular-    (non-space, non-symbol) string, which is useful for distinguishing-    apostrophes from single quote starts.--  * `Text.Pandoc.Parsing`:--    + `escaped` now returns a `Char`.-    + Removed `charsInBalanced'`, added a character parser as-      a parameter of `charsInBalanced`.  This is needed for-      proper handling of escapes, etc.-    + Added `withRaw`.--  * Added `toEntities` to `Text.Pandoc.XML`.--  * `Text.Pandoc.Readers.LaTeX`:--    + Export `handleIncludes`.-    + Export `rawLaTeXBlock` instead of `rawLaTeXEnvironment'`.--  * Added `ToJsonFilter` class and `toJsonFilter` function to-    `Text.Pandoc`, deprecating the old `jsonFilter` function.--  * `Text.Pandoc.Highlighting`:--     + Removed `highlightHtml`, `defaultHighlightingCss`.-     + Export `formatLaTeXInline`, `formatLaTeXBlock`, and `highlight`, plus-       key functions from highlighting-kate.-     + Changed types of highlighting function.  `highlight` returns a-       `Maybe`, not an `Either`.--pandoc (1.8.2.1)--  * Relaxed cabal consntraints for test-framework (S. Trofimovich).--  * Relaxed cabal constraints for pandoc-types.--  * Adjusted Arbitrary instance to help avoid timeouts in tests.--  * Added `Tests.Writers.Markdown` to cabal file.--pandoc (1.8.2)--  * Added script to produce OS X package.--  * Made `templates` directory a git submodule.  This should make it-    easier for people to revise their custom templates when the default-    templates change.--  * Changed template naming scheme: `FORMAT.template` -> `default.FORMAT`.-    **Note:** If you have existing templates in `~/.pandoc/templates`, you-    must rename them to conform to the new scheme!--  * Fixed smart quotes bug, now handling `'...hi'` properly.--  * RST reader:--    + Partial support for labeled footnotes.-    + Improved accuracy of `simpleReferenceName` parser.--  * HTML reader:--    + Substitute correct unicode characters for-      characters in the 128..159 range, which are often found even in-      HTML that purports to be UTF-8.--  * LaTeX reader:  Handle `\subtitle` command (a subtitle is added-    to the title, after a colon and linebreak). Closes #280.--  * Leaner `reference.odt`.--  * Added unexported module `Text.Pandoc.MIME` for use in-    the ODT writer.--  * ODT writer:  Construct `manifest.xml` based on archive contents.-    This fixes a bug in ODTs containing images. Recent versions of-    LibreOffice would reject these as corrupt, because `manifest.xml`-    did not contain a reference to the image files.--  * LaTeX writer:--    + Make verbatim environments flush to avoid spurious-      blank lines.  Closes #277.-    + Use `\texttt` and escapes insntead of `\verb!...!`, which-      is too fragile (doesn't work in command arguments).-    + Use `\enquote{}` for quotes if the template includes-      the `csquotes` package. This provides better support for-      local quoting styles. (Thanks to Andreas Wagner for the idea.)--  * ConTeXt writer:  Make `\starttyping`/`\stoptyping` flush with-    margin, preventing spurious blank lines.--  * Slidy writer:--    + Use non-minimized version of `slidy.css` with `--offline`-      option, so users can more easily edit it.-    + Also fixed a bug in the CSS that prevented proper centering-      of title (now reported and fixed upstream).--  * S5 writer:--    + Replaced `s5/default/slides.js.{comment,packed}` with-      new compressed `s5/default/slides.min.js`.-    + Use `data:` protocol to embed S5 CSS in `<link>` tags,-      when `--offline` is specified. Using inline CSS didn't-      work with Chrome or Safari.  This fixes offline-      S5 on those browsers.--  * HTML writer:  Removed English title on footnote backlinks.-    This is incongrous in non-English documents.--  * Docbook writer:--    + Use CALS tables.  (Some older docbook software does not work-      well with XHTML tables.)  Closes #77.-    + Use `programlisting` tags (instead of `screen`) for code blocks.--  * `markdown2pdf`:--    + Calls latex with `-halt-on-error -interaction nonstopmode` instead-      of `-interaction=batchmode`, which essentially just ignored errors,-      leading to bad results. Better to know when something is wrong.-    + Fixed issues with non-UTF-8 output of `pdflatex`.-    + Better error reporting.--  * `--mathjax` now takes an optional URL argument. If it is not-    provided, pandoc links directly to the (secure) mathjax CDN,-    as now recommended (thanks to dsanson).--  * Deprecated `--xetex` option in `pandoc`.  It is no longer needed,-    since the LaTeX writer now produces a file that can be processed by-    `latex`, `pdflatex`, `lualatex`, or `xelatex`.--  * Introduced `--luatex` option to `markdown2pdf`. This causes `lualatex`-    to be used to create the PDF.--  * If a template specified with `--template` is not found, look for it-    in `datadir`.  Also, if no extension is provided, supply one based-    on the writer.  So now you can put your `special.latex` template in-    `~/.pandoc/templates`, and use it from any directory via-    `pandoc -t latex --template special`.--  * Default template improvements:--    + HTML:  Display author and date after title.-    + HTML:  Made table of contents more customizable.  The container-      for the TOC is now in the template, so users can insert a header-      or other styling. (Thanks to Bruce D'Arcus for the suggestion.)-    + HTML, Slidy, S5:  Enclose scripts in CDATA tags.-    + Slidy, S5: Added `s5-url` and `slidy-url` variables, instead of-      hard-coding.  If you want to put your slidy files in the slidy-      subdirectory, for example, you can do-      `pandoc -t slidy -V slidy-url=slidy -s`.-    + LaTeX: Use `\and` to separate authors in LaTeX documents (reader-      & writer).  Closes #279.-    + LaTeX: Use different `hyperref` options for `xetex`, fixing-      problems with unicode bookmarks (thanks to CircleCode).-    + LaTeX: Removed `ucs` package, use `utf8` rather than `utf8x`-      with `inputenc`.  This covers fewer characters but is more-      robust with other packages, and `ucs` is unmaintained.  Users-      who need better unicode support should use xelatex or lualatex.--pandoc (1.8.1.2)--  * Added `--epub-cover-image` option.--  * Documented `--biblatex` and `--natbib` options.--  * Allow `--section-divs` with slidy output.  Resolves Issue #296.--  * Disallow notes within notes in reST and markdown.-    These previously caused infinite looping and stack overflows.-    For example:--        [^1]--        [^1]: See [^1]--    Note references are allowed in reST notes, so this isn't a full-    implementation of reST. That can come later. For now we need to-    prevent the stack overflows.  Partially resolves Issue #297.--  * EPUB writer: Allow non-plain math methods.--  * Forbid ()s in citation item keys.  Resolves Issue #304: problems with-    `(@item1; @item2)` because the final paren was being parsed as part of-    the item key.--  * Changed URI parser so it doesn't include trailing punctuation.-    So, in RST, `http://google.com.` should be parsed as a link followed by a-    period. The parser is smart enough to recognize balanced parentheses, as-    often occur in wikipedia links: `http://foo.bar/baz_(bam)`.--  * Markdown+lhs reader: Require space after inverse bird tracks, so that-    HTML tags can be used freely at the left margin of a markdown+lhs document.-    Thanks to Conal Elliot for the suggestion.--  * Markdown reader:--    + Improved emph/strong parsing; fixes bug found by Perry Wagle.-    + Fixed bug in footnote order (reported by CircleCode).--  * RST reader:-      + Fixed bug in in field lists with multi-line items at the-        end of the list.-      + Added parentheses to RST `specialChars`, so-        `(http://google.com)` will be parsed as a link in parens.-        Resolves Issue #291.-      + Allow `|` followed by newline in RST line block.--  * LaTeX reader:-      + Support `\dots`.-      + Gobble option & space after linebreak `\\[10pt]`.--  * Textile reader:-      + Make it possible to have colons after links.  (qerub)-      + Make it possible to have colons after links.  (Christoffer Sawicki)--  * HTML reader:-      + Skip spaces after `<b>`, `<emph>`, etc.-      + Handle tbody, thead in simple tables.  Closes #274.-      + Implicit `Para`s instead of `Plains` in some contexts.--  * OpenDocument writer:  Use special `First paragraph` style for-    first paragraph after most non-paragraph blocks. This allows users to-    specify e.g. that only paragraphs after the first paragraph of a block are-    to be indented. Thanks to Andrea Rossato for the patch. Closes #20.--  * LaTeX writer:  use `deVerb` on table and picture captions.-    Otherwise LaTeX complains about `\verb` inside command argument.-    Thanks to bbanier for reporting the bug.--  * Markdown writer: Insert HTML comment btw list and indented code block.-    This prevents the code block from being interpreted as part of the list.--  * EPUB writer: Add a meta element specify the cover.-    Some EPUB e-readers, such as the Nook, require a meta element inside the-    OPF metadata block to ensure the cover image is properly displayed.-    (Kelsey Hightower)--  * HTML writer: Use embed tag for images with non-image extensions.-    (e.g.  PDFs).  Closes #264.--  * LaTeX writer: Improved tables.--      + More space between lines, top-align cells.-      + Use ctable package, which allows footnotes and-        provides additional options.-      + Made cell alignments work in multiline tables.-      + Closes #271, #272.--  * Un-URI-escape image filenames in LaTeX, ConTeXt, RTF, Texinfo.-    Also do this when copying image files into EPUBs and ODTs.-    Closes #263.--  * Changed to github issue tracker.--  * Added failing emph/strong markdown test case due to Perry Wagle.--  * Slidy improvements:-      + Updated to use Slidy2.-      + Fixed bug, unclosed div tag.-      + Added `duration` variable in template.-        Setting this activates the timer.-      + Use 'titlepage' instead of 'cover' for title div.--pandoc (1.8.1.1)--  * `markdown2pdf`:  Removed some debugging lines accidentally included-    in the 1.8.1 release. With those lines, the temp directory is created-    in the working directory, and it is not deleted.  This fix restores-    the original behavior.--pandoc (1.8.1)--  * Added `--ascii` option.  Currently supported only in HTML writer,-    which it causes to use numerical entities instead of UTF-8.--  * EPUB writer: `--toc` now works to provide a table of contents-    at the beginning of each chapter.--  * LaTeX writer:  Change figure defaults to `htbp`.-    This prevents "too many unprocessed floats."  Resolves-    Issue #285.--  * `Text.Pandoc.UTF8`:  Encode filenames even when using recent-    base.--  * `markdown2pdf`: Fixed filename encoding issues. With help from Paulo-    Tanimoto. Resolves Issue #286.--  * HTML writer: Put line breaks in section divs.--  * `Text.Pandoc.Shared`: Make `writerSectionDivs` default to False.--pandoc (1.8.0.3)--  * Fixed Source-repository stanza in cabal file.--pandoc (1.8.0.2)--  * HTML writer:--    + Stringify alt text instead of converting to HTML.-    + Break lines after block elements, not inside tags.-      HTML output now closely resembles that of tidy. Resolves Issue #134.--  * Markdown reader: Fixed bug in footnote block parser (pointed out-    by Jesse Rosenthal).  The problem arose when the blank line-    at the end of a footnote block contained indenting spaces.--  * Shared: Improved 'normalize' function so it normalizes Spaces too.-    In normal form, Space elements only occur to separate two non-Space-    elements.  So, we never have [Space], or [, ..., Space].--  * Tests:--    + Improved Arbitrary instance.-    + Added timeout for test instances.--  * README:--    + Added section on four-space rule for lists.  Resolves Issue #283.-    + Clarified optional arguments on math options.--  * markdown2pdf: Fixed bug with output file extensions.-    Previously `markdown2pdf test.txt -o test.en.pdf` would produce-    `test.pdf`, not `test.en.pdf`.  Thanks to Paolo Tanimoto for the fix.--pandoc (1.8.0.1)--  * Revised Interact.hs so that it works with the CPP macros-    in the UTF8 module.--  * Revised Setup.hs so that we don't call MakeManPage.hs unless-    the man pages are out of date.--pandoc (1.8)--  [new features]--  * Support for citations using Andrea Rossato's `citeproc-hs` 0.3.-    You can now write, for example,--        Water is wet [see @doe99, pp. 33-35; also @smith04, ch. 1].--    and, when you process your document using `pandoc`, specifying-    a citation style using `--csl` and a bibliography using `--bibliography`,-    the citation will be replaced by an appropriately formatted-    citation, and a list of works cited will be added to the end-    of the document.--    This means that you can switch effortlessly between different citation-    and bibliography styles, including footnote, numerical, and author-date-    formats. The bibliography can be in any of the following formats: MODS,-    BibTeX, BibLaTeX, RIS, EndNote, EndNote XML, ISI, MEDLINE, Copac, or JSON.-    See the README for further details.--    Citations are supported in the markdown reader, using a special-    syntax, and in the LaTeX reader, using natbib or biblatex syntax.-    (Thanks to Nathan Gass for the natbib and biblatex support.)--  * New `textile` reader and writer.  Thanks to Paul Rivier for contributing-    the `textile` reader, an almost complete implementation of the textile-    syntax used by the ruby [RedCloth library](http://redcloth.org/textile).-    Resolves Issue #51.--  * New `org` writer, for Emacs Org-mode, contributed by Puneeth Chaganti.--  * New `json` reader and writer, for reading and writing a JSON-    representation of the native Pandoc AST.  These are much faster-    than the `native` reader and writer, and should be used for-    serializing Pandoc to text.  To convert between the JSON representation-    and native Pandoc, use `encodeJSON` and `decodeJSON` from-    `Text.JSON.Generic`.--  * A new `jsonFilter` function in `Text.Pandoc` makes it easy-    to write scripts that transform a JSON-encoded pandoc document.-    For example:--        -- removelinks.hs - removes links from document-        import Text.Pandoc-        main = interact $ jsonFilter $ bottomUp removeLink-                 where removeLink (Link xs _) = Emph xs-                       removeLink x = x--    To use this to remove links while translating markdown to LaTeX:--        pandoc -t json | runghc removelinks.hs | pandoc -f json -t latex--  * Attributes are now allowed in inline `Code` elements, for example:--        In this code, `ulist ! [theclass "special"] << elts`{.haskell} is...--    The attribute syntax is the same as for delimited code blocks.-    `Code` inline has an extra argument place for attributes, just like-    `CodeBlock`. Inline code will be highlighted in HTML output, if pandoc-    is compiled with highlighting support. Resolves Issue #119.--  * New `RawBlock` and `RawInline` elements (replacing `RawHtml`,-    `HtmlInline`, and `TeX`) provide lots of flexibility in writing-    scripts to transform Pandoc documents. Scripts can now change-    how each element is rendered in each output format.--  * You can now define LaTeX macros in markdown documents, and pandoc-    will apply them to TeX math.  For example,--        \newcommand{\plus}[2]{#1 + #2}-        $\plus{3}{4}$--    yields `3+4`.  Since the macros are applied in the reader, they-    will work in every output format, not just LaTeX.--  * LaTeX macros can also be used in LaTeX documents (both in math-    and in non-math contexts).--  * A new `--mathjax` option has been added for displaying-    math in HTML using MathJax.  Resolves issue #259.--  * Footnotes are now supported in the RST reader. (Note, however,-    that unlike docutils, pandoc ignores the numeral or symbol used in-    the note; footnotes are put in an auto-numbered ordered list.)-    Resolves Issue #258.--  * A new `--normalize` option causes pandoc to normalize the AST-    before writing the document.  This means that, for example,-    `*hi**there*` will be rendered as `<em>hithere</em>`-    instead of `<em>hi</em><em>there</em>`.  This is not the default,-    because there is a significant performance penalty.--  * A new `--chapters` command-line option causes headers-    in DocBook, LaTeX, and ConTeXt to start with "chapter" (level one).-    Resolves Issue #265.--  * In DocBook output, `<chapter>` is now used for top-level-    headers if the template contains `<book>`. Resolves Issue #265.--  * A new `--listings` option in `pandoc` and `markdown2pdf` causes-    the LaTeX writer to use the listings package for code blocks.-    (Thanks to Josef Svennigsson for the pandoc patch, and Etienne-    Millon for the markdown2pdf patch.)--  * `markdown2pdf` now supports `--data-dir`.--  * URLs in autolinks now have class "url" so they can be styled.--  * Improved prettyprinting in most formats.  Lines will be wrapped-    more evenly and duplicate blank lines avoided.--  * New `--columns` command-line option sets the column width for-    line wrapping and relative width calculations for tables.--  * Made `--smart` work in HTML, RST, and Textile readers, as well-    as markdown.--  * Added `--html5` option for HTML5 output.--  * Added support for listings package in LaTeX reader-    (Puneeth Chaganti).--  * Added support for simple tables in the LaTeX reader.--  * Added support for simple tables in the HTML reader.--  * Significant performance improvements in many readers and writers.--  [API and program changes]--  * Moved `Text.Pandoc.Definition` from the `pandoc` package to a new-    auxiliary package, `pandoc-types`. This will make it possible for other-    programs to supply output in Pandoc format, without depending on the whole-    pandoc package.--  * Added `Attr` field to `Code`.--  * Removed `RawHtml`, `HtmlInline`, and `TeX` elements; added generic-    `RawBlock` and `RawInline`.--  * Moved generic functions to `Text.Pandoc.Generic`. Deprecated-    `processWith`, replacing it with two functions, `bottomUp` and `topDown`.-    Removed previously deprecated functions `processPandoc` and `queryPandoc`.--  * Added `Text.Pandoc.Builder`, for building `Pandoc` structures.--  * `Text.Pandoc` now exports association lists `readers` and `writers`.--  * Added `Text.Pandoc.Readers.Native`, which exports `readNative`.-    `readNative` can now read full pandoc documents, block lists, blocks,-    inline lists, or inlines.  It will interpret `Str "hi"`-    as if it were `Pandoc (Meta [] [] []) [Plain [Str "hi"]]`.-    This should make testing easier.--  * Removed deprecated `-C/--custom-header` option.-    Use `--template` instead.--  * `--biblio-file` has been replaced by `--bibliography`.-    `--biblio-format` has been removed; pandoc now guesses the format-    from the file extension (see README).--  * pandoc will treat an argument as a URI only if it has an-    `http(s)` scheme.  Previously pandoc would treat some-    Windows pathnames beginning with `C:/` as URIs.--  * The `--sanitize-html` option and the `stateSanitize` field in-    `ParserState` have been removed. Sanitization is better done in the-    resulting HTML using `xss-sanitize`, which is based on pandoc's-    sanitization, but improved.--  * pandoc now adds a newline to the end of its output in fragment-    mode (= not `--standalone`).--  * Added support for `lang` in `html` tag in the HTML template,-    so you can do `pandoc -s -V lang=es`, for example.--  * `highlightHtml` in `Text.Pandoc.Highlighting` now takes-    a boolean argument that selects between "inline" and-    "block" HTML.--  * `Text.Pandoc.Writers.RTF` now exports `rtfEmbedImage`.-    Images are embedded in RTF output when possible (png, jpeg).-    Resolves Issue #275.--  * Added `Text.Pandoc.Pretty`. This is better suited for pandoc than the-    `pretty` package.  Changed all writers that used-    `Text.PrettyPrint.HughesPJ` to use `Text.Pandoc.Pretty` instead.--  * Rewrote `writeNative` using the new prettyprinting module. It is-    now much faster. The output has been made more consistent and compressed.-    `writeNative` is also now sensitive to writerStandalone`, and will simply-    `print a block list if writerStandalone` is False.--  * Removed `Text.Pandoc.Blocks`. `Text.Pandoc.Pretty` allows you to define-    blocks and concatenate them, so a separate module is no longer needed.--  * `Text.Pandoc.Shared`:--    + Added `writerColumns`, `writerChapters`, and `writerHtml5` to-      `WriterOptions`.-    + Added `normalize`.-    + Removed unneeded prettyprinting functions:-      `wrapped`, `wrapIfNeeded`, `wrappedTeX`, `wrapTeXIfNeeded`, `hang'`,-      `BlockWrapper`, `wrappedBlocksToDoc`.-    + Made `splitBy` take a test instead of an element.-    + Added `findDataFile`, refactored `readDataFile`.-    + Added `stringify`. Rewrote `inlineListToIdentifier` using `stringify`.-    + Fixed `inlineListToIdentifier` to treat '\160' as ' '.--  * `Text.Pandoc.Readers.HTML`:--    + Removed `rawHtmlBlock`, `anyHtmlBlockTag`, `anyHtmlInlineTag`,-      `anyHtmlTag`, `anyHtmlEndTag`, `htmlEndTag`, `extractTagType`,-      `htmlBlockElement`, `htmlComment`-    + Added `htmlTag`, `htmlInBalanced`, `isInlineTag`, `isBlockTag`,-      `isTextTag`--  * Moved `smartPunctuation` from `Text.Pandoc.Readers.Markdown`-    to `Text.Pandoc.Readers.Parsing`, and parameterized it with-    an inline parser.--  * Added `nonspaceChar` to `Text.Pandoc.Parsing`.--  * Ellipses are no longer allowed to contain spaces.-    Previously we allowed '. . .', ' . . . ', etc.  This caused-    too many complications, and removed author's flexibility in-    combining ellipses with spaces and periods.--  * Allow linebreaks in URLs (treat as spaces). Also, a string of-    consecutive spaces or tabs is now parsed as a single space. If you have-    multiple spaces in your URL, use `%20%20`.--  * `Text.Pandoc.Parsing`:--    + Removed `refsMatch`.-    + Hid `Key` constructor.-    + Removed custom `Ord` and `Eq` instances for `Key`.-    + Added `toKey` and `fromKey` to convert between `Key` and `[Inline]`.-    + Generalized type on `readWith`.--  * Small change in calculation of relative widths of table columns.-    If the size of the header > the specified column width, use-    the header size as 100% for purposes of calculating-    relative widths of columns.--  * Markdown writer now uses some pandoc-specific features when `--strict`-    is not specified: `\` newline is used for a hard linebreak instead of-    two spaces then a newline. And delimited code blocks are used when-    there are attributes.--  * HTML writer:  improved gladTeX output by setting ENV appropriately-    for display or inline math (Jonathan Daugherty).--  * LaTeX writer: Use `\paragraph`, `\subparagraph` for level 4,5 headers.--  * LaTeX reader:--    + `\label{foo}` and `\ref{foo}` now become `{foo}` instead of `(foo)`.-    + `\index{}` commands are skipped.--  * Added `fontsize` variable to default LaTeX template.-    This makes it easy to set the font size using `markdown2pdf`:-    `markdown2pdf -V fontsize=12pt input.txt`.--  * Fixed problem with strikeout in LaTeX headers when using-    hyperref, by adding a command to the default LaTeX template-    that disables `\sout` inside pdf strings. Thanks to Joost Kremers-    for the fix.--  * The `COLUMNS` environment variable no longer has any effect.--  [under-the-hood improvements]--  * Pandoc now compiles with GHC 7. (This alone leads to a-    significant performance improvement, 15-20%.)--  * Completely rewrote HTML reader using tagsoup as a lexer. The-    new reader is faster and more accurate.  Unlike the-    old reader, it does not get bogged down on some input-    (Issues #277, 255). And it handles namespaces in tags-    (Issue #274).--  * Replaced `escapeStringAsXML` with a faster version.--  * Rewrote `spaceChar` and some other parsers in Text.Pandoc.Parsing-    for a significant performance boost.--  * Improved performance of all readers by rewriting parsers.--  * Simplified Text.Pandoc.CharacterReferences by using-    entity lookup functions from TagSoup.--  * `Text.Pandoc.UTF8` now uses the unicode-aware IO functions-    from `System.IO` if base >= 4.2.  This gives support for-    windows line endings on windows.--  * Remove duplications in documentation by generating the-    pandoc man page from README, using `MakeManPage.hs`.--  * README now includes a full description of markdown syntax,-    including non-pandoc-specific parts.  A new `pandoc_markdown`-    man page is extracted from this, so you can look up markdown-    syntax by doing `man pandoc_markdown`.--  * Completely revised test framework (with help from Nathan Gass).-    The new test framework is built when the `tests` Cabal flag is set. It-    includes the old integration tests, but also some new unit and quickcheck-    tests. Test output has been much improved, and you can now specify a glob-    pattern after `cabal test` to indicate which tests should be run;-    for example `cabal test citations` will run all the citation tests.--  * Added a shell script, `stripansi.sh`, for filtering ANSI control-    sequences from test output: `cabal test | ./stripansi.sh > test.log`.--  * Added `Interact.hs` to make it easier to use ghci while developing.-    `Interact.hs` loads `ghci` from the `src` directory, specifying-    all the options needed to load pandoc modules (including-    specific package dependencies, which it gets by parsing-    dist/setup-config).--  * Added `Benchmark.hs`, testing all readers + writers using criterion.--  * Added `stats.sh`, to make it easier to collect and archive-    benchmark and lines-of-code stats.--  * Added upper bounds to all cabal dependencies.--  * Include man pages in extra-source-files.  This allows users to-    install pandoc from the tarball without needing to build the man-    pages.--  [bug fixes]--  * Filenames are encoded as UTF8.  Resolves Issue #252.--  * Handle curly quotes better in `--smart` mode. Previously, curly quotes-    were just parsed literally, leading to problems in some output formats.-    Now they are parsed as `Quoted` inlines, if `--smart` is specified.-    Resolves Issue #270.--  * Text.Pandoc.Parsing: Fixed bug in grid table parser.-    Spaces at end of line were not being stripped properly,-    resulting in unintended LineBreaks.--  * Markdown reader:--    + Allow HTML comments as inline elements in markdown.-      So, `aaa <!-- comment --> bbb` can be a single paragraph.-    + Fixed superscripts with links: `^[link](/foo)^` gets-      recognized as a superscripted link, not an inline note followed by-      garbage.-    + Fixed regression, making markdown reference keys case-insensitive again.-      Resolves Issue #272.-    + Properly handle abbreviations (like `Mr.`) at the end of a line.-    + Better handling of intraword underscores, avoiding exponential-      slowdowns in some cases.  Resolves Issue #182.-    + Fixed bug in alignments in tables with blank rows in the header.--  * RST reader:--    + Field lists now allow spaces in field names, and-      block content in field values. (Thanks to Lachlan Musicman-      for pointing out the bug.)-    + Definition list items are now always `Para` instead of-      `Plain`, matching behavior of `rst2xml.py`.-    + In image blocks, the description is parsed properly and-      used for the alt attribute, not also the title.-    + Skip blank lines at beginning of file. Resolves-      Debian #611328.--  * LaTeX reader:--    + Improved parsing of preamble.-      Previously you'd get unexpected behavior on a document that-      contained `\begin{document}` in, say, a verbatim block.-    + Allow spaces between `\begin` or `\end` and `{`.-    + Support `\L` and `\l`.-    + Skip comments inside paragraphs.--  * LaTeX writer:--    + Escape strings in `\href{..}`.-    + In nonsimple tables, put cells in `\parbox`.--  * OpenDocument writer:  don't print raw TeX.--  * Markdown writer:--    + Fixed bug in `Image`.  URI was getting unescaped twice!-    + Avoid printing extra blank lines at the end if there are-      no notes or references.--  * LaTeX and ConTeXt: Escape `[` and `]` as `{[}` and `{]}`.-    This avoids unwanted interpretation as an optional argument.--  * ConTeXt writer: Fixed problem with inline code.  Previously-    `}` would be rendered `\type{}}`. Now we check the string for '}' and '{'.-    If it contains neither, use `\type{}`; otherwise use `\mono{}`-    with an escaped version of the string.--  * `:` now allowed in HTML tags. Resolves Issue #274.--pandoc (1.6)--  [ John MacFarlane ]--  * New EPUB and HTML Slidy writers. (Issue #122)--      - EPUB is a standard ebook format, used in Apple's iBooks for-        the iPad and iPhone, Barnes and Noble's nook reader, the Sony-        reader, and many other devices.-      - Slidy, like S5, is a system for producing HTML+javascript slide-        shows.--  * All input is assumed to be UTF-8, no matter what the locale and ghc-    version, and all output is UTF-8. This reverts to pre-1.5 behavior.-    Also, a BOM, if present, is stripped from the input.--  * Markdown now supports grid tables, whose cells can contain-    arbitrary block elements. (Issue #43)--  * Sequentially numbered example lists in markdown with `@` marker.--  * Markdown table captions can begin with a bare colon and no longer need-    to include the English word "table." Also, a caption can now occur-    either before or after the table. (Issue #227)--  * New command-line options:--      - `--epub-stylesheet` allows you to specify a CSS file that will-        be used to style your ebook.-      - `--epub-metadata` allows you to specify metadata for the ebook.-      - `--offline` causes the generated HTML slideshow to include all-        needed scripts and stylesheets.-      - `--webtex` causes TeX math to be converted to images using the-        Google Charts API (unless a different URL is specified).-      - `--section-divs` causes div tags to be added around each section-        in an HTML document. (Issue #230, 239)--  * Default behavior of S5 writer in standalone mode has changed:-    previously, it would include all needed scripts and stylesheets-    in the generated HTML; now, only links are included unless-    the `--offline` option is used.--  * Default behavior of HTML writer has changed. Between 1.2 and 1.5,-    pandoc would enclose sections in div tags with identifiers on the-    div tags, so that the sections can be manipulated in javascript.-    This caused undesirable interactions with raw HTML div tags. So,-    starting with 1.6, the default is to put the identifiers directly-    on the header tags, and not to include the divs.  The `--section-divs`-    option selects the 1.2-1.5 behavior.--  * API changes:--      - `HTMLMathMethod`: Added `WebTeX`, removed `MimeTeX`.-      - `WriterOptions`: Added `writerUserDataDir`, `writerSourceDirectory`,-        `writerEPUBMetadata` fields. Removed `writerIncludeBefore`,-        `writerIncludeAfter`.-      - Added `headerShift` to `Text.Pandoc.Shared`.-      - Moved parsing code and `ParserState` from `Text.Pandoc.Shared`-        to a new module, `Text.Pandoc.Parsing`.-      - Added `stateHasChapters` to `ParserState`.-      - Added `HTMLSlideVariant`.-      - Made `KeyTable` a map instead of an association list.-      - Added accessors for `Meta` fields (`docTitle`, `docAuthors`,-        `docDate`).-      - `Pandoc`, `Meta`, `Inline`, and `Block` have been given `Ord`-        instances.-      - Reference keys now have a type of their own (`Key`), with its-        own `Ord` instance for case-insensitive comparison.-      - Added `Text.Pandoc.Writers.EPUB`.-      - Added `Text.Pandoc.UUID`.-      - Removed `Text.Pandoc.ODT`, added `Text.Pandoc.Writers.ODT`.-        Removed `saveOpenDocumentAsODT`, added `writeODT`.-      - Added `Text.Pandoc.Writers.Native` and `writeNative`.-        Removed `prettyPandoc`.-      - Added `Text.Pandoc.UTF8` for portable UTF8 string IO.-      - Removed `Text.Pandoc.Writers.S5` and the `writeS5` function.-        Moved `s5Includes` to a new module, `Text.Pandoc.S5`.-        To write S5, you now use `writeHtml` with `writerSlideVariant`-        set to `S5Slides` or `SlidySlides`.--  * Template changes.  If you use custom templates, please update them,-    particularly if you use syntax highlighting with pandoc. The old HTML-    templates hardcoded highlighting CSS that will no longer work with-    the most recent version of highlighting-kate.--      - HTML template: avoid empty meta tag if no date.-      - HTML template: Use default highlighting CSS from highlighting-kate-        instead of hard-coding the CSS into the template.-      - HTML template: insert-before text goes before the title, and-        immediately after the <body> tag, as documented. (Issue #241)-      - Added slidy and s5 templates.-      - Added amssymb to preamble of latex template. (github Issue 1)--  * Removed excess newlines at the end of output. Note: because output-    will not contain an extra newline, you may need to make adjustments-    if you are inserting pandoc's output into a template.--  * In S5 and slidy, horizontal rules now cause a new slide, so you-    are no longer limited to one slide per section.--  * Improved handling of code in man writer. Inline code is now monospace,-    not bold, and code blocks now use .nf (no fill) and .IP (indented para).--  * HTML reader parses `<tt>` as Code. (Issue #247)--  * html+lhs output now contains bird tracks, even when compiled without-    highlighting support. (Issue #242)--  * Colons are now no longer allowed in autogenerated XML/HTML identifiers,-    since they have a special meaning in XML.--  * Code improvements in ODT writer.  Remote images are now replaced with-    their alt text rather than a broken link.--  * LaTeX reader improvements:--      - Made latex `\section`, `\chapter` parsers more forgiving of-        whitespace.-      - Parse `\chapter{}` in latex.-      - Changed `rawLaTeXInline` to accept `\section`, `\begin`, etc.-      - Use new `rawLaTeXInline'` in LaTeX reader, and export `rawLaTeXInline`-        for use in markdown reader.-      - Fixes bug wherein `\section{foo}` was not recognized as raw TeX-        in markdown document.--  * LaTeX writer:  images are automatically shrunk if they would extend-    beyond the page margin.--  * Plain, markdown, RST writers now use unicode for smart punctuation.--  * Man writer converts math to unicode when possible, as in other writers.--  * `markdown2pdf` can now recognize citeproc options.--  * Command-line arguments are converted to UTF-8. (Issue #234)--  * `Text.Pandoc.TeXMath` has been rewritten to use texmath's parser.-    This allows it to handle a wider range of formulas. Also, if a formula-    cannot be converted, it is left in raw TeX; formulas are no longer-    partially converted.--  * Unicode curly quotes are left alone when parsing smart quotes. (Issue-    #143)--  * Cabal file changes:--      - Removed parsec < 3 restriction.-      - Added 'threaded' flag for architectures where GHC lacks a threaded-        runtime.-      - Use 'threaded' only for markdown2pdf; it is not needed for pandoc.-      - Require highlighting-kate 0.2.7.--  * Use explicit imports from `Data.Generics`. Otherwise we have a-    conflict with the 'empty' symbol, introduced in syb >= 0.2. (Issue #237)--  * New data files:  slidy/slidy.min.js, slidy/slidy.min.css, epub.css.--pandoc (1.5.1.1)--  [ John MacFarlane ]--  * Fixed uniqueIdent in Shared so that header identifiers work as-   advertized in the README and are are valid XHTML names.--pandoc (1.5.1)--  [ John MacFarlane ]--  * Fixed treatment of unicode characters in URIs.-    + Shared now exports escapeURI and unescapeURI. These handle-      UTF8 encoding and decoding as well as URI escaping/unescaping.-    + Shared: uri and emailAddress now return a pair of the original-      parsed text and the escaped URI (in the latter case, with-      the mailto: prefix).-    + HTML reader: unsanitaryURI has been modified to allow unicode-      high characters in a URI.-    + Readers:  All link and image URIs are now escaped using-      escapeURI.-    + Markdown and RST writers:  unescapeURI is used so that URIs-      in these formats are human-readable.--  * Setup.hs: Don't assume that the build directory is "dist".-    Instead, get it from localBuildInfo.--  * OpenDocument writer: Use a Map for stTextStyleAttr.-    This avoids duplicates (and invalid xml). Resolves Issue #222.--pandoc (1.5.0.1)--  [ John MacFarlane ]--  * HTML writer: Fixed error in math writer (with MathML option)-    that caused an infinite loop for unparsable MathML.--pandoc (1.5)--  [ John MacFarlane ]--  * Added --mathml option.  When this is selected, pandoc will convert-    TeX math into MathML.-    + Added data/MathMLinHTML.js, which is included when no URL is-      provided for --mathml.  This allows MathML to be displayed (in-      better browsers) as text/html.-    + Removed Text.Pandoc.LaTeXMathML.  The module was no longer-      necessary; it was replaced by two lines in pandoc.hs.-    + Replaced LaTeXMathML.js.commend and LaTeXMathML.js.packed with a-      single combined file, LaTeXMathML.js.--  * Added --data-dir option.-    This specifies a user data directory. If not specified, will default-    to ~/.pandoc on unix or Application Data\pandoc on Windows.-    Files placed in the user data directory will override system default-    data files.--  * Added Maybe datadir parameter to readDataFile, saveOpenDocumentAsODT,-    latexMathMLScript, s5HeaderIncludes, and getDefaultTemplate. If-	  Nothing, no user directory is searched for an override.--  * Added 'plain' output format. This is similar to markdown, but-    removes links, pictures, inline formatting, and most anything that-    looks even vaguely markupish. The function writePlain is exported by-    Text.Pandoc.Writers.Markdown, with which it shares most of its code.--  * Allow multi-line titles and authors in meta block.-    Titles may span multiple lines, provided continuation lines-    begin with a space character.  Separate authors may be put on-    multiple lines, provided each line after the first begins with-    a space character.  Each author must fit on one line. Multiple-    authors on a single line may still be separated by a semicolon.-    Based on a patch by Justin Bogner.--  * When given an absolute URI as parameter, pandoc will try to fetch-    the content via HTTP.  So you can do:-    'pandoc -r html -w markdown http://www.fsf.org'-    Adds dependency on HTTP.--  * Made HTML reader much more forgiving.-    + Incorporated idea (from HXT) that an element can be closed-      by an open tag for another element.-    + Javascript is partially parsed to make sure that a <script>-      section is not closed by a </script> in a comment or string.-    + More lenient non-quoted attribute values.-      Now we accept anything but a space character, quote, or <>.-      This helps in parsing e.g. www.google.com!-    + Bare & signs are now parsed as a string.  This is a common-      HTML mistake.-    + Skip a bare < in malformed HTML.--  * Removed html2markdown and hsmarkdown.-    + html2markdown is no longer needed, since you can now pass URI-      arguments to pandoc and directly convert web pages. (Note,-      however, that pandoc assumes the pages are UTF8. html2markdown-      made an attempt to guess the encoding and convert them.)-    + hsmarkdown is pointless -- a large executable that could be-      replaced by 'pandoc --strict'.--  * In most writers, an image in a paragraph by itself is now rendered-    as a figure, with the alt text as the caption. (Texinfo, HTML, RST,-    MediaWiki, Docbook, LaTeX, ConTeXt, HTML.) Other images are-    rendered inline.--  * Depend on extensible-exceptions.  This allows pandoc to be compiled-    on GHC 6.8.--  * Added --base-header-level option.  For example, --base-header-level=2-    will change level 1 headers to level 2, level 2 to level 3, etc.-    Closes Debian #563416.--  * Incomplete support for RST tables (simple and grid).-    Thanks to Eric Kow. Colspans and rowspans not yet supported.--  * Added accessors (docTitle, docAuthors, docDate) to Meta type.--  * MediaWiki writer:  format links with relative URLs as wikilinks.-    The new rule:  If the link target is an absolute URL, an external-    link is created. Otherwise, a wikilink is created.--  * Text.Pandoc.Shared: Export uniqueIdent, and don't allow tilde in-    identifier.  Note:  This may break links to sections that involve-    tildes.--  * Markdown(+lhs) reader:  handle "inverse bird tracks."-    Inverse bird tracks (<) are used for haskell example code that is not-    part of the literate Haskell program.  Resolves Issue #211.--  * LaTeX reader:-    + Recognize '\ ' (interword space).-    + Recognize nonbreaking space '~'.-    + Ignore \section, \pdfannot, \pdfstringdef.  Ignore alt title in-      section headers.  Don't treat \section as inline LaTeX.-      Resolves Issue #202.-    + LaTeX reader:  allow any special character to be escaped.-      Resolves Issue #221.-    + LaTeX reader: treat \paragraph and \subparagraph as level 4, 5-      headers.  Resolves Issue #207.--  * Use template variables for include-before/after.-    + These options now imply -s; previously they worked also in fragment-      mode.-    + Users can now adjust position of include-before and include-after-      text in the templates.-    + Default position of include-before moved back (as it was before 1.4)-      before table of contents.-    + Resolves Issue #217.--  * Don't print an empty table header: (all writers).-    Resolves Issue #210.--  * HTML, Docbook writer: Use tbody, thead, and cols in tables.--  * HTML writer: Don't include TOC div if table of contents is empty.--  * Markdown writer:  Fixed citations.-    Previously the markdown writer printed raw citation codes, e.g.-    [geach1970], rather than the expanded citations provided by-    citeproc, e.g. (Geach 1970). Now it prints the expanded citations.-    This means that the document produced can be processed as a markdown-    document without citeproc. Thanks to dsanson for reporting, and-    Andrea Rossato for the patch.--  * Improved and simplified title block in context template.-    Previously it caused an error if there was no title.-    This method should also be easier for users to customize.--  * Markdown reader:-    + Treat p., pp., sec., ch., as abbreviations in smart mode.-    + Disallow blank lines in inline code span.-    + Allow footnotes to be indented < 4 spaces.-      This fixes a regression.  A test case has been added.-    + Escape spaces in URLs as %20. Previously they were incorrectly-		  escaped as +, which is appropriate only for the query part of-			a URL. Resolves Issue #220.-    + Require two spaces after capital letter + period for list item.-      Otherwise "E. coli" starts a list. This might change the semantics-      of some existing documents, since previously the two-space-      requirement was only enforced when the second word started-      with a capital letter. But it is consistent with the existing-      documentation and follows the principle of least surprise.-      Resolves Issue #212.--  * LaTeX template: redefine labelwidth when using enumerate package.-    Otherwise the list labels (numbers) often extend past the left-    margin, which looks bad.--  * Mediawiki writer: Don't print a "== Notes ==" header before-    references.  This is too English-centric. Writers can provide their-    own header at the end of the document.--  * Promoted mediawiki headers.  '= head =' is now level 1, '== head =='-    level 2, etc.  This seems to be correct; it's only by convention-    that wikipedia articles have level 2 headers at most.-    Patch due to Eric Kow.--  * RunTests.hs: Set LANG to a UTF-8 locale. Use 'pandoc --data-dir=' so-    data files don't need to have been installed. This removes the need to-    set HOME.--  * HTML reader:-    + Handle spaces before <html>.  Resolves Issue #216.-    + Be forgiving in parsing a bare list within a list.-      The following is not valid xhtml, but the intent is clear:-      <ol>-      <li>one</li>-      <ol><li>sub</li></ol>-      <li>two</li>-      </ol>-      We'll treat the <ol> as if it's in a <li>.  Resolves Issue #215.--  * Updated INSTALL instructions.  cabal method is now promoted.--  * Updated markdown2pdf man page. It no longer says all pandoc options-    are accepted.--  * README/man pages: Removed advice to pipe through tidy before HTML-    reader.  This is obsolete, now that we have a forgiving HTML parser.--  * LaTeX writer: set numbersections template variable, so-    the section numbering options work again.--  * Removed obsolete Makefile.--  * Website: renamed index.txt.in -> index.txt.--  * New batch file to make-windows-installer.-    + Removed old Makefile.windows-    + Added make-windows-installer.bat-    + Modified default installer name in pandoc-setup.iss--  * Removed freebsd and macports directories.-    They are no longer up to date.--  * Setup.hs:-    + Made man page building sensitive to build verbosity.-    + Improved detection of highlighting support in test hook.-    + Install wrapper scripts into cabal bin directory.-    + Also simplified installManpages.-    + Setup.hs: install manpages to mandir.  Code borrowed from darcs.--  * Changed default of writerXeTeX to False.--  * HTML writer: don't include empty UL if --toc but no sections.-    Resolves Issue #199.--  * LaTeX writer:--    + If book, report, or memoir documentclass, use \chapter{}-      for first-level headers. Otherwise use \section{}.-    + Removed stLink, link template variable. Reason: we now always-      include hyperref in the template.--  * LaTeX template:--    + Only show \author if there are some.-    + Always include hyperref package. It is used not just for links but-      for toc, section heading bookmarks, footnotes, etc. Also added-      unicode=true on hyperref options.--  * markdown2pdf: always do at least two runs. hyperref bookmarks-    require this.--  * cabal file: Removed unneeded dependency on template-haskell.--  * Windows installer - fixed bug in data file locations.-    Resolves Issue #197.--  * Deprecated --custom-header in documentation.-    Removed old "Custom Headers" section in README.--pandoc (1.4)--  [ John MacFarlane ]--  * Pandoc will now compile with either GHC 6.10 or 6.12.-    + Don't use System.IO.UTF8 when compiling with 6.12-    + Use -fno-warn-unused-do-bind option when compiling with 6.12--  * Replaced old headers with templates.  Now users have much more-    control over the way documents appear in --standalone mode,-    and writer code is simplified.  Resolves Issues #59, 147.-    Every effort has been made to retain backwards compatibilty.-    So, the --custom-header option should still work as before.--    + Added Text.Pandoc.Templates.  This provides functions for-      retrieving default templates and for rendering templates.-    + System templates (in the pandoc data directory) can be-      overridden by user templates in $HOME/.pandoc/templates.-    + Removed Text.Pandoc.DefaultHeaders.-    + Removed data/headers directory.-    + Added templates directory.-    + Added writerTemplate and writerVariables fields to WriterOptions.-    + Removed writerTitlePrefix, writerHeader fields from WriterOptions.-    + Changed --print-default-header to --print-default-template.-    + Added --template option.-    + Added -V/--variable option to set custom template variables.--  * Pandoc no longer requires Template Haskell.  Resolves Issue #186.--    + Removed need for TH in ODT module. Instead get reference.odt from-	  data file at run time.-    + Removed TH dependency from S5 module. S5 module now exports-      s5HeaderIncludes, which pandoc.hs includes if writer is s5 and-      standalone.-    + Refactored LaTeXMathML not to use TH.--  * Meta is now Meta [Inline] [[Inline]] [Inline] rather than-    Meta [Inline] [String] String. Authors and date in Meta are now lists-    of Inline elements rather than raw strings. This means that they can-    be formatted and can include footnotes. NOTE: This may be a breaking-    change for those using pandoc as a library.--  * Added readDataFile to Text.Pandoc.Shared.  This retrieves-    a data file from the user pandoc data directory (~/.pandoc-    on unix), or, if not found there, from the system data-    directory ($CABALDIR/shared/pandoc-VERSION/). All data-    files, including templates, LaTeXMathML.js, s5 styles,-	and reference.odt, can be overridden by the user.--  * s5 files moved from data/ui/default to s5/default.--  * Use unicode instead of entities in HTML and XML output.  Resolves-    Issue #163.--  * Prettier HTML footnote references:  put anchor inside sup,-    instead of other way.  Resolves Issue #191. Thanks to-    infinity0x.--  * Added --xetex option to pandoc and markdown2pdf.-    If --xetex is specified, pandoc produces latex suitable for-    processing by xelatex, and markdown2pdf uses xelatex to create-    the PDF. Resolves Issue #185.--  * RTF writer: multiple authors now occupy multiple paragraphs rather-    than using a line break.--  * Man writer: now the "--after-body" will come after the "AUTHORS"-    section, whereas before it would come before it.  This is a-    slight break from backwards compatibility.--  * Added --reference-odt option, so users may customize the styles-    used in pandoc-generated ODT files.  Users may also place a-	default reference.odt in the ~\.pandoc directory.--  * ODT writer:-    + Indented and line-broke styles.xml so it can be modified more easily.-    + Omitted some unnecessary style declarations.-    + Don't wrap text in OpenDocument writer.  The tags are too long, making-      wrapping ugly and pointless.--  * LaTeX reader: use \\ to separate multiple authors.--  * Markdown reader: use ; as separator between authors.-    This allows you to use ',' within author names: e.g. "John Jones, Jr."--  * S5 writer: use linebreak to separate authors in title page.--  * RST reader: Allow :: before lhs code block. The RST spec requires the-    :: before verbatim blocks. This :: should not be treated as literal-    colons. Resolves Issue #189.--  * Documented pandoc 1.3's new definition list syntax in README.-    (An oversight in the last release.)--  * markdown2pdf.hs:-    + interpret ! in a log as an error line.-    + --toc now works properly.--  * Changes in RunTests.hs:-    + Use the Diff library rather than a local copy of Diff.hs.-      (This vastly increases performance.) This change means that 'cabal-      test' presupposes that the Diff library is installed.-    + Removed tests/Diff.hs from cabal file.-    + Changed RunTests to use local environment. We need at least HOME, so-      pandoc can find its data directory.--  * Updated windows installer to install data files in the app directory.--  * Windows installer now installs portable wrappers hsmarkdown and-    markdown2pdf.--pandoc (1.3)--  [ John MacFarlane ]--  * Added --id-prefix option (Issue #41). This adds a prefix to all-    automatically generated HTML identifiers, which helps prevent-    duplicate identifiers when you're generating a fragment (say a blog-    post).--  * Added --indented-code-classes option.  This specifies classes-    to use for indented code blocks.  (Patch due to buttock; Issue #87.)--  * --number-sections now affects HTML output as well as ConTeXt and LaTeX-    (Issue #150).--  * Improved syntax for markdown definition lists (Issue #24).-    Definition lists are now more compatible with PHP Markdown Extra.-    + You can have multiple definitions for a term (but still not-      multiple terms).-    + Multi-block definitions no longer need a column before each block-      (indeed, this will now cause multiple definitions).-    + The marker no longer needs to be flush with the left margin,-      but can be indented at or two spaces.  Also, ~ as well as :-      can be used as the marker (this suggestion due to David-      Wheeler.)-    + There can now be a blank line between the term and the-      definitions.--  * Better looking simple tables.  Resolves Issue #180.-    + Markdown reader: simple tables are now given column widths of 0.-    + Column width of 0 is interpreted as meaning: use default column width.-    + Writers now include explicit column width information only-      for multiline tables.  (Exception:  RTF writer, which requires-      column widths.  In this case, columns are given equal widths,-      adding up to the text width.)-    + Simple tables should now look better in most output formats.--  * Allow markdown tables without headers (Issue #50).-    The new syntax is described in README. Also allow optional line of-    dashes at bottom of simple tables.--  * Compensate for width of final table column (Issue #144).--  * Treat a backslash followed by a newline as a hard line break-    in markdown.  Resolves Issue #154.  This is a nice alternative-	to markdown's "invisible" way of indicating hardline breaks-	using lines that end with two spaces.--  * Improved performance of markdown reader by ~10% by eliminating the-    need for a separate parsing pass for notes. Raw notes are now stored-    on the first pass (which parses references), then parsed when the-    note is inserted into the AST. The stateNotes field in ParserState-    is now a list of [(String, String)] pairs instead of [(String,-    [Block])].--  * In markdown reader, treat 4 or more * or _ in a row as literal-    text.  (Trying to parse long strings of * or _ as strong or emph-	leads to exponential performance problems.)--  * Markdown reader: Use + rather than %20 for spaces in URLs.--  * Fixed htmlComment parser, adding a needed 'try'.--  * Don't print raw HTML in man output.--  * Allow . _ and ~ in header identifiers.--  * Specially mark code blocks that were "literate" in the input.-    They can then be treated differently in the writers.  This allows-    authors to distinguish bits of the literate program they are writing-    from source code examples, even if the examples are marked as-    Haskell for highlighting.  (Issue #174.)--  * Modified html+lhs output to use "haskell" highlighter instead-    of "literateHaskell". The highlighting module now adds bird tracks-	after highlighting (for HTML output), if the code block has the-	"literate" class.  This gives better results, because kate's-    haskell highlighter is much better than the literateHaskell-    highlighter.--  * Fixed handling of footnotes in titles (HTML) and headers (LaTeX).-    (Issue #137.)--  * Support for "..code-block" directive in RST reader. Not core-    RST, but used in Sphinx for code blocks annotated with syntax-    information. Thanks to Luke Plant for the patch.--  * Added "head" to list of block-level HTML tags. Resolves-    Issue #108.--  * Added stripTags to Text.Pandoc.XML.  This is used in the HTML writer.--  * Set utf-8 encoding in texinfo headers.--  * Docbook writer: add ids to sections.  Use link for internal links.-    (Issue #60.)--  * Blank lines after lists in MediaWiki writer.--  * Properly handle commented-out list items in markdown.-    Resolves Issue #142.  Example:--    - a-    <!---    - b-    -->-    - c--  * Changed heuristic in compactify. compactify has to decide whether a-    Para that ends a list is a Para intentionally, or just because of-    the blank lines at the end of every list. In the latter case the-    Para is turned to a Plain. The old heuristic was: change final Para-    to Plain iff the other items all end in Plain. This produces bad-    results when, for example, an item contains just a Plain and an HTML-    comment, as it does in the list above. The new heuristic: change-    final Para to Plain iff the other items don't contain a Para.--  * Added % as an rst underline character.  Resolves Issue #173.--  * Fix inline math parser so that \$ is allowed in math.-    Resolves Issue #169.--  * Translate \int (integral) into unicode when using unicode math-    method. Resolves Issue #177.--  * markdown2pdf.hs improvements:-    + Use System.IO.UTF8.-    + Print error messages on last attempt.-    + Do not create a backup when overwriting a PDF (Issue #166).-    + Accept --longopt=val options.-    + Added man/man1/markdown2pdf.1 to extra-tmp-files in cabal, so that-      it is properly cleaned.--  * Added haddock comments warning that readers assume \n line endings.--  * Updated COPYRIGHT file.--  * Makefile: Changed EXECSBASE so it doesn't pull in hsmarkdown &-    markdown2pdf. Otherwise strip tries to strip shell scripts when you-    install using 'make'.--  * Changed Makefile so it doesn't build Haskell wrappers.--  * Fixed Makefile so it doesn't try to build man pages in build-doc.--  * Install pcre3.dll in Windows install script; this allows us to-    package a version of pandoc with highlighting support.--pandoc (1.2.1)--  [ John MacFarlane ]--  * Fixed regression with --preserveTabs. Brought back optPreserveTabs.-    The trick of setting tabStop to 0 to mean "preserve tabs" had a bad-    side effect: strings of 0 spaces were interpreted as indentation.-    So, with --preserve-tabs, unindented paragraphs were treated as-    code. Resolves Issue #138.--  * HTML writer:  wrap sections in divs.  Resolves Issue #70.--    + hierarchicalize has been rationalized; it builds a hierarchical-      representation of the document from the headers, and simultaneously-      gives each section a unique identifier based on the heading title.-    + Identifiers are now attached to the divs rather than-      to the headers themselves.-    + Table of content backlinks go to the beginning of the table, rather-      than to the section reference that was clicked.-    + Code for constructing identifiers has been moved to Text.Pandoc.Shared-      from the HTML writer, since it is now consumed only by-      hierarchicalize.-    + In --strict mode, pandoc just prints bare headings, as before-      (unless --toc has been specified).-    + In s5 output, it does not wrap sections in divs, as that seems to-      confuse the s5 javascript.--  * Man writer: break lines at end of each sentence. groff expects this-    and treats '.' and '?' differently when followed by line ending as-    opposed to ordinary space. Also, don't escape periods. Instead, use-    zero-width character \& to avoid unwanted interpretation of periods-    at start of line. Resolves Issue #148.--  * Markdown writer:  Added '#' and '>' to list of characters to be-    escaped in markdown output.  Removed '<', as it is not an officially-    escapable character. This partially resolves Issue #96.--  * Make --smart the default for man output format. Otherwise we have-    trouble dividing lists of endlines into sentences.--  * DocBook writer: Use language attribute to indicate source language-    in code blocks.--  * RST reader:--    + Allow # to continue list, even if the list was started with an-      explicit marker. For example:--        A. my list-		#. continued--      Resolves Issue #140.-    + Allow continuation lines in line blocks. Also added test cases for-      line blocks for RST reader. Resolves Issue #149.-    + Allow explicit links with spaces in URL: `link <to this>`_--  * Improved LaTeX reader's coverage of math modes. Remove displaymath*-    (which is not in LaTeX) and recognize all the amsmath environments-    that are alternatives to eqnarray, namely equation, equation*,-    gather, gather*, gathered, multline, multline*, align, align*,-    alignat, alignat*, aligned, alignedat, split. Resolves Issue #103.-    Thanks to shreevatsa.public for the patch.--  * Markdown reader:--    + Allow -, _, :, . in markdown attribute names. These are legal in-      XML attribute names.-    + Use non-breaking spaces in abbreviations.-    + Markdown reader: improved efficiency of abbreviation parsing.-      Instead of a separate abbrev parser, we just check for-      abbreviations each time we parse a string. This gives a huge-      performance boost with -S. Resolves Issue #141.--  * Improved efficiency of shared parsers:  hexNum, htmlComment,-    whitespace, indentSpaces.--  * Export HTMLMathMethod in Text.Pandoc.--  * Export languagesByExtension in Text.Pandoc.Highlighting.--  * Added new Haskell version of markdown2pdf, due to-    Paulo Tanimoto.  This should be more portable than the old-	shell script.--  * Made 'pandoc -v' more explicit about compiler options.-    Resolves Issue #139.--  * pandoc.hs:  Made --strict compatible with --standalone, --toc.--  * Use Paths_pandoc to get version number, instead of hard-coding it-    into Text/Pandoc.hs.--pandoc (1.2)--  [ John MacFarlane ]--  * Added support for literate Haskell. lhs support is triggered by-    '+lhs' suffixes in formats. For example, 'latex+lhs' is literate-    Haskell LaTeX. '.lhs' files are treated by default as literate-    markdown.--    + Added stateLiterateHaskell to parser state.-    + Added parser for lhsCodeBlock to Markdown, RST, LaTeX readers.-    + Added parser for |inline lhs| to LaTeX reader.-    + Added writerLiterateHaskell to WriterOptions.-    + Added lhs support to Markdown, RST, LaTeX, HTML writers.-    + Added definition of code environment to LaTeX header.-    + Added tests (run only if highlighting support compiled in).-    + Documented lhs features in man page and README.--  * In Text.Pandoc.Definition, added processWith, processWithM,-    and queryWith, and deprecated processPandoc and queryPandoc-    for these more general functions.--  * Fixed bug in mediawiki writer:  improper closing tags in tables.-    Thanks to Benct Philip Jonsson for reporting the bug.--  * Added --email-obfuscation option.--    + Added writer option for email obfuscation.-    + Implemented email obfuscation options in HTML writer.-    + Added option to option parser.-    + Documented in README and pandoc man page.-    + Resolves Issue #97.--  * LaTeX writer: fixed bug with empty table cells.-    Resolves Issue #107.  Thanks to rodja.trappe for the patch.--  * Fixed bug with header spacing in Markdown and RST writers.-    A null header (Meta [] [] []) should not cause a blank line-    at the beginning of output.  But a blank line is needed between-    a non-null header and the main text.--  * Markdown reader: Relax spacing rules for $$ in display math. Now-    space and newlines are allowed after the opening $$ and before the-    closing $$. However, the display math cannot contain an entirely-    blank line. Resolves Issue #105.--  * Markdown reader: Gobble space after Plain blocks containing only-    raw html inline. Otherwise following header blocks are not parsed-    correctly, since the parser sees blank space before them. Resolves-    Issue #124.--  * Markdown reader: Allow " as well as '' to end a latex double-quote.--  * Conditionally depend on syb and base >= 4 if ghc >= 6.10.-    Resolves Issue #109.--  * Fixed problems in RST and markdown output due to bug in pretty-1.0.1.0--    + Added hang' function to Text.Pandoc.Shared; this will be used instead-      of hang, which doesn't work properly in pretty-1.0.1.0.  When pretty-      is upgraded, we can go back to hang.-      See  http://article.gmane.org/gmane.comp.lang.haskell.general/16687-    + Use hang' (and some different techniques) in RST and markdown writers.-      Some output is now a bit different.--  * Brought citeproc support up to date for citeproc-hs-0.2.-    (Patch by Andrea Rossato.)--  * Moved all haskell source to src subdirectory.  Renamed Main.hs to-    pandoc.hs.--  * Rewrote hsmarkdown in Haskell for portability (src/hsmarkdown.hs).-    For now, keeping the old shell script too.--  * Added TemplateHaskell to Extensions for executable, removed-    -threaded for library. Thanks to duncan.coutts for the bug report.-    Resolves Issue #121.--  * Moved some Extra-Source-Files to Data-Files.--  * Moved tabFilter to Shared.--  * In pandoc.hs, removed optPreserveTabs; instead, tabstop of 0 means-    preserve tabs.--  * Minor code cleanup based on hlint suggestions.--pandoc (1.1)--  [ John MacFarlane ]--  * Main.hs:--    + Changed date on copyright message in Main.hs.-    + Have the '-v' option print syntax highlighting languages-      separated by commas, and wrapped in lines, instead of in five-      columns as before.--  * Added --jsmath option.  Resolves Issue #68.--    + Added --jsmath option to Main.hs-    + Added JsMath to HTMLMathMethod in Text.Pandoc.Shared.-    + Handle math appropriately in HTML writer when JsMath selected.-    + Documented the option in README and man page.--  * Text.Pandoc.Shared:  Changed compactify to use a better heuristic-    for tight and loose lists. Final Para is changed to Plain if all-    other list items *end* with a Plain block. Addresses Issue #99.--  * HTML reader:--    + Added colons to protocols in unsanitaryURI. Closes Issue #88.-    + HTML reader: Don't interpret contents of <pre> blocks as markdown.-      Added rawVerbatimBlock parser.  Resolves Issue #94.--  * Markdown reader:--    + Allow URLs with spaces in them in links and references, but escape-      them as "%20".-    + Allow blank space at the end of horizontal rules.--  * RST reader: Modified 'unknownDirective' parser to handle comment-    blocks correctly, and added tests for comment blocks. Resolves Issue-    #86. Closes Debian Bug #500662.--  * HTML writer:--    + Include classes on tr elements in HTML output:-      "header", "odd", "even".  This allows tables to be styled with-      lines in alternating colors.  Resolves Issue #91.-    + Enclose all LaTeXMathML bits in <span class="LaTeX">.-      This prevents parts of the document that are not math from being-      interpreted as math by LaTeXMathML.js.--  * OpenDocument and ODT writers:  Added support for HorizontalRule elements,-    which were formerly ignored.  Resolves Issue #95.--  * Text.Pandoc.Shared:  Modified wrappedTeX to eliminate the line break-    between a footnote and immediately following nonspace characters in-    LaTeX and ConTeXt output. (This gets interpreted as a space, which-    is not desired in cases like "text^[note]---".)  Resolves Issue #93.--  * Windows installer: Don't require admin privileges to run-    installer.  Modified pandoc-setup.iss, and changed modpath.iss to-    modify HKCU path if user lacks admin privileges.  Also fixed case-    where oldpath is empty (previously this led to the new path-    beginning with a semicolon).--  * Updated INSTALL instructions for Arch packages and OS X install using-    cabal-install.--  * Removed the (now unneeded) debian directory.-    Removed empty Codec and System directories.--  * Moved odt-styles/ to data/.  Removed unneeded variable in Makefile.--  * Modified Setup.hs so that the "test" target returns an error status-    when tests fail, and "build" returns a success status if-    the build succeeds.  Resolves Issue #100.--  * Added BUGS to files in tarball.---pandoc (1.0.0.1)--  [ John MacFarlane ]--  * Removed spurious reference to pdf output format from pandoc(1) man page.--pandoc (1.0)--  [ Andrea Rossato ]--  * Added new OpenDocument writer.--  * Added support for SmallCaps inline element.--  * Added support for integrating pandoc with citeproc-hs.--    + Added Cite element to definition and writers.-    + Added Text.Pandoc.Biblio module-    + Note: This support is included only if the 'citeproc'-      Cabal configuration flag is set.--  * Made Pandoc data structure an instance of Typeable.-    Added new processPandoc and queryPandoc functions, to query-    or transform matching elements in a Pandoc structure.--  [ Peter Wang ]--  * Added new Texinfo writer.--  [ John MacFarlane ]--  * Changes to Texinfo writer:--    + No space between paragraph and following @verbatim (provides more-      pleasing appearance in text formats)-    + Blank line consistently after list environments.-    + Removed deVerb.-    + Use @code instead of @verb for inline code (this solves the character-      escaping problem for texi2dvi and texi2pdf).-    + Added news of Texinfo writer to README.-    + Added Texinfo to list of formats in man page, and removed extra 'groff'.-    + Added texi & texinfo extensions to Main.hs, and fixed bug in determining-      default output extension.-    + Modified disallowedInNode in Texinfo writer to correct list of disallowed characters.--  * Added tests for OpenDocument writer.--  * Added ODT writer (using zip-archive library to package output of-    OpenDocument writer).  Added odt-styles directory with default ODT styles.--  * Added new mediawiki writer and tests.--  * Markdown reader: Added support for delimited code blocks, with optional-    syntax highlighting using highlighting-kate (if the 'highlighting'-    configuration option is selected).--    + Currently highlighting is supported only in the HTML writer.-    + Delimited code blocks can have attributes; using the language name as-      class triggers highlighting.-    + New Attributes parameter in CodeBlock structure.-    + --version now indicates whether syntax highlighting support is compiled-      in, and prints a list of supported languages--  * Removed debian directory. Pandoc is no longer a native debian package.--  * Changes to build process:  pandoc can now be built from the repository-    using Cabal.  No unix tools are needed (so, pandoc can be built on Windows-    without Cygwin).--    + Include shell scripts themselves in repo, rather than generating from wrappers.-      Removed wrappers directory and wrappers Makefile target.-    + Text/Pandoc/ASCIIMathML.hs, Text/Pandoc/DefaultHeaders.hs,-      and Text/Pandoc/Writers/S5.hs are no longer built in Makefile-      from templates in the templates/ directory. Instead, they use template-      haskell to read data at compile time from the relevant files in data/.-      Template haskell functions go in a new module, Text.Pandoc.TH.-    + man pages are now generated in Setup.hs hook, not by Makefile-    + Makefile 'tarball' target now calls Cabal's 'sdist'-    + Added "Extra-Source-Files" to pandoc.cabal, so sdist contains everything needed-    + Added "Build-Type" field to pandoc.cabal to avoid warning.-    + Added to "Extra-source-files" and "Extra-tmp-files" in pandoc.cabal,-      so 'sdist' and 'clean' will work properly.-    + Setup.hs now generates man pages in a postbuild hook.-    + Added dependency-checking to Setup.hs, so it only rebuilds things-      that need rebuilding.-    + Added 'library' and 'executable' configuration flags.-      Cabal can now be told to build just the library or just the executable.-    + CABALOPTS may now be specified with 'make' to pass Cabal configuration flags.-      For example:  CABALOPTS=-fhighlighting make--  * Rewrote test suite so it doesn't depend on perl or unix tools.--    + Replaced old runtests.pl with a Haskell script RunTests.hs.-    + Added Diff.hs module to be used by RunTests.hs instead of unix 'diff'.-    + Added test hook to Setup.hs, so tests may be run from cabal.-    + Changed Makefile's 'test' target to run tests via cabal.-    + Removed old generate.sh.-    + Since we no longer have 'sed' to filter out raw HTML sections-      from the docbook writer test, or raw LaTeX sections from the-      context writer test, we now just include these sections.-      They can be taken out if it is necessary to process the files.-    + Updated latex and context writer tests to remove extra spaces-      after '\\item'-    + Added a markdown table reader test.-    + Added markdown-reader-more.txt to test suite, for additional test cases-      for raw ConTeXt environments and more.--  * Compatibility fixes for CPP, Cabal, and haddock:--    + Use CPP in "Extensions" field in pandoc.cabal.-    + Removed use of backslash string continuations in source files.--  * Removed pandoc.cabal.ghc66.  We now require Cabal >= 1.2, GHC >= 6.8,-    base >= 3.--  * Require parsec < 3.-    The compatibility module in parsec 3.0.0 gives far worse performance than-    parsec 2.1.  Eventually pandoc will be upgraded to use the new bytestring-    version of parsec, and then we'll go to parsec 3.0.0.--  * Removed Text.Regex dependencies by rewriting using plain Haskell-    (Text.Pandoc.Writers.RTF, Text.Pandoc.Writers.HTML, Main.hs)--  * Moved Text.Pandoc.Writers.DefaultHeaders -> Text.Pandoc.DefaultHeaders.--  * Makefile:--    + Added 'configure' as dependency of 'uninstall-all'.-      (It uses the Cabal build program.)-    + Makefile:  only use --with-hc-pkg if GHC_PKG is defined.-      Note that Cabal will automatically choose the ghc-pkg appropriate-      for the compiler selected, so normally specifying GHC by itself-      is sufficient.--  * Removed Text.Pandoc.UTF8 module; instead, depend on utf8-string and use-    its IO and conversion functions.--  * Added -Wall to ghc-options in pandoc.cabal.  Cleaned up modules so that-    everything is -Wall clean.--    + Added pragma to HTML writer to avoid deprecation warning for use of "start" attribute.-    + Added pragma to Text/Pandoc/Shared.hs to get rid of "orphan instance" warnings.-      (These are caused by the Lift instance for ByteString.)--  * Changed the comment used to replace unsafe HTML if sanitize-html option-    selected.--  * Made -c/--css option repeatable on the command line (like -H, -A, -B).--  * Moved XML-formatting functions to new unexported module Text.Pandoc.XML.--  * Escape '\160' as "&#160;", not "&nbsp;" in XML.-    "nbsp" isn't a predefined XML entity.--  * Fixed bug in RST reader, which would choke on: "p. one\ntwo\n".-    Added some try's in ordered list parsers.--  * Man writer:  don't escape " as \".--  * Allow newline before URL in markdown link references.  Resolves Issue #81.-    Added tests for this issue in new "markdown-reader-more" tests.-    Changed RunTests.hs to run these tests.--  * Support for display math.  Resolves Issue #47.--    + Added a DisplayMath/InlineMath selector to Math inlines.-    + Markdown parser yields DisplayMath for $$...$$.-    + LaTeX parser yields DisplayMath when appropriate.  Removed-      mathBlock parsers, since the same effect is achieved by the math-      inline parsers, now that they handle display math.-    + Writers handle DisplayMath as appropriate for the format.-    + Modified tests accordingly; added new tests for display math.--  * Use LaTeXMathML instead of ASCIIMathML.  LaTeXMathML is closer-    to LaTeX in its display of math, and supports many non-math LaTeX environments.--    + Changed -m option to use LaTeXMathML rather than ASCIIMathML.-    + Modified HTML writer to print raw TeX when LaTeXMathML is-      being used instead of suppressing it.-    + Removed ASCIIMathML files from data/ and added LaTeXMathML.-    + Replaced ASCIIMathML with LaTeXMathML in source files.-    + Modified README and pandoc man page source.-    + Added --latexmathml option (kept --asciimathml as a synonym-      for backwards compatibility)--  * Markdown reader: Parse setext headers before atx headers.-    Test case:-       # hi-       ====-    parsed by Markdown.pl as an H1 header with contents "# hi".--  * Markdown reader: Treat "mixed" lists the same way as Markdown.pl does.-    The marker on the first list item determines the type of the whole-    list.  Thus, a list like-       1. one-       -  two-       *  three-    gets parsed as a single ordered list.  (Previous versions of pandoc-    treated this as an ordered list with an unordered sublist.)--  * Markdown smart typography:--    + Em dashes no longer eat surrounding whitespace.  Resolves Issue #69.-    + Use nonbreaking spaces after known abbreviations in markdown parser.-      Thus, for example, "Mr. Brown" comes out as "Mr.~Brown" in LaTeX, and does-      not produce a sentence-separating space.  Resolves Issue #75.--  * Markdown writer: Print unicode \160 literally, rather than as &nbsp;.--  * Treat '\ ' in (extended) markdown as nonbreaking space.-    Print nonbreaking space appropriately in each writer (e.g. ~ in LaTeX).--  * The '--sanitize-html' option now examines URIs in markdown links-    and images, and in HTML href and src attributes.  If the URI scheme-    is not on a whitelist of safe schemes, it is rejected.  The main point-    is to prevent cross-site scripting attacks using 'javascript:' URIs.-    See http://www.mail-archive.com/markdown-discuss@six.pairlist.net/msg01186.html-    and http://ha.ckers.org/xss.html.  Resolves Issue #62.--  * HTML writer:--    + Override Text.XHtml's stringToHtml function,-      so that characters below 0xff are not converted to numerical entity-      references. Also convert '\160' to "&nbsp;". This should aid readability-      and editability of the HTML source. It does presuppose that the HTML-      will be served as UTF-8.-    + In code blocks, change leading newlines to <br /> tags.-      (Some browsers ignore them.)  Resolves Issue #71.-      See http://six.pairlist.net/pipermail/markdown-discuss/2008-May/001297.html-    + Use style attributes rather than css classes for strikethrough-      and ordered list styles.  This works better when fragments, rather than-      standalone documents, are generated.--  * HTML reader: Count anything that isn't a known block (HTML) tag as an-    inline tag (rather than the other way around).  Added "html", "head", and-    "body" to list of block tags.  Resolves Issue #66, allowing-    <lj> to count as an inline tag.--  * RTF writer: Fixed bug.  Extra spaces were being printed after emphasized,-    boldface, and other inline elements.  Resolves Issue #64.--  * LaTeX reader:  improvements in raw LaTeX parsing.--    + "loose punctuation" (like {}) parsed as Space-    + Para elements must contain more than Str "" and Space elements-    + Added parser for "\ignore" command used in literate haskell.-    + Reworked unknownCommand and rawLaTeXInline: when not in "parse raw"-      mode, these parsers simply strip off the command part and allow-      the arguments to be parsed normally.  So, for example,-      \blorg{\emph{hi}} will be parsed as Emph "hi" rather than-      Str "{\\emph{hi}}".-    + Parse lhs "code" environments as verbatim.-      Refactored parsers for verbatim environments.-    + Removed specialEnvironment parser.-    + parse '{}', if present, after \textless, \textgreater,-      \textbar, \textbackslash, \ldots.-    + Parse unescaped special characters verbatim rather than-      changing them to spaces.  This way arguments of unknown-      commands will appear in braces.--  * Parse raw ConTeXt environments as TeX in markdown reader.-    Resolves Issue #73.--  * Moved BlockWrapper and wrappedBlocksToDoc from ConTeXt writer to Shared.--  * Made some structural changes to parsing of raw LaTeX environments.-    Previously there was a special block parser for LaTeX environments.-    It returned a Para element containing the raw TeX inline. This has-    been removed, and the raw LaTeX environment parser is now used in the-    rawLaTeXInline parser. The effect is exactly the same, except that we-    can now handle consecutive LaTeX and ConTeXt environments not separated-    by spaces.  This new flexibility is required by the example in-    Issue #73:--        \placeformula \startformula-             L_{1} = L_{2}-        \stopformula--    API change: The LaTeX reader now exports rawLaTeXEnvironment' (which-    returns a string) rather than rawLaTeXEnvironment (which returns a block-    element). This is more likely to be useful in other applications.--  * Use \textsubscr instead of \textsubscript for LaTeX subscript macro.-    \textsubscript conflicts with a definition in the memoir class.-    Resolves Issue #65.--  * Removed unneeded space after "\\item" in LaTeX and ConTeXt output.--  * Added amsmath package to default LaTeX header. Resolves Issue #48.--  * Added \setupitemize[autointro] to ConTeXt header, to prevent orphaned-    list introduction lines.--  * Changed Float to Double in definition of Table element.-    (Double is more efficient in GHC.)--  * Fixed bug in Markdown parser:  regular $s triggering math mode.-    For example:  "shoes ($20) and socks ($5)."-    The fix consists in two new restrictions:--    + the $ that ends a math span may not be directly followed by a digit.-    + no blank lines may be included within a math span.--    Thanks to Joseph Reagle for noticing the bug.--  * Use Data.List's 'intercalate' instead of custom 'joinWithSep'.-    Removed 'joinWithSep' from Text.Pandoc.Shared.--  * Updated README and man pages.  Acknowledge contributors in README.-    Added paragraph to README about producing S5 with separate CSS/javascript.--  * Updated INSTALL to reflect new build system (including configuration-    options) and document new dependencies.  Added note to INSTALL that-    Cabal >= 1.2 is required for build.  Resolves Issue #74.--  * Fixed some haddock documentation errors.--  * Small fix to markdown2pdf man page: only input needs to be piped through iconv.--pandoc (0.46) unstable; urgency=low--  [ John MacFarlane ]--  * Made -H, -A, and -B options cumulative: if they are specified-    multiple times, multiple files will be included.--  * Added optional HTML sanitization using a whitelist.-    When this option is specified (--sanitize-html on the command line),-    unsafe HTML tags will be replaced by HTML comments, and unsafe HTML-    attributes will be removed.  This option should be especially useful-    for those who want to use pandoc libraries in web applications, where-    users will provide the input.--    + Main.hs:  Added --sanitize-html option.--    + Text.Pandoc.Shared:  Added stateSanitizeHTML to ParserState.--    + Text.Pandoc.Readers.HTML:-      - Added whitelists of sanitaryTags and sanitaryAttributes.-      - Added parsers to check these lists (and state) to see if a given-        tag or attribute should be counted unsafe.-      - Modified anyHtmlTag and anyHtmlEndTag to replace unsafe tags-        with comments.-      - Modified htmlAttribute to remove unsafe attributes.-      - Modified htmlScript and htmlStyle to remove these elements if-        unsafe.--    + Modified README and man pages to document new option.--  * Improved handling of email addresses in markdown and reStructuredText.-    Consolidated uri and email address parsers.  (Resolves Issue #37.)--    + New emailAddress and uri parsers in Text.Pandoc.Shared.-      - uri parser uses parseURI from Network.URI.-      - emailAddress parser properly handles email addresses with periods-        in them.--    + Removed uri and emailAddress parsers from Text.Pandoc.Readers.RST-      and Text.Pandoc.Readers.Markdown.--  * Markdown reader:--    + Fixed emph parser so that "*hi **there***" is parsed as a Strong-      nested in an Emph. (A '*' is only recognized as the end of the-      emphasis if it's not the beginning of a strong emphasis.)--    + Moved blockQuote parser before list parsers for performance.--    + Modified 'source' parser to allow backslash-escapes in URLs.-      So, for example, [my](/url\(1\)) yields a link to /url(1).-      Resolves Issue #34.--    + Disallowed links within links. (Resolves Issue #35.)-      - Replaced inlinesInBalanced with inlinesInBalancedBrackets, which-        instead of hard-coding the inline parser takes an inline parser-        as a parameter.-      - Modified reference and inlineNote to use inlinesInBalancedBrackets.-      - Removed unneeded inlineString function.-      - Added inlineNonLink parser, which is now used in the definition of-        reference.-      - Added inlineParsers list and redefined inline and inlineNonLink parsers-        in terms of it.-      - Added failIfLink parser.--    + Better handling of parentheses in URLs and quotation marks in titles.-      - 'source' parser first tries to parse URL with balanced parentheses;-        if that doesn't work, it tries to parse everything beginning with-        '(' and ending with ')'.-      - source parser now uses an auxiliary function source'.-      - linkTitle parser simplified and improved, under assumption that it-        will be called in context of source'.--    + Make 'block' conditional on strictness state, instead of using-      failIfStrict in block parsers. Use a different ordering of parsers-      in strict mode (raw HTML block before paragraph) for performance.-      In non-strict mode use rawHtmlBlocks instead of htmlBlock.-      Simplified htmlBlock, since we know it's only called in strict-      mode.--    + Improved handling of raw HTML.  (Resolves Issue #36.)-      - Tags that can be either block or inline (e.g. <ins>) should-        be treated as block when appropriate and as inline when-        appropriate. Thus, for example,-        <ins>hi</ins>-        should be treated as a paragraph with inline <ins> tags, while-        <ins>-        hi-        </ins>-        should be treated as a paragraph within <ins> tags.-      - Moved htmlBlock after para in list of block parsers.  This ensures-        that tags that can be either block or inline get parsed as inline-        when appropriate.-      - Modified rawHtmlInline' so that block elements aren't treated as-        inline.-      - Modified para parser so that paragraphs containing only HTML tags and-        blank space are not allowed.  Treat these as raw HTML blocks instead.--    + Fixed bug wherein HTML preceding a code block could cause it to-      be parsed as a paragraph.  The problem is that the HTML parser-      used to eat all blank space after an HTML block, including the-      indentation of the code block.  (Resolves Issue #39.)-      - In Text.Pandoc.Readers.HTML, removed parsing of following space-        from rawHtmlBlock.-      - In Text.Pandoc.Readers.Markdown, modified rawHtmlBlocks so that-        indentation is eaten *only* on the first line after the HTML-        block.  This means that in-        <div>-             foo-        <div>-        the foo won't be treated as a code block, but in-        <div>--            foo--        </div>-        it will.  This seems the right approach for least surprise.--  * RST reader:--    + Fixed bug in parsing explicit links (resolves Issue #44).-      The problem was that we were looking for inlines until a '<' character-      signaled the start of the URL; so, if you hit a reference-style link,-      it would keep looking til the end of the document.  Fix:  change-      inline => (notFollowedBy (char '`') >> inline).  Note that this won't-      allow code inlines in links, but these aren't allowed in resT anyway.--    + Cleaned up parsing of reference names in key blocks and links.-      Allow nonquoted reference links to contain isolated '.', '-', '_', so-      so that strings like 'a_b_' count as links.--    + Removed unnecessary check for following link in str.-      This is unnecessary now that link is above str in the definition of-      'inline'.--  * HTML reader:--    + Modified rawHtmlBlock so it parses </html> and </body> tags.-      This allows these tags to be handled correctly in Markdown.-      HTML reader now uses rawHtmlBlock', which excludes </html> and </body>,-      since these are handled in parseHtml.  (Resolves Issue #38.)--    + Fixed bug (emph parser was looking for `<IT>` tag, not `<I>`).--    + Don't interpret contents of style tags as markdown.-      (Resolves Issue #40.)-      - Added htmlStyle, analagous to htmlScript.-      - Use htmlStyle in htmlBlockElement and rawHtmlInline.-      - Moved "script" from the list of tags that can be either block or-        inline to the list of block tags.--    + Modified rawHtmlBlock to use anyHtmlBlockTag instead of anyHtmlTag-      and anyHtmlEndTag.  This fixes a bug in markdown parsing, where-      inline tags would be included in raw HTML blocks.--    + Modified anyHtmlBlockTag to test for (not inline) rather than-      directly for block.  This allows us to handle e.g. docbook in-      the markdown reader.--  * LaTeX reader:  Properly recognize --parse-raw in rawLaTeXInline.-    Updated LaTeX reader test to use --parse-raw.--  * HTML writer:--    + Modified rules for automatic HTML header identifiers to-      ensure that identifiers begin with an alphabetic character.-      The new rules are described in README.  (Resolves Issue #33.)--    + Changed handling of titles in HTML writer so you don't get-      "titleprefix - " followed by nothing.--  * ConTeXt writer: Use wrappers around Doc elements to ensure proper-    spacing.  Each block element is wrapped with either Pad or Reg.-    Pad'ed elements are guaranteed to have a blank line in between.--  * RST writer:--    + Refactored RST writer to use a record instead of a tuple for state,-      and to include options in state so it doesn't need to be passed as-      a parameter.--    + Use an interpreted text role to render math in restructuredText.-      See http://www.american.edu/econ/itex2mml/mathhack.rst for the-      strategy.--  [ Recai Oktaş ]--  * Debian packaging changes:--    + Remove the empty 'include' directory in -dev package, which lintian-      complains about.-    + Bump Standarts-Version to 3.7.3.-    + Use new 'Homepage:' field to specify the upstream URL on suggestion of-      lintian.-- -- Recai Oktaş <roktas@debian.org>  Tue, 08 Jan 2008 05:13:31 +0200--pandoc (0.45) unstable; urgency=low--  [ John MacFarlane ]--  * Simplified parsing of reference keys and notes in markdown and RST-    readers: The Reference data structure from Text.Pandoc.Shared is no-    longer needed, since referenceKey and noteBlock parses return strings-    (as many blank lines as were occupied by the key or note) and update-    state themselves.  getPosition and setPosition are now used to ensure-    that error messages will give the correct line number. This yields-    cleaner (and slightly faster) code, with more accurate parsing error-    messages.--  * Added new Math inline element:--    + Markdown and LaTeX readers now convert TeX math into Math elements,-      not TeX.-    + This allows math to be treated differently from raw TeX in output.-      TeX elements are no longer printed in output formats other than-      Markdown, LaTeX, and ConTeXt.  But Math elements are always printed.--  * New default handling of math in writers:--    + New module Text.Pandoc.Readers.TeXMath exports readTeXMath, which-      parses raw TeX math and outputs a string of Pandoc inlines that-      tries to render it as far as possible using unicode characters,-      lapsing into literal TeX when needed.-    + readTeXMath is now used for default HTML output in HTML, S5, RTF,-      and Docbook, if no other method for displaying math in HTML is-      specified.  Enclosing $'s are no longer printed by default.-    + By default, math is put inside `<span class="math">`. This way it can be-      distinguished from the surrounding text, e.g. put in a different-      font.--  * New --gladtex and --mimetex options for display of math in HTML:--    + If --gladtex is specified, math is output between `<eq>` tags, so-      it can be processed by gladTeX.-    + If --mimetex is specified, math is put in `<img>` tags with a link-      to the mimetex CGI script (or any other script that takes TeX math-      as input and outputs an image).  The URL of the script may be-      specified, but defaults to /cgi-bin/mimetex.cgi.-    + HTMLMathMethod structure in WriterOptions keeps track of how to-      display math in HTML output.-    + Updated README with a description of the four options for displaying-      math in HTML.--  * HTML reader:--    + Fixed bug: parser for minimized attributes should not swallow-      trailing spaces.-    + Simplified HTML attribute parsing.-    + Changed parsing of code blocks in HTML reader:  `<code>` tag is no-      longer needed. `<pre>` suffices. All HTML tags in the code block-      (e.g. for syntax highlighting) are skipped, because they are not-      portable to other output formats. A `<code>...</code>` block not-      surrounded by `<pre>` now counts as inline HTML, not a code block.-    + Remove just one leading and one trailing newline from contents of-      `<pre>...</pre>` in codeBlock parser.--  * Markdown reader:--    + Removed support for box-style block quotes.-    + Require space before title in links and references.-      This fixes a bug in parsing URLs like http://silly/url(withparen).-    + Improved and simplified setextHeader parser.-    + Fixed logic in smart quote parsing, adding some needed 'try'-      statements.-    + Fixed smart quote parsing so that unicode characters 8216 and 8217-      are recognized as single quotes, and 8220 and 8221 as double quotes.--  * RST reader:--    + Fixed bug in parsing of code blocks. Previously a full tab indent-      was required, but RST allows code to be indented any amount.-      Resolves Issue #27.-    + Allow field lists to be indented.-    + Parse the contents of field lists instead of treating as a raw string.-    + Represent field lists as definition lists instead of blockquotes.-    + Fixed bug in which metadata would be overridden if the document-      contained multiple field lists.-    + Parse fields associated with '.. image::' blocks, and use 'alt'-      field, if given, for image alt and title attributes.--  * LaTeX reader:--    + Modified specialChar so that '"' characters are parsed.-    + Fixed a bug in parsing of \[ \] math blocks (thanks to Mark Kalderon).--  * HTML writer:--    + Changes in handling of math (see above).-    + Don't produce HTML for table of contents if there are-      no headers. (This would be an empty list, which is invalid XHTML.)--  * Markdown writer:--    + Don't print title attribute if title is empty. (This differs from-      the behavior of Markdown.pl, and agrees with PHP Markdown. But John-      Gruber has indicated that he prefers this behavior.) Adjusted test-      suite accordingly.-    + Fixed incorrect line wrapping in paragraphs including hard line-      breaks. Resolves Issue #25.-    + Fixed bug in markdown writer:  If an ordered list item began with-      a marker greater than 3 characters in width, and the item took more-      than one line, it would appear on the line after the list marker,-      e.g.:--          (12)-              My list item.-              Multiline.--      Now it works as follows:--          (12) My list item.-              Multiline.--  * RST writer--    + Fixed bug in RST writer's handling of ordered lists. Previously,-      list items with multiple lines would not always line up with-      single-line list items. Now, list items are nested the length of-      the list marker + 1. This looks better and ensures that list items-      all line up. (Note that list markers are padded to the length of-      the longest list marker in the series.)-    + Use 3-space indent for unordered lists.-    + If label for a link reference contains a colon, surround it by `-      signs so it won't be interpreted as the end of the link label.--  * LaTeX writer:--    + Cleaner output for footnotes. Footnotes now always begin on a new-      line, and the final } is on a line by itself only when it needs to-      be (i.e. only when the note ends with a Verbatim environment).-    + Added writer options to state, so state doesn't need to be passed as-      a parameter.-    + Text wrapping now provided, using wrapTeXIfNeeded.--  * ConTeXt writer:  many improvements for more idiomatic ConTeXt output-    (thanks to Idris Samawi Hamid for suggestions).--    + PrettyPrint module now used for output.-    + Writer options are now in state, so they don't have to be passed as-      a parameter.-    + Text wrapping now provided, using wrapTeXIfNeeded.-    + Better treatment of footnotes:  footnotes are always on lines by-      themselves, and the final } is on a line by itself only when-      it needs to be (after \stoptyping).-    + Use \subject, \subsubject, ... or \section, \subsection, ... for headings,-      depending on whether --number-sections option is selected.-    + Extra blank line inserted after \stopitemize-    + Use new, "official" definition of blockquote environment. Also, use-      blank line after \startblockquote to balance blank line at the end.-    + Both itemized and enumerated lists are now generated using-      \start-stopitemize, with appropriate options. Removed definitions-      of ltxenum and ltxitem, which are no longer needed. Provided-      defaults for itemized lists in the preamble. State keeps track of-      ordered list level, so that when default numbering is specified,-      the appropriate scheme can be used.-    + Changed \useurl to \useURL.-    + Changed link color from red to blue.-    + Use \subsubsubsubsection etc., since these are supported-      (up to at least sub x 5).--  * Text.Pandoc.Shared:--    + Save and restore position in parseFromString, so that accurate-      error messages can be given.-    + Improved efficiency of romanNumeral parser.-    + Added wrappedTeX and wrapTeXIfNeeded functions.  These ensure-      that footnotes occur on lines by themselves (to make them-      easier to see and move) and do not screw up line wrapping.--  * Text.Pandoc.UTF8:  modified fromUTF8 to strip out the BOM-    if present.  Windows Notepad and other applications insert a-    BOM at the beginning of a UTF8 file.--  * Main.hs (tabFilter): Treat '\r' at end of line as newline (in-    addition to "\r\n" and '\n').--  * Added a writer option for wrapped text and a command-line option-    '--no-wrap', which disables text wrapping and minimizes whitespace-    in HTML. (Resolves Issue #26.)--    + Added support for '--no-wrap' to Main.hs.-    + Added wrapIfNeeded function to Text.Pandoc.Shared.-    + Use wrapIfNeeded instead of wrapped in the RST, Man, Docbook, and-      Markdown writers.-    + Added render and renderFragment helpers to HTML writer.--  * Modified html2markdown to run tidy only if the HTML cannot be-    parsed. Previously html2markdown piped all input through tidy-    before passing it to pandoc. This caused problems on certain pages-    (e.g. http://daringfireball.com/markdown) which have well-formed-    XHTML that causes tidy to choke. The solution is to pipe through-    tidy only if pandoc cannot parse the input by itself. This means-    that a temp file is now always used, even when input comes from a-    local file or standard input.--  * Removed 'version' constant from Main.hs; added 'pandocVersion' to-    Text.Pandoc library.--  * pandoc.cabal:--    + Modified to work with GHC 6.8 and Cabal configurations. (For GHC-      6.8, pretty and containers must be added to Build-Depends, and it-      is desirable to use the -O2 compiler option.)  Cabal configurations-      allows one to select options depending on the compiler version.-      For GHC 6.6, the splitBase option can be disabled.-    + pandoc.cabal.ghc66 is provided for users with older versions of-      Cabal, which do not support configurations.-    + Use Ghc-Prof-Options to ensure that '-auto-all' is used when-      '--enable-(executable|library)-profiling' is specified. Updated-      PROFILING instructions accordingly.--  * Makefile:--    + Makefile now checks GHC version. If GHC is 6.6, pandoc.cabal.ghc66-      is copied to pandoc.cabal, and the old pandoc.cabal is copied-      to pandoc.cabal.orig. Otherwise, pandoc.cabal is copied to-      pandoc.cabal.orig but otherwise unmodified. This way, the Makefile-      will work properly with either GHC 6.6 or 6.8.-    + Changed BUILDCONF to point to dist/setup-config, not .setup-config.-      This is where current versions of Cabal put it.-    + Added $(BUILDCMD) target, so setup doesn't get compiled every time.-    + Removed dependency of templates on ./templates, which is circular-      now that templates is a subdirectory of the top-level.--  * MacPorts Portfile:--    + Modified to install the pandoc library in addition to programs.-    + Installation must be done manually rather than using Makefile's-      install-all.-    + Note that the library must be registered in the activate phase,-      after the library files have been copied out of the destroot.-      Cabal generates a 'register.sh' script that will do this.--  * debian/control: Added libghc6-network-dev, libghc6-xhtml-dev, and-    libghc6-mtl-dev as dependencies for libghc6-pandoc-dev.-    Closes: #445235--  * debian/rules:  Converted to UTF-8.--  * Changed pandoc home page to http://johnmacfarlane.net/pandoc/.--  * Updated ASCIIMathML.js to latest version.--  * Directory structure:--    + Moved everything from src into the top-level directory.-    + Changed references to source directory in Makefile and-      pandoc.cabal.*.-    + Moved ASCIIMathML.js, headers, and ui into templates directory.-    + Modified fillTemplates.pl to reflect new paths.--  [ Recai Oktaş ]--  * Makefile: Fixed the issue of having two copies of the library-    documentation under some usage scenarios.--  * Replaced 'ghc' with '$(GHC)' in Makefile, and made GHC-    and GHC_PKG configurable through the environment, to support-    unusual ghc installations.  For example:-    GHC=/opt/ghc/bin/ghc GHC_PKG=/opt/ghc/bin/ghc-pkg make-- -- Recai Oktaş <roktas@debian.org>  Sun, 07 Oct 2007 20:51:43 +0300--pandoc (0.44) unstable; urgency=low--  [ John MacFarlane ]--  * Fixed bug in HTML writer:  when --toc was used, anchors were put around-    headers, which is invalid XHTML (block content within inline element).-    Now the anchors are put inside the header tags.  Resolves Issue #23.--  * Added xmlns attribute to html element in html writer tests.-    This attribute is added by more recent versions of the-    xhtml library (>= 3000), and is required for valid XHTML.--  [ Recai Oktaş ]--  * On configure, compile 'Setup.hs' to 'setup' and use 'setup' as the build-    command instead of 'runhaskell', which, on some platforms (such as s390,-    alpha, m68k), throws the following error:--        runhaskell Setup.hs configure --prefix=/usr-        ghc-6.6.1: not built for interactive use--    This causes a serious FTBFS bug.  Closes: #440668.-- -- Recai Oktaş <roktas@debian.org>  Mon, 03 Sep 2007 18:24:02 +0300--pandoc (0.43) unstable; urgency=low--  [ John MacFarlane ]--  * The focus of this release is performance.  The markdown parser-    is about five times faster than in 0.42, based on benchmarks-    with the TextMate manual.--  * Main.hs: Replaced CRFilter and tabFilter with single function-    tabFilter, which operates on the whole string rather than breaking-    it into lines, and handles dos-style line-endings as well as tabs.--  * Added separate LaTeX reader and native reader tests; removed-    round-trip tests.--  * Text.Pandoc.Shared:--    + Removed tabsToSpaces and tabsInLine (they were used only in Main.hs.)-    + General code cleanup (to elimante warnings when compiling with -Wall.)-    + Added 'wrapped' function, which helps wrap text into paragraphs,-      using the prettyprinting library.-    + Rewrote charsInBalanced and charsInBalanced'.-        - Documented restriction: open and close must be distinct characters.-        - Rearranged options for greater efficiency.-        - Bug fix: Changed inner call to charsInBalanced inside-          charsInBalanced' to charsInBalanced'.-    + anyLine now requires that the line end with a newline (not eof).-      This is a harmless assumption, since we always add newlines to the-      end of a block before parsing with anyLine, and it yields a 10% speed-      boost.-    + Removed unnecessary 'try' in anyLine.-    + Removed unneeded 'try' from romanNumeral parser.-    + Use notFollowedBy instead of notFollowedBy' in charsInBalanced.-    + Removed unneeded 'try' in parseFromString.-    + Removed unneeded 'try' from stringAnyCase.  (Now it behaves-      like 'string'.)-    + Changed definition of 'enclosed' in Text.Pandoc.Shared so that-      'try' is not automatically applied to the 'end' parser. Added-      'try' in calls to 'enclosed' where needed. Slight speed increase.--  * Writers:--    + Replaced individual wrapping routines in RST, Man, and Markdown-      writers with 'wrapped' from Text.Pandoc.Shared.-    + Rewrote LaTeX writer to use the prettyprinting library,-      so we get word wrapping, etc.-    + Modified latex writer tests for new latex writer using prettyprinter.-    + Fixed bug in LaTeX writer: autolinks would not cause-      '\usepackage{url}' to be put in the document header. Also, changes-      to state in enumerated list items would be overwritten.-    + In Markdown writer, escape paragraphs that begin with ordered list-      markers, so they don't get interpreted as ordered lists.--  * Text.Pandoc.Reades.LaTeX:--    + Fixed bug in LaTeX reader, which wrongly assumed that the roman-      numeral after "enum" in "setcounter" would consist entirely of-      "i"s. 'enumiv' is legitimate.-    + LaTeX command and environment names can't contain numbers.-    + Rearranged order of parsers in inline for slight speed improvement.-    + Added '`' to special characters and 'unescapedChar'.--  * Text.Pandoc.Readers.RST:--    + Removed unneeded try's in RST reader; also minor code cleanup.-    + Removed tabchar.-    + Rearranged parsers in inline (doubled speed).--  * Text.Pandoc.Readers.Markdown:--    + Skip notes parsing if running in strict mode. (This yields a nice-      speed improvement in strict mode.)-    + Simplify autolink parsing code, using Network.URI to test for-      URIs. Added dependency on network library to debian/control and-      pandoc.cabal.-    + More perspicuous definition of nonindentSpaces.-    + Removed unneeded 'try' in 'rawLine'.-    + Combined linebreak and whitespace into a new whitespace parser, to-      avoid unnecessary reparsing of space characters.-    + Removed unnecessary 'try' in 'codeBlock', 'ellipses', 'noteMarker',-      'multilineRow', 'dashedLine', 'rawHtmlBlocks'.-    + Use lookAhead in parsers for setext headers and definition lists-      to see if the next line begins appropriately; if not, don't waste-      any more time parsing.-    + Don't require blank lines after code block. (It's sufficient to-      end code block with a nonindented line.)-    + Changed definition of 'emph': italics with '_' must not-      be followed by an alphanumeric character. This is to help-      prevent interpretation of e.g. `[LC_TYPE]: my_type` as-      `[LC<em>TYPE]:my</em>type`.-    + Improved Markdown.pl-compatibility in referenceLink: the two parts-      of a reference-style link may be separated by one space, but not-      more... [a] [link], [not]    [a link].-    + Fixed markdown inline code parsing so it better accords with-      Markdown.pl: the marker for the end of the code section is a clump-      of the same number of `'s with which the section began, followed-      by a non-` character. So, for example,-         ` h ``` i ` -> `<code>h ``` i</code>`.-    + Split 'title' into 'linkTitle' and 'referenceTitle', since the-      rules are slightly different.-    + Rewrote 'para' for greater efficiency.-    + Rewrote link parsers for greater efficiency.-    + Removed redundant 'referenceLink' in definition of inline (it's-      already in 'link').-    + Refactored escapeChar so it doesn't need 'try'.-    + Refactored hrule for performance in Markdown reader.-    + More intelligent rearranging of 'inline' so that most frequently-      used parsers are tried first.-    + Removed tabchar parser, as whitespace handles tabs anyway.--  * Text.Pandoc.CharacterReferences:--    + Refactored.-    + Removed unnecessary 'try's for a speed improvement.-    + Removed unnecessary '&' and ';' from the entity table.--  * Build process:--    + Makefile: Get VERSION from cabal file, not Main.hs.-    + Modified MacPorts Portfile:-        - Depend on haddock-        - Build and install libraries and library documentation in-          addition to pandoc executable-        - Added template item for md5 sum in Portfile.in.-        - Incorporated changes from MacPorts repository (r28278).-    + FreeBSD port:  Don't try to generate distinfo in Makefile.-      It can be made using 'make makesum' in FreeBSD.-    + Make both freebsd and macports targets depend on tarball.--  * Website and documentation:--    + Updated INSTALL instructions.-    + Added pandocwiki demo to website.-    + Removed local references to Portfile, since pandoc is now in the-      MacPorts repository.-- -- Recai Oktaş <roktas@debian.org>  Sun, 02 Sep 2007 15:50:11 +0300--pandoc (0.42) unstable; urgency=low--  [ John MacFarlane ]--  * Main.hs: Use utf8 conversion on the extra files loaded with-    the -H, -C, -B, and -A options.  This fixes problems with unicode-    characters in these files.--  * Exposed Text.Pandoc.ASCIIMathML, since it is imported in-    Text.Pandoc.Readers.HTML and without it we get a linking error when-    using the library.--  * Markdown reader:--    + Added new rule for enhanced markdown ordered lists: if the list-      marker is a capital letter followed by a period (including a-      single-letter capital roman numeral), then it must be followed by-      at least two spaces. The point of this is to avoid accidentally-      treating people's initials as list markers: a paragraph might begin,-      "B. Russell was an English philosopher," and this shouldn't be-      treated as a list.  Documented change in README.-    + Blocks that start with "p. " and a digit are no longer treated-      as ordered lists (it's a page number).-    + Added a needed 'try' to listItem.-    + Removed check for a following setext header in endline.-      A full test is too inefficient (doubles benchmark time), and the-      substitute we had before is not 100% accurate.-    + Don't use Code elements for autolinks if --strict specified.--  * LaTeX writer:  When a footnote ends with a Verbatim environment, the-    close } of the footnote cannot occur on the same line or an error occurs.-    Fixed this by adding a newline before the closing } of every footnote.--  * HTML writer:-    + Removed incorrect "{}" around style information in HTML tables.-      Column widths now work properly in HTML.-    + If --strict option is specified (and --toc is not), don't include-      identifiers in headers, for better Markdown compatibility.--  * Build process:--    + Separated $(web_dest) and website targets.-    + In website, index.txt is now constructed from template index.txt.in.-    + Added freebsd target to Markefile. This creates the freebsd Makefile-      from Makefile.in, and creates distinfo.  Removed Makefile and distinfo-      from the repository.-    + Added macport target to Makefile. Portfile is built from template-      Portfile.in.-    + Removed OSX package targets.  (Too many difficulties involving-      dependencies on dynamic libraries.)-    + More complete INSTALL instructions for all architectures.--  * Website:-    + Added a programming demo, pandocwiki.--  [ Recai Oktaş ]--  * Do not forget to close pandoc's ITP.  Closes: #391666-- -- Recai Oktaş <roktas@debian.org>  Sun, 26 Aug 2007 22:51:32 +0300--pandoc (0.41) unstable; urgency=low--  [ John MacFarlane ]--  * Fixed bugs in HTML reader:-    + Skip material at end *only if* `</html>` is present (previously,-      only part of the document would be parsed if an error was-      found; now a proper error message is given).-    + Added new constant eitherBlockOrInline with elements that may-      count either as block-level or as inline. Modified isInline and-      isBlock to take this into account.-    + Modified rawHtmlBlock to accept any tag (even an inline tag):-      this is innocuous, because rawHtmlBlock is tried only if a regular-      inline element can't be parsed.-    + Added a necessary 'try' in definition of 'para'.--  * Fixed bug in markdown ordered list parsing.  The problem was that-    anyOrderedListStart did not check for a space following the-    ordered list marker.  So in 'A.B. 2007' the parser would be-    expecting a list item, but would not find one, causing an error.-    Fixed a similar bug in the RST reader.  Resolves Issue #22.--  * Refactored RST and Markdown readers using parseFromString.--  * LaTeX reader will now skip anything after \end{document}.--  * Fixed blockquote output in markdown writer: previously, block-    quotes in indented contexts would be indented only in the first-    line.--  * Added note to INSTALL about variations in versions of the xhtml-    library that can lead to failed tests (thanks to Leif LeBaron).-- -- Recai Oktaş <roktas@debian.org>  Sun, 19 Aug 2007 23:26:07 +0300--pandoc (0.4) unstable; urgency=low--  [ John MacFarlane ]--  * Added two new output formats: groff man pages and ConTeXt. By-    default, output files with extensions ".ctx" and ".context" are-    assumed to be ConTeXt, and output files with single-digit extensions-    are assumed to be man pages.--  * Enhanced ordered lists (documented in README, under Lists):-    + The OrderedList block element now stores information about-      list number style, list number delimiter, and starting number.-    + The readers parse this information when possible.-    + The writers use this information to style ordered lists.-    + The enhancement can be disabled using the --strict option.--  * Added support for tables (with a new Table block element). Two kinds-    of tables are supported: a simple table with one-line rows, and a-    more complex variety with multiline rows. All output formats are-    supported, but only markdown tables are parsed at the moment. The-    syntax is documented in README.--  * Added support for definition lists (with a new DefinitionList block-    element). All output and input formats are supported. The syntax is-    documented in README.--  * Added support for superscripts and subscripts (with new Superscript-    and Subscript inline elements).  All input and output-    formats.  The syntax is documented in README.--  * Added support for strikeout (with a new Strikeout inline element).-    All input and output formats are supported. Thanks to Bradley Kuhn,-    who contributed a patch. The syntax is documented in README. Resolves-    Issue #18.--  * Added a --toc|--table-of-contents option.  This causes an automatically-    generated table of contents (or an instruction that creates one) to-    be inserted at the beginning of the document. Not supported in S5,-    DocBook, or man page writers.--  * Modified the -m|--asciimathml option:--    + If an optional URL argument is provided, a link is inserted-      instead of the contents of the ASCIIMathML.js script.-    + Nothing is inserted unless the document actually contains-      LaTeX math.--  * Removed Blank block element as unnecessary.--  * Removed Key and Note blocks from the Pandoc data structure. All-    links are now stored as explicit links, and note contents are-    stored with the (inline) notes.--    + All link Targets are now explicit (URL, title) pairs; there-      is no longer a 'Ref' target.-    + Markdown and RST parsers now need to extract data from key and-      note blocks and insert them into the relevant inline elements.-      Other parsers have been simplified, since there is no longer any need-      to construct separate key and note blocks.-    + Markdown, RST, and HTML writers need to construct lists of-      notes; Markdown and RST writers need to construct lists of link-      references (when the --reference-links option is specified); and-      the RST writer needs to construct a list of image substitution-      references. All writers have been rewritten to use the State monad-      when state is required.-    + Several functions (generateReference, keyTable,-      replaceReferenceLinks, replaceRefLinksBlockList, and some auxiliaries-      used by them) have been removed from Text.Pandoc.Shared, since-      they are no longer needed. New functions and data structures-      (Reference, isNoteBlock, isKeyBlock, isLineClump) have been-      added. The functions inTags, selfClosingTag, inTagsSimple, and-      inTagsIndented have been moved to the DocBook writer, since that-      is now the only module that uses them. NoteTable is now exported-      in Text.Pandoc.Shared.-    + Added stateKeys and stateNotes to ParserState; removed stateKeyBlocks,-      stateKeysUsed, stateNoteBlocks, stateNoteIdentifiers, stateInlineLinks.-    + Added writerNotes and writerReferenceLinks to WriterOptions.--  * Added Text.Pandoc module that exports basic readers, writers,-    definitions, and utility functions. This should export everything-    needed for most uses of Pandoc libraries. The haddock documentation-    includes a short example program.--  * Text.Pandoc.ASCIIMathML is no longer an exported module.--  * Added Text.Pandoc.Blocks module to help in printing markdown-    and RST tables.  This module provides functions for working with-    fixed-width blocks of text--e.g., placing them side by side, as-    in a table row.--  * Refactored to avoid reliance on Haskell's Text.Regex library, which-    (a) is slow, and (b) does not properly handle unicode.  This fixed-    some strange bugs, e.g. in parsing S-cedilla, and improved performance.--    + Replaced 'gsub' with a general list function  'substitute'-      that does not rely on Text.Regex.-    + Rewrote extractTagType in HTML reader so that it doesn't use-      regexs.-    + In Markdown reader, replaced email regex test with a custom email-      autolink parser (autoLinkEmail). Also replaced selfClosingTag regex-      with a custom function isSelfClosingTag.-    + Modified Docbook writer so that it doesn't rely on Text.Regex for-      detecting 'mailto' links.-    + Removed escapePreservingRegex and reamped entity-handling-      functions in Text.Pandoc.Shared and Text.Pandoc.CharacterReferences to-      avoid reliance on Text.Regex (see below on character reference-      handling changes).--  * Renamed Text.Pandoc.Entities as Text.Pandoc.CharacterReferences.--  * Changed handling of XML entities.  Entities are now parsed (and unicode-    characters returned) in the Markdown and HTML readers, rather than being-    handled in the writers.  In HTML and Docbook writers, UTF-8 is now used-    instead of entities for characters above 128.  This makes the HTML and-    DocBook output much more readable and more easily editable.--    + Removed sgmlHexEntity, sgmlDecimalEntity, sgmlNamedEntity, and-      sgmlCharacterEntity regexes from Text.Pandoc.Shared.-    + Renamed escapeSGMLChar to escapeCharForXML.  Added escapeStringForXML.-      Moved both functions to Text.Pandoc.Writers.Docbook.-    + Added characterReference parser to Text.Pandoc.CharacterReferences.-      This parses a string and return a unicode character.-    + Rewrote decodeCharacterReferences to use the new parser instead of-      Text.Regex.-    + Added new charRef parser for Markdown and HTML, which replaces the-      old 'entity' parser. Added '&' as a special character in Markdown reader.-    + Modified HTML and Markdown readers to call decodeEntities on all raw-      strings (e.g. authors, dates, link titles), to ensure that no-      unprocessed entities are included in the native representation of-      the document.  (In the HTML reader, most of this work is done by a-      change in extractAttributeName.)-    + In XML and Markdown output, escape unicode nonbreaking space as '&nbsp;',-      since a unicode non-breaking space is impossible to distinguish visually-      from a regular space.  (Resolves Issue #3.)-    + Removed encodeEntitiesNumerical.-    + Use Data.Map for entityTable and (new) reverseEntityTable, for a-      slight performance boost over the old association list.-    + Removed unneeded decodeEntities from 'str' parser in HTML and-      Markdown readers.--  * Text.Pandoc.UTF8:  Renamed encodeUTF8 to toUTF8, decodeUTF8 to-    fromUTF8, for clarity.--  * Replaced old haskell98 module names replaced by hierarchical module-    names, e.g. List by Data.List.  Removed haskell98 from dependencies-    in pandoc.cabal, and added mtl (needed for state monad). Substituted-    xhtml for html.--  * Refactored and cleaned up character escaping in writers, using-    backslashEscapes and escapeStringUsing functions.--  * Instead of adding "\n\n" to the end of an input string in Main.hs,-    this is now done in the readers. This makes the libraries behave-    the way you'd expect from the pandoc program. Resolves Issue #10.--  * URLs and email addresses in autolinks are now typeset as Code.--  * In Main.hs, changed putStr to putStrLn -- mainly because MacOS X-    doesn't display the whole output unless there's a line ending.--  * Major code cleanup in all modules, for greater consistency, concision,-    and readability.--  * HTML reader:--    + Fixed several bugs (extractTagType, attribute parsing).-    + Remove Null blocks in lists of blocks when possible.-    + Allow HTML comments as raw HTML inline.--  * Markdown reader:--    + Ordered list items may no longer begin with uppercase letters, or-      letters greater than 'n'.  (This prevents first initials and page-      reference, e.g. 'p. 400', from being parsed as beginning lists.)-      Also, numbers beginning list items may no longer end with ')',-      which is now allowed only after letters.  Note: These changes-      may cause documents to be parsed differently. Users should take-      care in upgrading.-    + Changed autoLink parsing to conform better to Markdown.pl's-      behavior. `<google.com>` is not treated as a link, but-      `<http://google.com>`, `<ftp://google.com>`, and-      `<mailto:google@google.com>` are.-    + Cleaned up handling of embedded quotes in link titles.  Now these are-      stored as a '"' character, not as '&quot;'.-    + Use lookAhead parser for the 'first pass' (looking for reference keys),-      instead of parsing normally, then using setInput to reset input.  This-      yields a slight performance boost.-    + Fixed several bugs in smart quote recognition.-    + Fixed bug in indentSpaces (which didn't properly handle-      cases with mixed spaces and tabs).-    + Consolidated 'text', 'special', and 'inline' into 'inline'.-    + Fixed bug which allowed URL and title to be separated by multiple blank-      lines in links and reference keys.  They can be on separate lines but-      can't have blank lines between them.-    + Correctly handle bracketed text inside inline footnotes and links,using-      new function inlinesInBalanced.  Resolves Issue #14.-    + Fixed bug in footnotes: links in footnotes were not being-      processed. Solution: three-stage parse. First, get all the-      reference keys and add information to state. Next, get all the-      notes and add information to state. (Reference keys may be needed-      at this stage.) Finally, parse everything else.-    + Replaced named constants like 'emphStart' with literals.-    + Removed an extra occurance of escapedChar in definition of inline.--  * RST reader:--    + Allow the URI in a RST hyperlink target to start on the line-      after the reference key.-    + Added 'try' in front of 'string', where needed, or used a different-      parser.  This fixes a bug where ````` would not be correctly parsed as-      a verbatim `.-    + Fixed slow performance in parsing inline literals in RST reader.  The-      problem was that ``#`` was seen by 'inline' as a potential link or image.-      Fix:  inserted 'notFollowedBy (char '`')' in link parsers.-      Resolves Issue #8.-    + Use lookAhead instead of getInput/setInput in RST reader.  Removed-      unneeded getState call, since lookAhead automatically saves and-      restores the parser state.-    + Allow hyperlink target URIs to be split over multiple lines, and-      to start on the line after the reference. Resolves Issue #7.-    + Fixed handling of autolinks.--  * LaTeX reader:--    + Replaced 'choice [(try (string ...), ...]' idiom with 'oneOfStrings',-      for clarity.-    + Added clauses for tilde and caret. Tilde is \ensuremath{\sim}, and-      caret is \^{}, not \^ as before.-    + Added parsing for \url.-    + Parse \texttt{} as code, provided there's nothing fancy inside.--  * HTML writer:--    + Modified HTML writer to use the Text.XHtml library. This results-      in cleaner, faster code, and it makes it easier to use Pandoc in-      other projects, like wikis, which use Text.XHtml. Two functions are-      now provided, writeHtml and writeHtmlString: the former outputs an-      Html structure, the latter a rendered string. The S5 writer is also-      changed, in parallel ways (writeS5, writeS5String).-    + The Html header is now written programmatically, so it has been-      removed from the 'headers' directory. The S5 header is still-      needed, but the doctype and some of the meta declarations have-      been removed, since they are written programatically. This change-      introduces a new dependency on the xhtml package.-    + Fixed two bugs in email obfuscation involving improper escaping-      of '&' in the `<noscript>` section and in `--strict` mode. Resolves-      Issue #9.-    + Fixed another bug in email obfuscation: If the text to be obfuscated-      contains an entity, this needs to be decoded before obfuscation.-      Thanks to thsutton for the patch. Resolves Issue #15.-    + Changed the way the backlink is displayed in HTML footnotes.-      Instead of appearing on a line by itself, it now generally-      appears on the last line of the note.  (Exception:  when the-      note does not end with a Plain or Para block.) This saves space-      and looks better.-    + Added automatic unique identifiers to headers:-      - The identifier is derived from the header via a scheme-        documented in README.-      - WriterState now includes a list of header identifiers and a table-        of contents in addition to notes.-      - The function uniqueIdentifiers creates a list of unique identifiers-        from a list of inline lists (e.g. headers).-      - This list is part of WriterState and gets consumed by blockToHtml-        each time a header is encountered.-    + Include CSS for .strikethrough class in header only if strikethrough-      text appears in the document.-    + If the 'strict' option is specified, elements that do not appear in-      standard markdown (like definition lists) are passed through as-      raw HTML.-    + Simplified treatment of autolinks, using pattern matching instead of-      conditionals.--  * Markdown writer:--    + Links in markdown output are now printed as inline links by default,-      rather than reference links.  A --reference-links option has been added-      that forces links to be printed as reference links.  Resolves Issue #4.-    + Use autolinks when possible.  Instead of `[site.com](site.com)`,-      use `<site.com>`.--  * LaTeX writer:--    + Rewrote to use the State monad. The preamble now includes only those-      packages that are actually required, given the document's content.-      Thus, for example, if strikeout is not used, ulem is not required.-      Modified LaTeXHeader accordingly.-    + Modified LaTeX writer to insert '\,' between consecutive quotes.-    + Removed unused function tableRowColumnWidths.-    + Simplified code for escaping special characters.-    + Leave extra blank line after \maketitle.-    + Include empty '\author{}' when no author specified to avoid LaTeX-      errors.-    + Include fancyvrb code in header only if needed -- that is, only-      if there is actually code in a footnote.-    + Use \url{} for autolinks.-    + Include [mathletters] option in ucs package, so that basic unicode-      Greek letters will work correctly.--  * RST writer:  Force blank line before lists, so that sublists will-    be handled correctly.--  * Docbook writer:  Fixed a bug:  email links with text, like-    [foo](me@bar.baz), were being incorrectly treated as autolinks.--  * Removed Text.ParserCombinators.Pandoc and moved all its functions to-    Text.Pandoc.Shared.--  * Text.Pandoc.Shared:--    + Added defaultWriterOptions.-    + Added writerTableOfContents to WriterOptions.-    + Added writerIgnoreNotes option to WriterOptions.  This is needed-      for processing header blocks for a table of contents, since notes on-      headers should not appear in the TOC.-    + Added prettyprinting for native Table format.-    + Removed some unneeded imports.-    + Moved escape and nullBlock parsers from-      Text.ParserCombinators.Pandoc, since the latter is for-      general-purpose parsers that don't depend on Text.Pandoc.Definition.-    + Moved isHeaderBlock from Text.Pandoc.Writers.HTML.-    + Moved Element, headerAtLeast, and hierarchicalize from Docbook-      writer, because HTML writer now uses these in constructing a table-      of contents.-    + Added clauses for new inline elements (Strikeout, Superscript,-      Subscript) to refsMatch.-    + Removed backslashEscape; added new functions escapeStringUsing and-      backslashEscapes.-    + Moved failIfStrict from markdown reader, since it is now used also-      by the HTML reader.-    + Added a 'try' to the definition of indentSpaces.-    + In definition of 'reference', added check to make sure it's not a note-      reference.-    + Added functions: camelCaseToHyphenated, toRomanNumeral,-      anyOrderedListMarker, orderedListmarker, orderedListMarkers,-      charsInBalanced', withHorizDisplacement, romanNumeral-    + Fixed a bug in the anyLine parser. Previously it would parse an empty-      string "", but it should fail on an empty string, or we get an error-      when it is used inside "many" combinators.-    + Removed followedBy' parser, replacing it with the lookAhead parser from-      Parsec.-    + Added some needed 'try's before multicharacter parsers, especially in-      'option' contexts.-    + Removed the 'try' from the 'end' parser in 'enclosed', so that-      'enclosed' behaves like 'option', 'manyTill', etc.-    + Added lineClump parser, which parses a raw line block up to and-      including any following blank lines.-    + Renamed parseFromStr to parseFromString.-    + Added a 'try' to the 'end' parser in 'enclosed'.  This makes errors in-      the use of 'enclosed' less likely. Removed some now-unnecessary 'try's-      in calling code.-    + Removed unneeded 'try' in blanklines.-    + Removed endsWith function and rewrote calling functions to use-      isSuffixOf instead.-    + Added >>~ combinator.-    + Fixed bug in normalizeSpaces:  Space:Str "":Space should compress to-      Space.--  * Refactored runtests.pl; added separate tests for tables.--  * Shell scripts:--    + Added -asxhtml flag to tidy in html2markdown. This will-      perhaps help the parser, which expects closing tags.-    + Modified markdown2pdf to run pdflatex a second time if --toc or-      --table-of-contents was specified; otherwise the table of-      contents won't appear.-    + Modified markdown2pdf to print a helpful message if the 'ulem'-      LaTeX package is required and not found.--  * Changes to build process:--    + Dropped support for compilation with GHC 6.4.  GHC 6.6 or higher-      is now required.-    + Removed cabalize and Pandoc.cabal.in. The repository now contains-      pandoc.cabal itself.-    + Pandoc.cabal has been changed to pandoc.cabal, because HackageDB-      likes the cabal file to have the same name as the tarball.-    + Expanded and revised the package description in pandoc.cabal.-      Revised the package synopsis.-    + The tarball built by 'make tarball' now contains files built from-      templates (including man pages and shell scripts), so pandoc can-      be built directly using Cabal tools, without preprocessing.-    + Executable binaries are now stripped before installing.-    + Man pages are now generated from markdown sources, using pandoc's-      man page writer.-    + Use HTML version of README (instead of RTF) in Mac OS X installer.-    + Instead of testing for the existence of a pandoc symlink in build-exec,-      use ln -f.--  * Documentation:--    + Updated README and man pages with information on new features.-    + Updated INSTALL instructions with some useful clarifications and-      links.-    + Updated web content.--  * Added FreeBSD port.--  [ Recai Oktaş ]--  * debian/control:--    + Changed pandoc's Build-Depends to include libghc6-mtl-dev and-      libghc6-xhtml-dev.  Removed libghc6-html-dev.-    + Suggest texlive-latex-recommended | tetex-extra instead of-      tetex-bin.  This brings in fancyvrb and unicode support.-- -- Recai Oktaş <roktas@debian.org>  Tue, 16 Jan 2007 00:37:21 +0200--pandoc (0.3) unstable; urgency=low--  [ John MacFarlane ]--  * Changes in pandoc options:--    + Allow options to follow or precede arguments.-    + Changed '--smartypants' to '--smart' and adjusted symbols accordingly.-    + Added '--strict' option.-    + Added '-o/--output' option.-    + Added '--dump-args' and '--ignore-args' options (for use in wrappers).-    + Modified '-v' and '-h' output to go to STDERR, not STDOUT, and return-      error conditions.  This is helpful for writing wrappers.-    + Added copyright message to '-v' output, modeled after FSF messages.-    + Reformatted usage message so that it doesn't wrap illegibly.-    + Removed extra blanks after '-h' and '-D' output.--  * Added docbook writer.--  * Added implicit setting of default input and output format based-    on input and output filename extensions.  These defaults are-    overridden if explicit input and output formats are specified using-    '-t', '-f', '-r', or '-w' options.  Documented in pandoc(1) man page-    and README.--  * Allow ordered list items to begin with (single) letters, as well-    as numbers.  The list item marker may now be terminated either by-    '.' or by ')'.  This extension to standard markdown is documented-    in README.--  * Revised footnote syntax.  (See README for full details.)  The-    '[^1]' format now standard in markdown extensions is supported,-    as are inline footnotes with this syntax: '^[My note.]'.-    The earlier footnote syntax '^(1)' is no longer supported.+pandoc (2.0)++  [new features]++  * New output format `ms` (groff ms). Complete support, including+    tables, math, syntax highlighting, and PDF bookmarks. The writer uses+    texmath's new eqn writer to convert math to eqn format, so a ms file+    produced with this writer should be processed with `groff -ms -e` if+    it contains math.++  * New output format `jats` (Journal Article Tag Suite).  This is an XML+    format used in archiving and publishing articles.  Note that a+    URI-encoded CSL stylesheet (`data/jats.csl`) is added automatically+    unless a stylesheet is specified using `--css`.++  * New output format `gfm` (GitHub-flavored CommonMark) (#3841).+    This uses bindings to GitHub's fork of cmark, so it should parse+    gfm exactly as GitHub does (excepting certain postprocessing+    steps, involving notifications, emojis, etc.).  `markdown_github`+    has been deprecated in favor of `gfm`.++  * New output format `muse` (Emacs Muse) (Alexander Krotov, #3489).++  * New input format `gfm` (GitHub-flavored CommonMark) (#3841).+    This uses bindings to GitHub's fork of cmark.  `markdown_github`+    has been deprecated in favor of `gfm`.++  * New input format `muse` (Emacs Muse) reader (Alexander Krotov, #3620).++  * New input format `tikiwiki` (TikiWiki markup) (rlpowell, #3800).++  * New input format `vimwiki` (Vimwiki markup) (Yuchen Pei, #3705).+    Note that there is a new data file, `data/vimwiki.css`, which can+    be used to display the HTML produced by this reader and+    pandoc's HTML writer in the style of vimwiki's own HTML+    export.++  * New input format `creole` (Creole 1.0) (#3994, Sascha Wilde).++  * New syntax for Divs, with `fenced_divs` extension enabled by+    default (#168).  This gives an attractive, plain-text way to create+    containers for block-level content.++  * Added new syntax for including raw content in any output format,+    enabled by the `raw_attribute` extension (which is on by default+    for `markdown` and `multimarkdown`).  The syntax is the same as+    for fenced code blocks or code inlines, only with `{=FORMAT}` for+    attributes, where `FORMAT` is the name of the output format+    (e.g., `ms`, `html`).++  * Implement multicolumn support for slide formats (#1710).+    The structure expected is:++        <div class="columns">+          <div class="column" width="40%">+            contents...+          </div>+          <div class="column" width="60%">+            contents...+          </div>+        </div>++    Support has been added for beamer and all HTML slide formats.++  * Allows line comments in templates, beginning with `$--` (#3806).+    (Requires doctemplates 0.2.1.)++  * Add `--eol=crlf|lf|native` flag and writer option to control line endings+    (Stefan Dresselhaus, #3663, #2097).++  * Add `--log` option to save log messages in JSON format to a file (#3392).++  * Add `--request-header` option, to set request headers when pandoc+    makes HTTP requests to fetch external resources. For example:+    `--request-header User-Agent:blah`.++  * Added lua filters (Albert Krewinkel, #3514).  The new `--lua-filter`+    option works like `--filter` but takes pathnames of special lua filters+    and uses the lua interpreter baked into pandoc, so that no external+    interpreter is needed.  Note that lua filters are all applied after+    regular filters, regardless of their position on the command line.+    For documentation of lua filters, see `doc/lua-filters.md`.++  * Set `PANDOC_READER_OPTIONS` in environment where filters are run.+    This contains a JSON representation of `ReaderOptions`, so filters+    can access it.++  * Support creation of pdf via groff `ms` and pdfroff.+    `pandoc -t ms -o output.pdf input.txt`.++  * Support for PDF generation via HTML and `weasyprint` or `prince`+    (Mauro Bieg, #3909).  `pandoc -t html5 -o output.pdf --pdf-engine=prince`.++  * Added `--epub-subdirectory` option (#3720).  This specifies the+    subdirectory in the OCF container that holds the EPUB specific content.+    We now put all EPUB related content in an `EPUB/` subdirectory by default+    (later this will be configurable).++    ```+      mimetype+      META-INF/+        com.apple.ibooks.display-options.xml+        container.xml+      EPUB/ <<--configurable-->>+        fonts/ <<--static-->>+        font.otf+      media/ <<--static-->>+        cover.jpg+        fig1.jpg+      styles/ <<--static-->>+        stylesheet.css+      content.opf+      toc.ncx+      text/ <<--static-->>+        ch001.xhtml+    ```++  * Added `--resource-path=SEARCHPATH` command line option (#852).+    SEARCHPATH is separated by the usual character, depending on OS+    (: on unix, ; on windows).  Default resource path is just working+    directory.  However, the working directory must be explicitly+    specified if the `--resource-path` option is used.++  * Added --abbreviations=FILE option for custom abbreviations file+    (#256).  Dfault abbreviations file (`data/abbreviations`) contains+    a list of strings that will be recognized by pandoc's+    Markdown parser as abbreviations.  (A nonbreaking space will+    be inserted after the period, preventing a sentence space in+    formats like LaTeX.) Users can override the default by putting a file+    abbreviations in their user data directory (`~/.pandoc` on *nix).++  * Allow a theme file as argument to `--highlight-style`.+    Also include a sample, `default.theme`, in `data/`.++  * Allow `--syntax-definition` option for dynamic loading of syntax+    highlighting definitions (#3334).++  * Lists in `markdown` by default now use the CommonMark variable+    nesting rules (#3511). The indentation required for a block-level+    item to be included in a list item is no longer fixed, but is+    determined by the first line of the list item.  To be included in+    the list item, a block must be indented to the level of the first+    non-space content after the list marker. Exception: if are 5 or more+    spaces after the list marker, then the content is interpreted as an+    indented code block, and continuation paragraphs must be indented+    two spaces beyond the end of the list marker.  See the CommonMark+    spec for more details and examples.++    Documents that adhere to the four-space rule should, in most cases,+    be parsed the same way by the new rules.  Here are some examples+    of texts that will be parsed differently:++        - a+          - b++    will be parsed as a list item with a sublist; under the four-space+    rule, it would be a list with two items.++        - a++              code++    Here we have an indented code block under the list item, even though it+    is only indented six spaces from the margin, because it is four spaces+    past the point where a continuation paragraph could begin.  With the+    four-space rule, this would be a regular paragraph rather than a code+    block.++        - a++                code++    Here the code block will start with two spaces, whereas under+    the four-space rule, it would start with `code`.  With the four-space+    rule, indented code under a list item always must be indented eight+    spaces from the margin, while the new rules require only that it+    be indented four spaces from the beginning of the first non-space+    text after the list marker (here, `a`).++    This change was motivated by a slew of bug reports from people+    who expected lists to work differently (#3125, #2367, #2575, #2210,+     #1990, #1137, #744, #172, #137, #128) and by the growing prevalance+    of CommonMark (now used by GitHub, for example).  Those who+    prefer the old behavior can use `-f markdown+four_space_rule`.++  * Added `four_space_rule` extension.  This triggers the old pandoc+    parsing rule for content nested under list items (the "four space+    rule").++  * Added `spaced_reference_links` extension (#2602).  It allows whitespace+    between the two parts of a reference link:  e.g.++        [a] [b]++        [b]: url++    This was previously enabled by default; now it is now forbidden by default.++  * Add `space_in_atx_header` extension (#3512).  This is enabled by default+    in pandoc and GitHub markdown but not the other flavors.+    This requirse a space between the opening #'s and the header+    text in ATX headers (as CommonMark does but many other implementations+    do not).  This is desirable to avoid falsely capturing things ilke++        #hashtag++    or++        #5++  * Add `sourcefile` and `outputfile` template variables (Roland Hieber,+    #3431).++  * Allow ibooks-specific metadata in epubs (#2693).  You can now have+    the following fields in your YAML metadata, and it will be treated+    appropriately in the generated EPUB:++    ```+      ibooks:+        version: 1.3.4+        specified-fonts: false+        ipad-orientation-lock: portrait-only+        iphone-orientation-lock: landscape-only+        binding: true+        scroll-axis: vertical+    ```+++  [behavior changes]++  * Reader functions no longer presuppose that CRs have been+    stripped from the input. (They strip CRs themselves, before+    parsing, to simplify the parsers.)++  * Added support for translations (localization) (#3559).+    Currently this only affects the LaTeX reader, for things+    like `\figurename`.  Translation data files for 46 languages+    can be found in `data/translations`.++  * Make `--ascii` work with DocBook output too.++  * Rename `--latex-engine` to `--pdf-engine`,+    and `--latex-engine-opt` to `--pdf-engine-opt`.++  * Removed `--parse-raw` and `readerParseRaw`.  These were confusing.+    Now we rely on the `+raw_tex` or `+raw_html` extension with latex or html+    input.  Thus, instead of `--parse-raw -f latex` we use `-f latex+raw_tex`,+    and instead of `--parse-raw -f html` we use `-f html+raw_html`.++  * With `--filter` R filters are now recognized, even if they are+    not executable (#3940, #3941, Andrie de Vries).++  * Support SVG in PDF output, converting with `rsvg2pdf` (#1793).++  * Make epub an alias for epub3, not epub2.++  * Removed `--epub-stylesheet`; use `--css` instead (#3472, #847).+    Multiple stylesheets may be used.  Stylesheets will be taken both from+    `--css` and from the `stylesheet` metadata field (which can contain+    either a file path or a list of them).++  * `--mathml` and MathML in HTMLMathMethod no longer take an argument.+    The argument was for a bridge JavaScript that used to be necessary+    in 2004.  We have removed the script already.++  * `--katex` improvements.  The latest version is used, and the+    autoload script is loaded by default.++  * Change MathJax CDN default since old one is shutting down (#3544).+    Note:  The new URL requires a version number, which we'll have+    to update manually in subsequent pandoc releases in order to+    take advantage of mathjax improvements.++  * `--self-contained`: don't incorporate elements with `data-external="1"`+    (#2656).  You can leave an external link as it is by adding the attribute+    data-external="1" to the element.  Pandoc will then not try to+    incorporate its content when `--self-contained` is used.  This is+    similar to a feature already supported by the EPUB writer.++  * Allow `--extract-media` to work with non-binary input formats+    (#1583, #2289).  If `--extract-media` is supplied with a non-binary+    input format, pandoc will attempt to extract the contents of all+    linked images, whether in local files, data: uris, or external uris.+    They will be named based on the sha1 hash of the contents.++  * Make `papersize: a4` work regardless of the case of `a4`.+    It is converted to `a4` in LaTeX and `A4` in ConTeXt.++  * Make `east_asian_line_breaks` affect all readers/writers (#3703).++  * Underlined elements are now treated consistently by readers+    (#2270, hftf); they are always put in a Span with class `underline`.+    This allows the user to treat them differently from other emphasis,+    using a filter.  Docx, Org, Textile, Txt2Tags, and HTML readers+    have been changed.++  * Improved behavior of `auto_identifiers` when there are explicit ids+    (#1745).  Previously only autogenerated ids were added to the list+    of header identifiers in state, so explicit ids weren't taken+    into account when generating unique identifiers.  Duplicated+    identifiers could result.  This simple fix ensures that explicitly given+    identifiers are also taken into account.++  * Use `table-of-contents` for contents of toc, make `toc` a boolean+    (#2872).  Changed markdown, rtf, and HTML-based templates accordingly.+    This allows you to set `toc: true` in the metadata; this+    previously produced strange results in some output formats.+    For backwards compatibility, `toc` is still set to the+    toc contents.  But it is recommended that you update templates+    to use `table-of-contents` for the toc contents and `toc`+    for a boolean flag.++  * Change behavior with binary format output to stdout.+    Previously, for binary formats, output to stdout was disabled+    unless we could detect that the output was being piped (and not+    sent to the terminal).  Unfortunately, such detection is not+    possible on Windows, leaving windows users no way to pipe binary+    output.  So we have changed the behavior in the following way:++    + Output to stdout is allowed when it can be determined that+      the output is being piped (on non-Windows platforms).+    + If the `-o` option is not used, binary output is never sent+      to stdout by default; instead, an error is raised.+    + If `-o -` is used, binary output is sent to stdout, regardless+      of whether it is being piped. This works on Windows too.++  * Better error behavior:  uses of `error` have been replaced by+    raising of `PandocError`, which can be trapped and handled by the+    calling program.++  * Removed `hard_line_breaks` extension from `markdown_github` (#3594).+    GitHub has two Markdown modes, one for long-form documents like READMEs+    and one for short things like issue coments. In issue comments, a line+    break is treated as a hard line break. In README, wikis, etc., it is+    treated as a space as in regular Markdown.  Since pandoc is more likely to+    be used to convert long-form documents from GitHub Markdown,+    `-hard_line_breaks` is a better default.++  * Include `backtick_code_blocks` extension in `mardkown_mmd` (#3637).++  * Escape `MetaString` values (as added with `-M/--metadata` flag) (#3792).+    Previously they would be transmitted to the template without any+    escaping.  Note that `--M title='*foo*'` yields a different result from++        ---+        title: *foo*+        ---++    In the latter case, we have emphasis; in the former case, just+    a string with literal asterisks (which will be escaped+    in formats, like Markdown, that require it).++  * Allow `em`, `cm`, `in` for image height/width in HTML, LaTeX (#3450).++  * HTML writer: Insert `data-` in front of unsupported attributes.  Thus,+    a span with attribute `foo` gets written to HTML5 with `data-foo`, so+    it is valid HTML5.  HTML4 is not affected.  This will allow us to use+    custom attributes in pandoc without producing invalid HTML. (With help+    from Wandmalfarbe, #3817.)++  * Plain writer:  improved super/subscript rendering.  We now+    handle more non-digit characters for which there are+    sub/superscripted unicode characters.  When unicode+    sub/superscripted characters are not available, we use+    `_(..)` or `^(..)` (#3518).++  * Docbook, JATS, TEI writers: print INFO message when omitting interior+    header (#3750).  This only applies to section headers inside list items,+    e.g., which were otherwise silently omitted.++  * Change to `--reference-links` in Markdown writer (#3701).  With+    `--reference-location` of `section` or `block`, pandoc will now repeat+    references that have been used in earlier sections.  The Markdown+    reader has also been modified, so that *exactly* repeated references+    do not generate a warning, only references with the same label but+    different targets.  The idea is that, with references after every block,+    one might want to repeat references sometimes.++  * ODT/OpenDocument writer:++    + Support `lang` attribute (#1667).+    + Added support for `--toc` (#2836).  Thanks to @anayrat.++  * Docx writer:++    + `lang` meta, see #1667 (Mauro Bieg, #3515).+    + Change `FigureWithCaption` to `CaptionedFigure` (iandol, #3658).+    + Use `Table` rather than `Table Normal` for table style (#3275).+      `Table Normal` is the default table style and can't be modified.+    + Pass through comments (#2994).  We assume that comments are defined as+      parsed by the docx reader:++        I want <span class="comment-start" id="0" author="Jesse Rosenthal"+        date="2016-05-09T16:13:00Z">I left a comment.</span>some text to+        have a comment <span class="comment-end" id="0"></span>on it.++      We assume also that the id attributes are unique and properly+      matched between comment-start and comment-end.+    + Bookmark improvements.  Bookmark start/end now surrounds content rather+      than preceding it.  Bookmarks generated for Div with id+      (jgm/pandoc-citeproc#205).+    + Add `keywords` metadata to docx document properties (Ian).++  * RST writer: support unknown interpreted text roles by+    parsing them as `Span` with `role` attributes (#3407).  This+    way they can be manipulated in the AST.++  * HTML writer:++    + Line block: Use class instead of style attribute (#1623).  We now+      issue `<div class="line-block">` and include a default definition+      for `line-block` in the default templates, instead of hard-coding a+      `style` on the div.+    + Add class `footnoteBack` to footnote back references (Timm Albers).+      This allows for easier CSS styling.+    + Render SmallCaps as span with smallcaps class (#1592), rather than+      using a style attribute directly.  This gives the user more flexibility+      in styling small caps in CSS.+    + With reveal.js we use `data-src` instead of `src` for images for+      lazy loading.+    + Special-case `.stretch` class for images in reveal.js (#1291).+      Now in reveal.js, an image with class `stretch` in a paragraph+      by itself will stretch to fill the whole screen, with no+      caption or figure environment.++  * Added warnings for non-rendered blocks to writers.++  * Writers now raise an error on template failure.++  * When creating a PDF via LaTeX, warn if the font is missing some+    characters (#3742).++  * Remove initial check for PDF-creating program (#3819).+    Instead, just try running it and raise the exception if it+    isn't found at that point.  This improves things for users of Cygwin+    on Windows, where the executable won't be found by `findExecutable`+    unless `.exe` is added.  The same exception is raised as before, but+    at a later point.++  * Readers issue warning for duplicate header identifiers (#1745).+    Autogenerated header identifiers are given suffixes so as not to clash+    with previously used header identifiers. But they may still coincide with+    an explicit identifier that is given for a header later in the document,+    or with an identifier on a div, span, link, or image. We now issue+    a warning in this case, so users can supply an explicit identifier.++  * CommonMark reader now supports `emoji`, `hard_line_breaks`, `smart`,+    and `raw_html` extensions.++  * Markdown reader:++    + Don't allow backslash + newline to affect block structure (#3730).+      Note that as a result of this change, the following, which formerly+      produced a header with two lines separated by a line break, will+      now produce a header followed by a paragraph:++        # Hi\+        there++      This may affect some existing documents that relied on+      this undocumented and unintended behavior.  This change makes pandoc+      more consistent with other Markdown implementations, and with itself+      (since the two-space version of a line break doesn't work inside ATX+      headers, and neither version works inside Setext headers).+++  * Org reader (Albert Krewinkel, unless noted):++    + Support `table.el` tables (#3314).+    + Support macros (#3401).+    + Support the `#+INCLUDE:` file inclusion mechanism (#3510).+      Recognized include types are `example`, `export`, `src`, and+      normal org file inclusion.  Advanced features like line numbers+      and level selection are not implemented yet.+    + Interpret more meta value as inlines.  The values of the following+      meta variables are now interpreted using org-markup instead of+      treating them as pure strings: `keywords` (comma-separated list of+      inlines), `subtitle` (inline values), `nocite` (inline values, can+      be repeated).+    + Support `\n` export option (#3940).  This turns all newlines in the+      text into hard linebreaks.++  * RST reader:++    + Improved admonition support (#223).  We no longer add an+      `admonition` class, we just use the class for the type of admonition,+      `note` for example.  We put the word corresponding to the label in+      a paragraph inside a `Div` at the beginning of the admonition with+      class `admonition-title`.  This is about as close as we can get to+      RST's own output.+    + Initial support of `.. table` directive.  This allows adding captions+      to tables.+    + Support `.. line-block` directive.  This is deprecated but may still+      be in older documents.+    + Support scale and align attributes of images (#2662).+    + Implemented implicit internal header links (#3475).+    + Support RST-style citations (#853).  The citations appear at the end+      of the document as a definition list in a special div with id+      `citations`. Citations link to the definitions.+    + Recurse into bodies of unknown directives (#3432).+      In most cases it's better to preserve the content than+      to emit it.  This isn't guaranteed to have good results;+      it will fail spectacularly for unknown raw or verbatim directives.+    + Handle chained link definitions (#262).  For example,++          .. _hello:+          .. _goodbye: example.com++      Here both `hello` and `goodbye` should link to `example.com`.+    + Support anchors (#262).  E.g.++          `hello`++          .. _hello:++          paragraph++      This is supported by putting "paragraph" in a `Div` with id `hello`.+    + Support `:widths:` attribute for table directive.+    + Implement csv-table directive (#3533).  Most attributes are supported,+      including `:file:` and `:url:`.+    + Support unknown interpreted text roles by parsing them as Span+      with "role" attributes (#3407).  This way they can be manipulated in+      the AST.++  * HTML reader: parse a span with class `smallcaps` as `SmallCaps`.++  * LaTeX reader:+ +    + Implemented `\graphicspath` (#736).+    + Properly handle column prefixes/suffixes.  For example, in+      `\begin{tabular}{>{$}l<{$}>{$}l<{$} >{$}l<{$}}`+      each cell will be interpreted as if it has a `$`+      before its content and a `$` after (math mode).+    + Handle komascript `\dedication` (#1845).  It now adds a+      `dedication` field to metadata.  It is up to the user to supply+      a template that uses this variable.+    + Support all `\textXX` commands, where XX = `rm`, `tt`, `up`, `md`,+      `sf`, `bf` (#3488).  Spans with a class are used when there is+      nothing better.+    + Expand `\newenvironment` macros (#987).+    + Add support for LaTeX subfiles package (Marc Schreiber, #3530).+    + Better support for subfigure package (#3577).+      A figure with two subfigures turns into two pandoc+      figures; the subcaptions are used and the main caption+      ignored, unless there are no subcaptions.+    + Add support for \vdots (Marc Schreiber, #3607).+    + Add basic support for hyphenat package (Marc Schreiber, #3603).+    + Add basic `\textcolor` support (Marc Schreiber).+    + Add support for `tabularx` environment (Marc Schreiber, #3632).+    + Better handling of comments inside math environments (#3113).+      This solves a problem with commented out `\end{eqnarray}` inside+      an eqnarray (among other things).+    + Parse tikzpicture as raw verbatim environment if `raw_tex` extension+      is selected (#3692).  Otherwise skip with a warning.  This is better+      than trying to parse it as text!+    + Add `\colorbox` support (Marc Schreiber).+    + Set identifiers on Spans used for `\label`.+    + Have `\setmainlanguage` set `lang` in metadata.+    + Support etoolbox's `\ifstrequal`.+    + Support `plainbreak`, `fancybreak` et al from the memoir class+      (bucklereed, #3833).+    + Support `\let`.  Also, fix regular macros so they're expanded at the+      point of use, and NOT also the point of definition.  `\let` macros,+      by contrast, are expanded at the point of definition.  Added an+      `ExpansionPoint` field to `Macro` to track this difference.+    + Support simple `\def` macros.  Note that we still don't support+      macros with fancy parameter delimiters, like `\def\foo#1..#2{...}`.+    + Support \chaptername, \partname, \abstractname, etc.  (#3559,+      obsoletes #3560).+    + Put content of `\ref`, `\label`, `\eqref` commands into `Span` with+      attributes, so they can be handled in filters (Marc Schreiber, #3639)+    + Add Support for `glossaries` and `acronym` package (Marc Schreiber,+      #3589). Acronyms are not resolved by the reader, but acronym and+      glossary information is put into attributes on Spans so that they+      can be processed in filters.+    + Use `Link` instead of `Span` for `\ref`.  This makes more sense+      semantically and avoids unnecessary `Span [Link]` nestings when+      references are resolved.+    + Rudimentary support for `\hyperlink`.+    + Support `\textquoteleft|right`, `\textquotedblleft|right` (#3849).+    + Support `\lq`, `\rq`.+    + Implement `\newtoggle`, `\iftoggle`, `\toggletrue|false` from etoolbox+      (#3853).+    + Support `\RN` and `\Rn`, from biblatex (bucklereed, #3854).+    + Improved support for `\hyperlink`, `\hypertarget` (#2549).+    + Support `\k` ogonek accent.+    + Improve handling of accents.  Handle ogonek, and fall back correctly+      with forms like `\"{}`.+    + Better support for ogonek accents.+    + Support for `\faCheck` and `\faClose` (Marc Schreiber, #3727).+    + Support for `xspace` (Marc Schreiber, #3797).+    + Support `\setmainlanguage` or `\setdefaultlanguage` (polyglossia)+      and `\figurename`.+    + Better handling of `\part` in LaTeX (#1905).  Now we parse chapters as+      level 0 headers, and parts as level -1 headers.  After parsing, we+      check for the lowest header level, and if it's less than 1 we bump+      everything up so that 1 is the lowest header level.  So `\part` will+      always produce a header; no command-line options are needed.+    + Add block version of `\textcolor` (Marc Schreiber).+    + `\textcolor` works as inline and block command (Marc Schreiber).+    + `\textcolor` will be parse as span at the beginning of a paragraph+      (Marc Schreiber).+    + Read polyglossia/babel `\text(LANG){...}` (bucklereed)+    + Improved handling of include files in LaTeX reader (#3971).+      Previously `\include` wouldn't work if the included file+      contained, e.g., a begin without a matching end.+    + Support `\expandafter` (#3983).+    + Handle `\DeclareRobustCommand` (#3983).  Currently it's just treated+      as a synonym for `\newcommand`.+    + Handle `\lettrine` (Mauro Bieg).++  * Math improvements due to updates in texmath:++    + Improved handling of accents and upper/lower delimiters.+    + Support for output in GNU eqn format (used with *roff).+    + Allow `\boldsymbol` + a token without braces, and similarly+      with other styling commands.+    + Improve parsing of `\mathop` to allow multi-character operator names.+    + Add thin space after math operators when "faking it with+      unicode."++  * `walk` is now used instead of `bottomUp` in the `ToJSONFilter`+    instance for `a -> [a]` (pandoc-types).  Note that behavior+    will be slightly different, since `bottomUp`'s treatment of+    a function `[a] -> [a]` is to apply it to each sublist of a+    list, while walk applies it only to maximal sublists.+    Usually the latter behavior is what is wanted, and the+    former can be simulated when needed.  But there may be+    existing filters that need to be rewritten in light of the+    new behavior.  Performance should be improved.++  * There are some changes to syntax highlighting due to revisions+    in the `skylighting` library:++    + Support for `powershell` has been added, and many syntax+      definitions have been updated.+    + Background colors have been added to the `kate` style.+    + The way highlighted code blocks are formatted in HTML has+      been changed (David Baynard), in ways that may require+      changes in hard-coded CSS affecting highlighting.+      (If you haven't included hard-coded highlighting CSS in+      your template, you needn't change anything.)+++  [API changes]++  * New module `Text.Pandoc.Class` (Jesse Rosenthal, John MacFarlane).+    This contains definitions of the `PandocMonad` typeclass, the+    `PandocIO` and `PandocPure` monads, and associated functions.++  * Changed types of all writers and readers.++    + We now use `Text` instead of `String` in the interface (#3731).+      (We have not yet changed the internals of most readers to work+      with `Text`, but making this change in the API now opens up a+      path to doing that.)+    + The result is now of form `m a` with constraint `PandocMonad m`.+      Readers and writers can be combined to form monadic values which+      can be run using either `runIO` or `runPure`.  If `runIO` is used,+      then both readers and writers will be able to do IO when needed+      (for include files, for example); if `runPure` is used,+      then the functions are pure and will not touch IO.+    + Where previously you used+      `writeRST def (readMarkdown def "[foo](url)")`, now you+      would use+      `runPure $ readMarkdown def (pack "[foo](url)") >>= writeRST def`.++  * New module `Text.Pandoc.Readers` (Albert Krewinkel).  This+    contains reader helper functions formerly defined in the+    top-level `Text.Pandoc` module.++    + Changed `StringReader` -> `TextReader`.+    + `getReader` now returns a pair of a reader and+      `Extensions`, instead of building the extensions into the+      reader (#3659).  The calling code must explicitly set+      `readerExtensions` using the `Extensions` returned.  The+      point of the change is to make it possible for the calling+      code to determine what extensions are being used.++  * New module `Text.Pandoc.Writers` (Albert Krewinkel).+    This contains writer helper functions formerly defined in the+    top-level `Text.Pandoc` module.++    + Changed `StringWriter` -> `TextWriter`.+    + `getWriter` now retuns a pair of a reader and+      `Extensions`, instead of building the extensions into the+      reader (#3659).  The calling code must explicitly set+      `readerExtensions` using the `Extensions` returned.  The+      point of the change is to make it possible for the calling+      code to determine what extensions are being used.++  * New module `Text.Pandoc.Lua`, exporting `runLuaFilter` (Albert Krewinkel,+    #3514).++  * New module `Text.Pandoc.App`.  This abstracts out the functionality+    of the command line program (`convertWithOpts`), so it can be reproduced+    e.g. in a desktop or web application.  Instead of exiting, we throw errors+    (#3548), which are caught (leading to exit) in pandoc.hs, but allow other+    users of `Text.Pandoc.App` to recover.  `pandoc.hs` is now a 2-liner.+    The module also exports some utility functions for parsing options+    and running filters.++  * New module `Text.Pandoc.Logging` (exported module) (#3392).+    This now contains the `Verbosity` definition previously in+    `Text.Pandoc.Options`, as well as a new `LogMessage` datatype that will+    eventually be used instead of raw strings for warnings.  This will enable+    us, among other things, to provide machine-readable warnings if desired.+    Include ToJSON instance and showLogMessage.  This gives us the possibility+    of both machine-readable and human-readable output for log messages.++  * New module `Text.Pandoc.BCP47`, with `getLang`, `Lang(..)`, `parseBCP47`.++  * New module `Text.Pandoc.Translations`, exporting `Term`,+    `Translations`, `readTranslations`.++  * New module `Text.Pandoc.Readers.LaTeX.Types', exporting `Macro`, `Tok`,+    `TokType`, `Line`, `Column`.++  * `Text.Pandoc.Error`: added many new constructors for `PandocError`.++  * Expose some previously private modules (#3260).  These are often+    helpful to people writing their own reader or writer modules:++    + `Text.Pandoc.Writers.Shared`+    + `Text.Pandoc.Parsing`+    + `Text.Pandoc.Asciify`+    + `Text.Pandoc.Emoji`+    + `Text.Pandoc.ImageSize`+    + `Text.Pandoc.Highlighting`+`+  * New module `Text.Pandoc.Extensions` (Albert Krewinkel):+    Extension parsing and processing functions were defined in the top-level+    `Text.Pandoc` module.  These functions are moved to the Extensions+    submodule as to enable reuse in other submodules.++  * Add `Ext_raw_attribute` constructor for `Extension`.++  * Add `Ext_fenced_divs` constructor for `Extension'.++  * Add `Ext_four_space_rule` constructor in `Extension`.++  * Add `Ext_gfm_auto_identifiers` constructor for `Extension`.++  * Add `Monoid` instance for `Extensions`.++  * Add `Text.Pandoc.Writers.Ms`, exporting `writeMs`.++  * Add `Text.Pandoc.Writers.JATS`, exporting `writeJATS`.++  * Add `Text.Pandoc.Writers.Muse`, exporting `writeMuse`.++  * Add `Text.Pandoc.Readers.Muse`, exporting `readMuse`.++  * Add `Text.Pandoc.Readers.TikiWiki`, exporting `readTikiWiki`.++  * Add `Text.Pandoc.Readers.Vimwiki`, exporting `readVimwiki`.++  * Add `Text.Pandoc.Readers.Creole`, exporting `readCreole`.++  * Export `setVerbosity` from `Text.Pandoc`.++  * `Text.Pandoc.Pretty`: Add `Eq` instance for `Doc`.++  * `Text.Pandoc.XML`: `toEntities`: changed type to `Text -> Text`.++  * `Text.Pandoc.UTF8`:++    + Export `fromText`, `fromTextLazy`, `toText`, `toTextLazy`.+      Define `toString`, `toStringLazy` in terms of them.+    + Add new functions parameterized on `Newline`: `writeFileWith`,+      `putStrWith`, `putStrLnWith`, `hPutStrWith`, `hPutStrLnWith`.++  * `Text.Pandoc.MediaBag`: removed `extractMediaBag`.++  * `Text.Pandoc.Highlighting`:++    + `highlighting` now returns an Either rather than Maybe.+      This allows us to display error information returned by the skylighting+      library.  Display a warning if the highlighting library throws an error.+    + Add parameter for `SyntaxMap` to `highlight`.++  * `Text.Pandoc.Writers.Math`:++    + Export `defaultMathJaxURL`, `defaultKaTeXURL`.  This will ensure that+      we only need to update these in one place.++  * `Text.Pandoc.SelfContained`:++    + Removed `WriterOptions` parameter from `makeSelfContained`.+    + Put `makeSelfContained` in PandocMonad instead of IO.  This removes+      the need to pass MediaBag around and improves exceptions.  It also+      opens up the possibility of using makeSelfContained purely.+    + Export `makeDataURI`.++  * `Text.Pandoc.ImageSize`:++    + Export `lengthToDim`, new function `scaleDimension`.+    + Export `inEm` from ImageSize (#3450).+    + Change `showFl` and `show` instance for `Dimension` so+      extra decimal places are omitted.+    + Added `Em` as a constructor of `Dimension`.+    + Add `WriterOptions` parameter to `imageSize` signature (Mauro Bieg).++  * `Text.Pandoc.Templates`:++    + Change type of `renderTemplate'`.  Now it runs in `PandocMonad`+      and raises a proper `PandocTemplateError` if there are problems, rather+      than failing with uncatchable `error`.+    + Change signature of `getDefaultTemplate`.  Now it runs in any instance+      of `PandocMonad`, and returns a `String` rather than an `Either` value.+      And it no longer takes a `datadir` parameter, since this can be+      retrieved from `CommonState`.++  * `Text.Pandoc.Options`:++    + Added `writerEpubSubdirectory` to `WriterOptions` (#3720).+      The EPUB writer now takes its EPUB subdirectory from this option.+    + In `WriterOptions`, rename `writerLaTeXEngine` to `writerPdfEngine`+      and `writerLaTeXArgs` to `writerPdfArgs` (Mauro Bieg, #3909).+    + Add `writerSyntaxMap` to `WriterOptions`.+    + Removed `writerEpubStylesheet` from `WriterOptions`.+    + Remove `writerUserDataDir` from `WriterOptions`.  It is now carried+      in `CommonState` in `PandocMonad` instances.  (And thus it can be used+      by readers too.)+    + Changed `writerEpubMetadata` to a `Maybe String`.+    + Removed `readerApplyMacros` from `ReaderOptions`.  Now we just check+      the `latex_macros` reader extension.+    + FromJSON/ToJSON instances for `ReaderOptions`.+    + In `HTMLMathMethod`, the `KaTeX` contsructor now takes only+      one string (for the KaTeX base URL), rather than two.+    + Removed `writerSourceURL` from `WriterOptions`.  We now use+      `stSourceURL` in `CommonState`, which is set by `setInputFiles`.++  * `Text.Pandoc.Shared`:++    + `tabFilter` now takes a `Text`, not `String`.+    + `openURL`: Changed type from an Either.  Now it will just raise+      an exception to be trapped later.+    + Remove `normalizeSpaces` (#1530).+    + Remove `warn`.  (Use `report` from `Text.Pandoc.Class` instead.)+    + Export a new function `crFilter`.+    + Add `eastAsianLineBreakFilter` (previously in Markdown reader).+    + Provide custom `isURI` that rejects unknown schemes.+      (Albert Krewinkel, #2713).  We also export the set of known+      `schemes`.  The new function replaces the function of the same name+      from `Network.URI`, as the latter did not check whether a scheme is+      well-known.  All official IANA schemes (as of 2017-05-22) are+      included in the set of known schemes.  The four non-official schemes+      `doi`, `isbn`, `javascript`, and `pmid` are kept.+    + Remove `err`.+    + Remove `readDataFile`, `readDefaultDataFile`, `getReferenceDocx`,+      `getReferenceODT`. These now live in `Text.Pandoc.Class`,+      where they are defined in terms of `PandocMonad`+      primitives and have different signatures.+    + Remove `openURL`.  Use `openURL` from `Text.Pandoc.Class` instead.+    + Add `underlineSpan`.++  * `Text.Pandoc.Readers.HTML`: export new `NamedTag` class.++  * `Text.Pandoc.Readers.Markdown`: remove `readDocxWithWarnings`.+     With the new API one can simply use `getLog` after running+     the reader.++  * `Text.Pandoc.Readers.LaTeX`: Changed types for `rawLaTeXInline`+     and `rawLaTeXBlock`.  (Both now return a `String`, and they are+     polymorphic in state.)+++  [bug fixes and under-the-hood improvements]++  * TEI writer: Added identifiers on `<div>` elements.++  * DokuWiki reader: Better handling for code block in list item (#3824).++  * Custom writer: Remove old preprocesesor conditionals (Albert Krewinkel).++  * ZimWiki writer: Removed internal formatting from note and table cells,+    because ZimWiki does not support it (Alex Ivkin, #3446).++  * MediaWiki writer:++    + Updated list of syntax highlighting languages (#3461).+      Now `r` gets you `<source>` rather than `<code>` (among others).+    + Add display attribute on `<math>` tags (#3452).  This allows display+      math to be rendered properly.+    + Remove newline before `</ref>` (#2652).+    + Don't softbreak lines inside list items (#3531).++  * Org writer:++    + Reduce to two spaces after bullets (#3417, Albert Krewinkel).+    + Add unit tests (Alexander Krotov).+    + Stop using raw HTML to wrap divs (Albert Krewinkel, #3771).+    + Do not strip `#` from Org anchor links (Alexander Krotov).++  * CommonMark writer:++    + Avoid excess blank lines at end of output.+    + Prefer pipe tables to HTML tables even if it means losing relative+      column width information (#3734).+    + Support table, strikethrough extensions, when enabled (as with gfm).+      Note that we bypass the commonmark writer from cmark and construct our+      own pipe tables, with better results.+    + Properly support `--wrap=none`.+    + Use smallcaps class for `SmallCaps` (#1592).+    + Omit "fig:" prefix in image titles.  This is used internally to+      indicate internal figures.++  * RST writer:++    + Properly handle table captions.+    + Don't wrap lines in in definition list terms.  Wrapping is not allowed.+    + Implemented `+/-smart` and improved escaping with `+smart`.+    + Add empty comments when needed to avoid including a blockquote+      in the indented content of a preceding block (#3675).+    + Improve grid table output, fix bug with empty rows (#3516).+      Uses the new `gridTable` in Writers.Shared, which is here+      improved to better handle 0-width cells.+    + Remove space at beginning/end of RST code span (#3496).  Otherwise+      we get invalid RST.  There seems to be no way to escape the space.+    + Add header anchors when header has non-standard id (#3937).+    + Correctly handle inline code containing backticks, using a `:literal:`+      role (#3974).+    + Don't backslash-escape word-internal punctuation (#3978).++  * Markdown writer:++    + Don't include variables in metadata blocks.  Previously variables set+      on the command line were included in e.g. YAML metadata, contrary to+      documentation and intentions.+    + Improved escaping with `+smart`.+    + Fixed grid tables embedded in grid tables (#2834).+    + Use span with class 'smallcaps' for SmallCaps, instead of a style+      attribute as before (#1592).+    + Escape initial `%` in a paragraph if the `pandoc_title_blocks`+      extension is enabled (#3454).  Otherwise in a document starting with+      a literal `%` the first line is wrongly interpreted as a title.+    + Fixed false ordered lists in YAML metadata (#3492, #1685).  Now we+      properly escape things that would otherwise start ordered lists,+      such as++          ---+          title: 1. inline+          ...+    + Better handling of tables with empty columns (#3337).  We now+      calculate the number of columns based on the longest row (or the+      length of aligns or widths).+    + Escape unordered list markers at beginning of paragraph (#3497), to+      avoid false interpretation as a list.+    + Escape `|` appropriately.+    + Ensure space before list at top level (#3487).+    + Avoid spurious blanklines at end of document after tables and list,+      for example.+    + Fixed bugs in simple/multiline list output (#3384).+      Previously we got overlong lists with `--wrap=none`.  This is fixed.+      Previously a multiline list could become a simple list (and would+      always become one with `--wrap=none`).+    + Don't emit a simple table if `simple_tables` disabled (#3529).+    + Case-insensitive reference links (David A Roberts, #3616).+      Ensure that we do not generate reference links whose labels differ only+      by case.  Also allow implicit reference links when the link+      text and label are identical up to case.+    + Put space before reference link definitions (Mauro Bieg, #3630).+    + Better escaping for links (David A. Roberts, #3619).  Previously the+      Markdown writer would sometimes create links where there were none+      in the source.  This is now avoided by selectively escaping bracket+      characters when they occur in a place where a link might be created.+    + Added missing `\n` (David A. Roberts, #3647).+    + Fixed duplicated reference links with `--reference-links`+      and `--reference-location=section` (#3674).  Also ensure that there+      are no empty link references `[]`.+    + Avoid inline surround-marking with empty content (#3715).+      E.g. we don't want `<strong></strong>` to become `****`.+      Similarly for emphasis, super/subscript, strikeout.+    + Don't allow soft break in header (#3736).+    + Make sure `plain`, `markdown_github`, etc. work for raw.+      Previously only `markdown` worked.  Note: currently a raw block labeled+      `markdown_github` will be printed for any `markdown` format.+    + Ensure that `+` and `-` are escaped properly so they don't cause+      spurious lists (#3773).  Previously they were only+      if succeeded by a space, not if they were at end of line.+    + Use pipe tables if `raw_html` disabled and `pipe_tables` enabled,+      even if the table has relative width information (#3734).+    + Markdown writer: don't crash on `Str ""`.+    + Make `Span` with null attribute transparent.  That is, we don't use+      brackets or `<span>` tags to mark spans when there are no attributes;+      we simply output the contents.+    + Escape pipe characters when `pipe_tables` enabled (#3887).+    + Better escaping of `<` and `>`.  If `all_symbols_escapable` is set,+      we backslash escape these.  Otherwise we use entities as before.+    + When writing plain, don't use `&nbsp;` to separate list and indented+      code.  There's no need for it in this context, since this isn't to be+      interpreted using Markdown rules.+    + Preserve classes in JS obfuscated links (Timm Albers, #2989).+      HTML links containing classes originally now preserve them when using+      javascript email obfuscation.+    + Render `SmallCaps` as a native span when `native_spans` are enabled.+    + Always write attributes with `bracketed_spans` (d-dorazio).++  * Man writer:++    + Fix handling of nested font commands (#3568).  Previously pandoc emitted+      incorrect markup for bold + italic, for example, or bold + code.+    + Avoid error for definition lists with no definitions (#3832).++  * DocBook writer:++    + Fix internal links with `writerIdentifierPrefix opt`+      (#3397, Mauro Bieg).++  * Docx writer:++    + Don't include bookmarks on headers unless non-null id (#3476).+    + Support 9 levels of headers (#1642).+    + Allow 9 list levels (#3519).+    + Don't take `distArchive` from datadir (#3322).  The docx writer takes+      components from the distribution's version of `reference.docx` when it+      can't find them in a user's custom `reference.docx`.  Previously, we+      allowed a `reference.docx` in the data directory (e.g. `~/.pandoc`)+      to be used as the distribution's reference.docx.  This led to a+      bizarre situation where pandoc would produce a good docx using+      `--template ~/.pandoc/ref.docx`, but if `ref.docx` were moved to+      `~/.pandoc/reference.docx`, it would then produce a corrupted docx.+    + Fixed handling of soft hyphen (0173) (#3691).+    + Better handling of keywords (#3719).+    + Cleaner code for handling dir and style attributes for `Div`.+    + Use `Set` for dynamic styles to avoid duplicates.+    + Removed redundant element from data/docx/word/numbering.xml.+      The elements we need are generated when the document is+      compiled; this didn't do anything.+    + Activate `evenAndOddHeaders` from reference docx (#3901,+      Augustín Martín Barbero).++  * ODT/OpenDocument writer:++    + Calculate aspect ratio for percentage-sized images (Mauro Bieg, #3239).+    + Use more widely available bullet characters (#1400).  The old+      characters weren't available in some font sets.  These seem to work+      well on Windows and Linux versions of LibreOffice.+    + Wider labels for lists (#2421).  This avoids overly narrow labels for+      ordered lists with `()` delimiters.  However, arguably it creates+      overly wide labels for bullets.  Also, lists now start flush with+      the margin, rather than indented.+    + Fixed dropped elements in some ordered lists (#2434).++  * FB2 writer:++    + Don't render `RawBlock` as code.+    + Don't fail with an error on interior headers (e.g. in list) (#3750).+      Instead, omit them with an INFO message.+    + Add support for "lang" metadata (Alexander Krotov, #3625).+    + Format `LineBlock` as poem (Alexander Krotov).  Previously writer+      produced one paragraph with `<empty-line/>` elements, which are not+      allowed inside `<p>` according to FB2 schema.+    + Replace `concatMap` with `cMap` (Alexander Krotov).+    + Write FB2 lists without nesting blocks inside `<p>` (Alexander+      Krotov, #4004)++  * HTML writer:++    + Make sure `html4`, `html5` formats work for raw blocks/inlines.+    + Render raw inline environments when `--mathjax` used (#3816).+      We previously did this only with raw blocks, on the assumption+      that math environments would always be raw blocks. This has changed+      since we now parse them as inline environments.+    + Ensure we don't get two style attributes for width and height.+    + Report when not rendering raw inline/block.+    + Issue warning if no title specified and template used (#3473).+    + Info message if `lang` is unspecified (#3486).+    + Removed unused parameter in `dimensionsToAttributeList`.+    + Avoid two class attributes when adding `uri` class (#3716).+    + Fix internal links with `writerIdentifierPrefix opt` (#3397, Mauro+      Bieg).+    + Use revealjs's math plugin for mathjax (#3743).  This is a thin+      wrapper around mathjax that makes math look better on revealjs.+    + Slidy:  use h1 for all slides, even if they were originally+      level 2 headers (#3566).  Otherwise the built-in table of contents+      in Slidy breaks.++  * LaTeX writer:++    + Don't render LaTeX images with data: URIs (#3636).  Note that+      `--extract-media` can be used when the input contains data: URIs.+    + Make highlighted code blocks work in footnotes (Timm Albers).+    + Don't use figure inside table cell (#3836).+    + Use proper code for list enumerators (#3891).  This should fix problems+      with lists that don't use arabic numerals.+    + Always add hypertarget when there's a non-empty identifier (#2719).+      Previously the hypertargets were only added when there was actually+      a link to that identifier.+    + Use `%` after hypertarget before code block.+    + Add `\leavevmode` before hypertarget at start of paragraph (#2704,+      fixes formatting problems in beamer citations).+    + Don't use `lstinline` in \item[..] (#645).  If you do, the contents+      of item disappear or are misplaced.  Use `\texttt` instead.+    + Fix problem with escaping in `lstinline` (#1629).  Previously the+      LaTeX writer created invalid LaTeX when `--listings` was specified and+      a code span occured inside emphasis or another construction.+    + Fix error with line breaks after empty content (#2874).  LaTeX+      requires something before a line break, so we insert a `~` if no+      printable content has yet been emitted.+    + Use BCP47 parser.+    + Fixed detection of otherlangs (#3770).  We weren't recursing into+      inline contexts.+    + Handle language in inline code with `--listings` (#3422).+    + Write euro symbol directly in LaTeX (Andrew Dunning, #3801).+      The textcomp package allows pdfLaTeX to parse `€` directly, making the+      `\euro` command unneeded.+    + Fixed footnotes in table captions (#2378).  Note that if the table has+      a first page header and a continuation page header, the notes will+      appear only on the first occurrence of the header.+    + In `writeBeamer` output, allow hyperlinks to frames (#3220).+      Previously you could link to a header above or below slide level but+      not *to* slide level.  This commit changes that.  Hypertargets are+      inserted inside frame titles; technically the reference is to just+      after the title, but in normal use (where slides are viewed full+      screen in a slide show), this does not matter.+    + Remove `\strut` at beginning of table cells (#3436).  This fixes a+      problem with alignment of lists in table cells.  The `\strut` at the+      end seems to be enough to avoid the too-close spacing that motivated+      addition of the strut  in #1573.+    + Add partial siunitx Support (Marc Schreiber, #3588).++  * ConTeXt writer:++    + Refactored to use BCP47 module.+    + Remove unnecessary `$` (Alexander Krotov, #3482).+    + Use header identifiers for chapters (#3968).++  * EPUB writer:++    + `title_page.xhtml` is now put in `text/`.+    + Don't strip formatting in TOC (#1611).++  * Textile reader:++    + Fix bug for certain links in table cells (#3667).+    + Allow 'pre' code in list item (#3916).++  * HTML reader:++    + Added warnings for ignored material (#3392).+    + Better sanity checks to avoid parsing unintended things as+      raw HTML in the Markdown reader (#3257).+    + Revise treatment of `li` with `id` attribute (#3596).  Previously we+      always added an empty div before the list item, but this created+      problems with spacing in tight lists.  Now we do this: If the list+      item contents begin with a `Plain` block, we modify the `Plain`+      block by adding a `Span` around its contents.  Otherwise, we add a+      `Div` around the contents of the list item (instead of adding an+      empty `Div` to the beginning, as before).+    + Add `details` tag to list of block tags (#3694).+    + Removed `button` from block tag list (#3717).  It is already in the+      `eitherBlockOrInlineTag` list, and should be both places.+    + Use `Set`s instead of lists for block tag lookup.+    + Rewrote to use `Text` throughout.  Effect on memory usage is modest+      (< 10%).+    + Use the lang value of `<html>` to set the lang meta value (bucklereed,+      #3765).+    + Ensure that paragraphs are closed properly when the parent block+      element closes, even without `</p>` (#3794).+    + Parse `<figure>` and `<figcaption>` (Mauro Bieg, #3813).+    + Parse `<main>` like `<div role=main>` (bucklereed, #3791).+      `<main>` closes `<p>` and behaves like a block element generally+    + Support column alignments (#1881).  These can be set either+      with a `width` attribute or with `text-width` in a `style` attribute.+    + Modified state type to be an instance of `HasLogMessages`, so+      `registerHeader` can issue warnings.+    + `</td>` or `</th>` should close any open block tag (#3991).+    + `<td>` should close an open `<th>` or `<td>`.+    + `htmlTag` improvements (#3989).  We previously failed on cases+      where an attribute contained a `>` character. This patch fixes the+      bug, which especially affects raw HTML in Markdown.++  * Txt2Tags reader:++    + Newline is not indentation (Alexander Krotov).++  * MediaWiki reader:++    + Allow extra hyphens after `|-` in tables (#2649).+    + Allow blank line after table start (#2649).+    + Fixed more table issues (#2649).+    + Ensure that list starts begin at left margin (#2606).  Including when+      they're in tables or other list items.+    + Make smart double quotes depend on `smart` extension (#3585).+    + Don't do curly quotes inside `<tt>` contexts (#3585).  Even if `+smart`.+    + Modified state type to be an instance of `HasLogMessages`, so+      `registerHeader` can issue warnings.++  * TWiki reader (Alexander Krotov):++    + Remove unnecessary `$` (#3597).+    + Simplify `linkText` (#3605).++  * EPUB reader:++    + Minor refactoring, avoiding explicit MediaBag handling.+      This all works behind the scenes in CommonState plumbing.++  * Docx reader:++    + Don't drop smartTag contents (#2242).+    + Handle local namespace declarations (#3365).  Previously we didn't+      recognize math, for example, when the xmlns declaration occured on+      the element and not the root.+    + More efficient trimSps (#1530).  Replacing `trimLineBreaks`.  This+      does the work of `normalizeSpaces` as well, so we avoid the need for+      that function here.+    + Avoid 0-level headers (Jesse Rosenthal, #3830).  We used to parse+      paragraphs styled with "HeadingN" as "nth-level header." But if a+      document has a custom style named "Heading0", this will produce a+      0-level header, which shouldn't exist. We only parse this style+      if N>0. Otherwise we treat it as a normal style name, and+      follow its dependencies, if any.+    + Add tests for avoiding zero-level header (Jesse Rosenthal).++  * ODT reader:++    + Replaced `collectRights` with Rights from `Data.Either`.+    + Remove dead code (Albert Krewinkel).++  * Org reader (Albert Krewinkel, unless noted).++    + Don't allow tables inside list items (John MacFarlane, #3499).+    + Disallow tables on list marker lines (#3499).+    + Convert markup at beginning of footnotes (John MacFarlane, #3576).+    + Allow emphasized text to be followed by `[` (#3577).+    + Handle line numbering switch for src blocks.+      The line-numbering switch that can be given to source blocks (`-n` with+      an start number as an optional parameter) is parsed and translated to a+      class/key-value combination used by highlighting and other readers and+      writers.+    + Stop adding rundoc prefix to src params.  Source block parameter names+      are no longer prefixed with `rundoc`. This was intended to simplify+      working with the rundoc project, a babel runner. However, the rundoc+      project is unmaintained, and adding those markers is not the reader's+      job anyway.  The original language that is specified for a source+      element is now retained as the `data-org-language` attribute and only+      added if it differs from the translated language.+    + Allow multi-word arguments to src block params (#3477).  The reader now+      correctly parses src block parameter list even if parameter arguments+      contain multiple words.+    + Avoid creating `nullMeta` by applying `setMeta` directly+      (Alexander Krotov).+    + Replace `sequence . map` with `mapM`.+    + Fix smart parsing behavior.  Parsing of smart quotes and special+      characters can either be enabled via the `smart` language extension or+      the `'` and `-` export options. Smart parsing is active if either the+      extension or export option is enabled.  Only smart parsing of special+      characters (like ellipses and en and em dashes) is enabled by default,+      while smart quotes are disabled.  Previously, all smart parsing was+      disabled unless the language extension was enabled.+    + Subject full doc tree to headline transformations (Albert Krewinkel,+      #3695).  Emacs parses org documents into a tree structure, which is+      then post-processed during exporting. The reader is changed to do the+      same, turning the document into a single tree of headlines starting+      at level 0.+    + Fix cite parsing behaviour (Herwig Stuetz).  Until now, `org-ref`+      cite keys included special characters also at the end. This caused+      problems when citations occur right before colons or at the end of+      a sentence.  With this change, all non alphanumeric characters at+      the end of a cite key are ignored.  This also adds `,` to the list+      of special characters that are legal in cite keys to better mirror+      the behaviour of org-export.+    + Fix module names in haddock comments.  Copy-pasting had lead to+      haddock module descriptions containing the wrong module names.+    + Recognize babel result blocks with attributes (#3706).  Babel+      result blocks can have block attributes like captions and names.+      Result blocks with attributes were not recognized and were parsed+      as normal blocks without attributes.+    + Include tags in headlines.  The Emacs default is to include tags in the+      headline when exporting.  Instead of just empty spans, which contain the+      tag name as attribute, tags are rendered as small caps and wrapped in+      those spans.  Non-breaking spaces serve as separators for multiple tags.+    + Respect export option for tags (#3713).  Tags are appended to+      headlines by default, but will be omitted when the `tags` export option+      is set to nil.+    + Use `tag-name` attribute instead of `data-tag-name`.+    + Use `org-language` attribute rather than `data-org-language`.+    + Modified state type to be an instance of `HasLogMessages`, so+      `registerHeader` can issue warnings.+    + End footnotes after two blank lines.  Footnotes can not only be+      terminated by the start of a new footnote or a header, but also by two+      consecutive blank lines.+    + Update emphasis border chars (#3933).  The org reader was updated to+      match current org-mode behavior: the set of characters which are+      acceptable to occur as the first or last character in an org emphasis+      have been changed and now allows all non-whitespace chars at the+      inner border of emphasized text (see `org-emphasis-regexp-components`).++  * RST reader:++    + Fixed small bug in list parsing (#3432).  Previously the parser didn't+      handle properly this case:++          * - a+            - b+          * - c+            - d+    + Handle multiline cells in simple tables (#1166).+    + Parse list table directive (Keiichiro Shikano, #3432).+    + Make use of `anyLineNewline` (Alexander Krotov, #3686).+    + Use `anyLineNewline` in `rawListItem` (Alexander Krotov, #3702).+    + Reorganize block parsers for ~20% faster parsing.+    + Fixed `..include::` directive (#3880).+    + Handle blank lines correctly in line blocks (Alexander Krotov, #3881).+      Previously pandoc would sometimes combine two line blocks separated+      by blanks, and ignore trailing blank lines within the line block.+    + Fix indirect hyperlink targets (#512).++  * Markdown reader:++    + Allow attributes in reference links to start on next line (#3674).+    + Parse YAML metadata in a context that sees footnotes defined in+      the body of the document (#1279).+    + When splitting pipe table cells, skip tex math (#3481).+      You might have a `|` character inside math.  (Or for that matter+      something that the parser might mistake for raw HTML.)+    + Treat span with class `smallcaps` as SmallCaps.+      This allows users to specify small caps in Markdown this way:+      `[my text]{.smallcaps}` (#1592).+    + Fixed internal header links (#2397).+      This patch also adds `shortcut_reference_links` to the list+      of mmd extensions.+    + Treat certain environments as inline+      when they occur without space surrounding them (#3309, #2171).+      E.g. equation, math.  This avoids incorrect vertical space+      around equations.+    + Optimized `nonindentSpaces`.  Makes the benchmark go from 40 to 36 ms.+    + Allow latex macro definitions indented 1-3 spaces.+      Previously they only worked if nonindented.+    + Improved parsing of indented raw HTML blocks (#1841).+      Previously we inadvertently interpreted indented HTML as+      code blocks.  This was a regression.  We now seek to determine the+      indentation level of the contents of an HTML block, and (optionally)+      skip that much indentation.  As a side effect, indentation may be+      stripped off of raw HTML blocks, if `markdown_in_html_blocks` is+      used. This is better than having things interpreted as indented+      code blocks.+    + Fixed smart quotes after emphasis (#2228).  E.g. in `*foo*'s 'foo'`.+    + Warn for notes defined but not used (#1718).+    + Use `anyLineNewline` (Alexander Krotov).+    + Interpret YAML metadata as Inlines when possible (#3755).  If+      the metadata field is all on one line, we try to interpret it as+      Inlines, and only try parsing as Blocks if that fails.  If it+      extends over one line (including possibly the `|` or `>` character+      signaling an indented block), then we parse as Blocks.  This was+      motivated by some German users finding that `date: '22. Juin 2017'`+      got parsed as an ordered list.+    + Fixed spurious parsing as citation as reference def (#3840).+      We now disallow reference keys starting with `@` if the+      `citations` extension is enabled.+    + Parse `-@roe` as suppress-author citation (pandoc-citeproc#237).+      Previously only `[-@roe]` (with brackets) was recognized as+      suppress-author, and `-@roe` was treated the same as `@roe`.+    + Fixed parsing of fenced code after list when there is no intervening+      blank line (#3733).+    + Allow raw latex commands starting with `\start` (#3558).  Previously+      these weren't allowed because they were interpreted as starting+      ConTeXt environments, even without a corresponding `\stop`...+    + Added `inlines`, `inlines1`.+    + Require nonempty alt text for `implicit_figures` (#2844).+      A figure with an empty caption doesn't make sense.+    + Removed texmath macro material; now all this is handled+      in the LaTeX reader functions.+    + Fixed bug with indented code following raw LaTeX (#3947).++  * LaTeX reader:++    + Rewrote LaTeX reader with proper tokenization (#1390,+      #2118, #3236, #3779, #934, #982).  This rewrite is primarily+      motivated by the need to get macros working properly.  A side benefit+      is that the reader is significantly faster.  We now tokenize the+      input text, then parse the token stream.  Macros modify the token+      stream, so they should now be effective in any context, including+      math. Thus, we no longer need the clunky macro processing+      capacities of texmath.+    + Parse `\,` to `\8198` (six-per-em space) (Henri Werth).+    + Allow `\newcommand\foo{blah}` without braces.+    + Support `\lstinputlisting` (#2116).+    + Issue warnings when skipping unknown latex commands (#3392).+    + Include contents of `\parbox`.+    + Allow `\hspace` and `\vspace` to count as raw block or inline.+      Previously we would refuse to parse anything as raw inline if+      it was in the `blockCommands` list.  Now we allow exceptions+      if they're listed under ignoreInlines in inlineCommands.+      This should make it easier e.g. to include an `\hspace`+      between two side-by-side raw LaTeX tables.+    + Don't drop contents of `\hypertarget`.+    + Handle spaces before `\cite` arguments.+    + Allow newpage, clearpage, pagebreak in inline contexts as well as+      block contexts (#3494).+    + Treat `{{xxx}}` the same as `{xxx}` (#2115).+    + Use `pMacroDefinition` in macro (for more direct parsing).+      Note that this means that `macro` will now parse one+      macro at a time, rather than parsing a whole group together.+    + Fixed failures on \ref{}, \label{} with `+raw_tex`.  Now these+      commands are parsed as raw if `+raw_tex`; otherwise, their argument+      is parsed as a bracketed string.+    + Don't crash on empty `enumerate` environment (#3707).+    + Handle escaped `&` inside table cell (#3708).+    + Handle block structure inside table cells (#3709).  `minipage` is no+      longer required.+    + Handle some width specifiers on table columns (#3709).  Currently+      we only handle the form `0.9\linewidth`.  Anything else would have+      to be converted to a percentage, using some kind arbitrary assumptions+      about line widths.+    + Make sure `\write18` is parsed as raw LaTeX.  The change is in the+      LaTeX reader's treatment of raw commands, but it also affects the+      Markdown reader.+    + Fixed regression with starred environment names (#3803).+    + Handle optional args in raw `\titleformat` (#3804).+    + Improved heuristic for raw block/inline.  An unknown command at the+      beginning of the line that could be either block or inline is+      treated as block if we have a sequence of block commands followed by+      a newline or a `\startXXX` command (which might start a raw ConTeXt+      environment).+    + Don't remove macro definitions from the output, even if+      `Ext_latex_macros` is set, so that macros will be applied.+      Since they're only applied to math in Markdown, removing the macros+      can have bad effects.  Even for math macros, keeping them should be+      harmless.+    + Removed `macro`.  It is no longer necessary, since the+      `rawLaTeXBlock` parser will parse macro definitions.  This also avoids+      the need for a separate `latexMacro` parser in the Markdown reader.+    + Use `label` instead of `data-label` for label in caption (#3639).+    + Fixed space after \figurename etc.+    + Resolve references to section numbers.+    + Fix `\let\a=0` case, with single character token.+    + Allow `@` as a letter in control sequences.  `@` is commonly used+      in macros using `\makeatletter`.  Ideally we'd make the tokenizer+      sensitive to `\makeatletter` and `\makeatother`, but until then this+      seems a good change.+    + Track header numbers and correlate with labels.+    + Allow `]` inside group in option brackets (#3857).+    + lstinline with braces can be used (verb cannot be used with braces)+      (Marc Schreiber, #3535).+    + Fix keyval funtion: pandoc did not parse options in braces correctly+      (Marc Schreiber, #3642).+    + When parsing raw LaTeX commands, include trailing space (#1773).+      Otherwise things like `\noindent foo` break and turn into+      `\noindentfoo`.  Affects `-f latex+raw_tex` and `-f markdown` (and other+      formats that allow `raw_tex`).+    + Don't treat "..." as Quoted (#3958).  This caused quotes to be omitted in+      `\texttt` contexts.+    + Add tests for existing `\includegraphics` behaviour (Ben Firshman).+    + Allow space before `=` in bracketd options (Ben Firshman).+    + Be more forgiving in parsing command options.  This was needed, for+      example, to make some minted options work.+    + Strip off quotes in `\include` filenames.++  * Added `Text.Pandoc.CSV`, simple (unexported) CSV parser.++  * `Text.Pandoc.PDF`:++    + Got `--resource-path` working with PDF output (#852).+    + Fetch images when generating PDF via context (#3380).+      To do this, we create the temp directory as a subdirectory+      of the working directory. Since context mk IV by default looks+      for images in the parent directory, this works.+    + Use `report` instead of `warn`, make it sensitive to verbosity settings.+    + Use `fillMediaBag` and `extractMedia` to extract media to temp dir.+      This reduces code duplication.+    + `html2pdf`: use stdin instead of intermediate HTML file+    + Removed useless `TEXINPUTS` stuff for `context2pdf`.  mkiv context+      doesn't use `TEXINPUTS`.++  * `Text.Pandoc.Pretty`:++    + Simplified definition of `realLength`.+    + Don't error for blocks of size < 1.  Instead, resize to 1 (see #1785).++  * `Text.Pandoc.MIME`:++    + Use `application/javascript` (not `application/x-javascript`).+    + Added `emf` to mimeTypes with type `application/x-msmetafile` (#1713).++  * `Text.Pandoc.ImageSize`:++    + Improve SVG image size code (Marc Schreiber, #3580).+    + Make `imageSize` recognize basic SVG dimensions (Mauro Bieg, #3462).++  * Use `Control.Monad.State.Strict` throughout.  This gives 20-30% speedup+    and reduction of memory usage in most of the writers.++  * Use `foldrWithKey` instead of deprecated `foldWithKey`.++  * `Text.Pandoc.SelfContained`:++    + Fixed problem with embedded fonts (#3629).+    + Refactored getData from `getDataURI` in `SelfContained`.+    + Don't use data URIs for script or style (#3423).  Instead, just use+      script or style tags with the content inside.  The old method with+      data URIs prevents certain optimizations outside pandoc.  Exception:+      data URIs are still used when a script contains `</script>` or a+      style contains `</`.+    + SelfContained: Handle URL inside material retrieved from a URL+      (#3629).  This can happen e.g. with an @import of a google web font.+      (What is imported is some CSS which contains an url reference+      to the font itself.) Also, allow unescaped pipe (|) in URL.+    + Load resources from `data-src` (needed for lazy loading in+      reveal.js slide shows).+    + Handle `data-background-image` attribute on section (#3979).++  * `Text.Pandoc.Parsing`:++    + Added `indentWith` (Alexander Krotov, #3687).+    + Added `stateCitations` to `ParserState`.+    + Removed `stateChapters` from `ParserState`.+    + In `ParserState`, make `stateNotes'` a Map, add `stateNoteRefs`.+    + Added `gobbleSpaces` and `gobbleAtMostSpaces`.+    + Adjusted type of `insertIncludedFile` so it can be used with token+      parser.+    + Replace old texmath macro stuff from Parsing.  Use Macro from+      Text.Pandoc.Readers.LaTeX.Types instead.+    + Export `insertIncludedFile`.+    + Added `HasLogMessages`, `logMessage`, `reportLogMessages` (#3447).+    + Replace partial with total function (Albert Krewinkel).+    + Introduce `HasIncludeFiles` type class (Albert Krewinkel).  The+      `insertIncludeFile` function is generalized to work with all parser+      states which are instances of that class.+    + Add `insertIncludedFilesF` which returns F blocks (Albert Krewinkel).+      The `insertIncludeFiles` function was generalized and renamed+      to `insertIncludedFiles'`; the specialized versions are based on that.+    + `many1Till`: Check for the end condition before parsing (Herwig+      Stuetz).  By not checking for the end condition before the first+      parse, the parser was applied too often, consuming too much of the+      input. This only affects `many1Till p end` where `p` matches on a+      prefix of `end`.+    + Provide `parseFromString` (#3690).  This is a verison of+      `parseFromString` specialied to ParserState, which resets+      `stateLastStrPos` at the end.  This is almost always what we want.+      This fixes a bug where `_hi_` wasn't treated as emphasis in the+      following, because pandoc got confused about the position of the+      last word: `- [o] _hi_`.+    + Added `takeP`, `takeWhileP` for efficient parsing of `[Char]`.+    + Fix `blanklines` documentation (Alexander Krotov, #3843).+    + Give less misleading line information with `parseWithString`.+      Previously positions would be reported past the end of the chunk.+      We now reset the source position within the chunk and report+      positions "in chunk."+    + Add `anyLineNewline` (Alexander Krotov).+    + Provide shared F monad functions for Markdown and Org readers+      (Albert Krewinkel).  The `F` monads used for delayed evaluation+      of certain values in the Markdown and Org readers are based on a+      shared data type capturing the common pattern of both `F` types.+    + Add `returnF` (Alexander Krotov).+    + Avoid parsing `Notes:**` as a bare URI (#3570).  This avoids parsing+      bare URIs that start with a scheme + colon + `*`, `_`, or `]`.+    + Added `readerAbbreviations` to `ParserState`.  Markdown reader+      now consults this to determine what is an abbreviation.+    + Combine grid table parsers (Albert Krewinkel, #3638).  The grid table+      parsers for markdown and rst was combined into one single+      parser `gridTable`, slightly changing parsing behavior of both+      parsers: (1) The markdown parser now compactifies block content+      cell-wise: pure text blocks in cells are now treated as paragraphs+      only if the cell contains multiple paragraphs, and as plain blocks+      otherwise. Before, this was true only for single-column tables. (2)+      The rst parser now accepts newlines and multiple blocks in header+      cells.+    + Generalize tableWith, gridTableWith (Albert Krewinkel).+      The parsing functions `tableWith` and `gridTableWith` are generalized+      to work with more parsers. The parser state only has to be an+      instance of the `HasOptions` class instead of requiring a concrete+      type. Block parsers are required to return blocks wrapped into a+      monad, as this makes it possible to use parsers returning results+      wrapped in `Future`s.++  * `Text.Pandoc.Shared`:++    + Simplify `toRomanNumeral` using guards (Alexander Krotov, #3445)+    + `stringify`: handle Quoted better (#3958).  Previously we were losing+      the quotation marks in Quoted elements.++  * `Text.Pandoc.Writers.Shared`:++    + Export `metaToJSON'`, `addVariablesToJSON` (#3439).+      This allows us to add the variables AFTER using the metadata+      to generate a YAML header (in the Markdown writer).+    + Added `unsmartify` (previously in RST writer).+      Undo literal double curly quotes.  Previously we left these.+    + Generalize type of `metaToJSON` so it can take a Text.  Previously a+      String was needed as argument; now any ToJSON instance will do.+    + Added `gridTable` (previously in Markdown writer).+    + `gridTable`: Refactored to use widths in chars.+    + `gridTable`:  remove unnecessary extra space in cells.+    + Fixed `addVariablesToJSON`.  It was previously not allowing multiple+      values to become lists.+    + Pipe tables: impose minimum cell size (see #3526).+++  [default template changes]++  * HTML templates (including EPUB and HTML slide show templates):++    + Make default.html5 polyglot markup conformant (John Luke Bentley,+      #3473).  Polyglot markup is HTML5 that is also valid XHTML. See+      <https://www.w3.org/TR/html-polyglot>.  With this change, pandoc's+      html5 writer creates HTML that is both valid HTML5 and valid XHTML.+    + Regularized CSS in html/epub/html slide templates (#3485).+      All templates now include `code{white-space: pre-wrap}`+      and CSS for `q` if `--html-q-tags` is used.  Previously some templates+      had `pre` and others `pre-wrap`; the `q` styles were only sometimes+      included.+    + CSS for `.smallcaps`, (Mauro Bieg, #1592)+    + `default.revealjs`: make `history` default to true.+    + `default.revealjs`: use lazy loading (#2283).+    + `default.revealjs`: add `mathjax` variable and some conditional code+      to use the MathJaX plugin.+    + `default.slidy` uses `https` instead of `http` (ickc, #3848).+    + `default.dzslides`: Load Google Font using HTTPS by default+      (Yoan Blanc).++  * DocBook5 template: Use `lang` and `subtitle` variables (Jens Getreu,+    #3855).++  * LaTeX/Beamer template:++    + Combine LaTeX/Beamer templates (Andrew Dunning, #3878).+      `default.beamer` has been removed; beamer now uses the+      `default.latex` template.  Beamer-specific parts are conditional+      on the `beamer` variable set by the writer. Note that+      `pandoc -D beamer` will return this (combined) template.+    + Use `xcolor` for `colorlinks` option (Andrew Dunning, #3877).+      Beamer loads `xcolor` rather than `color`, and thus the+      `dvipsnames` option doesn't take effect. This also provides a wider+      range of colour selections with the `svgnames` option.+    + Use starred versions of `xcolor` names (Andrew Dunning).+      Prevents changes to documents defined using the `dvipsnames` list (e.g.+      `Blue` gives a different result with svgnames enabled).+    + Load `polyglossia` after header-includes (#3898).  It needs to be+      loaded as late as possible.+    + Use `unicode-math` (Vaclav Haisman).  Use `mathspec` with only+      XeLaTeX on request.+    + Don't load `fontspec` before `unicode-math` (over there).+      The `unicode-math` package loads `fontspec` so explict loading of+      `fontspec` before `unicode-math` is not necessary.+    + Use `unicode-math` by default in default.latex template.  mathspec will+      be used in xelatex if the `mathspec` variable is set; otherwise+      unicode-math will be used (Václav Haisman).+    + Use `dvipsnames` options when `colorlinks` specified (otherwise+      we get an error for `maroon`) (Thomas Hodgson).+    + Added beamer `titlegraphic` and `logo` variables (Thomas Hodgson).+    + Fix typo in fix for notes in tables (#2378, zeeMonkeez).+    + Fix `hyperref` options clash (Andrew Dunning, #3847) Avoids an options+      clash when loading a package (e.g. `tufte-latex`) that uses+      `hyperref` settings different from those in the template.+    + Add `natbiboptions` variable (#3768).+    + Fix links inside captions in LaTeX output with links-as-notes+      (Václav Haisman, #3651).  Declare our redefined `\href` robust.+    + Load `parskip` before `hyperref` (Václav Haisman, #3654).+    + Allow setting Japanese fonts when using LuaLaTeX (Václav Haisman,+      #3873).  by using the `luatexja-fontspec` and `luatexja-preset`+      packages. Use existing `CJKmainfont` and `CJKoptions` template+      variables. Add `luatexjafontspecoptions` for `luatexja-fontspec`+      and `luatexjapresetoptions` for `luatexja-preset`.+    + Added `aspectratio` variable to beamer template (Václav Haisman,+      #3723).+    + Modified template.latex to fix XeLaTex being used with tables+      (lwolfsonkin, #3661).  Reordered `lang` variable handling to+      immediately before `bidi`.++  * ConTeXt template: Improved font handling: `simplefonts` is now+    obsolete in ConTeXt (Pablo Rodríguez).+++  [documentation improvements]++  * MANUAL.txt:++    + Add URL for Prince HTML > PDF engine (Ian, #3919).+    + Document that content above slide-level will be omitted in+      slide shows.  See #3460, #2265.+    + Explain `--webtex` SVG url (Mauro Bieg, #3471)+    + Small clarification in YAML metadata section.+    + Document that html4 is technically XHTML 1.0 transitional.+    + Remove refs to highlighting-kate (#3672).+    + Document ibooks specific epub metadata.+    + Clarify that mathml is used for ODT math.+    + Mention limitations of Literate Haskell Support (#3410,+      Joachim Breitner).+    + Add documentation of limitations of grid tables (Stephen+      McDowell, #3864).+    + Clarify that meta-json contains transformed values (Jakob Voß,+      #3491) Make clear that template variable `meta-json` does not+      contain plain text values or JSON output format but field values+      transformed to the selected output format.++  * COPYRIGHT:++    + Clarify that templates are dual-licensed.+    + Clarify that pandoc-types is BSD3 licensed.+    + List new files not written by jgm (Albert Krewinkel).+    + Update dates in copyright notices (Albert Krewinkel).  This follows+      the suggestions given by the FSF for GPL licensed software.+      <https://www.gnu.org/prep/maintain/html_node/Copyright-Notices.html>++  * INSTALL.md:++    + Improved instructions for tests with patterns.+    + Put RPM-based distros on separate point (Mauro Bieg, #3449)++  * CONTRIBUTING.md:++    + Fixed typos (Wandmalfarbe, #3479).+    + Add "ask on pandoc-discuss" (Mauro Bieg).++  * Add lua filter documentation in `doc/lua-filters.md`.  Note that the+    end of this document is autogenerated from `data/pandoc.lua`+    using `make doc/lua-filters.md`, which uses `tools/ldoc.ltp`+    (Albert Krewinkel).++  * Add `doc/filters.md`. This is the old scripting tutorial from+    the website.++  * Add `doc/using-the-pandoc-api.md` (#3289).  This gives an introduction+    to using pandoc as a Haskell library.+++  [build infrastructure improvements]++  * Removed `data/templates` submodule.  Templates are now a subtree+    in `data/templates`.  This removes the need to do `git submodule+    update`.++  * Renamed `tests` -> `test`.++  * Remove `https` flag.  Always build with HTTPS support.++  * Use `file-embed` instead of `hsb2hs` to embed data files when+    `embed_data_files` flag is set.  `file-embed` gives us better dependency+    tracking:  if a data file changes, ghc/stack/cabal know to recompile+    the Data module.  This also removes `hsb2hs` as a build dependency.++  * Add `custom-setup` stanza to pandoc, lowercase field names.++  * Add `static` Cabal flag.++  * Name change OSX -> MacOS.  Add a -MacOS suffix to mac package rather+    than -OSX.  Changed local names from osx to macos.++  * make_macos_package.sh - Use strip to reduce executable size.++  * Revised binary linux package.  Now a completely static executable+    is created, using Docker and alpine.  We create both a deb and a+    tarball.  The old `deb` directory has been replaced with a `linux`+    directory.  Running `make` in the `linux` directory should+    perform the build, putting the binary packages in `artifacts/`.++  * `linux/control.in`: add `Replaces:`, so existing pandoc-citeproc and+    pandoc-data packages will be uninstalled; this package provides+    both (#3822).  Add latex packages as 'suggested', update+    description.++  * Remove cpphs build requirement -- it is no longer needed.++  * Replaced `{deb,macos,windows}/stack.yaml` with `stack.pkg.yaml`.++  * Name change OSX -> macOS (ickc, #3869).++  * Fix casing of Linux, UNIX, and Windows (ickc).++  * `.travis.yml`:  create a source dist and do cabal build and test there.+    That way we catch errors due to files missing from the data+    section of pandoc.cabal.++  * Makefile:++    + Split `make haddock` from `make full`.+    + Add BRANCH variable for winpkg.+    + Add `lint` target.+    + Improve `make full`. Disable optimizations.+      Build everything, inc. trypandoc and benchmarks.  Use parallel build.+    + Allow `make test` to take `TESTARGS`.++  * Added new command tests (`Tests.Command`), using small text files+    in `test/command/`.  Any files added in this directory will be treated+    as shell tests (see smart.md for an example).  This makes it very easy+    to add regression tests etc.++  * Test fixes so we can find data files.  In old tests & command tests,+    we now set the environment variable `pandoc_datadir`.  In lua tests,+    we set the datadir explicitly.++  * Refactored `compareOutput` in docx writer test.++  * Consolidated some common functions in `Tests.Helper`.++  * Small change to unbalanced bracket test to speed up test suite.++  * Speed up Native writer quickcheck tests.++  * Use tasty for tests rather than test-framework.++  * Add simple Emacs mode to help with Pandoc templates editing.+    (Václav Haisman, #3889). `tools/pandoc-template-mode.el`+++pandoc (1.19.2)++  * Use skylighting library instead of highlighting-kate for syntax+    highlighting. Skylighting is faster and more accurate (#3363).+    Later we'll be able to add features like warning messages, dynamic+    loading of xml syntax definitions, and dynamic loading of themes.++  * Added a new highlight style, `breezeDark`.++  * Text.Pandoc.Highlighting: Update list of `listings` languages (#3374).+    This allows more languages to be used when using the `--listings`+    option.++  * OpenDocument writer:++    + Small refactoring.  Removed separate 'parent' parameter in paraStyle.+    + Don't profilerate text styles unnecessarily (#3371).+      This change makes the writer create only as many temporary+      text styles as are absolutely necessary. It also consolidates+      adjacent nodes with the same style.++  * Org reader (Albert Krewinkel):++    + Allow short hand for single-line raw blocks (Albert Krewinkel,+      #3366).  Single-line raw blocks can be given via `#+FORMAT: raw line`,+      where `FORMAT` must be one of `latex`, `beamer`, `html`, or `texinfo`.+    + Accept org-ref citations followed by commas (Albert Krewinkel).+      Bugfix for an issue which, whenever the citation was immediately+      followed by a comma, prevented correct parsing of org-ref citations.+    + Ensure emphasis markup can be nested.  Nested emphasis markup (e.g.+      `/*strong and emphasized*/`) was interpreted incorrectly in that the+      inner markup was not recognized.+    + Remove pipe char irking the haddock coverage tool (Albert Krewinkel).++  * Docx reader: Empty header should be list of lists (Jesse Rosenthal).+    In the past, the docx reader wrote an empty header as an empty list. It+    should have the same width as a row (and be filled with empty cells).++  * MediaWiki reader:++    + Improved handling of display math (#3362).  Sometimes display math is+      indented with more than one colon.  Previously we handled these cases+      badly, generating definition lists and missing the math.+    + Fix quotation mark parsing (#3336, tgkokk).  Change MediaWiki reader's+      behavior when the smart option is parsed to match other readers'+      behavior.++  * Markdown reader:++    + Fixed `-f markdown_github-hard_line_breaks+escaped_line_breaks`+      (#3341).  Previously this did not properly enable escaped line breaks.+    + Disallow space between inline code and attributes (#3326, #3323,+      Mauro Bieg).++  * DocBook5 writer: make id attribute xml:id, fixes #3329 (#3330, Mauro Bieg).++  * Added some test cases for ODT reader (#3306, #3308, Hubert Plociniczak).++  * LaTeX writer: allow tables with empty cells to count as "plain."+    This addresses a problem of too-wide tables when empty cells+    are used.  Thanks to Joost Kremers for reporting the issue.++  * Org writer: prefix footnote numbers with `fn:` (Albert Krewinkel).+    Unprefixed numbers where used by older org-mode versions, but are no+    longer supported.++  * HTML writer: don't process pars with empty RawInline, (#1040, #3327,+    Mauro Bieg).++  * Markdown writer: Fix display math with `--webtex` (#3298).++  * Fix sample.lua so it properly handles raw blocks/inlines (#3358,+    bumper314).++  * Templates:++    + default.latex: Moved geometry after hyperref (Václav Haisman).+      Otherwise PDF sizes can be wrong in some circumstances.+    + Copied a few changes from default.latex to default.beamer+      (Wandmalfarbe).+    + default.latex, default.beamer: Changed position of `\VerbatimNotes`+      and `fancyvrb`.  This fixes hyperlinks on footnotes in documents+      that contain verbatim in notes (#3361).  (Note: the beamer template+      was updated to match the LaTeX template, but at this point verbatim+      in notes seems not to work in beamer.)+    + default.latex: Allow passing `microtypeoptions` to microtype+      (Václav Haisman).+    + default.latex: Add hyphen option to url package.+    + default.docbook5: Fix namespace declarations (Mauro Bieg).++  * Moved `make_osx_package.sh` to `osx/` directory.++  * Travis continuous integration:++    + Fix false positives with dist build.+    + Speed improvements (Kolen Cheung, #3304, #3357).++  * MANUAL.txt:++    + Clarify that blank space is needed around footnotes (#3352).+    + Fixed typo (#3351, Alexey Rogechev).+    + Note that `--wrap=auto` does not work in HTML output.+    + Default `--columns` width is 72, not 80.+    + Fixed broken links (#3316, Kolen Cheung).+    + Document usage of `@*` in nocite section (#3333, John Muccigrosso).++  * INSTALL.md:++    + Indent code so it's properly formatted (#3335, Bheesham Persaud).+    + Added instructions for extracting binary from OSX, Windows packages.++  * CONTRIBUTING.md: Describe labels currently used in issue tracker+    (Albert Krewinkel).  The labels have changed over time, the list of+    labels is updated to reflect the current set of labels used in the+    issue tracker.++  * Rearrange and extend badges in README (Albert Krewinkel, #3354)++  * Bumped version bounds for dependencies.+++pandoc (1.19.1)++  * Set `PANDOC_VERSION` environment variable for filters (#2640).+    This allows filters to check the pandoc version that produced+    the JSON they are receiving.++  * Docx reader: Ensure one-row tables don't have header (#3285,+    Jesse Rosenthal).  Tables in MS Word are set by default to have+    special first-row formatting, which pandoc uses to determine whether+    or not they have a header. This means that one-row tables will, by+    default, have only a header -- which we imagine is not what people+    want. This change ensures that a one-row table is not understood to+    be a header only.  Note that this means that it is impossible to+    produce a header-only table from docx, even though it is legal+    pandoc. But we believe that in nearly all cases, it will be an+    accidental (and unwelcome) result++  * HTML reader:++    + Fixed some bad regressions in HTML table parser (#3280).+      This regression leads to the introduction of empty rows+      in some circumstances.+    + Understand `style=width:` as well as `width` in `col` (#3286).++  * RST reader:++    + Print warnings when keys, substitition, notes not found.+      Previously the parsers failed and we got raw text.  Now we get a+      link with an empty URL, or empty inlines in the case of a note or+      substitution.++    + Fix hyperlink aliases (#3283).++  * Man writer: Ensure that periods are escaped at beginning of line+    (#3270).++  * LaTeX writer: Fix unnumbered headers when used with `--top-level`+    (#3272, Albert Krewinkel).  Fix interaction of top-level divisions+    `part` or `chapter` with unnumbered headers when emitting LaTeX.  Headers+    are ensured to be written using stared commands (like `\subsection*{}`).++  * LaTeX template: use comma not semicolon to separate keywords for+    `pdfkeywords`.  Thanks to Wandmalfarbe.++  * Markdown writer: Fixed incorrect word wrapping (#3277).  Previously pandoc+    would sometimes wrap lines too early due to this bug.++  * Text.Pandoc.Pretty:  Added `afterBreak` [API change].  This makes it+    possible to insert escape codes for content that needs escaping at the+    beginning of a line.++  * Removed old MathMLInHTML.js from 2004, which should no longer+    be needed for MathML with modern browsers.++  * Fixed tests with dynamic linking (#2709).++  * Makefile: Use stack instead of cabal for targets.  This is just+    a convenience for developers.++  * Fixed bash completion of filenames with space (#2749).++  * MANUAL: improved documentation on how to create a custom `reference.docx`.++  * Fix minor spelling typos in the manual (#3273, Anthony Geoghegan)++pandoc (1.19)++  * Changed resolution of filter paths.++    + We now first treat the argument of `--filter` as a full (absolute+      or relative) path, looking for a program there. If it's found, we+      run it.+    + If not, and if it is a simple program name or a relative path, we+      try resolving it relative to `$DATADIR/filters`.+    + If this fails, then we treat it as a program name and look in the+      user's PATH.+    + Removed a hardcoded '/' that may have caused problems with+      Windows paths.++    Previously if you did `--filter foo` and you had `foo` in your path and+    also an executable `foo` in your working directory, the one in the path+    would be used. Now the one in the working directory is used.++    In addition, when you do `--filter foo/bar.hs`, pandoc will now find a+    filter `$DATADIR/filters/foo/bar.hs` -- assuming there isn't a+    `foo/bar.hs` relative to the working directory.++  * Allow `file://` URIs as arguments (#3196). Also improved default reader+    format detection. Previously with a URI ending in .md or .markdown,+    pandoc would assume HTML input. Now it treats these as markdown.++  * Allow to overwrite top-level division type heuristics (#3258,+    Albert Krewinkel). Pandoc uses heuristics to determine the most+    reasonable top-level division type when emitting LaTeX or+    Docbook markup. It is now possible to overwrite this implicitly set+    top-level division via the `top-level-division` command line parameter.++  * Text.Pandoc.Options \[API changes\]:++    + Removed `writerStandalone` field in `WriterOptions`, made+      `writerTemplate` a `Maybe` value. Previously setting+      `writerStandalone = True` did nothing unless a template was provided+      in writerTemplate. Now a fragment will be generated if+      `writerTemplate` is `Nothing`; otherwise, the specified template+      will be used and standalone output generated.+    + `Division` has been renamed `TopLevelDivision` (#3197). The+      `Section`, `Chapter`, and `Part` constructors were renamed to+      `TopLevelSection`, `TopLevelChapter`, and+      `TopLevelPart`, respectively. An additional `TopLevelDefault`+      constructor was added, which is now also the new default value of+      the `writerTopLevelDivision` field in `WriterOptions`.++  * Improved error if they give wrong arg to `--top-level-division`.++  * Use new module from texmath to lookup MS font codepoints in Docx reader.+    Removed unexported module Text.Pandoc.Readers.Docx.Fonts. Its code now+    lives in texmath (0.9).++  * DocBook reader: Fixed xref lookup (#3243). It previously only worked+    when the qnames lacked the docbook namespace URI.++  * HTML reader:++    + Improved table parsing (#3027). We now check explicitly for non-1+      rowspan or colspan attributes, and fail when we encounter them.+      Previously we checked that each row had the same number of cells,+      but that could be true even with rowspans/colspans. And there are+      cases where it isn't true in tables that we can handle fine -- e.g.+      when a tr element is empty. So now we just pad rows with empty cells+      when needed.+    + Treat `<math>` as MathML by default unless something else is+      explicitly specified in xmlns. Provided it parses as MathML,+      of course. Also fixed default which should be to inline math if no+      display attribute is used.+    + Only treat "a" element as link if it has href (#3226). Otherwise+      treat as span.++  * Docx reader (Jesse Rosenthal):++    + Add a placeholder value for CHART. We wrap `[CHART]` in a+      `<span class="chart">`. Note that it maps to inlines because, in+      docx, anything in a drawing tag can be part of a larger paragraph.+    + Be more specific in parsing images We not only want `w:drawing`,+      because that could also include charts. Now we specify+      `w:drawing/pic:pic`. This shouldn't change behavior at all, but it's+      a first step toward allowing other sorts of drawing data as well.+    + Abstract out function to avoid code repetition.+    + Update tests for img title and alt (#3204).+    + Handle Alt text and titles in images. We use the "description" field+      as alt text and the "title" field as title. These can be accessed+      through the "Format Picture" dialog in Word.+    + Docx reader utils: handle empty namespace in `elemName`. Previously,+      if given an empty namespace `(elemName ns "" "foo")` `elemName`+      would output a QName with a `Just ""` namespace. This is never what+      we want. Now we output a `Nothing`. If someone *does* want a+      `Just ""` in the namespace, they can enter the QName+      value explicitly.++  * ODT reader/writer:++    + Inline code when text has a special style (Hubert Plociniczak). When+      a piece of text has a text `Source_Text` then we assume that this is+      a piece of the document that represents a code that needs to+      be inlined. Adapted the writer to also reflect that change.+      Previously it was just writing a 'preformatted' text using a+      non-distinguishable font style. Code blocks are still not recognized+      by the ODT reader. That's a separate issue.+    + Infer table's caption from the paragraph (#3224,+      Hubert Plociniczak). ODT's reader always put empty captions for the+      parsed tables. This commit++        1.  checks paragraphs that follow the table definition+        2.  treats specially a paragraph with a style named 'Table'+        3.  does some postprocessing of the paragraphs that combines tables+            followed immediately by captions++      The ODT writer used the `TableCaption` style for the caption+      paragraph.  This commit follows the OpenOffice approach which allows+      for appending captions to table but uses a built-in style named+      `Table` instead of `TableCaption`. Users of a custom `reference.odt`+      should change the style's name from `TableCaption` to `Table`.++  * ODT reader: Infer tables' header props from rows (#3199,+    Hubert Plociniczak). ODT reader simply provided an empty header list+    which meant that the contents of the whole table, even if not empty, was+    simply ignored. While we still do not infer headers we at least have to+    provide default properties of columns.++  * Markdown reader:++    +   Allow reference link labels starting with `@...` if `citations`+        extension disabled (#3209). Example: in++            \[link text\]\[@a\]++        `link text` isn't hyperlinked because `[@a]` is parsed as+        a citation. Previously this happened whether or not the `citations`+        extension was enabled. Now it happens only if the `citations`+        extension is enabled.+    +   Allow alignments to be specified in Markdown grid tables. For+        example,++            +-------+---------------+--------------------++            | Right    | Left                 | Centered |+            +=========:+:=================+:=============:++            | Bananas | $1.34         | built-in wrapper |+            +-------+---------------+--------------------+++    +   Allow Small Caps elements to be created using bracketed spans (as+        they already can be using HTML-syntax spans) (#3191, Kolen Cheung).++  * LaTeX reader:++    + Don't treat `\vspace` and `\hspace` as block commands (#3256).+      Fixed an error which came up, for example, with `\vspace` inside+      a caption. (Captions expect inlines.)+    + Improved table handling. We can now parse all of the tables emitted+      by pandoc in our tests. The only thing we don't get yet are+      alignments and column widths in more complex tables. See #2669.+    + Limited support for minipage.+    + Allow for `[]`s inside LaTeX optional args. Fixes cases like:+    + Handle BVerbatim from fancyvrb (#3203).+    + Handle hungarumlaut (#3201).+    + Allow beamer-style `<...>` options in raw LaTeX (also in Markdown)+      (#3184). This allows use of things like `\only<2,3>{my content}` in+      Markdown that is going to be converted to beamer.++  * Use pre-wrap for code in dzslides template (Nicolas Porcel). Otherwise+    overly long code will appear on every slide.++  * Org reader (Albert Krewinkel):++    +   Respect column width settings (#3246). Table column properties can+        optionally specify a column's width with which it is displayed in+        the buffer. Some exporters, notably the ODT exporter in org-mode+        v9.0, use these values to calculate relative column widths. The org+        reader now implements the same behavior. Note that the org-mode+        LaTeX and HTML exporters in Emacs don't support this feature yet,+        which should be kept in mind by users who use the column+        widths parameters.+    +   Allow HTML attribs on non-figure images (#3222). Images which are+        the only element in a paragraph can still be given HTML attributes,+        even if the image does not have a caption and is hence not a figure.+        The following will add set the `width` attribute of the image to+        `50%`:++            +ATTR\_HTML: :width 50%+            =======================++            \[\[file:image.jpg\]\]++    +   Support `ATTR_HTML` for special blocks (#3182). Special+        blocks (i.e. blocks with unrecognized names) can be prefixed with an+        `ATTR_HTML` block attribute. The attributes defined in that+        meta-directive are added to the `Div` which is used to represent the+        special block.+    +   Support the `todo` export option. The `todo` export option allows to+        toggle the inclusion of TODO keywords in the output. Setting this to+        `nil` causes TODO keywords to be dropped from headlines. The default+        is to include the keywords.+    +   Add support for todo-markers. Headlines can have optional+        todo-markers which can be controlled via the `#+TODO`, `#+SEQ_TODO`,+        or `#+TYP_TODO` meta directive. Multiple such directives can be+        given, each adding a new set of recognized todo-markers. If no+        custom todo-markers are defined, the default `TODO` and `DONE`+        markers are used. Todo-markers are conceptually separate from+        headline text and are hence excluded when autogenerating+        headline IDs. The markers are rendered as spans and labelled with+        two classes: One class is the markers name, the other signals the+        todo-state of the marker (either `todo` or `done`).++  * LaTeX writer:++    + Use `\autocites*` when "suppress-author" citation used.+    + Ensure that simple tables have simple cells (#2666). If cells+      contain more than a single Plain or Para, then we need to set+      nonzero widths and put contents into minipages.+    + Remove invalid inlines in sections (#3218, Hubert Plociniczak).++  * Markdown writer:++    + Fix calculation of column widths for aligned multiline tables+      (#1911, Björn Peemöller). This also fixes excessive CPU and memory+      usage for tables when `--columns` is set in such a way that cells+      must be very tiny. Now cells are guaranteed to be big enough so that+      single words don't need to line break, even if this pushes the line+      length above the column width.+    + Use bracketed form for native spans when `bracketed_spans`+      enabled (#3229).+    + Fixed inconsistent spacing issue (#3232). Previously a tight bullet+      sublist got rendered with a blank line after, while a tight ordered+      sublist did not. Now we don't get the blank line in either case.+    + Fix escaping of spaces in super/subscript (#3225). Previously two+      backslashes were inserted, which gave a literal backslash.+    + Adjust widths in Markdown grid tables so that they match+      on round-trip.++  * Docx writer:++    + Give full detail when there are errors converting tex math.+    + Handle title text in images (Jesse Rosenthal). We already handled+      alt text. This just puts the image "title" into the docx+      "title" attr.+    + Fixed XML markup for empty cells (#3238). Previously the Compact+      style wasn't being applied properly to empty cells.++  * HTML writer:++    + Updated `renderHtml` import from blaze-html.++  * Text.Pandoc.Pretty:++    + Fixed some bugs that caused blank lines in tables (#3251). The bugs+      caused spurious blank lines in grid tables when we had things like+      `blankline $$ blankline`.+    + Add exported function `minOffet` \[API change\] (Björn Peemöller).+    + Added error message for illegal call to `block` (Björn Peemöller).++  * Text.Pandoc.Shared:++    + Put `warn` in MonadIO.+    + `fetchItem`: Better handling of protocol-relative URL (#2635). If+      URL starts with `//` and there is no "base URL" (as there would be+      if a URL were used on the command line), then default to http:.++  * Export Text.Pandoc.getDefaultExtensions \[API change\] (#3178).++  * In --version, trap error in `getAppUserDataDirectory` (#3241). This+    fixes a crash with `pandoc --version` on unusual systems with no real+    user (e.g. SQL Server 2016).++  * Added weigh-pandoc for memory usage diagnostics (#3169).++  * Use correct mime types for woff and woff2 (#3228).++  * Remove make\_travis\_yml.hs (#3235, Kolen Cheung).++  * changelog: Moved an item that was misplaced in the 1.17.2 section to the+    1.18 section where it belongs.++  * CONTRIBUTING.md: minor change in wording and punctuation (#3252,+    Kolen Cheung).++  * Further revisions to manual for `--version` changes (#3244).+++pandoc (1.18)++  * Added `--list-input-formats`, `--list-output-formats`,+    `--list-extensions`, `--list-highlight-languages`, and+    `--list-highlight-styles` (#3173).  Removed list of highlighting+    languages from `--version` output.  Removed list of input and output+    formats from default `--help` output.++  * Added `--reference-location=block|section|document` option+    (Jesse Rosenthal).  This determines whether Markdown link references+    and footnotes are placed at the end of the document, the end of the+    section, or the end of the top-level block.++  * Added `--top-level-division=section|chapter|part` (Albert Krewinkel).+    This determines what a level-1 header corresponds to in LaTeX,+    ConTeXt, DocBook, and TEI output.  The default is `section`.+    The `--chapters` option has been deprecated in favor of+    `--top-level-division=chapter`.++  * Added `LineBlock` constructor for `Block` (Albert Krewinkel).  This+    is now used in parsing RST and Markdown line blocks, DocBook+    `linegroup`/`line` combinations, and Org-mode `VERSE` blocks.+    Previously `Para` blocks with hard linebreaks were used.  `LineBlock`s+    are handled specially in the following ouput formats: AsciiDoc+    (as `[verse]` blocks), ConTeXt (`\startlines`/`\endlines`),+    HTML (`div` with a style), Markdown (line blocks if `line_blocks`+    is enabled), Org-mode (`VERSE` blocks), RST (line blocks). In+    other output formats, a paragraph with hard linebreaks is emitted.++  * Allow binary formats to be written to stdout (but not to tty) (#2677).+    Only works on posix, since we use the unix library to check whether+    output is to tty.  On Windows, pandoc works as before and always requires+    an output file parameter for binary formats.++  * Changed JSON output format (Jesse Rosenthal).  Previously we used+    generically generated JSON, but this was subject to change depending+    on the version of aeson pandoc was compiled with.  To ensure stability,+    we switched to using manually written ToJSON and FromJSON+    instances, and encoding the API version.  **Note:**  pandoc filter+    libraries will need to be revised to handle the format change.+    Here is a summary of the essential changes:++    + The toplevel JSON format is now `{"pandoc-api-version" :+      [MAJ, MIN, REV], "meta" : META, "blocks": BLOCKS}`+      instead of `[{"unMeta": META}, [BLOCKS]]`.+      Decoding fails if the major and minor version numbers don't+      match.+    + Leaf nodes no longer have an empty array for their "c" value.+      Thus, for example, a `Space` is encoded as `{"t":"Space"}`+      rather than `{"t":"Space","c":[]}` as before.++  * Removed `tests/Tests/Arbitrary.hs` and added a `Text.Pandoc.Arbitrary`+    module to pandoc-types (Jesse Rosenthal).  This makes it easier+    to use QuickCheck with pandoc types outside of pandoc itself.++  * Add `bracketed_spans` Markdown extension, enabled by default+    in pandoc `markdown`.  This allows you to create a native span+    using this syntax:  `[Here is my span]{#id .class key="val"}`.++  * Added `angle_brackets_escapable` Markdown extension (#2846).+    This is needed because github flavored Markdown has a slightly+    different set of escapable symbols than original Markdown;+    it includes angle brackets.++  * Export `Text.Pandoc.Error` in `Text.Pandoc` [API change].++  * Print highlighting-kate version in `--version`.++  * `Text.Pandoc.Options`:++    + `Extension` has new constructors `Ext_brackted_spans` and+      `Ext_angle_brackets_escapable` [API change].+    + Added `ReferenceLocation` type [API change] (Jesse Rosenthal).+    + Added `writerReferenceLocation` field to `WriterOptions` (Jesse+      Rosenthal).++  * `--filter`:  we now check `$DATADIR/filters` for filters before+    looking in the path (#3127, Jesse Rosenthal, thanks to Jakob+    Voß for the idea).  Filters placed in this directory need not+    be executable; if the extension is `.hs`, `.php`, `.pl`, `.js`,+    or `.rb`, pandoc will run the right interpreter.++  * For `--webtex`, replace deprecated Google Chart API by CodeCogs as+    default (Kolen Cheung).++  * Removed `raw_tex` extension from `markdown_mmd` defaults (Kolen Cheung).++  * Execute .js filters with node (Jakob Voß).++  * Textile reader:++    + Support `bc..` extended code blocks (#3037).  Also, remove trailing+      newline in code blocks (consistently with Markdown reader).+    + Improve table parsing.  We now handle cell and row attributes, mostly+      by skipping them.  However, alignments are now handled properly.+      Since in pandoc alignment is per-column, not per-cell, we+      try to devine column alignments from cell alignments.+      Table captions are also now parsed, and textile indicators+      for thead and tfoot no longer cause parse failure.  (However,+      a row designated as tfoot will just be a regular row in pandoc.)+    + Improve definition list parsing.  We now allow multiple terms+      (which we concatenate with linebreaks).  An exponential parsing+      bug (#3020) is also fixed.+    + Disallow empty URL in explicit link (#3036).++  * RST reader:++    + Use Div instead of BlockQuote for admonitions (#3031).+      The Div has class `admonition` and (if relevant) one of the+      following:  `attention`, `caution`, `danger`, `error`, `hint`,+      `important`, `note`, `tip`, `warning`.  **Note:** This will change+      the rendering of some RST documents!  The word ("Warning", "Attention",+      etc.) is no longer added; that must be done with CSS or a filter.+    + A Div is now used for `sidebar` as well.+    + Skip whitespace before note (Jesse Rosenthal, #3163).  RST requires a+      space before a footnote marker. We discard those spaces so that footnotes+      will be adjacent to the text that comes before it. This is in line with+      what rst2latex does.+    + Allow empty lines when parsing line blocks (Albert Krewinkel).++  * Markdown reader:++    + Allow empty lines when parsing line blocks (Albert Krewinkel).+    + Allow attributes on autolinks (#3183, Daniele D'Orazio).++  * LaTeX reader:++    + More robust parsing of unknown environments (#3026).+      We no longer fail on things like `^` inside options for tikz.+    + Be more forgiving of non-standard characters, e.g. `^` outside of math.+      Some custom environments give these a meaning, so we should try not to+      fall over when we encounter them.+    + Drop duplicate `*` in bibtexKeyChars (Albert Krewinkel)++  * MediaWiki reader:++    + Fix for unquoted attribute values in mediawiki tables (#3053).+      Previously an unquoted attribute value in a table row+      could cause parsing problems.+    + Improved treatment of verbatim constructions (#3055).+      Previously these yielded strings of alternating Code and Space+      elements; we now incorporate the spaces into the Code.  Emphasis+      etc. is still possible inside these.+    + Properly interpret XML tags in pre environments (#3042).  They are meant+      to be interpreted as literal text.++  * EPUB reader:  don't add root path to data: URIs (#3150).+    Thanks to @lep for the bug report and patch.++  * Org reader (Albert Krewinkel):++    + Preserve indentation of verse lines (#3064).  Leading spaces in verse+      lines are converted to non-breaking spaces, so indentation is preserved.+    + Ensure image sources are proper links.  Image sources as those in plain+      images, image links, or figures, must be proper URIs or relative file+      paths to be recognized as images.  This restriction is now enforced+      for all image sources.  This also fixes the reader's usage of uncleaned+      image sources, leading to `file:` prefixes not being deleted from+      figure images.  Thanks to @bsag for noticing this bug.+    + Trim verse lines properly (Albert Krewinkel).+    + Extract meta parsing code to module.  Parsing of meta-data is well+      separable from other block parsing tasks.  Moving into new module to+      get small files and clearly arranged code.+    + Read markup only for special meta keys.  Most meta-keys should be read+      as normal string values, only a few are interpreted as marked-up text.+    + Allow multiple, comma-separated authors.  Multiple authors can be+      specified in the `#+AUTHOR` meta line if they are given as a+      comma-separated list.+    + Give precedence to later meta lines.  The last meta-line of any given+      type is the significant line.  Previously the value of the first line+      was kept, even if more lines of the same type were encounterd.+    + Read LaTeX_header as header-includes.  LaTeX-specific header commands+      can be defined in `#+LaTeX_header` lines.  They are parsed as+      format-specific inlines to ensure that they will only show up in LaTeX+      output.+    + Set documentclass meta from LaTeX_class.+    + Set classoption meta from LaTeX_class_options.+    + Read HTML_head as header-includes.  HTML-specific head content can be+      defined in `#+HTML_head` lines.  They are parsed as format-specific+      inlines to ensure that they will only show up in HTML output.+    + Respect `author` export option.  The `author` option controls whether+      the author should be included in the final markup.  Setting+      `#+OPTIONS: author:nil` will drop the author from the final meta-data+      output.+    + Respect `email` export option.  The `email` option controls whether the+      email meta-field should be included in the final markup. Setting+      `#+OPTIONS: email:nil` will drop the email field from the final+      meta-data output.+    + Respect `creator` export option.  The `creator` option controls whether+      the creator meta-field should be included in the final markup.  Setting+      `#+OPTIONS: creator:nil` will drop the creator field from the final+      meta-data output.  Org-mode recognizes the special value `comment` for+      this field, causing the creator to be included in a comment.  This is+      difficult to translate to Pandoc internals and is hence interpreted the+      same as other truish values (i.e. the meta field is kept if it's+      present).+    + Respect unnumbered header property (#3095).  Sections the `unnumbered`+      property should, as the name implies, be excluded from the automatic+      numbering of section provided by some output formats.  The Pandoc+      convention for this is to add an "unnumbered" class to the header.  The+      reader treats properties as key-value pairs per default, so a special+      case is added to translate the above property to a class instead.+    + Allow figure with empty caption (Albert Krewinkel, #3161).+      A `#+CAPTION` attribute before an image is enough to turn an image into+      a figure. This wasn't the case because the `parseFromString` function,+      which processes the caption value, would fail on empty values. Adding+      a newline character to the caption value fixes this.++  * Docx reader:++    + Use XML convenience functions (Jesse Rosenthal).+      The functions `isElem` and `elemName` (defined in Docx/Util.hs) make+      the code a lot cleaner than the original XML.Light functions, but they+      had been used inconsistently. This puts them in wherever applicable.+    + Handle anchor spans with content in headers.  Previously, we would only+      be able to figure out internal links to a header in a docx if the+      anchor span was empty. We change that to read the inlines out of the+      first anchor span in a header.+    + Let headers use exisiting id.  Previously we always generated an id for+      headers (since they wouldn't bring one from Docx). Now we let it use an+      existing one if possible. This should allow us to recurs through anchor+      spans.+    + Use all anchor spans for header ids.  Previously we only used the first+      anchor span to affect header ids. This allows us to use all the anchor+      spans in a header, whether they're nested or not (#3088).+    + Test for nested anchor spans in header.  This ensures that anchor spans+      in header with content (or with other anchor spans inside) will resolve+      to links to a header id properly.++  * ODT reader (Hubert Plociniczak)++    + Include list's starting value.  Previously the starting value of+      the lists' items has been hardcoded to 1. In reality ODT's list+      style definition can provide a new starting value in one of its+      attributes.+    + Infer caption from the text following the image.+      Frame can contain other frames with the text boxes.+    + Add `fig:` to title for Image with a caption (as expected+      by pandoc's writers).+    + Basic support for images in ODT documents.+    + Don't duplicate text for anchors (#3143).  When creating an anchor+      element we were adding its representation as well as the original+      content, leading to text duplication.++  * DocBook writer:++    + Include an anchor element when a div or span has an id (#3102).+      Note that DocBook does not have a class attribute, but at least this+      provides an anchor for internal links.++  * LaTeX writer:++    + Don't use * for unnumbered paragraph, subparagraph.  The starred+      variants don't exist.  This helps with part of #3058...it gets rid of+      the spurious `*`s.  But we still have numbers on the 4th and 5th level+      headers.+    + Properly escape backticks in verbatim (#3121, Jesse Rosenthal).+      Otherwise they can cause unintended ligatures like `` ?` ``.+    + Handle NARRAOW NO-BREAK SPACE into LaTeX (Vaclav Zeman) as `\,`.+    + Don't include `[htbp]` placement for figures (#3103, Václav Haisman).+      This allows figure placement defaults to be changed by the user+      in the template.++  * HTML writer (slide show formats): In slide shows, don't change slide title+    to level 1 header (#2221).++  * TEI writer: remove heuristic to detect book template (Albert Krewinkel).+    TEI doesn't have `<book>` elements but only generic `<divN>` division+    elements. Checking the template for a trailing `</book>` is nonsensical.++  * MediaWiki writer:  transform filename with underscores in images (#3052).+    `foo bar.jpg` becomes `foo_bar.jpg`. This was already done+    for internal links, but it also needs to happen for images.++  * ICML writer: replace partial function (!!) in table handling (#3175,+    Mauro Bieg).++  * Man writer: allow section numbers that are not a single digit (#3089).++  * AsciiDoc writer: avoid unnecessary use of "unconstrained" emphasis+    (#3068).  In AsciiDoc, you must use a special form of emphasis+    (double `__`) for intraword emphasis.  Pandoc was previously using+    this more than necessary.++  * EPUB writer:  use stringify instead of plain writer for metadata+    (#3066).  This means that underscores won't be used for emphasis,+    or CAPS for bold.  The metadata fields will just have unadorned+    text.++  * Docx Writer:++    + Implement user-defined styles (Jesse Rosenthal).  Divs and Spans+      with a `custom-style` key in the attributes will apply the corresponding+      key to the contained blocks or inlines.+    + Add ReaderT env to the docx writer (Jesse Rosenthal).+    + Clean up and streamline RTL behavior (Jesse Rosenthal, #3140).+      You can set `dir: rtl` in YAML metadata, or use `-M dir=rtl`+      on the command line.  For finer-grained control, you can set+      the `dir` attribute in Div or Span elements.++  * Org writer (Albert Krewinkel):++    + Remove blank line after figure caption.  Org-mode only treats an image+      as a figure if it is directly preceded by a caption.+    + Ensure blank line after figure.  An Org-mode figure should be surrounded+      by blank lines.  The figure would be recognized regardless, but images+      in the following line would unintentionally be treated as figures as+      well.+    + Ensure link targets are paths or URLs.  Org-mode treats links as+      document internal searches unless the link target looks like a URL or+      file path, either relative or absolute.  This change ensures that this+      is always the case.+    + Translate language identifiers.  Pandoc and Org-mode use different+      programming language identifiers.  An additional translation between+      those identifiers is added to avoid unexpected behavior.  This fixes a+      problem where language specific source code would sometimes be output+      as example code.+    + Drop space before footnote markers (Albert Krewinkel, #3162).+      The writer no longer adds an extra space before footnote markers.++  * Markdown writer:++    + Don't emit HTML for tables unless `raw_html` extension is set (#3154).+      Emit `[TABLE]` if no suitable table formats are enabled and raw HTML+      is disabled.+    + Check for the `raw_html` extension before emiting a raw HTML block.+    + Abstract out note/ref function (Jesse Rosenthal).+    + Add ReaderT monad for environment variables (Jesse Rosenthal).++  * HTML, EPUB, slidy, revealjs templates: Use `<p>` instead of `<h1>` for+    subtitle, author, date (#3119).  Note that, as a result of this change,+    authors may need to update CSS.++  * revealjs template:  Added `notes-server` option+    (jgm/pandoc-templates#212, Yoan Blanc).++  * Beamer template:++    + Restore whitespace between paragraphs. This was+      a regression in the last release (jgm/pandoc-templates#207).+    + Added `themeoptions` variable (Carsten Gips).+    + Added `beamerarticle` variable.  This causes the `beamerarticle`+      package to be loaded in beamer, to produce an article from beamer+      slides.  (Carsten Gips)+    + Added support for `fontfamilies` structured variable+      (Artem Klevtsov).+    + Added hypersetup options (Jake Zimmerman).++  * LaTeX template:++    + Added dummy definition for `\institute`.+      This isn't a standard command, and we want to avoid a crash when+      `institute` is used with the default template.+    + Define default figure placement (Václav Haisman), since pandoc+      no longer includes `[htbp]` for figures.  Users with custom templates+      will want to add this. See #3103.+    + Use footnote package to fix notes in tables (jgm/pandoc-templates#208,+      Václav Haisman).++  * Moved template compiling/rendering code to a separate library.+    `doctemplates`.  This allows the pandoc templating system to be+    used independently.++  * Text.Pandoc.Error: Fix out of index error in `handleError`+    (Matthew Pickering).  The fix is to not try to show the exact line when+    it would cause an out-of-bounds error as a result of included files.++  * Text.Pandoc.Shared: Add `linesToBlock` function (Albert Krewinkel).++  * Text.Pandoc.Parsing.emailAddress: tighten up parsing of email+    addresses.  Technically `**@user` is a valid email address, but if we+    allow things like this, we get bad results in markdown flavors+    that autolink raw email addresses (see #2940).  So we exclude a few+    valid email addresses in order to avoid these more common bad cases.++  * Text.Pandoc.PDF:  Don't crash with nonexistent image (#3100).  Instead,+    emit the alt text, emphasized.  This accords with what the ODT writer+    currently does.  The user will still get a warning about a nonexistent+    image.++  * Fix example in API documentation (#3176, Thomas Weißschuh).++  * Tell where to get tarball in INSTALL (#3062).++  * Rename README to MANUAL.txt and add GitHub-friendly README.md+    (Albert Krewinkel, Kolen Cheung).++  * Replace COPYING with Markdown version COPYING.md from GNU (Kolen Cheung).++  * MANUAL.txt:++    + Put note on structured vars in separate paragraph (#2148, Albert+      Krewinkel).  Make it clearer that structured author variables require a+      custom template+    + Note that `--katex` works best with `html5` (#3077).+    + Fix the LaTeX and EPUB links in manual (Morton Fox).+    + Document `biblio-title` variable.++  * Improve spacing of footnotes in `--help` output (Waldir Pimenta).++  * Update KaTeX to v0.6.0 (Kolen Cheung).++  * Allow latest dependencies.++  * Use texmath 0.8.6.6 (#3040).++  * Allow http-client 0.4.30, which is the version in stackage lts.+    Previously we required 0.5.+    Remove CPP conditionals for earlier versions.++  * Remove support for GHC < 7.8 (Jesse Rosenthal).++    + Remove Compat.Monoid.+    + Remove an inline monad compatibility macro.+    + Remove Text.Pandoc.Compat.Except.+    + Remove directory compat.+    + Change constraint on mtl.+    + Remove unnecessary CPP condition in UTF8.+    + Bump base lower bound to 4.7.+    + Remove 7.6 build from .travis.yaml.+    + Bump supported ghc version in CONTRIBUTING.md.+    + Add note about GHC version support to INSTALL.+    + Remove GHC 7.6 from list of tested versions (Albert Krewinkel).+    + Remove TagSoup compat.+    + Add EOL note to time compat module.  Because time 1.4 is a boot library+      for GHC 7.8, we will support the compatibility module as long as we+      support 7.8. But we should be clear about when we will no longer need+      it.+    + Remove blaze-html CPP conditional.+    + Remove unnecessary CPP in custom Prelude.++pandoc (1.17.2)++  * Added Zim Wiki writer, template and tests. `zimwiki` is now+    a valid output format. (Alex Ivkin)++  * Changed email-obfuscation default to no obfuscation (#2988).+    + `writerEmailObfuscation` in `defaultWriterOptions` is now+      `NoObfuscation`.+    + the default for the command-line `--email-obfuscation` option is+      now `none`.++  * Docbook writer: Declare xlink namespace in Docbook5 output (Ivo Clarysse).++  * Org writer:++    + Support arbitrary raw inlines (Albert Krewinkel).+      Org mode allows arbitrary raw inlines ("export snippets" in Emacs+      parlance) to be included as `@@format:raw foreign format text@@`.+    + Improve Div handling (Albert Krewinkel).  Div blocks handling is+      changed to make the output look more like idiomatic org mode:+        - Div-wrapped content is output as-is if the div's attribute is the+          null attribute.+        - Div containers with an id but neither classes nor key-value pairs+          are unwrapped and the id is added as an anchor.+        - Divs with classes associated with greater block elements are+          wrapped in a `#+BEGIN`...`#+END` block.+        - The old behavior for Divs with more complex attributes is kept.++  * HTML writer:++    + Better support for raw LaTeX environments (#2758).+      Previously we just passed all raw TeX through when MathJax was used for+      HTML math.  This passed through too much.  With this patch, only raw+      LaTeX environments that MathJax can handle get passed through.+      This patch also causes raw LaTeX environments to be treated+      as math, when possible, with MathML and WebTeX output.++  * Markdown writer:  use raw HTML for simple, pipe tables with linebreaks+    (#2993).  Markdown line breaks involve a newline, and simple and pipe+    tables can't contain one.++  * Make --webtex work with the Markdown writer (#1177).+    This is a convenient option for people using+    websites whose Markdown flavors don't provide for math.++  * Docx writer:++    + Set paragraph to FirstPara after display math (Jesse Rosenthal).+      We treat display math like block quotes, and apply FirstParagraph style+      to paragraphs that follow them. These can be styled as the user+      wishes. (But, when the user is using indentation, this allows for+      paragraphs to continue after display math without indentation.)+    + Use actual creation time as doc prop (Jesse Rosenthal).+      Previously, we had used the user-supplied date, if available, for Word's+      document creation metadata. This could lead to weird results, as in+      cases where the user post-dates a document (so the modification might be+      prior to the creation). Here we use the actual computer time to set the+      document creation.++  * LaTeX writer:++    + Don't URI-escape image source (#2825).  Usually this is a local file,+      and replacing spaces with `%20` ruins things.+    + Allow 'standout' as a beamer frame option (#3007).+      `## Slide title {.standout}`.++  * RST reader: Fixed links with no explicit link text.  The link+    `` `<foo>`_ `` should have `foo` as both its link text and its URL.+    See RST spec at <http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html#embedded-uris-and-aliases>+    Closes Debian #828167 -- reported by Christian Heller.++  * Textile reader:++    + Fixed attributes (#2984).  Attributes can't be followed by+      a space.  So, `_(class)emph_` but `_(noclass) emph_`.+    + Fixed exponential parsing bug (#3020).+    + Fix overly aggressive interpretation as images (#2998).+      Spaces are not allowed in the image URL in textile.++  * LaTeX reader:++    + Fix `\cite` so it is a NormalCitation not AuthorInText.+    + Strip off double quotes around image source if present (#2825).+      Avoids interpreting these as part of the literal filename.++  * Org reader:++    + Add semicolon to list of special chars (Albert Krewinkel)+      Semicolons are used as special characters in citations syntax.  This+      ensures the correct parsing of Pandoc-style citations: `[prefix; @key;+      suffix]`.  Previously, parsing would have failed unless there was a space+      or other special character as the last <prefix> character.+    + Add support for "Berkeley-style" cites (Albert Krewinkel, #1978).+      A specification for an official Org-mode citation syntax was drafted by+      Richard Lawrence and enhanced with the help of others on the orgmode+      mailing list.  Basic support for this citation style is added to the+      reader.+    + Support arbitrary raw inlines (Albert Krewinkel).+      Org mode allows arbitrary raw inlines ("export snippets" in Emacs+      parlance) to be included as `@@format:raw foreign format text@@`.+    + Remove partial functions (Albert Krewinkel, #2991).+      Partial functions like `head` lead to avoidable errors and should be+      avoided.  They are replaced with total functions.+    + Support figure labels (Albert Krewinkel, #2496, #2999).+      Figure labels given as `#+LABEL: thelabel` are used as the ID of the+      respective image.  This allows e.g. the LaTeX to add proper `\label`+      markup.+    + Improve tag and properties type safety (Albert Krewinkel).+      Specific newtype definitions are used to replace stringly typing of tags+      and properties.  Type safety is increased while readability is improved.+    + Parse as headlines, convert to blocks (Albert Krewinkel).+      Emacs org-mode is based on outline-mode, which treats documents as trees+      with headlines are nodes.  The reader is refactored to parse into a+      similar tree structure.  This simplifies transformations acting on+      document (sub-)trees.+    * Refactor comment tree handling (Albert Krewinkel).+      Comment trees were handled after parsing, as pattern matching on lists+      is easier than matching on sequences.  The new method of reading+      documents as trees allows for more elegant subtree removal.+    * Support archived trees export options (Albert Krewinkel).+      Handling of archived trees can be modified using the `arch` option.+      Archived trees are either dropped, exported completely, or collapsed to+      include just the header when the `arch` option is nil, non-nil, or+      `headline`, respectively.+    * Put export setting parser into module (Albert Krewinkel).+      Export option parsing is distinct enough from general block parsing to+      justify putting it into a separate module.+    * Support headline levels export setting (Albert Krewinkel).+      The depths of headlines can be modified using the `H` option.  Deeper+      headlines will be converted to lists.+    * Replace ugly code with view pattern (Albert Krewinkel).+      Some less-than-smart code required a pragma switching of overlapping+      pattern warnings in order to compile seamlessly.  Using view patterns+      makes the code easier to read and also doesn't require overlapping+      pattern checks to be disabled.+    * Fix parsing of verbatim inlines (Albert Krewinkel, #3016).+      Org rules for allowed characters before or after markup chars were not+      checked for verbatim text.  This resultet in wrong parsing outcomes of+      if the verbatim text contained e.g. space enclosed markup characters as+      part of the text (`=is_substr = True=`).  Forcing the parser to update+      the positions of allowed/forbidden markup border characters fixes this.++  * LaTeX template: fix for obscure hyperref/xelatex issue.+    Here's a minimal case:++        \documentclass[]{article}+        \usepackage{hyperref}+        \begin{document}+        \section{\%á}+        \end{document}++    Without this change, this fails on the second invocation of xelatex.+    This affects inputs this like `# %á` with pdf output via xelatex.++  * trypandoc:  call results 'html' instead of 'result'.+    This is for better compatibility with babelmark2.++  * Document MultiMarkdown as input/output format (Albert Krewinkel, #2973).+    MultiMarkdown was only mentioned as a supported Markdown dialect but not+    as a possible input or output format.  A brief mention is added+    everywhere the other supported markdown dialects are mentioned.++  * Document Org mode as a format containing raw HTML (Albert Krewinkel)+    Raw HTML is kept when the output format is Emacs Org mode.++  * Implement `RawInline` and `RawBlock` in sample lua custom writer (#2985).++  * Text.Pandoc.Shared:++    + Introduce blocksToInlines function (Jesse Rosenthal).+      This is a lossy function for converting `[Block] -> [Inline]`. Its main+      use, at the moment, is for docx comments, which can contain arbitrary+      blocks (except for footnotes), but which will be converted to spans.+      This is, at the moment, pretty useless for everything but the basic+      `Para` and `Plain` comments. It can be improved, but the docx reader+      should probably emit a warning if the comment contains more than this.+    + Add BlockQuote to blocksToInlines (Jesse Rosenthal).+    + Add further formats for `normalizeDate` (Jesse Rosenthal).+      We want to avoid illegal dates -- in particular years with greater than+      four digits. We attempt to parse series of digits first as `%Y%m%d`, then+      `%Y%m`, and finally `%Y`.+    + `normalizeDate` should reject illegal years (Jesse Rosenthal).+      We only allow years between 1601 and 9999, inclusive. The ISO 8601+      actually says that years are supposed to start with 1583, but MS Word+      only allows 1601-9999. This should stop corrupted word files if the date+      is out of that range, or is parsed incorrectly.+    + Improve year sanity check in normalizeDate (Jesse Rosenthal).+      Previously we parsed a list of dates, took the first one, and then+      tested its year range. That meant that if the first one failed, we+      returned nothing, regardless of what the others did. Now we test for+      sanity before running `msum` over the list of Maybe values. Anything+      failing the test will be Nothing, so will not be a candidate.++  * Docx reader:++    + Add simple comment functionality. (Jesse Rosenthal).+      This adds simple track-changes comment parsing to the docx reader. It is+      turned on with `--track-changes=all`. All comments are converted to+      inlines, which can list some information. In the future a warning will be+      added for comments with formatting that seems like it will be excessively+      denatured.  Note that comments can extend across blocks. For that reason+      there are two spans: `comment-start` and `comment-end`.  `comment-start`+      will contain the comment. `comment-end` will always be empty.  The two+      will be associated by a numeric id.+    + Enable warnings in top-level reader (Jesse Rosenthal).+      Previously we had only allowed for warnings in the parser. Now we allow+      for them in the `Docx.hs` as well. The warnings are simply concatenated.+    + Add warning for advanced comment formatting. (Jesse Rosenthal).+      We can't guarantee we'll convert every comment correctly, though we'll+      do the best we can. This warns if the comment includes something other+      than Para or Plain.+    + Add tests for warnings. (Jesse Rosenthal).+    + Add tests for comments (Jesse Rosenthal).+      We test for comments, using all track-changes options. Note that we+      should only output comments if `--track-changes=all`. We also test for+      emitting warnings if there is complicated formatting.++  * README: update to include track-changes comments. (Jesse Rosenthal)++  * Improved Windows installer - don't ignore properties set on command-line.+    See #2708.  Needs testing to see if this resolves the issue.+    Thanks to @nkalvi.++  * Process markdown extensions on command line in L->R order (#2995).+    Previously they were processed, very unintuitively, in R->L+    order, so that `markdown-tex_math_dollars+tex_math_dollars`+    had `tex_math_dollars` disabled.++  * Added `secnumdepth` variable to LaTeX template (#2920).++  * Include table of contents in README.html in Windows package.++  * Writers: treat SoftBreak as space for stripping (Jesse Rosenthal)+    In Writers.Shared, we strip leading and trailing spaces for display+    math. Since SoftBreak's are treated as spaces, we should strip those+    too.++  * beamer, latex templates:  pass biblatexoptions directly in package load.+    This allows runtime optinos to be used.  Fixes jgm/pandoc-citeproc#201++  * CPP workaround for deprecation of `parseUrl` in http-client.++  * Removed some redundant class constraints.++  * make_oxs_package.sh - use OSX env variable.++  * Replaced INSTALL with INSTALL.md, incorporating INSTALL and the+    old installing page from website.++  * Added `winpkg` target to Makefile.  This downloads the windows package+    from appveyor and signs it using the key.++  * Document Org mode as a format containing raw TeX (Albert Krewinkel).+    Raw TeX is kept verbatim when the output format is Emacs Org mode.++  * Support math with haddock-library >= 1.4.++  * Removed `-rtsopts` from library stanza.  It has no effect, and Hackage+    wouldn't accept the package.++  * Update library dependency versions.++pandoc (1.17.1)++  * New output format: `docbook5` (Ivo Clarysse).++  * `Text.Pandoc.Options`: Add `writerDocBook5` to `WriterOptions`+    (API change).++  * Org writer:++    + Add :PROPERTIES: drawer support (Albert Krewinkel, #1962).+      This allows header attributes to be added to org documents in the form+      of `:PROPERTIES:` drawers.  All available attributes are stored as+      key/value pairs.  This reflects the way the org reader handles+      `:PROPERTIES:` blocks.+    + Add drawer capability (Carlos Sosa).  For the implementation of the+      Drawer element in the Org Writer, we make use of a generic Block+      container with attributes.  The presence of a `drawer` class defines+      that the `Div` constructor is a drawer. The first class defines the+      drawer name to use.  The key-value list in the attributes defines+      the keys to add inside the Drawer.  Lastly, the list of Block elements+      contains miscellaneous blocks elements to add inside of the Drawer.+    + Use `CUSTOM_ID` in properties (Albert Krewinkel).  The `ID` property is+      reserved for internal use by Org-mode and should not be used.+      The `CUSTOM_ID` property is to be used instead, it is converted to the+      `ID` property for certain export format.++  * LaTeX writer:++    + Ignore `--incremental` unless output format is beamer (#2843).+    + Fix polyglossia to babel env mapping (Mauro Bieg, #2728).+      Allow for optional argument in square brackets.+    + Recognize `la-x-classic` as Classical Latin (Andrew Dunning).+      This allows one to access the hyphenation patterns in CTAN's+      hyph-utf8.+    + Add missing languages from hyph-utf8 (Andrew Dunning).+    + Improve use of `\strut` with `\minipage` inside tables+      (Jose Luis Duran).  This improves spacing in multiline+      tables.+    + Use `{}` around options containing special chars (#2892).+    + Avoid lazy `foldl`.+    + Don't escape underscore in labels (#2921).  Previously they were+      escaped as `ux5f`.+    + brazilian -> brazil for polyglossia (#2953).++  * HTML writer: Ensure mathjax link is added when math appears in footnote+    (#2881).  Previously if a document only had math in a footnote, the+    MathJax link would not be added.++  * EPUB writer: set `navpage` variable on nav page.+    This allows templates to treat it differently.++  * DocBook writer:++    + Use docbook5 if `writerDocbook5` is set (Ivo Clarysse).+    + Properly handle `ulink`/`link` (Ivo Clarysse).++  * EPUB reader:++    + Unescape URIs in spine (#2924).+    + EPUB reader:  normalise link id (Mauro Bieg).++  * Docx Reader:++    + Parse `moveTo` and `moveFrom` (Jesse Rosenthal).+      `moveTo` and `moveFrom` are track-changes tags that are used when a+      block of text is moved in the document. We now recognize these tags and+      treat them the same as `insert` and `delete`, respectively. So,+      `--track-changes=accept` will show the moved version, while+      `--track-changes=reject` will show the original version.+    + Tests for track-changes moving (Jesse Rosenthal).++  * ODT, EPUB, Docx readers: throw `PandocError` on unzip failure+    (Jesse Rosenthal) Previously, `readDocx`, `readEPUB`, and `readOdt`+    would error out if zip-archive failed. We change the archive extraction+    step from `toArchive` to `toArchiveOrFail`, which returns an Either value.++  * Markdown, HTML readers:  be more forgiving about unescaped `&` in+    HTML (#2410).  We are now more forgiving about parsing invalid HTML with+    unescaped `&` as raw HTML.  (Previously any unescaped `&`+    would cause pandoc not to recognize the string as raw HTML.)++  * Markdown reader:++    + Added bracket syntax for native spans (#168).+    + Fix pandoc title blocks with lines ending in 2 spaces (#2799).+    + Added `-s` to markdown-reader-more test.++  * HTML reader: fixed bug in `pClose`.  This caused exponential parsing+    behavior in documnets with unclosed tags in `dl`, `dd`, `dt`.++  * MediaWiki reader: Allow spaces before `!` in MediaWiki table header+    (roblabla).++  * RST reader: Support `:class:` option for code block in RST reader+    (Sidharth Kapur).++  * Org reader (all Albert Krewinkel, except where noted otherwise):++    + Stop padding short table rows.+      Emacs Org-mode doesn't add any padding to table rows.  The first+      row (header or first body row) is used to determine the column count,+      no other magic is performed.+    + Refactor rows-to-table conversion.  This refactors+      the codes conversing a list table lines to an org table ADT.+      The old code was simplified and is now slightly less ugly.+    + Fix handling of empty table cells, rows (Albert Krewinkel, #2616).+      This fixes Org mode parsing of some corner cases regarding empty cells+      and rows.  Empty cells weren't parsed correctly, e.g. `|||` should be+      two empty cells, but would be parsed as a single cell containing a pipe+      character.  Empty rows where parsed as alignment rows and dropped from+      the output.+    + Fix spacing after LaTeX-style symbols.+      The org-reader was droping space after unescaped LaTeX-style symbol+      commands: `\ForAll \Auml` resulted in `∀Ä` but should give `∀ Ä`+      instead.  This seems to be because the LaTeX-reader treats the+      command-terminating space as part of the command.  Dropping the trailing+      space from the symbol-command fixes this issue.+    + Print empty table rows.  Empty table rows should not+      be dropped from the output, so row-height is always set to be at least 1.+    + Move parser state into separate module.+      The org reader code has become large and confusing.  Extracting smaller+      parts into submodules should help to clean things up.+    + Add support for sub/superscript export options.+      Org-mode allows to specify export settings via `#+OPTIONS` lines.+      Disabling simple sub- and superscripts is one of these export options,+      this options is now supported.+    + Support special strings export option Parsing of special strings+      (like `...` as ellipsis or `--` as en dash) can be toggled using the `-`+      option.+    + Support emphasized text export option.  Parsing of emphasized text can+      be toggled using the `*` option.  This influences parsing of text marked+      as emphasized, strong, strikeout, and underline.  Parsing of inline math,+      code, and verbatim text is not affected by this option.+    + Support smart quotes export option.  Reading of smart quotes can be+      toggled using the `'` option.+    + Parse but ignore export options. All known export options are parsed+      but ignored.+    + Refactor block attribute handling.  A parser state attribute was used+      to keep track of block attributes defined in meta-lines.  Global state+      is undesirable, so block attributes are no longer saved as part of the+      parser state.  Old functions and the respective part of the parser state+      are removed.+    + Use custom `anyLine`.  Additional state changes need to be made after+      a newline is parsed, otherwise markup may not be recognized correctly.+      This fixes a bug where markup after certain block-types would not be+      recognized.+    + Add support for `ATTR_HTML` attributes (#1906).+      Arbitrary key-value pairs can be added to some block types using a+      `#+ATTR_HTML` line before the block.  Emacs Org-mode only includes these+      when exporting to HTML, but since we cannot make this distinction here,+      the attributes are always added.  The functionality is now supported+      for figures.+    + Add `:PROPERTIES:` drawer support (#1877).+      Headers can have optional `:PROPERTIES:` drawers associated with them.+      These drawers contain key/value pairs like the header's `id`.  The+      reader adds all listed pairs to the header's attributes; `id` and+      `class` attributes are handled specially to match the way `Attr` are+      defined.  This also changes behavior of how drawers of unknown type+      are handled.  Instead of including all unknown drawers, those are not+      read/exported, thereby matching current Emacs behavior.+    + Use `CUSTOM_ID` in properties.  See above on Org writer changes.+    + Respect drawer export setting.  The `d` export option can be used+      to control which drawers are exported and which are discarded.+      Basic support for this option is added here.+    + Ignore leading space in org code blocks (Emanuel Evans, #2862).+      Also fix up tab handling for leading whitespace in code blocks.+    + Support new syntax for export blocks.  Org-mode version 9+      uses a new syntax for export blocks.  Instead of `#+BEGIN_<FORMAT>`,+      where `<FORMAT>` is the format of the block's content, the new+      format uses `#+BEGIN_export <FORMAT>` instead.  Both types are+      supported.+    + Refactor `BEGIN...END` block parsing.+    + Fix handling of whitespace in blocks, allowing content to be indented+      less then the block header.+    + Support org-ref style citations.  The *org-ref* package is an+      org-mode extension commonly used to manage citations in org+      documents.  Basic support for the `cite:citeKey` and+      `[[cite:citeKey][prefix text::suffix text]]` syntax is added.+    + Split code into separate modules, making for cleaner code and+      better decoupling.++  * Added `docbook5` template.++  * `--mathjax` improvements:++    + Use new CommonHTML output for MathJax (updated default MathJax URL,+      #2858).+    + Change default mathjax setup to use `TeX-AMS_CHTML` configuration.+      This is designed for cases where the input is always TeX and maximal+      conformity with TeX is desired.  It seems to be smaller and load faster+      than what we used before.  See #2858.+    + Load the full MathJax config to maximize loading speed (KolenCheung).++  * Bumped upper version bounds to allow use of latest packages+    and compilation with ghc 8.++  * Require texmath 0.8.6.2.  Closes several texmath-related bugs (#2775,+    #2310, #2310, #2824).  This fixes behavior of roots, e.g.+    `\sqrt[3]{x}`, and issues with sub/superscript positioning+    and matrix column alignment in docx.++  * README:++    + Clarified documentation of `implicit_header_references` (#2904).+    + Improved documentation of `--columns` option.++  * Added appveyor setup, with artefacts (Jan Schulz).++  * stack.yaml versions: Use proper flags used for texmath, pandoc-citeproc.++  * LaTeX template: support for custom font families (vladipus).+    Needed for correct polyglossia operation with Cyrillic fonts and perhaps+    can find some other usages.  Example usage in YAML metadata:++          fontfamilies:+          - name: \cyrillicfont+            font: Liberation Serif+          - name: \cyrillicfonttt+            options: Scale=MatchLowercase+            font: Liberation++  * Create unsigned msi as build artifact in appveyor build.++  * On travis, test with ghc 8.0.1; drop testing for ghc 7.4.1.++pandoc (1.17.0.3)++  * LaTeX writer: Fixed position of label in figures (#2813).+    Previously the label wasn't in the right place, and `\ref`+    wouldn't work properly.+  * Added .tei test files to pandoc.cabal so they'll be included+    in tarball (#2811).+  * Updated copyright dates.++pandoc (1.17.0.2)++  * Fixed serious regression in `htmlInBalanced`, which caused+    newlines to be omitted in some raw HTML blocks in Markdown+    (#2804).++pandoc (1.17.0.1)++  * File scope is no longer used when there are no input files (i.e.,+    when input comes from stdin).  Previously file scope was triggered+    when the `json` reader was specified and input came from `stdin`,+    and this caused no output to be produced.  (Fix due to Jesse Rosenthal;+    thanks to Fedor Sheremetyev for calling the bug to our attention.)+  * Improved documentation of templates (#2797).++pandoc (1.17)++  * Added `--file-scope` option (Jesse Rosenthal).+    By default pandoc operates on multiple files by first concatenating+    them (around extra line breaks) and then processing the joined file. So+    it only parses a multi-file document at the document scope. This has the+    benefit that footnotes and links can be in different files, but for+    some purposes it is useful to parse the individual files first+    and then combine their outputs (e.g. when the files use footnotes+    or links with the same labels).  The `--file-scope` option causes+    pandoc to parse the files first, and then combine the parsed output,+    instead of combining before parsing. `--file-scope` is selected+    automatically for binary input files (which cannot be concatenated)+    and for pandoc json.++  * Add TEI Writer (Chris Forster) and `tei` output format.++  * Added a general `ByteStringReader` with warnings, used by the docx+    reader (API change, Jesse Rosenthal).++  * Add `readDocxWithWarnings` (API change, Jesse Rosenthal).++  * Changed type of `Shared.uniqueIdent`'s argument from `[String]`+    to `Set String.` This avoids performance problems in documents with+    many identically named headers (API change, #2671).++  * Removed `tex_math_single_backslash` from `markdown_github` options+    (#2707).++  * Make language extensions as well as full language names+    trigger syntax highlighting.  For example, `py` will now work as+    well as `python` (jgm/highlighting-kate#83).++  * Added `institute` variable to latex, beamer templates (Fraser+    Tweedale, Josef Svenningsson).++  * Docx reader (Jesse Rosenthal):++    + Handle alternate content.  Some word functions (especially graphics)+      give various choices for content so there can be backwards compatibility.+    + Don't turn numbered headers into lists.+    + Docx Reader: Add state to the parser, for warnings+    + Update feature checklist in source code.+    + Get rid of `Modifiable` typeclass.+    + Add tests for adjacent hyperlinks.+    + Add a "Link" modifier to `Reducible`. We want to make sure that+      links have their spaces removed, and are appropriately smushed+      together (#2689).++  * HTML reader:++    + Fixed behavior of base tag (#2777).+      If the base path does not end with slash, the last component+      will be replaced.  E.g. base = `http://example.com/foo`+      combines with `bar.html` to give `http://example.com/bar.html`.+      If the href begins with a slash, the whole path of the base+      is replaced.  E.g. base = `http://example.com/foo/` combines+      with `/bar.html` to give `http://example.com/bar.html`.+    + Rewrote `htmlInBalanced`.  This version avoids an exponential+      performance problem with `<script>` tags, and it should be faster+      in general (#2730).+    + Properly handle an empty cell in a simple table (#2718).+    + Handle multiple `<meta>` tags with same name.  Put them in a list+      in the metadata so they are all preserved, rather than (as before)+      throwing out all but one..++  * Markdown reader:++    + Improved pipe table parsing (#2765).+    + Allow `+` separators in pipe table cells.  We already allowed+      them in the header, but not in the body rows, for some reason.+      This gives compatibility with org-mode tables.+    + Don't cross line boundary parsing pipe table row.+      Previously an Emph element could be parsed across the newline+      at the end of the pipe table row.+    + Use `htmlInBalanced` for `rawVerbatimBlock`, for better+      performance (#2730).+    + Fixed bug with smart quotes around tex math.++  * LaTeX reader:++    + Handle interior `$` characters in math (#2743).  For example,+      `$$\hbox{$i$}$$`.+    + `inlineCommand` now gobbles an empty `{}` after any command (#2687).+      This gives better results when people write e.g. `\TeX{}` in Markdown.+    + Properly handle LaTeX "math" environment as inline math (#2171).++  * Textile reader: Support `>`, `<`, `=`, `<>` text alignment attributes.+    Closes #2674.++  * Org reader (Albert Krewinkel):++    + Prefix even empty figure names with "fig:" (#2643).  The+      convention used by pandoc for figures is to mark them by prefixing+      the name with `fig:`.  The org reader failed to do this if a figure+      had no name.+    + Refactor link-target processing (#2684).++  * ConTeXt writer: Fix whitespace at line beginning in line blocks (#2744).+    Thanks to @c-foster.++  * HTML writer: Don't include alignment attribute for default table columns.+    Previously these were given "left" alignment.  Better to leave off+    alignment attributes altogether (#2694).++  * Markdown writer: Use hyphens for YAML metadata block bottom line, for+    better compatibility with other Markdown flavors (Henrik Tramberend).++  * LaTeX writer:++    + Use image identifier to create a label and hypertarget for+      figures (Mauro Bieg).+    + Avoid double toprule in headerless table with caption (#2742).+    + Clean up options parser (Jesse Rosenthal).+    + Treat `memoir` template with `article` option as article, instead+      of treating all `memoir` templates as books.+    + Allow more flexible table alignment (Henrik Tramberend, #2665).+      New default is not to include `[c]` option (which is the default+      anyway if no positioning is specified).  Now LaTeX emplates can+      control the overall table alignment in a document by setting the+      longtable length variables `LTleft` and `LTright`.  For example,+      `\setlength\LTleft\parindent\setlength\LTright\fill`+      will create left-aligned tables that respect paragraph indentation.++  * Docx writer: Handle image alt text (#2754, Mauro Bieg).++  * Org writer - pass through RawInline with format "org".++  * DokuWiki writer: use `$$` for display math.++  * Custom writer: Pass attributes parameter to CaptionedImage (#2697).++  * Make protocol-relative URIs work again (#2737).++  * make_osx_package.sh:  Use env variable for developer id certs.++  * Raise `tagsoup` lower bound to 0.13.7 to fix entity-related+    problems (#2734).++  * Allow `zip-archive` 0.3.++  * Allow `aeson` 0.11.++pandoc (1.16.0.2)++  * Depend on deepseq rather than deepseq-generics (fpco/stackage#1096).++  * Fixed regression in latex smart quote parsing (#2645).+    In cases where a match was not found for a quote, everything+    from the open quote to the end of the paragraph was being dropped.++pandoc (1.16.0.1)++  * Fixed regression with `--latex-engine` (#2618).  In 1.16 `--latex-engine`+    raises an error if a full path is given.++  * Org reader: Fix function dropping subtrees tagged `:noexport`+    (Albert Krewinkel, #2628):++  * Markdown reader: renormalize table column widths if they exceed 100%+    (#2626).++  * Textile reader:  don't allow block HTML tags in inline contexts.+    The reader previously did allow this, following redcloth,+    which happily parses++        Html blocks can be <div>inlined</div> as well.++    as++        <p>Html blocks can be <div>inlined</div> as well.</p>++    This is invalid HTML.  The above sample now produces;++        <p>Html blocks can be</p>+        <div>+        <p>inlined</p>+        </div>+        <p>as well.</p>++  * Improved default template lookup for custom lua scripts (#2625).+    Previously, if you tried to do `pandoc -s -t /path/to/lua/script.lua`,+    pandoc would look for the template in+    `~/.pandoc/templates/default./path/to/lua/script.lua`.+    With this change it will look in the more reasonable+    `~/.pandoc/templates/default.script.lua`.  This makes it possible to+    store default templates for custom writers.++  * RST, Markdown writers: Fixed rendering of grid tables with blank rows+    (#2615).++  * LaTeX writer: restore old treatment of Span (#2624).  A Span is+    now rendered with surrounding `{}`, as it was before 1.16.++  * Entity handling fixes: improved handling of entities like+    `&lang;` that require a trailing semicolon.  Allow uppercase+    `x` in numerical hexidecimal character references, working+    around a tagsoup bug.++  * `stack.yaml` - use lts-4.0, but with older aeson to avoid excessive+    memory use on compile.  With aeson 0.10 we were getting an out of+    memory error on a 2GB Ubuntu 64-bit VM.++  * Improved deb package creation script. Made `DPKGVER` work.+    Renamed `COMMIT` to `TREE`.  You should now be able to do+    `TREE=1.16.0.1 DPKGVER=2 make deb`.+++pandoc (1.16)++  * Added `Attr` field to `Link` and `Image` (Mauro Bieg, #261, API change).++    + Added syntax for link and image attributes to pandoc's Markdown.+    + Updated readers and writers to use link and image attributes+      when appropriate.+    + Support image attributes in Docx, Textile, RST readers.++  * Renamed link attribute extensions.  The old `link_attributes` is+    now `mmd_link_attributes`, and `link_attributes` now enables the+    new pandoc-style link and image attributes (API change).+    Note: this change could break some existing workflows.++  * Implemented `SoftBreak` and new `--wrap` option (#1701, API change).+    Added threefold wrapping option.++    + Command line option: deprecated `--no-wrap`, added+      `--wrap=[auto|none|preserve]`+    + Added `WrapOption`, exported from `Text.Pandoc.Options`+    + Changed type of `writerWrapText` in `WriterOptions` from+      `Bool` to `WrapOption`.+    + Modified `Text.Pandoc.Shared` functions to allow `SoftBreak`.+    + Supported `SoftBreak` in readers and writers.++  * Text.Pandoc.Options:  Added `writerDpi` to `WriterOptions` (API+    change, Mauro Bieg).++  * Added `--dpi` command-line option (Mauro Bieg).++  * Rationalized behavior of `--no-tex-ligatures` and `--smart` (#2541).+    This change makes `--no-tex-ligatures` affect the LaTeX reader+    as well as the LaTeX and ConTeXt writers.  If it is used,+    the LaTeX reader will parse characters `` ` ``, `'`, and `-`+    literally, rather than parsing ligatures for quotation marks+    and dashes.  And the LaTeX writer will print unicode quotation+    mark and dash characters literally, rather than converting+    them to the standard ASCII ligatures.  Note that `--smart` has+    no effect on the LaTeX reader.  `--smart` is still the default+    for all input formats when LaTeX or ConTeXt is the output format,+    *unless* `--no-tex-ligatures` is used.++    Some examples to illustrate the logic:++    ```+    % echo "'hi'" | pandoc -t latex+    `hi'+    % echo "'hi'" | pandoc -t latex --no-tex-ligatures+    'hi'+    % echo "'hi'" | pandoc -t latex --no-tex-ligatures --smart+    ‘hi’+    % echo "'hi'" | pandoc -f latex --no-tex-ligatures+    <p>'hi'</p>+    % echo "'hi'" | pandoc -f latex+    <p>’hi’</p>+    ```++  * Removed deprecated options `--offline` and `--html5`.++  * Fixed language code for Czech (`cs` not `cz`) (#2597).++  * Implemented `east_asian_line_breaks` extension (#2586).+    In `Text.Pandoc.Options`, added `Ext_east_asian_line_breaks` constructor+    to `Extension` (API change).  This extension is like+    `ignore_line_breaks`, but smarter -- it only ignores line breaks+    between two East Asian wide characters.  This makes it better suited+    for writing with a mix of East Asian and non-East Asian scripts.++  * Added support for PDF creation via `wkhtmltopdf`.+    To use this: `pandoc -t html5 -o result.pdf` (and add `--mathjax`+    if you have math.) Margins can be set using the variables+    `margin-top`, `margin-bottom`, `margin-left`, `margin-right`.+    Other styling can be done through CSS.++  * Fixed cite key parsing regression (jgm/pandoc-citeproc#201).+    We were capturing final colons as in `[@foo: bar]`; the citation id+    was being parsed as `@foo:`.++  * ICML writer:++    + Fixed image syntax for local files (#2589).+    + Changed type of `writeICML` (Mauro Bieg).+      API change:  It is now `WriterOptions -> Pandoc -> IO String`.+      Also handle new image attributes.+    + Intersperse line breaks instead of appending them to+      every `ParagraphStyleRange` (Mauro Bieg, #2501).+    + Add `Cite` style to citations (Mauro Bieg).+    + Added figure handling (#2590, Mauro Bieg).+    + Better handling of math.  Instead of just printing the raw tex,+      we now try to fake it with unicode characters.++  * HTML writer: Include `example` class for example lists (#2524).++  * ODT/OpenDocument writer: improved image attributes (Mauro Bieg).++    + Support for percentage widths/heights+    + Use `Attr` instead of title to get dimensions from ODT walker+      to `writeOpenDocument`.++  * AsciiDoc writer:++    + Support anchors in spans and divs with id elements+      (jgm/pandoc-citeproc#143).+    + Fixed code blocks (#1861).++  * Haddock writer:  omit formatting inside links, which isn't supported+    by Haddock (#2515).++  * MediaWiki writer:  Fixed spacing issues in table cells.++    + Start cell on new line unless it's a single Para or Plain+      (#2606).+    + For single Para or Plain, insert a space after the `|` to+      avoid problems when the text begins with a character like+      `-` (#2604).++  * Beamer writer: mark frame as fragile when it contains verbatim (#1613).++  * LaTeX writer:++    + Add support for GAP highlighting using listings (Raniere Silva).+    + Consider `header-includes` content as well as templates+      when determining whether to use csquotes (Andreas Lööw).+    + Create defaults for geometry using `margin-left` etc.+      If `geometry` has no value, but `margin-left`, `margin-right`,+      `margin-top`, and/or `-margin-bottom` are given, a default value+      for `geometry` is created from these.  Note that these variables+      already affect PDF production via HTML5 with `wkhtmltopdf`.++  * ConTeXt writer: set default layout based on `margin-left`, etc.+    This sets up `\setuplayout` based on the variables `margin-left`,+    `margin-right`, `margin-bottom`, and `margin-top`, if no layout+    is given.++  * Docx writer:  better handling of PDF images.  Previously we tried+    to get the image size from the image even if an explicit size was+    specified.  Since we still can't get image size for PDFs, this made+    it impossible to use PDF images in docx.  Now we don't try to get+    the image size when a size is already explicitly specified.++  * Markdown writer:  use raw HTML for link/image attributes when+    the `link_attributes` extension is unset and `raw_html` is set (#2554).++  * MediaWiki reader: interpret markup inside `<tt>`, `<code>` (#2607).++  * LaTeX reader:++    + Improved smart quote parsing (#2555). This fixes redering of+      unmatched quotes.+    + Use curly quotes for unmatched ` (#2555).+    + Allow blank space between braced arguments of commands (#2592).++  * Markdown reader:++    + Improved pipe table relative widths.  Previously pipe table+      columns got relative widths (based on the header underscore lines)+      when the source of one of the rows was greater in width than the+      column width.  This gave bad results in some cases where much of+      the width of the row was due to nonprinting material (e.g. link+      URLs).  Now pandoc only looks at printable width (the width of a+      plain string version of the source), which should give better results.+      Thanks to John Muccigrosso for bringing up the issue.+    + Fixed parsing bug with macros.  Previously macro definitions in+      indented code blocks were being parsed as macro definitions, not code.++  * Textile reader:  skip over attribute in image source (#2515).+    We don't have a place yet for styles or sizes on images, but+    we can skip the attributes rather than incorrectly taking them+    to be part of the filename.++  * Docx reader: Handle dummy list items (Jesse Rosenthal).+    These come up when people create a list item and then delete the+    bullet. It doesn't refer to any real list item, and we used to ignore+    it.++  * CommonMark reader/writer rewritten to use latest `cmark`.++  * Fixed Emoji character definitions (#2523).  There were many bugs in the+    definitions.++  * `Text.Pandoc.CSS`:++    + Added `pickStylesToKVs` function to extract multiple properties at+      once (API change, Mauro Bieg).+    + Parse CSS that doesn't contain the optional semicolon (Mauro Bieg).++  * `trypandoc`: sort drop-down lists.++  * Beamer template:++    + Made `\euro` conditional on presence of character.+      for xelatex and lualatex, as it is for pdflatex (Andrew Dunning).+    + Moved `header-includes` before setting of title (Thomas Hodgson),+      to match the LaTeX template (jgm/pandoc-templates#168).+    + Added `section-titles` variable (defaults to true)+      to enable/suppress section title pages in beamer+      slide shows (Thomas Hodgson).+    + Moved beamer themes after fonts, so that themes can+      change fonts.  (Previously the fonts set were being+      clobbered by lmodern.sty.) (Thomas Hodgson).++  * Beamer/LaTeX template changes (Thomas Hodgson):+    + Added `thanks` variable+    + Use `parskip.sty` when `indent` isn't set (fall back to using+      `setlength` as before if `parskip.sty` isn't available).+    + Use `biblio-style` with biblatex.+    + Added `biblatexoptions` variable.++  * LaTeX template changes:++    + Added `paper` after `$papersize$` variable in latex template.+      Thus you can say `papersize: a4` and the latex will contain+      `a4paper`.  This change may break some existing workflows; if+      you currently specify `a4paper`, you'll get `a4paperpaper` which+      is meaningless.  However, the change seems worth it, as it will+      make the `papersize` variable work uniformly across ConTeXt, LaTeX,+      and html->pdf via wkhtmltopdf.+    + Only pass options to color package if `colorlinks` is set+      (Andrew Dunning).+    + Make definition of `\euro` conditional in xelatex/lualatex,+      as it is already for pdflatex (Andrew Dunning).+    + Removed setting of `subject` in PDF metadata.+      This used to be set to the subtitle, but really the subtitle+      need not give the subject.  Also, `subtitle` can contain formatting,+      so we'd need, at least, a plain text version for this.+    + Moved `header-includes` before setting of `\title`, `\author`,+      etc.  This allows these macros to be redefined.+    + Use `\subtitle` command for `subtitle`, instead of tacking it+      on to the title as before.  We give a no-op fallback definition if it+      is not defined.  This change should produce much better results+      in classes that support `\subtitle`.  With the default article+      class, which does not define `\subtitle`, subtitles will no+      longer be printed unless the user defines `\subtitle` and+      redefines `\maketitle`.+    + Moved redefinitions of `\paragraph` and `\subparagraph` to+      before header-includes.++  * Context template:++    + Use `simplefonts` for font loading (Paolo Rodríguez).  This is+      needed for things to work on ConTeXt stable from TeXLive 2015.+    + Revert use of `\setuphead` in title block (Andrew Dunning,+      Rik Kabel).++  * Update LaTeX/ConTeXt link colour usage (Andrew Dunning).++  * Fixed man template so disabling hyphenation actually works.+    The command needs to come after .TH.++  * Added 'navigation' variable to beamer template (#2543).+    Valid values are `empty` (the default), `horizontal`, `vertical`,+    and `frame`.  Note that this changes the default behavior from+    `horizontal` to `empty`.  Closes #2543.++  * Added `toc` to HTML slide format templates (Andrew Dunning),+    so that `--toc` creates a contents slide.++  * Added `stack.full.yaml` to build `pandoc-citeproc` as well.++  * Allow pipe tables with no body rows (#2556).+    Previously this raised a runtime error.++  * Shared: Improved `fetchItem` so that `C:/Blah/Blah.jpg` isn't treated+    as URL.  The Haskell URI parsing routines will accept "C:" as a+    scheme, so we rule that out manually.  This helps with+    `--self-contained` and absolute Windows paths.++  * Define a `meta-json` variable for all writers (#2019).  This contains+    a JSON version of all the metadata, in the format selected for the+    writer.  So, for example, to get just the YAML metadata, you can run+    pandoc with the following custom template: `$meta-json$`.  The intent+    is to make it easier for static site generators and other tools to get+    at the metadata.++  * Document limitations of --self-contained (#2553).++  * Improved Citations section of README (#2551).  Added information+    about `link-citations` and a link to the pandoc-citeproc man page.++  * `ImageSize`: use `safeRead` instead of `readMaybe`, which isn't+    in base < 4.6.++  * Allow .adoc file extension for AsciiDoc (Andrew Dunning).++  * Improved implicit pandoc-citeproc inclusion.+    The filter pandoc-citeproc is automatically used when+    `--bibliography` is specified on the command line, unless+    `--natbib` or `--biblatex` is used.  However, previously this+    only worked if `--bibliography` was spelled out in full, and not+    if `--biblio` was used.++  * reveal.js: Interpret pauses correctly for all headers (#2530).+    Previously, when using headers below the slide level, pauses are left+    uninterpreted into pauses. In my opinion, unexpected behavior but+    intentional looking at the code.++  * Remove redundant `center` variable for reveal.js (Andrew Dunning).++  * Parsing: Add `extractIdClass`, modified type of `KeyTable` (Mauro+    Bieg, API change).++  * ImageSize:  Added functions for converting between image dimensions+    (Mauro Bieg).++  * Use lts-3.18 in stack.yaml.  This avoids Windows build+    issues with the HTTP library.++  * Bump version bounds for dependencies.++pandoc (1.15.2.1)++  * Added two missing test files, and `stack.yaml`, to+    `extra-source-files` so they're included in the source tarball.++  * reveal.js template: Fixed parallaxBackground options.+    `parallaxBackgroundHorizontal` and `parallaxBackgroundVertical`+    need integer values, not strings.  (Vaughn Iverson)++pandoc (1.15.2)++  * `pandoc my.md -t context -o my.pdf` will now create a PDF using+    ConTeXt rather than LaTeX (#2463).++  * Fixed omitted `url(...)` in CSS data-uri with `--self-contained` (#2489).++  * Added `emoji` Markdown extension, enabled by default in `markdown_github`+    (#2523).  Added `Ext_emoji` to `Extension` in `Text.Pandoc.Options`+    (API change).++  * `Text.Pandoc.Readers.HTML.parseTags`: Fixed over-eager raw HTML inline+    parsing (#2469).  Tightened up the inline HTML parser so it disallows+    TagWarnings.++  * Derive `Generic` instances for the types in `Text.Pandoc.Options`.++  * Org reader:++    + Fix paragraph/list interaction (Albert Krewinkel, #2464).+      Paragraphs can be followed by lists, even if there is no blank line+      between the two blocks.  However, this should only be true if the+      paragraph is not within a list, were the preceding block should be+      parsed as a plain instead of paragraph (to allow for compact lists).+      Thanks to @rgaiacs for bringing this up.+    + Allow toggling header args (Albert Krewinkel, #2269).+      Org-mode allows to skip the argument of a code block header argument if+      it's toggling a value.  Argument-less headers are now recognized,+      avoiding weird parsing errors.+    + Fix markup parsing in headers (Albert Krewinkel, #2504).+      Markup as the very first item in a header wasn't recognized.  This was+      caused by an incorrect parser state: positions at which inline markup+      can start need to be marked explicitly by changing the parser state.+      This wasn't done for headers.  The proper function to update the state+      is now called at the beginning of the header parser, fixing this issue.+    + Fix emphasis rules for smart parsing (Albert Krewinkel, #2513).+      Smart quotes, ellipses, and dashes should behave like normal quotes,+      single dashes, and dots with respect to text markup parsing.+    + Require whitespace around definition list markers (#2518).+      This rule was not checked before, resulting in bugs with footnotes+      and some link types.++  * Markdown reader:++    + Pipe tables with long lines now get relative cell widths (#2471).+      If a pipe table contains a line longer than the column width (as set by+      `--columns` or 80 by default), relative widths are computed based on the+      widths of the separator lines relative to the column width.  This should+      solve persistent problems with long pipe tables in LaTeX/PDF output, and+      give more flexibility for determining relative column widths in other+      formats, too.  For narrower pipe tables, column widths of 0 are used,+      telling pandoc not to specify widths explicitly in output formats that+      permit this.+    + Improved parser for `mmd_title_block`.  We now allow blank metadata+      fields.  These were explicitly disallowed before.+    + Citation keys can now contain `://`, so URLs and DOIs can be used+      as citation keys (jgm/pandoc-citeproc#166).++  * Beamer template:  fix incompatibility of section slides with natbib.+    Natbib (and presumably biblatex) bibliography commands create+    their own section.  Since these are in frame environments,+    we have an incompatibility with the `\AtBeginSection` macro+    which creates a special frame when a new section occurs.+    (We can't have a frame inside another frame.) This change disables+    `\AtBeginSection` inside bibliography slides.  Thinks to Yihui Xie for+    bringing the problem to my attention.  This supersedes #145.  See+    discussion there.++  * Textile reader:  don't do smart punctuation unless explicitly asked+    (#2480).  Note that although smart punctuation is part of the textile+    spec, it's not always wanted when converting from textile+    to, say, Markdown.  So it seems better to make this an option.++  * LaTeX reader: Handle `comment` environment (Arata Mizuki).+    The `comment` environment is handled in a similar way to the+    `verbatim` environment, except that its content is discarded.++  * Docx reader:  Follow relationships correctly in foot/endnotes (#2258,+    Jesse Rosenthal).  This fixes a problem with links in notes.++  * LaTeX and ConTeXt writers: support `lang` attribute on divs and spans+    (Mauro Bieg).  For LaTeX, also collect `lang` and `dir` attributes on+    spans and divs to set the `lang`, `otherlangs` and `dir` variables if+    they aren’t set already.  See #895.++  * LaTeX writer:++    + Use proper command for `\textarabic` (Mauro Bieg).+    + Added `de-CH-1901`, fixed `el-polyton` in `toPloyglossia` (Nick Bart).+    + Use `\hypertarget` and `\hyperlink` for links.  This works correctly+      to link to Div or Span elements.  We now don't bother defining `\label`+      for Div or Span elements.  Closes jgm/pandoc-citeproc#174.+    + Avoid footnotes in list of figures (#1506).+    + Properly handle footnotes in captions (#1506).+    + Add `\protect` to `\hyperlink` (#2490).  Thanks to Hadrien Mary.+    + Set `colorlinks` if `linkcolor`, `urlcolor`, `citecolor`, or+      `toccolor` is set (#2508).++  * Textile writer: support start number in ordered lists (#2465).++  * OpenDocument writer:  Allow customization of opendocument+    automatic styles.  Automatic styles can now be inserted in the+    template, which now provides the enclosing `<office:automatic-styles>`+    tags (#2520).++  * Docx writer:  insert space between footnote reference and note (#2527).+    This matches Word's default behavior.++  * EPUB writer:  don't download linked media when `data-external` attribute+    set (#2473).  By default pandoc downloads all linked media and includes it+    in the EPUB container.  This can be disabled by setting `data-external` on+    the tags linking to media that should not be downloaded.  Example:++        <audio controls="1">+          <source src="http://example.com/music/toccata.mp3"+                  data-external="1" type="audio/mpeg">+          </source>+        </audio>++  * HTML writer:  use width on whole table if col widths sum to < 100%.+    Otherwise some browsers display the table with the columns+    separated far apart.++  * AsciiDoc template:  Fix `author` and `date`; add `keywords`,+    `abstract` (Andrew Dunning).++  * HTML-based templates (Andrew Dunning):++    + Use en dash instead of hyphen between title prefix and title.+    + Add `keywords` to metadata.+    + Add `lang`, `dir`, `quotes` where missing.+    + Always make author and date display conditional.+    + Updated dzslides template from source.++  * Man template: make "generated by" comment conditional.++  * LaTeX, Beamer templates:++    + Add `babel-otherlangs` for language divs/spans; `babel-newcommands`,+      filled by commands that make babel understand the polyglossia-style+      language directives (Mauro Bieg, #137).+    + Improved formatting of conditionals; `$for$` is always provided to allow+      multiple options (Andrew Dunning, #141).+    + Use `Ligatures=TeX` rather than `Mapping=tex-text` with `fontspec`+      to improve support for LuaTeX (Andrew Dunning, #135).+    + Revise `hyperref` usage (Andrew Dunning, #139, #141):+        - use same options for all LaTeX engines;+        - add `subtitle` and `keywords` to PDF metadata;+        - do not override `hyperref` link coloring without user input, effectively making+          the `hidelinks` option the default (removed as a separate variable);+        - link colors can be enabled (using a slightly darker version of the old+          defaults) using a new `colorlinks` variable, automatically used by+          the LaTeX writer when custom colors are specified;+        - `pdfborder={0 0 0}` is automatically set by `hyperref` with+          `colorlinks`, and is only applied if `colorlinks` is disabled.++  * ConTeXt template (Andrew Dunning):++    + New variables for controlling styles: `linkstyle`, `linkcolor`,+      `linkcontrastcolor`, `layout`, `pagenumbering`, `whitespace`, `indenting`,+      `interlinespace`, `headertext`, `footertext`, `mainfont`, `sansfont`,+      `monofont`, `mathfont`, `fontsize`.+    + Default template no longer supports MkII.+    + Improve writing of title block (suppressing numbering of first page).+    + Add `title` `subtitle`, `author`, `date`, `keywords` to PDF metadata.+    + Support `subtitle`, `abstract`.+    + Support list of figures (`lof`), list of tables (`lot`).+    + Disable link styling by default.+    + Define styles for all section types.+    + Enable microtype.+    + Improved formatting of conditionals.++  * Beamer template:  added code to prevent slide breaks inside paragraphs+    (#2422, thanks to Nick Bart).  This will matter, in practice, only when+    `allowframebreaks` is used.  It is especially helpful for bibliography+    slides.++  * OpenDocument template:  Add `<office:automatic-styles>` tag around+    automatic styles.  The writer now longer provides this (see #2520).++  * Restored Text.Pandoc.Compat.Monoid.++  * Do not export (<>) from custom Prelude.  The Prelude now matches+    base 4.8 Prelude's API.++  * Don't use custom prelude with ghc 7.10.  Use the custom prelude+    only for earlier versions.  This change makes `stack ghci` and+    `cabal repl` work (#2503), at least with ghc 7.10.++  * Changed § to % in operators from Odt.Arrows.Utils (#2457).+    This prevents problems building haddocks with "C" locale.++  * Change default for old-locale flag to False.++  * Use stack in deb, osx, and Windows package generators.++  * Added Vagrantfile for building deb in vm.+    This should help in automating binary package creation.  'make package'+    will make the package.  'make package COMMIT=blah' will make the package+    from commit blah.++  * README:++    + Consistent capitalization for pandoc and Markdown.+    + Fixed `auto_identifiers` examples (Benoit Schweblin).+    + Improved documentation of template variables (Andrew Dunning).++pandoc (1.15.1.1)++  * `Text.Pandoc.Data`:  store paths in dataFiles using posix separators.+    This way we have uniform separators, whether on Windows or Linux.+    This should solve a problem where on some Windows versions+    the data files weren't being found (#2459).++pandoc (1.15.1)++  * `pandocVersion` is now defined in `Text.Pandoc.Shared`+    and reexported from `Text.Pandoc` (Alex Vong).  This allows+    writers to access it.  (Alex Vong) (API change)++  * For `markdown_mmd`, add: `implicit_figures`, `superscripts`,+    `subscripts` (#2401).++  * Added `odt` as input format (Martin Linnemann).  Added new module+    `Text.Pandoc.Reader.ODT` (API change). Fully implemented features:+    Paragraphs, Headers, Basic styling, Unordered lists, Ordered lists,+    External Links, Internal Links, Footnotes, Endnotes, Blockquotes.+    Partly implemented features: Citations, Tables.++  * Markdown Reader:++    + Add basic tests for each header style (Ophir Lifshitz).+    + Add implicit header ref tests for headers with spaces (Ophir Lifshitz).+    + Skip spaces in headers (Ophir Lifshitz).+    + Handle 'id' and 'class' in parsing key/value attributes (#2396).+      `# Header {id="myid" class="foo bar"}`+      is now equivalent to `# Header {#myid .foo .bar}`.+    + Use '=' instead of '#' for atx-style headers in markdown+lhs.+      (Kristof Bastiaensen)+    + Pipe tables: allow indented columns.  Previously the left-hand column+      could not start with 4 or more spaces indent.  This was inconvenient+      for right-aligned left columns.  Note that the first (header column)+      must still have 3 or fewer spaces indentation, or the table will be+      treated as an indented code  block.+    + Fix regression:  allow HTML comments containing `--`.+      Technically this isn't allowed in an HTML comment, but+      we've always allowed it, and so do most other implementations.+      It is handy if e.g. you want to put command line arguments+      in HTML comments.++  * LaTeX reader:++    + Don't eat excess whitespace after macros with only optional+      arguments (#2446).+    + Support longtable (#2411).+    + Implement `\Cite` (#2335).+    + Support abstract environment.  The abstract populates an+      `abstract` metadata field.+    + Properly handle booktabs lines.  Lines aren't part of the+      pandoc table model, so we just ignore them (#2307).++  * HTML reader:++    + Handle type attribute on ol, e.g. `<ol type="i">` (#2313).+    + Updated for new automatic header attributes.+    + Add auto identifiers if not present on headers.  This makes+      TOC linking work properly.+    + Detect `font-variant` with `pickStyleAttrProps` (Ophir Lifshitz).+    + Test `<ol>` type, class, and inline list-style(-type) CSS+      (Ophir Lifshitz).+    + Better handling of "section" elements (#2438).  Previously+      `<section>` tags were just parsed as raw HTML blocks.  With+      this change, section elements are parsed as Div elements with+      the class "section".++  * MediaWiki reader:  handle unquoted table attributes (#2355).++  * DocBook reader:++    + Added proper support for DocBook `xref` elements (Frerich Raabe).+      Added `dbContent` field to reader state, so we can lookup+      cross refs.+    + Handle `informalexample` (#2319).++  * Docx Reader:++    + Create special punctuation test (Ophir Lifshitz).+    + Parse soft, no-break hyphen elements (Ophir Lifshitz).+    + Updated headers test (Ophir Lifshitz). Replaced `styles.xml`+      in `headers.docx` with pandoc's current `styles.xml`, which+      contains styles for Heading 1 through 6. Added Heading 4+      through 7 to the test document. Note that Heading 7 is not+      parsed as a Heading because there is no Heading 7 style.++  * RST reader:  better handling of indirect roles.+    Previously the parser failed on this kind of case++        .. role:: indirect(code)++        .. role:: py(indirect)+           :language: python++        :py:`hi`++    Now it correctly recognizes `:py:` as a code role.++  * Org reader:++    + Add auto identifiers if not present on headers+      (#2354, Juliusz Gonera).+    + Allow verse blocks to contain empty lines (#2402,+      Albert Krewinkel).++  * EPUB reader:  stop mangling external URLs (#2284).++  * RST writer:++    + Don't insert `\ ` when complex expression in matched pairs.+      E.g. `` [:sup:`3`] `` is okay; you don't need `` [:sup:`3`\ ] ``.+    + Ensure that `\ ` is inserted when needed before Cite and Span+      elements that begin with a "complex" element (jgm/pandoc-citeproc#157).+    + Normalize headers only in "standalone" mode (#2394).++  * Haddock writer: escape `*` and `^` (G. Bataille).++  * Markdown writer:++    + In TOC, add links to headers (#829).+    + Use unicode super/subscripts for digits in plain output+      (when the `superscripts` and `subscripts` extensions are+      not enabled).++  * Docx writer:++    + Moved invalid character stripping to `formattedString`.+      This avoids an inefficient generic traversal (#2356).+    + Use user data directory for `reference.docx` archive.+      This allows the test suite to work without installing pandoc first.+      It also brings the docx writer in line with the odt writer.+    + Tests:  docx writer tests now use `../data` for data directory.+      This allows tests to be run without installing first.+    + Tests: Use real jpg (not empty) for docx tests to avoid warning.++  * LaTeX writer:++    + Fixed detection of 'chapters' from template.+      If a documentclass isn't specified in metadata, but the+      template has a hardwired bookish documentclass, act as if+      `--chapters` was used.  This was the default in earlier+      versions, but it has been broken for a little while.+    + Correctly recognize book documentclass in metadata (#2395).+    + Set language-related variables automatically, depending+      on the value of the `lang` field, which is now always+      assumed to be in BCP47 format (Mauro Bieg, #1614, #2437).+    + Add `\protect` to `\hyperdef` in inline context.  This way we+      don't get an error when this is used as a moveable argument (#2136).+    + Support all frame attributes in Beamer.+    + Percent-encode more special characters in URLs (#1640, #2377).+      The special characters are '<','>','|','"','{','}','[',']','^', '`'.++  * HTML writer:++    + Update KaTeX JS and CSS versions (Emily Eisenberg).+    + For dzslides, add `role="note"` for speaker notes (#1693).+    + Percent-encode more special characters in URLs (#1640, #2377).+      The special characters are '<','>','|','"','{','}','[',']','^', '`'.+    + Render Div with class `section` as `<section>` in HTML5.++  * EPUB writer:++    + In TOC, replace literal `<br/>` with space (#2105).+    + With `--webtex`, include image file rather than `data:` URI (#2363).++  * Native writer: format Div properly, with blocks separated.++  * Support bidirectional text output with XeLaTeX, ConTeXt and HTML+    (#2191, Mauro Bieg).++  * Reference Docx:++    + Add missing Header 6 style (steel blue) (Ophir Lifshitz).+    + Correct `outlineLvl` for Header styles (Ophir Lifshitz).++  * Templates++    + Beamer:  Add `innertheme`, `outertheme` variables+      (Guilhem Bonnefille, #121). Add space after colon in figure caption.+      Integrate recent font and language updates from LaTeX template;+      allow use of `mainfont` variable for changing the slide text+      in XeTeX and LuaTeX (Andrew Dunning, #131).+    + LaTeX:  Add `mainfontoptions`, `sansfontoptions`,+      `monofontoptions`, `mathfontoptions`, `fontfamilyoptions`+      (Andrew Dunning, #122).  Support handling of bidirectional+      text (Mauro Bieg, #120). Improve reliability of superscripts/subscripts+      under XeTeX and prevent letters and numbers from appearing on a+      different baseline by removing use of the `realscripts` package+      (via `xltxtra`).  To restore use of OpenType characters for these+      features under XeTeX or LuaTeX, add `\usepackage{realscripts}` to+      `header-includes` (Andrew Dunning, #130).  Remove redundant+      reference to `xunicode` (Andrew Dunning, #130).  Add `fontenc`,+      `indent`, `subparagraph` variables (Andrew Dunning).+      Allow use of `hidelinks` variable for `hyperref` package (Hugo Roy,+      #113).  Prevent package clash with `tufte-latex` and other classes that+      include `hyperref` or `color` (Xavier Olive, #115).+    + ConTeXt:  Support handling of bidirectional text (Mauro Bieg, #120).+    + LaTeX and ConTeXt: Use more specific language variables.+      Instead of directly using `lang`, we now use `babel-lang` and+      `polyglossia-lang` and `context-lang`.  These variables are set by+      the writers to the necessary values, based on the `lang` variable+      (which now always takes a value in BCP47 format). (Mauro Bieg, #114,+      #129).+    + HTML:  Support handling of bidirectional text (Mauro Bieg, #120).+      Move HTML5 shiv after CSS and fix URL (Andrew Dunning).+      Add dir attribute in html5 (Andrew Dunning).+    + reveal.js: Add `controls`, `progress` variables (Grégoire Pineau, #127).+      Add `width`, `height` variables (Andrew Dunning).  Update template+      from 3.1 source (Andrew Dunning).  All configuration options are now+      available as variables, but are only be included if set (reveal.js+      uses defaults otherwise).+    + man: Added comment stating that the page is autogenerated by pandoc,+      giving version.  Added `adjusting` and `hyphenate` variables+      (Alex Vong, #123).++  * epub.css: added selectors for nested emphasis (Pablo Rodriguez).++  * MediaBag:  ensure that `/` is always used as path separator.++  * `sample.lua`: define `CaptionedImage`, add newline at end (#2393).++  * Added `--bash-completion` option.  This generates a bash completion+    script.  To use: `eval "$(pandoc --bash-completion)"`.++  * Text.Pandoc.Error: Define Typeable and Exception instances+    for PandocError (#2386).++  * Text.Pandoc.Parsing: `toKey`: strip off outer brackets.+    This makes keys with extra space at the beginning and end+    work:  e.g.++        [foo]: bar++        [ foo ]++    will now be a link to bar (it wasn't before).++  * Text.Pandoc: disable `auto_identifiers` for epub.+    The epub writer inserts its own auto identifiers;+    this is more complex due to splitting into "chapter" files.++  * Renamed Text.Pandoc.Compat.Locale -> Text.Pandoc.Compat.Time.+    It now reexports Data.Time.++  * Use custom Prelude to avoid compiler warnings.++    + The (non-exported) prelude is in prelude/Prelude.hs.+    + It exports Monoid and Applicative, like base 4.8 prelude,+      but works with older base versions.+    + It exports (<>) for mappend.+    + It hides 'catch' on older base versions.++  * Added a `stack.ymal` and stack install instructions to INSTALL.++  * Clarified what is "out of scope" in README and CONTRIBUTING.md.++  * Added note to CONTRIBUTING.md about ghc versions and travis.++  * Clarify docs on block quotes.  The space after `>` is optional (#2346).++  * Removed obsolete reference to default.csl (#2372).++  * List all styles in manual for `--reference-docx` (Chris Black)++  * Don't capitalize header links in man page.++  * Added section on repl to CONTRIBUTING.md.++  * README:  Added space after backslash in image example (#2329).++  * Document details of citation locator terms (Nick Bart).++  * Fixed some internal links in README (#2309).++  * Improve CSL documentation, variables documentations,+    links, and cross-references in README. (Andrew Dunning)++  * Fix build failure with `--flags=-https` (Sergei Trofimovich).++  * Use `newManager` instead of `withManager` in recent `http-client`.+    This avoids a deprecation warning.++  * Allow building with latest versions of http-types,+    HUnit, criterion, syb, aeson.++  * Updated benchmark program for new criterion API.++  * Setup.hs: rewrite so as not to use process, directory, filepath.+    Using anything outside base is dangerous, since older+    versions of ghc may link against two different versions.++  * Added appveyor (Windows continuous integration) builds.++  * New `.travis.yml`.  Autgenerated using `make_travis_yml.hs`.+    This script has been modified in a few ways, e.g. to add `GHCOPTS`.+    `make .travis.yml` regenerates it based on the tested-with+    field of the cabal file.++pandoc (1.15.0.6)++  * `--self-contained`:  Fixed overaggressive CSS minimization (#2301, 2286).+    Previously `--self-contained` wiped out all spaces in CSS,+    including semantically significant spaces.  This was a regression+    from 1.14.x.++  * Markdown reader: don't allow bare URI links or autolinks in link+    label (#2300).  Added test cases.++  * `Text.Pandoc.Parsing`, `uri`: Improved bare autolink detection (#2299).+    Previously we disallowed `-` at the end of an autolink,+    and disallowed the combination `=-`.  This commit liberalizes the+    rules for allowing punctuation in a bare URI, and adds test cases.+    One potential drawback is that you can no longer put a bare+    URI in em dashes like this:+    `this uri---http://example.com---is an example.`+    But in this respect we now match github's treatment of bare URIs.++  * HTML writer:  support speaker notes in dzslides.+    With this change `<div class="notes">` and also `<div class="notes"+    role="note">` will be output if `-t dzslides` is used. So we can+    have speaker notes in dzslides too.  Thanks to maybegeek.++  * Updated dzslides template.++  * Improved documentation of options to print system default files (#2298).+    `--print-default-data-file` and `--print-default-template`.++  * DokuWiki writer: use `$..$` for Math instead of `<math>..</math>`+    (Tiziano Müller).  MathJax seems currently to be the only maintained+    math rendering extension for DokuWiki.++  * `Text.Pandoc.Shared`: Changed `hierarchicalize` so it treats references+    div as top-level header (#2294).  This fixes a bug with `--section-divs`,+    where the final references section added by pandoc-citeproc, enclosed in+    its own div, got nested in the div for the section previous to it.++  * Allow vector 0.11.++  * Require cmark > 0.4.++pandoc (1.15.0.5)++  * HTML writer: Fixed email javascript obfuscation with `mailto:`+    URLs (#2280).  This fixes a potential security issue.  Because+    single quotes weren't being escaped in the link portion, a+    specially crafted email address could allow javascript code injection.++  * Markdown/HTML readers:  Avoid parsing partial URLs like+    `<www.pandoc.org/blah#foo>` as HTML tags (#2277).++  * RST reader:  allow inline formatting in definition list field+    names (Lars-Dominik Braun).++  * PDF:  Make sure `--latex-engine-opt` goes before the filename+    on the command line.  LaTeX needs the argument to come after+    the options (#1779).++  * CommonMark writer: fixed tags used for super/subscript.++  * ConTeXt template:  activate hanging indent for definition lists+    (Mauro Bieg).++  * Make cabal require `hsb2hs` >= 0.3.1 if `embed_data_files` specified.+    This is done by adding `hookedPrograms` in `Setup.hs`, which allows us+    to include `hsb2hs` in Build-Tools in cabal.++  * Improved Windows installer (thanks to nkalvi).++    + When per-machine installation is chosen, the system path+      is updated instead of the user's.+    + An appropriate default is used for per-machine installation+      directory.+    + Admin privileges are no longer required for a per-user install++  * Travis:  unpack sdist for build to catch packaging bugs.++  * Improved documentation on where user templates go (#2272).++pandoc (1.15.0.4)++  * Added pandoc.1 man page to the repository.  It is no longer+    built as part of the cabal build process. (This proved too+    fragile.)  pandoc.1 can be regenerated (`make man/pandoc.1`)+    when `README` is changed.++  * Copying of the man page now respects `--destdir` (#2262).++  * Improved error messages for filters.  User is now informed if+    the filter requires an interpreter that isn't found in the path,+    or if the filter returns an error status.++pandoc (1.15.0.3)++  * Ensure target directory is created when installing man page.++pandoc (1.15.0.2)++  * Added files needed for building man page to Extra-Source-Files.++pandoc (1.15.0.1)++  * Man page is now built and installed as part of the cabal build+    process. Removed Makefile target for man page.++pandoc (1.15)++  * Man page changes:++    + Removed `--man1`, `--man5` options (breaking change).+    + Removed `Text.Pandoc.ManPages` module (breaking API change).+    + Makefile target for `man/man1/pandoc.1`.  This uses pandoc to+      create the man page from README using a custom template and filters.+    + Added `man/` directory with template and filters needed to build+      man page.+    + We no longer have two man pages: `pandoc.1` and `pandoc_markdown.5`.+      Now there is just pandoc.1, which has all the content from README.+      This change was needed because of the extensive cross-references+      between parts of the README.+    + Removed old `data/pandoc.1.template` and+      `data/pandoc_markdown.5.template`.++  * OpenDocument writer: Do not add a carriage return after a hard+    line break (Michael Chladek).++  * ConTeXt writer:++    + use `\goto` for internal links.+    + Added a `%` at end for `\reference` to avoid spurious space.++  * Ignore sandbox on 'make quick'++pandoc (1.14.1)++  * Added `--man1` and `--man5` options to pandoc, allowing pandoc+    to generate its own man pages.  Man pages are no longer automatically+    generated in the build process (the process for this was too complex+    and prone to failure, #2190).  The `make-pandoc-man-pages` executable+    has been removed.  The `man/` directory has been removed, and man page+    templates have been moved to `data/`.  NOTE TO PACKAGERS:  You will no+    longer find pandoc's man pages in `man/`, but you can generate them using+    `pandoc --man1 > pandoc.1` and `pandoc --man5 > pandoc_markdown.5`.++  * Added new unexported module:  `Text.Pandoc.ManPages`.++  * `README` now acts like a data file (even though it isn't in+    `data/`).  So, for example, `pandoc --print-default-data-file README`+    will produce the README.)  This change was required for the `--man1`+    and `--man5` options, since the man pages are produced from the+    README, but it may be useful for other purposes as well.++  * Allow `reference.docx` and `reference.odt` to be used with+    `--print-default-data-file` and to shadow defaults if placed in+    the user data directory.  Note that as of 1.14, we no longer+    include these files as data files; instead, we include their+    components.  This change causes pandoc to behave as if it has+    these data files; they are constructed on demand when needed+    using `getDefaultReferenceDocx` and `getDefaultReferenceODT`.++  * Fixed regression in CSS parsing with `--self-contained` (#2224).+    Pandoc 1.14.0.x used css-text to parse the CSS, but its parser+    silently drops big sections of CSS.  This commit replaces the+    use of css-text with a small but principled CSS preprocessor,+    which removes whitespace and comments and replaces `url()` with+    base 64 data when possible.++  * Use `https://` instead of `//` for MathJax and KaTeX CDN URLs (#1920).+    This will allow math to work when pages are being viewed locally.++  * `Text.Pandoc.Options`:  Export `plainExtensions`.+    These are the extensions used in `plain` output.++  * LaTeX reader: Don't parse `_` and `^` as sub/superscript outside of+    math mode; treat them as regular inline text.  Normally these will+    cause an error in LaTeX, but there are contexts (e.g. `alltt`+    environments) where they are allowed.++  * HTML reader:  allow `<body>` to close `<head>`.++  * DocBook reader: support `mediaobject`s and `figures` (#2184, Mauro Bieg).++  * RST reader: Fix reference names with special characters+    (Lars-Dominik Braun).++  * Textile writer:  escape `+` and `-` as entities (#2225).++  * DokuWiki writer: Use proper `<code>` tags for code blocks (#2213).++  * Plain writer:  don't use symbols for super/subscript (#2237).+    Simplified code by using `plainExtensions`.++  * InDesign writer: Properly escape URLs containing more than one+    colon character (gohai).++  * Docx writer: Make sure we use dist version of `reference.docx`+    (and not the user's version) for certain settings.  Taking some+    settings values from a user-supplied reference.docx can lead to+    corruption.  This fixes a regression from the last release (#2249).++  * `Text.Pandoc.Shared`: exports `getDefaultReferenceDocx` and+    `getDefaultReferenceODT` (API change).  These functions have been+    removed from the Docx and ODT writers.++  * LaTeX template (Xavier Olive):+    + Added `CJKmainfont` and `CJKoptions` variables.+    + Allow dvipsnames (e.g. `MidnightBlue`) for colors (Xavier Olive).++  * Epub templates:  use `author.role`, not `author.type`.++  * Bump cmark version to >= 0.3.4.++  * Improved Windows installer (#2205, thanks to nkalvi).+    Users can now select a per-user or systemwide install, and can set+    the installation path.  At the end of installation, the install location+    is given.  The install location is also now given in the list of+    installed programs in Control Panel.  Cleaner WiX syntax is used for+    setting the path.++  * Added `download_stats` target to Makefile.++pandoc (1.14.0.4)++  * Added missing commonmark template.++  * Improved try pandoc (moved button, show raw command).++pandoc (1.14.0.3)++  * Allow compilation with syb 0.5.*.++  * Custom writer:  fixed some compiler warnings for ghc < 7.10.++pandoc (1.14.0.2)++  * Allow building with hslua 0.4.++pandoc (1.14.0.1)++  * Fixed problem with building of `reference.docx` and `reference.odt`+    when the `embed_data_files` flag is used.  Instead of having a phase+    of the build where `reference.docx` and `reference.odt` are created+    from their constituent data files, we now construct these archives+    from their constituents when a `docx` or `odt` is built.  The+    constituent files have been moved from `extra-source-files` to+    `data-files`, and `reference.docx` and `reference.odt` have been+    removed. Users can create their own `reference.docx` or+    `reference.odt` by using pandoc to create a simple `docx` or `odt`.+    `make-reference-files.hs` has been removed, simplifying the build+    process (#2187)++  * Don't include generated man pages in extra-source-files (#2189).++  * Bumped upper bound for aeson.++  * ConTeXt writer:  create internal link anchors for Div elements with+    identifiers.  (This is needed for linked citations to work.)++pandoc (1.14)++  [new features]++  * Added `commonmark` as input and output format.++  * Added `--verbose` flag for debugging output in PDF production (#1840,+    #1653).++  * Allow wildcards in `--epub-embed-font` arguments (#1939).++  * Added `--latex-engine-opt` option (#969, #1779, Sumit Sahrawat).++  * Added `shortcut_reference_links` extension (Konstantin Zudov, #1977).+    This is enabled by default for those markdown flavors that+    support reading shortcut reference links, namely: `markdown`,+    `markdown_strict`, `markdown_github`, `markdown_php`.+    If the extension is enabled, the reader parses shortcut reference+    links like `[foo]`, and the writer creates such links unless doing+    so would cause problems.  Users of markdown flavors that support+    shortcut reference links should not notice a difference in reading+    markdown, but the markdown pandoc produces may differ.+    If shortcut links are not desired, the extension can be disabled+    in the normal way.++  [behavior changes]++  * `--toc` is now supported for `docx` output (#458, Nikolay Yakimov).+    A "dirty" TOC is created at the beginning of document.+    It can be regenerated after the document has been opened.++  * An implicit `--filter pandoc-citeproc` is now triggered only when the+    `--bibliography` option is used, and not when the `bibliography`+    field in metadata is specified (#1849).++  * Markdown reader:++    + Reference links with `implicit_header_references` are no longer+      case-sensitive (#1606).+    + Definition lists no longer require indentation for first line (#2087).+      Previously the body of the definition (after the `:` or `~` marker)+      needed to be in column 4.  This commit relaxes that requirement,+      to better match the behavior of PHP Markdown Extra.  So, now+      this is a valid definition list:++            foo+            : bar+    + Resolve a potentially ambiguity with table captions:++            foo++              : bar++              -----+              table+              -----++      Is "bar" a definition, or the caption for the table?  We'll count+      it as a caption for the table.+    + Disallow headerless pipe tables (#1996), to conform to GFM and PHP+      Markdown Extra.  Note:  If you have been using headerless pipe tables,+      this change may cause existing tables to break.+    + Allow pipe tables with header but no body (#2017).+    + Allow a digit as first character of a citation key (Matthias Troffaes).+      See https://github.com/jgm/pandoc-citeproc/issues/97++  * LaTeX reader:++    + Don't limit includes to `.tex` extension (#1882).+      If the extension is not `.tex`, it must be given explicitly in+      the `\input` or `\include`.++  * Docx reader:++    + Allow numbering in the style file.  This allows inherited styles+      with numbering (lists) (Jesse Rosenthal).++  * Org reader:++    + Support smart punctuation (Craig Bosma).+    + Drop trees with a :noexport: tag (Albert Krewinkel). Trees having a+      `:noexport:` tag set are not exported.  This mirrors org-mode.+    + Put header tags into empty spans (Albert Krewinkel, #2160).+      Org mode allows headers to be tagged: `* Headline  :TAG1:TAG2`.+      Instead of being interpreted as part of the headline, the tags are now+      put into the attributes of empty spans.  Spans without textual content+      won't be visible by default, but they are detectable by filters.  They+      can also be styled using CSS when written as HTML.+    + Generalize code block result parsing (Albert Krewinkel).+      Previously, only code blocks were recognized as result blocks;+      now, any kind of block can be the result.++  * Append newline to the LineBreak in Dokuwiki, HTML, EPUB,+    LaTeX, MediaWiki, OpenDocument, Texinfo writers (#1924, Tim Lin).++  * HTML writer:++    + Add "inline" or "display" class to math spans (#1914).+      This allows inline and display math to be styled differently.+    + Include raw latex blocks if `--mathjax` specified (#1938).+    + Require highlighting-kate >= 0.5.14 (#1903).+      This ensures that all code blocks will be wrapped in a `div`+      with class `sourceCode`.  Also, the default highlighting CSS+      now adds `div.sourceCode { x-overflow: auto; }`, which means+      that code blocks (even with line numbers) will acquire a scroll+      bar on screens too small to display them (e.g. mobile phones).+      See also jgm/highlighting-kate#65.++  * LaTeX writer:++    + Use a declaration for tight lists (Jose Luis Duran, Joseph+      Harriott). Previously, pandoc hard-coded some commands to make+      tight lists in LaTeX.  Now we use a custom command instead,+      allowing the styling to be changed in a macro in the header.+      (Note:  existing templates may need to be modified to include+      the definition of this macro.  See the current template.)+    + Beamer output: if the header introducing a slide has the+      class `fragile`, add the `[fragile]` option to the slide (#2119).++  * MediaWiki writer:++    + Use `File:` instead of the deprecated `Image:` for images and+      other media files (Greg Rundlett).++  * DocBook writer:++    + Render a `Div (id,_,_) [Para _]` element as a `para` element+      with an `id` attribute.  This makes links to citations work in+      DocBook with pandoc-citeproc.++  * RST writer:++    + Normalize headings to sequential levels (Nikolay Yakimov).+      This is pretty much required by docutils.+    + Treat headings in block quotes, etc as rubrics (Nikolay Yakimov).+    + Better handling of raw latex inline (#1961).  We use+      `` :raw-latex:`...` `` and add a definition for this role to+      the template.++  * EPUB writer:++    + Remove `linear=no` from cover `itemref` (#1609).+    + Don't use `sup` element for epub footnotes (#1995).+      Instead, just use an a element with class `footnoteRef`.+      This allows more styling options, and provides better results+      in some readers (e.g. iBooks, where anything inside the a+      tag breaks popup footnotes).+    + Take TOC title from `toc-title` metadata field.++  * Docx writer:++    + Implemented `FirstParagraph` style (Jesse Rosenthal).+      Following the ODT writer, we add the `FirstParagraph` style to the+      first text paragraph following an image, blockquote, table, heading,+      or beginning of document.  This allows it to be styled differently.+      The default is for it to be the same as `Normal`.+    + Added `BodyText` style (Jesse Rosenthal).+      We apply a `BodyText` style to all unstyled paragraphs. This is,+      essentially, the same as `Normal`, except that since not everything+      inherits from `BodyText` (the metadata won't, for example, or+      the headers or footnote numbers), we can change the text in the body+      without having to make exceptions for everything.  If we do want to+      change *everything*, we can still do it through `Normal`.+    + Altered `Blockquote` style slightly (Jesse Rosenthal).+      Since `BlockQuote` derives from `BodyText`, we just want to specify+      by default that it won't indent, regardless of what `BodyText` does.+      Note that this will not produce any visible difference in the default+      configuration.+    + Take TOC title from `toc-title` metadata field (Nikolay Yakimov).+    + Added a style to figure images (Nikolay Yakimov).+      Figures with empty captions use style `Figure`.+      Figures with nonempty captions use style `Figure with Caption`, which+      is based on `Figure`, and additionally has `keepNext` set.++  * ODT writer:++    + Added figure captions (Nikolay Yakimov). The following styles are+      used for figures:+      `Figure` -- for figure with empty caption),+      `FigureWithCaption` (based on `Figure`) -- for figure with caption,+      `FigureCaption` (based on `Caption`) -- for figure captions.+      Also, `TableCaption` (based on `Caption`) is used for table captions.++  [API changes]++  * New `Text.Pandoc.Error` module with `PandocError` type+    (Matthew Pickering).++  * All readers now return `Either PandocError Pandoc` instead of `Pandoc`+    (Matthew Pickering).  This allows better handling of errors.++  * Added `Text.Pandoc.Writers.CommonMark`, exporting `writeCommonMark`.++  * Added `Text.Pandoc.Readers.CommonMark`, exporting `readCommonMark`.++  * Derive `Data` and `Typeable` instances for `MediaBag`, `Extension`,+    `ReaderOptions`, `EPUBVersion`, `CiteMethod`, `ObfuscationMethod`,+    `HTMLSlideVariant`, `TrackChanges`, `WriterOptions` (Shabbaz+    Youssefi).++  * New `Ext_shortcut_reference_links` constructor for `Extension`+    (Konstantin Zudov).++  [bug fixes]++  * Markdown reader:++    + Allow smart `'` after inline math (#1909, Nikolay Yakimov).+    + Check for tex macros after indented code (#1973).+    + Rewrote `charsInBalancedBrackets` for efficiency.+    + Make sure a closing `</div>` doesn't get included in a+      definition list item (#2127).+    + Don't parse bracketed text as citation if it might be a link,+      image, or footnote (Nikolay Yakimov).+    + Require space after key in mmd title block (#2026, Nikolay+      Yakimov).  Require space after key-value delimiter colon in mmd title+      block.+    + Require nonempty value in mmd title block (Nikolay Yakimov).+    + Disable all metadata block extensions when parsing+      metadata field values (#2026, Nikolay Yakimov).  Otherwise we+      could get a mmd title block inside YAML metadata, for example.++  * HTML reader:++    + Improve self-closing tag detection in `htmlInBalanced` (#2146).+    + Handle tables with `<th>` in body rows (#1859, Mauro Bieg).+    + Fixed `htmlTag` (#1820).  If the tag parses as a comment, we check+      to see if the input starts with `<!--`. If not, it's bogus comment+      mode and we fail `htmlTag`.+    + Handle `base` tag; if it has an `href` value, this is added to+      all relative URLs in links and images.++  * DocBook reader:++    + Look inside "info" elements for section titles (#1931).++  * Docx reader:++    + Parse images in deprecated vml format (Jesse Rosenthal).+    + Allow sub/superscript verbatims (Jesse Rosenthal).+      Verbatim usually shuts off all other run styles, but we don't want it+      to shut off sub/superscript.++  * LaTeX reader:++    + Handle `tabular*` environment (#1850).+      Note that the table width is not actually parsed or taken into+      account, but pandoc no longer chokes on it.+    + Ignore options in `\lstinline` rather than raising error (#1997).+    + Add some test cases for simple tables (Mathias Schenner).+    + Handle valign argument in tables (Mathias Schenner) (currently+      we just ignore this).+    + Allow non-empty colsep in tables (Mathias Schenner).+      The `tabular` environment allows non-empty column separators+      with the "@{...}" syntax. Previously, pandoc would fail to+      parse tables if a non-empty colsep was present. With this+      commit, these separators are still ignored, but the table gets+      parsed. A test case is included.+    + Recognize `\newpage` as a block command.+    + Allow block content in \title{} (#2001).+    + Check for block-level newcommand aliases in blockCommand (Nikolay+      Yakimov).+    + Guard against paragraph starting with inline macro (Nikolay Yakimov).+    + Properly gobble spaces after `\\` (#2007).++  * Textile reader:++    +  Handle newlines in table cells, and empty cells (#1919).++  * Org reader:++    + Allow image links with non-image targets (Hans-Peter Deifel).+      This matches behavior of Org-Mode for links like+      `[[http://example.com][https://www.haskell.org/static/img/logo.png]]`.++  * Docbook writer:++    + Don't print empty id attributes (thanks to Steve Horne).++  * HTML writer:++    + Fixed list-style-type for numbered example lists.+      Should be "decimal," not "example" (#1902).+    + Do not omit missing `alt` attribute on `img` tag (#1131,+      Konstantin Zudov).+    + Allow multiple colgroups in table (#2122).+    + In revealjs, ensure that lists in speaker notes don't add "fragment"+      classes, which can cause additional keypresses to be needed to+      advance a slide (#1394).++  * LaTeX writer:++    + Don't escape `$` in URL (#1913).+    + Don't use listings in headers (Matthew Pickering, #1963).+    + Recognize book documentclass if set in metadata (#1971).+      This sets `--chapters` implicitly if the documentclass in metadata+      is a book documentclass.  Previously this was done only if a book+      documentclass was set in a variable.+    + Add a `\label` in `\hyperdef` for Div, Span (or links don't work).+    + Make `mainlang` work when `lang` is in metadata (#2174).++  * Texinfo writer:++    + Fix wrapping by using breakable spaces (Tim Lin).++  * RST writer:++    + Fixed toc depth in RST writer.  Previously the depth was being+      rendered as a floating point number with a decimal point.++  * Markdown writer:++    + Improved escaping (#2086).  `<` should not be escaped as `\<`, for+      compatibility with original Markdown.  We now escape `<` and `>`+      with entities.  Also, we now backslash-escape square brackets.+    + Avoid introducing spurious list items through wrapping (#1946).+    + Don't emit span tags if plain or raw HTML disabled.++  * MediaWiki writer:++    + Convert spaces to underscores in wikilink URL (#1982), like MediaWiki.++  * AsciiDoc writer:++    + Insert some needed blank lines (#1860).+    + Avoid wrapping after list marker (#1858).++  * EPUB writer:++    + Properly handle internal links to IDs in spans, divs (#1884).+    + Use plain writer for metadata dc: fields (#2121).+      This gives better results when we have, e.g. multiple paragraphs.+      Note that tags aren't allowed in these fields.+    + Properly handle image links without an extension (#1855).+    + Improved chapter splitting and internal link rewriting (#1887,+      #2162, #2163).  This will ensure that internal links work and+      that the references section produced by pandoc-citeproc is+      in its own chapter.+    + Fixed handling of svg images (#2183).++  * ICML writer:++    + Better handling of raw blocks and inlines (#1951).+      Previously these were always escaped and printed verbatim.+      Now they are ignored unless the format is `icml`, in which+      case they are passed through unescaped.+    + Fixed image URIs in ICML output (gohai).++  * Custom writer:++    + Raise error if loadstring returns an error status.+    + Raise `PandocLuaException` instead of using 'error'.+      Eventually we'll change the return type so that no exception+      is involved, but at least this can be trapped.+    + Use UTF-8 aware bytestring conversion.+    + Set foreign encoding to UTF-8 (Nikolay Yakimov, #2101, #1634).+      Also factored out ByteString, since it's only used as an intermediate+      representation.++  * Docx writer:++    + Copy hyphenation settings from reference.docx (Nikolay Yakimov).+    + Filter out illegal XML characters (#1992, Matthew Pickering).+    + Added `noProof` to docx syntax highlighting `SourceCode` style.+    + Added footnotes id -1 and 0 (Jesse Rosenthal).+      Word uses, by default, footnotes with id -1 and 0 for separators. If a+      user modifies `reference.docx`, they will end up with a `settings.xml`+      file that references these footnotes, but no such footnotes in the+      document. This will produce a corruption error. Here we add these to the+      document and `settings.xml` file, so future modifications won't break+      the file.+    + Handle lists correctly inside table cells (Jesse Rosenthal).+      Previously we didn't transform lists inside table cells.+    + Set firstRow information in tables (Nikolay Yakimov).+    + Don't replace `SourceCode` style in `reference.docx` if it is defined+      there (Nikolay Yakimov, #1872).  If `--no-highlight` specified, remove+      any `SourceCode` and `*Tok` styles in `reference.docx`.+    + Attempt to match international style names (#1607, Nikolay Yakimov).+    + Set these styles as custom (Nikolay Yakimov): `Author`, `Abstract`,+      `Compact`, `Image Caption`, `Table Caption`, `Definition Term`,+      `Definition`, `First Paragraph`.+    + Rename these styles to correspond with Word `Normal.dotm` (Nikolay+      Yakimov): `Block Quote -> Block Text`, `Link -> Hyperlink`,+      `Footnote Ref -> Footnote Reference`.+    + Added `Caption` style (Nikolay Yakimov).+    + Changed these styles' inheritance (Nikolay Yakimov):+      `Image Caption <- Caption`, `Table Caption <- Caption`.+    + Remove `SourceCode` style from `reference.docx` (#1872).+      This is added automatically by the docx writer.+    + Added toc heading style to `reference.docx` (Nikolay Yakimov).++  * `Text.Pandoc.PDF`++    + Don't suggest "Try xelatex" if xelatex already in use (Mauro Bieg,+      #1832).+    + More comprehensible errors on image conversion (#2067).+      EPS can't be supported without shelling out to something like+      ImageMagick, but at least we can avoid mysterious error messages.++  * `Text.Pandoc.Shared`:++    + Make safeRead safe (#1801, Matthew Pickering).+    + Addded `mapLeft`, `hush` (Matthew Pickering).++  * `Text.Pandoc.Pretty`:++    + Remove partial function (Matthew Pickering).++  * `Text.Pandoc.SelfContained`:++    + Add `;charset=utf-8` to script mime type if missing (#1842).+    + Improved building of data URIs (#1940).  Now base64 is used except+      for `text/*` mime types.+    + `cssURLs` no longer tries to fetch fragment URLs (#2121).+    + Properly handle data URIs in css urls (#2129).+      Use a proper CSS parser (adds dependency on `text-css`).++  * `Text.Pandoc.UTF8`:++    + Better handling of bare CRs in input files (#2132).+      Previously we just stripped them out; now we convert+      other line ending styles to LF line endings.++  * `Text.Pandoc.ImageSize`:++    + Fixed some exif header parsing bugs (#1834).+    + Make imageSize return an Either, not a Maybe (#1834).+      Use `runGetOrFail` (with `binary >= 0.7`) to return `Left` on+      parse failure (rather than `error`).+    + Improved warnings when image size can't be determined.+    + Removed error landmines (Matthew Pickering).++  * Added woff2 to MIME types (Alfred Wechselberger).++  * pandoc:  When a binary input format is used, warn that file+    arguments past the first one are being ignored (Matthew Pickering).++  [template changes]++  * LaTeX template:++    + Degrade gracefully if `\paragraph` not defined.+    + Include `grffile` together with `graphicx` (#2074).+      This properly handles filenames containing spaces and dots.+    + Redefine `\paragraph`, `\subparagraph`...  to behave more+      like section headers (#1658).+    + Import hyperref before polyglossia to avoid an error with xelatex,+      "please load package hyperref before bidi package" (Nick Bart).+    + Added `toccolor` variable to control link color in toc (Kaixhin).++  * LaTeX, Beamer templates:++    + Provide `\tightlist`, which is now used by the LaTeX writer.+    + Use polyglossia in beamer (#85).+    + Use `bibliography` instead of `biblio-files`+      (#1661).  Also use `\addbibresource` instead of `\bibliography` for+      biblatex.+    + Added `setotherlanguages` in polyglossia. This uses an `otherlang`+      variable that is derived from a comma-separated list in `lang`;+      the last language is `mainlang` and the others are `otherlang`.++  * EPUB templates:++    + Use `div`, not `p`, for "rights" on title page.+    + Added header-includes, include-before, include-after (#1987).++  * OpenDocument template:++    + Use `text:p` instead of `text:h` for title.+      Using `text:h` causes problems with numbering.  Closes #2059.+      Thansk to @nkalvi for diagnosing this.++  * reveal.js template:++    + Link to non-minified css, js.  The minified versions no longer+      ship with the library.+    + Correctly include style CSS (#1949).+    + New configurable options options: `center`, `maxScale`, `slideNuber`+      (Dmitry Smirnov, pandoc-templates#89).+    + Moved custom CSS after theme.  This allows custom CSS to modify+      themes, instead of being replaced by them.+    + Allow `center` to be set to false.++  [under the hood improvements]++  * Removed pre-built `reference.docx` and `reference.odt` (Nikolay+    Yakimov).  Instead the repository now includes the component text files,+    and the zipped binaries are built from these using a helper+    program, `make-reference-files`.  This should make maintenance of+    these components easier going forward.++  * `Text.Pandoc.Parsing`:++    + Added new `<+?>` combinator (Nikolay Yakimov).+    + Added `stateHeaderKeys` to `ParserState`.++  * `make_deb.sh` fixes:++    + Detect architecture.+    + Add Installed-Size to debian package control file (#1900).+    + Use `fakeroot` to get permissions right.+    + Use `mkdir` and `cp` instead of `install`.+    + Set permissions of directories to 755.+    + Install in `/usr` rather than `/usr/local`.+    + Compress man pages.+    + Combine copyright files for `pandoc`, `pandoc-citeproc`.++  * Added `Text.Pandoc.Compat.Locale` and `old-locale` flag+    to assist with transition to `time` 1.5.++  * Updated CONTRIBUTING.md with information about issue tags (Matthew+    Pickering).++  * Updated travis installs to the new sudo-less syntax (Tim Lin).++  * Updated dependency version bounds.++  * EPUB tests:  don't use `joinPath`, which varies across platforms.+    Instead, use a forward-slash to join paths, regardless of the+    platform. This matches the way `MediaBag` now works.++  * Clarify JSON input and output in usage message (Caleb McDaniel).++  * Improved INSTALL instructions.++  * Always build man pages.  Removed make-pandoc-man-pages flag.++  * Makefile:  removed man target, now that we generate man pages by default.++  * README:++    + Fixed typos (J. Lewis Muir).+    + Added documentation on backtick_code_blocks (#2135, Nikolay Yakimov).+    + Added note on in-field markup in biblio databases (Nick Bart).+    + Fixed misleading example of raw HTML block.+    + Various minor formatting and consistency fixes for the program+      options (Andreas Lööw).+    + Made definition lists for options all "loose" for consistency.+    + Added YAML biblio format to table, and note on `pandoc-citeproc`'s+      `--bib2json` and `--bib2yaml` options (Nick Bart).+    + Removed obsolete reference to `mods2yaml` (Nick Bart).+    + Added section on syntax highlighting.+    + Documented `toccolor` variable.++pandoc (1.13.2.1)++  * Updated to build with ghc 7.10.1.++  * Bumped package upper bounds for filepath, blaze-html,+    blaze-markup.++pandoc (1.13.2)++  * TWiki Reader: add new new twiki reader (API change, Alexander Sulfrian).++  * Markdown reader:++    + Better handling of paragraph in div (#1591).+      Previously text that ended a div would be parsed as Plain+      unless there was a blank line before the closing div tag.+    + Don't treat a citation as a reference link label (#1763).+    + Fix autolinks with following punctuation (#1811).+      The price of this is that autolinked bare URIs can no longer+      contain `>` characters, but this is not a big issue.+    + Fix `Ext_lists_without_preceding_blankline` bug (#1636, Artyom).+    + Allow `startnum` to work without `fancy_lists`. Formerly+      `pandoc -f markdown-fancy_lists+startnum` did not work properly.++  * RST reader (all Daniel Bergey):++    + Parse quoted literal blocks (#65).  RST quoted literal blocks are+      the same as indented literal blocks (which pandoc already supports)+      except that the quote character is preserved in each line.+    + Parse RST class directives. The class directive accepts one or more+      class names, and creates a Div value with those classes.  If the+      directive has an indented body, the body is parsed as the children of+      the Div.  If not, the first block folowing the directive is made a+      child of the Div. This differs from the behavior of rst2xml, which+      does not create a Div element.  Instead, the specified classes are+      applied to each child of the directive.  However, most Pandoc Block+      constructors to not take an Attr argument, so we can't duplicate this+      behavior.+    + Warn about skipped directives.+    + Literal role now produces Code. Code role should have "code" class.+    + Improved support for custom roles++        - Added `sourceCode` to classes for `:code:` role, and anything+          inheriting from it.+        - Add the name of the custom role to classes if the Inline+          constructor supports Attr.+        - If the custom role directive does not specify a parent role,+          inherit from the `:span:` role.++      This differs somewhat from the `rst2xml.py` behavior.  If a custom+      role inherits from another custom role, Pandoc will attach both+      roles' names as classes.  `rst2xml.py` will only use the class of+      the directly invoked role (though in the case of inheriting from a+      `:code:` role with a `:language:` defined, it will also provide the+      inherited language as a class).+    + Warn about ignored fields in role directives.++  * LaTeX reader:++    + Parse label after caption into a span instead of+     inserting an additional paragraph of bracketed text (#1747).+    + Parse math environments as inline when possible (#1821).+    + Better handling of `\noindent` and `\greektext` (#1783).+    + Handle `\texorpdfstring` more gracefully.+    + Handle `\cref` and `\sep` (Wikiwide).+    + Support `\smartcite` and `\Smartcite` from biblatex.++  * HTML reader:++    + Retain display type of MathML output (#1719, Matthew Pickering).+    + Recognise `<br>` tags inside `<pre>` blocks (#1620, Matthew Pickering).+    + Make `embed` tag either block or inline (#1756).++  * DocBook reader:++    + Handle `keycombo`, `keycap` (#1815).+    + Get string content in inner tags for literal elements (#1816).+    + Handle `menuchoice` elements better, with a `>` between (#1817).+    + Include `id` on section headers (#1818).+    + Document/test "type" as implemented (Brian O'Sullivan).+    + Add support for calloutlist and callout (Brian O'Sullivan).+      We treat a calloutlist as a bulleted list. This works well in practice.+    + Add support for `classname` (Bryan O'Sullivan).++  * Docx reader:++    + Fix window path for image lookup (Jesse Rosenthal).+      Don't use os-sensitive "combine", since we always want the paths in our+      zip-archive to use forward-slashes.+    + Single-item headers in ordered lists are headers (Jesse Rosenthal).+      When users number their headers, Word understands that as a single item+      enumerated list. We make the assumption that such a list is, in fact,+      a header.+    + Rewrite rewriteLink to work with new headers (Jesse Rosenthal).+      There could be new top-level headers after making lists, so we have to+      rewrite links after that.+    + Use polyglot header list (Jesse Rosenthal).+      We're just keeping a list of header formats that different languages+      use as their default styles. At the moment, we have English, German,+      Danish, and French. We can continue to add to this.+      This is simpler than parsing the styles file, and perhaps less+      error-prone, since there seems to be some variations, even within a+      language, of how a style file will define headers.+    + Remove header class properly in other langs (Jesse Rosenthal).+      When we encounter one of the polyglot header styles, we want to remove+      that from the par styles after we convert to a header. To do that, we+      have to keep track of the style name, and remove it appropriately.+    + Account for external link URLs with anchors. Previously, if a URL+      had an anchor, the reader would incorrectly identify it as an+      internal link and return only the anchor as URL. (Caleb McDaniel)+    + Fix for Issue #1692 (i18n styles) (Nikolay Yakimov).++  * Org reader:++    + Added state changing blanklines (Jesse Rosenthal).+      This allows us to emphasize at the beginning of a new paragraph (or, in+      general, after blank lines).+    + Fixed bug with bulleted lists:++        - a+        - b+        * c++      was being parsed as a list, even though an unindented `*`+      should make a heading.  See+      <http://orgmode.org/manual/Plain-lists.html#fn-1>.+    + Org reader: absolute, relative paths in link (#1741, Albert+      Krewinkel). The org reader was too restrictive when parsing links;+      some relative links and links to files given as absolute paths+      were not recognized correctly.+    + Org reader:  allow empty links (jgm/gitit#471, Albert Krewinkel).+      This is important for use in gitit, which uses empty links+      for wikilinks.+    + Respect indent when parsing Org bullet lists (#1650, Timothy+      Humphries).  Fixes issue with top-level bullet list parsing.+    + Fix indent issue for definition lists (Timothy Humphries,+      see #1650, #1698, #1680).+    + Parse multi-inline terms correctly in definition list (#1649,+      Matthew Pickering).+    + Fix rules for emphasis recognition (Albert Krewinkel).+      Things like `/hello,/` or `/hi'/` were falsy recognized as emphasised+      strings.  This is wrong, as `,` and `'` are forbidden border chars and+      may not occur on the inner border of emphasized text.+    + Drop COMMENT document trees (Albert Krewinkel).+      Document trees under a header starting with the word `COMMENT` are+      comment trees and should not be exported.  Those trees are dropped+      silently (#1678).+    + Properly handle links to `file:target` (Albert Krewinkel).+      Org links like `[[file:target][title]]` were not handled correctly,+      parsing the link target verbatim.  The org reader is changed such that+      the leading `file:` is dropped from the link target (see #756, #1812).+    + Parse LaTeX-style MathML entities (#1657, Albert Krewinkel).+      Org supports special symbols which can be included using LaTeX syntax,+      but are actually MathML entities.  Examples for this are+      `\nbsp` (non-breaking space), `\Aacute` (the letter A with accent acute)+      or `\copy` (the copyright sign ©)++  * EPUB reader:++    + URI handling improvements. Now we outsource most of the work to+      `fetchItem'`. Also, do not include queries in file extensions (#1671).++  * LaTeX writer:++    + Use `\texorpdfstring` for section captions when needed (Vaclav Zeman).+    + Handle consecutive linebreaks (#1733).+    + Protect graphics in headers (Jesse Rosenthal).+      Graphics in `\section`/`\subsection` etc titles need to be `\protect`ed.+    + Put `~` before header in list item text (Jesse Rosenthal).+      Because of the built-in line skip, LaTeX can't handle a section header+      as the first element in a list item.+    + Avoid using reserved characters as `\lstinline` delimiters (#1595).+    + Better handling of display math in simple tables (#1754).+      We convert display math to inline math in simple tables,+      since LaTeX can't deal with display math in simple tables.+    + Escape spaces in code (#1694, Bjorn Buckwalter).++  * MediaWiki writer:++    + Fixed links with URL = text. Previously these were rendered as bare+      words, even if the URL was not an absolute URL (#1825).++  * ICML writer:++    + Don't force all citations into footnotes.++  * RTF writer:++    + Add blankline at end of output (#1732, Matthew Pickering).++  * RST writer:++    + Ensure blank line after figure.+    + Avoid exces whitespace after last list item (#1777).+    + Wrap line blocks with spaces before continuations (#1656).+    + Fixed double-rendering of footnotes in RST tables (#1769).++  * DokuWiki writer:++    + Better handling of block quotes. This change ensures that+      multiple paragraph blockquotes are rendered using native `>`+      rather than as HTML (#1738).+    + Fix external images (#1739). Preface relative links with ":",+      absolute URIs without. (Timothy Humphries)++  * HTML writer:++    + Use protocol-relative URL for mathjax.+    + Put newline btw img and caption paragraph.+    + MathML now outputted with tex annotation (#1635, Matthew Pickering).+    + Add support for KaTeX HTML math (#1626, Matthew Pickering).+      This adds `KaTeX` to `HTMLMathMethod` (API change).+    + Don't double render when `email-obfuscation=none` (#1625, Matthew+      Pickering).+    + Make header attributes work outside top level (#1711).+      Previously they only appeared on top level header elements.+      Now they work e.g. in blockquotes.++  * ODT writer:++    + Correctly handle images without extensions (#1729).+    + Strip querystring in ODT write (#1682, Todd Sifleet).++  * FB2 writer:++    + Add newline to output.++  * EPUB writer:++    + Don't add `sourceURL` to absolute URIs (#1669).+    + Don't use unsupported `opf:title-type` for epub2.+    + Include "landmarks" section in nav document for epub3 (#1757).+    + Removed playOrder from navpoint elements in ncx file (#1760).+      These aren't required, and they make manual modification of epubs+      difficult.+    + Extract title even from structured title.+    + Don't include nav node in spine unless `--toc` was requested.+      Previously we included it in the spine with `linear="no"`, leading+      to odd results in some readers (#1593).+    + Fixed absolute URI detection (#1672).+    + Correctly resolve relative URIs (#1671).+    + Use regular page template for `nav.xhtml`, including doctype (#1759).++  * Docx writer:++    + Put docx table captions above tables (#1641, Nikolay Yakimov).+    + Get the page width from the reference docx file, and use+      it to scale images that are too large to fit (Grégory Bataille).+    + Partial fix for #1607 (Nikolay Yakimov). International heading styles+      are inferred based on `<w:name val="heading #">` fallback, if there+      are no en-US "Heading#" styles+    + Look in user data dir for archive `reference.docx`.+    + Renumber header and footer relationships to avoid collisions (Jesse+      Rosenthal). We previously took the old relationship names of the+      headers and footer in secptr. That led to collisions. We now make+      a map of availabl names in the relationships file, and then rename+     in secptr.++  * ConTeXt writer:++    + Add function toLabel (Mark Szepieniec).+      This function can be used to sanitize reference labels so that+      they do not contain any of the illegal characters \#[]",{}%()|= .+      Currently only Links have their labels sanitized, because they+      are the only Elements that use passed labels.++  * `Text.Pandoc.Shared`:++    + Moved import of `toChunks` outside of CPP conditional (#1590).+    + Fix `inDirectory` to reset to the original directory in case+      an exception occurs (Freiric Barral).++  * Templates:++    + LaTeX template: load polyglossia before bibtex (jgm/pandoc-templates#70).+      Thanks to bluebirch.+    + LaTeX template: Added `\VerbatimFootnotes` if there is verbatim in notes+      (#1616).+    + LaTeX template:  Add shorthands=off to babel options (#1648).+    + EPUB, EPUB3 templates: Added `id="cover"` to body of cover page.+      This aids styling, making it possible for example to set 0 margins+      on the title page (#1758).+    + EPUB, EPUB3 templates:  Handle structured metadata on titlepage.+      Previously we just expected 'title', 'subtitle', 'author', 'date'.+      Now we still support those, but also support the format recommended+      for epub metadata in the pandoc README:++            ---+            title:+            - type: main+              text: My Book+            - type: subtitle+              text: An investigation of metadata+            creator:+            - role: author+              text: John Smith+            - role: editor+              text: Sarah Jones+            identifier:+            - scheme: DOI+              text: doi:10.234234.234/33+            publisher:  My Press+            rights:  (c) 2007 John Smith, CC BY-NC+            ...++  * `Text.Pandoc.Templates.getDefaultTemplate`:+    don't fail when called with "fb2" (#1660).++  * `Text.Pandoc.Parsing`:++    + Fixed `inlineMath` so it handles `\text{..}` containing `$`.+      For example: `$x = \text{the $n$th root of $y$}` (#1677).+    + Change `parseFromString` to fail if not all input is consumed.+      (Matthew Pickering)+    + Moved `addWarning` from Markdown reader to `Parsing`, so it can be+      used by more readers (API change, Daniel Bergey).++  * `Text.Pandoc.Pretty`:++    +  Improve performance of `realLength` (Matthew Pickering).+    +  Make CR + BLANKLINE = BLANKLINE. This fixes an extra blank line we+       were getting at the end of markdown fragments (as well as rst, org,+       etc.) (#1705).++  * `Text.Pandoc.MIME`:++    + Add mime type for WebVTT (Jason Ronallo).+    + Changed mime type for `otf` to `application/vnd.ms-opentype` (#1761).+      This is needed for epub3 validation.++  * `Text.Pandoc.MediaBag`:++    + Fix Windows specific path problems (#1597).++  * `Text.Pandoc.Shared`:++    + Make `collapseFilePath` OS-agnostic (Matthew Pickering).++  * Link the test suite using `-threaded`.+    This allows the test suite to be run using `+RTS -N`.++  * Added `network` dependency under `network-uri` flag in test section.++  * Give better error messages when someone tries to convert from+    pdf, doc, odt (#1683).++  * Added `track` to list of tags treated by `--self-contained` (#1664).++pandoc (1.13.1)++  * Fixed `--self-contained` with Windows paths (#1558).+    Previously `C:\foo.js` was being wrongly interpreted as a URI.++  * HTML reader:  improved handling of tags that can be block or inline.+    Previously a section like this would be enclosed in a paragraph,+    with RawInline for the video tags (since video is a tag that can+    be either block or inline):++        <video controls="controls">+           <source src="../videos/test.mp4" type="video/mp4" />+           <source src="../videos/test.webm" type="video/webm" />+           <p>+              The videos can not be played back on your system.<br/>+              Try viewing on Youtube (requires Internet connection):+              <a href="http://youtu.be/etE5urBps_w">Relative Velocity on+        Youtube</a>.+           </p>+        </video>++    This change will cause the video and source tags to be parsed+    as RawBlock instead, giving better output.+    The general change is this:  when we're parsing a "plain" sequence+    of inlines, we don't parse anything that COULD be a block-level tag.++  * Docx reader:++    + Be sensitive to user styles.  Note that "Hyperlink" is+      "blacklisted," as we don't want the default underline styling to be+      inherited by all links by default (Jesse Rosenthal).+    + Read single paragraph in table cell as `Plain` (Jesse Rosenthal).+      This makes to docx reader's native output fit with the way the markdown+      reader understands its markdown output.++  * Textile writer:  Extended the range of cases where native textile+    tables will be used (as opposed to raw HTML):  we now handle any+    alignment type, but only for simple tables with no captions.++  * Txt2Tags reader:++    + Header is now parsed only if standalone flag is set (Matthew Pickering).+    + The header is now parsed as meta information. The first line is the+      `title`, the second is the `author` and third line is the `date`+      (Matthew Pickering).+    + Corrected formatting of `%%mtime` macro (Matthew Pickering).+    + Fixed crash when reading from stdin.++  * EPUB writer:  Don't use page-progression-direction in EPUB2, which+    doesn't support it.  Also, if page-progression-direction not specified+    in metadata, don't include the attribute even in EPUB3; not including it+    is the same as including it with the value "default", as we did before.+    (#1550)++  * Org writer: Accept example lines with indentation at the beginning+    (Calvin Beck).++  * DokuWiki writer:++    + Refactor to use Reader monad (Matthew Pickering).+    + Avoid using raw HTML in table cells; instead, use `\\`+      instead of newlines (Jesse Rosenthal).+    + Properly handle HTML table cell alignments, and use spacing+      to make the tables look prettier (#1566).++  * Docx writer:++    + Bibliography entries get `Bibliography` style (#1559).+    + Implement change tracking (Jesse Rosenthal).++  * LaTeX writer:++    + Fixed a bug that caused a table caption to repeat across all pages+      (Jose Luis Duran).+    + Improved vertical spacing in tables and made it customizable using+      standard lengths set by booktab.  See+      <https://groups.google.com/forum/#!msg/pandoc-discuss/qMu6_5lYy0o/ZAU7lzAIKw0J>+      (Jose Luis Duran).+    + Added `\strut` to fix spacing in multiline tables (Jose Luis Duran).+    + Use `\tabularnewline` instead of `\\` in table cells (Jose Luis Duran).+    + Made horizontal rules more flexible (Jose Luis Duran).++  * Text.Pandoc.MIME:++    + Added `MimeType` (type synonym for `String`) and `getMimeTypeDef`.+      Code cleanups (Artyom Kazak).++  * Templates:++    + LaTeX template: disable microtype protrusion for typewriter font (#1549,+      thanks lemzwerg).++  * Improved OSX build procedure.++  * Added `network-uri` flag, to deal with split of `network-uri` from+    `network`.++  * Fix build dependencies for the `trypandoc` flag, so that they are+    ignored if `trypandoc` flag is set to False (Gabor Pali).++  * Updated README to remove outdated claim that `--self-contained`+    looks in the user data directory for missing files.++pandoc (1.13.0.1)++  * Docx writer:++    + Fixed regression which bungled list numbering (#1544), causing+      all lists to appear as basic ordered lists.+    + Include row width in table rows (Christoffer Ackelman, Viktor Kronvall).+      Added a property to all table rows where the sum of column widths+      is specified in pct (fraction of 5000).  This helps persuade Word+      to lay out the table with the widths we specify.++  * Fixed a bug in Windows 8 which caused pandoc not to find the+    `pandoc-citeproc` filter (#1542).++  * Docx reader: miscellaneous under-the-hood improvements (Jesse Rosenthal).+    Most significantly, the reader now uses Builder, leading to some+    performance improvements.++  * HTML reader:  Parse appropriately styled span as SmallCaps.++  * Markdown writer: don't escape `$`, `^`, `~` when `tex_math_dollars`,+    `superscript`, and `subscript` extensions, respectively, are+    deactivated (#1127).++  * Added `trypandoc` flag to build CGI executable used in the online+    demo.++  * Makefile:  Added 'quick', 'osxpkg' targets.++  * Updated README in templates to indicate templates license.+    The templates are dual-licensed, BSD3 and GPL2+.++pandoc (1.13)++  [new features]++  * Added `docx` as an input format (Jesse Rosenthal).  The docx+    reader includes conversion of native Word equations to pandoc+    LaTeX `Math` elements.  Metadata is taken from paragraphs at the+    beginning of the document with styles `Author`, `Title`, `Subtitle`,+    `Date`, and `Abstract`.++  * Added `epub` as an input format (Matthew Pickering).  The epub+    reader includes conversion of MathML to pandoc LaTeX `Math`+    elements.++  * Added `t2t` (Txt2Tags) as an input format (Matthew Pickering).+    Txt2tags is a lightweight markup format described at+    <http://txt2tags.org/>.++  * Added `dokuwiki` as an output format (Clare Macrae).++  * Added `haddock` as an output format.++  * Added `--extract-media` option to extract media contained in a zip+    container (docx or epub) while adjusting image paths to point to the+    extracted images.++  * Added a new markdown extension, `compact_definition_lists`, that+    restores the syntax for definition lists of pandoc 1.12.x, allowing+    tight definition lists with no blank space between items, and+    disallowing lazy wrapping.  (See below under behavior changes.)++  * Added an extension `epub_html_exts` for parsing HTML in EPUBs.++  * Added extensions `native_spans` and `native_divs` to activate+    parsing of material in HTML span or div tags as Pandoc Span+    inlines or Div blocks.++  * `--trace` now works with the Markdown, HTML, Haddock, EPUB,+    Textile, and MediaWiki readers.  This is an option intended+    for debugging parsing problems; ordinary users should not need+    to use it.++  [behavior changes]++  * Changed behavior of the `markdown_attribute` extension, to bring+    it in line with PHP markdown extra and multimarkdown.  Setting+    `markdown="1"` on an outer tag affects all contained tags,+    recursively, until it is reversed with `markdown="0"` (#1378).++  * Revised markdown definition list syntax (#1429).  Both the reader+    and writer are affected.  This change brings pandoc's definition list+    syntax into alignment with that used in PHP markdown extra and+    multimarkdown (with the exception that pandoc is more flexible about+    the definition markers, allowing tildes as well as colons).  Lazily+    wrapped definitions are now allowed.  Blank space is required+    between list items.  The space before a definition is used to determine+    whether it is a paragraph or a "plain" element.  **WARNING: This change+    may break existing documents!**  Either check your documents for+    definition lists without blank space between items, or use+    `markdown+compact_definition_lists` for the old behavior.++  * `.numberLines` now works in fenced code blocks even if no language+    is given (#1287, jgm/highlighting-kate#40).++  * Improvements to `--filter`:++    + Don't search PATH for a filter with an explicit path.+      This fixed a bug wherein `--filter ./caps.py` would run `caps.py` from+      the system path, even if there was a `caps.py` in the working directory.+    + Respect shebang if filter is executable (#1389).+    + Don't print misleading error message.+      Previously pandoc would say that a filter was not found,+      even in a case where the filter had a syntax error.++  * HTML reader:++    + Parse `div` and `span` elements even without `--parse-raw`,+      provided `native_divs` and `native_spans` extensions are set.+      Motivation:  these now generate native pandoc Div and Span+      elements, not raw HTML.+    + Parse EPUB-specific elements if the `epub_html_exts`+      extension is enabled.  These include `switch`, `footnote`,+      `rearnote`, `noteref`.++  * Org reader:++    + Support for inline LaTeX.  Inline LaTeX is now accepted and parsed by the+      org-mode reader.  Both math symbols (like `\tau`) and LaTeX commands (like+      `\cite{Coffee}`), can be used without any further escaping (Albert+      Krewinkel).++  * Textile reader and writer:++    + The `raw_tex` extension is no longer set by default.  You can+      enable it with `textile+raw_tex`.++  * DocBook reader:++    + Support `equation`, `informalequation`, `inlineequation` elements with+      `mml:math` content.  This is converted into LaTeX and put into a Pandoc+      Math inline.++  * Revised `plain` output, largely following the style of Project+    Gutenberg:++    + Emphasis is rendered with `_underscores_`, strong emphasis+      with ALL CAPS.+    + Headings are rendered differently, with space to set them off,+      not with setext style underlines. Level 1 headers are ALL CAPS.+    + Math is rendered using unicode when possible, but without the+      distracting emphasis markers around variables.+    + Footnotes use a regular `[n]` style.++  * Markdown writer:++    + Horizontal rules are now a line across the whole page.+    + Prettier pipe tables.  Columns are now aligned  (#1323).+    + Respect the `raw_html` extension.  `pandoc -t markdown-raw_html`+      no longer emits any raw HTML, including span and div tags+      generated by Span and Div elements.+    + Use span with style for `SmallCaps` (#1360).++  * HTML writer:++    + Autolinks now have class `uri`, and email autolinks have class+      `email`, so they can be styled.++  * Docx writer:++    + Document formatting is carried over from `reference.docx`.+      This includes margins, page size, page orientation, header,+      and footer, including images in headers and footers.+    + Include abstract (if present) with `Abstract` style (#1451).+    + Include subtitle (if present) with `Subtitle` style, rather+      than tacking it on to the title (#1451).++  * Org writer:++    + Write empty span elements with an id attribute as org anchors.+      For example `Span ("uid",[],[]) []` becomes `<<uid>>`.++  * LaTeX writer:++    + Put table captions above tables, to match the conventional+      standard.  (Previously they appeared below tables.)+    + Use `\(..\)` instead of `$..$` for inline math (#1464).+    + Use `\nolinkurl` in email autolinks.  This allows them to be styled+      using `\urlstyle{tt}`.  Thanks to Ulrike Fischer for the solution.+    + Use `\textquotesingle` for `'` in inline code.  Otherwise we get+      curly quotes in the PDF output (#1364).+    + Use `\footnote<.>{..}` for notes in beamer, so that footnotes+      do not appear before the overlays in which their markers appear+      (#1525).+    + Don't produce a `\label{..}` for a Div or Span element.  Do produce+      a `\hyperdef{..}` (#1519).++  * EPUB writer:++    + If the metadata includes `page-progression-direction` (which can be+      `ltr` or `rtl`, the `page-progression-direction` attribute will+      be set in the EPUB spine (#1455).++  * Custom lua writers:++    + Custom writers now work with `--template`.+    + Removed HTML header scaffolding from `sample.lua`.+    + Made citation information available in lua writers.++  * `--normalize` and `Text.Pandoc.Shared.normalize` now consolidate+    adjacent `RawBlock`s when possible.++  [API changes]++  * Added `Text.Pandoc.Readers.Docx`, exporting `readDocx` (Jesse Rosenthal).++  * Added `Text.Pandoc.Readers.EPUB`, exporting `readEPUB` (Matthew+    Pickering).++  * Added `Text.Pandoc.Readers.Txt2Tags`, exporting `readTxt2Tags` (Matthew+    Pickering).++  * Added `Text.Pandoc.Writers.DokuWiki`, exporting `writeDokuWiki`+    (Clare Macrae).++  * Added `Text.Pandoc.Writers.Haddock`, exporting `writeHaddock`.++  * Added `Text.Pandoc.MediaBag`, exporting `MediaBag`, `lookupMedia`,+    `insertMedia`, `mediaDirectory`, `extractMediaBag`.  The docx and epub+    readers return a pair of a `Pandoc` document and a `MediaBag` with+    the media resources they contain.  This can be extracted using+    `--extract-media`.  Writers that incorporate media (PDF, Docx,+    ODT, EPUB, RTF, or HTML formats with `--self-contained`) will look+    for resources in the `MediaBag` generated by the reader, in addition to+    the file system or web.++  * `Text.Pandoc.Readers.TexMath`: Removed deprecated `readTeXMath`.+    Renamed `readTeXMath'` to `texMathToInlines`.++  * `Text.Pandoc`: Added `Reader` data type (Matthew Pickering).+    `readers` now associates names of readers with `Reader`+     structures.  This allows inclusion of readers, like the docx+     reader, that take binary rather than textual input.++  * `Text.Pandoc.Shared`:++    + Added `capitalize` (Artyom Kazak), and replaced uses of+      `map toUpper` (which give bad results for many languages).+    + Added `collapseFilePath`, which removes intermediate `.` and+      `..` from a path (Matthew Pickering).+    + Added `fetchItem'`, which works like `fetchItem` but searches+      a `MediaBag` before looking on the net or file system.+    + Added `withTempDir`.+    + Added `removeFormatting`.+    + Added `extractSpaces` (from HTML reader) and generalized its type+      so that it can be used by the docx reader (Matthew Pickering).+    + Added `ordNub`.+    + Added `normalizeInlines`, `normalizeBlocks`.+    + `normalize` is now `Pandoc -> Pandoc` instead of+      `Data a :: a -> a`.  Some users may need to change their uses of+      `normalize` to the newly exported `normalizeInlines` or+      `normalizeBlocks`.++  * `Text.Pandoc.Options`:++    + Added `writerMediaBag` to `WriterOptions`.+    + Removed deprecated and no longer used `readerStrict` in+      `ReaderOptions`.  This is handled by `readerExtensions` now.+    + Added `Ext_compact_definition_lists`.+    + Added `Ext_epub_html_exts`.+    + Added `Ext_native_divs` and `Ext_native_spans`.+      This allows users to turn off the default pandoc behavior of+      parsing contents of div and span tags in markdown and HTML+      as native pandoc Div blocks and Span inlines.++  * `Text.Pandoc.Parsing`:++    + Generalized `readWith` to `readWithM` (Matthew Pickering).+    + Export `runParserT` and `Stream` (Matthew Pickering).+    + Added `HasQuoteContext` type class (Matthew Pickering).+    + Generalized types of `mathInline`, `smartPunctuation`, `quoted`,+      `singleQuoted`, `doubleQuoted`, `failIfInQuoteContext`,+      `applyMacros` (Matthew Pickering).+    + Added custom `token` (Matthew Pickering).+    + Added `stateInHtmlBlock` to `ParserState`.  This is used to keep+      track of the ending tag we're waiting for when we're parsing inside+      HTML block tags.+    + Added `stateMarkdownAttribute` to `ParserState`. This is used+      to keep track of whether the markdown attribute has been set in+      an enclosing tag.+    + Generalized type of `registerHeader`, using new type classes+      `HasReaderOptions`, `HasIdentifierList`, `HasHeaderMap` (Matthew+      Pickering).  These allow certain common functions to be reused+      even in parsers that use custom state (instead of `ParserState`),+      such as the MediaWiki reader.+    + Moved `inlineMath`, `displayMath` from Markdown reader to Parsing,+      and generalized their types (Matthew Pickering).++  * `Text.Pandoc.Pretty`:++    + Added `nestle`.+    + Added `blanklines`, which guarantees a certain number of blank lines+      (and no more).++  [bug fixes]++  * Markdown reader:++    + Fixed parsing of indented code in list items.  Indented code+      at the beginning of a list item must be indented eight spaces+      from the margin (or edge of the container), or four spaces+      from the list marker, whichever is greater.+    + Fixed small bug in HTML parsing with `markdown_attribute`, which+      caused incorrect tag nesting for input like+      `<aside markdown="1">*hi*</aside>`.+    + Fixed regression with intraword underscores (#1121).+    + Improved parsing of inline links containing quote characters (#1534).+    + Slight rewrite of `enclosure`/`emphOrStrong` code.+    + Revamped raw HTML block parsing in markdown (#1330).+      We no longer include trailing spaces and newlines in the+      raw blocks.  We look for closing tags for elements (but without+      backtracking).  Each block-level tag is its own `RawBlock`;+      we no longer try to consolidate them (though `--normalize` will do so).+    + Combine consecutive latex environments.  This helps when you have+      two minipages which can't have blank lines between them (#690, #1196).+    + Support smallcaps through span.+      `<span style="font-variant:small-caps;">foo</span>` will be+      parsed as a `SmallCaps` inline, and will work in all output+      formats that support small caps (#1360).+    + Prevent spurious line breaks after list items (#1137).  When the+      `hard_line_breaks` option was specified, pandoc would formerly+      produce a spurious line break after a tight list item.+    + Fixed table parsing bug (#1333).+    + Handle `c++` and `objective-c` as language identifiers in+      github-style fenced blocks (#1318).+    + Inline math must have nonspace before final `$` (#1313).++  * LaTeX reader:++    + Handle comments at the end of tables.  This resolves the issue+      illustrated in <http://stackoverflow.com/questions/24009489>.+    + Correctly handle table rows with too few cells.  LaTeX seems to+      treat them as if they have empty cells at the end  (#241).+    + Handle leading/trailing spaces in `\emph` better.+      `\emph{ hi }` gets parsed as `[Space, Emph [Str "hi"], Space]`+      so that we don't get things like `* hi *` in markdown output.+      Also applies to `\textbf` and some other constructions (#1146).+    + Don't assume preamble doesn't contain environments (#1338).+    + Allow (and discard) optional argument for `\caption` (James Aspnes).++  * HTML reader:++    + Fixed major parsing problem with HTML tables.  Table cells were+      being combined into one cell (#1341).+    + Fixed performance issue with malformed HTML tables.+      We let a `</table>` tag close an open `<tr>` or `<td>` (#1167).+    + Allow space between `<col>` and `</col>`.+    + Added `audio` and `source` in `eitherBlockOrInline`.+    + Moved `video`, `svg`, `progress`, `script`, `noscript`, `svg` from+      `blockTags` to `eitherBlockOrInline`.+    + `map` and `object` were mistakenly in both lists; they have been removed+      from `blockTags`.+    + Ignore `DOCTYPE` and `xml` declarations.++  * MediaWiki reader:++    + Don't parse backslash escapes inside `<source>` (#1445).+    + Tightened up template parsing.+      The opening `{{` must be followed by an alphanumeric or `:`.+      This prevents the exponential slowdown in #1033.+    + Support "Bild" for images.++  * DocBook reader:++    + Better handle elements inside code environments.  Pandoc's document+      model does not allow structure inside code blocks, but at least this way+      we preserve the text (#1449).+    + Support `<?asciidoc-br?>` (#1236).++  * Textile reader:++    + Fixed list parsing. Lists can now start without an intervening+      blank line (#1513).+    + HTML block-level tags that do not start a line are parsed as+      inline HTML and do not interrupt paragraphs (as in RedCloth).++  * Org reader:++    + Make tildes create inline code (#1345).  Also relabeled `code` and+      `verbatim` parsers to accord with the org-mode manual.+    + Respect `:exports` header argument in code blocks (Craig Bosma).+    + Fixed tight lists with sublists (#1437).++  * EPUB writer:++    + Avoid excess whitespace in `nav.xhtml`.  This should improve+      TOC view in iBooks (#1392).+    + Fixed regression on cover image.+      In 1.12.4 and 1.12.4.2, the cover image would not appear properly,+      because the metadata id was not correct.  Now we derive the id from the+      actual cover image filename, which we preserve rather than using+      "cover-image."+    + Keep newlines between block elements.  This allows+      easier diff-ability (#1424).+    + Use `stringify` instead of custom `plainify`.+    + Use `renderTags'` for all tag rendering.  This properly handles tags+      that should be self-closing.  Previously `<hr/>` would appear in EPUB+      output as `<hr></hr>` (#1420).+    + Better handle HTML media tags.+    + Handle multiple dates with OPF `event` attributes.  Note: in EPUB3 we+      can have only one dc:date, so only the first one is used.++  * LaTeX writer:++    + Correctly handle figures in notes.  Notes can't contain figures in+      LaTeX, so we fake it to avoid an error  (#1053).+    + Fixed strikeout + highlighted code (#1294).+      Previously strikeout highlighted code caused an error.++  * ConTeXt writer:++    + Improved detection of autolinks with URLs containing escapes.++  * RTF writer:++    + Improved image embedding: `fetchItem'` is now used to get the+      images, and calculated image sizes are indicated in the RTF.+    + Avoid extra paragraph tags in metadata (#1421).++  * HTML writer:++    + Deactivate "incremental" inside slide speaker notes (#1394).+    + Don't include empty items in the table of contents for+      slide shows.  (These would result from creating a slide+      using a horizontal rule.)++  * MediaWiki writer:++    + Minor renaming of `st` prefixed names.++  * AsciiDoc writer:++    + Double up emphasis and strong emphasis markers in intraword+      contexts, as required by asciidoc (#1441).++  * Markdown writer:++    + Avoid wrapping that might start a list, blockquote, or header (#1013).+    + Use Span instead of (hackish) `SmallCaps` in `plainify`.+    + Don't use braced attributes for fenced code (#1416).+      If `Ext_fenced_code_attributes` is not set, the first class+      attribute will be printed after the opening fence as a bare word.+    + Separate adjacent lists of the same kind with an HTML comment (#1458).++  * PDF writer:++    + Fixed treatment of data uris for images (#1062).++  * Docx writer:++    + Use Compact style for empty table cells (#1353).+      Otherwise we get overly tall lines when there are empty+      table cells and the other cells are compact.+    + Create overrides per-image for `media/` in reference docx.+      This should be somewhat more robust and cover more types of images.+    + Improved `entryFromArchive` to avoid an unneeded parse.+    + Section numbering carries over from reference.docx (#1305).+    + Simplified `abstractNumId` numbering.  Instead of sequential numbering,+      we assign numbers based on the list marker styles.++  * `Text.Pandoc.Options`:++    + Removed `Ext_fenced_code_attributes` from `markdown_github`+      extensions.++  * `Text.Pandoc.ImageSize`:++    + Use default instead of failing if image size not found+      in exif header (#1358).+    + ignore unknown exif header tag rather than crashing.+      Some images seem to have tag type of 256, which was causing+      a runtime error.++  * `Text.Pandoc.Shared`:++    + `fetchItem`:  unescape URI encoding before reading local file (#1427).+    + `fetchItem`:  strip a fragment like `?#iefix` from the extension before+      doing mime lookup, to improve mime type guessing.+    + Improved logic of `fetchItem`:  absolute URIs are fetched from the net;+      other things are treated as relative URIs if `sourceURL` is `Just _`,+      otherwise as file paths on the local file system.+    + `fetchItem` now properly handles links without a protocol (#1477).+    + `fetchItem` now escapes characters not allowed in URIs before trying+      to parse the URIs.+    + Fixed runtime error with `compactify'DL` on certain lists (#1452).++  * `pandoc.hs`: Don't strip path off of `writerSourceURL`: the path is+    needed to resolve relative URLs when we fetch resources (#750).++  * `Text.Pandoc.Parsing`++    + Simplified `dash` and `ellipsis` (#1419).+    + Removed `(>>~)` in favor of the equivalent `(<*)` (Matthew Pickering).+    + Generalized functions to use `ParsecT` (Matthew Pickering).+    + Added `isbn` and `pmid` to list of recognized schemes (Matthew+      Pickering).++  [template changes]++  * Added haddock template.+  * EPUB3:  Added `type` attribute to `link` tags.  They are supposed to+    be "advisory" in HTML5, but kindlegen seems to require them.+  * EPUB3:  Put title page in section with `epub:type="titlepage"`.+  * LaTeX: Made `\subtitle` work properly (#1327).+  * LaTeX/Beamer: remove conditional around date (#1321).+  * LaTeX:  Added `lot` and `lof` variables, which can be set to+    get `\listoftables` and `\listoffigures` (#1407).  Note that+    these variables can be set at the command line with `-Vlot -Vlof`+    or in YAML metadata.++  [under the hood improvements]++  * Rewrote normalize for efficiency (#1385).++  * Rewrote Haddock reader to use `haddock-library` (#1346).++    + This brings pandoc's rendering of haddock markup in line+      with the new haddock.+    + Fixed line breaks in `@` code blocks.+    + alex and happy are no longer build-depends.++  * Added `Text.Pandoc.Compat.Directory` to allow building against+    different versions of the `directory` library.++  + Added `Text.Pandoc.Compat.Except` to allow building against+    different verions of `mtl`.++  * Code cleanup in some writers, using Reader monad to avoid+    passing options parameter around (Matej Kollar).++  * Improved readability in `pandoc.hs`.++  * Miscellaneous code cleanups (Artyom Kazak).++  * Avoid `import Prelude hiding (catch)` (#1309, thanks to Michael+    Thompson).++  * Changed `http-conduit` flag to `https`.  Depend on `http-client`+    and `http-client-tls` instead of `http-conduit`.  (Note:  pandoc still+    depends on `conduit` via `yaml`.)++  * Require `highlighting-kate >= 0.5.8.5` (#1271, #1317, Debian #753299).+    This change to highlighting-kate means that PHP fragments no longer need+    to start with `<?php`.  It also fixes a serious bug causing failures with+    ocaml and fsharp.++  * Require latest `texmath`.  This fixes `\tilde{E}` and allows+    `\left` to be used with `]`, `)` etc. (#1319), among many other+    improvements.++  * Require latest `zip-archive`.  This has fixes for unicode path names.++  * Added tests for plain writer.++  * `Text.Pandoc.Templates`:++    + Fail informatively on template syntax errors.+      With the move from parsec to attoparsec, we lost good error+      reporting.  In fact, since we weren't testing for end of input,+      malformed templates would fail silently.  Here we revert back to+      Parsec for better error messages.+    + Use `ordNub` (#1022).++  * Benchmarks:++    + Made benchmarks compile again (Artyom Kazak).+    + Fixed so that the failure of one benchmark does not prevent others+      from running (Artyom Kazak).+    + Use `nfIO` instead of the `getLength` trick to force full evaluation.+    + Changed benchmark to use only the test suite, so that benchmarks+      run more quickly.++  * Windows build script:++    + Add `-windows` to file name.+    + Use one install command for pandoc, pandoc-citeproc.+    + Force install of pandoc-citeproc.++  * `make_osx_package`:  Call zip file `pandoc-VERSION-osx.zip`.+    The zip should not be named `SOMETHING.pkg.zip`, or OSX finder+    will extract it into a folder named `SOMETHING.pkg`, which it+    will interpret as a defective package (#1308).++  * `README`:++    + Made headers for all extensions so they have IDs and can be+      linked to (Beni Cherniavsky-Paskin).+    + Fixed typos (Phillip Alday).+    + Fixed documentation of attributes (#1315).+    + Clarified documentation on small caps (#1360).+    + Better documentation for `fenced_code_attributes` extension+      (Caleb McDaniel).+    + Documented fact that you can put YAML metadata in a separate file+      (#1412).+++pandoc (1.12.4.2)++  * Require highlighting-kate >= 0.5.8.  Fixes a performance regression.++  * Shared:  `addMetaValue` now behaves slightly differently:+    if both the new and old values are lists, it concatenates their+    contents to form a new list.++  * LaTeX reader:++    + Set `bibliography` in metadata from `\bibliography` or+      `\addbibresource` command.+    + Don't error on `%foo` with no trailing newline.++  * Org reader:++    + Support code block headers (`#+BEGIN_SRC ...`) (Albert Krewinkel).+    + Fix parsing of blank lines within blocks (Albert Krewinkel).+    + Support pandoc citation extension (Albert Krewinkel).  This can+      be turned off by specifying `org-citations` as the input format.++  * Markdown reader:++    + `citeKey` moved to `Text.Pandoc.Parsing` so it can be used by+      other readers (Albert Krewinkel).++  * `Text.Pandoc.Parsing`:++    + Added `citeKey` (see above).+    + Added `HasLastStrPosition` type class and `updateLastStrPos`+      and `notAfterString` functions.++  * Updated copyright notices (Albert Krewinkel).++  * Added default.icml to data files so it installs with the package.++  * OSX package:++    + The binary is now built with options to ensure that it can be+      used with OSX 10.6+.+    + Moved OSX package materials to osx directory.+    + Added OSX package uninstall script, included in the zip container+      (thanks to Daniel T. Staal).++pandoc (1.12.4)++  * Made it possible to run filters that aren't executable (#1096).+    Pandoc first tries to find the executable (searching the path+    if path isn't given).  If it fails, but the file exists and has+    a `.py`, `.pl`, `.rb`, `.hs`, or `.php` extension, pandoc runs the filter+    using the appropriate interpreter.  This should make it easier to+    use filters on Windows, and make it more convenient for everyone.++  * Added Emacs org-mode reader (Albert Krewinkel).++  * Added InDesign ICML Writer (Mauro Bieg).++  * MediaWiki reader:++    + Accept image links in more languages (Jaime Marquínez Ferrándiz).+    + Fixed bug in certain nested lists (#1213).  If a level 2 list was+      followed by a level 1 list, the first item of the level 1 list+      would be lost.+    + Handle table rows containing just an HTML comment (#1230).++  * LaTeX reader:++    + Give better location information on errors, pointing to line+      numbers within included files (#1274).+    + LaTeX reader:  Better handling of `table` environment (#1204).+      Positioning options no longer rendered verbatim.+    + Better handling of figure and table with caption (#1204).+    + Handle `@{}` and `p{length}` in tabular.  The length is not actually+      recorded, but at least we get a table (#1180).+    + Properly handle `\nocite`.  It now adds a `nocite` metadata+      field.  Citations there will appear in the bibliography but not+      in the text (unless you explicitly put a `$nocite$` variable+      in your template).++  * Markdown reader:++    + Ensure that whole numbers in YAML metadata are rendered without+      decimal points.  (This became necessary with changes to aeson+      and yaml libraries.  aeson >= 0.7 and yaml >= 0.8.8.2 are now required.)+    + Fixed regression on line breaks in strict mode (#1203).+    + Small efficiency improvements.+    + Improved parsing of nested `div`s.  Formerly a closing `div` tag+      would be missed if it came right after other block-level tags.+    + Avoid backtracking when closing `</div>` not found.+    + Fixed bug in reference link parsing in `markdown_mmd`.+    + Fixed a bug in list parsing (#1154).  When reading a raw list+      item, we now strip off up to 4 spaces.+    + Fixed parsing of empty reference link definitions (#1186).+    + Made one-column pipe tables work (#1218).++  * Textile reader:++    + Better support for attributes.  Instead of being ignored, attributes+      are now parsed and included in Span inlines.  The output will be a bit+      different from stock textile: e.g. for `*(foo)hi*`, we'll get+      `<em><span class="foo">hi</span></em>` instead of+      `<em class="foo">hi</em>`.  But at least the data is not lost.+    + Improved treatment of HTML spans (%) (#1115).+    + Improved link parsing.  In particular we now pick up on attributes.+      Since pandoc links can't have attributes, we enclose the whole link in+      a span if there are attributes (#1008).+    + Implemented correct parsing rules for inline markup (#1175, Matthew+      Pickering).+    + Use Builder (Matthew Pickering).+    + Fixed list parsing bug (#1500).+    + Don't allow inline formatting to extend over newlines.+      This matches the behavior of RedCarpet, avoids some ugly bugs,+      and improves performance.++  * DocBook reader:++    + Better treatment of `formalpara`.  We now emit the title (if present)+      as a separate paragraph with boldface text (#1215).+    + Set metadata `author` not `authors`.+    + Added recognition of `authorgroup` and `releaseinfo` elements (#1214,+      Matthew Pickering).+    + Converted current meta information parsing in DocBook to a more+      extensible version which is aware of the more recent meta+      representation (Matthew Pickering).++  * HTML reader:++    + Require tagsoup 0.13.1, to fix a bug with parsing of script tags+      (#1248).+    + Treat processing instructions & declarations as block.  Previously+      these were treated as inline, and included in paragraph tags in HTML+      or DocBook output, which is generally not what is wanted (#1233).+    + Updated `closes` with rules from HTML5 spec.+    + Use Builder (Matthew Pickering, #1162).++  * RST reader:++    + Remove duplicate `http` in PEP links (Albert Krewinkel).+    + Make rst figures true figures (#1168, CasperVector)+    + Enhanced Pandoc's support for rST roles (Merijn Verstaaten).+      rST parser now supports: all built-in rST roles, new role definition,+      role inheritance, though with some limitations.+    + Use `author` rather than `authors` in metadata.+    + Better handling of directives.  We now correctly handle field+      lists that are indented more than three spaces.  We treat an+      `aafig` directive as a code block with attributes, so it can be+      processed in a filter (#1212).++  * LaTeX writer:++    + Mark span contents with label if span has an ID (Albert Krewinkel).+    + Made `--toc-depth` work well with books in latex/pdf output (#1210).+    + Handle line breaks in simple table cells (#1217).+    + Workaround for level 4-5 headers in quotes.  These previously produced+      invalid LaTeX: `\paragraph` or `\subparagraph` in a `quote` environment.+      This adds an `mbox{}` in these contexts to work around the problem.+      See <http://tex.stackexchange.com/a/169833/22451> (#1221).+    + Use `\/` to avoid en-dash ligature instead of `-{}-` (Vaclav Zeman).+      This is to fix LuaLaTeX output. The `-{}-` sequence does not avoid the+      ligature with LuaLaTeX but `\/` does.+    + Fixed string escaping in `hyperref` and `hyperdef` (#1130).++  * ConTeXt writer:  Improved autolinks (#1270).++  * DocBook writer:++    + Improve handling of hard line breaks in Docbook writer+      (Neil Mayhew).  Use a `<literallayout>` for the entire paragraph, not+      just for the newline character.+    + Don't let line breaks inside footnotes influence the enclosing+      paragraph (Neil Mayhew).+    + Distinguish tight and loose lists in DocBook output, using+      `spacing="compact"` (Neil Mayhew, #1250).++  * Docx writer:  When needed files are not present in the user's+    `reference.docx`, fall back on the versions in the `reference.docx`+    in pandoc's data files. This fixes a bug that occurs when a+    `reference.docx` saved by LibreOffice is used. (#1185)++  * EPUB writer:++    + Include extension in epub ids.  This fixes a problem with duplicate+      extensions for fonts and images with the same base name but different+      extensions (#1254).+    + Handle files linked in raw `img` tags (#1170).+    + Handle media in `audio` source tags (#1170).+      Note that we now use a `media` directory rather than `images`.+    + Incorporate files linked in `video` tags (#1170).  `src` and `poster`+      will both be incorporated into `content.opf` and the epub container.++  * HTML writer:++    + Add colgroup around col tags (#877).  Also affects EPUB writer.+    + Fixed bug with unnumbered section headings.  Unnumbered section+      headings (with class `unnumbered`) were getting numbers.+    + Improved detection of image links. Previously image links with+      queries were not recognized, causing `<embed>` to be used instead+      of `<img>`.++  * Man writer:  Ensure that terms in definition lists aren't line wrapped+    (#1195).++  * Markdown writer:++    + Use proper escapes to avoid unwanted lists (#980).  Previously we used+      0-width spaces, an ugly hack.+    + Use longer backtick fences if needed (#1206).  If the content contains a+      backtick fence and there are attributes, make sure longer fences are+      used to delimit the code.  Note:  This works well in pandoc, but github+      markdown is more limited, and will interpret the first string of three+      or more backticks as ending the code block.++  * RST writer:  Avoid stack overflow with certain tables (#1197).++  * RTF writer:  Fixed table cells containing paragraphs.++  * Custom writer:++    + Correctly handle UTF-8 in custom lua scripts (#1189).+    + Fix bugs with lua scripts with mixed-case filenames and+      paths containing `+` or `-` (#1267).  Note that `getWriter`+      in `Text.Pandoc` no longer returns a custom writer on input+      `foo.lua`.++  * AsciiDoc writer:  Handle multiblock and empty table cells+    (#1245, #1246).  Added tests.++  * `Text.Pandoc.Options`: Added `readerTrace` to `ReaderOptions`++  * `Text.Pandoc.Shared`:++    + Added `compactify'DL` (formerly in markdown reader) (Albert Krewinkel).+    + Fixed bug in `toRomanNumeral`:  numbers ending with '9' would+      be rendered as Roman numerals ending with 'IXIV' (#1249).  Thanks to+      Jesse Rosenthal.+    + `openURL`: set proxy with value of http_proxy env variable (#1211).+      Note:  proxies with non-root paths are not supported, due to+      limitations in `http-conduit`.++  * `Text.Pandoc.PDF`:++    + Ensure that temp directories deleted on Windows (#1192).  The PDF is+      now read as a strict bytestring, ensuring that process ownership will+      be terminated, so the temp directory can be deleted.+    + Use `/` as path separators in a few places, even on Windows.+      This seems to be necessary for texlive (#1151, thanks to Tim Lin).+    + Use `;` for `TEXINPUTS` separator on Windows (#1151).+    + Changes to error reporting, to handle non-UTF8 error output.++  * `Text.Pandoc.Templates`:++    + Removed unneeded datatype context (Merijn Verstraaten).++    + YAML objects resolve to "true" in conditionals (#1133).+      Note:  If `address` is a YAML object and you just have `$address$`+      in your template, the word `true` will appear, which may be+      unexpected.  (Previously nothing would appear.)++  * `Text.Pandoc.SelfContained`:++    + `mkSelfContained` now takes just two arguments, `WriterOptions` and+      the string.+    * It no longer looks in data files.  This only made sense when we+      had copies of slidy and S5 code there.+    * `fetchItem'` is used instead of the nearly duplicate `getItem`.+    + Handle `poster` attribute in `video` tags (#1188).++  * `Text.Pandoc.Parsing`:++    + Made `F` an instance of Applicative (#1138).+    + Added `stateCaption`.+    + Added `HasMacros`, simplified other typeclasses.+      Removed `updateHeaderMap`, `setHeaderMap`, `getHeaderMap`,+      `updateIdentifierList`, `setIdentifierList`, `getIdentifierList`.+    + Changed the smart punctuation parser to return `Inlines`+      rather than `Inline` (Matthew Pickering).+    + Changed `HasReaderOptions`, `HasHeaderMap`, `HasIdentifierList`+      from typeclasses of monads to typeclasses of states.  This simplifies+      the instance definitions and provides more flexibility.  Generalized+      type of `getOption` and added a default definition.  Removed+      `askReaderOption`.  Added `extractReaderOption`.  Added+      `extractHeaderMap` and `updateHeaderMap` in `HasHeaderMap`.+      Gave default definitions for `getHeaderMap`, `putHeaderMap`,+      `modifyHeaderMap`.  Added `extractIdentifierList` and+      `updateIdentifierList` in `HasIdentifierList`.  Gave defaults+      for `getIdentifierList`, `putIdentifierList`, and+      `modifyIdentifierList`.  The ultimate goal here is to allow different+      parsers to use their own, tailored parser states (instead of+      `ParserState`) while still using shared functions.++  * Template changes:++    + LaTeX template: Use `fontenc` package only with `pdflatex` (#1164).+    + LaTeX template:  Add `linestretch` and `fontfamily` variables.+    + LaTeX template:  Conditionalize author and date commands.+    + Beamer template: Consistent styles for figure and table captions+      (aaronwolen).+    + LaTeX and beamer template:  Adjust widths correctly for oversized+      images.  Use `\setkeys{Gin}{}` to set appropriate defaults for+      `\includegraphics` (Yihui Xie, Garrick Aden-Buie).  Load+      `upquote` only after `fontenc` (Yihui Xie).+    + Beamer template: Added caption package (#1200).+    + Beamer template:  changes for better unicode handling (KarolS).+    + DocBook template:  use `authorgroup` if there are authors.+    + revealjs template: Move `include-after` to end (certainlyakey).+    + revealjs template: Fixed PDF print function (#1220, kevinkenan).++  * Bumped version bounds of dependencies.++  * Added a `--trace` command line option, for debugging backtracking+    bugs.  So far this only works with the markdown reader.++  * MathMLinHTML:  Fixed deprecation warning (#362, gwern, Albert Krewinkel).++  * Updated travis script to test with multiple GHC versions.++  * Force failure of a Travis build if GHC produces warnings (Albert+    Krewinkel).++  * Add `.editorconfig` (Albert Krewinkel).+    See <http://editorconfig.org/> for details.++  * Give more useful error message if '-t pdf' is specified (#1155).++  * Added `Cite`, `SmallCaps` to `Arbitrary` instance (#1269).++  * Allow `html4` as a synonym of `html` as a reader (it already works+    as a writer).++  * README:++    + Added an explanation of how to use YAML metadata to+      force items to appear in the bibliography without citations in+      the text (like LaTeX `\nocite`).+    + Added note to `--bibtex/--natbib`: not for use in making PDF+      (#1194, thanks to nahoj).+    + Added explanatory notes about `--natbib` and `--biblatex`.+    + Added specification of legal syntax for citation keys.+    + Fixed variable defaults documentation (Albert Krewinkel).++  * Removed copyright statements for files that have been removed+    (Albert Krewinkel).++  * Moved some doc files from `data-files` to `extra-source-files` (#1123).+    They aren't needed at runtime.  We keep README and COPYRIGHT in data+    to ensure that they'll be available on all systems on which pandoc+    is installed.++  * Use cabal sandboxes in Windows build script.++pandoc (1.12.3.3)++  * To changes to source; recompiled tarball with latest alex and+    happy, so they will work with GHC 7.8.++pandoc (1.12.3.2)++  * Bumped version bounds for blaze-html, blaze-markup.++  * ImageSize:  Avoid use of lookAhead, which is not in binary >= 0.6+    (#1124).++  * Fixed mediawiki ordered list parsing (#1122).++  * HTML reader:  Fixed bug reading inline math with `$$` (#225).++  * Added support for LaTeX style literate Haskell code blocks in rST+    (Merijn Verstraaten).++pandoc (1.12.3.1)++  * Relaxed version constraint on binary, allowing the use of binary 0.5.++pandoc (1.12.3)++  * The `--bibliography` option now sets the `biblio-files` variable.+    So, if you're using `--natbib` or `--biblatex`, you can just use+    `--bibliography=foo.bib` instead of `-V bibliofiles=foo`.++  * Don't run pandoc-citeproc filter if `--bibliography` is+    used together with `--natbib` or `--biblatex` (Florian Eitel).++  * Template changes:++    + Updated beamer template to include booktabs.+    + Added `abstract` variable to LaTeX template.+    + Put `header-includes` after `title` in LaTeX template (#908).+    + Allow use of `\includegraphics[size]` in beamer.+      This just required porting a macro definition from the default+      LaTeX template to the default beamer template.++  * `reference.docx`:  Include `FootnoteText` style.+    Otherwise Word ignores the style, even when specified in the `pPr`.+    (#901)++  * `reference.odt`:  Tidied `styles.xml`.++  * Relaxed version bounds for dependencies.++  * Added `withSocketsDo` around http conduit code in `openURL`,+    so it works on Windows (#1080).++  * Added `Cite` function to `sample.lua`.++  * Markdown reader:++    + Fixed regression in title blocks (#1089).+      If author field was empty, date was being ignored.+    + Allow backslash-newline hard line breaks in grid and+      multiline table cells.+    + Citation keys may now start with underscores, and may contain+      underscores adjacent to internal punctuation.++  * LaTeX reader:++    + Add support for `Verb` macro (jrnold) (#1090).+    + Support babel-style quoting: `` "`..."' ``.++  * Properly handle script blocks in strict mode.  (That is,+    `markdown-markdown_in_html_blocks`.) Previously a spurious+    `<p>` tag was being added (#1093).++  * Docbook reader: Avoid failure if `tbody` contains no `tr` or `row`+    elements.++  * LaTeX writer:++    + Factored out function for table cell creation.+    + Better treatment of footnotes in tables.+      Notes now appear in the regular sequence, rather than in the+      table cell.  (This was a regression in 1.10.)++  * HTML reader: Parse name/content pairs from meta tags as metadata.+    Closes #1106.++  * Moved `fixDisplayMath` from Docx writer to `Writer.Shared`.++  * OpenDocument writer:  Fixed `RawInline`, `RawBlock` so they don't escape.++  * ODT writer:  Use mathml for proper rendering of formulas.+    Note:  LibreOffice's support for this seems a bit buggy.  But+    it should be better than what we had before.++  * RST writer: Ensure no blank line after def in definition list (#992).++  * Markdown writer: Don't use tilde code blocks with braced attributes in+    `markdown_github` output.  A consequence of this change is that the+    backtick form will be preferred in general if both are enabled.  That+    is good, as it is much more widespread than the tilde form.  (#1084)++  * Docx writer:  Fixed problem with some modified reference docx files.+    Include `word/_rels/settings.xml.rels` if it exists, as well as other+    `rels` files besides the ones pandoc generates explicitly.++  * HTML writer:++    + With `--toc`, headers no longer link to themselves (#1081).+    + Omit footnotes from TOC entries.  Otherwise we get doubled+      footnotes when headers have notes!++  * EPUB writer:++    + Avoid duplicate notes when headings contain notes.+      This arose because the headings are copied into the metadata+      "title" field, and the note gets rendered twice.  We strip the+      note now before putting the heading in "title".+    + Strip out footnotes from toc entries.+    + Fixed bug with `--epub-stylesheet`.  Now the contents of+      `writerEpubStylesheet` (set by `--epub-stylesheet`)+      should again work, and take precedence over a stylesheet specified+      in the metadata.++  * `Text.Pandoc.MIME`: Added `wmf`, `emf`.++  * `Text.Pandoc.Shared`:  `fetchItem` now handles image URLs beginning+    with `//`.++  * `Text.Pandoc.ImageSize`:  Parse EXIF format JPEGs.  Previously+    we could only get size information for JFIF format, which led+    to squished images in Word documents. Closes #976.++  * Removed old `MarkdownTest_1.0.3` directory (#1104).++pandoc (1.12.2.1)++  * Markdown reader:  Fixed regression in list parser, involving+    continuation lines containing raw HTML (or even verbatim raw HTML).++pandoc (1.12.2)++  * Metadata may now be included in YAML blocks in a markdown document.+    For example,++        ---+        title:+        - type: main+          text: My Book+        - type: subtitle+          text: An investigation of metadata+        creator:+        - role: author+          text: John Smith+        - role: editor+          text: Sarah Jones+        identifier:+        - scheme: DOI+          text: doi:10.234234.234/33+        publisher:  My Press+        rights:  (c) 2007 John Smith, CC BY-NC+        cover-image: img/mypic.jpg+        ...++    Metadata may still be provided using `--epub-metadata`; it will+    be merged with the metadata in YAML blocks.++  * EPUB writer:++    + `meta` tags are now used instead of `opf` attributes for EPUB3.+    + Insert "svg" property as needed in opf (EPUB 3).+    + Simplify `imageTypeOf` using `getMimeType`.+    + Add properties attribute to `cover-image` item for EPUB 3.+    + Don't include node for `cover.xhtml` if no cover!+    + Ensure that same identifier is used throughout (#1044).+      If an identifier is given in metadata, we use that; otherwise+      we generate a random uuid.+    + Add cover reference to guide element (EPUB 2) (Shaun Attfield).+      Fixes an issue with Calibre putting the cover at the end of the book+      if the spine has `linear="no"`.  Apparently this is best practice+      for other converters as well:+      <http://www.idpf.org/epub/20/spec/OPF_2.0.1_draft.htm#Section2.6>.+    + Allow `stylesheet` in metadata.  The value is a path to the stylesheet.+    + Allow partial dates:  `YYYY`, `YYYY-MM`.++  * Markdown writer:  Fix rendering of tight sublists (#1050).+    Previously a spurious blank line was included after a tight sublist.++  * ODT writer:  Add `draw:name` attribute to `draw:frame` elements (#1069).+    This is reported to be necessary to avoid an error from recent+    versions of Libre Office when files contain more than one image+    Thanks to wmanley for reporting and diagnosing the problem.++  * ConTeXt writer:  Don't hardcode figure/table placement and numbering.+    Instead, let this be set in the template, using `\setupfloat`.+    Thanks to on4aa and Aditya Mahajan for the suggestion (#1067).++  * Implemented CSL flipflopping spans in DOCX, LaTeX, and HTML writers.++  * Fixed bug with markdown intraword emphasis.  Closes #1066.++  * Docbook writer:  Hierarchicalize block content in metadata.+    Previously headers just disappeared from block-level metadata+    when it was used in templates.  Now we apply the 'hierarchicalize'+    transformation.  Note that a block headed by a level-2 header will+    turn into a `<sect1>` element.++  * OpenDocument writer:  Skip raw HTML (#1035).+    Previously it was erroneously included as verbatim text.++  * HTML/EPUB writer, footnotes:  Put `<sup>` tag inside `<a>` tags.+    This allows better control of formatting, since the `<a>`+    tags have a distinguishing class (#1049).++  * Docx writer:++    + Use mime type info returned by fetchItem.+    + Fixed core metadata (#1046).+      Don't create empty date nodes if no date given.+      Don't create multiple `dc:creator` nodes; instead separate by+      semicolons.+    + Fix URL for core-properties in `_rels/.rels` (#1046).++  * Plain writer: don't print `<span>` tags.++  * LaTeX writer:++    + Fix definition lists with internal links in terms (#1032).+      This fix puts braces around a term that contains an internal+      link, to avoid problems with square brackets.+    + Properly escape pdftitle, pdfauthor (#1059).+    + Use booktabs package for tables (thanks to Jose Luis Duran).++  * Updated beamer template.  Now references should work properly+    (in a slide) when `--biblatex` or `--natbib` is used.++  * LaTeX reader:++    + Parse contents of curly quotes or matched `"` as quotes.+    + Support `\textnormal` as span with class `nodecor`.+      This is needed for pandoc-citeproc.+    + Improved citation parsing.  This fixes a run-time error that occured+      with `\citet{}` (empty list of keys).  It also ensures that empty keys+      don't get produced.++  * MediaWiki reader:  Add automatic header identifiers.++  * HTML reader:++    + Use pandoc `Div` and `Span` for raw `<div>`, `<span>` when+      `--parse-raw`.+    + Recognize `svg` tags as block level content (thanks to MinRK).+    + Parse LaTeX math if appropriate options are set.++  * Markdown reader:++    + Yaml block must start immediately after `---`.  If there's a blank+      line after `---`, we interpreted it as a horizontal rule.+    + Correctly handle empty bullet list items.+    + Stop parsing "list lines" when we hit a block tag.+      This fixes exponential slowdown in certain input, e.g.+      a series of lists followed by `</div>`.++  * Slides:  Preserve `<div class="references">` in references slide.++  * `Text.Pandoc.Writer.Shared`:++    + Fixed bug in `tagWithAttrs`.  A space was omitted before key-value+      attributes, leading to invalid HTML.+    + `normalizeDate`: Allow dates with year only (thanks to Shaun Attfield).+    + Fixed bug in `openURL` with `data:` URIs.  Previously the base-64+      encoded bytestring was returned.  We now decode it so it's a proper+      image!++  * DocBook reader:  Handle numerical attributes starting with decimal.+    Also use `safeRead` instead of `read`.++  * `Text.Pandoc.Readers.TexMath`: Export `readTeXMath'`, which attends+    to display/inline.  Deprecate `readTeXMath`, and use `readTeXMath'`+    in all the writers.  Require `texmath >= 0.6.5.2`.++  * `Text.Pandoc.MIME`:++    + Add entry for `jfif`.+    + In looking up extensions, drop the encoding info.+      E.g. for 'image/jpg;base64' we should lookup 'image/jpg'.++  * Templates:  Changed how array variables are resolved.  Previously if+    `foo` is an array (which might be because multiple values were set on+    the command line), `$foo$` would resolve to the concatenation of the+    elements of foo.  This is rarely useful behavior.  It has been changed+    so that the first value is rendered.  Of course, you can still iterate+    over the values using `$for(foo)$`.  This has the result that you can+    override earlier settings using `-V` by putting new values later on the+    command line, which is useful for many purposes.++  * `Text.Pandoc`:  Don't default to `pandocExtensions` for all writers.++  * Allow "epub2" as synonym for "epub", "html4" for "html".++  * Don't look for slidy files in data files with `--self-contained`.++  * Allow `https:` command line arguments to be downloaded.++  * Fixed `make_osx_package.sh` so data files embedded in `pandoc-citeproc`.++pandoc (1.12.1)++  * `Text.Pandoc.Definition`:  Changed default JSON serialization format.+    Instead of `{"Str": "foo"}`, for example, we now have `{"t": "Str",+    "c": "foo"}`.  This new format is easier to work with outside of Haskell.+    Incidentally, "t" stands for "tag", "c" for "contents".++  * MediaWiki reader: Trim contents of `<math>` tags, to avoid problems+    when converting to markdown (#1027).++  * LaTeX reader:++    + Ensure that preamble doesn't contribute to the text of+      the document.+    + Fixed character escaping in \url{}.  Previously `\~` wasn't handled+      properly, among others.+    + Parse `{groups}` as `Span`.  This is needed for accurate conversion of+      bibtex titles, since we need to know what was protected from+      titlecase conversions.++  * LaTeX writer:++    + Specially escape non-ascii characters in labels.+      Otherwise we can get compile errors and other bugs when+      compiled with pdflatex (#1007).  Thanks to begemotv2718 for the fix.+    + Add link anchors for code blocks with identifiers (#1025).++  * Throughout the code, use `isURI` instead of `isAbsoluteURI`.+    It allows fragments identifiers.++  * Slide formats:++    + A Div element with class "notes" is treated as speaker+      notes.  Currently beamer goes to `\note{}`, revealjs to+      `<aside class="notes">`, and the notes are simply suppressed in+      other formats  (#925).+    + Fixed `. . .` (pause) on HTML slide formats.  Closes #1029.+      The old version caused a pause to be inserted before the first+      material on a slide. This has been fixed.+    + Removed data files for s5, slideous, slidy.+      Users of s5 and slideous will have to download the needed+      files, as has been documented for some time in the README.+      By default, slidy code will be sought on the web, as before.++  * HTML writer: Insert command to typeset mathjax only in slideous output+    (#966, #1012).++  * RST writer:  Skip spaces after display math.  Otherwise we get indentation+    problems, and part of the next paragraph may be rendered as part of the+    math.++  * OpenDocument writer:  Fix formatting of strikeout code (#995),+    thanks to wilx.  don't use `font-face-decls` variable.++  * Fixed test suite so it works with cabal sandboxes.++pandoc (1.12.0.2)++  * Removed `stringable` dependency.++pandoc (1.12.0.1)++  * Allow `--metadata` to be repeated for the same key to form a list.+    This also has the effect that `--bibliography` can be repeated,+    as before.++  * Handle boolean values in `--metadata`.  Note that anything not parseable+    as a YAML boolean or string is treated as a literal string.+    You can get a string value with "yes", or any of the strings interpretable+    as booleans, by quoting it:++        -M boolvalue=yes -M stringvalue='"yes"'++  * LaTeX writer: Don't print references if `--natbib` or `--biblatex`+    option used.++  * DOCX writer: Add `settings.xml` to the zip container.  Fixes a bug+    in which docx files could not be read by some versions of Word+    and LibreOffice (#990).++  * Fixed a regression involving slide shows with bibliographies.+    The Div container around references messed up the procedure for carving+    a document into slides.  So we now remove the surrounding Div in+    `prepSlides`.++  * More informative error message when a filter is not found in path.++  * Depend on pandoc-types 1.12.1.  This provide `ToJSONFilter`+    instances for `Data a => a -> [a]` and `Data a => a -> IO [a]`.++  * Don't use unicode_collation in building OSX package:+    it adds something like 50MB of dependencies to the package.++  * Declare alex and happy as build-tools (#986).++pandoc (1.12)++  [new features]++  * Much more flexible metadata, including arbitrary fields and structured+    values.  Metadata can be specified flexibly in pandoc markdown using+    YAML metadata blocks, which may occur anywhere in the document:++        ---+        title: Here is my title.+        abstract: |+          This is the abstract.++          1. It can contain+          2. block content+             and *inline markup*++        tags: [cat, dog, animal]+        ...++    Metadata fields automatically populate template variables.++  * Added `opml` (OPML) as input and output format.  The `_note` attribute,+    used in OmniOutliner and supported by multimarkdown, is supported.+    We treat the contents as markdown blocks under a section header.++  * Added `haddock` (Haddock markup) as input format (David Lazar).++  * Added `revealjs` output format, for reveal.js HTML 5 slide shows.+    (Thanks to Jamie F. Olson for the initial patch.)+    Nested vertical stacks are used for hierarchical structure.+    Results for more than one level of nesting may be odd.++  * Custom writers can now be written in lua.++        pandoc -t data/sample.lua++    will load the script sample.lua and use it as a custom writer.+    (For a sample, do `pandoc --print-default-data-file sample.lua`.)+    Note that pandoc embeds a lua interpreter, so lua need not be+    installed separately.++  * New `--filter/-F` option to make it easier to run "filters"+    (Pandoc AST transformations that operate on JSON serializations).+    Filters are always passed the name of the output format, so their+    behavior can be tailored to it.  The repository+    <https://github.com/jgm/pandocfilters> contains+    a python module for writing pandoc filters in python, with+    a number of examples.++  * Added `--metadata/-M` option.+    This is like `--variable/-V`, but actually adds to metadata, not+    just variables.++  * Added `--print-default-data-file` option, which allows printing+    of any of pandoc's data files. (For example,+    `pandoc --print-default-data-file reference.odt` will print+    `reference.odt`.)++  * Added syntax for "pauses" in slide shows:++        This gives++        . . .++        me pause.++  * New markdown extensions:++    + `ignore_line_breaks`:  causes intra-paragraph line breaks to be ignored,+      rather than being treated as hard line breaks or spaces.  This is useful+      for some East Asian languages, where spaces aren't used between words,+      but text is separated into lines for readability.+    + `yaml_metadata_block`:  Parse YAML metadata blocks.  (Default.)+    + `ascii_identifiers`: This will force `auto_identifiers` to use ASCII+       only. (Default for `markdown_github`.) (#807)+    + `lists_without_preceding_blankline`:  Allow lists to start without+      preceding blank space.  (Default for `markdown_github`.) (#972)++  [behavior changes]++  * `--toc-level` no longer implies `--toc`.+    Reason: EPUB users who don't want a visible TOC may still want+    to set the TOC level for in the book navigation.++  * `--help` now prints in and out formats in alphabetical order, and+    says something about PDF output (#720).++  * `--self-contained` now returns less verbose output (telling you+    which URLs it is fetching, but not giving the full header).  In+    addition, there are better error messages when fetching a URL fails.++  * Citation support is no longer baked in to core pandoc. Users who+    need citations will need to install and use a separate filter+    (`--filter pandoc-citeproc`).  This filter will take `bibliography`,+    `csl`, and `citation-abbreviations` from the metadata, though it+    may still be specified on the command line as before.++  * A `Cite` element is now created in parsing markdown whether or not+    there is a matching reference.++  * The `pandoc-citeproc` script will put the bibliography at the+    end of the document, as before.  However, it will be put inside a `Div`+    element with class "references", allowing users some control+    over the styling of references.  A final header, if any, will+    be included in the `Div`.++  * The markdown writer will not print a bibliography if the+    `citations` extension is enabled.  (If the citations are formatted+    as markdown citations, it is redundant to have a bibliography,+    since one will be generated automatically.)++  * Previously we used to store the directory of the first input file,+    even if it was local, and used this as a base directory for finding+    images in ODT, EPUB, Docx, and PDF.  This has been confusing to many+    users.  So we now look for images relative to the current+    working directory, even if the first file argument is in another+    directory.   Note that this change may break some existing workflows.+    If you have been assuming that relative links will be interpreted+    relative to the directory of the first file argument, you'll need+    to make that the current directory before running pandoc. (#942)++  * Better error reporting in some readers, due to changes in `readWith`:+    the line in which the error occured is printed, with a caret pointing+    to the column.++  * All slide formats now support incremental slide view for definition lists.++  * Parse `\(..\)` and `\[..\]` as math in MediaWiki reader.+    Parse `:<math>...</math>` as display math.  These notations are used with+    the MathJax MediaWiki extension.++  * All writers: template variables are set automatically from metadata+    fields.  However, variables specified on the command line with+    `--variable` will completely shadow metadata fields.++  * If `--variable` is used to set many variables with the same name,+    a list is created.++  * Man writer:  The `title`, `section`, `header`, and `footer` can now+    all be set individually in metadata.  The `description` variable has been+    removed.  Quotes have been added so that spaces are allowed in the+    title.  If you have a title that begins++        COMMAND(1) footer here | header here++    pandoc will still parse it into a title, section, header, and+    footer.  But you can also specify these elements explicitly (#885).++  * Markdown reader++    + Added support for YAML metadata blocks, which can come anywhere+      in the document (not just at the beginning).  A document can contain+      multiple YAML metadata blocks.+    + HTML span and div tags are parsed as pandoc Span and Div elements.++  * Markdown writer++    + Allow simple tables to be printed as grid tables,+      if other table options are disabled.  This means you can do+      `pandoc -t markdown-pipe_tables-simple_tables-multiline_tables`+      and all tables will render as grid tables.+    + Support YAML title block (render fields in alphabetical order+      to make output predictable).++  [API changes]++  * `Meta` in `Text.Pandoc.Definition` has been changed to allow+    structured metadata.  (Note:  existing code that pattern-matches+    on `Meta` will have to be revised.)  Metadata can now contain+    indefinitely many fields, with content that can be a string,+    a Boolean, a list of `Inline` elements, a list of `Block`+    elements, or a map or list of these.++  * A new generic block container (`Div`) has been added to `Block`,+    and a generic inline container (`Span`) has been added to `Inline`.+    These can take attributes.  They will render in HTML, Textile,+    MediaWiki, Org, RST and and Markdown (with `markdown_in_html`+    extension) as HTML `<div>` and `<span>` elements; in other formats+    they will simply pass through their contents.  But they can be+    targeted by scripts.++  * `Format` is now a newtype, not an alias for String.+    Equality comparisons are case-insensitive.++  * Added `Text.Pandoc.Walk`, which exports hand-written tree-walking+    functions that are much faster than the SYB functions from+    `Text.Pandoc.Generic`.  These functions are now used where possible+    in pandoc's code.  (`Tests.Walk` verifies that `walk` and `query`+    match the generic traversals `bottomUp` and `queryWith`.)++  * Added `Text.Pandoc.JSON`, which provides `ToJSON` and `FromJSON`+    instances for the basic pandoc types. They use GHC generics and+    should be faster than the old JSON serialization using+    `Data.Aeson.Generic`.++  * Added `Text.Pandoc.Process`, exporting `pipeProcess`.+    This is a souped-up version of `readProcessWithErrorcode` that+    uses lazy bytestrings instead of strings and allows setting+    environment variables.  (Used in `Text.Pandoc.PDF`.)++  * New module `Text.Pandoc.Readers.OPML`.++  * New module `Text.Pandoc.Writers.OPML`.++  * New module `Text.Pandoc.Readers.Haddock` (David Lazar).+    This is based on Haddock's own lexer/parser.++  * New module `Text.Pandoc.Writers.Custom`.++  * In `Text.Pandoc.Shared`, `openURL` and `fetchItem` now return an+    Either, for better error handling.++  * Made `stringify` polymorphic in `Text.Pandoc.Shared`.++  * Removed `stripTags` from `Text.Pandoc.XML`.++  * `Text.Pandoc.Templates`:++    + Simplified `Template` type to a newtype.+    + Removed `Empty`.+    + Changed type of `renderTemplate`: it now takes a JSON context+      and a compiled template.+    + Export `compileTemplate`.+    + Export `renderTemplate'` that takes a string instead of a compiled+      template.+    + Export `varListToJSON`.++  * `Text.Pandoc.PDF` exports `makePDF` instead of `tex2pdf`.+    The signature of `makePDF` has changed and now contains+    an additional argument for pdf engine options.++  * `Text.Pandoc`:++    + Made `toJsonFilter` an alias for `toJSONFilter` from `Text.Pandoc.JSON`.+    + Removed `ToJsonFilter` typeclass.  `ToJSONFilter` from+      `Text.Pandoc.JSON` should be used instead.  (Compiling against+      pandoc-types instead of pandoc will also produce smaller executables.)+    * Removed the deprecated `jsonFilter` function.+    + Added `readJSON`, `writeJSON` to the API (#817).++  * `Text.Pandoc.Options`:++    + Added `Ext_lists_without_preceding_blankline`,+      `Ext_ascii_identifiers`, `Ext_ignore_line_breaks`,+      `Ext_yaml_metadataBlock` to `Extension`.+    + Changed `writerSourceDirectory` to `writerSourceURL` and changed the+      type to a `Maybe`.  `writerSourceURL` is set to 'Just url' when the+      first command-line argument is an absolute URL.  (So, relative links+      will be resolved in relation to the first page.)  Otherwise, 'Nothing'.+    + All bibliography-related fields have been removed from+      `ReaderOptions` and `WriterOptions`: `writerBiblioFiles`,+      `readerReferences`, `readerCitationStyle`.+    + Removed `writerPdfArgs` from `WriterOptions`.  These are now+      passed in as a parameter to `makePDF`.++  * The `Text.Pandoc.Biblio` module has been removed.  Users of the+    pandoc library who want citation support will need to use+    `Text.CSL.Pandoc` from `pandoc-citeproc`.+++  [bug fixes]++  * In markdown, don't autolink a bare URI that is followed by `</a>`+    (#937).++  * `Text.Pandoc.Shared`++    + `openURL` now follows redirects (#701), properly handles `data:`+      URIs, and prints diagnostic output to stderr rather than stdout.+    + `readDefaultDataFile`: normalize the paths.  This fixes bugs in+      `--self-contained` on pandoc compiled with `embed_data_files` (#833).+    + Fixed `readDefaultDataFile` so it works on Windows.+    + Better error messages for `readDefaultDataFile`.  Instead of+      listing the last path tried, which can confuse people who are+      using `--self-contained`, so now we just list the data file name.+    + URL-escape pipe characters.  Even though these are legal, `Network.URI`+      doesn't regard them as legal in URLs.  So we escape them first (#535).++  * Mathjax in HTML slide shows:  include explicit "Typeset" call.+    This seems to be needed for some formats (e.g. slideous) and won't+    hurt in others (#966).++  * `Text.Pandoc.PDF`++    + On Windows, create temdir in working directory, since the system+      temp directory path may contain tildes, which can cause+      problems in LaTeX (#777).+    + Put temporary output directory in `TEXINPUTS` (see #917).+    + `makePDF` tries to download images that are not found locally,+      if the first argument is a URL (#917).+    + If compiling with `pdflatex` yields an encoding error, offer+      the suggestion to use `--latex-engine=xelatex`.++  * Produce automatic header identifiers in parsing textile, RST,+    and LaTeX, unless `auto_identifiers` extension is disabled (#967).++  * `Text.Pandoc.SelfContained`:  Strip off fragment, query of relative URL+     before treating as a filename.  This fixes `--self-contained` when used+     with CSS files that include web fonts using the method described here:+      <http://paulirish.com/2009/bulletproof-font-face-implementation-syntax/>+      (#739).  Handle `src` in `embed`, `audio`, `source`, `input` tags.++  * `Text.Pandoc.Parsing`: `uri` parser no longer treats punctuation before+    percent-encoding, or a `+` character, as final punctuation.++  * `Text.Pandoc.ImageSize`:  Handle EPS (#903).  This change will make+    EPS images properly sized on conversion to Word.++  * Slidy:  Use slidy.js rather than slidy.js.gz.+    Reason:  some browsers have trouble with the gzipped js file,+    at least on the local file system (#795).++  * Markdown reader++    + Properly handle blank line at beginning of input (#882).+    + Fixed bug in unmatched reference links.  The input+      `[*infile*] [*outfile*]` was getting improperly parsed:+      "infile" was emphasized, but "*outfile*" was literal (#883).+    + Allow internal `+` in citation identifiers (#856).+    + Allow `.` or `)` after `#` in ATX headers if no `fancy_lists`.+    + Do not generate blank title, author, or date metadata elements.+      Leave these out entirely if they aren't present.+    + Allow backtick code blocks not to be preceded by blank line (#975).++  * Textile reader:++    + Correctly handle entities.+    + Improved handling of `<pre>` blocks (#927). Remove internal HTML tags+      in code blocks, rather than printing them verbatim. Parse attributes+      on `<pre>` tag for code blocks.++  * HTML reader: Handle non-simple tables (#893).  Column widths are read from+    `col` tags if present, otherwise divided equally.++  * LaTeX reader++    + Support alltt environment (#892).+    + Support `\textasciitilde`, `\textasciicircum` (#810).+    + Treat `\textsl` as emphasized text reader (#850).+    + Skip positional options after `\begin{figure}`.+    + Support `\v{}` for hacek (#926).+    + Don't add spurious ", " to citation suffixes.+      This is added when needed in pandoc-citeproc.+    + Allow spaces in alignment spec in tables, e.g. `{ l r c }`.+    + Improved support for accented characters (thanks to Scott Morrison).+    + Parse label after section command and set id (#951).++  * RST reader:++    + Don't insert paragraphs where docutils doesn't.+      `rst2html` doesn't add `<p>` tags to list items (even when they are+      separated by blank lines) unless there are multiple paragraphs in the+      list.  This commit changes the RST reader to conform more closely to+      what docutils does (#880).+    + Improved metadata.  Treat initial field list as metadata when+      standalone specified.  Previously ALL fields "title", "author",+      "date" in field lists were treated as metadata, even if not at+      the beginning.  Use `subtitle` metadata field for subtitle.+    + Fixed 'authors' metadata parsing in reST.  Semicolons separate+      different authors.++  * MediaWiki reader++    + Allow space before table rows.+    + Fixed regression for `<ref>URL</ref>`.+      `<` is no longer allowed in URLs, according to the uri parser+      in `Text.Pandoc.Parsing`.  Added a test case.+    + Correctly handle indented preformatted text without preceding+      or following blank line.+    + Fixed `|` links inside table cells.  Improved attribute parsing.+    + Skip attributes on table rows.  Previously we just crashed if+      rows had attributes, now we ignore them.+    + Ignore attributes on headers.+    + Allow `Image:` for images (#971).+    + Parse an image with caption in a paragraph by itself as a figure.++  * LaTeX writer++    + Don't use ligatures in escaping inline code.+    + Fixed footnote numbers in LaTeX/PDF tables.  This fixes a bug+      wherein notes were numbered incorrectly in tables (#827).+    + Always create labels for sections.  Previously the labels were only+      created when there were links to the section in the document (#871).+    + Stop escaping `|` in LaTeX math.+      This caused problems with array environments (#891).+    + Change `\` to `/` in paths.  `/` works even on Windows in LaTeX.+      `\` will cause major problems if unescaped.+    + Write id for code block to label attribute in LaTeX when listings+      is used (thanks to Florian Eitel).+    + Scale LaTeX tables so they don't exceed columnwidth.+    + Avoid problem with footnotes in unnumbered headers (#940).++  * Beamer writer: when creating beamer slides, add `allowframebreaks` option+      to the slide if it is one of the header classes.  It is recommended+      that your bibliography slide have this attribute:++        # References {.allowframebreaks}++    This causes multiple slides to be created if necessary, depending+    on the length of the bibliography.++  * ConTeXt writer: Properly handle tables without captions.  The old output+    only worked in MkII. This should work in MkIV as well (#837).++  * MediaWiki writer: Use native mediawiki tables instead of HTML (#720).++  * HTML writer:++    + Fixed `--no-highlight` (Alexander Kondratskiy).+    + Don't convert to lowercase in email obfuscation (#839).+    + Ensure proper escaping in `<title>` and `<meta>` fields.++  * AsciiDoc writer:++    + Support `--atx-headers` (Max Rydahl Andersen).+    + Don't print empty identifier blocks `([[]])` on headers (Max+      Rydahl Andersen).++  * ODT writer:++    + Fixing wrong numbered-list indentation in open document format+      (Alexander Kondratskiy) (#369).+    + `reference.odt`: Added pandoc as "generator" in `meta.xml`.+    + Minor changes for ODF 1.2 conformance (#939). We leave the+      nonconforming `contextual-spacing` attribute, which is provided by+      LibreOffice itself and seems well supported.++  * Docx writer:++    + Fixed rendering of display math in lists.+      In 1.11 and 1.11.1, display math in lists rendered as a new list+      item.  Now it always appears centered, just as outside of lists,+      and in proper display math style, no matter how far indented the+      containing list item is (#784).+    + Use `w:br` with `w:type` `textWrapping` for linebreaks.+      Previously we used `w:cr` (#873).+    + Use Compact style for Plain block elements, to+      differentiate between tight and loose lists (#775).+    + Ignore most components of `reference.docx`.+      We take the `word/styles.xml`, `docProps/app.xml`,+      `word/theme/theme1.xml`, and `word/fontTable.xml` from+      `reference.docx`, ignoring everything else.  This should help+      with the corruption problems caused when different versions of+      Word resave the reference.docx and reorganize things.+    +  Made `--no-highlight` work properly.++  * EPUB writer++    + Don't add `dc:creator` tags if present in EPUB metadata.+    + Add `id="toc-title"` to `h1` in `nav.xhtml` (#799).+    + Don't put blank title page in reading sequence.+      Set `linear="no"` if no title block.  Addresses #797.+    + Download webtex images and include as data URLs.+      This allows you to use `--webtex` in creating EPUBs.+      Math with `--webtex` is automatically made self-contained.+    + In `data/epub.css`, removed highlighting styles (which+      are no longer needed, since styles are added by the HTML+      writer according to `--highlighting-style`).  Simplified+      margin fields.+    + If resource not found, skip it, as in Docx writer (#916).++  * RTF writer:++    + Properly handle characters above the 0000-FFFF range.+      Uses surrogate pairs.  Thanks to Hiromi Ishii for the patch.+    + Fixed regression with RTF table of contents.+    + Only autolink absolute URIs.  This fixes a regression, #830.++  * Markdown writer:++    + Only autolink absolute URIs.  This fixes a regression, #830.+    + Don't wrap attributes in fenced code blocks.+    + Write full metadata in MMD style title blocks.+    + Put multiple authors on separate lines in pandoc titleblock.+      Also, don't wrap long author entries, as new lines get treated+      as new authors.++  * `Text.Pandoc.Templates`:++    + Fixed bug retrieving default template for markdown variants.+    + Templates can now contain "record lookups" in variables;+      for example, `author.institution` will retrieve the `institution`+      field of the `author` variable.+    + More consistent behavior of `$for$`.  When `foo` is not a list,+      `$for(foo)$...$endfor$` should behave like $if(foo)$...$endif$.+      So if `foo` resolves to "", no output should be produced.+      See pandoc-templates#39.++  * Citation processing improvements (now part of pandoc-citeproc):++    + Fixed `endWithPunct` The new version correctly sees a sentence+      ending in '.)' as ending with punctuation.  This fixes a bug which+      led such sentences to receive an extra period at the end: '.).'.+      Thanks to Steve Petersen for reporting.+    + Don't interfere with Notes that aren't citation notes.+      This fixes a bug in which notes not generated from citations were+      being altered (e.g. first letter capitalized) (#898).+    + Only capitalize footnote citations when they have a prefix.+    + Changes in suffix parsing.  A suffix beginning with a digit gets 'p'+      inserted before it before passing to citeproc-hs, so that bare numbers+      are treated as page numbers by default.  A suffix not beginning with+      punctuation has a space added at the beginning (rather than a comma and+      space, as was done before for not-author-in-text citations).+      The result is that `\citep[23]{item1}` in LaTeX will be interpreted+      properly, with '23' treated as a locator of type 'page'.+    + Many improvements to citation rendering, due to fixes in citeproc-hs+      (thanks to Andrea Rossato).+    + Warnings are issued for undefined citations, which are rendered+      as `???`.+    + Fixed hanging behavior when locale files cannot be found.++  [template changes]++  * DocBook:  Use DocBook 4.5 doctype.++  * Org: '#+TITLE:' is inserted before the title.+    Previously the writer did this.++  * LaTeX:  Changes to make mathfont work with xelatex.+    We need the mathspec library, not just fontspec, for this.+    We also need to set options for setmathfont (#734).++  * LaTeX: Use `tex-ansi` mapping for `monofont`.+    This ensures that straight quotes appear as straight, rather than+    being treated as curly.  See #889.++  * Made `\includegraphics` more flexible in LaTeX template.+    Now it can be used with options, if needed.  Thanks to Bernhard Weichel.++  * LaTeX/Beamer: Added `classoption` variable.+    This is intended for class options like `oneside`; it may+    be repeated with different options.  (Thanks to Oliver Matthews.)++  * Beamer: Added `fonttheme` variable.  (Thanks to Luis Osa.)++  * LaTeX: Added `biblio-style` variable (#920).++  * DZSlides: title attribute on title section.++  * HTML5: add meta tag to allow scaling by user (Erik Evenson)++  [under-the-hood improvements]++  * Markdown reader:Improved strong/emph parsing, using the strategy of+    <https://github.com/jgm/Markdown>.  The new parsing algorithm requires+    no backtracking, and no keeping track of nesting levels.  It will give+    different results in some edge cases, but these should not affect normal+    uses.++  * Added `Text.Pandoc.Compat.Monoid`.+    This allows pandoc to compile with `base` < 4.5, where `Data.Monoid`+    doesn't export `<>`.  Thanks to Dirk Ullirch for the patch.++  * Added `Text.Pandoc.Compat.TagSoupEntity`.+    This allows pandoc to compile with `tagsoup` 0.13.x.+    Thanks to Dirk Ullrich for the patch.++  * Most of `Text.Pandoc.Readers.TeXMath` has been moved to the+    `texmath` module (0.6.4).  (This allows `pandoc-citeproc` to+    handle simple math in bibliography fields.)++  * Added `Text.Pandoc.Writers.Shared` for shared functions used+    only in writers.  `metaToJSON` is used in writers to create a+    JSON object for use in the templates from the pandoc metadata+    and variables.  `getField`, `setField`, and `defField` are+    for working with JSON template contexts.++  * Added `Text.Pandoc.Asciify` utility module.+    This exports functions to create ASCII-only versions of identifiers.++  * `Text.Pandoc.Parsing`++    + Generalized state type on `readWith` (API change).+    + Specialize readWith to `String` input. (API change).+    + In `ParserState`, replace `stateTitle`, `stateAuthors`, `stateDate`+      with `stateMeta` and `stateMeta'`.++  * `Text.Pandoc.UTF8`: use strict bytestrings in reading.  The use of lazy+     bytestrings seemed to cause problems using pandoc on 64-bit Windows+     7/8 (#874).++  * Factored out `registerHeader` from markdown reader, added to+    `Text.Pandoc.Parsing`.++  * Removed `blaze_html_0_5` flag, require `blaze-html` >= 0.5.+    Reason:  < 0.5 does not provide a monoid instance for Attribute,+    which is now needed by the HTML writer (#803).++  * Added `http-conduit` flag, which allows fetching https resources.+    It also brings in a large number of dependencies (`http-conduit`+    and its dependencies), which is why for now it is an optional flag+    (#820).++  * Added CONTRIBUTING.md.++  * Improved INSTALL instructions.++  * `make-windows-installer.bat`: Removed explicit paths for executables.++  * `aeson` is now used instead of `json` for JSON.++  * Set default stack size to 16M.  This is needed for some large+    conversions, esp. if pandoc is compiled with 64-bit ghc.++  * Various small documentation improvements.+    Thanks to achalddave and drothlis for patches.++  * Removed comment that chokes recent versions of CPP (#933).++  * Removed support for GHC version < 7.2, since pandoc-types now+    requires at least GHC 7.2 for GHC generics.+++pandoc (1.11.1)++  * Markdown reader:++    + Fixed regression in which parentheses were lost in link URLs.+      Added tests.  Closes #786.+    + Better handling of unmatched double quotes in `--smart` mode.+      These occur frequently in fiction, since it is customary not to+      close quotes in dialogue if the speaker does not change between+      paragraphs.  The unmatched quotes now get turned into literal+      left double quotes. (No `Quoted` inline is generated, however.)+      Closes #99 (again).++  * HTML writer: Fixed numbering mismatch between TOC and sections.+    `--number-offset` now affects TOC numbering as well+    as section numbering, as it should have all along.  Closes #789.++  * Markdown writer: Reverted 1.11 change that caused citations to be rendered+    as markdown citations, even if `--bibliography` was specified, unless+    `citation` extension is disabled.  Now, formatted citations are always+    printed if `--bibliography` was specified.  If you want to reformat+    markdown keeping pandoc markdown citations intact, don't use+    `--bibliography`.  Note that citations parsed from LaTeX documents will+    be rendered as pandoc markdown citations when `--bibliography` is not+    specified.++  * ODT writer: Fixed regression leading to corrupt ODTs.+    This was due to a change in the `Show` instance for+    `Text.Pandoc.Pretty.Doc`.  Closes #780.++  * Fixed spacing bugs involving code block attributes in+    RST reader and Markdown writer. Closes #763.++  * Windows package:  Various improvements due to Fyodor Sheremetyev.++    + Automatically set installation path (Program Files or Local App Data).+    + Set system PATH environment variable when installing for all users.+    + Pandoc can installed for all users using the following command.+      `msiexec /i pandoc-1.11.msi ALLUSERS=1`.++  * Bumped QuickCheck version bound.++pandoc (1.11)++  * Added `--number-offset` option.  (See README for description.)++  * Added `--default-image-extension` option.  (See README for description.)++  * `--number-sections` behavior change: headers with class `unnumbered`+    will not be numbered.++  * `--version` now reports the default data directory.++  * `Text.Pandoc.Parsing` is no longer exposed. (API change.)++  * `Text.Pandoc.Highlighting` is no longer exposed. (API change.)++  * `Text.Pandoc.Shared`:  Changed type of `Element`.  `Sec` now includes+    a field for `Attr` rather than just `String`.  (API change.)++  * Added `markdown_github` as input format.  This was an accidental+    omission in 1.10.++  * Added `readerDefaultImageExtension` field to `ReaderOptions`.  (API+    change.)++  * Added `writerNumberOffset` field in `WriterOptions`. (API change.)++  * Beamer template:++    + Fixed captions with longtable.  Thanks to Joost Kremers.+    + Provide `\Oldincludegraphics` as in LaTeX template (Benjamin Bannier).++  * LaTeX template:++    + Load microtype after fonts.  Microtype needs to know+      what fonts are being used.  Thanks to dfc for the patch.+    + Set `secnumdepth` to 5 if `--number-sections` specified.+      This yields behavior equivalent to the other writers, numbering+      level 4 and 5 headers too.  Closes #753.++  * HTML reader:++    + Handle `<colgroup>` tag.+    + Preserve all header attributes.++  * LaTeX reader:++    + Parse `\hrule` as `HorizontalRule`.  Closes #746.+    + Parse starred variants of `\section` etc. as headers with+      attribute `unnumbered`.+    + Read optional attributes in `lstlisting` and `Verbatim` environments.+      We convert these to pandoc standard names, e.g. `numberLines`+      for `numbers=left`, `startFrom=100` from `firstnumber=100`.+    + Handle language attribute for lstlistings.+    + Better support for Verbatim and minted environments.  Closes #763.++  * Markdown reader:++    + `-` in an attribute context = `.unnumbered`.  The point of this+      is to provide a way to specify unnumbered headers in non-English+      documents.+    + Fixed bug parsing key/value attributes.  Parsing failed if you+      had an unquoted attribute immediately before the final '}'.+    + Make backslash escape work in attributes.+    + Fix title block parsing.  Now if `mmd_title_blocks` is specified,+      pandoc will parse a MMD title block if it sees one, even if+      `pandoc_title_blocks` is enabled.+    + Refactoring: `litChar` now includes entities, so we don't need+      to use `fromEntities` e.g. on titles.+    + Allow spaces around borders in pipe tables.  Closes #772.+    + Allow all punctuation in angle-bracket autolinks.  Previously+      things like `----` were disallowed, because the uri parser+      treated them as trailing punctuation.  Closes #768.+    + Make `implicit_header_references` work properly when+      headers are given explicit identifiers.+    + Check for tables before line blocks.  Otherwise some pipe+      tables get treated as line blocks.+    + Allow `&` in emails (for entities).+    + Properly handle entities in titles and links.  A markdown link+      `<http://g&ouml;ogle.com>` should be a link to `http://göogle.com`.+      Closes #723.++  * Textile reader:++    + Handle attributes on headers.++  * LaTeX reader:++    + Add `fig:` as title for images with captions.+      This is needed for them to be rendered as figures.  Closes #766.+    + Never emit an empty paragraph.  See #761.+    + Handle `\caption` for images in figures.  Closes #766.+    + Parse `\section*`, etc. as unnumbered sections.++  * HTML writer:++    + Support header attributes.  The attributes go on+      the enclosing `section` or `div` tag if `--section-divs` is specified.+    + Fixed a regression (only now noticed) in html+lhs output.+      Previously the bird tracks were being omitted.++  * LaTeX writer:++    + Omit lists with no items to avoid LaTeX errors.+    + Support line numbering with `--listings`.+      If `numberLines` class is present, we add `numbers=left`;+      if `startFrom` is present, we add `firstnumber=`. (#763)++  * ConTeXt writer:++    + Removed `\placecontent`.  This produced a duplicate toc,+      in conjunction with `\placelist`.+    + Use `\title`, `\subject` etc. for headers with+      `unnumbered` class.++  * Textile writer:++    + Support header attributes.++  * Markdown writer:++    + Use grid tables when needed, and if enabled.  Closes #740.+    + Render citations as pandoc-markdown citations.+      Previously citations were rendered as citeproc-formatted citations+      by default.  Now we render them as pandoc citations, e.g. `[@item1]`,+      unless the `citations` extension is disabled.+      If you still want formatted citations in your markdown output,+      use `pandoc -t markdown-citations`.++  * RST writer:++    + Support `:number-lines:` in code blocks.++  * Docx writer:++    + Better treatment of display math.  Display math inside a+      paragraph is now put in a separate paragraph, so it will render+      properly (centered and without extra blank lines around it).+      Partially addresses #742.+    + Content types and document rels xml files are now created from+      scratch, rather than being taken over from `reference.docx`.+      This fixes problems that arise when you edit the `reference.docx`+      with Word.+    + We also now encode mime types for each individual image rather+      than using defaults.  This should allow us to handle a wider+      range of image types (including PDF).   Closes #414.+    + Changed style names in `reference docx`.+      `FootnoteReference` -> `FootnoteRef`, `Hyperlink` -> `Link`.+      The old names got changed by Word when the `reference.docx` was+      edited.  Closes #414.++  * EPUB writer:++    + Fix section numbering.  Previously the numbering restarted from 1+      in each chapter (with `--number-sections`), though the numbers in+      the table of contents were correct.+    + Headers with "unnumbered" attribute are not numbered.  (Nor do they+      cause an increment in running numbering.) Section numbers now work+      properly, even when there is material before the first numbered section.+    + Include HTML TOC, even in epub2.  The TOC is included in `<spine>`,+      but `linear` is set to `no` unless the `--toc` option is specified.+      Include `<guide>` element in OPF.  This should allow the TOC to+      be useable in Kindles when converted with kindlegen. Closes #773.++  * `Text.Pandoc.Parsing`: Optimized `oneOfStringsCI`.+    This dramatically reduces the speed penalty that comes from enabling the+    `autolink_bare_uris` extension.  The penalty is still substantial (in one+    test, from 0.33s to 0.44s), but nowhere near what it used to be.+    The RST reader is also much faster now, as it autodetects URIs.++  * `Text.Pandoc.Shared`:  `hierarchicalize` will not number section+    with class "unnumbered".  Unnumbered sections get `[]` for their+    section number.++  * `Text.Pandoc.Pretty`:++    + Fixed `chomp` so it works inside `Prefixed` elements.+    + Changed `Show` instance so it is better for debugging.++  * `Text.Pandoc.ImageSize`:  Added `Pdf` to `ImageType`.++  * `Text.Pandoc.UTF8`:  Strip off BOM if present.  Closes #743.++  * Windows installer improvements:++    + The installer is now signed with a certificate (thanks to+      Fyodor Sheremetyev).+    + WiX is used instead of InnoSetup.  The installer is now a+      standard msi file.+    + The version number is now auto-detected, and need not be+      updated separately.++  * OSX installer improvements:++    + The package and pandoc executable are now signed with a+      certificate (thanks to Fyodor Sheremetyev).+    + RTF version of license is used.+    + Use full path for sysctl in `InstallationCheck` script (jonahbull).+      Closes #580.++  * Converted COPYING to markdown.++  * pandoc.cabal:  Require latest versions of highlighting-kate,+    texmath, citeproc-hs, zip-archive.++pandoc (1.10.1)++  * Markdown reader:  various optimizations, leading to a+    significant performance boost.++  * RST reader:  Allow anonymous form of inline links:+    `` `hello <url>`__ `` Closes #724.++  * Mediawiki reader: Don't require newlines after tables.+    Thanks to jrunningen for the patch. Closes #733.++  * Fixed LaTeX macro parsing.  Now LaTeX macro definitions are preserved+    when output is LaTeX, and applied when it is another format.+    Partially addresses #730.++  * Markdown and RST readers:  Added parser to `block` that skips blank+    lines.  This fixes a subtle regression involving grid tables with+    empty cells.  Also added test for grid table with empty cells.+    Closes #732.++  * RST writer:  Use `.. code:: language` for code blocks with language.+    Closes #721.++  * DocBook writer:  Fixed output for hard line breaks, adding a newline+    between `<literallayout>` tags.++  * Markdown writer:  Use an autolink when link text matches url.+    Previously we also checked for a null title, but this+    test fails for links produced by citeproc-hs in bibliographies.+    So, if the link has a title, it will be lost on conversion+    to an autolink, but that seems okay.++  * Markdown writer:  Set title, author, date variables as before.+    These are no longer used in the default template, since we use+    titleblock, but we set them anyway for those who use custom templates.++  * LaTeX writer:  Avoid extra space at start/end of table cell.+    Thanks to Nick Bart for the suggestion of using @{}.++  * `Text.Pandoc.Parsing`:++    + More efficient version of `anyLine`.+    + Type of `macro` has changed; the parser now returns `Blocks`+      instead of `Block`.++  * Relaxed old-time version bound, allowing 1.0.*.++  * Removed obsolete `hsmarkdown` script.  Those who need `hsmarkdown`+    should create a symlink as described in the README.++pandoc (1.10.0.5)++  * Markdown reader: Try `lhsCodeBlock` before `rawTeXBlock`.  Otherwise+    `\begin{code}...\end{code}` isn't handled properly in markdown+lhs.+    Thanks to Daniel Miot for noticing the bug and suggesting the fix.++  * Markdown reader: Fixed bug with headerless grid tables.+    The 1.10 code assumed that each table header cell contains exactly one+    block. That failed for headerless tables (0) and also for tables with+    multiple blocks in a header cell.  The code is fixed and tests provided.+    Thanks to Andrew Lee for pointing out the bug.++  * Markdown reader: Fixed regressions in fenced code blocks. Closes #722.++    + Tilde code fences can again take a bare language string+      (`~~~ haskell`), not just curly-bracketed attributes+      (`~~~ {.haskell}`).+    + Backtick code blocks can take the curly-bracketed attributes.+    + Backtick code blocks don't *require* a language.+    + Consolidated code for the two kinds of fenced code blocks.++  * LaTeX template: Use `\urlstyle{same}` to avoid monospace URLs.++  * Markdown writer: Use proportional font for email autolinks with+    obfuscation.  Closes #714.++  * Corrected name of `blank_before_blockquote` in README.  Closes #718.++  * `Text.Pandoc.Shared`: Fixed bug in `uri` parser.+    The bug prevented an autolink at the end of a string (e.g.+    at the end of a line block line) from counting as a link.  Closes #711.++  * Use the `hsb2hs` preprocessor instead of TH for embed_data_files.+    This should work on Windows, unlike the TH solution with+    file-embed.++  * Eliminated use of TH in test suite.++  * Added `Text.Pandoc.Data` (non-exported) to hold the association+    list of embedded data files, if the `embed_data_files` flag is selected.+    This isolates the code that needs special treatment with file-embed or+    `hsb2hs`.++  * Changes to `make-windows-installer.bat`.++    + Exit batch file if any of the cabal-dev installs fail.+    + There's no longer any need to reinstall `highlighting-kate`.+    + Don't start with a `cabal update`; leave that to the user.+    + Force reinstall of pandoc.++  * Fixed EPUB writer so it builds with blaze-html 0.4.x. Thanks to+    Jens Petersen.++pandoc (1.10.0.4)++  * Fixed bug with escaped % in LaTeX reader. Closes #710.++pandoc (1.10.0.3)++  * Added further missing fb2 tests to cabal file.++pandoc (1.10.0.2)++  * Added fb2 tests to cabal file's extra-source-files.++pandoc (1.10.0.1)++  * Bump version bounds on test-framework packages.++pandoc (1.10)++  [new features]++  * New input formats:  `mediawiki` (MediaWiki markup).++  * New output formats:  `epub3` (EPUB v3 with MathML),+    `fb2` (FictionBook2 ebooks).++  * New `--toc-depth` option, specifying how many levels of+    headers to include in a table of contents.++  * New `--epub-chapter-level` option, specifying the header+    level at which to divide EPUBs into separate files.+    Note that this normally affects only performance, not the+    visual presentation of the EPUB in a reader.++  * Removed the `--strict` option.  Instead of using `--strict`,+    one can now use the format name `markdown_strict` for either input+    or output.  This gives more fine-grained control that `--strict`+    did, allowing one to convert from pandoc's markdown to strict+    markdown or vice versa.++  * It is now possible to enable or disable specific syntax+    extensions by appending them (with `+` or `-`) to the writer+    or reader name.  For example,++        pandoc -f markdown-footnotes+hard_line_breaks++    disables footnotes and enables treating newlines as hard+    line breaks.  The literate Haskell extensions are now implemented+    this way as well, using either `+lhs` or `+literate_haskell`.+    For a list of extension names, see the README under+    "Pandoc's Markdown."++  * The following aliases have been introduced for specific+    combinations of markdown extensions:  `markdown_phpextra`,+    `markdown_github`, `markdown_mmd`, `markdown_strict`.  These aliases+    work just like regular reader and writer names, and can be modified+    with extension modifiers as described above. (Note that conversion+    from one markdown dialect to another does not work perfectly,+    because there are differences in markdown parsers besides+    just the extensions, and because pandoc's internal document model is+    not rich enough to capture all of the extensions.)++  * New `--html-q-tags` option.  The previous default was to use `<q>`+    tags for smart quotes in HTML5.  But `<q>` tags are also valid HTML4.+    Moreover, they are not a robust way of typesetting quotes, since+    some user agents don't support them, and some CSS resets (e.g.+    bootstrap) prevent pandoc's quotes CSS from working properly.+    We now just insert literal quote characters by default in both+    `html` and `html5` output, but this option is provided for+    those who still want `<q>` tags.++  * The markdown reader now prints warnings (to stderr) about+    duplicate link and note references.  Closes #375.++  * Markdown syntax extensions:++    + Added pipe tables.  Thanks to François Gannaz for the initial patch.+      These conform to PHP Markdown Extra's pipe table syntax. A subset+      of org-mode table syntax is also supported, which means that you can+      use org-mode's nice table editor to create tables.++    + Added support for RST-style line blocks. These are+      useful for verse and addresses.++    + Attributes can now be specified for headers, using the same+      syntax as in code blocks.  (However, currently only the+      identifier has any effect in most writers.)  For example,++            # My header {#foo}++            See [the header above](#foo).++    + Pandoc will now act as if link references have been defined+      for all headers without explicit identifiers.+      So, you can do this:++            # My header++            Link to [My header].+            Another link to [it][My header].++      Closes #691.++  * LaTeX reader:++    + Command macros now work everywhere, including non-math.+      Environment macros still not supported.+    + `\input` now works, as well as `\include`.  TEXINPUTS is used.+      Pandoc looks recursively into included files for more included files.++  [behavior changes]++  * The Markdown reader no longer puts the text of autolinks in a+    `Code` inline.  This means that autolinks will no longer appear+    in a monospace font.++  * The character `/` can now appear in markdown citation keys.++  * HTML blocks in strict_markdown are no longer required to begin+    at the left margin.  Technically this is required, according to+    the markdown syntax document, but `Markdown.pl` and other markdown+    processors are more liberal.++  * The `-V` option has been changed so that if there are duplicate+    variables, those specified later on the command line take precedence.++  * Tight lists now work in LaTeX and ConTeXt output.++  * The LaTeX writer no longer relien on the `enumerate` package.+    Instead, it uses standard LaTeX commands to change the list numbering+    style.++  * The LaTeX writer now uses `longtable` instead of `ctable`. This allows+    tables to be split over page boundaries.++  * The RST writer now uses a line block to render paragraphs containing+    linebreaks (which previously weren't supported at all).++  * The markdown writer now applies the `--id-prefix` to footnote IDs.+    Closes #614.++  * The plain writer no longer uses backslash-escaped line breaks+    (which are not very "plain").++  * `Text.Pandoc.UTF8`: Better error message for invalid UTF8.+    Read bytestring and use `Text`'s decodeUtf8 instead of using+    `System.IO.hGetContents`.  This way you get a message saying+    "invalid UTF-8 stream" instead of "invalid byte sequence."+    You are also told which byte caused the problem.++  * Docx, ODT, and EPUB writers now download images specified by a URL+    instead of skipping them or raising an error.++  * EPUB writer:++    + The default CSS now left-aligns headers by default, instead of+      centering.  This is more consistent with the rest of the writers.+    + A proper multi-level table of contents is now used in `toc.ncx`.+      There is no longer a subsidiary table of contents at the beginning+      of each chapter.+    + Code highlighting now works by default.+    + Section divs are used by default for better semantic markup.+    + The title is used instead of "Title Page" in the table of contents.+      Otherwise we have a hard-coded English string, which looks+      strange in ebooks written in other languages.  Closes #572.++  * HTML writer:++    + Put mathjax in span with class "math".  Closes #562.+    + Put citations in a span with class "citation." In HTML5, also include+      a `data-cite` attribute with a space-separated list of citation+      keys.++  * `Text.Pandoc.UTF8`:  use universalNewlineMode in reading.+    This treats both `\r\n` and `\n` as `\n` on input, no matter+    what platform we're running on.++  * Citation processing is now done in the Markdown and LaTeX+    readers, not in `pandoc.hs`.  This makes it easier for library users+    to use citations.++  [template changes]++  * HTML: Added css to template to preserve spaces in `<code>` tags.+    Thanks to Dirk Laurie.++  * Beamer:  Remove English-centric strings in section pages.+    Section pages used to have "Section" and a number as well as the+    section title. Now they just have the title.  Similarly for part+    and subsection.  Closes #566.++  * LaTeX, ConTeXt: Added papersize variable.++  * LaTeX, Beamer templates: Use longtable instead of ctable.++  * LaTeX, Beamer templates: Don't require 'float' package for tables.+    We don't actually seem to use the '[H]' option.++  * LaTeX:  Use `upquote` package if it is available.  This fixes+    straight quotes in verbatim environments.++  * Markdown, plain: Fixed titleblock so it is just a single string.+    Previously separate title, author, and date variables were used,+    but this didn't allow different kinds of title blocks.++  * EPUB:++    + Rationalized templates.  Previously there were three different+      templates involved in epub production. There is now just one+      template, `default.epub` or `default.epub3`. It can now be+      overridden using `--template`, just like other templates.+      The titlepage is now folded into the default template.+      A `titlepage` variable selects it.+    + UTF-8, lang tag, meta tags, title element.++  * Added scale-to-width feature to beamer template++  [API changes]++  * `Text.Pandoc.Definition`: Added `Attr` field to `Header`.+    Previously header identifers were autogenerated by the writers.+    Now they are added in the readers (either automatically or explicitly).++  * `Text.Pandoc.Builder`:++    + `Inlines` and `Blocks` are now synonyms for `Many Inline` and+      `Many Block`.  `Many` is a newtype wrapper around `Seq`, with+      custom Monoid instances for `Many Inline` and `Many Block.  This+      allows `Many` to be made an instance of `Foldable` and `Traversable`.+    + The old `Listable` class has been removed.+    + The module now exports `isNull`, `toList`, `fromList`.+    + The old `Read` and `Show` instances have been removed; derived+      instances are now used.+    + Added `headerWith`.++  * The readers now take a `ReaderOptions` rather than a `ParserState`+    as a parameter.  Indeed, not all parsers use the `ParserState` type;+    some have a custom state.  The motivation for this change was to separate+    user-specifiable options from the accounting functions of parser state.++  * New module `Text.Pandoc.Options`.  This includes the `WriterOptions`+    formerly in `Text.Pandoc.Shared`, and its associated+    data types.  It also includes a new type `ReaderOptions`, which+    contains many options formerly in `ParserState`, and its associated+    data types:++    + `ParserState.stateParseRaw` -> `ReaderOptions.readerParseRaw`.+    + `ParserState.stateColumns` -> `ReaderOptions.readerColumns`.+    + `ParserState.stateTabStop` -> `ReaderOptions.readerTabStop`.+    + `ParserState.stateOldDashes` -> `ReaderOptions.readerOldDashes`.+    + `ParserState.stateLiterateHaskell` -> `ReaderOptions.readerLiterateHaskell`.+    + `ParserState.stateCitations` -> `ReaderOptions.readerReferences`.+    + `ParserState.stateApplyMacros` -> `ReaderOptions.readerApplyMacros`.+    + `ParserState.stateIndentedCodeClasses` ->+      `ReaderOptions.readerIndentedCodeClasses`.+    + Added `ReaderOptions.readerCitationStyle`.++  * `WriterOptions` now includes `writerEpubVersion`, `writerEpubChapterLevel`,+    `writerEpubStylesheet`, `writerEpubFonts`, `writerReferenceODT`,+    `writerReferenceDocx`, and `writerTOCDepth`.  `writerEPUBMetadata` has+    been renamed `writerEpubMetadata` for consistency.++  * Changed signatures of `writeODT`, `writeDocx`, `writeEPUB`, since they no+    longer stylesheet, fonts, reference files as separate parameters.++  * Removed `writerLiterateHaskell` from `WriterOptions`, and+    `readerLiterateHaskell` from `ReaderOptions`.  LHS is now handled+    by an extension (`Ext_literate_haskell`).++  * Removed deprecated `writerXeTeX`.++  * Removed `writerStrict` from `WriterOptions`.  Added `writerExtensions`.+    Strict is now handled through extensions.++  * `Text.Pandoc.Options` exports `pandocExtensions`, `strictExtensions`,+    `phpMarkdownExtraExtensions`, `githubMarkdownExtensions`,+    and `multimarkdownExtensions`, as well as the `Extensions` type.++  * New `Text.Pandoc.Readers.MediaWiki` module, exporting+    `readMediaWiki`.++  * New `Text.Pandoc.Writers.FB2` module, exporting `writeFB2`+    (thanks to Sergey Astanin).++  * `Text.Pandoc`:++    + Added `getReader`, `getWriter` to `Text.Pandoc`.+    + `writers` is now an association list `(String, Writer)`.+      A `Writer` can be a `PureStringWriter`, an `IOStringWriter`, or+      an `IOByteStringWriter`.  ALL writers are now in the 'writers'+      list, including the binary writers and FB2 writer.  This allows+      code in `pandoc.hs` to be simplified.+    + Changed type of `readers`, so all readers are in IO.+      Users who want pure readers can still get them form the reader+      modules; this just affects the function `getReader` that looks up+      a reader based on the format name.  The point of this change is to+      make it possible to print warnings from the parser.++  * `Text.Pandoc.Parsing`:++    + `Text.Parsec` now exports all Parsec functions used in pandoc code.+      No other module directly imports Parsec.  This will make it easier+      to change the parsing backend in the future, if we want to.+    + `Text.Parsec` is used instead of `Text.ParserCombinators.Parsec`.+    + Export the type synonym `Parser`.+    + Export `widthsFromIndices`, `NoteTable'`, `KeyTable'`, `Key'`, `toKey'`,+     `withQuoteContext`, `singleQuoteStart`, `singleQuoteEnd`,+     `doubleQuoteStart`, `doubleQuoteEnd`, `ellipses`, `apostrophe`,+     `dash`, `nested`, `F(..)`, `askF`, `asksF`, `runF`, `lineBlockLines`.+    + `ParserState` is no longer an instance of `Show`.+    + Added `stateSubstitutions` and `stateWarnings` to `ParserState`.+    + Generalized type of `withQuoteContext`.+    + Added `guardEnabled`, `guardDisabled`, `getOption`.+    + Removed `failIfStrict`.+    + `lookupKeySrc` and `fromKey` are no longer exported.++  * `Data.Default` instances are now provided for `ReaderOptions`,+    `WriterOptions`, and `ParserState`.  `Text.Pandoc` re-exports `def`.+    Now you can use `def` (which is re-exported by `Text.Pandoc`) instead+    of `defaultWriterOptions` (which is still defined).  Closes #546.++  * `Text.Pandoc.Shared`:++    + Added `safeRead`.+    + Renamed `removedLeadingTrailingSpace` to `trim`,+      `removeLeadingSpace` to `triml`, and `removeTrailingSpace` to `trimr`.+    + Count `\r` as space in `trim` functions.+    + Moved `renderTags'` from HTML reader and `Text.Pandoc.SelfContained`+      to `Shared`.+    + Removed `failUnlessLHS`.+    + Export `compactify'`, formerly in Markdown reader.+    + Export `isTightList`.+    + Do not export `findDataFile`.+    + `readDataFile` now returns a strict ByteString.+    + Export `readDataFileUTF8` which returns a String, like the+      old `readDataFile`.+    + Export `fetchItem` and `openURL`.++  * `Text.Pandoc.ImageSize`: Use strict, not lazy bytestrings.+    Removed `readImageSize`.++  * `Text.Pandoc.UTF8`: Export `encodePath`, `decodePath`,+     `decodeArg`, `toString`, `fromString`, `toStringLazy`,+     `fromStringLazy`.++  * `Text.Pandoc.UTF8` is now an exposed module.++  * `Text.Pandoc.Biblio`:++    + csl parameter now a `String` rather than a `FilePath`.+    + Changed type of `processBiblio`.  It is no longer in the IO monad.+      It now takes a `Maybe Style` argument rather than parameters for CSL+      and abbrev filenames.  (`pandoc.hs` now calls the functions to parse+      the style file and add abbreviations.)++  * Markdown reader now exports `readMarkdownWithWarnings`.++  * `Text.Pandoc.RTF` now exports `writeRTFWithEmbeddedImages` instead of+    `rtfEmbedImage`.++  [bug fixes]++  * Make `--ascii` work properly with `--self-contained`.  Closes #568.++  * Markdown reader:++    + Fixed link parser to avoid exponential slowdowns.  Closes #620.+      Previously the parser would hang on input like this:++            [[[[[[[[[[[[[[[[[[hi++      We fixed this by making the link parser parser characters+      between balanced brackets (skipping brackets in inline code spans),+      then parsing the result as an inline list.  One change is that++            [hi *there]* bud](/url)++      is now no longer parsed as a link.  But in this respect pandoc behaved+      differently from most other implementations anyway, so that seems okay.++    + Look for raw html/latex blocks before tables.+      Otherwise the following gets parsed as a table:++            \begin{code}+            --------------+            -- My comment.+            \end{code}++      Closes #578.++  * RST reader:++    + Added support for `:target:` on `.. image::` blocks+      and substitutions.+    + Field list fixes:++        - Fixed field lists items with body beginning after a new line+          (Denis Laxalde).+        - Allow any char but ':' in names of field lists in RST reader+          (Denis Laxalde).+        - Don't allow line breaks in field names.+        - Require whitespace after field list field names.+        - Don't create empty definition list for metadata field lists.+          Previously a field list consisting only of metadata fields (author,+          title, date) would be parsed as an empty DefinitionList, which is+          not legal in LaTeX and not needed in any format.++    + Don't recognize inline-markup starts inside words.+      For example, `2*2 = 4*1` should not contain an emphasized+      section.  Added test case for "Literal symbols".  Closes #569.+    + Allow dashes as separator in simple tables.  Closes #555.+    + Added support for `container`, `compound`, `epigraph`,+      `rubric`, `highlights`, `pull-quote`.+    + Added support for `.. code::`.+    + Made directive labels case-insensitive.+    + Removed requirement that directives begin at left margin.+      This was (correctly) not in earlier releases; docutils doesn't+      make the requirement.+    + Added support for `replace::` and `unicode::` substitutions.+    + Ignore unknown interpreted roles.+    + Renamed image parser to `subst`, since it now handles all+      substitution references.++  * Textile reader:++    + Allow newlines before pipes in table.  Closes #654.+    + Fixed bug with list items containing line breaks.+      Now pandoc correctly handles hard line breaks inside list items.+      Previously they broke list parsing.+    + Implemented comment blocks.+    + Fixed bug affected words ending in hyphen.+    + Properly handle links with surrounding brackets.+      Square brackets need to be used when the link isn't surrounded by+      spaces or punctuation, or when the URL ending may be ambiguous.+      Closes #564.+    + Removed nullBlock.  Better to know about parsing problems than+      to skip stuff when we get stuck.+    + Allow ID attributes on headers.+    + Textile reader:  Avoid parsing dashes as strikeout.+      Previously the input++            text--+            text--+            text--+            text--++      would be parsed with strikeouts rather than dashes. This fixes+      the problem by requiring that a strikeout delimiting - not be+      followed by a -.  Closes #631.+    + Expanded list of `stringBreakers`.+      This fixes a bug on input like "(_hello_)" which should+      be a parenthesized emphasized "hello".+      The new list is taken from the PHP source of textile 2.4.+    + Fixed autolinks.  Previously the textile reader and writer+      incorrectly implented RST-style autolinks for URLs and email+      addresses.  This has been fixed.  Now an autolink is done this way:+      `"$":http://myurl.com`.+    + Fixed footnotes bug in textile.  This affected notes occuring+      before punctuation, e.g. `foo[1].`.  Closes #518.++  * LaTeX reader:++    + Better handling of citation commands.+    + Better handling of `\noindent`.+    + Added a 'try' in rawLaTeXBlock, so we can handle `\begin` without `{`.+      Closes #622.+    + Made `rawLaTeXInline` try to parse block commands as well.  This+      is usually what we want, given how `rawLaTeXInline` is used in+      the markdown and textile readers.  If a block-level LaTeX command+      is used in the middle of a paragraph (e.g. `\subtitle` inside a title),+      we can treat it as raw inline LaTeX.+    + Handle \slash command.  Closes #605.+    + Basic `\enquote` support.+    + Fixed parsing of paragraphs beginning with a group.  Closes #606.+    + Use curly quotes for bare straight quotes.+    + Support obeylines environment.  Closes #604.+    + Guard against "begin", "end" in inlineCommand and+      blockCommand.+    + Better error messages for environments.  Now it should tell you that+      it was looking for \end{env}, instead of giving "unknown parse error."++  * HTML reader:++    + Added HTML 5 tags to list of block-level tags.+    + HTML reader: Fixed bug in `htmlBalanced`, which+      caused hangs in parsing certain markdown input using+      strict mode.+    + Parse `<q>` as `Quoted DoubleQuote`.+    + Handle nested `<q>` tags properly.+    + Modified `htmlTag` for fewer false positives.+      A tag must start with `<` followed by `!`,`?`, `/`, or a letter.+      This makes it more useful in the wikimedia and markdown parsers.++  * DocBook reader: Support title in "figure" element.  Closes #650.++  * MediaWiki writer:++    + Remove newline after `<br/>` in translation of `LineBreak`+      There's no particular need for a newline (other than making the+      generated MediaWiki source look nice to a human), and in fact+      sometimes it is incorrect: in particular, inside an enumeration, list+      items cannot have embedded newline characters. (Brent Yorgey)+    + Use `<code>` not `<tt>` for Code.++  * Man writer: Escape `-` as `\-`.+    Unescaped `-`'s become hyphens, while `\-`'s are left as ascii minus+    signs.  That is preferable for use with command-line options.  See+    <http://lintian.debian.org/tags/hyphen-used-as-minus-sign.html>.  Thanks+    to Andrea Bolognani for bringing the issue to our attention.++  * RST writer:++    + Improved line block output. Use nonbreaking spaces for+      initial indent (otherwise lost in HTML and LaTeX).+      Allow multiple paragraphs in a single line block.+      Allow soft breaks w continuations in line blocks.+    + Properly handle images with no alt text.  Closes #678.+    + Fixed bug with links with duplicate text.  We now (a) use anonymous+      links for links with inline URLs, and (b) use an inline link instead+      of a reference link if the reference link would require a label that+      has already been used for a different link.  Closes #511.+    + Fixed hyperlinked images. Closes #611. Use `:target:`+      field when you have a simple linked image.+    + Don't add `:align: center` to figures.++  * Texinfo writer:  Fixed internal cross-references.+    Now we insert anchors after each header, and use `@ref` instead of `@uref`+    for links.  Commas are now escaped as `@comma{}` only when needed;+    previously all commas were escaped.  (This change is needed, in part,+    because `@ref` commands must be followed by a real comma or period.) Also+    insert a blank line in from of `@verbatim` environments.++  * DocBook writer:++    + Made --id-prefix work in DocBook as well as HTML.+      Closes #607.+    + Don't include empty captions in figures.  Closes #581.++  * LaTeX writer:++    + Use `\hspace*` for nonbreaking space after line break,+      since `~` spaces after a line break are just ignored.+      Closes #687.+    + Don't escape `_` in URLs or hyperref identifiers.+    + Properly escape strings inside \url{}.  Closes #576.+    + Use `[fragile]` only for slides containing code rendered+      using listings. Closes #649.+    + Escape `|` as `\vert` in LaTeX math.  This avoids a clash with+      highlighting-kate's macros, which redefine `|` as a short verbatim+      delimiter.  Thanks to Björn Peemöller for raising this issue.+    + Use minipage rather than parbox for block containers in tables.+      This allows verbatim code to be included in grid tables.+      Closes #663.+    + Prevent paragraphs containing only linebreaks or spaces.++  * HTML writer:++    + Included `highlighting-css` for code spans, too.+      Previously it was only included if used in a code block.  Closes #653.+    + Improved line breaks with `<dd>` tags.  We now put a newline between+      `</dd>` and `<dd>` when there are multiple definitions.+    + Changed mathjax cdn url so it doesn't use https.  (This caused+      problems when used with `--self-contained`.) See #609.++  * EPUB writer:++    + `--number-sections` now works properly.+    + Don't strip meta and link elements in epub metadata.+      Patch from aberrancy. Closes #589.+    + Fixed a couple validation bugs.+    + Use ch001, ch002, etc. for chapter filenames.  This improves sorting+      of chapters in some readers, which apparently sort ch2 after ch10.+      Closes #610.++  * ODT writer: properly set title property (Arlo O'Keeffe).++  * Docx writer:++    + Fixed bug with nested lists.  Previously a list like++            1. one+                - a+                - b+            2. two++      would come out with a bullet instead of "2."+      Thanks to Russell Allen for reporting the bug.+    + Use `w:cr` in `w:r` instead of `w:br` for linebreaks.+      This seems to fix a problem viewing pandoc-generated+      docx files in LibreOffice.+    + Use integer ids for bookmarks.  Closes #626.+    + Added nsid to abstractNum elements.  This helps when merging+      word documents with numbered or bulleted lists.  Closes #627.+    + Use separate footnotes.xml for notes.+      This seems to help LibreOffice convert the file, even though+      it was valid docx before.  Closes #637.+    + Use rIdNN identifiers for r:embed in images.+    + Avoid reading image files again when we've already processed them.+    + Fixed typo in `referenc.docx` that prevented image captions from+      working. Thanks to Huashan Chen.++  * `Text.Pandoc.Parsing`:++    + Fixed bug in `withRaw`, which didn't correctly handle the case+      where nothing is parsed.+    + Made `emailAddress` parser more correct.  Now it is based on RFC 822,+      though it still doesn't implement quoted strings in email addresses.+    + Revised URI parser.  It now allows many more schemes, allows+      uppercase URIs, and better handles trailing punctuation and+      trailing slashes in bare URIs.  Added many tests.+    + Simplified and improved singleQuoteStart.  This makes `'s'`, `'l'`,+      etc. parse properly.  Formerly we had some English-centric heuristics,+      but they are no longer needed. Closes #698.++  * `Text.Pandoc.Pretty`:  Added wide punctuation range to `charWidth`.+    This fixes bug with Chinese commas in markdown and reST tables, and+    a bug that caused combining characters to be dropped.++  * `Text.Pandoc.MIME`: Added MIME types for .wof and .eot.  Closes #640.++  * `Text.Pandoc.Biblio`:++    + Run `mvPunc` and `deNote` on metadata too.+      This fixed a bug with notes on titles using footnote styles.+    + Fixed bug in fetching CSL files from CSL data directory.++  * `pandoc.hs`:  Give correct value to `writerSourceDirectory` when a URL+    is provided.  It should be the URL up to the path.++  * Fixed/simplified diff output for tests.+    Biblio: Make sure mvPunc and deNote run on metadata too.+    This fixed a bug with notes on titles using footnote styles.++  [under the hood improvements]++  * We no longer depend on `utf8-string`.  Instead we use functions+    defined in `Text.Pandoc.UTF8` that use `Data.Text`'s conversions.++  * Use `safeRead` instead of using `reads` directly (various modules).++  * "Implicit figures" (images alone in a paragraph) are now handled+    differently.  The markdown reader gives their titles the prefix `fig:`; the+    writers look for this before treating the image as a figure.  Though this+    is a bit of a hack, it has two advantages: (i) implicit figures can be+    limited to the markdown reader, and (ii) they can be deactivated by turning+    off the `implicit_figures` extension.++  * `catch` from `Control.Exception` is now used instead of the+    old Preface `catch`.++  * `Text.Pandoc.Shared`:  Improved algorithm for `normalizeSpaces`+    and `oneOfStrings` (which is now non-backtracking).++  * `Text.Pandoc.Biblio`: Remove workaround for `toCapital`.+    Now citeproc-hs is fixed upstream, so this is no longer needed.+    Closes #531.++  * Textile reader: Improved speed of `hyphenedWords`.+    This speeds up the textile  reader by about a factor of 4.++  * Use `Text.Pandoc.Builder` in RST reader, for more flexibility,+    better performance, and automatic normalization.++  * Major rewrite of markdown reader:++    + Use `Text.Pandoc.Builder` instead of lists.  This also+      means that everything is normalized automatically.+    + Move to a one-pass parsing strategy, returning values in the reader+      monad, which are then run (at the end of parsing) against the final+      parser state.++  * In HTML writer, we now use `toHtml` instead of pre-escaping.+    We work around the problem that blaze-html unnecessarily escapes `'`+    by pre-escaping just the `'` characters, instead of the whole string.+    If blaze-html later stops escaping `'` characters, we can simplify+    `strToHtml` to `toHtml`.  Closes #629.++  * Moved code for embedding images in RTFs from `pandoc.hs` to the+    RTF writer (which now exports `writeRTFWithEmbeddedImages`).++  * Moved citation processing from `pandoc.hs` into the readers.+    This makes things more convenient for library users.++  * The man pages are now built by an executable `make-pandoc-man-pages`,+    which has its own stanza in the cabal file so that dependencies can be+    handled by Cabal. Special treatment in `Setup.hs` ensures that this+    executable never gets installed; it is only used to create the man pages.++  * The cabal file has been modified so that the pandoc library is used+    in building the pandoc executable.  (This required moving `pandoc.hs`+    from `src` to `.`.)  This cuts compile time in half.++  * `-O2` is no longer used in building pandoc.  The performance improvement+    it yields is so slight that it is not worth it.  (Measured with+    benchmarks on ghc 7.4.)++  * The `executable` and `library` flags have been removed.++  * `-threaded` has been removed from ghc-options.++  * Version bounds of dependencies have been raised, and the+    `blaze_html_0_5` flag now defaults to True.  Pandoc now compiles on+    GHC 7.6.++  * We now require base >= 4.2.++  * Integrated the benchmark program into cabal.  One can now do:++        cabal configure --enable-benchmarks && cabal build+        cabal bench --benchmark-option='markdown' --benchmark-option='-s 20'++    The benchmark now uses README + testsuite, so benchmark results+    from older versions aren't comparable.++  * Integrated test suite with cabal.+    To run tests, configure with `--enable-tests`, then `cabal test`.+    You can specify particular tests using `--test-options='-t markdown'`.+    No output is shown unless tests fail.  The Haskell test modules+    have been moved from `src/` to `tests/`.++  * Moved all data files and templates to the `data/` subdirectory.++  * Added an `embed_data_files` cabal flag.  This causes all+    data files to be embedded in the binary, so that the binary+    is self-sufficient and can be relocated anywhere, copied on+    a USB key, etc.  The Windows installer now uses this.+    (Since we no longer have the option to build the executable+    without the library, this is the only way to get a relocatable+    binary on Windows.)++  * Removed pcre3.dll from windows package.+    It isn't needed unless highlighting-kate is compilled with the+    `pcre-light` flag. By default, regex-prce-builtin is used.+++pandoc (1.9.4.2)++  * Don't encode/decode file paths if base >= 4.4.+    Prior to base 4.4, filepaths and command line arguments were treated+    as unencoded lists of bytes, not unicode strings, so we had to work+    around that by encoding and decoding them. This commit adds CPP+    checks for the base version that intelligibly enable encoding/decoding+    when needed. Fixes a bug with multilingual filenames when pandoc was+    compiled with ghc 7.4 (#540).++  * Don't generate an empty H1 after hrule slide breaks.+    We now use a slide-level header with contents `[Str "\0"]` to mark+    an hrule break.  This avoids creation of an empty H1 in these+    contexts.  Closes #484.++  * Docbook reader: Added support for "bold" emphasis.  Thanks to Mauro Bieg.++  * In make_osx_package.sh, ensure citeproc-hs is built with the+    embed_data_files flag.++  * MediaWiki writer: Avoid extra blank lines after sublists (Gavin Beatty).++  * ConTeXt writer: Don't escape `&`, `^`, `<`, `>`, `_`,+    simplified escapes for `}` and `{` to `\{` and `\}` (Aditya Mahajan).++  * Fixed handling of absolute URLs in CSS imports with `--self-contained`.+    Closes #535.++  * Added webm to mime types. Closes #543.++  * Added some missing exports and tests to the cabal file+    (Alexander V Vershilov).++  * Compile with `-rtsopts` and `-threaded` by default.++pandoc (1.9.4.1)++  * Markdown reader: Added `cf.` and `cp.` to list of likely abbreviations.++  * LaTeX template: Added `linkcolor`, `urlcolor` and `links-as-notes`+    variables.  Make TOC links black.++  * LaTeX template improvements.++    + Don't print date unless one is given explicitly in the document.+    + Simplified templates.+    + Use fontenc [T1] by default, and lmodern.+    + Use microtype if available.++  * Biblio:++    + Add comma to beginning of bare suffix, e.g. `@item1 [50]`.+      Motivation: `@item1 [50]` should be as close as possible to+      `[@item1, 50]`.+    + Added workaround for a bug in citeproc-hs 0.3.4 that causes footnotes+      beginning with a citation to be empty.  Closes #531.++  * Fixed documentation on mixed lists.  Closes #533.++pandoc (1.9.4)++  * Simplified `Text.Pandoc.Biblio` and fixed bugs with citations inside+    footnotes and captions.  We now handle note citations by inserting+    footnotes during initial citation processing, and doing a separate+    pass later to remove notes inside notes.++  * Added 'zenburn' highlight style from highlighting-kate.++  * Added Slideous writer. Slideous is an HTML + javascript slide show+    format, similar to Slidy, but works with IE 7. (Jonas Smedegaard)++  * LaTeX writer:++    + Ensure we don't have extra blank lines at ends of cells.+      This can cause LaTeX errors, as they are interpreted as new paragraphs.+    + More consistent interblock spacing.+    + Require highlighting-kate >= 0.5.1, for proper highlighted inline+      code in LaTeX.  Closes #527.+    + Ensure that a Verbatim at the end of a footnote is followed by+      a newline. (Fixes a regression in the previous version.)+    + In default template, use black for internal links and TOC.+      Added commented-out code to use footnotes for links, as would+      be suitable in print output.++  * Beamer writer:  When `--incremental` is used, lists inside+    a block quote should appear all at once.  (This makes Beamer+    output consistent with the HTML slide show formats.)++  * ConTeXt writer:++    + Escape `%` as `\letterpercent{}` not `\letterpercent `,+      to avoid gobbling spaces after the `%` sign.+    + Ensure space after `\stopformula`.++  * Markdown writer:++    + Use `:` form instead of `~` in definition lists, for better+      compatibility with other markdown implementations.+    + Don't wrap the term, because it breaks definition lists.+    + Use a nonzero space to prevent false recognition+      of list marker in ordered lists.  Closes #516.++  * Org writer: Add space before language name.  Closes #523.++  * Docx writer: Simplified bullet characters so they work properly+    with Word 2007. Closes #520.++  * LaTeX reader: Support `\centerline`.++  * RST reader:  handle figures.  Closes #522.++  * Textile reader: fix for `<notextile>` and `==`.  Closes #517.+    (Paul Rivier)++pandoc (1.9.3)++  * Fixed bug in `fromEntities`.  The previous version would turn+    `hi & low you know;` into `hi &`.++  * HTML reader:++    + Don't skip nonbreaking spaces.+      Previously a paragraph containing just `&nbsp;` would be rendered+      as an empty paragraph. Thanks to Paul Vorbach for pointing out the bug.+    + Support `<col>` and `<caption>` in tables. Closes #486.++  * Markdown reader:++    + Don't recognize references inside delimited code blocks.+    + Allow list items to begin with lists.++  * Added basic docbook reader (John MacFarlane and Mauro Bieg).++  * LaTeX reader:++    + Handle `\bgroup`, `\egroup`, `\begingroup`, `\endgroup`.+    + Control sequences can't be followed by a letter.+      This fixes a bug where `\begingroup` was parsed as `\begin`+      followed by `group`.+    + Parse 'dimension' arguments to unknown commands.  e.g. `\parindent0pt`+    + Make `\label` and `\ref` sensitive to `--parse-raw`.+      If `--parse-raw` is selected, these will be parsed as raw latex+      inlines, rather than bracketed text.+    + Don't crash on unknown block commands (like `\vspace{10pt}`)+      inside `\author`; just skip them.  Closes #505.++  * Textile reader:++    + Implemented literal escapes with `==` and `<notextile>`.  Closes #473.+    + Added support for LaTeX blocks and inlines (Paul Rivier).+    + Better conformance to RedCloth inline parsing (Paul Rivier).+    + Parse '+text+' as emphasized (should be underlined, but this+      is better than leaving literal plus characters in the output.++  * Docx writer: Fixed multi-paragraph list items.  Previously they each+    got a list marker.  Closes #457.++  * LaTeX writer:++    + Added `--no-tex-ligatures` option to avoid replacing+      quotation marks and dashes with TeX ligatures.+    + Use `fixltx2e` package to provide '\textsubscript'.+    + Improve spacing around LaTeX block environments:+      quote, verbatim, itemize, description, enumerate.+      Closes #502.+    + Use blue instead of pink for URL links in latex/pdf output.++  * ConTeXt writer: Fixed escaping of `%`.+    In text, `%` needs to be escaped as `\letterpercent`, not `\%`+    Inside URLs, `%` needs to be escaped as `\%`+    Thanks to jmarca and adityam for the fix.  Closes #492.++  * Texinfo writer:  Escape special characters in node titles.+    This fixes a problem pointed out by Joost Kremers.  Pandoc used+    to escape an '@' in a chapter title, but not in the corresponding+    node title, leading to invalid texinfo.++  * Fixed document encoding in texinfo template.+    Resolves Debian Bug #667816.++  * Markdown writer:++    + Don't force delimited code blocks to be flush left.+      Fixes bug with delimited code blocks inside lists etc.+    + Escape `<` and `$`.++  * LaTeX writer: Use `\hyperref[ident]{text}` for internal links.+    Previously we used `\href{\#ident}{text}`, which didn't work on+    all systems. Thanks to Dirk Laurie.++  * RST writer: Don't wrap link references.  Closes #487.++  * Updated to use latest versions of blaze-html, mtl.+++pandoc (1.9.2)++  * LaTeX reader:++    + Made `lstlisting` work as a proper verbatim environment.+    + Fixed bug parsing LaTeX tables with one column.++  * LaTeX writer:++    + Use `{}` around `ctable` caption, so that formatting can be used.+    + Don't require eurosym package unless document has a €.++  * LaTeX template: Added variables for `geometry`, `romanfont`,+    `sansfont`, `mathfont`, `mainfont` so users can more easily+    customize fonts.++  * PDF writer:++    + Run latex engine at least two times, to ensure+      that PDFs will have hyperlinked bookmarks.+    + Added PDF metadata (title,author) in LaTeX standalone + PDF output.++  * Texinfo writer: retain directories in image paths.  (Peter Wang)++  * RST writer:  Better handling of inline formatting, in accord+    with docutils' "inline markup recognition rules" (though we don't+    implement the unicode rules fully). Now `hi*there*hi` gets+    rendered properly as `hi\ *there*\ hi`, and unnecessary+    `\ ` are avoided around `:math:`, `:sub:`, `:sup:`.++  * RST reader:++    + Parse `\ ` as null, not escaped space.+    + Allow `` :math:`...` `` even when not followed by blank+      or `\`.  This does not implement the complex rule docutils follows,+      but it should be good enough for most purposes.+    + Add support for the rST default-role directive. (Greg Maslov)++  * Text.Pandoc.Parsing: Added `stateRstDefaultRole` field to `ParserState`.+    (Greg Maslov)++  * Markdown reader: Properly handle citations nested in other inline+    elements.++  * Markdown writer:  don't replace empty alt in image with "image".++  * DZSlides:  Updated template.html and styles in default template.+    Removed bizarre CSS for `q` in dzslides template.++  * Avoid repeated `id` attribute in section and header in HTML slides.++  * README improvements:  new instructions on internal links,+    removed misleading note on reST math.++  * Build system:++    + Fixed Windows installer so that dzslides works.+    + Removed stripansi.sh.+    + Added .travis.yml for Travis continuous integration support..+    + Fixed upper bound for zlib (Sergei Trofimovich).+    + Fixed upper bound for test-framework.+    + Updated haddocks for haddock-2.10 (Sergei Trofimovich).++pandoc (1.9.1.2)++  * Added `beamer+lhs` as output format.++  * Don't escape `<` in `<style>` tags with `--self-contained`.+    This fixes a bug which prevented highlighting from working+    when using `--self-contained`.++  * PDF: run latex engine three times if `--toc` specified.+    This fixes page numbers in the table of contents.++  * Docx writer: Added TableNormal style to tables.++  * LaTeX math environment fixes. `aligned` is now used instead of+    the nonexistent `aligned*`. `multline` instead of the nonexistent+    `multiline`.++  * LaTeX writer: Use `\textasciitilde` for literal `~`.++  * HTML writer: Don't escape contents of EQ tags with --gladtex.+    This fixes a regression from 1.8.++  * Use `<q>` tags for Quoted items for HTML5 output.+    The quote style can be changed by modifying the template+    or including a css file. A default quote style is included.++  * LaTeX reader: Fixed accents (\~{a}, `\c{c}`).+    Correctly handle \^{}. Support "minted" as a LaTeX verbatim block.++  * Updated LaTeX template for better language support.+    Use `polyglossia` instead of `babel` with xetex.+    Set `lang` as documentclass option.+    `\setmainlanguage` will use the last of a comma-separated+    list of languages. Thanks to François Gannaz.++  * Fixed default LaTeX template so `\euro` and `€` work.  The+    `eurosym` package is needed if you are using pdflatex.++  * Fixed escaping of period in man writer (thanks to Michael Thompson).++  * Fixed list label positions in beamer.++  * Set `mainlang` variable in context writer.+    This parallels behavior of latex writer.  `mainlang` is the last+    of a comma-separated list of languages in lang.++  * EPUB language metadat: convert e.g. `en_US` from locale to `en-US`.++  * Changed `-V` so that you can specify a key without a value.+    Such keys get the value `true`.++  * Fixed permissions on installed man pages - thanks Magnus Therning.++  * Windows installer: require XP or higher.  The installer is+    now compiled on a Windows 7 machine, which fixes a problem+    using citation functions on Windows 7.++  * OSX package: Check for 64-bit Intel CPU before installing.++pandoc (1.9.1.1)++  * Better handling of raw latex environments in markdown.  Now++        \begin{equation}+        a_1+        \end{equation}++    turns into a raw latex block as expected.++  * Improvements to LaTeX reader:++    + Skip options after block commands.+    + Correctly handle `{\\}` in braced.+    + Added a needed 'try'.+    + Citations: add `, ` to suffix if it doesn't start with space or+      punctuation. Otherwise we get no space between the year and the+      suffix in author-date styles.++  * Added two needed data files for S5.  This fixes a problem with+    `pandoc -t s5 --self-contained`.  Also removed `slides.min.js`,+    which was no longer being used.++  * Fixed some minor problems in `reference.docx`:+    name on "Date" style, `xCs` instead of `xIs`.++  * Fixed a problem creating docx files using a reference docx+    modified using Word.  The problem seems to be that Word+    modifies `_rels/.rels`, changing the Type of the Relationship to+    `docProps/core.xml`. Pandoc now changes this back to the correct+    value if it has been altered, fixing the problem.++  * Fixed html5 template so it works properly with highlighting.++pandoc (1.9.1)++  * LaTeX reader:++    + Fixed regression in 1.9; properly handle escaped $ in latex math.+    + Put LaTeX verse environments in blockquotes.++  * Markdown reader:++    + Limit nesting of strong/emph.  This avoids exponential lookahead+      in parasitic cases, like `a**a*a**a*a**a*a**a*a**a*a**a*a**a*a**`.+    + Improved attributes syntax (inn code blocks/spans):+      (1) Attributes can contain line breaks. (2) Values in key-value+      attributes can be surrounded by either double or single quotes, or+      left unquoted if they contain no spaces.++  * Don't wrap headers in markdown or RST writers.++  * Added `stateMaxNestingLevel` to `ParserState`.+    We set this to 6, so you can still have `Emph` inside `Emph`,+    just not indefinitely.++  * More efficient implementation of `nowrap` in `Text.Pandoc.Pretty`.++  * `Text.Pandoc.PDF`:  Only run latex twice if `\tableofcontents`+    is present.++  * Require highlighting-kate >= 0.5.0.2, texmath >= 0.6.0.2.++pandoc (1.9.0.5)++  * Changed cabal file so that build-depends for the test program+    are not required unless the tests flag is used.++  * LaTeX writer:  insert `{}` between adjacent hyphens so they don't+    form ligatures (dashes) in code spans.++pandoc (1.9.0.4)++  * Raised version bound on test-framework to avoid problems+    compiling tests on GHC 7.4.1.++  * LaTeX reader: Use raw LaTeX as fallback inline text for Cites,+    so citations don't just disappear unless you process with+    citeproc.  Ignore `\bibliographystyle`, `\nocite`.++  * Simplified tex2pdf; it will always run latex twice to+    resolve table of contents and hyperrefs.++pandoc (1.9.0.3)++  * Require Cabal >= 1.10.+  * Tweaked cabal file to meet Cabal 1.10 requirements.++pandoc (1.9.0.2)++  * Allow build with json 0.4 or 0.5.  Otherwise we can't build with+    ghc 6.12.++pandoc (1.9)++  [new features]++  * Added a Microsoft Word `docx` writer. The writer includes support+    for highlighted code and for math (which is converted from TeX to OMML,+    Office's native math markup language, using texmath's new OMML module).+    A new option `--reference-docx` allows the user to customize the+    styles.++  * Added an `asciidoc` writer (<http://www.methods.co.nz/asciidoc/>).++  * Better support for slide shows:++    + Added a `dzslides` writer. DZSlides is a lightweight HTML5/javascript+      slide show format due to Paul Rouget (<http://paulrouget.com/dzslides/>).++    + Added a LaTeX `beamer` writer. Beamer is a LaTeX package for creating+      slide presentations.++    + New, flexible rules for dividing documents into sections and slides+      (see the "Structuring the slide show" in the User's Guide).  These+      are backward-compatible with the old rules, but they allow slide+      shows to be organized into sections and subsections containing+      multiple slides.++    + A new `--slide-level` option allows users to override defaults+      and select a slide level below the first header level with content.++  * A new `--self-contained` option produces HTML output that does not+    depend on an internet connection or the presence of any external+    files. Linked images, CSS, and javascript is downloaded (or fetched+    locally) and encoded in `data:` URIs. This is useful for making portable+    `HTML slide shows. The --offline` option has been deprecated and is now+    `treated as a synonym or --self-contained`.++  * Support for PDF output:++    + Removed the old `markdown2pdf`.+    + `pandoc` can now create PDFs (assuming you have latex and a set of+      appropriate packages installed): just specify an output file with the+      `.pdf` extension.+    + A new option `--latex-engine` allows you to specify `pdflatex`,+      `xelatex`, or `lualatex` as the processor.++  * Highlighting changes:++    + Syntax highlighting is now a standard feature; the `highlighting`+      flag is no longer needed when compiling.+    + A new `--no-highlight` option allows highlighting to be disabled.+    + Highlighting now works in `docx`, `latex`, and `epub`, as well as+      `html`, `html5`, `dzslides`, `s5`, and `slidy`.+    + A new `--highlight-style` option selects between various highlighting+      color themes.++  * Internal links to sections now work in ConTeXt and LaTeX as well as HTML.++  * LaTeX `\include` and `\usepackage` commands are now processed,+    provided the files are in the working directory.++  * EPUB improvements:++    + Internal and external links now work in EPUB.+    + Raw HTML is allowed.+    + New `--epub-embed-font` option.+    + Customizable templates for EPUB pages offer more control over+      formatting: `epub-page.html`, `epub-coverimage.html`,+      `epub-titlepage.html`.++  * `--mathml` now works with DocBook.++  * Added support for math in RST reader and writer.  Inline math uses the+    `` :math:`...` `` construct.  Display math uses++        .. math:: ...++    or if the math is multiline,++        .. math::++           ...++    These constructions are now supported now by `rst2latex.py`.++  * GitHub syntax for fenced code blocks is supported in pandoc's+    markdown.  You can now write++        ```ruby+        x = 2+        ```++    instead of++        ~~~ {.ruby}+        x = 2+        ~~~~++  * Easier scripting:  a new `toJsonFilter` function makes it easier to+    write Haskell scripts to manipulate the Pandoc AST.++  [behavior changes]++  * Fixed parsing of consecutive lists in markdown.+    Pandoc previously behaved like Markdown.pl for consecutive+    lists of different styles. Thus, the following would be parsed+    as a single ordered list, rather than an ordered list followed+    by an unordered list:++        1. one+        2. two++        - one+        - two++    This change makes pandoc behave more sensibly, parsing this as+    two lists.  Any change in list type (ordered/unordered) or in+    list number style will trigger a new list. Thus, the following+    will also be parsed as two lists:++        1. one+        2. two++        a. one+        b. two++    Since we regard this as a bug in Markdown.pl, and not something+    anyone would ever rely on, we do not preserve the old behavior+    even when `--strict` is selected.++  * Dashes work differently with `--smart`: `---` is always em-dash,+    and `--` is always en-dash.  Pandoc no longer tries to guess when+    `-` should be en-dash.  *Note:* This may change how existing documents+    look when processed with pandoc. A new option, `--old-dashes`,+    is provided for legacy documents.++  * The markdown writer now uses setext headers for levels 1-2.+    The old behavior (ATX headers for all levels) can be restored+    using the new `--atx-headers` option.++  * Links are now allowed in markdown image captions.  They are also+    allowed in links, but will appear there as regular text. So,++        [link with [link](/url)](/url)++    will turn into++        <p><a href="/url">link with link</a></p>++  * Improved handling of citations using `citeproc-hs-0.3.4`.+    Added `--citation-abbreviations` option.++  * Citation keys can no longer end with a punctuation character.+    This means that `@item1.` will be parsed as a citation with key+    'item1', followed by a period, instead of a citation with key+    'item1.', as was the case previously.++  * In HTML output, citations are now put in a span with class `citation`.++  * The markdown reader now recognizes DocBook block and inline tags.+    It was always possible to include raw DocBook tags in a markdown+    document, but now pandoc will be able to distinguish block from+    inline tags and behave accordingly. Thus, for example,++        <sidebar>+        hello+        </sidebar>++    will not be wrapped in `<para>` tags.++  * The LaTeX parser has been completely rewritten; it is now much more+    accurate, robust, and extensible. However, there are two important+    changes in how it treats unknown LaTeX. (1) Previously, unknown+    environments became BlockQuote elements; now, they are treated+    as "transparent", so `\begin{unknown}xyz\end{unknown}` is the+    same as `xyz`.  (2) Previously, arguments of unknown commands+    were passed through with their braces; now the braces are stripped+    off.++  * `--smart` is no longer selected automatically with `man` output.++  * The deprecated `--xetex` option has been removed.++  * The `--html5`/`-5` option has been deprecated. Use `-t html5`+    instead. `html5` and `html5+lhs` are now separate output formats.++  * Single quotes are no longer escaped in HTML output.  They do not+    need to be escaped outside of attributes.++  * Pandoc will no longer transform leading newlines in code+    blocks to `<br/>` tags.++  * The ODT writer now sizes images appropriately, using the image+    size and DPI information embedded in the image.++  * `--standalone` is once again implicitly for a non-text output format+    (ODT, EPUB).  You can again do `pandoc test.txt -o test.odt`+    and get a standalone ODT file.++  * The Docbook writer now uses `<sect1>`, `<sect2>`, etc. instead of+    `<section>`.++  * The HTML writer now uses `<del>` for strikeout.++  * In HTML output with `--section-divs`, the classes `section` and+    `level[1,2,..6]` are put on the `div` tags so they can be styled.+    In HTML 5 output with `--section-divs`, the classes+    `level[1,2,...6]` are put on `section` tags.++  * EPUB writer changes:++    + The `lang` variable now sets the language+      in the metadata (if it is not set, we default to the locale).+    + EPUB:  UTF-8 is used rather than decimal entities.++  * Added `titleslide` class to title slide in S5 template.++  * In HTML, EPUB, and docx metadata, the date is normalized into+    YYYY-MM-DD format if possible. (This is required for validation.)++  * Attributes in highlighted code blocks are now preserved in HTML.+    The container element will have the classes, id, and key-value attributes+    you specified in the delimited code block. Previously these were stripped+    off.++  * The reference backlink in the HTML writer no longer has a special+    `footnoteBacklink` class.++  * The HTML template has been split into `html` and `html5` templates.++  * Author and date are treated more consistently in HTML templates.+    Authors are now `<h2>`, date `<h3>`.++  * URLs are hyphenated in the ConTeXt writer (B. Scott Michel).++  * In `Text.Pandoc.Builder`, `+++` has been replaced by `<>`.++  [bug fixes]++  * Better support for combining characters and East Asian wide characters+    in markdown and reST.++  * Better handling of single quotes with `--smart`.+    Previously `D'oh l'*aide*` would be parsed with left and right single+    quotes instead of apostrophes. This kind of error is now fixed.++  * Highlighting: Use `reads` instead of `read` for better error handling.+    Fixes crash on `startNum="abc"`.++  * Added blank comment after directives in rst template.++  * Unescape entities in citation `refId`. The `refId`s coming+    from citeproc contain XML numeric entities, and these don't match with the+    citation keys parsed by pandoc. Solution is to unescape them.++  * HTML reader: Fixed bug parsing tables with both thead and tbody.++  * Markdown reader:++    + Better handling of escapes in link URLs and titles.+    + Fixed backslash escapes in reference links.+    + Fixed bug in table/hrule parsing, by checking that the top+      line of a table is not followed by a blank line. This bug caused+      slowdowns on some files with hrules and tables, as pandoc tried to+      interpret the hrules as the tops of multiline tables.+    + Fixed bug in code block attribute parser. Previously the ID attribute+      got lost if it didn't come first. Now attributes can come in any order.++  * RST reader: allow footnotes followed by newline without space characters.++  * LaTeX reader:++    + Ignore empty groups {}, { }.+    + LaTeX reader: Handle \@.+    + LaTeX reader:  Don't crash on commands like `\itemsep`.+    + LaTeX reader:  Better handling of letter environments.++  * RST writer: Fixed bug involving empty table cells. isSimple was being+    calculated in a way that assumed there were no non-empty cells.++  * ConTeXt writer:++    + Made `--toc` work even without `--number-sections`.+    + Escape # in link URLs.+    + Use buffering for footnotes containing code blocks.+    + Changed 'descr' to 'description', fixed alignment.++  * LaTeX writer:++    + Escape euro character.+    + Don't escape ~ inside href{...}.+    + Escape # in href URLs.+    + Improved detection of book classes.  We now check the+      `documentclass` variable, and if that is not set, we look through+      the template itself.  Also, we have added the KOMA classes scrreprt+      and scrbook.  You can now make a book using+      `pandoc -V documentclass:book mybook.txt -o mybook.pdf`+    + LHS files now set the "listings" variable, so that the definition+      of the `code` environment will be included in the template.+    + Links are colored blue by default (this can be changed by+      modifying `hyperref` settings in the template).+    + Added `lang` variable to LaTeX template.++  * HTML writer:++    + Fixed bug in HTML template with html5 and mathml.+    + Don't use self-closing img, br, hr tags for HTML5.+    + Use `<section>` for footnotes if HTML5.+    + Update HTML templates to use Content-Style-Type meta tag.+    + Use separate variables for meta-date, meta-author.+      This makes footnotes work in author and date fields.+    + Use 'vertical-align:middle' in WebTeX math for better alignment.++  * S5/slidy writer:  Make footnotes appear on separate slide at end.++  * MIME: Added 'layout-cache' to getMimeType. This ensures that the+    META-INF/manifest.xml for ODT files will have everything it needs, so+    that ODT files modified by LibreOffice can be used as `--reference-odt`.++  * `Text.Pandoc.Templates`: Return empty string for json template.++  * `Text.Pandoc.Biblio`:++    + Expand citations recursively inside nested inlines.+    + Treat `\160` as space when parsing locator and suffix.+      This fixes a bug with "p. 33" when `--smart` is used. Previously+      the whole "p. 33" would be included in the suffix, with no locator.+    + Put whole author-in-text citation in a Cite.  Previously just the+      date and other info went in the Cite.+    + Don't add comma+space to prefix if it ends in punctuation.++  * Updated chicago-author-date.csl.  The old version did not work+    properly for edited volumes with no author.++  * EPUB writer:++    + Add date to EPUB titlepage and metadata.+    + Added TOC identifier in EPUB page template.+    + Don't generate superfluous file `cover-image.jpg`.++  [under the hood improvements]++  * Modified `make_osx_package.sh` to use cabal-dev.+    Items are no longer installed as root.+    Man pages are zipped and given proper permissions.++  * Modified windows installer generater to use cabal-dev.++  * Setup: Making man pages now works with cabal-dev (at least on OSX). In+    Setup.hs we now invoke 'runghc' in a way that points it to the correct+    package databases, instead of always falling back to the default user+    package db.++  * Updated to work with GHC 7.4.1.++  * Removed dependency on old-time.++  * Removed dependency on dlist.++  * New slidy directory for "self-contained."++  * TeXMath writer:  Use unicode thin spaces for thin spaces.++  * Markdown citations: don't strip off initial space in locator.++  [API changes]++  * Removed `Apostrophe`, `EmDash`, `EnDash`, and `Ellipses`+    from the native `Inline` type in pandoc-types.  Now we use `Str`+    elements with unicode.++  * Improvements to `Text.Pandoc.Builder`:++    + `Inlines` and `Blocks` are now newtypes (not synonyms for+      sequences).+    + Instances are defined for `IsString`, `Show`, `Read`, `Monoid`,+      and a new `Listable` class, which allows these to be manipulated+      to some extent like lists. Monoid append includes automatic+      normalization.+    + `+++` has been replaced by `<>` (mappend).++  * Use blaze-html instead of xhtml for HTML generation.+    This changes the type of `writeHtml`.++  * `Text.Pandoc.Shared`:++    + Added `warn` and `err`.+    + Removed `unescapeURI`, modified `escapeURI`.+      (See under [behavior changes], above.)++  * Changes in URI escaping:  Previously the readers escaped URIs by+    converting unicode characters to octets and then percent encoding.+    Now unicode characters are left as they are, and `escapeURI` only+    percent-encodes space characters.  This gives more readable+    URIs, and works well with modern user agents. URIs are no longer unescaped+    at all on conversion to `markdown`, `asciidoc`, `rst`, `org`.++  * New module `Text.Pandoc.SelfContained`.++  * New module `Text.Pandoc.Docx`.++  * New module `Text.Pandoc.PDF`.++  * Added `writerBeamer` to `WriterOptions`.++  * Added `normalizeDate` to `Text.Pandoc.Shared`.++  * Added `splitStringWithIndices` in `Text.Pandoc.Shared`.+    This is like `splitWithIndices`, but it is sensitive to distinctions+    between wide, combining, and regular characters.++  * `Text.Pandoc.Pretty`:++    + Added `chomp` combinator.+    + Added `beforeNonBreak` combinator.  This allows you to include+      something conditionally on it being before a nonblank.+      Used for RST inline math.+    + Added `charWidth` function. All characters marked W or F in the unicode+      spec EastAsianWidth.txt get width 2.+    + Added `realLength`, based on `charWidth`. `realLength` is now+      used in calculating offsets.++  * New module `Text.Pandoc.Slides`, for common functions for breaking+    a document into slides.++  * Removed `Text.Pandoc.S5`, which is no longer needed.++  * Removed `Text.Pandoc.CharacterReferences`.  Moved+    `characterReference` to `Text.Pandoc.Parsing`.+    `decodeCharacterReferences` is replaced by `fromEntities`+    in `Text.Pandoc.XML`.++  * Added `Text.Pandoc.ImageSize`.  This is intened for use+    in `docx` and `odt` writers, so the size and dpi of images+    can be calculated.++  * Removed `writerAscii` in `WriterOptions`.++  * Added `writerHighlight` to `WriterOptions`.++  * Added `DZSlides` to `HTMLSlideVariant`.++  * `writeEPUB` has a new argument for font files to embed.++  * Added `stateLastStrPos` to `ParserState`. This lets us keep track+    of whether we're parsing the position immediately after a regular+    (non-space, non-symbol) string, which is useful for distinguishing+    apostrophes from single quote starts.++  * `Text.Pandoc.Parsing`:++    + `escaped` now returns a `Char`.+    + Removed `charsInBalanced'`, added a character parser as+      a parameter of `charsInBalanced`.  This is needed for+      proper handling of escapes, etc.+    + Added `withRaw`.++  * Added `toEntities` to `Text.Pandoc.XML`.++  * `Text.Pandoc.Readers.LaTeX`:++    + Export `handleIncludes`.+    + Export `rawLaTeXBlock` instead of `rawLaTeXEnvironment'`.++  * Added `ToJsonFilter` class and `toJsonFilter` function to+    `Text.Pandoc`, deprecating the old `jsonFilter` function.++  * `Text.Pandoc.Highlighting`:++     + Removed `highlightHtml`, `defaultHighlightingCss`.+     + Export `formatLaTeXInline`, `formatLaTeXBlock`, and `highlight`, plus+       key functions from highlighting-kate.+     + Changed types of highlighting function.  `highlight` returns a+       `Maybe`, not an `Either`.++pandoc (1.8.2.1)++  * Relaxed cabal consntraints for test-framework (S. Trofimovich).++  * Relaxed cabal constraints for pandoc-types.++  * Adjusted Arbitrary instance to help avoid timeouts in tests.++  * Added `Tests.Writers.Markdown` to cabal file.++pandoc (1.8.2)++  * Added script to produce OS X package.++  * Made `templates` directory a git submodule.  This should make it+    easier for people to revise their custom templates when the default+    templates change.++  * Changed template naming scheme: `FORMAT.template` -> `default.FORMAT`.+    **Note:** If you have existing templates in `~/.pandoc/templates`, you+    must rename them to conform to the new scheme!++  * Fixed smart quotes bug, now handling `'...hi'` properly.++  * RST reader:++    + Partial support for labeled footnotes.+    + Improved accuracy of `simpleReferenceName` parser.++  * HTML reader:++    + Substitute correct unicode characters for+      characters in the 128..159 range, which are often found even in+      HTML that purports to be UTF-8.++  * LaTeX reader:  Handle `\subtitle` command (a subtitle is added+    to the title, after a colon and linebreak). Closes #280.++  * Leaner `reference.odt`.++  * Added unexported module `Text.Pandoc.MIME` for use in+    the ODT writer.++  * ODT writer:  Construct `manifest.xml` based on archive contents.+    This fixes a bug in ODTs containing images. Recent versions of+    LibreOffice would reject these as corrupt, because `manifest.xml`+    did not contain a reference to the image files.++  * LaTeX writer:++    + Make verbatim environments flush to avoid spurious+      blank lines.  Closes #277.+    + Use `\texttt` and escapes insntead of `\verb!...!`, which+      is too fragile (doesn't work in command arguments).+    + Use `\enquote{}` for quotes if the template includes+      the `csquotes` package. This provides better support for+      local quoting styles. (Thanks to Andreas Wagner for the idea.)++  * ConTeXt writer:  Make `\starttyping`/`\stoptyping` flush with+    margin, preventing spurious blank lines.++  * Slidy writer:++    + Use non-minimized version of `slidy.css` with `--offline`+      option, so users can more easily edit it.+    + Also fixed a bug in the CSS that prevented proper centering+      of title (now reported and fixed upstream).++  * S5 writer:++    + Replaced `s5/default/slides.js.{comment,packed}` with+      new compressed `s5/default/slides.min.js`.+    + Use `data:` protocol to embed S5 CSS in `<link>` tags,+      when `--offline` is specified. Using inline CSS didn't+      work with Chrome or Safari.  This fixes offline+      S5 on those browsers.++  * HTML writer:  Removed English title on footnote backlinks.+    This is incongrous in non-English documents.++  * Docbook writer:++    + Use CALS tables.  (Some older docbook software does not work+      well with XHTML tables.)  Closes #77.+    + Use `programlisting` tags (instead of `screen`) for code blocks.++  * `markdown2pdf`:++    + Calls latex with `-halt-on-error -interaction nonstopmode` instead+      of `-interaction=batchmode`, which essentially just ignored errors,+      leading to bad results. Better to know when something is wrong.+    + Fixed issues with non-UTF-8 output of `pdflatex`.+    + Better error reporting.++  * `--mathjax` now takes an optional URL argument. If it is not+    provided, pandoc links directly to the (secure) mathjax CDN,+    as now recommended (thanks to dsanson).++  * Deprecated `--xetex` option in `pandoc`.  It is no longer needed,+    since the LaTeX writer now produces a file that can be processed by+    `latex`, `pdflatex`, `lualatex`, or `xelatex`.++  * Introduced `--luatex` option to `markdown2pdf`. This causes `lualatex`+    to be used to create the PDF.++  * If a template specified with `--template` is not found, look for it+    in `datadir`.  Also, if no extension is provided, supply one based+    on the writer.  So now you can put your `special.latex` template in+    `~/.pandoc/templates`, and use it from any directory via+    `pandoc -t latex --template special`.++  * Default template improvements:++    + HTML:  Display author and date after title.+    + HTML:  Made table of contents more customizable.  The container+      for the TOC is now in the template, so users can insert a header+      or other styling. (Thanks to Bruce D'Arcus for the suggestion.)+    + HTML, Slidy, S5:  Enclose scripts in CDATA tags.+    + Slidy, S5: Added `s5-url` and `slidy-url` variables, instead of+      hard-coding.  If you want to put your slidy files in the slidy+      subdirectory, for example, you can do+      `pandoc -t slidy -V slidy-url=slidy -s`.+    + LaTeX: Use `\and` to separate authors in LaTeX documents (reader+      & writer).  Closes #279.+    + LaTeX: Use different `hyperref` options for `xetex`, fixing+      problems with unicode bookmarks (thanks to CircleCode).+    + LaTeX: Removed `ucs` package, use `utf8` rather than `utf8x`+      with `inputenc`.  This covers fewer characters but is more+      robust with other packages, and `ucs` is unmaintained.  Users+      who need better unicode support should use xelatex or lualatex.++pandoc (1.8.1.2)++  * Added `--epub-cover-image` option.++  * Documented `--biblatex` and `--natbib` options.++  * Allow `--section-divs` with slidy output.  Resolves Issue #296.++  * Disallow notes within notes in reST and markdown.+    These previously caused infinite looping and stack overflows.+    For example:++        [^1]++        [^1]: See [^1]++    Note references are allowed in reST notes, so this isn't a full+    implementation of reST. That can come later. For now we need to+    prevent the stack overflows.  Partially resolves Issue #297.++  * EPUB writer: Allow non-plain math methods.++  * Forbid ()s in citation item keys.  Resolves Issue #304: problems with+    `(@item1; @item2)` because the final paren was being parsed as part of+    the item key.++  * Changed URI parser so it doesn't include trailing punctuation.+    So, in RST, `http://google.com.` should be parsed as a link followed by a+    period. The parser is smart enough to recognize balanced parentheses, as+    often occur in wikipedia links: `http://foo.bar/baz_(bam)`.++  * Markdown+lhs reader: Require space after inverse bird tracks, so that+    HTML tags can be used freely at the left margin of a markdown+lhs document.+    Thanks to Conal Elliot for the suggestion.++  * Markdown reader:++    + Improved emph/strong parsing; fixes bug found by Perry Wagle.+    + Fixed bug in footnote order (reported by CircleCode).++  * RST reader:+      + Fixed bug in in field lists with multi-line items at the+        end of the list.+      + Added parentheses to RST `specialChars`, so+        `(http://google.com)` will be parsed as a link in parens.+        Resolves Issue #291.+      + Allow `|` followed by newline in RST line block.++  * LaTeX reader:+      + Support `\dots`.+      + Gobble option & space after linebreak `\\[10pt]`.++  * Textile reader:+      + Make it possible to have colons after links.  (qerub)+      + Make it possible to have colons after links.  (Christoffer Sawicki)++  * HTML reader:+      + Skip spaces after `<b>`, `<emph>`, etc.+      + Handle tbody, thead in simple tables.  Closes #274.+      + Implicit `Para`s instead of `Plains` in some contexts.++  * OpenDocument writer:  Use special `First paragraph` style for+    first paragraph after most non-paragraph blocks. This allows users to+    specify e.g. that only paragraphs after the first paragraph of a block are+    to be indented. Thanks to Andrea Rossato for the patch. Closes #20.++  * LaTeX writer:  use `deVerb` on table and picture captions.+    Otherwise LaTeX complains about `\verb` inside command argument.+    Thanks to bbanier for reporting the bug.++  * Markdown writer: Insert HTML comment btw list and indented code block.+    This prevents the code block from being interpreted as part of the list.++  * EPUB writer: Add a meta element specify the cover.+    Some EPUB e-readers, such as the Nook, require a meta element inside the+    OPF metadata block to ensure the cover image is properly displayed.+    (Kelsey Hightower)++  * HTML writer: Use embed tag for images with non-image extensions.+    (e.g.  PDFs).  Closes #264.++  * LaTeX writer: Improved tables.++      + More space between lines, top-align cells.+      + Use ctable package, which allows footnotes and+        provides additional options.+      + Made cell alignments work in multiline tables.+      + Closes #271, #272.++  * Un-URI-escape image filenames in LaTeX, ConTeXt, RTF, Texinfo.+    Also do this when copying image files into EPUBs and ODTs.+    Closes #263.++  * Changed to github issue tracker.++  * Added failing emph/strong markdown test case due to Perry Wagle.++  * Slidy improvements:+      + Updated to use Slidy2.+      + Fixed bug, unclosed div tag.+      + Added `duration` variable in template.+        Setting this activates the timer.+      + Use 'titlepage' instead of 'cover' for title div.++pandoc (1.8.1.1)++  * `markdown2pdf`:  Removed some debugging lines accidentally included+    in the 1.8.1 release. With those lines, the temp directory is created+    in the working directory, and it is not deleted.  This fix restores+    the original behavior.++pandoc (1.8.1)++  * Added `--ascii` option.  Currently supported only in HTML writer,+    which it causes to use numerical entities instead of UTF-8.++  * EPUB writer: `--toc` now works to provide a table of contents+    at the beginning of each chapter.++  * LaTeX writer:  Change figure defaults to `htbp`.+    This prevents "too many unprocessed floats."  Resolves+    Issue #285.++  * `Text.Pandoc.UTF8`:  Encode filenames even when using recent+    base.++  * `markdown2pdf`: Fixed filename encoding issues. With help from Paulo+    Tanimoto. Resolves Issue #286.++  * HTML writer: Put line breaks in section divs.++  * `Text.Pandoc.Shared`: Make `writerSectionDivs` default to False.++pandoc (1.8.0.3)++  * Fixed Source-repository stanza in cabal file.++pandoc (1.8.0.2)++  * HTML writer:++    + Stringify alt text instead of converting to HTML.+    + Break lines after block elements, not inside tags.+      HTML output now closely resembles that of tidy. Resolves Issue #134.++  * Markdown reader: Fixed bug in footnote block parser (pointed out+    by Jesse Rosenthal).  The problem arose when the blank line+    at the end of a footnote block contained indenting spaces.++  * Shared: Improved 'normalize' function so it normalizes Spaces too.+    In normal form, Space elements only occur to separate two non-Space+    elements.  So, we never have [Space], or [, ..., Space].++  * Tests:++    + Improved Arbitrary instance.+    + Added timeout for test instances.++  * README:++    + Added section on four-space rule for lists.  Resolves Issue #283.+    + Clarified optional arguments on math options.++  * markdown2pdf: Fixed bug with output file extensions.+    Previously `markdown2pdf test.txt -o test.en.pdf` would produce+    `test.pdf`, not `test.en.pdf`.  Thanks to Paolo Tanimoto for the fix.++pandoc (1.8.0.1)++  * Revised Interact.hs so that it works with the CPP macros+    in the UTF8 module.++  * Revised Setup.hs so that we don't call MakeManPage.hs unless+    the man pages are out of date.++pandoc (1.8)++  [new features]++  * Support for citations using Andrea Rossato's `citeproc-hs` 0.3.+    You can now write, for example,++        Water is wet [see @doe99, pp. 33-35; also @smith04, ch. 1].++    and, when you process your document using `pandoc`, specifying+    a citation style using `--csl` and a bibliography using `--bibliography`,+    the citation will be replaced by an appropriately formatted+    citation, and a list of works cited will be added to the end+    of the document.++    This means that you can switch effortlessly between different citation+    and bibliography styles, including footnote, numerical, and author-date+    formats. The bibliography can be in any of the following formats: MODS,+    BibTeX, BibLaTeX, RIS, EndNote, EndNote XML, ISI, MEDLINE, Copac, or JSON.+    See the README for further details.++    Citations are supported in the markdown reader, using a special+    syntax, and in the LaTeX reader, using natbib or biblatex syntax.+    (Thanks to Nathan Gass for the natbib and biblatex support.)++  * New `textile` reader and writer.  Thanks to Paul Rivier for contributing+    the `textile` reader, an almost complete implementation of the textile+    syntax used by the ruby [RedCloth library](http://redcloth.org/textile).+    Resolves Issue #51.++  * New `org` writer, for Emacs Org-mode, contributed by Puneeth Chaganti.++  * New `json` reader and writer, for reading and writing a JSON+    representation of the native Pandoc AST.  These are much faster+    than the `native` reader and writer, and should be used for+    serializing Pandoc to text.  To convert between the JSON representation+    and native Pandoc, use `encodeJSON` and `decodeJSON` from+    `Text.JSON.Generic`.++  * A new `jsonFilter` function in `Text.Pandoc` makes it easy+    to write scripts that transform a JSON-encoded pandoc document.+    For example:++        -- removelinks.hs - removes links from document+        import Text.Pandoc+        main = interact $ jsonFilter $ bottomUp removeLink+                 where removeLink (Link xs _) = Emph xs+                       removeLink x = x++    To use this to remove links while translating markdown to LaTeX:++        pandoc -t json | runghc removelinks.hs | pandoc -f json -t latex++  * Attributes are now allowed in inline `Code` elements, for example:++        In this code, `ulist ! [theclass "special"] << elts`{.haskell} is...++    The attribute syntax is the same as for delimited code blocks.+    `Code` inline has an extra argument place for attributes, just like+    `CodeBlock`. Inline code will be highlighted in HTML output, if pandoc+    is compiled with highlighting support. Resolves Issue #119.++  * New `RawBlock` and `RawInline` elements (replacing `RawHtml`,+    `HtmlInline`, and `TeX`) provide lots of flexibility in writing+    scripts to transform Pandoc documents. Scripts can now change+    how each element is rendered in each output format.++  * You can now define LaTeX macros in markdown documents, and pandoc+    will apply them to TeX math.  For example,++        \newcommand{\plus}[2]{#1 + #2}+        $\plus{3}{4}$++    yields `3+4`.  Since the macros are applied in the reader, they+    will work in every output format, not just LaTeX.++  * LaTeX macros can also be used in LaTeX documents (both in math+    and in non-math contexts).++  * A new `--mathjax` option has been added for displaying+    math in HTML using MathJax.  Resolves issue #259.++  * Footnotes are now supported in the RST reader. (Note, however,+    that unlike docutils, pandoc ignores the numeral or symbol used in+    the note; footnotes are put in an auto-numbered ordered list.)+    Resolves Issue #258.++  * A new `--normalize` option causes pandoc to normalize the AST+    before writing the document.  This means that, for example,+    `*hi**there*` will be rendered as `<em>hithere</em>`+    instead of `<em>hi</em><em>there</em>`.  This is not the default,+    because there is a significant performance penalty.++  * A new `--chapters` command-line option causes headers+    in DocBook, LaTeX, and ConTeXt to start with "chapter" (level one).+    Resolves Issue #265.++  * In DocBook output, `<chapter>` is now used for top-level+    headers if the template contains `<book>`. Resolves Issue #265.++  * A new `--listings` option in `pandoc` and `markdown2pdf` causes+    the LaTeX writer to use the listings package for code blocks.+    (Thanks to Josef Svennigsson for the pandoc patch, and Etienne+    Millon for the markdown2pdf patch.)++  * `markdown2pdf` now supports `--data-dir`.++  * URLs in autolinks now have class "url" so they can be styled.++  * Improved prettyprinting in most formats.  Lines will be wrapped+    more evenly and duplicate blank lines avoided.++  * New `--columns` command-line option sets the column width for+    line wrapping and relative width calculations for tables.++  * Made `--smart` work in HTML, RST, and Textile readers, as well+    as markdown.++  * Added `--html5` option for HTML5 output.++  * Added support for listings package in LaTeX reader+    (Puneeth Chaganti).++  * Added support for simple tables in the LaTeX reader.++  * Added support for simple tables in the HTML reader.++  * Significant performance improvements in many readers and writers.++  [API and program changes]++  * Moved `Text.Pandoc.Definition` from the `pandoc` package to a new+    auxiliary package, `pandoc-types`. This will make it possible for other+    programs to supply output in Pandoc format, without depending on the whole+    pandoc package.++  * Added `Attr` field to `Code`.++  * Removed `RawHtml`, `HtmlInline`, and `TeX` elements; added generic+    `RawBlock` and `RawInline`.++  * Moved generic functions to `Text.Pandoc.Generic`. Deprecated+    `processWith`, replacing it with two functions, `bottomUp` and `topDown`.+    Removed previously deprecated functions `processPandoc` and `queryPandoc`.++  * Added `Text.Pandoc.Builder`, for building `Pandoc` structures.++  * `Text.Pandoc` now exports association lists `readers` and `writers`.++  * Added `Text.Pandoc.Readers.Native`, which exports `readNative`.+    `readNative` can now read full pandoc documents, block lists, blocks,+    inline lists, or inlines.  It will interpret `Str "hi"`+    as if it were `Pandoc (Meta [] [] []) [Plain [Str "hi"]]`.+    This should make testing easier.++  * Removed deprecated `-C/--custom-header` option.+    Use `--template` instead.++  * `--biblio-file` has been replaced by `--bibliography`.+    `--biblio-format` has been removed; pandoc now guesses the format+    from the file extension (see README).++  * pandoc will treat an argument as a URI only if it has an+    `http(s)` scheme.  Previously pandoc would treat some+    Windows pathnames beginning with `C:/` as URIs.++  * The `--sanitize-html` option and the `stateSanitize` field in+    `ParserState` have been removed. Sanitization is better done in the+    resulting HTML using `xss-sanitize`, which is based on pandoc's+    sanitization, but improved.++  * pandoc now adds a newline to the end of its output in fragment+    mode (= not `--standalone`).++  * Added support for `lang` in `html` tag in the HTML template,+    so you can do `pandoc -s -V lang=es`, for example.++  * `highlightHtml` in `Text.Pandoc.Highlighting` now takes+    a boolean argument that selects between "inline" and+    "block" HTML.++  * `Text.Pandoc.Writers.RTF` now exports `rtfEmbedImage`.+    Images are embedded in RTF output when possible (png, jpeg).+    Resolves Issue #275.++  * Added `Text.Pandoc.Pretty`. This is better suited for pandoc than the+    `pretty` package.  Changed all writers that used+    `Text.PrettyPrint.HughesPJ` to use `Text.Pandoc.Pretty` instead.++  * Rewrote `writeNative` using the new prettyprinting module. It is+    now much faster. The output has been made more consistent and compressed.+    `writeNative` is also now sensitive to writerStandalone`, and will simply+    `print a block list if writerStandalone` is False.++  * Removed `Text.Pandoc.Blocks`. `Text.Pandoc.Pretty` allows you to define+    blocks and concatenate them, so a separate module is no longer needed.++  * `Text.Pandoc.Shared`:++    + Added `writerColumns`, `writerChapters`, and `writerHtml5` to+      `WriterOptions`.+    + Added `normalize`.+    + Removed unneeded prettyprinting functions:+      `wrapped`, `wrapIfNeeded`, `wrappedTeX`, `wrapTeXIfNeeded`, `hang'`,+      `BlockWrapper`, `wrappedBlocksToDoc`.+    + Made `splitBy` take a test instead of an element.+    + Added `findDataFile`, refactored `readDataFile`.+    + Added `stringify`. Rewrote `inlineListToIdentifier` using `stringify`.+    + Fixed `inlineListToIdentifier` to treat '\160' as ' '.++  * `Text.Pandoc.Readers.HTML`:++    + Removed `rawHtmlBlock`, `anyHtmlBlockTag`, `anyHtmlInlineTag`,+      `anyHtmlTag`, `anyHtmlEndTag`, `htmlEndTag`, `extractTagType`,+      `htmlBlockElement`, `htmlComment`+    + Added `htmlTag`, `htmlInBalanced`, `isInlineTag`, `isBlockTag`,+      `isTextTag`++  * Moved `smartPunctuation` from `Text.Pandoc.Readers.Markdown`+    to `Text.Pandoc.Readers.Parsing`, and parameterized it with+    an inline parser.++  * Added `nonspaceChar` to `Text.Pandoc.Parsing`.++  * Ellipses are no longer allowed to contain spaces.+    Previously we allowed '. . .', ' . . . ', etc.  This caused+    too many complications, and removed author's flexibility in+    combining ellipses with spaces and periods.++  * Allow linebreaks in URLs (treat as spaces). Also, a string of+    consecutive spaces or tabs is now parsed as a single space. If you have+    multiple spaces in your URL, use `%20%20`.++  * `Text.Pandoc.Parsing`:++    + Removed `refsMatch`.+    + Hid `Key` constructor.+    + Removed custom `Ord` and `Eq` instances for `Key`.+    + Added `toKey` and `fromKey` to convert between `Key` and `[Inline]`.+    + Generalized type on `readWith`.++  * Small change in calculation of relative widths of table columns.+    If the size of the header > the specified column width, use+    the header size as 100% for purposes of calculating+    relative widths of columns.++  * Markdown writer now uses some pandoc-specific features when `--strict`+    is not specified: `\` newline is used for a hard linebreak instead of+    two spaces then a newline. And delimited code blocks are used when+    there are attributes.++  * HTML writer:  improved gladTeX output by setting ENV appropriately+    for display or inline math (Jonathan Daugherty).++  * LaTeX writer: Use `\paragraph`, `\subparagraph` for level 4,5 headers.++  * LaTeX reader:++    + `\label{foo}` and `\ref{foo}` now become `{foo}` instead of `(foo)`.+    + `\index{}` commands are skipped.++  * Added `fontsize` variable to default LaTeX template.+    This makes it easy to set the font size using `markdown2pdf`:+    `markdown2pdf -V fontsize=12pt input.txt`.++  * Fixed problem with strikeout in LaTeX headers when using+    hyperref, by adding a command to the default LaTeX template+    that disables `\sout` inside pdf strings. Thanks to Joost Kremers+    for the fix.++  * The `COLUMNS` environment variable no longer has any effect.++  [under-the-hood improvements]++  * Pandoc now compiles with GHC 7. (This alone leads to a+    significant performance improvement, 15-20%.)++  * Completely rewrote HTML reader using tagsoup as a lexer. The+    new reader is faster and more accurate.  Unlike the+    old reader, it does not get bogged down on some input+    (Issues #277, 255). And it handles namespaces in tags+    (Issue #274).++  * Replaced `escapeStringAsXML` with a faster version.++  * Rewrote `spaceChar` and some other parsers in Text.Pandoc.Parsing+    for a significant performance boost.++  * Improved performance of all readers by rewriting parsers.++  * Simplified Text.Pandoc.CharacterReferences by using+    entity lookup functions from TagSoup.++  * `Text.Pandoc.UTF8` now uses the unicode-aware IO functions+    from `System.IO` if base >= 4.2.  This gives support for+    windows line endings on windows.++  * Remove duplications in documentation by generating the+    pandoc man page from README, using `MakeManPage.hs`.++  * README now includes a full description of markdown syntax,+    including non-pandoc-specific parts.  A new `pandoc_markdown`+    man page is extracted from this, so you can look up markdown+    syntax by doing `man pandoc_markdown`.++  * Completely revised test framework (with help from Nathan Gass).+    The new test framework is built when the `tests` Cabal flag is set. It+    includes the old integration tests, but also some new unit and quickcheck+    tests. Test output has been much improved, and you can now specify a glob+    pattern after `cabal test` to indicate which tests should be run;+    for example `cabal test citations` will run all the citation tests.++  * Added a shell script, `stripansi.sh`, for filtering ANSI control+    sequences from test output: `cabal test | ./stripansi.sh > test.log`.++  * Added `Interact.hs` to make it easier to use ghci while developing.+    `Interact.hs` loads `ghci` from the `src` directory, specifying+    all the options needed to load pandoc modules (including+    specific package dependencies, which it gets by parsing+    dist/setup-config).++  * Added `Benchmark.hs`, testing all readers + writers using criterion.++  * Added `stats.sh`, to make it easier to collect and archive+    benchmark and lines-of-code stats.++  * Added upper bounds to all cabal dependencies.++  * Include man pages in extra-source-files.  This allows users to+    install pandoc from the tarball without needing to build the man+    pages.++  [bug fixes]++  * Filenames are encoded as UTF8.  Resolves Issue #252.++  * Handle curly quotes better in `--smart` mode. Previously, curly quotes+    were just parsed literally, leading to problems in some output formats.+    Now they are parsed as `Quoted` inlines, if `--smart` is specified.+    Resolves Issue #270.++  * Text.Pandoc.Parsing: Fixed bug in grid table parser.+    Spaces at end of line were not being stripped properly,+    resulting in unintended LineBreaks.++  * Markdown reader:++    + Allow HTML comments as inline elements in markdown.+      So, `aaa <!-- comment --> bbb` can be a single paragraph.+    + Fixed superscripts with links: `^[link](/foo)^` gets+      recognized as a superscripted link, not an inline note followed by+      garbage.+    + Fixed regression, making markdown reference keys case-insensitive again.+      Resolves Issue #272.+    + Properly handle abbreviations (like `Mr.`) at the end of a line.+    + Better handling of intraword underscores, avoiding exponential+      slowdowns in some cases.  Resolves Issue #182.+    + Fixed bug in alignments in tables with blank rows in the header.++  * RST reader:++    + Field lists now allow spaces in field names, and+      block content in field values. (Thanks to Lachlan Musicman+      for pointing out the bug.)+    + Definition list items are now always `Para` instead of+      `Plain`, matching behavior of `rst2xml.py`.+    + In image blocks, the description is parsed properly and+      used for the alt attribute, not also the title.+    + Skip blank lines at beginning of file. Resolves+      Debian #611328.++  * LaTeX reader:++    + Improved parsing of preamble.+      Previously you'd get unexpected behavior on a document that+      contained `\begin{document}` in, say, a verbatim block.+    + Allow spaces between `\begin` or `\end` and `{`.+    + Support `\L` and `\l`.+    + Skip comments inside paragraphs.++  * LaTeX writer:++    + Escape strings in `\href{..}`.+    + In nonsimple tables, put cells in `\parbox`.++  * OpenDocument writer:  don't print raw TeX.++  * Markdown writer:++    + Fixed bug in `Image`.  URI was getting unescaped twice!+    + Avoid printing extra blank lines at the end if there are+      no notes or references.++  * LaTeX and ConTeXt: Escape `[` and `]` as `{[}` and `{]}`.+    This avoids unwanted interpretation as an optional argument.++  * ConTeXt writer: Fixed problem with inline code.  Previously+    `}` would be rendered `\type{}}`. Now we check the string for '}' and '{'.+    If it contains neither, use `\type{}`; otherwise use `\mono{}`+    with an escaped version of the string.++  * `:` now allowed in HTML tags. Resolves Issue #274.++pandoc (1.6)++  [ John MacFarlane ]++  * New EPUB and HTML Slidy writers. (Issue #122)++      - EPUB is a standard ebook format, used in Apple's iBooks for+        the iPad and iPhone, Barnes and Noble's nook reader, the Sony+        reader, and many other devices.+      - Slidy, like S5, is a system for producing HTML+javascript slide+        shows.++  * All input is assumed to be UTF-8, no matter what the locale and ghc+    version, and all output is UTF-8. This reverts to pre-1.5 behavior.+    Also, a BOM, if present, is stripped from the input.++  * Markdown now supports grid tables, whose cells can contain+    arbitrary block elements. (Issue #43)++  * Sequentially numbered example lists in markdown with `@` marker.++  * Markdown table captions can begin with a bare colon and no longer need+    to include the English word "table." Also, a caption can now occur+    either before or after the table. (Issue #227)++  * New command-line options:++      - `--epub-stylesheet` allows you to specify a CSS file that will+        be used to style your ebook.+      - `--epub-metadata` allows you to specify metadata for the ebook.+      - `--offline` causes the generated HTML slideshow to include all+        needed scripts and stylesheets.+      - `--webtex` causes TeX math to be converted to images using the+        Google Charts API (unless a different URL is specified).+      - `--section-divs` causes div tags to be added around each section+        in an HTML document. (Issue #230, 239)++  * Default behavior of S5 writer in standalone mode has changed:+    previously, it would include all needed scripts and stylesheets+    in the generated HTML; now, only links are included unless+    the `--offline` option is used.++  * Default behavior of HTML writer has changed. Between 1.2 and 1.5,+    pandoc would enclose sections in div tags with identifiers on the+    div tags, so that the sections can be manipulated in javascript.+    This caused undesirable interactions with raw HTML div tags. So,+    starting with 1.6, the default is to put the identifiers directly+    on the header tags, and not to include the divs.  The `--section-divs`+    option selects the 1.2-1.5 behavior.++  * API changes:++      - `HTMLMathMethod`: Added `WebTeX`, removed `MimeTeX`.+      - `WriterOptions`: Added `writerUserDataDir`, `writerSourceDirectory`,+        `writerEPUBMetadata` fields. Removed `writerIncludeBefore`,+        `writerIncludeAfter`.+      - Added `headerShift` to `Text.Pandoc.Shared`.+      - Moved parsing code and `ParserState` from `Text.Pandoc.Shared`+        to a new module, `Text.Pandoc.Parsing`.+      - Added `stateHasChapters` to `ParserState`.+      - Added `HTMLSlideVariant`.+      - Made `KeyTable` a map instead of an association list.+      - Added accessors for `Meta` fields (`docTitle`, `docAuthors`,+        `docDate`).+      - `Pandoc`, `Meta`, `Inline`, and `Block` have been given `Ord`+        instances.+      - Reference keys now have a type of their own (`Key`), with its+        own `Ord` instance for case-insensitive comparison.+      - Added `Text.Pandoc.Writers.EPUB`.+      - Added `Text.Pandoc.UUID`.+      - Removed `Text.Pandoc.ODT`, added `Text.Pandoc.Writers.ODT`.+        Removed `saveOpenDocumentAsODT`, added `writeODT`.+      - Added `Text.Pandoc.Writers.Native` and `writeNative`.+        Removed `prettyPandoc`.+      - Added `Text.Pandoc.UTF8` for portable UTF8 string IO.+      - Removed `Text.Pandoc.Writers.S5` and the `writeS5` function.+        Moved `s5Includes` to a new module, `Text.Pandoc.S5`.+        To write S5, you now use `writeHtml` with `writerSlideVariant`+        set to `S5Slides` or `SlidySlides`.++  * Template changes.  If you use custom templates, please update them,+    particularly if you use syntax highlighting with pandoc. The old HTML+    templates hardcoded highlighting CSS that will no longer work with+    the most recent version of highlighting-kate.++      - HTML template: avoid empty meta tag if no date.+      - HTML template: Use default highlighting CSS from highlighting-kate+        instead of hard-coding the CSS into the template.+      - HTML template: insert-before text goes before the title, and+        immediately after the <body> tag, as documented. (Issue #241)+      - Added slidy and s5 templates.+      - Added amssymb to preamble of latex template. (github Issue 1)++  * Removed excess newlines at the end of output. Note: because output+    will not contain an extra newline, you may need to make adjustments+    if you are inserting pandoc's output into a template.++  * In S5 and slidy, horizontal rules now cause a new slide, so you+    are no longer limited to one slide per section.++  * Improved handling of code in man writer. Inline code is now monospace,+    not bold, and code blocks now use .nf (no fill) and .IP (indented para).++  * HTML reader parses `<tt>` as Code. (Issue #247)++  * html+lhs output now contains bird tracks, even when compiled without+    highlighting support. (Issue #242)++  * Colons are now no longer allowed in autogenerated XML/HTML identifiers,+    since they have a special meaning in XML.++  * Code improvements in ODT writer.  Remote images are now replaced with+    their alt text rather than a broken link.++  * LaTeX reader improvements:++      - Made latex `\section`, `\chapter` parsers more forgiving of+        whitespace.+      - Parse `\chapter{}` in latex.+      - Changed `rawLaTeXInline` to accept `\section`, `\begin`, etc.+      - Use new `rawLaTeXInline'` in LaTeX reader, and export `rawLaTeXInline`+        for use in markdown reader.+      - Fixes bug wherein `\section{foo}` was not recognized as raw TeX+        in markdown document.++  * LaTeX writer:  images are automatically shrunk if they would extend+    beyond the page margin.++  * Plain, markdown, RST writers now use unicode for smart punctuation.++  * Man writer converts math to unicode when possible, as in other writers.++  * `markdown2pdf` can now recognize citeproc options.++  * Command-line arguments are converted to UTF-8. (Issue #234)++  * `Text.Pandoc.TeXMath` has been rewritten to use texmath's parser.+    This allows it to handle a wider range of formulas. Also, if a formula+    cannot be converted, it is left in raw TeX; formulas are no longer+    partially converted.++  * Unicode curly quotes are left alone when parsing smart quotes. (Issue+    #143)++  * Cabal file changes:++      - Removed parsec < 3 restriction.+      - Added 'threaded' flag for architectures where GHC lacks a threaded+        runtime.+      - Use 'threaded' only for markdown2pdf; it is not needed for pandoc.+      - Require highlighting-kate 0.2.7.++  * Use explicit imports from `Data.Generics`. Otherwise we have a+    conflict with the 'empty' symbol, introduced in syb >= 0.2. (Issue #237)++  * New data files:  slidy/slidy.min.js, slidy/slidy.min.css, epub.css.++pandoc (1.5.1.1)++  [ John MacFarlane ]++  * Fixed uniqueIdent in Shared so that header identifiers work as+   advertized in the README and are are valid XHTML names.++pandoc (1.5.1)++  [ John MacFarlane ]++  * Fixed treatment of unicode characters in URIs.+    + Shared now exports escapeURI and unescapeURI. These handle+      UTF8 encoding and decoding as well as URI escaping/unescaping.+    + Shared: uri and emailAddress now return a pair of the original+      parsed text and the escaped URI (in the latter case, with+      the mailto: prefix).+    + HTML reader: unsanitaryURI has been modified to allow unicode+      high characters in a URI.+    + Readers:  All link and image URIs are now escaped using+      escapeURI.+    + Markdown and RST writers:  unescapeURI is used so that URIs+      in these formats are human-readable.++  * Setup.hs: Don't assume that the build directory is "dist".+    Instead, get it from localBuildInfo.++  * OpenDocument writer: Use a Map for stTextStyleAttr.+    This avoids duplicates (and invalid xml). Resolves Issue #222.++pandoc (1.5.0.1)++  [ John MacFarlane ]++  * HTML writer: Fixed error in math writer (with MathML option)+    that caused an infinite loop for unparsable MathML.++pandoc (1.5)++  [ John MacFarlane ]++  * Added --mathml option.  When this is selected, pandoc will convert+    TeX math into MathML.+    + Added data/MathMLinHTML.js, which is included when no URL is+      provided for --mathml.  This allows MathML to be displayed (in+      better browsers) as text/html.+    + Removed Text.Pandoc.LaTeXMathML.  The module was no longer+      necessary; it was replaced by two lines in pandoc.hs.+    + Replaced LaTeXMathML.js.commend and LaTeXMathML.js.packed with a+      single combined file, LaTeXMathML.js.++  * Added --data-dir option.+    This specifies a user data directory. If not specified, will default+    to ~/.pandoc on unix or Application Data\pandoc on Windows.+    Files placed in the user data directory will override system default+    data files.++  * Added Maybe datadir parameter to readDataFile, saveOpenDocumentAsODT,+    latexMathMLScript, s5HeaderIncludes, and getDefaultTemplate. If+	  Nothing, no user directory is searched for an override.++  * Added 'plain' output format. This is similar to markdown, but+    removes links, pictures, inline formatting, and most anything that+    looks even vaguely markupish. The function writePlain is exported by+    Text.Pandoc.Writers.Markdown, with which it shares most of its code.++  * Allow multi-line titles and authors in meta block.+    Titles may span multiple lines, provided continuation lines+    begin with a space character.  Separate authors may be put on+    multiple lines, provided each line after the first begins with+    a space character.  Each author must fit on one line. Multiple+    authors on a single line may still be separated by a semicolon.+    Based on a patch by Justin Bogner.++  * When given an absolute URI as parameter, pandoc will try to fetch+    the content via HTTP.  So you can do:+    'pandoc -r html -w markdown http://www.fsf.org'+    Adds dependency on HTTP.++  * Made HTML reader much more forgiving.+    + Incorporated idea (from HXT) that an element can be closed+      by an open tag for another element.+    + Javascript is partially parsed to make sure that a <script>+      section is not closed by a </script> in a comment or string.+    + More lenient non-quoted attribute values.+      Now we accept anything but a space character, quote, or <>.+      This helps in parsing e.g. www.google.com!+    + Bare & signs are now parsed as a string.  This is a common+      HTML mistake.+    + Skip a bare < in malformed HTML.++  * Removed html2markdown and hsmarkdown.+    + html2markdown is no longer needed, since you can now pass URI+      arguments to pandoc and directly convert web pages. (Note,+      however, that pandoc assumes the pages are UTF8. html2markdown+      made an attempt to guess the encoding and convert them.)+    + hsmarkdown is pointless -- a large executable that could be+      replaced by 'pandoc --strict'.++  * In most writers, an image in a paragraph by itself is now rendered+    as a figure, with the alt text as the caption. (Texinfo, HTML, RST,+    MediaWiki, Docbook, LaTeX, ConTeXt, HTML.) Other images are+    rendered inline.++  * Depend on extensible-exceptions.  This allows pandoc to be compiled+    on GHC 6.8.++  * Added --base-header-level option.  For example, --base-header-level=2+    will change level 1 headers to level 2, level 2 to level 3, etc.+    Closes Debian #563416.++  * Incomplete support for RST tables (simple and grid).+    Thanks to Eric Kow. Colspans and rowspans not yet supported.++  * Added accessors (docTitle, docAuthors, docDate) to Meta type.++  * MediaWiki writer:  format links with relative URLs as wikilinks.+    The new rule:  If the link target is an absolute URL, an external+    link is created. Otherwise, a wikilink is created.++  * Text.Pandoc.Shared: Export uniqueIdent, and don't allow tilde in+    identifier.  Note:  This may break links to sections that involve+    tildes.++  * Markdown(+lhs) reader:  handle "inverse bird tracks."+    Inverse bird tracks (<) are used for haskell example code that is not+    part of the literate Haskell program.  Resolves Issue #211.++  * LaTeX reader:+    + Recognize '\ ' (interword space).+    + Recognize nonbreaking space '~'.+    + Ignore \section, \pdfannot, \pdfstringdef.  Ignore alt title in+      section headers.  Don't treat \section as inline LaTeX.+      Resolves Issue #202.+    + LaTeX reader:  allow any special character to be escaped.+      Resolves Issue #221.+    + LaTeX reader: treat \paragraph and \subparagraph as level 4, 5+      headers.  Resolves Issue #207.++  * Use template variables for include-before/after.+    + These options now imply -s; previously they worked also in fragment+      mode.+    + Users can now adjust position of include-before and include-after+      text in the templates.+    + Default position of include-before moved back (as it was before 1.4)+      before table of contents.+    + Resolves Issue #217.++  * Don't print an empty table header: (all writers).+    Resolves Issue #210.++  * HTML, Docbook writer: Use tbody, thead, and cols in tables.++  * HTML writer: Don't include TOC div if table of contents is empty.++  * Markdown writer:  Fixed citations.+    Previously the markdown writer printed raw citation codes, e.g.+    [geach1970], rather than the expanded citations provided by+    citeproc, e.g. (Geach 1970). Now it prints the expanded citations.+    This means that the document produced can be processed as a markdown+    document without citeproc. Thanks to dsanson for reporting, and+    Andrea Rossato for the patch.++  * Improved and simplified title block in context template.+    Previously it caused an error if there was no title.+    This method should also be easier for users to customize.++  * Markdown reader:+    + Treat p., pp., sec., ch., as abbreviations in smart mode.+    + Disallow blank lines in inline code span.+    + Allow footnotes to be indented < 4 spaces.+      This fixes a regression.  A test case has been added.+    + Escape spaces in URLs as %20. Previously they were incorrectly+		  escaped as +, which is appropriate only for the query part of+			a URL. Resolves Issue #220.+    + Require two spaces after capital letter + period for list item.+      Otherwise "E. coli" starts a list. This might change the semantics+      of some existing documents, since previously the two-space+      requirement was only enforced when the second word started+      with a capital letter. But it is consistent with the existing+      documentation and follows the principle of least surprise.+      Resolves Issue #212.++  * LaTeX template: redefine labelwidth when using enumerate package.+    Otherwise the list labels (numbers) often extend past the left+    margin, which looks bad.++  * Mediawiki writer: Don't print a "== Notes ==" header before+    references.  This is too English-centric. Writers can provide their+    own header at the end of the document.++  * Promoted mediawiki headers.  '= head =' is now level 1, '== head =='+    level 2, etc.  This seems to be correct; it's only by convention+    that wikipedia articles have level 2 headers at most.+    Patch due to Eric Kow.++  * RunTests.hs: Set LANG to a UTF-8 locale. Use 'pandoc --data-dir=' so+    data files don't need to have been installed. This removes the need to+    set HOME.++  * HTML reader:+    + Handle spaces before <html>.  Resolves Issue #216.+    + Be forgiving in parsing a bare list within a list.+      The following is not valid xhtml, but the intent is clear:+      <ol>+      <li>one</li>+      <ol><li>sub</li></ol>+      <li>two</li>+      </ol>+      We'll treat the <ol> as if it's in a <li>.  Resolves Issue #215.++  * Updated INSTALL instructions.  cabal method is now promoted.++  * Updated markdown2pdf man page. It no longer says all pandoc options+    are accepted.++  * README/man pages: Removed advice to pipe through tidy before HTML+    reader.  This is obsolete, now that we have a forgiving HTML parser.++  * LaTeX writer: set numbersections template variable, so+    the section numbering options work again.++  * Removed obsolete Makefile.++  * Website: renamed index.txt.in -> index.txt.++  * New batch file to make-windows-installer.+    + Removed old Makefile.windows+    + Added make-windows-installer.bat+    + Modified default installer name in pandoc-setup.iss++  * Removed freebsd and macports directories.+    They are no longer up to date.++  * Setup.hs:+    + Made man page building sensitive to build verbosity.+    + Improved detection of highlighting support in test hook.+    + Install wrapper scripts into cabal bin directory.+    + Also simplified installManpages.+    + Setup.hs: install manpages to mandir.  Code borrowed from darcs.++  * Changed default of writerXeTeX to False.++  * HTML writer: don't include empty UL if --toc but no sections.+    Resolves Issue #199.++  * LaTeX writer:++    + If book, report, or memoir documentclass, use \chapter{}+      for first-level headers. Otherwise use \section{}.+    + Removed stLink, link template variable. Reason: we now always+      include hyperref in the template.++  * LaTeX template:++    + Only show \author if there are some.+    + Always include hyperref package. It is used not just for links but+      for toc, section heading bookmarks, footnotes, etc. Also added+      unicode=true on hyperref options.++  * markdown2pdf: always do at least two runs. hyperref bookmarks+    require this.++  * cabal file: Removed unneeded dependency on template-haskell.++  * Windows installer - fixed bug in data file locations.+    Resolves Issue #197.++  * Deprecated --custom-header in documentation.+    Removed old "Custom Headers" section in README.++pandoc (1.4)++  [ John MacFarlane ]++  * Pandoc will now compile with either GHC 6.10 or 6.12.+    + Don't use System.IO.UTF8 when compiling with 6.12+    + Use -fno-warn-unused-do-bind option when compiling with 6.12++  * Replaced old headers with templates.  Now users have much more+    control over the way documents appear in --standalone mode,+    and writer code is simplified.  Resolves Issues #59, 147.+    Every effort has been made to retain backwards compatibilty.+    So, the --custom-header option should still work as before.++    + Added Text.Pandoc.Templates.  This provides functions for+      retrieving default templates and for rendering templates.+    + System templates (in the pandoc data directory) can be+      overridden by user templates in $HOME/.pandoc/templates.+    + Removed Text.Pandoc.DefaultHeaders.+    + Removed data/headers directory.+    + Added templates directory.+    + Added writerTemplate and writerVariables fields to WriterOptions.+    + Removed writerTitlePrefix, writerHeader fields from WriterOptions.+    + Changed --print-default-header to --print-default-template.+    + Added --template option.+    + Added -V/--variable option to set custom template variables.++  * Pandoc no longer requires Template Haskell.  Resolves Issue #186.++    + Removed need for TH in ODT module. Instead get reference.odt from+	  data file at run time.+    + Removed TH dependency from S5 module. S5 module now exports+      s5HeaderIncludes, which pandoc.hs includes if writer is s5 and+      standalone.+    + Refactored LaTeXMathML not to use TH.++  * Meta is now Meta [Inline] [[Inline]] [Inline] rather than+    Meta [Inline] [String] String. Authors and date in Meta are now lists+    of Inline elements rather than raw strings. This means that they can+    be formatted and can include footnotes. NOTE: This may be a breaking+    change for those using pandoc as a library.++  * Added readDataFile to Text.Pandoc.Shared.  This retrieves+    a data file from the user pandoc data directory (~/.pandoc+    on unix), or, if not found there, from the system data+    directory ($CABALDIR/shared/pandoc-VERSION/). All data+    files, including templates, LaTeXMathML.js, s5 styles,+	and reference.odt, can be overridden by the user.++  * s5 files moved from data/ui/default to s5/default.++  * Use unicode instead of entities in HTML and XML output.  Resolves+    Issue #163.++  * Prettier HTML footnote references:  put anchor inside sup,+    instead of other way.  Resolves Issue #191. Thanks to+    infinity0x.++  * Added --xetex option to pandoc and markdown2pdf.+    If --xetex is specified, pandoc produces latex suitable for+    processing by xelatex, and markdown2pdf uses xelatex to create+    the PDF. Resolves Issue #185.++  * RTF writer: multiple authors now occupy multiple paragraphs rather+    than using a line break.++  * Man writer: now the "--after-body" will come after the "AUTHORS"+    section, whereas before it would come before it.  This is a+    slight break from backwards compatibility.++  * Added --reference-odt option, so users may customize the styles+    used in pandoc-generated ODT files.  Users may also place a+	default reference.odt in the ~\.pandoc directory.++  * ODT writer:+    + Indented and line-broke styles.xml so it can be modified more easily.+    + Omitted some unnecessary style declarations.+    + Don't wrap text in OpenDocument writer.  The tags are too long, making+      wrapping ugly and pointless.++  * LaTeX reader: use \\ to separate multiple authors.++  * Markdown reader: use ; as separator between authors.+    This allows you to use ',' within author names: e.g. "John Jones, Jr."++  * S5 writer: use linebreak to separate authors in title page.++  * RST reader: Allow :: before lhs code block. The RST spec requires the+    :: before verbatim blocks. This :: should not be treated as literal+    colons. Resolves Issue #189.++  * Documented pandoc 1.3's new definition list syntax in README.+    (An oversight in the last release.)++  * markdown2pdf.hs:+    + interpret ! in a log as an error line.+    + --toc now works properly.++  * Changes in RunTests.hs:+    + Use the Diff library rather than a local copy of Diff.hs.+      (This vastly increases performance.) This change means that 'cabal+      test' presupposes that the Diff library is installed.+    + Removed tests/Diff.hs from cabal file.+    + Changed RunTests to use local environment. We need at least HOME, so+      pandoc can find its data directory.++  * Updated windows installer to install data files in the app directory.++  * Windows installer now installs portable wrappers hsmarkdown and+    markdown2pdf.++pandoc (1.3)++  [ John MacFarlane ]++  * Added --id-prefix option (Issue #41). This adds a prefix to all+    automatically generated HTML identifiers, which helps prevent+    duplicate identifiers when you're generating a fragment (say a blog+    post).++  * Added --indented-code-classes option.  This specifies classes+    to use for indented code blocks.  (Patch due to buttock; Issue #87.)++  * --number-sections now affects HTML output as well as ConTeXt and LaTeX+    (Issue #150).++  * Improved syntax for markdown definition lists (Issue #24).+    Definition lists are now more compatible with PHP Markdown Extra.+    + You can have multiple definitions for a term (but still not+      multiple terms).+    + Multi-block definitions no longer need a column before each block+      (indeed, this will now cause multiple definitions).+    + The marker no longer needs to be flush with the left margin,+      but can be indented at or two spaces.  Also, ~ as well as :+      can be used as the marker (this suggestion due to David+      Wheeler.)+    + There can now be a blank line between the term and the+      definitions.++  * Better looking simple tables.  Resolves Issue #180.+    + Markdown reader: simple tables are now given column widths of 0.+    + Column width of 0 is interpreted as meaning: use default column width.+    + Writers now include explicit column width information only+      for multiline tables.  (Exception:  RTF writer, which requires+      column widths.  In this case, columns are given equal widths,+      adding up to the text width.)+    + Simple tables should now look better in most output formats.++  * Allow markdown tables without headers (Issue #50).+    The new syntax is described in README. Also allow optional line of+    dashes at bottom of simple tables.++  * Compensate for width of final table column (Issue #144).++  * Treat a backslash followed by a newline as a hard line break+    in markdown.  Resolves Issue #154.  This is a nice alternative+	to markdown's "invisible" way of indicating hardline breaks+	using lines that end with two spaces.++  * Improved performance of markdown reader by ~10% by eliminating the+    need for a separate parsing pass for notes. Raw notes are now stored+    on the first pass (which parses references), then parsed when the+    note is inserted into the AST. The stateNotes field in ParserState+    is now a list of [(String, String)] pairs instead of [(String,+    [Block])].++  * In markdown reader, treat 4 or more * or _ in a row as literal+    text.  (Trying to parse long strings of * or _ as strong or emph+	leads to exponential performance problems.)++  * Markdown reader: Use + rather than %20 for spaces in URLs.++  * Fixed htmlComment parser, adding a needed 'try'.++  * Don't print raw HTML in man output.++  * Allow . _ and ~ in header identifiers.++  * Specially mark code blocks that were "literate" in the input.+    They can then be treated differently in the writers.  This allows+    authors to distinguish bits of the literate program they are writing+    from source code examples, even if the examples are marked as+    Haskell for highlighting.  (Issue #174.)++  * Modified html+lhs output to use "haskell" highlighter instead+    of "literateHaskell". The highlighting module now adds bird tracks+	after highlighting (for HTML output), if the code block has the+	"literate" class.  This gives better results, because kate's+    haskell highlighter is much better than the literateHaskell+    highlighter.++  * Fixed handling of footnotes in titles (HTML) and headers (LaTeX).+    (Issue #137.)++  * Support for "..code-block" directive in RST reader. Not core+    RST, but used in Sphinx for code blocks annotated with syntax+    information. Thanks to Luke Plant for the patch.++  * Added "head" to list of block-level HTML tags. Resolves+    Issue #108.++  * Added stripTags to Text.Pandoc.XML.  This is used in the HTML writer.++  * Set utf-8 encoding in texinfo headers.++  * Docbook writer: add ids to sections.  Use link for internal links.+    (Issue #60.)++  * Blank lines after lists in MediaWiki writer.++  * Properly handle commented-out list items in markdown.+    Resolves Issue #142.  Example:++    - a+    <!--+    - b+    -->+    - c++  * Changed heuristic in compactify. compactify has to decide whether a+    Para that ends a list is a Para intentionally, or just because of+    the blank lines at the end of every list. In the latter case the+    Para is turned to a Plain. The old heuristic was: change final Para+    to Plain iff the other items all end in Plain. This produces bad+    results when, for example, an item contains just a Plain and an HTML+    comment, as it does in the list above. The new heuristic: change+    final Para to Plain iff the other items don't contain a Para.++  * Added % as an rst underline character.  Resolves Issue #173.++  * Fix inline math parser so that \$ is allowed in math.+    Resolves Issue #169.++  * Translate \int (integral) into unicode when using unicode math+    method. Resolves Issue #177.++  * markdown2pdf.hs improvements:+    + Use System.IO.UTF8.+    + Print error messages on last attempt.+    + Do not create a backup when overwriting a PDF (Issue #166).+    + Accept --longopt=val options.+    + Added man/man1/markdown2pdf.1 to extra-tmp-files in cabal, so that+      it is properly cleaned.++  * Added haddock comments warning that readers assume \n line endings.++  * Updated COPYRIGHT file.++  * Makefile: Changed EXECSBASE so it doesn't pull in hsmarkdown &+    markdown2pdf. Otherwise strip tries to strip shell scripts when you+    install using 'make'.++  * Changed Makefile so it doesn't build Haskell wrappers.++  * Fixed Makefile so it doesn't try to build man pages in build-doc.++  * Install pcre3.dll in Windows install script; this allows us to+    package a version of pandoc with highlighting support.++pandoc (1.2.1)++  [ John MacFarlane ]++  * Fixed regression with --preserveTabs. Brought back optPreserveTabs.+    The trick of setting tabStop to 0 to mean "preserve tabs" had a bad+    side effect: strings of 0 spaces were interpreted as indentation.+    So, with --preserve-tabs, unindented paragraphs were treated as+    code. Resolves Issue #138.++  * HTML writer:  wrap sections in divs.  Resolves Issue #70.++    + hierarchicalize has been rationalized; it builds a hierarchical+      representation of the document from the headers, and simultaneously+      gives each section a unique identifier based on the heading title.+    + Identifiers are now attached to the divs rather than+      to the headers themselves.+    + Table of content backlinks go to the beginning of the table, rather+      than to the section reference that was clicked.+    + Code for constructing identifiers has been moved to Text.Pandoc.Shared+      from the HTML writer, since it is now consumed only by+      hierarchicalize.+    + In --strict mode, pandoc just prints bare headings, as before+      (unless --toc has been specified).+    + In s5 output, it does not wrap sections in divs, as that seems to+      confuse the s5 javascript.++  * Man writer: break lines at end of each sentence. groff expects this+    and treats '.' and '?' differently when followed by line ending as+    opposed to ordinary space. Also, don't escape periods. Instead, use+    zero-width character \& to avoid unwanted interpretation of periods+    at start of line. Resolves Issue #148.++  * Markdown writer:  Added '#' and '>' to list of characters to be+    escaped in markdown output.  Removed '<', as it is not an officially+    escapable character. This partially resolves Issue #96.++  * Make --smart the default for man output format. Otherwise we have+    trouble dividing lists of endlines into sentences.++  * DocBook writer: Use language attribute to indicate source language+    in code blocks.++  * RST reader:++    + Allow # to continue list, even if the list was started with an+      explicit marker. For example:++        A. my list+		#. continued++      Resolves Issue #140.+    + Allow continuation lines in line blocks. Also added test cases for+      line blocks for RST reader. Resolves Issue #149.+    + Allow explicit links with spaces in URL: `link <to this>`_++  * Improved LaTeX reader's coverage of math modes. Remove displaymath*+    (which is not in LaTeX) and recognize all the amsmath environments+    that are alternatives to eqnarray, namely equation, equation*,+    gather, gather*, gathered, multline, multline*, align, align*,+    alignat, alignat*, aligned, alignedat, split. Resolves Issue #103.+    Thanks to shreevatsa.public for the patch.++  * Markdown reader:++    + Allow -, _, :, . in markdown attribute names. These are legal in+      XML attribute names.+    + Use non-breaking spaces in abbreviations.+    + Markdown reader: improved efficiency of abbreviation parsing.+      Instead of a separate abbrev parser, we just check for+      abbreviations each time we parse a string. This gives a huge+      performance boost with -S. Resolves Issue #141.++  * Improved efficiency of shared parsers:  hexNum, htmlComment,+    whitespace, indentSpaces.++  * Export HTMLMathMethod in Text.Pandoc.++  * Export languagesByExtension in Text.Pandoc.Highlighting.++  * Added new Haskell version of markdown2pdf, due to+    Paulo Tanimoto.  This should be more portable than the old+	shell script.++  * Made 'pandoc -v' more explicit about compiler options.+    Resolves Issue #139.++  * pandoc.hs:  Made --strict compatible with --standalone, --toc.++  * Use Paths_pandoc to get version number, instead of hard-coding it+    into Text/Pandoc.hs.++pandoc (1.2)++  [ John MacFarlane ]++  * Added support for literate Haskell. lhs support is triggered by+    '+lhs' suffixes in formats. For example, 'latex+lhs' is literate+    Haskell LaTeX. '.lhs' files are treated by default as literate+    markdown.++    + Added stateLiterateHaskell to parser state.+    + Added parser for lhsCodeBlock to Markdown, RST, LaTeX readers.+    + Added parser for |inline lhs| to LaTeX reader.+    + Added writerLiterateHaskell to WriterOptions.+    + Added lhs support to Markdown, RST, LaTeX, HTML writers.+    + Added definition of code environment to LaTeX header.+    + Added tests (run only if highlighting support compiled in).+    + Documented lhs features in man page and README.++  * In Text.Pandoc.Definition, added processWith, processWithM,+    and queryWith, and deprecated processPandoc and queryPandoc+    for these more general functions.++  * Fixed bug in mediawiki writer:  improper closing tags in tables.+    Thanks to Benct Philip Jonsson for reporting the bug.++  * Added --email-obfuscation option.++    + Added writer option for email obfuscation.+    + Implemented email obfuscation options in HTML writer.+    + Added option to option parser.+    + Documented in README and pandoc man page.+    + Resolves Issue #97.++  * LaTeX writer: fixed bug with empty table cells.+    Resolves Issue #107.  Thanks to rodja.trappe for the patch.++  * Fixed bug with header spacing in Markdown and RST writers.+    A null header (Meta [] [] []) should not cause a blank line+    at the beginning of output.  But a blank line is needed between+    a non-null header and the main text.++  * Markdown reader: Relax spacing rules for $$ in display math. Now+    space and newlines are allowed after the opening $$ and before the+    closing $$. However, the display math cannot contain an entirely+    blank line. Resolves Issue #105.++  * Markdown reader: Gobble space after Plain blocks containing only+    raw html inline. Otherwise following header blocks are not parsed+    correctly, since the parser sees blank space before them. Resolves+    Issue #124.++  * Markdown reader: Allow " as well as '' to end a latex double-quote.++  * Conditionally depend on syb and base >= 4 if ghc >= 6.10.+    Resolves Issue #109.++  * Fixed problems in RST and markdown output due to bug in pretty-1.0.1.0++    + Added hang' function to Text.Pandoc.Shared; this will be used instead+      of hang, which doesn't work properly in pretty-1.0.1.0.  When pretty+      is upgraded, we can go back to hang.+      See  http://article.gmane.org/gmane.comp.lang.haskell.general/16687+    + Use hang' (and some different techniques) in RST and markdown writers.+      Some output is now a bit different.++  * Brought citeproc support up to date for citeproc-hs-0.2.+    (Patch by Andrea Rossato.)++  * Moved all haskell source to src subdirectory.  Renamed Main.hs to+    pandoc.hs.++  * Rewrote hsmarkdown in Haskell for portability (src/hsmarkdown.hs).+    For now, keeping the old shell script too.++  * Added TemplateHaskell to Extensions for executable, removed+    -threaded for library. Thanks to duncan.coutts for the bug report.+    Resolves Issue #121.++  * Moved some Extra-Source-Files to Data-Files.++  * Moved tabFilter to Shared.++  * In pandoc.hs, removed optPreserveTabs; instead, tabstop of 0 means+    preserve tabs.++  * Minor code cleanup based on hlint suggestions.++pandoc (1.1)++  [ John MacFarlane ]++  * Main.hs:++    + Changed date on copyright message in Main.hs.+    + Have the '-v' option print syntax highlighting languages+      separated by commas, and wrapped in lines, instead of in five+      columns as before.++  * Added --jsmath option.  Resolves Issue #68.++    + Added --jsmath option to Main.hs+    + Added JsMath to HTMLMathMethod in Text.Pandoc.Shared.+    + Handle math appropriately in HTML writer when JsMath selected.+    + Documented the option in README and man page.++  * Text.Pandoc.Shared:  Changed compactify to use a better heuristic+    for tight and loose lists. Final Para is changed to Plain if all+    other list items *end* with a Plain block. Addresses Issue #99.++  * HTML reader:++    + Added colons to protocols in unsanitaryURI. Closes Issue #88.+    + HTML reader: Don't interpret contents of <pre> blocks as markdown.+      Added rawVerbatimBlock parser.  Resolves Issue #94.++  * Markdown reader:++    + Allow URLs with spaces in them in links and references, but escape+      them as "%20".+    + Allow blank space at the end of horizontal rules.++  * RST reader: Modified 'unknownDirective' parser to handle comment+    blocks correctly, and added tests for comment blocks. Resolves Issue+    #86. Closes Debian Bug #500662.++  * HTML writer:++    + Include classes on tr elements in HTML output:+      "header", "odd", "even".  This allows tables to be styled with+      lines in alternating colors.  Resolves Issue #91.+    + Enclose all LaTeXMathML bits in <span class="LaTeX">.+      This prevents parts of the document that are not math from being+      interpreted as math by LaTeXMathML.js.++  * OpenDocument and ODT writers:  Added support for HorizontalRule elements,+    which were formerly ignored.  Resolves Issue #95.++  * Text.Pandoc.Shared:  Modified wrappedTeX to eliminate the line break+    between a footnote and immediately following nonspace characters in+    LaTeX and ConTeXt output. (This gets interpreted as a space, which+    is not desired in cases like `text^[note]---`.)  Resolves Issue #93.++  * Windows installer: Don't require admin privileges to run+    installer.  Modified pandoc-setup.iss, and changed modpath.iss to+    modify HKCU path if user lacks admin privileges.  Also fixed case+    where oldpath is empty (previously this led to the new path+    beginning with a semicolon).++  * Updated INSTALL instructions for Arch packages and OS X install using+    cabal-install.++  * Removed the (now unneeded) debian directory.+    Removed empty Codec and System directories.++  * Moved odt-styles/ to data/.  Removed unneeded variable in Makefile.++  * Modified Setup.hs so that the "test" target returns an error status+    when tests fail, and "build" returns a success status if+    the build succeeds.  Resolves Issue #100.++  * Added BUGS to files in tarball.+++pandoc (1.0.0.1)++  [ John MacFarlane ]++  * Removed spurious reference to pdf output format from pandoc(1) man page.++pandoc (1.0)++  [ Andrea Rossato ]++  * Added new OpenDocument writer.++  * Added support for SmallCaps inline element.++  * Added support for integrating pandoc with citeproc-hs.++    + Added Cite element to definition and writers.+    + Added Text.Pandoc.Biblio module+    + Note: This support is included only if the 'citeproc'+      Cabal configuration flag is set.++  * Made Pandoc data structure an instance of Typeable.+    Added new processPandoc and queryPandoc functions, to query+    or transform matching elements in a Pandoc structure.++  [ Peter Wang ]++  * Added new Texinfo writer.++  [ John MacFarlane ]++  * Changes to Texinfo writer:++    + No space between paragraph and following @verbatim (provides more+      pleasing appearance in text formats)+    + Blank line consistently after list environments.+    + Removed deVerb.+    + Use @code instead of @verb for inline code (this solves the character+      escaping problem for texi2dvi and texi2pdf).+    + Added news of Texinfo writer to README.+    + Added Texinfo to list of formats in man page, and removed extra 'groff'.+    + Added texi & texinfo extensions to Main.hs, and fixed bug in determining+      default output extension.+    + Modified disallowedInNode in Texinfo writer to correct list of disallowed characters.++  * Added tests for OpenDocument writer.++  * Added ODT writer (using zip-archive library to package output of+    OpenDocument writer).  Added odt-styles directory with default ODT styles.++  * Added new mediawiki writer and tests.++  * Markdown reader: Added support for delimited code blocks, with optional+    syntax highlighting using highlighting-kate (if the 'highlighting'+    configuration option is selected).++    + Currently highlighting is supported only in the HTML writer.+    + Delimited code blocks can have attributes; using the language name as+      class triggers highlighting.+    + New Attributes parameter in CodeBlock structure.+    + --version now indicates whether syntax highlighting support is compiled+      in, and prints a list of supported languages++  * Removed debian directory. Pandoc is no longer a native debian package.++  * Changes to build process:  pandoc can now be built from the repository+    using Cabal.  No unix tools are needed (so, pandoc can be built on Windows+    without Cygwin).++    + Include shell scripts themselves in repo, rather than generating from wrappers.+      Removed wrappers directory and wrappers Makefile target.+    + Text/Pandoc/ASCIIMathML.hs, Text/Pandoc/DefaultHeaders.hs,+      and Text/Pandoc/Writers/S5.hs are no longer built in Makefile+      from templates in the templates/ directory. Instead, they use template+      haskell to read data at compile time from the relevant files in data/.+      Template haskell functions go in a new module, Text.Pandoc.TH.+    + man pages are now generated in Setup.hs hook, not by Makefile+    + Makefile 'tarball' target now calls Cabal's 'sdist'+    + Added "Extra-Source-Files" to pandoc.cabal, so sdist contains everything needed+    + Added "Build-Type" field to pandoc.cabal to avoid warning.+    + Added to "Extra-source-files" and "Extra-tmp-files" in pandoc.cabal,+      so 'sdist' and 'clean' will work properly.+    + Setup.hs now generates man pages in a postbuild hook.+    + Added dependency-checking to Setup.hs, so it only rebuilds things+      that need rebuilding.+    + Added 'library' and 'executable' configuration flags.+      Cabal can now be told to build just the library or just the executable.+    + CABALOPTS may now be specified with 'make' to pass Cabal configuration flags.+      For example:  CABALOPTS=-fhighlighting make++  * Rewrote test suite so it doesn't depend on perl or unix tools.++    + Replaced old runtests.pl with a Haskell script RunTests.hs.+    + Added Diff.hs module to be used by RunTests.hs instead of unix 'diff'.+    + Added test hook to Setup.hs, so tests may be run from cabal.+    + Changed Makefile's 'test' target to run tests via cabal.+    + Removed old generate.sh.+    + Since we no longer have 'sed' to filter out raw HTML sections+      from the docbook writer test, or raw LaTeX sections from the+      context writer test, we now just include these sections.+      They can be taken out if it is necessary to process the files.+    + Updated latex and context writer tests to remove extra spaces+      after '\\item'+    + Added a markdown table reader test.+    + Added markdown-reader-more.txt to test suite, for additional test cases+      for raw ConTeXt environments and more.++  * Compatibility fixes for CPP, Cabal, and haddock:++    + Use CPP in "Extensions" field in pandoc.cabal.+    + Removed use of backslash string continuations in source files.++  * Removed pandoc.cabal.ghc66.  We now require Cabal >= 1.2, GHC >= 6.8,+    base >= 3.++  * Require parsec < 3.+    The compatibility module in parsec 3.0.0 gives far worse performance than+    parsec 2.1.  Eventually pandoc will be upgraded to use the new bytestring+    version of parsec, and then we'll go to parsec 3.0.0.++  * Removed Text.Regex dependencies by rewriting using plain Haskell+    (Text.Pandoc.Writers.RTF, Text.Pandoc.Writers.HTML, Main.hs)++  * Moved Text.Pandoc.Writers.DefaultHeaders -> Text.Pandoc.DefaultHeaders.++  * Makefile:++    + Added 'configure' as dependency of 'uninstall-all'.+      (It uses the Cabal build program.)+    + Makefile:  only use --with-hc-pkg if GHC_PKG is defined.+      Note that Cabal will automatically choose the ghc-pkg appropriate+      for the compiler selected, so normally specifying GHC by itself+      is sufficient.++  * Removed Text.Pandoc.UTF8 module; instead, depend on utf8-string and use+    its IO and conversion functions.++  * Added -Wall to ghc-options in pandoc.cabal.  Cleaned up modules so that+    everything is -Wall clean.++    + Added pragma to HTML writer to avoid deprecation warning for use of "start" attribute.+    + Added pragma to Text/Pandoc/Shared.hs to get rid of "orphan instance" warnings.+      (These are caused by the Lift instance for ByteString.)++  * Changed the comment used to replace unsafe HTML if sanitize-html option+    selected.++  * Made -c/--css option repeatable on the command line (like -H, -A, -B).++  * Moved XML-formatting functions to new unexported module Text.Pandoc.XML.++  * Escape '\160' as "&#160;", not "&nbsp;" in XML.+    "nbsp" isn't a predefined XML entity.++  * Fixed bug in RST reader, which would choke on: "p. one\ntwo\n".+    Added some try's in ordered list parsers.++  * Man writer:  don't escape " as \".++  * Allow newline before URL in markdown link references.  Resolves Issue #81.+    Added tests for this issue in new "markdown-reader-more" tests.+    Changed RunTests.hs to run these tests.++  * Support for display math.  Resolves Issue #47.++    + Added a DisplayMath/InlineMath selector to Math inlines.+    + Markdown parser yields DisplayMath for $$...$$.+    + LaTeX parser yields DisplayMath when appropriate.  Removed+      mathBlock parsers, since the same effect is achieved by the math+      inline parsers, now that they handle display math.+    + Writers handle DisplayMath as appropriate for the format.+    + Modified tests accordingly; added new tests for display math.++  * Use LaTeXMathML instead of ASCIIMathML.  LaTeXMathML is closer+    to LaTeX in its display of math, and supports many non-math LaTeX environments.++    + Changed -m option to use LaTeXMathML rather than ASCIIMathML.+    + Modified HTML writer to print raw TeX when LaTeXMathML is+      being used instead of suppressing it.+    + Removed ASCIIMathML files from data/ and added LaTeXMathML.+    + Replaced ASCIIMathML with LaTeXMathML in source files.+    + Modified README and pandoc man page source.+    + Added --latexmathml option (kept --asciimathml as a synonym+      for backwards compatibility)++  * Markdown reader: Parse setext headers before atx headers.+    Test case:+       # hi+       ====+    parsed by Markdown.pl as an H1 header with contents "# hi".++  * Markdown reader: Treat "mixed" lists the same way as Markdown.pl does.+    The marker on the first list item determines the type of the whole+    list.  Thus, a list like+       1. one+       -  two+       *  three+    gets parsed as a single ordered list.  (Previous versions of pandoc+    treated this as an ordered list with an unordered sublist.)++  * Markdown smart typography:++    + Em dashes no longer eat surrounding whitespace.  Resolves Issue #69.+    + Use nonbreaking spaces after known abbreviations in markdown parser.+      Thus, for example, "Mr. Brown" comes out as "Mr.~Brown" in LaTeX, and does+      not produce a sentence-separating space.  Resolves Issue #75.++  * Markdown writer: Print unicode \160 literally, rather than as &nbsp;.++  * Treat '\ ' in (extended) markdown as nonbreaking space.+    Print nonbreaking space appropriately in each writer (e.g. ~ in LaTeX).++  * The '--sanitize-html' option now examines URIs in markdown links+    and images, and in HTML href and src attributes.  If the URI scheme+    is not on a whitelist of safe schemes, it is rejected.  The main point+    is to prevent cross-site scripting attacks using 'javascript:' URIs.+    See http://www.mail-archive.com/markdown-discuss@six.pairlist.net/msg01186.html+    and http://ha.ckers.org/xss.html.  Resolves Issue #62.++  * HTML writer:++    + Override Text.XHtml's stringToHtml function,+      so that characters below 0xff are not converted to numerical entity+      references. Also convert '\160' to "&nbsp;". This should aid readability+      and editability of the HTML source. It does presuppose that the HTML+      will be served as UTF-8.+    + In code blocks, change leading newlines to <br /> tags.+      (Some browsers ignore them.)  Resolves Issue #71.+      See http://six.pairlist.net/pipermail/markdown-discuss/2008-May/001297.html+    + Use style attributes rather than css classes for strikethrough+      and ordered list styles.  This works better when fragments, rather than+      standalone documents, are generated.++  * HTML reader: Count anything that isn't a known block (HTML) tag as an+    inline tag (rather than the other way around).  Added "html", "head", and+    "body" to list of block tags.  Resolves Issue #66, allowing+    <lj> to count as an inline tag.++  * RTF writer: Fixed bug.  Extra spaces were being printed after emphasized,+    boldface, and other inline elements.  Resolves Issue #64.++  * LaTeX reader:  improvements in raw LaTeX parsing.++    + "loose punctuation" (like {}) parsed as Space+    + Para elements must contain more than Str "" and Space elements+    + Added parser for "\ignore" command used in literate haskell.+    + Reworked unknownCommand and rawLaTeXInline: when not in "parse raw"+      mode, these parsers simply strip off the command part and allow+      the arguments to be parsed normally.  So, for example,+      \blorg{\emph{hi}} will be parsed as Emph "hi" rather than+      Str "{\\emph{hi}}".+    + Parse lhs "code" environments as verbatim.+      Refactored parsers for verbatim environments.+    + Removed specialEnvironment parser.+    + parse '{}', if present, after \textless, \textgreater,+      \textbar, \textbackslash, \ldots.+    + Parse unescaped special characters verbatim rather than+      changing them to spaces.  This way arguments of unknown+      commands will appear in braces.++  * Parse raw ConTeXt environments as TeX in markdown reader.+    Resolves Issue #73.++  * Moved BlockWrapper and wrappedBlocksToDoc from ConTeXt writer to Shared.++  * Made some structural changes to parsing of raw LaTeX environments.+    Previously there was a special block parser for LaTeX environments.+    It returned a Para element containing the raw TeX inline. This has+    been removed, and the raw LaTeX environment parser is now used in the+    rawLaTeXInline parser. The effect is exactly the same, except that we+    can now handle consecutive LaTeX and ConTeXt environments not separated+    by spaces.  This new flexibility is required by the example in+    Issue #73:++        \placeformula \startformula+             L_{1} = L_{2}+        \stopformula++    API change: The LaTeX reader now exports rawLaTeXEnvironment' (which+    returns a string) rather than rawLaTeXEnvironment (which returns a block+    element). This is more likely to be useful in other applications.++  * Use \textsubscr instead of \textsubscript for LaTeX subscript macro.+    \textsubscript conflicts with a definition in the memoir class.+    Resolves Issue #65.++  * Removed unneeded space after "\\item" in LaTeX and ConTeXt output.++  * Added amsmath package to default LaTeX header. Resolves Issue #48.++  * Added \setupitemize[autointro] to ConTeXt header, to prevent orphaned+    list introduction lines.++  * Changed Float to Double in definition of Table element.+    (Double is more efficient in GHC.)++  * Fixed bug in Markdown parser:  regular $s triggering math mode.+    For example:  "shoes ($20) and socks ($5)."+    The fix consists in two new restrictions:++    + the $ that ends a math span may not be directly followed by a digit.+    + no blank lines may be included within a math span.++    Thanks to Joseph Reagle for noticing the bug.++  * Use Data.List's 'intercalate' instead of custom 'joinWithSep'.+    Removed 'joinWithSep' from Text.Pandoc.Shared.++  * Updated README and man pages.  Acknowledge contributors in README.+    Added paragraph to README about producing S5 with separate CSS/javascript.++  * Updated INSTALL to reflect new build system (including configuration+    options) and document new dependencies.  Added note to INSTALL that+    Cabal >= 1.2 is required for build.  Resolves Issue #74.++  * Fixed some haddock documentation errors.++  * Small fix to markdown2pdf man page: only input needs to be piped through iconv.++pandoc (0.46) unstable; urgency=low++  [ John MacFarlane ]++  * Made -H, -A, and -B options cumulative: if they are specified+    multiple times, multiple files will be included.++  * Added optional HTML sanitization using a whitelist.+    When this option is specified (--sanitize-html on the command line),+    unsafe HTML tags will be replaced by HTML comments, and unsafe HTML+    attributes will be removed.  This option should be especially useful+    for those who want to use pandoc libraries in web applications, where+    users will provide the input.++    + Main.hs:  Added --sanitize-html option.++    + Text.Pandoc.Shared:  Added stateSanitizeHTML to ParserState.++    + Text.Pandoc.Readers.HTML:+      - Added whitelists of sanitaryTags and sanitaryAttributes.+      - Added parsers to check these lists (and state) to see if a given+        tag or attribute should be counted unsafe.+      - Modified anyHtmlTag and anyHtmlEndTag to replace unsafe tags+        with comments.+      - Modified htmlAttribute to remove unsafe attributes.+      - Modified htmlScript and htmlStyle to remove these elements if+        unsafe.++    + Modified README and man pages to document new option.++  * Improved handling of email addresses in markdown and reStructuredText.+    Consolidated uri and email address parsers.  (Resolves Issue #37.)++    + New emailAddress and uri parsers in Text.Pandoc.Shared.+      - uri parser uses parseURI from Network.URI.+      - emailAddress parser properly handles email addresses with periods+        in them.++    + Removed uri and emailAddress parsers from Text.Pandoc.Readers.RST+      and Text.Pandoc.Readers.Markdown.++  * Markdown reader:++    + Fixed emph parser so that "*hi **there***" is parsed as a Strong+      nested in an Emph. (A '*' is only recognized as the end of the+      emphasis if it's not the beginning of a strong emphasis.)++    + Moved blockQuote parser before list parsers for performance.++    + Modified 'source' parser to allow backslash-escapes in URLs.+      So, for example, [my](/url\(1\)) yields a link to /url(1).+      Resolves Issue #34.++    + Disallowed links within links. (Resolves Issue #35.)+      - Replaced inlinesInBalanced with inlinesInBalancedBrackets, which+        instead of hard-coding the inline parser takes an inline parser+        as a parameter.+      - Modified reference and inlineNote to use inlinesInBalancedBrackets.+      - Removed unneeded inlineString function.+      - Added inlineNonLink parser, which is now used in the definition of+        reference.+      - Added inlineParsers list and redefined inline and inlineNonLink parsers+        in terms of it.+      - Added failIfLink parser.++    + Better handling of parentheses in URLs and quotation marks in titles.+      - 'source' parser first tries to parse URL with balanced parentheses;+        if that doesn't work, it tries to parse everything beginning with+        '(' and ending with ')'.+      - source parser now uses an auxiliary function source'.+      - linkTitle parser simplified and improved, under assumption that it+        will be called in context of source'.++    + Make 'block' conditional on strictness state, instead of using+      failIfStrict in block parsers. Use a different ordering of parsers+      in strict mode (raw HTML block before paragraph) for performance.+      In non-strict mode use rawHtmlBlocks instead of htmlBlock.+      Simplified htmlBlock, since we know it's only called in strict+      mode.++    + Improved handling of raw HTML.  (Resolves Issue #36.)+      - Tags that can be either block or inline (e.g. <ins>) should+        be treated as block when appropriate and as inline when+        appropriate. Thus, for example,+        <ins>hi</ins>+        should be treated as a paragraph with inline <ins> tags, while+        <ins>+        hi+        </ins>+        should be treated as a paragraph within <ins> tags.+      - Moved htmlBlock after para in list of block parsers.  This ensures+        that tags that can be either block or inline get parsed as inline+        when appropriate.+      - Modified rawHtmlInline' so that block elements aren't treated as+        inline.+      - Modified para parser so that paragraphs containing only HTML tags and+        blank space are not allowed.  Treat these as raw HTML blocks instead.++    + Fixed bug wherein HTML preceding a code block could cause it to+      be parsed as a paragraph.  The problem is that the HTML parser+      used to eat all blank space after an HTML block, including the+      indentation of the code block.  (Resolves Issue #39.)+      - In Text.Pandoc.Readers.HTML, removed parsing of following space+        from rawHtmlBlock.+      - In Text.Pandoc.Readers.Markdown, modified rawHtmlBlocks so that+        indentation is eaten *only* on the first line after the HTML+        block.  This means that in+        <div>+             foo+        <div>+        the foo won't be treated as a code block, but in+        <div>++            foo++        </div>+        it will.  This seems the right approach for least surprise.++  * RST reader:++    + Fixed bug in parsing explicit links (resolves Issue #44).+      The problem was that we were looking for inlines until a '<' character+      signaled the start of the URL; so, if you hit a reference-style link,+      it would keep looking til the end of the document.  Fix:  change+      inline => (notFollowedBy (char '`') >> inline).  Note that this won't+      allow code inlines in links, but these aren't allowed in resT anyway.++    + Cleaned up parsing of reference names in key blocks and links.+      Allow nonquoted reference links to contain isolated '.', '-', '_', so+      so that strings like 'a_b_' count as links.++    + Removed unnecessary check for following link in str.+      This is unnecessary now that link is above str in the definition of+      'inline'.++  * HTML reader:++    + Modified rawHtmlBlock so it parses </html> and </body> tags.+      This allows these tags to be handled correctly in Markdown.+      HTML reader now uses rawHtmlBlock', which excludes </html> and </body>,+      since these are handled in parseHtml.  (Resolves Issue #38.)++    + Fixed bug (emph parser was looking for `<IT>` tag, not `<I>`).++    + Don't interpret contents of style tags as markdown.+      (Resolves Issue #40.)+      - Added htmlStyle, analagous to htmlScript.+      - Use htmlStyle in htmlBlockElement and rawHtmlInline.+      - Moved "script" from the list of tags that can be either block or+        inline to the list of block tags.++    + Modified rawHtmlBlock to use anyHtmlBlockTag instead of anyHtmlTag+      and anyHtmlEndTag.  This fixes a bug in markdown parsing, where+      inline tags would be included in raw HTML blocks.++    + Modified anyHtmlBlockTag to test for (not inline) rather than+      directly for block.  This allows us to handle e.g. docbook in+      the markdown reader.++  * LaTeX reader:  Properly recognize --parse-raw in rawLaTeXInline.+    Updated LaTeX reader test to use --parse-raw.++  * HTML writer:++    + Modified rules for automatic HTML header identifiers to+      ensure that identifiers begin with an alphabetic character.+      The new rules are described in README.  (Resolves Issue #33.)++    + Changed handling of titles in HTML writer so you don't get+      "titleprefix - " followed by nothing.++  * ConTeXt writer: Use wrappers around Doc elements to ensure proper+    spacing.  Each block element is wrapped with either Pad or Reg.+    Pad'ed elements are guaranteed to have a blank line in between.++  * RST writer:++    + Refactored RST writer to use a record instead of a tuple for state,+      and to include options in state so it doesn't need to be passed as+      a parameter.++    + Use an interpreted text role to render math in restructuredText.+      See http://www.american.edu/econ/itex2mml/mathhack.rst for the+      strategy.++  [ Recai Oktaş ]++  * Debian packaging changes:++    + Remove the empty 'include' directory in -dev package, which lintian+      complains about.+    + Bump Standarts-Version to 3.7.3.+    + Use new 'Homepage:' field to specify the upstream URL on suggestion of+      lintian.++ -- Recai Oktaş <roktas@debian.org>  Tue, 08 Jan 2008 05:13:31 +0200++pandoc (0.45) unstable; urgency=low++  [ John MacFarlane ]++  * Simplified parsing of reference keys and notes in markdown and RST+    readers: The Reference data structure from Text.Pandoc.Shared is no+    longer needed, since referenceKey and noteBlock parses return strings+    (as many blank lines as were occupied by the key or note) and update+    state themselves.  getPosition and setPosition are now used to ensure+    that error messages will give the correct line number. This yields+    cleaner (and slightly faster) code, with more accurate parsing error+    messages.++  * Added new Math inline element:++    + Markdown and LaTeX readers now convert TeX math into Math elements,+      not TeX.+    + This allows math to be treated differently from raw TeX in output.+      TeX elements are no longer printed in output formats other than+      Markdown, LaTeX, and ConTeXt.  But Math elements are always printed.++  * New default handling of math in writers:++    + New module Text.Pandoc.Readers.TeXMath exports readTeXMath, which+      parses raw TeX math and outputs a string of Pandoc inlines that+      tries to render it as far as possible using unicode characters,+      lapsing into literal TeX when needed.+    + readTeXMath is now used for default HTML output in HTML, S5, RTF,+      and Docbook, if no other method for displaying math in HTML is+      specified.  Enclosing $'s are no longer printed by default.+    + By default, math is put inside `<span class="math">`. This way it can be+      distinguished from the surrounding text, e.g. put in a different+      font.++  * New --gladtex and --mimetex options for display of math in HTML:++    + If --gladtex is specified, math is output between `<eq>` tags, so+      it can be processed by gladTeX.+    + If --mimetex is specified, math is put in `<img>` tags with a link+      to the mimetex CGI script (or any other script that takes TeX math+      as input and outputs an image).  The URL of the script may be+      specified, but defaults to /cgi-bin/mimetex.cgi.+    + HTMLMathMethod structure in WriterOptions keeps track of how to+      display math in HTML output.+    + Updated README with a description of the four options for displaying+      math in HTML.++  * HTML reader:++    + Fixed bug: parser for minimized attributes should not swallow+      trailing spaces.+    + Simplified HTML attribute parsing.+    + Changed parsing of code blocks in HTML reader:  `<code>` tag is no+      longer needed. `<pre>` suffices. All HTML tags in the code block+      (e.g. for syntax highlighting) are skipped, because they are not+      portable to other output formats. A `<code>...</code>` block not+      surrounded by `<pre>` now counts as inline HTML, not a code block.+    + Remove just one leading and one trailing newline from contents of+      `<pre>...</pre>` in codeBlock parser.++  * Markdown reader:++    + Removed support for box-style block quotes.+    + Require space before title in links and references.+      This fixes a bug in parsing URLs like http://silly/url(withparen).+    + Improved and simplified setextHeader parser.+    + Fixed logic in smart quote parsing, adding some needed 'try'+      statements.+    + Fixed smart quote parsing so that unicode characters 8216 and 8217+      are recognized as single quotes, and 8220 and 8221 as double quotes.++  * RST reader:++    + Fixed bug in parsing of code blocks. Previously a full tab indent+      was required, but RST allows code to be indented any amount.+      Resolves Issue #27.+    + Allow field lists to be indented.+    + Parse the contents of field lists instead of treating as a raw string.+    + Represent field lists as definition lists instead of blockquotes.+    + Fixed bug in which metadata would be overridden if the document+      contained multiple field lists.+    + Parse fields associated with '.. image::' blocks, and use 'alt'+      field, if given, for image alt and title attributes.++  * LaTeX reader:++    + Modified specialChar so that '"' characters are parsed.+    + Fixed a bug in parsing of \[ \] math blocks (thanks to Mark Kalderon).++  * HTML writer:++    + Changes in handling of math (see above).+    + Don't produce HTML for table of contents if there are+      no headers. (This would be an empty list, which is invalid XHTML.)++  * Markdown writer:++    + Don't print title attribute if title is empty. (This differs from+      the behavior of Markdown.pl, and agrees with PHP Markdown. But John+      Gruber has indicated that he prefers this behavior.) Adjusted test+      suite accordingly.+    + Fixed incorrect line wrapping in paragraphs including hard line+      breaks. Resolves Issue #25.+    + Fixed bug in markdown writer:  If an ordered list item began with+      a marker greater than 3 characters in width, and the item took more+      than one line, it would appear on the line after the list marker,+      e.g.:++          (12)+              My list item.+              Multiline.++      Now it works as follows:++          (12) My list item.+              Multiline.++  * RST writer++    + Fixed bug in RST writer's handling of ordered lists. Previously,+      list items with multiple lines would not always line up with+      single-line list items. Now, list items are nested the length of+      the list marker + 1. This looks better and ensures that list items+      all line up. (Note that list markers are padded to the length of+      the longest list marker in the series.)+    + Use 3-space indent for unordered lists.+    + If label for a link reference contains a colon, surround it by `+      signs so it won't be interpreted as the end of the link label.++  * LaTeX writer:++    + Cleaner output for footnotes. Footnotes now always begin on a new+      line, and the final } is on a line by itself only when it needs to+      be (i.e. only when the note ends with a Verbatim environment).+    + Added writer options to state, so state doesn't need to be passed as+      a parameter.+    + Text wrapping now provided, using wrapTeXIfNeeded.++  * ConTeXt writer:  many improvements for more idiomatic ConTeXt output+    (thanks to Idris Samawi Hamid for suggestions).++    + PrettyPrint module now used for output.+    + Writer options are now in state, so they don't have to be passed as+      a parameter.+    + Text wrapping now provided, using wrapTeXIfNeeded.+    + Better treatment of footnotes:  footnotes are always on lines by+      themselves, and the final } is on a line by itself only when+      it needs to be (after \stoptyping).+    + Use \subject, \subsubject, ... or \section, \subsection, ... for headings,+      depending on whether --number-sections option is selected.+    + Extra blank line inserted after \stopitemize+    + Use new, "official" definition of blockquote environment. Also, use+      blank line after \startblockquote to balance blank line at the end.+    + Both itemized and enumerated lists are now generated using+      \start-stopitemize, with appropriate options. Removed definitions+      of ltxenum and ltxitem, which are no longer needed. Provided+      defaults for itemized lists in the preamble. State keeps track of+      ordered list level, so that when default numbering is specified,+      the appropriate scheme can be used.+    + Changed \useurl to \useURL.+    + Changed link color from red to blue.+    + Use \subsubsubsubsection etc., since these are supported+      (up to at least sub x 5).++  * Text.Pandoc.Shared:++    + Save and restore position in parseFromString, so that accurate+      error messages can be given.+    + Improved efficiency of romanNumeral parser.+    + Added wrappedTeX and wrapTeXIfNeeded functions.  These ensure+      that footnotes occur on lines by themselves (to make them+      easier to see and move) and do not screw up line wrapping.++  * Text.Pandoc.UTF8:  modified fromUTF8 to strip out the BOM+    if present.  Windows Notepad and other applications insert a+    BOM at the beginning of a UTF8 file.++  * Main.hs (tabFilter): Treat '\r' at end of line as newline (in+    addition to "\r\n" and '\n').++  * Added a writer option for wrapped text and a command-line option+    '--no-wrap', which disables text wrapping and minimizes whitespace+    in HTML. (Resolves Issue #26.)++    + Added support for '--no-wrap' to Main.hs.+    + Added wrapIfNeeded function to Text.Pandoc.Shared.+    + Use wrapIfNeeded instead of wrapped in the RST, Man, Docbook, and+      Markdown writers.+    + Added render and renderFragment helpers to HTML writer.++  * Modified html2markdown to run tidy only if the HTML cannot be+    parsed. Previously html2markdown piped all input through tidy+    before passing it to pandoc. This caused problems on certain pages+    (e.g. http://daringfireball.com/markdown) which have well-formed+    XHTML that causes tidy to choke. The solution is to pipe through+    tidy only if pandoc cannot parse the input by itself. This means+    that a temp file is now always used, even when input comes from a+    local file or standard input.++  * Removed 'version' constant from Main.hs; added 'pandocVersion' to+    Text.Pandoc library.++  * pandoc.cabal:++    + Modified to work with GHC 6.8 and Cabal configurations. (For GHC+      6.8, pretty and containers must be added to Build-Depends, and it+      is desirable to use the -O2 compiler option.)  Cabal configurations+      allows one to select options depending on the compiler version.+      For GHC 6.6, the splitBase option can be disabled.+    + pandoc.cabal.ghc66 is provided for users with older versions of+      Cabal, which do not support configurations.+    + Use Ghc-Prof-Options to ensure that '-auto-all' is used when+      '--enable-(executable|library)-profiling' is specified. Updated+      PROFILING instructions accordingly.++  * Makefile:++    + Makefile now checks GHC version. If GHC is 6.6, pandoc.cabal.ghc66+      is copied to pandoc.cabal, and the old pandoc.cabal is copied+      to pandoc.cabal.orig. Otherwise, pandoc.cabal is copied to+      pandoc.cabal.orig but otherwise unmodified. This way, the Makefile+      will work properly with either GHC 6.6 or 6.8.+    + Changed BUILDCONF to point to dist/setup-config, not .setup-config.+      This is where current versions of Cabal put it.+    + Added $(BUILDCMD) target, so setup doesn't get compiled every time.+    + Removed dependency of templates on ./templates, which is circular+      now that templates is a subdirectory of the top-level.++  * MacPorts Portfile:++    + Modified to install the pandoc library in addition to programs.+    + Installation must be done manually rather than using Makefile's+      install-all.+    + Note that the library must be registered in the activate phase,+      after the library files have been copied out of the destroot.+      Cabal generates a 'register.sh' script that will do this.++  * debian/control: Added libghc6-network-dev, libghc6-xhtml-dev, and+    libghc6-mtl-dev as dependencies for libghc6-pandoc-dev.+    Closes: #445235++  * debian/rules:  Converted to UTF-8.++  * Changed pandoc home page to http://johnmacfarlane.net/pandoc/.++  * Updated ASCIIMathML.js to latest version.++  * Directory structure:++    + Moved everything from src into the top-level directory.+    + Changed references to source directory in Makefile and+      pandoc.cabal.*.+    + Moved ASCIIMathML.js, headers, and ui into templates directory.+    + Modified fillTemplates.pl to reflect new paths.++  [ Recai Oktaş ]++  * Makefile: Fixed the issue of having two copies of the library+    documentation under some usage scenarios.++  * Replaced 'ghc' with '$(GHC)' in Makefile, and made GHC+    and GHC_PKG configurable through the environment, to support+    unusual ghc installations.  For example:+    GHC=/opt/ghc/bin/ghc GHC_PKG=/opt/ghc/bin/ghc-pkg make++ -- Recai Oktaş <roktas@debian.org>  Sun, 07 Oct 2007 20:51:43 +0300++pandoc (0.44) unstable; urgency=low++  [ John MacFarlane ]++  * Fixed bug in HTML writer:  when --toc was used, anchors were put around+    headers, which is invalid XHTML (block content within inline element).+    Now the anchors are put inside the header tags.  Resolves Issue #23.++  * Added xmlns attribute to html element in html writer tests.+    This attribute is added by more recent versions of the+    xhtml library (>= 3000), and is required for valid XHTML.++  [ Recai Oktaş ]++  * On configure, compile 'Setup.hs' to 'setup' and use 'setup' as the build+    command instead of 'runhaskell', which, on some platforms (such as s390,+    alpha, m68k), throws the following error:++        runhaskell Setup.hs configure --prefix=/usr+        ghc-6.6.1: not built for interactive use++    This causes a serious FTBFS bug.  Closes: #440668.++ -- Recai Oktaş <roktas@debian.org>  Mon, 03 Sep 2007 18:24:02 +0300++pandoc (0.43) unstable; urgency=low++  [ John MacFarlane ]++  * The focus of this release is performance.  The markdown parser+    is about five times faster than in 0.42, based on benchmarks+    with the TextMate manual.++  * Main.hs: Replaced CRFilter and tabFilter with single function+    tabFilter, which operates on the whole string rather than breaking+    it into lines, and handles dos-style line-endings as well as tabs.++  * Added separate LaTeX reader and native reader tests; removed+    round-trip tests.++  * Text.Pandoc.Shared:++    + Removed tabsToSpaces and tabsInLine (they were used only in Main.hs.)+    + General code cleanup (to elimante warnings when compiling with -Wall.)+    + Added 'wrapped' function, which helps wrap text into paragraphs,+      using the prettyprinting library.+    + Rewrote charsInBalanced and charsInBalanced'.+        - Documented restriction: open and close must be distinct characters.+        - Rearranged options for greater efficiency.+        - Bug fix: Changed inner call to charsInBalanced inside+          charsInBalanced' to charsInBalanced'.+    + anyLine now requires that the line end with a newline (not eof).+      This is a harmless assumption, since we always add newlines to the+      end of a block before parsing with anyLine, and it yields a 10% speed+      boost.+    + Removed unnecessary 'try' in anyLine.+    + Removed unneeded 'try' from romanNumeral parser.+    + Use notFollowedBy instead of notFollowedBy' in charsInBalanced.+    + Removed unneeded 'try' in parseFromString.+    + Removed unneeded 'try' from stringAnyCase.  (Now it behaves+      like 'string'.)+    + Changed definition of 'enclosed' in Text.Pandoc.Shared so that+      'try' is not automatically applied to the 'end' parser. Added+      'try' in calls to 'enclosed' where needed. Slight speed increase.++  * Writers:++    + Replaced individual wrapping routines in RST, Man, and Markdown+      writers with 'wrapped' from Text.Pandoc.Shared.+    + Rewrote LaTeX writer to use the prettyprinting library,+      so we get word wrapping, etc.+    + Modified latex writer tests for new latex writer using prettyprinter.+    + Fixed bug in LaTeX writer: autolinks would not cause+      '\usepackage{url}' to be put in the document header. Also, changes+      to state in enumerated list items would be overwritten.+    + In Markdown writer, escape paragraphs that begin with ordered list+      markers, so they don't get interpreted as ordered lists.++  * Text.Pandoc.Reades.LaTeX:++    + Fixed bug in LaTeX reader, which wrongly assumed that the roman+      numeral after "enum" in "setcounter" would consist entirely of+      "i"s. 'enumiv' is legitimate.+    + LaTeX command and environment names can't contain numbers.+    + Rearranged order of parsers in inline for slight speed improvement.+    + Added '`' to special characters and 'unescapedChar'.++  * Text.Pandoc.Readers.RST:++    + Removed unneeded try's in RST reader; also minor code cleanup.+    + Removed tabchar.+    + Rearranged parsers in inline (doubled speed).++  * Text.Pandoc.Readers.Markdown:++    + Skip notes parsing if running in strict mode. (This yields a nice+      speed improvement in strict mode.)+    + Simplify autolink parsing code, using Network.URI to test for+      URIs. Added dependency on network library to debian/control and+      pandoc.cabal.+    + More perspicuous definition of nonindentSpaces.+    + Removed unneeded 'try' in 'rawLine'.+    + Combined linebreak and whitespace into a new whitespace parser, to+      avoid unnecessary reparsing of space characters.+    + Removed unnecessary 'try' in 'codeBlock', 'ellipses', 'noteMarker',+      'multilineRow', 'dashedLine', 'rawHtmlBlocks'.+    + Use lookAhead in parsers for setext headers and definition lists+      to see if the next line begins appropriately; if not, don't waste+      any more time parsing.+    + Don't require blank lines after code block. (It's sufficient to+      end code block with a nonindented line.)+    + Changed definition of 'emph': italics with '_' must not+      be followed by an alphanumeric character. This is to help+      prevent interpretation of e.g. `[LC_TYPE]: my_type` as+      `[LC<em>TYPE]:my</em>type`.+    + Improved Markdown.pl-compatibility in referenceLink: the two parts+      of a reference-style link may be separated by one space, but not+      more... [a] [link], [not]    [a link].+    + Fixed markdown inline code parsing so it better accords with+      Markdown.pl: the marker for the end of the code section is a clump+      of the same number of `'s with which the section began, followed+      by a non-` character. So, for example,+         ` h ``` i ` -> `<code>h ``` i</code>`.+    + Split 'title' into 'linkTitle' and 'referenceTitle', since the+      rules are slightly different.+    + Rewrote 'para' for greater efficiency.+    + Rewrote link parsers for greater efficiency.+    + Removed redundant 'referenceLink' in definition of inline (it's+      already in 'link').+    + Refactored escapeChar so it doesn't need 'try'.+    + Refactored hrule for performance in Markdown reader.+    + More intelligent rearranging of 'inline' so that most frequently+      used parsers are tried first.+    + Removed tabchar parser, as whitespace handles tabs anyway.++  * Text.Pandoc.CharacterReferences:++    + Refactored.+    + Removed unnecessary 'try's for a speed improvement.+    + Removed unnecessary '&' and ';' from the entity table.++  * Build process:++    + Makefile: Get VERSION from cabal file, not Main.hs.+    + Modified MacPorts Portfile:+        - Depend on haddock+        - Build and install libraries and library documentation in+          addition to pandoc executable+        - Added template item for md5 sum in Portfile.in.+        - Incorporated changes from MacPorts repository (r28278).+    + FreeBSD port:  Don't try to generate distinfo in Makefile.+      It can be made using 'make makesum' in FreeBSD.+    + Make both freebsd and macports targets depend on tarball.++  * Website and documentation:++    + Updated INSTALL instructions.+    + Added pandocwiki demo to website.+    + Removed local references to Portfile, since pandoc is now in the+      MacPorts repository.++ -- Recai Oktaş <roktas@debian.org>  Sun, 02 Sep 2007 15:50:11 +0300++pandoc (0.42) unstable; urgency=low++  [ John MacFarlane ]++  * Main.hs: Use utf8 conversion on the extra files loaded with+    the -H, -C, -B, and -A options.  This fixes problems with unicode+    characters in these files.++  * Exposed Text.Pandoc.ASCIIMathML, since it is imported in+    Text.Pandoc.Readers.HTML and without it we get a linking error when+    using the library.++  * Markdown reader:++    + Added new rule for enhanced markdown ordered lists: if the list+      marker is a capital letter followed by a period (including a+      single-letter capital roman numeral), then it must be followed by+      at least two spaces. The point of this is to avoid accidentally+      treating people's initials as list markers: a paragraph might begin,+      "B. Russell was an English philosopher," and this shouldn't be+      treated as a list.  Documented change in README.+    + Blocks that start with "p. " and a digit are no longer treated+      as ordered lists (it's a page number).+    + Added a needed 'try' to listItem.+    + Removed check for a following setext header in endline.+      A full test is too inefficient (doubles benchmark time), and the+      substitute we had before is not 100% accurate.+    + Don't use Code elements for autolinks if --strict specified.++  * LaTeX writer:  When a footnote ends with a Verbatim environment, the+    close } of the footnote cannot occur on the same line or an error occurs.+    Fixed this by adding a newline before the closing } of every footnote.++  * HTML writer:+    + Removed incorrect "{}" around style information in HTML tables.+      Column widths now work properly in HTML.+    + If --strict option is specified (and --toc is not), don't include+      identifiers in headers, for better Markdown compatibility.++  * Build process:++    + Separated $(web_dest) and website targets.+    + In website, index.txt is now constructed from template index.txt.in.+    + Added freebsd target to Markefile. This creates the freebsd Makefile+      from Makefile.in, and creates distinfo.  Removed Makefile and distinfo+      from the repository.+    + Added macport target to Makefile. Portfile is built from template+      Portfile.in.+    + Removed OSX package targets.  (Too many difficulties involving+      dependencies on dynamic libraries.)+    + More complete INSTALL instructions for all architectures.++  * Website:+    + Added a programming demo, pandocwiki.++  [ Recai Oktaş ]++  * Do not forget to close pandoc's ITP.  Closes: #391666++ -- Recai Oktaş <roktas@debian.org>  Sun, 26 Aug 2007 22:51:32 +0300++pandoc (0.41) unstable; urgency=low++  [ John MacFarlane ]++  * Fixed bugs in HTML reader:+    + Skip material at end *only if* `</html>` is present (previously,+      only part of the document would be parsed if an error was+      found; now a proper error message is given).+    + Added new constant eitherBlockOrInline with elements that may+      count either as block-level or as inline. Modified isInline and+      isBlock to take this into account.+    + Modified rawHtmlBlock to accept any tag (even an inline tag):+      this is innocuous, because rawHtmlBlock is tried only if a regular+      inline element can't be parsed.+    + Added a necessary 'try' in definition of 'para'.++  * Fixed bug in markdown ordered list parsing.  The problem was that+    anyOrderedListStart did not check for a space following the+    ordered list marker.  So in 'A.B. 2007' the parser would be+    expecting a list item, but would not find one, causing an error.+    Fixed a similar bug in the RST reader.  Resolves Issue #22.++  * Refactored RST and Markdown readers using parseFromString.++  * LaTeX reader will now skip anything after \end{document}.++  * Fixed blockquote output in markdown writer: previously, block+    quotes in indented contexts would be indented only in the first+    line.++  * Added note to INSTALL about variations in versions of the xhtml+    library that can lead to failed tests (thanks to Leif LeBaron).++ -- Recai Oktaş <roktas@debian.org>  Sun, 19 Aug 2007 23:26:07 +0300++pandoc (0.4) unstable; urgency=low++  [ John MacFarlane ]++  * Added two new output formats: groff man pages and ConTeXt. By+    default, output files with extensions ".ctx" and ".context" are+    assumed to be ConTeXt, and output files with single-digit extensions+    are assumed to be man pages.++  * Enhanced ordered lists (documented in README, under Lists):+    + The OrderedList block element now stores information about+      list number style, list number delimiter, and starting number.+    + The readers parse this information when possible.+    + The writers use this information to style ordered lists.+    + The enhancement can be disabled using the --strict option.++  * Added support for tables (with a new Table block element). Two kinds+    of tables are supported: a simple table with one-line rows, and a+    more complex variety with multiline rows. All output formats are+    supported, but only markdown tables are parsed at the moment. The+    syntax is documented in README.++  * Added support for definition lists (with a new DefinitionList block+    element). All output and input formats are supported. The syntax is+    documented in README.++  * Added support for superscripts and subscripts (with new Superscript+    and Subscript inline elements).  All input and output+    formats.  The syntax is documented in README.++  * Added support for strikeout (with a new Strikeout inline element).+    All input and output formats are supported. Thanks to Bradley Kuhn,+    who contributed a patch. The syntax is documented in README. Resolves+    Issue #18.++  * Added a --toc|--table-of-contents option.  This causes an automatically+    generated table of contents (or an instruction that creates one) to+    be inserted at the beginning of the document. Not supported in S5,+    DocBook, or man page writers.++  * Modified the -m|--asciimathml option:++    + If an optional URL argument is provided, a link is inserted+      instead of the contents of the ASCIIMathML.js script.+    + Nothing is inserted unless the document actually contains+      LaTeX math.++  * Removed Blank block element as unnecessary.++  * Removed Key and Note blocks from the Pandoc data structure. All+    links are now stored as explicit links, and note contents are+    stored with the (inline) notes.++    + All link Targets are now explicit (URL, title) pairs; there+      is no longer a 'Ref' target.+    + Markdown and RST parsers now need to extract data from key and+      note blocks and insert them into the relevant inline elements.+      Other parsers have been simplified, since there is no longer any need+      to construct separate key and note blocks.+    + Markdown, RST, and HTML writers need to construct lists of+      notes; Markdown and RST writers need to construct lists of link+      references (when the --reference-links option is specified); and+      the RST writer needs to construct a list of image substitution+      references. All writers have been rewritten to use the State monad+      when state is required.+    + Several functions (generateReference, keyTable,+      replaceReferenceLinks, replaceRefLinksBlockList, and some auxiliaries+      used by them) have been removed from Text.Pandoc.Shared, since+      they are no longer needed. New functions and data structures+      (Reference, isNoteBlock, isKeyBlock, isLineClump) have been+      added. The functions inTags, selfClosingTag, inTagsSimple, and+      inTagsIndented have been moved to the DocBook writer, since that+      is now the only module that uses them. NoteTable is now exported+      in Text.Pandoc.Shared.+    + Added stateKeys and stateNotes to ParserState; removed stateKeyBlocks,+      stateKeysUsed, stateNoteBlocks, stateNoteIdentifiers, stateInlineLinks.+    + Added writerNotes and writerReferenceLinks to WriterOptions.++  * Added Text.Pandoc module that exports basic readers, writers,+    definitions, and utility functions. This should export everything+    needed for most uses of Pandoc libraries. The haddock documentation+    includes a short example program.++  * Text.Pandoc.ASCIIMathML is no longer an exported module.++  * Added Text.Pandoc.Blocks module to help in printing markdown+    and RST tables.  This module provides functions for working with+    fixed-width blocks of text--e.g., placing them side by side, as+    in a table row.++  * Refactored to avoid reliance on Haskell's Text.Regex library, which+    (a) is slow, and (b) does not properly handle unicode.  This fixed+    some strange bugs, e.g. in parsing S-cedilla, and improved performance.++    + Replaced 'gsub' with a general list function  'substitute'+      that does not rely on Text.Regex.+    + Rewrote extractTagType in HTML reader so that it doesn't use+      regexs.+    + In Markdown reader, replaced email regex test with a custom email+      autolink parser (autoLinkEmail). Also replaced selfClosingTag regex+      with a custom function isSelfClosingTag.+    + Modified Docbook writer so that it doesn't rely on Text.Regex for+      detecting 'mailto' links.+    + Removed escapePreservingRegex and reamped entity-handling+      functions in Text.Pandoc.Shared and Text.Pandoc.CharacterReferences to+      avoid reliance on Text.Regex (see below on character reference+      handling changes).++  * Renamed Text.Pandoc.Entities as Text.Pandoc.CharacterReferences.++  * Changed handling of XML entities.  Entities are now parsed (and unicode+    characters returned) in the Markdown and HTML readers, rather than being+    handled in the writers.  In HTML and Docbook writers, UTF-8 is now used+    instead of entities for characters above 128.  This makes the HTML and+    DocBook output much more readable and more easily editable.++    + Removed sgmlHexEntity, sgmlDecimalEntity, sgmlNamedEntity, and+      sgmlCharacterEntity regexes from Text.Pandoc.Shared.+    + Renamed escapeSGMLChar to escapeCharForXML.  Added escapeStringForXML.+      Moved both functions to Text.Pandoc.Writers.Docbook.+    + Added characterReference parser to Text.Pandoc.CharacterReferences.+      This parses a string and return a unicode character.+    + Rewrote decodeCharacterReferences to use the new parser instead of+      Text.Regex.+    + Added new charRef parser for Markdown and HTML, which replaces the+      old 'entity' parser. Added '&' as a special character in Markdown reader.+    + Modified HTML and Markdown readers to call decodeEntities on all raw+      strings (e.g. authors, dates, link titles), to ensure that no+      unprocessed entities are included in the native representation of+      the document.  (In the HTML reader, most of this work is done by a+      change in extractAttributeName.)+    + In XML and Markdown output, escape unicode nonbreaking space as '&nbsp;',+      since a unicode non-breaking space is impossible to distinguish visually+      from a regular space.  (Resolves Issue #3.)+    + Removed encodeEntitiesNumerical.+    + Use Data.Map for entityTable and (new) reverseEntityTable, for a+      slight performance boost over the old association list.+    + Removed unneeded decodeEntities from 'str' parser in HTML and+      Markdown readers.++  * Text.Pandoc.UTF8:  Renamed encodeUTF8 to toUTF8, decodeUTF8 to+    fromUTF8, for clarity.++  * Replaced old haskell98 module names replaced by hierarchical module+    names, e.g. List by Data.List.  Removed haskell98 from dependencies+    in pandoc.cabal, and added mtl (needed for state monad). Substituted+    xhtml for html.++  * Refactored and cleaned up character escaping in writers, using+    backslashEscapes and escapeStringUsing functions.++  * Instead of adding "\n\n" to the end of an input string in Main.hs,+    this is now done in the readers. This makes the libraries behave+    the way you'd expect from the pandoc program. Resolves Issue #10.++  * URLs and email addresses in autolinks are now typeset as Code.++  * In Main.hs, changed putStr to putStrLn -- mainly because MacOS X+    doesn't display the whole output unless there's a line ending.++  * Major code cleanup in all modules, for greater consistency, concision,+    and readability.++  * HTML reader:++    + Fixed several bugs (extractTagType, attribute parsing).+    + Remove Null blocks in lists of blocks when possible.+    + Allow HTML comments as raw HTML inline.++  * Markdown reader:++    + Ordered list items may no longer begin with uppercase letters, or+      letters greater than 'n'.  (This prevents first initials and page+      reference, e.g. 'p. 400', from being parsed as beginning lists.)+      Also, numbers beginning list items may no longer end with ')',+      which is now allowed only after letters.  Note: These changes+      may cause documents to be parsed differently. Users should take+      care in upgrading.+    + Changed autoLink parsing to conform better to Markdown.pl's+      behavior. `<google.com>` is not treated as a link, but+      `<http://google.com>`, `<ftp://google.com>`, and+      `<mailto:google@google.com>` are.+    + Cleaned up handling of embedded quotes in link titles.  Now these are+      stored as a '"' character, not as '&quot;'.+    + Use lookAhead parser for the 'first pass' (looking for reference keys),+      instead of parsing normally, then using setInput to reset input.  This+      yields a slight performance boost.+    + Fixed several bugs in smart quote recognition.+    + Fixed bug in indentSpaces (which didn't properly handle+      cases with mixed spaces and tabs).+    + Consolidated 'text', 'special', and 'inline' into 'inline'.+    + Fixed bug which allowed URL and title to be separated by multiple blank+      lines in links and reference keys.  They can be on separate lines but+      can't have blank lines between them.+    + Correctly handle bracketed text inside inline footnotes and links,using+      new function inlinesInBalanced.  Resolves Issue #14.+    + Fixed bug in footnotes: links in footnotes were not being+      processed. Solution: three-stage parse. First, get all the+      reference keys and add information to state. Next, get all the+      notes and add information to state. (Reference keys may be needed+      at this stage.) Finally, parse everything else.+    + Replaced named constants like 'emphStart' with literals.+    + Removed an extra occurance of escapedChar in definition of inline.++  * RST reader:++    + Allow the URI in a RST hyperlink target to start on the line+      after the reference key.+    + Added 'try' in front of 'string', where needed, or used a different+      parser.  This fixes a bug where ````` would not be correctly parsed as+      a verbatim `.+    + Fixed slow performance in parsing inline literals in RST reader.  The+      problem was that ``#`` was seen by 'inline' as a potential link or image.+      Fix:  inserted 'notFollowedBy (char '`')' in link parsers.+      Resolves Issue #8.+    + Use lookAhead instead of getInput/setInput in RST reader.  Removed+      unneeded getState call, since lookAhead automatically saves and+      restores the parser state.+    + Allow hyperlink target URIs to be split over multiple lines, and+      to start on the line after the reference. Resolves Issue #7.+    + Fixed handling of autolinks.++  * LaTeX reader:++    + Replaced 'choice [(try (string ...), ...]' idiom with 'oneOfStrings',+      for clarity.+    + Added clauses for tilde and caret. Tilde is \ensuremath{\sim}, and+      caret is \^{}, not \^ as before.+    + Added parsing for \url.+    + Parse \texttt{} as code, provided there's nothing fancy inside.++  * HTML writer:++    + Modified HTML writer to use the Text.XHtml library. This results+      in cleaner, faster code, and it makes it easier to use Pandoc in+      other projects, like wikis, which use Text.XHtml. Two functions are+      now provided, writeHtml and writeHtmlString: the former outputs an+      Html structure, the latter a rendered string. The S5 writer is also+      changed, in parallel ways (writeS5, writeS5String).+    + The Html header is now written programmatically, so it has been+      removed from the 'headers' directory. The S5 header is still+      needed, but the doctype and some of the meta declarations have+      been removed, since they are written programatically. This change+      introduces a new dependency on the xhtml package.+    + Fixed two bugs in email obfuscation involving improper escaping+      of '&' in the `<noscript>` section and in `--strict` mode. Resolves+      Issue #9.+    + Fixed another bug in email obfuscation: If the text to be obfuscated+      contains an entity, this needs to be decoded before obfuscation.+      Thanks to thsutton for the patch. Resolves Issue #15.+    + Changed the way the backlink is displayed in HTML footnotes.+      Instead of appearing on a line by itself, it now generally+      appears on the last line of the note.  (Exception:  when the+      note does not end with a Plain or Para block.) This saves space+      and looks better.+    + Added automatic unique identifiers to headers:+      - The identifier is derived from the header via a scheme+        documented in README.+      - WriterState now includes a list of header identifiers and a table+        of contents in addition to notes.+      - The function uniqueIdentifiers creates a list of unique identifiers+        from a list of inline lists (e.g. headers).+      - This list is part of WriterState and gets consumed by blockToHtml+        each time a header is encountered.+    + Include CSS for .strikethrough class in header only if strikethrough+      text appears in the document.+    + If the 'strict' option is specified, elements that do not appear in+      standard markdown (like definition lists) are passed through as+      raw HTML.+    + Simplified treatment of autolinks, using pattern matching instead of+      conditionals.++  * Markdown writer:++    + Links in markdown output are now printed as inline links by default,+      rather than reference links.  A --reference-links option has been added+      that forces links to be printed as reference links.  Resolves Issue #4.+    + Use autolinks when possible.  Instead of `[site.com](site.com)`,+      use `<site.com>`.++  * LaTeX writer:++    + Rewrote to use the State monad. The preamble now includes only those+      packages that are actually required, given the document's content.+      Thus, for example, if strikeout is not used, ulem is not required.+      Modified LaTeXHeader accordingly.+    + Modified LaTeX writer to insert '\,' between consecutive quotes.+    + Removed unused function tableRowColumnWidths.+    + Simplified code for escaping special characters.+    + Leave extra blank line after \maketitle.+    + Include empty '\author{}' when no author specified to avoid LaTeX+      errors.+    + Include fancyvrb code in header only if needed -- that is, only+      if there is actually code in a footnote.+    + Use \url{} for autolinks.+    + Include [mathletters] option in ucs package, so that basic unicode+      Greek letters will work correctly.++  * RST writer:  Force blank line before lists, so that sublists will+    be handled correctly.++  * Docbook writer:  Fixed a bug:  email links with text, like+    [foo](me@bar.baz), were being incorrectly treated as autolinks.++  * Removed Text.ParserCombinators.Pandoc and moved all its functions to+    Text.Pandoc.Shared.++  * Text.Pandoc.Shared:++    + Added defaultWriterOptions.+    + Added writerTableOfContents to WriterOptions.+    + Added writerIgnoreNotes option to WriterOptions.  This is needed+      for processing header blocks for a table of contents, since notes on+      headers should not appear in the TOC.+    + Added prettyprinting for native Table format.+    + Removed some unneeded imports.+    + Moved escape and nullBlock parsers from+      Text.ParserCombinators.Pandoc, since the latter is for+      general-purpose parsers that don't depend on Text.Pandoc.Definition.+    + Moved isHeaderBlock from Text.Pandoc.Writers.HTML.+    + Moved Element, headerAtLeast, and hierarchicalize from Docbook+      writer, because HTML writer now uses these in constructing a table+      of contents.+    + Added clauses for new inline elements (Strikeout, Superscript,+      Subscript) to refsMatch.+    + Removed backslashEscape; added new functions escapeStringUsing and+      backslashEscapes.+    + Moved failIfStrict from markdown reader, since it is now used also+      by the HTML reader.+    + Added a 'try' to the definition of indentSpaces.+    + In definition of 'reference', added check to make sure it's not a note+      reference.+    + Added functions: camelCaseToHyphenated, toRomanNumeral,+      anyOrderedListMarker, orderedListmarker, orderedListMarkers,+      charsInBalanced', withHorizDisplacement, romanNumeral+    + Fixed a bug in the anyLine parser. Previously it would parse an empty+      string "", but it should fail on an empty string, or we get an error+      when it is used inside "many" combinators.+    + Removed followedBy' parser, replacing it with the lookAhead parser from+      Parsec.+    + Added some needed 'try's before multicharacter parsers, especially in+      'option' contexts.+    + Removed the 'try' from the 'end' parser in 'enclosed', so that+      'enclosed' behaves like 'option', 'manyTill', etc.+    + Added lineClump parser, which parses a raw line block up to and+      including any following blank lines.+    + Renamed parseFromStr to parseFromString.+    + Added a 'try' to the 'end' parser in 'enclosed'.  This makes errors in+      the use of 'enclosed' less likely. Removed some now-unnecessary 'try's+      in calling code.+    + Removed unneeded 'try' in blanklines.+    + Removed endsWith function and rewrote calling functions to use+      isSuffixOf instead.+    + Added >>~ combinator.+    + Fixed bug in normalizeSpaces:  Space:Str "":Space should compress to+      Space.++  * Refactored runtests.pl; added separate tests for tables.++  * Shell scripts:++    + Added -asxhtml flag to tidy in html2markdown. This will+      perhaps help the parser, which expects closing tags.+    + Modified markdown2pdf to run pdflatex a second time if --toc or+      --table-of-contents was specified; otherwise the table of+      contents won't appear.+    + Modified markdown2pdf to print a helpful message if the 'ulem'+      LaTeX package is required and not found.++  * Changes to build process:++    + Dropped support for compilation with GHC 6.4.  GHC 6.6 or higher+      is now required.+    + Removed cabalize and Pandoc.cabal.in. The repository now contains+      pandoc.cabal itself.+    + Pandoc.cabal has been changed to pandoc.cabal, because HackageDB+      likes the cabal file to have the same name as the tarball.+    + Expanded and revised the package description in pandoc.cabal.+      Revised the package synopsis.+    + The tarball built by 'make tarball' now contains files built from+      templates (including man pages and shell scripts), so pandoc can+      be built directly using Cabal tools, without preprocessing.+    + Executable binaries are now stripped before installing.+    + Man pages are now generated from markdown sources, using pandoc's+      man page writer.+    + Use HTML version of README (instead of RTF) in Mac OS X installer.+    + Instead of testing for the existence of a pandoc symlink in build-exec,+      use ln -f.++  * Documentation:++    + Updated README and man pages with information on new features.+    + Updated INSTALL instructions with some useful clarifications and+      links.+    + Updated web content.++  * Added FreeBSD port.++  [ Recai Oktaş ]++  * debian/control:++    + Changed pandoc's Build-Depends to include libghc6-mtl-dev and+      libghc6-xhtml-dev.  Removed libghc6-html-dev.+    + Suggest texlive-latex-recommended | tetex-extra instead of+      tetex-bin.  This brings in fancyvrb and unicode support.++ -- Recai Oktaş <roktas@debian.org>  Tue, 16 Jan 2007 00:37:21 +0200++pandoc (0.3) unstable; urgency=low++  [ John MacFarlane ]++  * Changes in pandoc options:++    + Allow options to follow or precede arguments.+    + Changed '--smartypants' to '--smart' and adjusted symbols accordingly.+    + Added '--strict' option.+    + Added '-o/--output' option.+    + Added '--dump-args' and '--ignore-args' options (for use in wrappers).+    + Modified '-v' and '-h' output to go to STDERR, not STDOUT, and return+      error conditions.  This is helpful for writing wrappers.+    + Added copyright message to '-v' output, modeled after FSF messages.+    + Reformatted usage message so that it doesn't wrap illegibly.+    + Removed extra blanks after '-h' and '-D' output.++  * Added docbook writer.++  * Added implicit setting of default input and output format based+    on input and output filename extensions.  These defaults are+    overridden if explicit input and output formats are specified using+    '-t', '-f', '-r', or '-w' options.  Documented in pandoc(1) man page+    and README.++  * Allow ordered list items to begin with (single) letters, as well+    as numbers.  The list item marker may now be terminated either by+    '.' or by ')'.  This extension to standard markdown is documented+    in README.++  * Revised footnote syntax.  (See README for full details.)  The+    '[^1]' format now standard in markdown extensions is supported,+    as are inline footnotes with this syntax: `^[My note.]`.+    The earlier footnote syntax `^(1)` is no longer supported.    * Improved HTML representation of footnotes.  All footnotes     are now auto-numbered and appear in an ordered list at the
+ data/abbreviations view
@@ -0,0 +1,28 @@+Mr.+Mrs.+Ms.+Capt.+Dr.+Prof.+Gen.+Gov.+e.g.+i.e.+Sgt.+St.+vol.+vs.+Sen.+Rep.+Pres.+Hon.+Rev.+Ph.D.+M.D.+M.A.+p.+pp.+ch.+sec.+cf.+cp.
data/bash_completion.tpl view
@@ -29,8 +29,8 @@              COMPREPLY=( $(compgen -W "references javascript none" -- ${cur}) )              return 0              ;;-         --latex-engine)-             COMPREPLY=( $(compgen -W "pdflatex lualatex xelatex" -- ${cur}) )+         --pdf-engine)+             COMPREPLY=( $(compgen -W "pdflatex lualatex xelatex wkhtmltopdf weasyprint prince context pdfroff" -- ${cur}) )              return 0              ;;          --print-default-data-file)
+ data/default.theme view
@@ -0,0 +1,177 @@+{+    "metadata" : {+        "revision" : 1,+        "name" : "Default",+        "author" : "Kate Authors",+        "license" : "MIT",+        "read-only" : true+    },+    "text-styles": {+        "Normal" : {+            "text-color" : "#1f1c1b",+            "selected-text-color" : "#ffffff",+            "bold" : false,+            "italic" : false,+            "underline" : false,+            "strike-through" : false+        },+        "Keyword" : {+            "text-color" : "#1f1c1b",+            "selected-text-color" : "#ffffff",+            "bold" : true+        },+        "Function" : {+            "text-color" : "#644a9b",+            "selected-text-color" : "#452886"+        },+        "Variable" : {+            "text-color" : "#0057ae",+            "selected-text-color" : "#00316e"+        },+        "ControlFlow" : {+            "text-color" : "#1f1c1b",+            "selected-text-color" : "#ffffff",+            "bold" : true+        },+        "Operator" : {+            "text-color" : "#1f1c1b",+            "selected-text-color" : "#ffffff"+        },+        "BuiltIn" : {+            "text-color" : "#644a9b",+            "selected-text-color" : "#452886",+            "bold" : true+        },+        "Extension" : {+            "text-color" : "#0095ff",+            "selected-text-color" : "#ffffff",+            "bold" : true+        },+        "Preprocessor" : {+            "text-color" : "#006e28",+            "selected-text-color" : "#006e28"+        },+        "Attribute" : {+            "text-color" : "#0057ae",+            "selected-text-color" : "#00316e"+        },+        "Char" : {+            "text-color" : "#924c9d",+            "selected-text-color" : "#6c2477"+        },+        "SpecialChar" : {+            "text-color" : "#3daee9",+            "selected-text-color" : "#fcfcfc"+        },+        "String" : {+            "text-color" : "#bf0303",+            "selected-text-color" : "#9c0e0e"+        },+        "VerbatimString" : {+            "text-color" : "#bf0303",+            "selected-text-color" : "#9c0e0e"+        },+        "SpecialString" : {+            "text-color" : "#ff5500",+            "selected-text-color" : "#ff5500"+        },+        "Import" : {+            "text-color" : "#ff5500",+            "selected-text-color" : "#ff5500"+        },+        "DataType" : {+            "text-color" : "#0057ae",+            "selected-text-color" : "#00316e"+        },+        "DecVal" : {+            "text-color" : "#b08000",+            "selected-text-color" : "#805c00"+        },+        "BaseN" : {+            "text-color" : "#b08000",+            "selected-text-color" : "#805c00"+        },+        "Float" : {+            "text-color" : "#b08000",+            "selected-text-color" : "#805c00"+        },+        "Constant" : {+            "text-color" : "#aa5500",+            "selected-text-color" : "#5e2f00"+        },+        "Comment" : {+            "text-color" : "#898887",+            "selected-text-color" : "#5e5d5d"+        },+        "Documentation" : {+            "text-color" : "#607880",+            "selected-text-color" : "#46585e"+        },+        "Annotation" : {+            "text-color" : "#ca60ca",+            "selected-text-color" : "#a44ea4"+        },+        "CommentVar" : {+            "text-color" : "#0095ff",+            "selected-text-color" : "#ffffff"+        },+        "RegionMarker" : {+            "text-color" : "#0057ae",+            "selected-text-color" : "#00316e",+            "background-color" : "#e0e9f8"+        },+        "Information" : {+            "text-color" : "#b08000",+            "selected-text-color" : "#805c00"+        },+        "Warning" : {+            "text-color" : "#bf0303",+            "selected-text-color" : "#9c0e0e"+        },+        "Alert" : {+            "text-color" : "#bf0303",+            "selected-text-color" : "#9c0e0e",+            "background-color" : "#f7e6e6",+            "bold" : true+        },+        "Error" : {+            "text-color" : "#bf0303",+            "selected-text-color" : "#9c0e0e",+            "underline" : true+        },+        "Others" : {+            "text-color" : "#006e28",+            "selected-text-color" : "#006e28"+        }+   },+    "editor-colors": {+        "background-color" : "#ffffff",+        "code-folding" : "#94caef",+        "bracket-matching" : "#ffff00",+        "current-line" : "#f8f7f6",+        "icon-border" : "#f0f0f0",+        "indentation-line" : "#d2d2d2",+        "line-numbers" : "#a0a0a0",+        "current-line-number" : "#1e1e1e",+        "mark-bookmark" : "#0000ff",+        "mark-breakpoint-active" : "#ff0000",+        "mark-breakpoint-reached" : "#ffff00",+        "mark-breakpoint-disabled" : "#ff00ff",+        "mark-execution" : "#a0a0a4",+        "mark-warning" : "#00ff00",+        "mark-error" : "#ff0000",+        "modified-lines" : "#fdbc4b",+        "replace-highlight" : "#00ff00",+        "saved-lines" : "#2ecc71",+        "search-highlight" : "#ffff00",+        "selection" : "#94caef",+        "separator" : "#898887",+        "spell-checking" : "#bf0303",+        "tab-marker" : "#d2d2d2",+        "template-background" : "#d6d2d0",+        "template-placeholder" : "#baf8ce",+        "template-focused-placeholder" : "#76da98",+        "template-read-only-placeholder" : "#f6e6e6",+        "word-wrap-marker" : "#ededed"+    }+}
data/docx/word/numbering.xml view
@@ -1,2 +1,3 @@-<?xml version="1.0" encoding="UTF-8"?>-<w:numbering xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"><w:abstractNum w:abstractNumId="0"><w:nsid w:val="e17f69ba" /><w:multiLevelType w:val="multilevel" /><w:lvl w:ilvl="0"><w:numFmt w:val="bullet" /><w:lvlText w:val=" " /><w:lvlJc w:val="left" /><w:pPr><w:tabs><w:tab w:val="num" w:pos="0" /></w:tabs><w:ind w:left="480" w:hanging="480" /></w:pPr></w:lvl><w:lvl w:ilvl="1"><w:numFmt w:val="bullet" /><w:lvlText w:val=" " /><w:lvlJc w:val="left" /><w:pPr><w:tabs><w:tab w:val="num" w:pos="720" /></w:tabs><w:ind w:left="1200" w:hanging="480" /></w:pPr></w:lvl><w:lvl w:ilvl="2"><w:numFmt w:val="bullet" /><w:lvlText w:val=" " /><w:lvlJc w:val="left" /><w:pPr><w:tabs><w:tab w:val="num" w:pos="1440" /></w:tabs><w:ind w:left="1920" w:hanging="480" /></w:pPr></w:lvl><w:lvl w:ilvl="3"><w:numFmt w:val="bullet" /><w:lvlText w:val=" " /><w:lvlJc w:val="left" /><w:pPr><w:tabs><w:tab w:val="num" w:pos="2160" /></w:tabs><w:ind w:left="2640" w:hanging="480" /></w:pPr></w:lvl><w:lvl w:ilvl="4"><w:numFmt w:val="bullet" /><w:lvlText w:val=" " /><w:lvlJc w:val="left" /><w:pPr><w:tabs><w:tab w:val="num" w:pos="2880" /></w:tabs><w:ind w:left="3360" w:hanging="480" /></w:pPr></w:lvl><w:lvl w:ilvl="5"><w:numFmt w:val="bullet" /><w:lvlText w:val=" " /><w:lvlJc w:val="left" /><w:pPr><w:tabs><w:tab w:val="num" w:pos="3600" /></w:tabs><w:ind w:left="4080" w:hanging="480" /></w:pPr></w:lvl><w:lvl w:ilvl="6"><w:numFmt w:val="bullet" /><w:lvlText w:val=" " /><w:lvlJc w:val="left" /><w:pPr><w:tabs><w:tab w:val="num" w:pos="4320" /></w:tabs><w:ind w:left="4800" w:hanging="480" /></w:pPr></w:lvl></w:abstractNum><w:num w:numId="1"><w:abstractNumId w:val="0" /></w:num></w:numbering>+<?xml version="1.0" encoding="utf-8"?>+<w:numbering xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">+</w:numbering>
data/docx/word/styles.xml view
@@ -251,6 +251,66 @@       <w:szCs w:val="24" />     </w:rPr>   </w:style>+  <w:style w:type="paragraph" w:styleId="Heading7">+    <w:name w:val="Heading 7" />+    <w:basedOn w:val="Normal" />+    <w:next w:val="BodyText" />+    <w:uiPriority w:val="9" />+    <w:unhideWhenUsed />+    <w:qFormat />+    <w:pPr>+      <w:keepNext />+      <w:keepLines />+      <w:spacing w:before="200" w:after="0" />+      <w:outlineLvl w:val="6" />+    </w:pPr>+    <w:rPr>+      <w:rFonts w:asciiTheme="majorHAnsi" w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi" w:cstheme="majorBidi" />+      <w:color w:val="4F81BD" w:themeColor="accent1" />+      <w:sz w:val="24" />+      <w:szCs w:val="24" />+    </w:rPr>+  </w:style>+  <w:style w:type="paragraph" w:styleId="Heading8">+    <w:name w:val="Heading 8" />+    <w:basedOn w:val="Normal" />+    <w:next w:val="BodyText" />+    <w:uiPriority w:val="9" />+    <w:unhideWhenUsed />+    <w:qFormat />+    <w:pPr>+      <w:keepNext />+      <w:keepLines />+      <w:spacing w:before="200" w:after="0" />+      <w:outlineLvl w:val="7" />+    </w:pPr>+    <w:rPr>+      <w:rFonts w:asciiTheme="majorHAnsi" w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi" w:cstheme="majorBidi" />+      <w:color w:val="4F81BD" w:themeColor="accent1" />+      <w:sz w:val="24" />+      <w:szCs w:val="24" />+    </w:rPr>+  </w:style>+  <w:style w:type="paragraph" w:styleId="Heading9">+    <w:name w:val="Heading 9" />+    <w:basedOn w:val="Normal" />+    <w:next w:val="BodyText" />+    <w:uiPriority w:val="9" />+    <w:unhideWhenUsed />+    <w:qFormat />+    <w:pPr>+      <w:keepNext />+      <w:keepLines />+      <w:spacing w:before="200" w:after="0" />+      <w:outlineLvl w:val="8" />+    </w:pPr>+    <w:rPr>+      <w:rFonts w:asciiTheme="majorHAnsi" w:eastAsiaTheme="majorEastAsia" w:hAnsiTheme="majorHAnsi" w:cstheme="majorBidi" />+      <w:color w:val="4F81BD" w:themeColor="accent1" />+      <w:sz w:val="24" />+      <w:szCs w:val="24" />+    </w:rPr>+  </w:style>   <w:style w:type="paragraph" w:styleId="BlockText">     <w:name w:val="Block Text" />     <w:basedOn w:val="BodyText" />@@ -282,8 +342,9 @@     <w:semiHidden />     <w:unhideWhenUsed />   </w:style>-  <w:style w:type="table" w:default="1" w:styleId="TableNormal">-    <w:name w:val="Normal Table" />+  <w:style w:type="table" w:default="1" w:styleId="Table">+    <w:name w:val="Table" />+    <w:basedOn w:val="TableNormal" />     <w:semiHidden />     <w:unhideWhenUsed />     <w:qFormat />@@ -340,8 +401,8 @@     <w:name w:val="Figure" />     <w:basedOn w:val="Normal" />   </w:style>-  <w:style w:type="paragraph" w:customStyle="1" w:styleId="FigureWithCaption">-    <w:name w:val="Figure with Caption" />+  <w:style w:type="paragraph" w:customStyle="1" w:styleId="CaptionedFigure">+    <w:name w:val="Captioned Figure" />     <w:basedOn w:val="Figure" />     <w:pPr>       <w:keepNext />
+ data/jats.csl view
@@ -0,0 +1,208 @@+<?xml version="1.0" encoding="utf-8"?>+<style xmlns="http://purl.org/net/xbiblio/csl" class="in-text" version="1.0" default-locale="en-US">+  <info>+    <title>Journal Article Tag Suite</title>+    <title-short>JATS</title-short>+    <id>http://www.zotero.org/styles/journal-article-tag-suite</id>+    <link href="https://github.com/MartinPaulEve/JATS-CSL/blob/master/jats.csl" rel="self"/>+    <link rel="documentation" href="http://jats.nlm.nih.gov/archiving/tag-library/1.0/index.html"/>+    <author>+      <name>Martin Paul Eve</name>+      <email>martin@martineve.com</email>+    </author>+    <category citation-format="numeric"/>+    <category field="medicine"/>+    <category field="biology"/>+    <summary>Use this style to generate bibliographic data in Journal Article Tagging Suite (JATS) 1.0 XML format</summary>+    <updated>2014-06-21T17:41:26+00:00</updated>+    <rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License. Originally by Martin Fenner.</rights>+  </info>+  <locale xml:lang="en">+    <terms>+        <term name="et-al">{{jats}}&lt;etal/&gt;{{/jats}}</term>+    </terms>+  </locale>+  <macro name="citation-number">+    <text variable="citation-number" prefix="{{jats}}id=&quot;ref-{{/jats}}" suffix="{{jats}}&quot;&gt;{{/jats}}"/>+  </macro>+  <macro name="author">+    <names variable="author">+        <name prefix="{{jats}}&lt;name&gt;{{/jats}}" suffix="{{jats}}&lt;/name&gt;{{/jats}}" name-as-sort-order="all" sort-separator="">+            <name-part name="family" text-case="capitalize-first" prefix="{{jats}}&lt;surname&gt;{{/jats}}" suffix="{{jats}}&lt;/surname&gt;{{/jats}}"/>+            <name-part name="given" text-case="capitalize-first" prefix="{{jats}}&lt;given-names&gt;{{/jats}}" suffix="{{jats}}&lt;/given-names&gt;{{/jats}}"/>+      </name>+      <substitute>+        <names variable="editor"/>+      </substitute>+    </names>+  </macro>++  <macro name="editor">+    <names variable="editor" prefix="{{jats}}&lt;person-group person-group-type=&quot;editor&quot;&gt;{{/jats}}" suffix="{{jats}}&lt;/person-group&gt;{{/jats}}">+      <name prefix="{{jats}}&lt;name&gt;{{/jats}}" suffix="{{jats}}&lt;/name&gt;{{/jats}}" name-as-sort-order="all" sort-separator="">+        <name-part name="family" text-case="capitalize-first" prefix="{{jats}}&lt;surname&gt;{{/jats}}" suffix="{{jats}}&lt;/surname&gt;{{/jats}}"/>+        <name-part name="given" text-case="capitalize-first" prefix="{{jats}}&lt;given-names&gt;{{/jats}}" suffix="{{jats}}&lt;/given-names&gt;{{/jats}}"/>+      </name>+      <substitute>+        <names variable="editor"/>+      </substitute>+    </names>+  </macro>++  <macro name="editor">+    <group delimiter=": ">+      <names variable="editor">+        <name prefix="{{jats}}&lt;name&gt;{{/jats}}" suffix="{{jats}}&lt;/name&gt;{{/jats}}" name-as-sort-order="all" sort-separator="">+          <name-part name="family" text-case="capitalize-first" prefix="{{jats}}&lt;surname&gt;{{/jats}}" suffix="{{jats}}&lt;/surname&gt;{{/jats}}"/>+          <name-part name="given" text-case="capitalize-first" prefix="{{jats}}&lt;given-names&gt;{{/jats}}" suffix="{{jats}}&lt;given-names&gt;{{/jats}}"/>+        </name>+      </names>+    </group>+  </macro>+  <macro name="title">+    <choose>+      <if type="book" match="any">+        <group prefix="{{jats}}&lt;source&gt;{{/jats}}" suffix="{{jats}}&lt;/source&gt;{{/jats}}">+	        <text variable="title"/>+				</group>			+			</if>+      <else>+        <group prefix="{{jats}}&lt;article-title&gt;{{/jats}}" suffix="{{jats}}&lt;/article-title&gt;{{/jats}}">+	        <text variable="title"/>+				</group>+      </else>+    </choose>+  </macro>+  <macro name="container-title">+    <text variable="container-title" form="short" prefix="{{jats}}&lt;source&gt;{{/jats}}" suffix="{{jats}}&lt;/source&gt;{{/jats}}"/>+  </macro>+  <macro name="publisher">+    <text variable="publisher" prefix="{{jats}}&lt;publisher-name&gt;{{/jats}}" suffix="{{jats}}&lt;/publisher-name&gt;{{/jats}}"/>+    <text variable="publisher-place" prefix="{{jats}}&lt;publisher-loc&gt;{{/jats}}" suffix="{{jats}}&lt;/publisher-loc&gt;{{/jats}}"/>+  </macro>+  <macro name="link">+    <choose>+      <if match="any" variable="DOI">+        <group prefix="{{jats}}&lt;pub-id pub-id-type=&quot;doi&quot;&gt;{{/jats}}" suffix="{{jats}}&lt;/pub-id&gt;{{/jats}}">+          <text variable="DOI"/>+        </group>+      </if>+    </choose>+    <choose>+      <if match="any" variable="PMID">+        <group prefix="{{jats}}&lt;ext-link ext-link-type=&quot;pmid&quot; {{/jats}}" suffix="{{jats}}&lt;/ext-link&gt;{{/jats}}">+          <text variable="PMID" prefix="{{jats}}xlink:href=&quot;http://www.ncbi.nlm.nih.gov/pubmed/{{/jats}}" suffix="{{jats}}&quot; xlink:type=&quot;simple&quot;&gt;{{/jats}}"/>+          <text variable="PMID"/>+        </group>+      </if>+    </choose>+    <choose>+      <if variable="URL" match="any">+        <group prefix="{{jats}}&lt;ext-link ext-link-type=&quot;uri&quot; {{/jats}}" suffix="{{jats}}&lt;/ext-link&gt;{{/jats}}">+          <text variable="URL" prefix="{{jats}}xlink:href=&quot;{{/jats}}" suffix="{{jats}}&quot; xlink:type=&quot;simple&quot;&gt;{{/jats}}"/>+          <text variable="URL"/>+        </group>+      </if>+    </choose>+  </macro>+  <macro name="date">+    <choose>+      <if type="article-journal article-magazine article-newspaper report patent book" match="any">+        <group prefix="{{jats}}&lt;date&gt;{{/jats}}" suffix="{{jats}}&lt;/date&gt;{{/jats}}">+          <date variable="issued">+            <date-part name="day" form="numeric-leading-zeros" prefix="{{jats}}&lt;day&gt;{{/jats}}" suffix="{{jats}}&lt;/day&gt;{{/jats}}"/>+            <date-part name="month" form="numeric-leading-zeros" prefix="{{jats}}&lt;month&gt;{{/jats}}" suffix="{{jats}}&lt;/month&gt;{{/jats}}"/>+            <date-part name="year" prefix="{{jats}}&lt;year&gt;{{/jats}}" suffix="{{jats}}&lt;/year&gt;{{/jats}}"/>+          </date>+        </group>+      </if>+      <else>+        <group prefix="{{jats}}&lt;date-in-citation content-type=&quot;access-date&quot;{{/jats}}" suffix="{{jats}}&lt;/date-in-citation&gt;{{/jats}}">+          <date variable="accessed" prefix="{{jats}} iso-8601-date=&quot;{{/jats}}" suffix="{{jats}}&quot;&gt;{{/jats}}">+            <date-part name="year"/>+            <date-part name="month" form="numeric-leading-zeros" prefix="{{jats}}-{{/jats}}"/>+            <date-part name="day" form="numeric-leading-zeros" prefix="{{jats}}-{{/jats}}"/>+          </date>+          <date variable="accessed">+            <date-part name="day" prefix="{{jats}}&lt;day&gt;{{/jats}}" suffix="{{jats}}&lt;/day&gt;{{/jats}}"/>+            <date-part name="month" form="numeric-leading-zeros" prefix="{{jats}}&lt;month&gt;{{/jats}}" suffix="{{jats}}&lt;/month&gt;{{/jats}}"/>+            <date-part name="year" prefix="{{jats}}&lt;year&gt;{{/jats}}" suffix="{{jats}}&lt;/year&gt;{{/jats}}"/>+          </date>+        </group>+      </else>+    </choose>+  </macro>+  <macro name="location">+    <choose>+      <if type="article-journal article-magazine" match="any">+        <text variable="volume" prefix="{{jats}}&lt;volume&gt;{{/jats}}" suffix="{{jats}}&lt;/volume&gt;{{/jats}}"/>+        <text variable="issue" prefix="{{jats}}&lt;issue&gt;{{/jats}}" suffix="{{jats}}&lt;/issue&gt;{{/jats}}"/>+      </if>+    </choose>+    <choose>+      <if type="article-journal article-magazine article-newspaper chapter" match="any">+        <text variable="page-first" prefix="{{jats}}&lt;fpage&gt;{{/jats}}" suffix="{{jats}}&lt;/fpage&gt;{{/jats}}"/>+      </if>+    </choose>+  </macro>+  <macro name="publication-type">+    <group prefix="{{jats}} publication-type=&quot;{{/jats}}" suffix="{{jats}}&quot;&gt;{{/jats}}">+      <choose>+        <if type="article-journal article-magazine article-newspaper" match="any">+          <text value="journal"/>+        </if>+        <else-if type="book" match="any">+          <text value="book"/>+        </else-if>+        <else-if type="chapter" match="any">+          <text value="bookchapter"/>+        </else-if>+        <else-if type="dataset" match="any">+          <text value="dataset"/>+        </else-if>+        <else-if type="patent" match="any">+          <text value="patent"/>+        </else-if>+        <else-if type="report" match="any">+          <text value="report"/>+        </else-if>+        <else-if type="review" match="any">+          <text value="review"/>+        </else-if>+        <else>+          <text value="standard"/>+        </else>+      </choose>+    </group>+  </macro>+  <citation collapse="citation-number">+    <sort>+      <key variable="citation-number"/>+    </sort>+    <layout delimiter=",">+      <group prefix="{{jats}}&lt;xref ref-type=&quot;bibr&quot; rid=&quot;{{/jats}}" suffix="{{jats}}&lt;/xref&gt;{{/jats}}">+        <text variable="citation-number" prefix="{{jats}}ref-{{/jats}}" suffix="{{jats}}&quot;&gt;{{/jats}}"/>+        <text variable="citation-number"/>+      </group>+    </layout>+  </citation>+  <bibliography sort-separator="">+    <layout>+      <group prefix="{{jats}}&lt;ref {{/jats}}" suffix="{{jats}}&lt;/ref&gt;{{/jats}}">+        <text macro="citation-number"/>+        <group prefix="{{jats}}&lt;element-citation{{/jats}}" suffix="{{jats}}&lt;/element-citation&gt;{{/jats}}">+          <text macro="publication-type"/>+          <text macro="author" prefix="{{jats}}&lt;person-group person-group-type=&quot;author&quot;&gt;{{/jats}}" suffix="{{jats}}&lt;/person-group&gt;{{/jats}}"/>+          <text macro="title" />+          <text macro="container-title"/>+          <text macro="editor"/>+          <text macro="publisher"/>+          <text macro="date"/>+          <text macro="location"/>+          <text macro="link"/>+        </group>+      </group>+    </layout>+  </bibliography>+</style>+
+ data/pandoc.lua view
@@ -0,0 +1,846 @@+--[[+pandoc.lua++Copyright © 2017 Albert Krewinkel++Permission to use, copy, modify, and/or distribute this software for any purpose+with or without fee is hereby granted, provided that the above copyright notice+and this permission notice appear in all copies.++THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND+FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS+OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF+THIS SOFTWARE.+]]++---+-- Lua functions for pandoc scripts.+--+-- @author Albert Krewinkel+-- @copyright © 2017 Albert Krewinkel+-- @license MIT+local M = {+  _VERSION = "0.3.0"+}++------------------------------------------------------------------------+-- The base class for pandoc's AST elements.+-- @type Element+-- @local+local Element = {}++--- Create a new element subtype+-- @local+function Element:make_subtype(o)+  o = o or {}+  setmetatable(o, self)+  self.__index = self+  return o+end++--- Create a new element given its tag and arguments+-- @local+function Element:new(tag, ...)+  local element = { t = tag }+  local content = {...}+  -- special case for unary constructors+  if #content == 1 then+    element.c = content[1]+  -- Don't set 'c' field if no further arguments were given. This is important+  -- for nullary constructors like `Space` and `HorizontalRule`.+  elseif #content > 0 then+    element.c = content+  end+  setmetatable(element, self)+  self.__index = self+  return element+end++--- Create a new constructor+-- @local+-- @param tag Tag used to identify the constructor+-- @param fn Function to be called when constructing a new element+-- @param accessors names to use as accessors for numerical fields+-- @return function that constructs a new element+function Element:create_constructor(tag, fn, accessors)+  local constr = self:make_subtype({tag = tag, getters = {}, setters = {}})++  -- Add accessors to the metatable+  if type(accessors) == "string" then+    constr.getters[accessors] = function(elem)+      return elem.c+    end+    constr.setters[accessors] = function(elem, v)+      elem.c = v+    end+  else+    for i = 1, #(accessors or {}) do+      if type(accessors[i]) == "string" then+        constr.getters[accessors[i]] = function(elem)+          return elem.c[i]+        end+        constr.setters[accessors[i]] = function(elem, v)+          elem.c[i] = v+        end+      else -- only two levels of nesting are supported+        for k, v in ipairs(accessors[i]) do+          constr.getters[v] = function(elem)+            return elem.c[i][k]+          end+          constr.setters[v] = function(elem, v)+            elem.c[i][k] = v+          end+        end+      end+    end+  end++  function constr:new(...)+    local obj = fn(...)+    setmetatable(obj, self)+    self.__index = function(t, k)+      if getmetatable(t).getters[k] then+        return getmetatable(t).getters[k](t)+      elseif k == "t" then+        return getmetatable(t)["tag"]+      else+        return getmetatable(t)[k]+      end+    end+    self.__newindex = function(t, k, v)+      if getmetatable(t).setters[k] then+        getmetatable(t).setters[k](t, v)+      else+        rawset(t, k, v)+      end+    end+    return obj+  end+  self.constructor = self.constructor or {}+  self.constructor[tag] = constr+  return constr+end++--- Calls the constructor, creating a new element.+-- @local+function Element.__call(t, ...)+  return t:new(...)+end++------------------------------------------------------------------------+--- Pandoc Document+-- @section document++--- A complete pandoc document+-- @function Pandoc+-- @tparam      {Block,...} blocks      document content+-- @tparam[opt] Meta        meta        document meta data+function M.Pandoc(blocks, meta)+  meta = meta or {}+  return {+    ["blocks"] = blocks,+    ["meta"] = meta,+    ["pandoc-api-version"] = {1,17,0,5},+  }+end++-- DEPRECATED synonym:+M.Doc = M.Pandoc++------------------------------------------------------------------------+-- MetaValue+-- @section MetaValue+M.MetaValue = Element:make_subtype{}+M.MetaValue.__call = function(t, ...)+  return t:new(...)+end+--- Meta blocks+-- @function MetaBlocks+-- @tparam {Block,...} blocks blocks++--- Meta inlines+-- @function MetaInlines+-- @tparam {Inline,...} inlines inlines++--- Meta list+-- @function MetaList+-- @tparam {MetaValue,...} meta_values list of meta values++--- Meta map+-- @function MetaMap+-- @tparam table key_value_map a string-indexed map of meta values+M.meta_value_types = {+  "MetaBlocks",+  "MetaInlines",+  "MetaList",+  "MetaMap",+}+for i = 1, #M.meta_value_types do+  M[M.meta_value_types[i]] = M.MetaValue:create_constructor(+    M.meta_value_types[i],+    function(content)+      return content+    end+  )+end++--- Creates string to be used in meta data.+-- Does nothing, lua strings are meta strings.+-- @function MetaString+-- @tparam string str string value+function M.MetaString(str)+  return str+end++--- Creates boolean to be used in meta data.+-- Does nothing, lua booleans are meta booleans.+-- @function MetaBool+-- @tparam boolean bool boolean value+function M.MetaBool(bool)+  return bool+end++------------------------------------------------------------------------+-- Blocks+-- @section Block++--- Block elements+M.Block = Element:make_subtype{}+M.Block.__call = function (t, ...)+  return t:new(...)+end++--- Creates a block quote element+-- @function BlockQuote+-- @tparam      {Block,...} content     block content+-- @treturn     Block                   block quote element+M.BlockQuote = M.Block:create_constructor(+  "BlockQuote",+  function(content) return {c = content} end,+  "content"+)++--- Creates a bullet (i.e. unordered) list.+-- @function BulletList+-- @tparam      {{Block,...},...} content     list of items+-- @treturn     Block block quote element+M.BulletList = M.Block:create_constructor(+  "BulletList",+  function(content) return {c = content} end,+  "content"+)++--- Creates a code block element+-- @function CodeBlock+-- @tparam      string      text        code string+-- @tparam[opt] Attr        attr element attributes+-- @treturn     Block                   code block element+M.CodeBlock = M.Block:create_constructor(+  "CodeBlock",+  function(text, attr) return {c = {attr or M.Attr(), text}} end,+  {{"identifier", "classes", "attributes"}, "text"}+)++--- Creates a definition list, containing terms and their explanation.+-- @function DefinitionList+-- @tparam      {{{Inline,...},{Block,...}},...} content     list of items+-- @treturn     Block block quote element+M.DefinitionList = M.Block:create_constructor(+  "DefinitionList",+  function(content) return {c = content} end,+  "content"+)++--- Creates a div element+-- @function Div+-- @tparam      {Block,...} content     block content+-- @tparam[opt] Attr        attr  element attributes+-- @treturn     Block                   code block element+M.Div = M.Block:create_constructor(+  "Div",+  function(content, attr)+    return {c = {attr or M.Attr(), content}}+  end,+  {{"identifier", "classes", "attributes"}, "content"}+)++--- Creates a block quote element.+-- @function Header+-- @tparam      int          level       header level+-- @tparam      {Inline,...} content     inline content+-- @tparam[opt] Attr         attr element attributes+-- @treturn     Block                    header element+M.Header = M.Block:create_constructor(+  "Header",+  function(level, content, attr)+    return {c = {level, attr or M.Attr(), content}}+  end,+  {"level", {"identifier", "classes", "attributes"}, "content"}+)++--- Creates a horizontal rule.+-- @function HorizontalRule+-- @treturn     Block                   horizontal rule+M.HorizontalRule = M.Block:create_constructor(+  "HorizontalRule",+  function() return {} end+)++--- Creates a line block element.+-- @function LineBlock+-- @tparam      {{Inline,...},...} content    inline content+-- @treturn     Block                   block quote element+M.LineBlock = M.Block:create_constructor(+  "LineBlock",+  function(content) return {c = content} end,+  "content"+)++--- Creates a null element.+-- @function Null+-- @treturn     Block                   null element+M.Null = M.Block:create_constructor(+  "Null",+  function() return {} end+)++--- Creates an ordered list.+-- @function OrderedList+-- @tparam      {{Block,...},...} items list items+-- @param[opt]  listAttributes list parameters+-- @treturn     Block+M.OrderedList = M.Block:create_constructor(+  "OrderedList",+  function(items, listAttributes)+    listAttributes = listAttributes or {1, M.DefaultStyle, M.DefaultDelim}+    return {c = {listAttributes, items}}+  end,+  {{"start", "style", "delimiter"}, "content"}+)++--- Creates a para element.+-- @function Para+-- @tparam      {Inline,...} content    inline content+-- @treturn     Block                   block quote element+M.Para = M.Block:create_constructor(+  "Para",+  function(content) return {c = content} end,+  "content"+)++--- Creates a plain element.+-- @function Plain+-- @tparam      {Inline,...} content    inline content+-- @treturn     Block                   block quote element+M.Plain = M.Block:create_constructor(+  "Plain",+  function(content) return {c = content} end,+  "content"+)++--- Creates a raw content block of the specified format.+-- @function RawBlock+-- @tparam      string      format      format of content+-- @tparam      string      text        string content+-- @treturn     Block                   block quote element+M.RawBlock = M.Block:create_constructor(+  "RawBlock",+  function(format, text) return {c = {format, text}} end,+  {"format", "text"}+)++--- Creates a table element.+-- @function Table+-- @tparam      {Inline,...} caption    table caption+-- @tparam      {AlignDefault|AlignLeft|AlignRight|AlignCenter,...} aligns alignments+-- @tparam      {int,...}    widths     column widths+-- @tparam      {Block,...}  headers    header row+-- @tparam      {{Block,...}} rows      table rows+-- @treturn     Block                   block quote element+M.Table = M.Block:create_constructor(+  "Table",+  function(caption, aligns, widths, headers, rows)+    return {c = {caption, aligns, widths, headers, rows}}+  end,+  {"caption", "aligns", "widths", "headers", "rows"}+)+++------------------------------------------------------------------------+-- Inline+-- @section Inline++--- Inline element class+M.Inline = Element:make_subtype{}+M.Inline.__call = function (t, ...)+  return t:new(...)+end++--- Creates a Cite inline element+-- @function Cite+-- @tparam {Inline,...}   content       List of inlines+-- @tparam {Citation,...} citations     List of citations+-- @treturn Inline citations element+M.Cite = M.Inline:create_constructor(+  "Cite",+  function(content, citations) return {c = {citations, content}} end,+  {"citations", "content"}+)++--- Creates a Code inline element+-- @function Code+-- @tparam      string      text        brief image description+-- @tparam[opt] Attr        attr  additional attributes+-- @treturn Inline code element+M.Code = M.Inline:create_constructor(+  "Code",+  function(text, attr) return {c = {attr or M.Attr(), text}} end,+  {{"identifier", "classes", "attributes"}, "text"}+)++--- Creates an inline element representing emphasised text.+-- @function Emph+-- @tparam      {Inline,..} content     inline content+-- @treturn Inline emphasis element+M.Emph = M.Inline:create_constructor(+  "Emph",+  function(content) return {c = content} end,+  "content"+)++--- Creates a Image inline element+-- @function Image+-- @tparam      {Inline,..} caption     text used to describe the image+-- @tparam      string      src         path to the image file+-- @tparam[opt] string      title       brief image description+-- @tparam[opt] Attr        attr additional attributes+-- @treturn Inline image element+M.Image = M.Inline:create_constructor(+  "Image",+  function(caption, src, title, attr)+    title = title or ""+    attr = attr or M.Attr()+    return {c = {attr, caption, {src, title}}}+  end,+  {{"identifier", "classes", "attributes"}, "caption", {"src", "title"}}+)++--- Create a LineBreak inline element+-- @function LineBreak+-- @treturn Inline linebreak element+M.LineBreak = M.Inline:create_constructor(+  "LineBreak",+  function() return {} end+)++--- Creates a link inline element, usually a hyperlink.+-- @function Link+-- @tparam      {Inline,..} content     text for this link+-- @tparam      string      target      the link target+-- @tparam[opt] string      title       brief link description+-- @tparam[opt] Attr        attr additional attributes+-- @treturn Inline image element+M.Link = M.Inline:create_constructor(+  "Link",+  function(content, target, title, attr)+    title = title or ""+    attr = attr or M.Attr()+    return {c = {attr, content, {target, title}}}+  end,+  {{"identifier", "classes", "attributes"}, "content", {"target", "title"}}+)++--- Creates a Math element, either inline or displayed.+-- @function Math+-- @tparam      "InlineMath"|"DisplayMath" mathtype rendering specifier+-- @tparam      string      text        Math content+-- @treturn     Inline                  Math element+M.Math = M.Inline:create_constructor(+  "Math",+  function(mathtype, text)+    return {c = {mathtype, text}}+  end,+  {"mathtype", "text"}+)+--- Creates a DisplayMath element (DEPRECATED).+-- @function DisplayMath+-- @tparam      string      text        Math content+-- @treturn     Inline                  Math element+M.DisplayMath = M.Inline:create_constructor(+  "DisplayMath",+  function(text) return M.Math("DisplayMath", text) end,+  {"mathtype", "text"}+)+--- Creates an InlineMath inline element (DEPRECATED).+-- @function InlineMath+-- @tparam      string      text        Math content+-- @treturn     Inline                  Math element+M.InlineMath = M.Inline:create_constructor(+  "InlineMath",+  function(text) return M.Math("InlineMath", text) end,+  {"mathtype", "text"}+)++--- Creates a Note inline element+-- @function Note+-- @tparam      {Block,...} content     footnote block content+M.Note = M.Inline:create_constructor(+  "Note",+  function(content) return {c = content} end,+  "content"+)++--- Creates a Quoted inline element given the quote type and quoted content.+-- @function Quoted+-- @tparam      "DoubleQuote"|"SingleQuote" quotetype type of quotes to be used+-- @tparam      {Inline,..} content     inline content+-- @treturn     Inline                  quoted element+M.Quoted = M.Inline:create_constructor(+  "Quoted",+  function(quotetype, content) return {c = {quotetype, content}} end,+  {"quotetype", "content"}+)+--- Creates a single-quoted inline element (DEPRECATED).+-- @function SingleQuoted+-- @tparam      {Inline,..} content     inline content+-- @treturn     Inline                  quoted element+-- @see Quoted+M.SingleQuoted = M.Inline:create_constructor(+  "SingleQuoted",+  function(content) return M.Quoted(M.SingleQuote, content) end,+  {"quotetype", "content"}+)+--- Creates a single-quoted inline element (DEPRECATED).+-- @function DoubleQuoted+-- @tparam      {Inline,..} content     inline content+-- @treturn     Inline                  quoted element+-- @see Quoted+M.DoubleQuoted = M.Inline:create_constructor(+  "DoubleQuoted",+  function(content) return M.Quoted("DoubleQuote", content) end,+  {"quotetype", "content"}+)++--- Creates a RawInline inline element+-- @function RawInline+-- @tparam      string      format      format of the contents+-- @tparam      string      text        string content+-- @treturn     Inline                  raw inline element+M.RawInline = M.Inline:create_constructor(+  "RawInline",+  function(format, text) return {c = {format, text}} end,+  {"format", "text"}+)++--- Creates text rendered in small caps+-- @function SmallCaps+-- @tparam      {Inline,..} content     inline content+-- @treturn     Inline                  smallcaps element+M.SmallCaps = M.Inline:create_constructor(+  "SmallCaps",+  function(content) return {c = content} end,+  "content"+)++--- Creates a SoftBreak inline element.+-- @function SoftBreak+-- @treturn     Inline                  softbreak element+M.SoftBreak = M.Inline:create_constructor(+  "SoftBreak",+  function() return {} end+)++--- Create a Space inline element+-- @function Space+-- @treturn Inline space element+M.Space = M.Inline:create_constructor(+  "Space",+  function() return {} end+)++--- Creates a Span inline element+-- @function Span+-- @tparam      {Inline,..} content     inline content+-- @tparam[opt] Attr        attr  additional attributes+-- @treturn Inline span element+M.Span = M.Inline:create_constructor(+  "Span",+  function(content, attr) return {c = {attr or M.Attr(), content}} end,+  {{"identifier", "classes", "attributes"}, "content"}+)++--- Creates a Str inline element+-- @function Str+-- @tparam      string      text        content+-- @treturn     Inline                  string element+M.Str = M.Inline:create_constructor(+  "Str",+  function(text) return {c = text} end,+  "text"+)++--- Creates text which is striked out.+-- @function Strikeout+-- @tparam      {Inline,..} content     inline content+-- @treturn     Inline                  strikeout element+M.Strikeout = M.Inline:create_constructor(+  "Strikeout",+  function(content) return {c = content} end,+  "content"+)++--- Creates a Strong element, whose text is usually displayed in a bold font.+-- @function Strong+-- @tparam      {Inline,..} content     inline content+-- @treturn     Inline                  strong element+M.Strong = M.Inline:create_constructor(+  "Strong",+  function(content) return {c = content} end,+  "content"+)++--- Creates a Subscript inline element+-- @function Subscript+-- @tparam      {Inline,..} content     inline content+-- @treturn     Inline                  subscript element+M.Subscript = M.Inline:create_constructor(+  "Subscript",+  function(content) return {c = content} end,+  "content"+)++--- Creates a Superscript inline element+-- @function Superscript+-- @tparam      {Inline,..} content     inline content+-- @treturn     Inline                  strong element+M.Superscript = M.Inline:create_constructor(+  "Superscript",+  function(content) return {c = content} end,+  "content"+)+++------------------------------------------------------------------------+-- Helpers+-- @section helpers++-- Attr+M.Attr = {}+M.Attr._field_names = {identifier = 1, classes = 2, attributes = 3}+--- Create a new set of attributes (Attr).+-- @function Attr+-- @tparam[opt] string       identifier element identifier+-- @tparam[opt] {string,...} classes    element classes+-- @tparam[opt] table        attributes table containing string keys and values+-- @return element attributes+M.Attr.__call = function(t, identifier, classes, attributes)+  identifier = identifier or ''+  classes = classes or {}+  attributes = attributes or {}+  local attr = {identifier, classes, attributes}+  setmetatable(attr, t)+  return attr+end+M.Attr.__index = function(t, k)+  return rawget(t, k) or+    rawget(t, M.Attr._field_names[k]) or+    rawget(getmetatable(t), k)+end+M.Attr.__newindex = function(t, k, v)+  if M.Attr._field_names[k] then+    rawset(t, M.Attr._field_names[k], v)+  else+    rawset(t, k, v)+  end+end+setmetatable(M.Attr, M.Attr)+++--- Creates a single citation.+-- @function Citation+-- @tparam      string       id       citation identifier (like a bibtex key)+-- @tparam      AuthorInText|SuppressAuthor|NormalCitation mode citation mode+-- @tparam[opt] {Inline,...} prefix   citation prefix+-- @tparam[opt] {Inline,...} suffix   citation suffix+-- @tparam[opt] int          note_num note number+-- @tparam[opt] int          hash  hash number+M.Citation = function(id, mode, prefix, suffix, note_num, hash)+  prefix = prefix or {}+  suffix = suffix or {}+  note_num = note_num or 0+  hash = hash or 0+  return {+    citationId = id,+    citationPrefix = prefix,+    citationSuffix = suffix,+    citationMode = mode,+    citationNoteNum = note_num,+    citationHash = hash,+  }+end+++------------------------------------------------------------------------+-- Constants+-- @section constants++--- Author name is mentioned in the text.+-- @see Citation+-- @see Cite+M.AuthorInText = "AuthorInText"++--- Author name is suppressed.+-- @see Citation+-- @see Cite+M.SuppressAuthor = "SuppressAuthor"++--- Default citation style is used.+-- @see Citation+-- @see Cite+M.NormalCitation = "NormalCitation"++--- Table cells aligned left.+-- @see Table+M.AlignLeft = "AlignLeft"++--- Table cells right-aligned.+-- @see Table+M.AlignRight = "AlignRight"++--- Table cell content is centered.+-- @see Table+M.AlignCenter = "AlignCenter"++--- Table cells are alignment is unaltered.+-- @see Table+M.AlignDefault = "AlignDefault"++--- Default list number delimiters are used.+-- @see OrderedList+M.DefaultDelim = "DefaultDelim"++--- List numbers are delimited by a period.+-- @see OrderedList+M.Period = "Period"++--- List numbers are delimited by a single parenthesis.+-- @see OrderedList+M.OneParen = "OneParen"++--- List numbers are delimited by a double parentheses.+-- @see OrderedList+M.TwoParens = "TwoParens"++--- List are numbered in the default style+-- @see OrderedList+M.DefaultStyle = "DefaultStyle"++--- List items are numbered as examples.+-- @see OrderedList+M.Example = "Example"++--- List are numbered using decimal integers.+-- @see OrderedList+M.Decimal = "Decimal"++--- List are numbered using lower-case roman numerals.+-- @see OrderedList+M.LowerRoman = "LowerRoman"++--- List are numbered using upper-case roman numerals+-- @see OrderedList+M.UpperRoman = "UpperRoman"++--- List are numbered using lower-case alphabetic characters.+-- @see OrderedList+M.LowerAlpha = "LowerAlpha"++--- List are numbered using upper-case alphabetic characters.+-- @see OrderedList+M.UpperAlpha = "UpperAlpha"+++------------------------------------------------------------------------+-- Helper Functions+-- @section helpers++--- Parse the given string into a Pandoc document.+-- The method used to interpret input is specified by *format*. Acceptable+-- values for this parameter are equal to those that can be given to the+-- `--from` command line option.+-- @tparam      string markup the markup to be parsed+-- @tparam[opt] string format format specification, defaults to "markdown".+-- @treturn Pandoc pandoc document+-- @usage+-- local org_markup = "/emphasis/"  -- Input to be read+-- local document = pandoc.read(org_markup, "org")+-- -- Get the first block of the document+-- local block = document.blocks[1]+-- -- The inline element in that block is an `Emph`+-- assert(block.content[1].t == "Emph")+function M.read(markup, format)+  format = format or "markdown"+  local pd = pandoc._read(format, markup)+  if type(pd) == "string" then+    error(pd)+  else+    return pd+  end+end++--- Runs command with arguments, passing it some input, and returns the output.+-- @treturn string Output of command.+-- @raise A table containing the keys `command`, `error_code`, and `output` is+-- thrown if the command exits with a non-zero error code.+-- @usage+-- local ec, output = pandoc.pipe("sed", {"-e","s/a/b/"}, "abc")+function M.pipe (command, args, input)+  local ec, output = pandoc._pipe(command, args, input)+  if ec ~= 0 then+    err = setmetatable(+      { command = command, error_code = ec, output = output},+      { __tostring = function(e)+          return "Error running " .. e.command+            .. " (error code " .. e.error_code .. "): "+            .. e.output+        end+      }+    )+    error(err)+  end+  return output+end++--- Use functions defined in the global namespace to create a pandoc filter.+-- All globally defined functions which have names of pandoc elements are+-- collected into a new table.+-- @return A list of filter functions+-- @usage+-- -- within a file defining a pandoc filter:+-- function Str(text)+--   return pandoc.Str(utf8.upper(text))+-- end+--+-- return {pandoc.global_filter()}+-- -- the above is equivallent to+-- -- return {{Str = Str}}+function M.global_filter()+  local res = {}+  function is_filter_function(k)+    return M.Inline.constructor[k] or+      M.Block.constructor[k] or+      k == "Meta" or k == "Doc" or k == "Pandoc" or+      k == "Block" or k == "Inline"+  end+  for k, v in pairs(_G) do+    if is_filter_function(k) then+      res[k] = v+    end+  end+  return res+end++return M
− data/templates/default.beamer
@@ -1,278 +0,0 @@-\documentclass[$if(fontsize)$$fontsize$,$endif$$if(lang)$$babel-lang$,$endif$$if(handout)$handout,$endif$$if(beamer)$ignorenonframetext,$endif$$for(classoption)$$classoption$$sep$,$endfor$]{$documentclass$}-\setbeamertemplate{caption}[numbered]-\setbeamertemplate{caption label separator}{: }-\setbeamercolor{caption name}{fg=normal text.fg}-\beamertemplatenavigationsymbols$if(navigation)$$navigation$$else$empty$endif$-$if(fontfamily)$-\usepackage[$for(fontfamilyoptions)$$fontfamilyoptions$$sep$,$endfor$]{$fontfamily$}-$else$-\usepackage{lmodern}-$endif$-\usepackage{amssymb,amsmath}-\usepackage{ifxetex,ifluatex}-\usepackage{fixltx2e} % provides \textsubscript-\ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex-  \usepackage[$if(fontenc)$$fontenc$$else$T1$endif$]{fontenc}-  \usepackage[utf8]{inputenc}-$if(euro)$-  \usepackage{eurosym}-$endif$-\else % if luatex or xelatex-  \ifxetex-    \usepackage{mathspec}-  \else-    \usepackage{fontspec}-  \fi-  \defaultfontfeatures{Ligatures=TeX,Scale=MatchLowercase}-$for(fontfamilies)$-  \newfontfamily{$fontfamilies.name$}[$fontfamilies.options$]{$fontfamilies.font$}-$endfor$-$if(euro)$-  \newcommand{\euro}{€}-$endif$-$if(mainfont)$-    \setmainfont[$for(mainfontoptions)$$mainfontoptions$$sep$,$endfor$]{$mainfont$}-$endif$-$if(sansfont)$-    \setsansfont[$for(sansfontoptions)$$sansfontoptions$$sep$,$endfor$]{$sansfont$}-$endif$-$if(monofont)$-    \setmonofont[Mapping=tex-ansi$if(monofontoptions)$,$for(monofontoptions)$$monofontoptions$$sep$,$endfor$$endif$]{$monofont$}-$endif$-$if(mathfont)$-    \setmathfont(Digits,Latin,Greek)[$for(mathfontoptions)$$mathfontoptions$$sep$,$endfor$]{$mathfont$}-$endif$-$if(CJKmainfont)$-    \usepackage{xeCJK}-    \setCJKmainfont[$for(CJKoptions)$$CJKoptions$$sep$,$endfor$]{$CJKmainfont$}-$endif$-\fi-$if(theme)$-\usetheme[$for(themeoptions)$$themeoptions$$sep$,$endfor$]{$theme$}-$endif$-$if(colortheme)$-\usecolortheme{$colortheme$}-$endif$-$if(fonttheme)$-\usefonttheme{$fonttheme$}-$endif$-$if(mainfont)$-\usefonttheme{serif} % use mainfont rather than sansfont for slide text-$endif$-$if(innertheme)$-\useinnertheme{$innertheme$}-$endif$-$if(outertheme)$-\useoutertheme{$outertheme$}-$endif$-% use upquote if available, for straight quotes in verbatim environments-\IfFileExists{upquote.sty}{\usepackage{upquote}}{}-% use microtype if available-\IfFileExists{microtype.sty}{%-\usepackage{microtype}-\UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts-}{}-$if(lang)$-\ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex-  \usepackage[shorthands=off,$for(babel-otherlangs)$$babel-otherlangs$,$endfor$main=$babel-lang$]{babel}-$if(babel-newcommands)$-  $babel-newcommands$-$endif$-\else-  \usepackage{polyglossia}-  \setmainlanguage[$polyglossia-lang.options$]{$polyglossia-lang.name$}-$for(polyglossia-otherlangs)$-  \setotherlanguage[$polyglossia-otherlangs.options$]{$polyglossia-otherlangs.name$}-$endfor$-\fi-$endif$-\newif\ifbibliography-$if(natbib)$-\usepackage{natbib}-\bibliographystyle{$if(biblio-style)$$biblio-style$$else$plainnat$endif$}-$endif$-$if(biblatex)$-\usepackage[$if(biblio-style)$style=$biblio-style$,$endif$$for(biblatexoptions)$$biblatexoptions$$sep$,$endfor$]{biblatex}-$for(bibliography)$-\addbibresource{$bibliography$}-$endfor$-$endif$-$if(verbatim-in-note)$-\usepackage{fancyvrb}-$endif$-\hypersetup{-$if(title-meta)$-            pdftitle={$title-meta$},-$endif$-$if(author-meta)$-            pdfauthor={$author-meta$},-$endif$-$if(keywords)$-            pdfkeywords={$for(keywords)$$keywords$$sep$, $endfor$},-$endif$-$if(colorlinks)$-            colorlinks=true,-            linkcolor=$if(linkcolor)$$linkcolor$$else$Maroon$endif$,-            citecolor=$if(citecolor)$$citecolor$$else$Blue$endif$,-            urlcolor=$if(urlcolor)$$urlcolor$$else$Blue$endif$,-$else$-            pdfborder={0 0 0},-$endif$-            breaklinks=true}-\urlstyle{same}  % don't use monospace font for urls-$if(verbatim-in-note)$-\VerbatimFootnotes % allows verbatim text in footnotes-$endif$-$if(listings)$-\usepackage{listings}-$endif$-$if(lhs)$-\lstnewenvironment{code}{\lstset{language=Haskell,basicstyle=\small\ttfamily}}{}-$endif$-$if(highlighting-macros)$-$highlighting-macros$-$endif$-$if(tables)$-\usepackage{longtable,booktabs}-\usepackage{caption}-% These lines are needed to make table captions work with longtable:-\makeatletter-\def\fnum@table{\tablename~\thetable}-\makeatother-$endif$-$if(graphics)$-\usepackage{graphicx,grffile}-\makeatletter-\def\maxwidth{\ifdim\Gin@nat@width>\linewidth\linewidth\else\Gin@nat@width\fi}-\def\maxheight{\ifdim\Gin@nat@height>\textheight0.8\textheight\else\Gin@nat@height\fi}-\makeatother-% Scale images if necessary, so that they will not overflow the page-% margins by default, and it is still possible to overwrite the defaults-% using explicit options in \includegraphics[width, height, ...]{}-\setkeys{Gin}{width=\maxwidth,height=\maxheight,keepaspectratio}-$endif$--% Prevent slide breaks in the middle of a paragraph:-\widowpenalties 1 10000-\raggedbottom--$if(section-titles)$-\AtBeginPart{-  \let\insertpartnumber\relax-  \let\partname\relax-  \frame{\partpage}-}-\AtBeginSection{-  \ifbibliography-  \else-    \let\insertsectionnumber\relax-    \let\sectionname\relax-    \frame{\sectionpage}-  \fi-}-\AtBeginSubsection{-  \let\insertsubsectionnumber\relax-  \let\subsectionname\relax-  \frame{\subsectionpage}-}-$endif$--$if(links-as-notes)$-% Make links footnotes instead of hotlinks:-\renewcommand{\href}[2]{#2\footnote{\url{#1}}}-$endif$-$if(strikeout)$-\usepackage[normalem]{ulem}-% avoid problems with \sout in headers with hyperref:-\pdfstringdefDisableCommands{\renewcommand{\sout}{}}-$endif$-\setlength{\parindent}{0pt}-\setlength{\parskip}{6pt plus 2pt minus 1pt}-\setlength{\emergencystretch}{3em}  % prevent overfull lines-\providecommand{\tightlist}{%-  \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}-$if(numbersections)$-\setcounter{secnumdepth}{$if(secnumdepth)$$secnumdepth$$else$5$endif$}-$else$-\setcounter{secnumdepth}{0}-$endif$-$if(dir)$-\ifxetex-  % load bidi as late as possible as it modifies e.g. graphicx-  $if(latex-dir-rtl)$-  \usepackage[RTLdocument]{bidi}-  $else$-  \usepackage{bidi}-  $endif$-\fi-\ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex-  \TeXXeTstate=1-  \newcommand{\RL}[1]{\beginR #1\endR}-  \newcommand{\LR}[1]{\beginL #1\endL}-  \newenvironment{RTL}{\beginR}{\endR}-  \newenvironment{LTR}{\beginL}{\endL}-\fi-$endif$-$for(header-includes)$-$header-includes$-$endfor$--$if(title)$-\title{$title$}-$endif$-$if(subtitle)$-\subtitle{$subtitle$}-$endif$-$if(author)$-\author{$for(author)$$author$$sep$ \and $endfor$}-$endif$-$if(institute)$-\institute{$for(institute)$$institute$$sep$ \and $endfor$}-$endif$-\date{$date$}--\begin{document}-$if(title)$-\frame{\titlepage}-$endif$--$for(include-before)$-$include-before$--$endfor$-$if(toc)$-\begin{frame}-\tableofcontents[hideallsubsections]-\end{frame}--$endif$-$body$--$if(natbib)$-$if(bibliography)$-$if(biblio-title)$-$if(book-class)$-\renewcommand\bibname{$biblio-title$}-$else$-\renewcommand\refname{$biblio-title$}-$endif$-$endif$-\begin{frame}[allowframebreaks]{$biblio-title$}-\bibliographytrue-\bibliography{$for(bibliography)$$bibliography$$sep$,$endfor$}-\end{frame}--$endif$-$endif$-$if(biblatex)$-\begin{frame}[allowframebreaks]{$biblio-title$}-\bibliographytrue-\printbibliography[heading=none]-\end{frame}--$endif$-$for(include-after)$-$include-after$--$endfor$-\end{document}
data/templates/default.commonmark view
@@ -11,7 +11,7 @@  $endfor$ $if(toc)$-$toc$+$table-of-contents$  $endif$ $body$
data/templates/default.context view
@@ -23,6 +23,7 @@   style=$linkstyle$,   color=$linkcolor$,   contrastcolor=$linkcontrastcolor$]+ % make chapter, section bookmarks visible when opening document \placebookmarks[chapter, section, subsection, subsubsection, subsubsubsection, subsubsubsubsection][chapter, section] \setupinteractionscreen[option=bookmark]@@ -37,26 +38,22 @@ $if(pagenumbering)$ \setuppagenumbering[$for(pagenumbering)$$pagenumbering$$sep$,$endfor$] $endif$+ % use microtypography \definefontfeature[default][default][script=latn, protrusion=quality, expansion=quality, itlc=yes, textitalics=yes, onum=yes, pnum=yes] \definefontfeature[smallcaps][script=latn, protrusion=quality, expansion=quality, smcp=yes, onum=yes, pnum=yes] \setupalign[hz,hanging] \setupitaliccorrection[global, always]+ \setupbodyfontenvironment[default][em=italic] % use italic as em, not slanted-\usemodule[simplefonts$if(fontsize)$,$fontsize$$endif$]-\setmainfontfallback[DejaVu Serif][range={greekandcoptic, greekextended}, force=yes, rscale=auto]-$if(mainfont)$-\setmainfont[$mainfont$]-$endif$-$if(sansfont)$-\setsansfont[$sansfont$][rscale=auto]-$endif$-$if(monofont)$-\setmonofont[$monofont$][features=none, rscale=auto]-$endif$-$if(mathfont)$-\setmathfont[$mathfont$][rscale=auto]-$endif$++\definefallbackfamily[mainface][rm][DejaVu Serif][preset=range:greek, force=yes]+\definefontfamily[mainface][rm][$if(mainfont)$$mainfont$$else$Latin Modern Roman$endif$]+\definefontfamily[mainface][mm][$if(mathfont)$$mathfont$$else$Latin Modern Math$endif$]+\definefontfamily[mainface][ss][$if(sansfont)$$sansfont$$else$Latin Modern Sans$endif$]+\definefontfamily[mainface][tt][$if(monofont)$$monofont$$else$Latin Modern Typewriter$endif$][features=none]+\setupbodyfont[mainface$if(fontsize)$,$fontsize$$endif$]+ \setupwhitespace[$if(whitespace)$$whitespace$$else$medium$endif$] $if(indenting)$ \setupindenting[$for(indenting)$$indenting$$sep$,$endfor$]
− data/templates/default.docbook
@@ -1,32 +0,0 @@-<?xml version="1.0" encoding="utf-8" ?>-$if(mathml)$-<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook EBNF Module V1.1CR1//EN"-                  "http://www.oasis-open.org/docbook/xml/mathml/1.1CR1/dbmathml.dtd">-$else$-<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"-                  "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">-$endif$-<article>-  <articleinfo>-    <title>$title$</title>-$if(author)$-    <authorgroup>-$for(author)$-      <author>-        $author$-      </author>-$endfor$-    </authorgroup>-$endif$-$if(date)$-    <date>$date$</date>-$endif$-  </articleinfo>-$for(include-before)$-$include-before$-$endfor$-$body$-$for(include-after)$-$include-after$-$endfor$-</article>
+ data/templates/default.docbook4 view
@@ -0,0 +1,32 @@+<?xml version="1.0" encoding="utf-8" ?>+$if(mathml)$+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook EBNF Module V1.1CR1//EN"+                  "http://www.oasis-open.org/docbook/xml/mathml/1.1CR1/dbmathml.dtd">+$else$+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"+                  "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">+$endif$+<article>+  <articleinfo>+    <title>$title$</title>+$if(author)$+    <authorgroup>+$for(author)$+      <author>+        $author$+      </author>+$endfor$+    </authorgroup>+$endif$+$if(date)$+    <date>$date$</date>+$endif$+  </articleinfo>+$for(include-before)$+$include-before$+$endfor$+$body$+$for(include-after)$+$include-after$+$endfor$+</article>
data/templates/default.docbook5 view
@@ -1,6 +1,9 @@ <?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE article> <article+$if(lang)$+  xml:lang="$lang$"+$endif$   xmlns="http://docbook.org/ns/docbook" version="5.0" $if(mathml)$   xmlns:mml="http://www.w3.org/1998/Math/MathML"@@ -8,6 +11,9 @@   xmlns:xlink="http://www.w3.org/1999/xlink" >   <info>     <title>$title$</title>+$if(subtitle)$+    <subtitle>$subtitle$</subtitle>+$endif$ $if(author)$     <authorgroup> $for(author)$
data/templates/default.dzslides view
@@ -12,10 +12,14 @@   <meta name="keywords" content="$for(keywords)$$keywords$$sep$, $endfor$"> $endif$   <title>$if(title-prefix)$$title-prefix$ – $endif$$pagetitle$</title>-  <style type="text/css">code{white-space: pre-wrap;}</style>+  <style type="text/css">+      code{white-space: pre-wrap;}+      .smallcaps{font-variant: small-caps;}+      .column{display: inline-block;} $if(quotes)$-  <style type="text/css">q { quotes: "“" "”" "‘" "’"; }</style>+      q { quotes: "“" "”" "‘" "’"; } $endif$+  </style> $if(highlighting-css)$   <style type="text/css"> $highlighting-css$@@ -26,7 +30,7 @@   <link rel="stylesheet" href="$css$"> $endfor$ $else$-<link href='http://fonts.googleapis.com/css?family=Oswald' rel='stylesheet'>+<link href='https://fonts.googleapis.com/css?family=Oswald' rel='stylesheet'>  <style>   html, .view body { background-color: black; counter-reset: slideidx; }@@ -183,7 +187,7 @@ $endif$ $if(toc)$ <section id="$idprefix$TOC">-$toc$+$table-of-contents$ </section> $endif$ $for(include-before)$
− data/templates/default.epub
@@ -1,59 +0,0 @@-<?xml version="1.0" encoding="UTF-8"?>-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">-<html xmlns="http://www.w3.org/1999/xhtml"$if(lang)$ xml:lang="$lang$"$endif$>-<head>-  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />-  <meta http-equiv="Content-Style-Type" content="text/css" />-  <meta name="generator" content="pandoc" />-  <title>$pagetitle$</title>-$if(highlighting-css)$-  <style type="text/css">-$highlighting-css$-  </style>-$endif$-$for(css)$-  <link rel="stylesheet" type="text/css" href="$css$" />-$endfor$-$for(header-includes)$-  $header-includes$-$endfor$-</head>-<body$if(coverpage)$ id="cover"$endif$>-$if(titlepage)$-$for(title)$-$if(title.text)$-  <h1 class="$title.type$">$title.text$</h1>-$else$-  <h1 class="title">$title$</h1>-$endif$-$endfor$-$if(subtitle)$-  <p class="subtitle">$subtitle$</p>-$endif$-$for(author)$-  <p class="author">$author$</p>-$endfor$-$for(creator)$-  <p class="$creator.role$">$creator.text$</p>-$endfor$-$if(publisher)$-  <p class="publisher">$publisher$</p>-$endif$-$if(date)$-  <p class="date">$date$</p>-$endif$-$if(rights)$-  <div class="rights">$rights$</div>-$endif$-$else$-$for(include-before)$-$include-before$-$endfor$-$body$-$for(include-after)$-$include-after$-$endfor$-$endif$-</body>-</html>-
+ data/templates/default.epub2 view
@@ -0,0 +1,67 @@+<?xml version="1.0" encoding="UTF-8"?>+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">+<html xmlns="http://www.w3.org/1999/xhtml"$if(lang)$ xml:lang="$lang$"$endif$>+<head>+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />+  <meta http-equiv="Content-Style-Type" content="text/css" />+  <meta name="generator" content="pandoc" />+  <title>$pagetitle$</title>+  <style type="text/css">+      code{white-space: pre-wrap;}+      .smallcaps{font-variant: small-caps;}+      .line-block{white-space: pre-line;}+$if(quotes)$+      q { quotes: "“" "”" "‘" "’"; }+$endif$+  </style>+$if(highlighting-css)$+  <style type="text/css">+$highlighting-css$+  </style>+$endif$+$for(css)$+  <link rel="stylesheet" type="text/css" href="$css$" />+$endfor$+$for(header-includes)$+  $header-includes$+$endfor$+</head>+<body$if(coverpage)$ id="cover"$endif$>+$if(titlepage)$+$for(title)$+$if(title.text)$+  <h1 class="$title.type$">$title.text$</h1>+$else$+  <h1 class="title">$title$</h1>+$endif$+$endfor$+$if(subtitle)$+  <p class="subtitle">$subtitle$</p>+$endif$+$for(author)$+  <p class="author">$author$</p>+$endfor$+$for(creator)$+  <p class="$creator.role$">$creator.text$</p>+$endfor$+$if(publisher)$+  <p class="publisher">$publisher$</p>+$endif$+$if(date)$+  <p class="date">$date$</p>+$endif$+$if(rights)$+  <div class="rights">$rights$</div>+$endif$+$else$+$for(include-before)$+$include-before$+$endfor$+$body$+$for(include-after)$+$include-after$+$endfor$+$endif$+</body>+</html>+
data/templates/default.epub3 view
@@ -5,11 +5,14 @@   <meta charset="utf-8" />   <meta name="generator" content="pandoc" />   <title>$pagetitle$</title>-$if(quotes)$   <style type="text/css">-    q { quotes: "“" "”" "‘" "’"; }-  </style>+      code{white-space: pre-wrap;}+      .smallcaps{font-variant: small-caps;}+      .line-block{white-space: pre-line;}+$if(quotes)$+      q { quotes: "“" "”" "‘" "’"; } $endif$+  </style> $if(highlighting-css)$   <style type="text/css"> $highlighting-css$
− data/templates/default.html
@@ -1,64 +0,0 @@-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">-<html xmlns="http://www.w3.org/1999/xhtml"$if(lang)$ lang="$lang$" xml:lang="$lang$"$endif$$if(dir)$ dir="$dir$"$endif$>-<head>-  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />-  <meta http-equiv="Content-Style-Type" content="text/css" />-  <meta name="generator" content="pandoc" />-$for(author-meta)$-  <meta name="author" content="$author-meta$" />-$endfor$-$if(date-meta)$-  <meta name="date" content="$date-meta$" />-$endif$-$if(keywords)$-  <meta name="keywords" content="$for(keywords)$$keywords$$sep$, $endfor$" />-$endif$-  <title>$if(title-prefix)$$title-prefix$ – $endif$$pagetitle$</title>-  <style type="text/css">code{white-space: pre;}</style>-$if(quotes)$-  <style type="text/css">q { quotes: "“" "”" "‘" "’"; }</style>-$endif$-$if(highlighting-css)$-  <style type="text/css">-$highlighting-css$-  </style>-$endif$-$for(css)$-  <link rel="stylesheet" href="$css$" type="text/css" />-$endfor$-$if(math)$-  $math$-$endif$-$for(header-includes)$-  $header-includes$-$endfor$-</head>-<body>-$for(include-before)$-$include-before$-$endfor$-$if(title)$-<div id="$idprefix$header">-<h1 class="title">$title$</h1>-$if(subtitle)$-<h1 class="subtitle">$subtitle$</h1>-$endif$-$for(author)$-<h2 class="author">$author$</h2>-$endfor$-$if(date)$-<h3 class="date">$date$</h3>-$endif$-</div>-$endif$-$if(toc)$-<div id="$idprefix$TOC">-$toc$-</div>-$endif$-$body$-$for(include-after)$-$include-after$-$endfor$-</body>-</html>
+ data/templates/default.html4 view
@@ -0,0 +1,69 @@+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">+<html xmlns="http://www.w3.org/1999/xhtml"$if(lang)$ lang="$lang$" xml:lang="$lang$"$endif$$if(dir)$ dir="$dir$"$endif$>+<head>+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />+  <meta http-equiv="Content-Style-Type" content="text/css" />+  <meta name="generator" content="pandoc" />+$for(author-meta)$+  <meta name="author" content="$author-meta$" />+$endfor$+$if(date-meta)$+  <meta name="date" content="$date-meta$" />+$endif$+$if(keywords)$+  <meta name="keywords" content="$for(keywords)$$keywords$$sep$, $endfor$" />+$endif$+  <title>$if(title-prefix)$$title-prefix$ – $endif$$pagetitle$</title>+  <style type="text/css">+      code{white-space: pre-wrap;}+      .smallcaps{font-variant: small-caps;}+      .line-block{white-space: pre-line;}+      .column{display: inline-block;}+$if(quotes)$+      q { quotes: "“" "”" "‘" "’"; }+$endif$+  </style>+$if(highlighting-css)$+  <style type="text/css">+$highlighting-css$+  </style>+$endif$+$for(css)$+  <link rel="stylesheet" href="$css$" type="text/css" />+$endfor$+$if(math)$+  $math$+$endif$+$for(header-includes)$+  $header-includes$+$endfor$+</head>+<body>+$for(include-before)$+$include-before$+$endfor$+$if(title)$+<div id="$idprefix$header">+<h1 class="title">$title$</h1>+$if(subtitle)$+<h1 class="subtitle">$subtitle$</h1>+$endif$+$for(author)$+<h2 class="author">$author$</h2>+$endfor$+$if(date)$+<h3 class="date">$date$</h3>+$endif$+</div>+$endif$+$if(toc)$+<div id="$idprefix$TOC">+$table-of-contents$+</div>+$endif$+$body$+$for(include-after)$+$include-after$+$endfor$+</body>+</html>
data/templates/default.html5 view
@@ -1,23 +1,28 @@ <!DOCTYPE html>-<html$if(lang)$ lang="$lang$"$endif$$if(dir)$ dir="$dir$"$endif$>+<html xmlns="http://www.w3.org/1999/xhtml" lang="$lang$" xml:lang="$lang$"$if(dir)$ dir="$dir$"$endif$> <head>-  <meta charset="utf-8">-  <meta name="generator" content="pandoc">-  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">+  <meta charset="utf-8" />+  <meta name="generator" content="pandoc" />+  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" /> $for(author-meta)$-  <meta name="author" content="$author-meta$">+  <meta name="author" content="$author-meta$" /> $endfor$ $if(date-meta)$-  <meta name="dcterms.date" content="$date-meta$">+  <meta name="dcterms.date" content="$date-meta$" /> $endif$ $if(keywords)$-  <meta name="keywords" content="$for(keywords)$$keywords$$sep$, $endfor$">+  <meta name="keywords" content="$for(keywords)$$keywords$$sep$, $endfor$" /> $endif$   <title>$if(title-prefix)$$title-prefix$ – $endif$$pagetitle$</title>-  <style type="text/css">code{white-space: pre;}</style>+  <style type="text/css">+      code{white-space: pre-wrap;}+      .smallcaps{font-variant: small-caps;}+      .line-block{white-space: pre-line;}+      .column{display: inline-block;} $if(quotes)$-  <style type="text/css">q { quotes: "“" "”" "‘" "’"; }</style>+      q { quotes: "“" "”" "‘" "’"; } $endif$+  </style> $if(highlighting-css)$   <style type="text/css"> $highlighting-css$@@ -56,7 +61,7 @@ $endif$ $if(toc)$ <nav id="$idprefix$TOC">-$toc$+$table-of-contents$ </nav> $endif$ $body$
+ data/templates/default.jats view
@@ -0,0 +1,203 @@+<?xml version="1.0" encoding="utf-8" ?>+$if(xml-stylesheet)$+<?xml-stylesheet type="text/xsl" href="$xml-stylesheet$"?>+$endif$+<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Publishing DTD v1.0 20120330//EN"+                  "JATS-journalpublishing1.dtd">+$if(article.type)$+<article xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:xlink="http://www.w3.org/1999/xlink" dtd-version="1.0" article-type="$article.type$">+$else$+<article xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:xlink="http://www.w3.org/1999/xlink" dtd-version="1.0" article-type="other">+$endif$+<front>+<journal-meta>+$if(journal.publisher-id)$+<journal-id journal-id-type="publisher-id">$journal.publisher-id$</journal-id>+$endif$+$if(journal.nlm-ta)$+<journal-id journal-id-type="nlm-ta">$journal.nlm-ta$</journal-id>+$endif$+$if(journal.pmc)$+<journal-id journal-id-type="pmc">$journal.pmc$</journal-id>+$endif$+<journal-title-group>+$if(journal.title)$+<journal-title>$journal.title$</journal-title>+$endif$+$if(journal.abbrev-title)$+<abbrev-journal-title>$journal.abbrev-title$</abbrev-journal-title>+$endif$+</journal-title-group>+$if(journal.pissn)$+<issn pub-type="ppub">$journal.pissn$</issn>+$endif$+$if(journal.eissn)$+<issn pub-type="epub">$journal.eissn$</issn>+$endif$+<publisher>+<publisher-name>$journal.publisher-name$</publisher-name>+$if(journal.publisher-loc)$+<publisher-loc>$journal.publisher-loc$</publisher-loc>+$endif$+</publisher>+</journal-meta>+<article-meta>+$if(article.publisher-id)$+<article-id pub-id-type="publisher-id">$article.publisher-id$</article-id>+$endif$+$if(article.doi)$+<article-id pub-id-type="doi">$article.doi$</article-id>+$endif$+$if(article.pmid)$+<article-id pub-id-type="pmid">$article.pmid$</article-id>+$endif$+$if(article.pmcid)$+<article-id pub-id-type="pmcid">$article.pmcid$</article-id>+$endif$+$if(article.art-access-id)$+<article-id pub-id-type="art-access-id">$article.art-access-id$</article-id>+$endif$+$if(article.heading)$+<article-categories>+<subj-group subj-group-type="heading">+<subject>$article.heading$</subject>+</subj-group>+$if(article.categories)$+<subj-group subj-group-type="categories">+$for(article.categories)$+<subject>$article.categories$</subject>+$endfor$+</subj-group>+$endif$+</article-categories>+$endif$+$if(title)$+<title-group>+<article-title>$title$</article-title>+</title-group>+$endif$+$if(author)$+<contrib-group>+$for(author)$+<contrib contrib-type="author">+$if(author.orcid)$+<contrib-id contrib-id-type="orcid">$author.orcid$</contrib-id>+$endif$+<name>+$if(author.surname)$+<surname>$author.surname$</surname>+<given-names>$author.given-names$</given-names>+$else$+<string-name>$author$</string-name>+$endif$+</name>+$if(author.email)$+<email>$author.email$</email>+$endif$+$if(author.aff-id)$+<xref ref-type="aff" rid="aff-$contrib.aff-id$"/>+$endif$+$if(author.cor-id)$+<xref ref-type="corresp" rid="cor-$author.cor-id$"><sup>*</sup></xref>+$endif$+</contrib>+$endfor$+</contrib-group>+$endif$+$if(article.author-notes)$+<author-notes>+$if(article.author-notes.corresp)$+$for(article.author-notes.corresp)$+<corresp id="cor-$article.author-notes.corresp.id$">* E-mail: <email>$article.author-notes.corresp.email$</email></corresp>+$endfor$+$endif$+$if(article.author-notes.conflict)$+<fn fn-type="conflict"><p>$article.author-notes.conflict$</p></fn>+$endif$+$if(article.author-notes.con)$+<fn fn-type="con"><p>$article.author-notes.con$</p></fn>+$endif$+</author-notes>+$endif$+$if(date)$+$if(date.iso-8601)$+<pub-date pub-type="epub" iso-8601-date="$date.iso-8601$">+$else$+<pub-date pub-type="epub">+$endif$+$if(date.day)$+<day>$pub-date.day$</day>+$endif$+$if(date.month)$+<month>$pub-date.month$</month>+$endif$+$if(date.year)$+<year>$pub-date.year$</year>+$else$+<string-date>$date$</string-date>+$endif$+</pub-date>+$endif$+$if(article.volume)$+<volume>$article.volume$</volume>+$endif$+$if(article.issue)$+<issue>$article.issue$</issue>+$endif$+$if(article.fpage)$+<fpage>$article.fpage$</fpage>+$endif$+$if(article.lpage)$+<lpage>$article.lpage$</lpage>+$endif$+$if(article.elocation-id)$+<elocation-id>$article.elocation-id$</elocation-id>+$endif$+$if(history)$+<history>+</history>+$endif$+$if(copyright)$+<permissions>+$if(copyright.statement)$+<copyright-statement>$copyright.statement$</copyright-statement>+$endif$+$if(copyright.year)$+<copyright-year>$copyright.year$</copyright-year>+$endif$+$if(copyright.holder)$+<copyright-holder>$copyright.holder$</copyright-holder>+$endif$+$if(copyright.text)$+<license license-type="$copyright.type$" xlink:href="$copyright.link$">+<license-p>$copyright.text$</license-p>+</license>+</permissions>+$endif$+$endif$+$if(tags)$+<kwd-group kwd-group-type="author">+$for(tags)$+<kwd>$tags$</kwd>+$endfor$+</kwd-group>+$endif$+$if(article.funding-statement)$+<funding-group>+<funding-statement>$article.funding-statement$</funding-statement>+</funding-group>+$endif$+</article-meta>+$if(notes)$+<notes>$notes$</notes>+$endif$+</front>+<body>+$body$+</body>+<back>+$if(back)$+$back$+$endif$+</back>+</article>
data/templates/default.latex view
@@ -1,4 +1,16 @@-\documentclass[$if(fontsize)$$fontsize$,$endif$$if(lang)$$babel-lang$,$endif$$if(papersize)$$papersize$paper,$endif$$for(classoption)$$classoption$$sep$,$endfor$]{$documentclass$}+\PassOptionsToPackage{unicode=true}{hyperref} % options for packages loaded elsewhere+\PassOptionsToPackage{hyphens}{url}+$if(colorlinks)$+\PassOptionsToPackage{dvipsnames,svgnames*,x11names*}{xcolor}+$endif$+%+\documentclass[$if(fontsize)$$fontsize$,$endif$$if(lang)$$babel-lang$,$endif$$if(papersize)$$papersize$paper,$endif$$if(beamer)$ignorenonframetext,$if(handout)$handout,$endif$$if(aspectratio)$aspectratio=$aspectratio$,$endif$$endif$$for(classoption)$$classoption$$sep$,$endfor$]{$documentclass$}+$if(beamer)$+\setbeamertemplate{caption}[numbered]+\setbeamertemplate{caption label separator}{: }+\setbeamercolor{caption name}{fg=normal text.fg}+\beamertemplatenavigationsymbols$if(navigation)$$navigation$$else$empty$endif$+$endif$ $if(beamerarticle)$ \usepackage{beamerarticle} % needs to be loaded first $endif$@@ -17,22 +29,21 @@ \ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex   \usepackage[$if(fontenc)$$fontenc$$else$T1$endif$]{fontenc}   \usepackage[utf8]{inputenc}-$if(euro)$-  \usepackage{eurosym}-$endif$+  \usepackage{textcomp} % provides euro and other symbols \else % if luatex or xelatex+$if(mathspec)$   \ifxetex     \usepackage{mathspec}   \else-    \usepackage{fontspec}+    \usepackage{unicode-math}   \fi+$else$+  \usepackage{unicode-math}+$endif$   \defaultfontfeatures{Ligatures=TeX,Scale=MatchLowercase} $for(fontfamilies)$   \newfontfamily{$fontfamilies.name$}[$fontfamilies.options$]{$fontfamilies.font$} $endfor$-$if(euro)$-  \newcommand{\euro}{€}-$endif$ $if(mainfont)$     \setmainfont[$for(mainfontoptions)$$mainfontoptions$$sep$,$endfor$]{$mainfont$} $endif$@@ -43,13 +54,54 @@     \setmonofont[Mapping=tex-ansi$if(monofontoptions)$,$for(monofontoptions)$$monofontoptions$$sep$,$endfor$$endif$]{$monofont$} $endif$ $if(mathfont)$+$if(mathspec)$+  \ifxetex     \setmathfont(Digits,Latin,Greek)[$for(mathfontoptions)$$mathfontoptions$$sep$,$endfor$]{$mathfont$}+  \else+    \setmathfont[$for(mathfontoptions)$$mathfontoptions$$sep$,$endfor$]{$mathfont$}+  \fi+$else$+  \setmathfont[$for(mathfontoptions)$$mathfontoptions$$sep$,$endfor$]{$mathfont$} $endif$+$endif$ $if(CJKmainfont)$+  \ifxetex     \usepackage{xeCJK}     \setCJKmainfont[$for(CJKoptions)$$CJKoptions$$sep$,$endfor$]{$CJKmainfont$}+  \fi $endif$+$if(luatexjapresetoptions)$+  \ifluatex+    \usepackage[$for(luatexjapresetoptions)$$luatexjapresetoptions$$sep$,$endfor$]{luatexja-preset}+  \fi+$endif$+$if(CJKmainfont)$+  \ifluatex+    \usepackage[$for(luatexjafontspecoptions)$$luatexjafontspecoptions$$sep$,$endfor$]{luatexja-fontspec}+    \setmainjfont[$for(CJKoptions)$$CJKoptions$$sep$,$endfor$]{$CJKmainfont$}+  \fi+$endif$ \fi+$if(beamer)$+$if(theme)$+\usetheme[$for(themeoptions)$$themeoptions$$sep$,$endfor$]{$theme$}+$endif$+$if(colortheme)$+\usecolortheme{$colortheme$}+$endif$+$if(fonttheme)$+\usefonttheme{$fonttheme$}+$endif$+$if(mainfont)$+\usefonttheme{serif} % use mainfont rather than sansfont for slide text+$endif$+$if(innertheme)$+\useinnertheme{$innertheme$}+$endif$+$if(outertheme)$+\useoutertheme{$outertheme$}+$endif$+$endif$ % use upquote if available, for straight quotes in verbatim environments \IfFileExists{upquote.sty}{\usepackage{upquote}}{} % use microtype if available@@ -57,14 +109,22 @@ \usepackage[$for(microtypeoptions)$$microtypeoptions$$sep$,$endfor$]{microtype} \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts }{}-\PassOptionsToPackage{hyphens}{url} % url is loaded by hyperref+$if(indent)$+$else$+\IfFileExists{parskip.sty}{%+\usepackage{parskip}+}{% else+\setlength{\parindent}{0pt}+\setlength{\parskip}{6pt plus 2pt minus 1pt}+}+$endif$ $if(verbatim-in-note)$ \usepackage{fancyvrb} $endif$-\usepackage[unicode=true]{hyperref} $if(colorlinks)$-\PassOptionsToPackage{usenames,dvipsnames}{color} % color is loaded by hyperref+\usepackage{xcolor} $endif$+\usepackage{hyperref} \hypersetup{ $if(title-meta)$             pdftitle={$title-meta$},@@ -91,22 +151,11 @@ $if(geometry)$ \usepackage[$for(geometry)$$geometry$$sep$,$endfor$]{geometry} $endif$-$if(lang)$-\ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex-  \usepackage[shorthands=off,$for(babel-otherlangs)$$babel-otherlangs$,$endfor$main=$babel-lang$]{babel}-$if(babel-newcommands)$-  $babel-newcommands$-$endif$-\else-  \usepackage{polyglossia}-  \setmainlanguage[$polyglossia-lang.options$]{$polyglossia-lang.name$}-$for(polyglossia-otherlangs)$-  \setotherlanguage[$polyglossia-otherlangs.options$]{$polyglossia-otherlangs.name$}-$endfor$-\fi+$if(beamer)$+\newif\ifbibliography $endif$ $if(natbib)$-\usepackage{natbib}+\usepackage[$natbiboptions$]{natbib} \bibliographystyle{$if(biblio-style)$$biblio-style$$else$plainnat$endif$} $endif$ $if(biblatex)$@@ -117,6 +166,7 @@ $endif$ $if(listings)$ \usepackage{listings}+\newcommand{\passthrough}[1]{#1} $endif$ $if(lhs)$ \lstnewenvironment{code}{\lstset{language=Haskell,basicstyle=\small\ttfamily}}{}@@ -126,9 +176,17 @@ $endif$ $if(tables)$ \usepackage{longtable,booktabs}+$if(beamer)$+\usepackage{caption}+% These lines are needed to make table captions work with longtable:+\makeatletter+\def\fnum@table{\tablename~\thetable}+\makeatother+$else$ % Fix footnotes in tables (requires footnote package)-\IfFileExists{footnote.sty}{\usepackage{footnote}\makesavenoteenv{long table}}{}+\IfFileExists{footnote.sty}{\usepackage{footnote}\makesavenoteenv{longtable}}{} $endif$+$endif$ $if(graphics)$ \usepackage{graphicx,grffile} \makeatletter@@ -140,24 +198,40 @@ % using explicit options in \includegraphics[width, height, ...]{} \setkeys{Gin}{width=\maxwidth,height=\maxheight,keepaspectratio} $endif$+$if(beamer)$+% Prevent slide breaks in the middle of a paragraph:+\widowpenalties 1 10000+\raggedbottom+$if(section-titles)$+\AtBeginPart{+  \let\insertpartnumber\relax+  \let\partname\relax+  \frame{\partpage}+}+\AtBeginSection{+  \ifbibliography+  \else+    \let\insertsectionnumber\relax+    \let\sectionname\relax+    \frame{\sectionpage}+  \fi+}+\AtBeginSubsection{+  \let\insertsubsectionnumber\relax+  \let\subsectionname\relax+  \frame{\subsectionpage}+}+$endif$+$endif$ $if(links-as-notes)$ % Make links footnotes instead of hotlinks:-\renewcommand{\href}[2]{#2\footnote{\url{#1}}}+\DeclareRobustCommand{\href}[2]{#2\footnote{\url{#1}}} $endif$ $if(strikeout)$ \usepackage[normalem]{ulem} % avoid problems with \sout in headers with hyperref: \pdfstringdefDisableCommands{\renewcommand{\sout}{}} $endif$-$if(indent)$-$else$-\IfFileExists{parskip.sty}{%-\usepackage{parskip}-}{% else-\setlength{\parindent}{0pt}-\setlength{\parskip}{6pt plus 2pt minus 1pt}-}-$endif$ \setlength{\emergencystretch}{3em}  % prevent overfull lines \providecommand{\tightlist}{%   \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}@@ -166,6 +240,8 @@ $else$ \setcounter{secnumdepth}{0} $endif$+$if(beamer)$+$else$ $if(subparagraph)$ $else$ % Redefines (sub)paragraphs to behave more like sections@@ -178,6 +254,31 @@ \renewcommand{\subparagraph}[1]{\oldsubparagraph{#1}\mbox{}} \fi $endif$+$endif$++% set default figure placement to htbp+\makeatletter+\def\fps@figure{htbp}+\makeatother++$for(header-includes)$+$header-includes$+$endfor$+$if(lang)$+\ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex+  \usepackage[shorthands=off,$for(babel-otherlangs)$$babel-otherlangs$,$endfor$main=$babel-lang$]{babel}+$if(babel-newcommands)$+  $babel-newcommands$+$endif$+\else+  % load polyglossia as late as possible as it *could* call bidi if RTL lang (e.g. Hebrew or Arabic)+  \usepackage{polyglossia}+  \setmainlanguage[$polyglossia-lang.options$]{$polyglossia-lang.name$}+$for(polyglossia-otherlangs)$+  \setotherlanguage[$polyglossia-otherlangs.options$]{$polyglossia-otherlangs.name$}+$endfor$+\fi+$endif$ $if(dir)$ \ifxetex   % load bidi as late as possible as it modifies e.g. graphicx@@ -196,15 +297,6 @@ \fi $endif$ -% set default figure placement to htbp-\makeatletter-\def\fps@figure{htbp}-\makeatother--$for(header-includes)$-$header-includes$-$endfor$- $if(title)$ \title{$title$$if(thanks)$\thanks{$thanks$}$endif$} $endif$@@ -220,9 +312,20 @@ \institute{$for(institute)$$institute$$sep$ \and $endfor$} $endif$ \date{$date$}+$if(beamer)$+$if(titlegraphic)$+\titlegraphic{\includegraphics{$titlegraphic$}}+$endif$+$if(logo)$+\logo{\includegraphics{$logo$}}+$endif$+$endif$  \begin{document} $if(title)$+$if(beamer)$+\frame{\titlepage}+$else$ \maketitle $endif$ $if(abstract)$@@ -230,20 +333,27 @@ $abstract$ \end{abstract} $endif$+$endif$  $for(include-before)$ $include-before$  $endfor$ $if(toc)$+$if(beamer)$+\begin{frame}+\tableofcontents[hideallsubsections]+\end{frame}+$else$ { $if(colorlinks)$-\hypersetup{linkcolor=$if(toccolor)$$toccolor$$else$black$endif$}+\hypersetup{linkcolor=$if(toccolor)$$toccolor$$else$$endif$} $endif$ \setcounter{tocdepth}{$toc-depth$} \tableofcontents } $endif$+$endif$ $if(lot)$ \listoftables $endif$@@ -261,12 +371,26 @@ \renewcommand\refname{$biblio-title$} $endif$ $endif$+$if(beamer)$+\begin{frame}[allowframebreaks]{$biblio-title$}+\bibliographytrue+$endif$ \bibliography{$for(bibliography)$$bibliography$$sep$,$endfor$}+$if(beamer)$+\end{frame}+$endif$  $endif$ $endif$ $if(biblatex)$+$if(beamer)$+\begin{frame}[allowframebreaks]{$biblio-title$}+\bibliographytrue+\printbibliography[heading=none]+\end{frame}+$else$ \printbibliography$if(biblio-title)$[title=$biblio-title$]$endif$+$endif$  $endif$ $for(include-after)$
data/templates/default.markdown view
@@ -11,7 +11,7 @@  $endfor$ $if(toc)$-$toc$+$table-of-contents$  $endif$ $body$
+ data/templates/default.ms view
@@ -0,0 +1,108 @@+.\" **** Custom macro definitions *********************************+.\" * Super/subscript+.\" (https://lists.gnu.org/archive/html/groff/2012-07/msg00046.html)+.ds { \v'-0.3m'\\s[\\n[.s]*9u/12u]+.ds } \s0\v'0.3m'+.ds < \v'0.3m'\s[\\n[.s]*9u/12u]+.ds > \s0\v'-0.3m'+.\" * Horizontal line+.de HLINE+.LP+.ce+\l'20'+..+$if(highlighting-macros)$+.\" * Syntax highlighting macros+$highlighting-macros$+$endif$+.\" **** Settings *************************************************+.\" text width+.nr LL 5.5i+.\" left margin+.nr PO 1.25i+.\" top margin+.nr HM 1.25i+.\" bottom margin+.nr FM 1.25i+.\" header/footer width+.nr LT \n[LL]+.\" point size+.nr PS $if(pointsize)$$pointsize$$else$10p$endif$+.\" line height+.nr VS $if(lineheight)$$lineheight$$else$12p$endif$+.\" font family: A, BM, H, HN, N, P, T, ZCM+.fam $if(fontfamily)$$fontfamily$$else$T$endif$+.\" paragraph indent+.nr PI $if(indent)$$indent$$else$2m$endif$+.\" interparagraph space+.nr PD 0.33v+.\" footnote width+.nr FL \n[LL]+.\" footnote point size+.nr FPS (\n[PS] - 2000)+.\" color used for strikeout+.defcolor strikecolor rgb 0.7 0.7 0.7+.\" color for links (rgb)+.ds PDFHREF.COLOUR   0.35 0.00 0.60+.\" border for links (default none)+.ds PDFHREF.BORDER   0 0 0+.\" point size difference between heading levels+.nr PSINCR 1p+.\" heading level above which point size no longer changes+.nr GROWPS 2+.\" comment these out if you want a dot after section numbers:+.als SN SN-NO-DOT+.als SN-STYLE SN-NO-DOT+.\" pdf outline fold level+.nr PDFOUTLINE.FOLDLEVEL 3+.\" start out in outline view+.pdfview /PageMode /UseOutlines+.\" ***************************************************************+.\" PDF metadata+.pdfinfo /Title "$title-meta$"+.pdfinfo /Author "$author-meta$"+$if(adjusting)$+.ad $adjusting$+$endif$+$if(hyphenate)$+.hy+$else$+.nh \" Turn off hyphenation by default.+$endif$+$if(has-inline-math)$+.EQ+delim @@+.EN+$endif$+$for(header-includes)$+$header-includes$+$endfor$+$if(title)$+.TL+$title$+$endif$+$for(author)$+.AU+$author$+$endfor$+$if(date)$+.ND "$date$"+$endif$+$if(abstract)$+.AB+$abstract$+.AE+$endif$+.\" 1 column (use .2C for two column)+.1C+$for(include-before)$+$include-before$+$endfor$+$body$+$if(toc)$+.TC+$endif$+$for(include-after)$+$include-after$+$endfor$+.pdfsync
+ data/templates/default.muse view
@@ -0,0 +1,44 @@+$if(author)$+#author $author$+$endif$+$if(title)$+#title $title$+$endif$+$if(lang)$+#lang $lang$+$endif$+$if(LISTtitle)$+#LISTtitle $LISTtitle$+$endif$+$if(subtitle)$+#subtitle $subtitle$+$endif$+$if(SORTauthors)$+#SORTauthors $SORTauthors$+$endif$+$if(SORTtopics)$+#SORTtopics $SORTtopics$+$endif$+$if(date)$+#date $date$+$endif$+$if(notes)$+#notes $notes$+$endif$+$if(source)$+#source $source$+$endif$++$for(header-includes)$+$header-includes$++$endfor$+$for(include-before)$+$include-before$++$endfor$+$body$+$for(include-after)$++$include-after$+$endfor$
data/templates/default.opendocument view
@@ -23,6 +23,135 @@ $for(include-before)$ $include-before$ $endfor$+$if(toc)$+<text:table-of-content>+  <text:table-of-content-source text:outline-level="10">+    <text:index-title-template text:style-name="Contents_20_Heading">+        $toc-title$+    </text:index-title-template>+    <text:table-of-content-entry-template text:outline-level="1"+    text:style-name="Contents_20_1">+      <text:index-entry-link-start text:style-name="Internet_20_link" />+      <text:index-entry-chapter />+      <text:index-entry-text />+      <text:index-entry-link-end />+      <text:index-entry-tab-stop style:type="right"+      style:leader-char="." />+      <text:index-entry-link-start text:style-name="Internet_20_link" />+      <text:index-entry-page-number />+      <text:index-entry-link-end />+    </text:table-of-content-entry-template>+    <text:table-of-content-entry-template text:outline-level="2"+    text:style-name="Contents_20_2">+      <text:index-entry-link-start text:style-name="Internet_20_link" />+      <text:index-entry-chapter />+      <text:index-entry-text />+      <text:index-entry-link-end />+      <text:index-entry-tab-stop style:type="right"+      style:leader-char="." />+      <text:index-entry-link-start text:style-name="Internet_20_link" />+      <text:index-entry-page-number />+      <text:index-entry-link-end />+    </text:table-of-content-entry-template>+    <text:table-of-content-entry-template text:outline-level="3"+    text:style-name="Contents_20_3">+      <text:index-entry-link-start text:style-name="Internet_20_link" />+      <text:index-entry-chapter />+      <text:index-entry-text />+      <text:index-entry-link-end />+      <text:index-entry-tab-stop style:type="right"+      style:leader-char="." />+      <text:index-entry-link-start text:style-name="Internet_20_link" />+      <text:index-entry-page-number />+      <text:index-entry-link-end />+    </text:table-of-content-entry-template>+    <text:table-of-content-entry-template text:outline-level="4"+    text:style-name="Contents_20_4">+      <text:index-entry-link-start text:style-name="Internet_20_link" />+      <text:index-entry-chapter />+      <text:index-entry-text />+      <text:index-entry-link-end />+      <text:index-entry-tab-stop style:type="right"+      style:leader-char="." />+      <text:index-entry-link-start text:style-name="Internet_20_link" />+      <text:index-entry-page-number />+      <text:index-entry-link-end />+    </text:table-of-content-entry-template>+    <text:table-of-content-entry-template text:outline-level="5"+    text:style-name="Contents_20_5">+      <text:index-entry-link-start text:style-name="Internet_20_link" />+      <text:index-entry-chapter />+      <text:index-entry-text />+      <text:index-entry-link-end />+      <text:index-entry-tab-stop style:type="right"+      style:leader-char="." />+      <text:index-entry-link-start text:style-name="Internet_20_link" />+      <text:index-entry-page-number />+      <text:index-entry-link-end />+    </text:table-of-content-entry-template>+    <text:table-of-content-entry-template text:outline-level="6"+    text:style-name="Contents_20_6">+      <text:index-entry-link-start text:style-name="Internet_20_link" />+      <text:index-entry-chapter />+      <text:index-entry-text />+      <text:index-entry-link-end />+      <text:index-entry-tab-stop style:type="right"+      style:leader-char="." />+      <text:index-entry-link-start text:style-name="Internet_20_link" />+      <text:index-entry-page-number />+      <text:index-entry-link-end />+    </text:table-of-content-entry-template>+    <text:table-of-content-entry-template text:outline-level="7"+    text:style-name="Contents_20_7">+      <text:index-entry-link-start text:style-name="Internet_20_link" />+      <text:index-entry-chapter />+      <text:index-entry-text />+      <text:index-entry-link-end />+      <text:index-entry-tab-stop style:type="right"+      style:leader-char="." />+      <text:index-entry-link-start text:style-name="Internet_20_link" />+      <text:index-entry-page-number />+      <text:index-entry-link-end />+    </text:table-of-content-entry-template>+    <text:table-of-content-entry-template text:outline-level="8"+    text:style-name="Contents_20_8">+      <text:index-entry-link-start text:style-name="Internet_20_link" />+      <text:index-entry-chapter />+      <text:index-entry-text />+      <text:index-entry-link-end />+      <text:index-entry-tab-stop style:type="right"+      style:leader-char="." />+      <text:index-entry-link-start text:style-name="Internet_20_link" />+      <text:index-entry-page-number />+      <text:index-entry-link-end />+    </text:table-of-content-entry-template>+    <text:table-of-content-entry-template text:outline-level="9"+    text:style-name="Contents_20_9">+      <text:index-entry-link-start text:style-name="Internet_20_link" />+      <text:index-entry-chapter />+      <text:index-entry-text />+      <text:index-entry-link-end />+      <text:index-entry-tab-stop style:type="right"+      style:leader-char="." />+      <text:index-entry-link-start text:style-name="Internet_20_link" />+      <text:index-entry-page-number />+      <text:index-entry-link-end />+    </text:table-of-content-entry-template>+    <text:table-of-content-entry-template text:outline-level="10"+    text:style-name="Contents_20_10">+      <text:index-entry-link-start text:style-name="Internet_20_link" />+      <text:index-entry-chapter />+      <text:index-entry-text />+      <text:index-entry-link-end />+      <text:index-entry-tab-stop style:type="right"+      style:leader-char="." />+      <text:index-entry-link-start text:style-name="Internet_20_link" />+      <text:index-entry-page-number />+      <text:index-entry-link-end />+    </text:table-of-content-entry-template>+  </text:table-of-content-source>+</text:table-of-content>+$endif$ $body$ $for(include-after)$ $include-after$
data/templates/default.plain view
@@ -11,7 +11,7 @@  $endfor$ $if(toc)$-$toc$+$table-of-contents$  $endif$ $body$
data/templates/default.revealjs view
@@ -17,10 +17,15 @@   <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">   <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui">   <link rel="stylesheet" href="$revealjs-url$/css/reveal.css">-  <style type="text/css">code{white-space: pre;}</style>+  <style type="text/css">+      code{white-space: pre-wrap;}+      .smallcaps{font-variant: small-caps;}+      .line-block{white-space: pre-line;}+      .column{display: inline-block;} $if(quotes)$-  <style type="text/css">q { quotes: "“" "”" "‘" "’"; }</style>+      q { quotes: "“" "”" "‘" "’"; } $endif$+  </style> $if(highlighting-css)$   <style type="text/css"> $highlighting-css$@@ -75,7 +80,7 @@ $endif$ $if(toc)$ <section id="$idprefix$TOC">-$toc$+$table-of-contents$ </section> $endif$ @@ -103,9 +108,11 @@         // Display the page number of the current slide         slideNumber: $slideNumber$, $endif$-$if(history)$         // Push each slide change to the browser history+$if(history)$         history: $history$,+$else$+        history: true, $endif$ $if(keyboard)$         // Enable keyboard shortcuts for navigation@@ -223,15 +230,24 @@ $if(maxScale)$         maxScale: $maxScale$, $endif$+$if(mathjax)$+        math: {+          mathjax: 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js',+          config: 'TeX-AMS_HTML-full',+        },+$endif$          // Optional reveal.js plugins         dependencies: [           { src: '$revealjs-url$/lib/js/classList.js', condition: function() { return !document.body.classList; } },           { src: '$revealjs-url$/plugin/zoom-js/zoom.js', async: true },-    $if(notes-server)$+$if(notes-server)$           { src: '$revealjs-url$/socket.io/socker.io.js', async: true },           { src: '$revealjs-url$/plugin/notes-server/client.js', async: true },-    $endif$+$endif$+$if(mathjax)$+          { src: '$revealjs-url$/plugin/math/math.js', async: true },+$endif$           { src: '$revealjs-url$/plugin/notes/notes.js', async: true }         ]       });
data/templates/default.rtf view
@@ -18,7 +18,7 @@ {\pard \ql \f0 \sa180 \li0 \fi0 \par} $endif$ $if(toc)$-$toc$+$table-of-contents$ $endif$ $for(include-before)$ $include-before$
data/templates/default.s5 view
@@ -15,13 +15,18 @@   <meta name="keywords" content="$for(keywords)$$keywords$$sep$, $endfor$" /> $endif$   <title>$if(title-prefix)$$title-prefix$ – $endif$$pagetitle$</title>-  <style type="text/css">code{white-space: pre;}</style>+  <style type="text/css">+      code{white-space: pre-wrap;}+      .smallcaps{font-variant: small-caps;}+      .line-block{white-space: pre-line;}+      .column{display: inline-block;}+$if(quotes)$+      q { quotes: "“" "”" "‘" "’"; }+$endif$+  </style>   <!-- configuration parameters -->   <meta name="defaultView" content="slideshow" />   <meta name="controlVis" content="hidden" />-$if(quotes)$-  <style type="text/css">q { quotes: "“" "”" "‘" "’"; }</style>-$endif$ $if(highlighting-css)$   <style type="text/css"> $highlighting-css$@@ -74,7 +79,7 @@ $endif$ $if(toc)$ <div class="slide" id="$idprefix$TOC">-$toc$+$table-of-contents$ </div> $endif$ $body$
data/templates/default.slideous view
@@ -16,10 +16,15 @@   <meta name="keywords" content="$for(keywords)$$keywords$$sep$, $endfor$" /> $endif$   <title>$if(title-prefix)$$title-prefix$ – $endif$$pagetitle$</title>-  <style type="text/css">code{white-space: pre;}</style>+  <style type="text/css">+      code{white-space: pre-wrap;}+      .smallcaps{font-variant: small-caps;}+      .line-block{white-space: pre-line;}+      .column{display: inline-block;} $if(quotes)$-  <style type="text/css">q { quotes: "“" "”" "‘" "’"; }</style>+      q { quotes: "“" "”" "‘" "’"; } $endif$+  </style> $if(highlighting-css)$   <style type="text/css"> $highlighting-css$@@ -79,7 +84,7 @@ $endif$ $if(toc)$ <div class="slide" id="$idprefix$TOC">-$toc$+$table-of-contents$ </div> $endif$ $body$
data/templates/default.slidy view
@@ -16,10 +16,15 @@   <meta name="keywords" content="$for(keywords)$$keywords$$sep$, $endfor$" /> $endif$   <title>$if(title-prefix)$$title-prefix$ – $endif$$pagetitle$</title>-  <style type="text/css">code{white-space: pre;}</style>+  <style type="text/css">+      code{white-space: pre-wrap;}+      .smallcaps{font-variant: small-caps;}+      .line-block{white-space: pre-line;}+      .column{display: inline-block;} $if(quotes)$-  <style type="text/css">q { quotes: "“" "”" "‘" "’"; }</style>+      q { quotes: "“" "”" "‘" "’"; } $endif$+  </style> $if(highlighting-css)$   <style type="text/css"> $highlighting-css$@@ -65,7 +70,7 @@ $endif$ $if(toc)$ <div class="slide" id="$idprefix$TOC">-$toc$+$table-of-contents$ </div> $endif$ $body$
+ data/translations/am.yaml view
@@ -0,0 +1,20 @@+Abstract: አኅጽተሮ ጽሁፍ+Appendix: መድበል+Bibliography: ቢዋ መጽሃፍት+Cc: ግልባጭ+Chapter: ክፍል+Contents: ይዘት+Encl: አባሪዎች+Figure: ሥዕል+Index: ምህጻር ቃል+ListOfFigures: የሥዕችሎ ማውጫ+ListOfTables: የሰንጠዥረ ማውጫ+Page: ገጽ+Part: ንዑስ ክፍል+Preface: መቅድም+Proof: ማረጋገጫ+References: የነሥ ጹሁፍ ምንጭ+See: ይመልከቱ+SeeAlso: ይህምን ይመልከቱ+Table: ሰንጠረዥ+To: ለ
+ data/translations/ar.yaml view
@@ -0,0 +1,20 @@+Preface: ﻡﺪﺨﻟ+References: ﺎﻠﻣﺭﺎﺠﻋ+Abstract: ﻢﻠﺨﺻ+Bibliography: ﺎﻠﻤﺻﺍﺩﺭ+Chapter: ﺏﺎﺑ+Appendix: ﺎﻠﻣﻼﺤﻗ+Contents: ﺎﻠﻤﺤﺗﻮﻳﺎﺗ+ListOfFigures: ﻕﺎﺌﻣﺓ ﺍﻸﺸﻛﺎﻟ+ListOfTables: ﻕﺎﺌﻣﺓ ﺎﻠﺟﺩﺍﻮﻟ+Index: ﺎﻠﻔﻫﺮﺳ+Figure: ﺶﻜﻟ+Table: ﺝﺩﻮﻟ+Part: ﺎﻠﻘﺴﻣ+Encl: ﺎﻠﻣﺮﻔﻗﺎﺗ+To: ﺈﻟﻯ+Page: ﺺﻔﺣﺓ+See: ﺭﺎﺠﻋ+SeeAlso: ﺭﺎﺠﻋ ﺄﻴﺿًﺍ+Proof: ﺏﺮﻫﺎﻧ+Glossary: ﻕﺎﻣﻮﺳ
+ data/translations/bg.yaml view
@@ -0,0 +1,19 @@+Abstract: Абстракт+Appendix: Приложение+Bibliography: Библиография+Cc: копия+Chapter: Глава+Contents: Съдържание+Encl: Приложения+Figure: Фигура+Glossary: Glossary+Index: Азбучен указател+ListOfFigures: Списък на фигурите+ListOfTables: Списък на таблиците+Page: Стр.+Preface: Предговор+Proof: Proof+References: Литература+See: вж.+SeeAlso: вж. също и+Table: Таблица
+ data/translations/bn.yaml view
@@ -0,0 +1,21 @@+Abstract: সারসংক্ষেপ+Appendix: পরিশিষ্ট+Bibliography: তথ্যবিবরণ+Cc: অনুলিপি+Chapter: অধ্যায়+Contents: সূচীপত্র+Encl: সংযুক্তি+Figure: ছবি/নকশা+Glossary: পরিভাষার শব্দসম্ভার+Index: সূচক/নির্দেশক+ListOfFigures: ছবি/নকশা সমূহের তালিকা+ListOfTables: তালিকাসারণী+Page: পৃষ্ঠা+Part: খন্ড+Preface: পূর্বকথা+Proof: প্রমাণ+References: তথ্যসুত্রসমূহ+See: দেখুন+SeeAlso: আরও দেখুন+Table: সারনী+To: প্রতি
+ data/translations/ca.yaml view
@@ -0,0 +1,21 @@+Abstract: Resum+Appendix: Apèndix+Bibliography: Bibliografia+Cc: Còpies a+Chapter: Capítol+Contents: Índex+Encl: Adjunt+Figure: Figura+Glossary: Glossari+Index: Índex alfabètic+ListOfFigures: Índex de figures+ListOfTables: Índex de taules+Page: Pàgina+Part: Part+Preface: Pròleg+Proof: Demostració+References: Referències+See: Vegeu+SeeAlso: Vegeu també+Table: Taula+To: A
+ data/translations/cs.yaml view
@@ -0,0 +1,21 @@+Abstract: Abstrakt+Appendix: Dodatek+Bibliography: Literatura+Cc: Na vědomí:+Chapter: Kapitola+Contents: Obsah+Encl: Příloha+Figure: Obrázek+Glossary: Slovník+Index: Index+ListOfFigures: Seznam obrázků+ListOfTables: Seznam tabulek+Page: Strana+Part: Část+Preface: Předmluva+Proof: Důkaz+References: Reference+See: viz+SeeAlso: viz+Table: Tabulka+To: Komu
+ data/translations/da.yaml view
@@ -0,0 +1,21 @@+Abstract: Resumé+Appendix: Bilag+Bibliography: Litteratur+Cc: Kopi til}+Chapter: Kapitel+Contents: Indhold+Encl: Vedlagt+Figure: Figur+Glossary: Gloseliste+Index: Indeks+ListOfFigures: Figurer+ListOfTables: Tabeller+Page: Side+Part: Del+Preface: Forord+Proof: Bevis+References: Litteratur+See: Se+SeeAlso: Se også+Table: Tabel+To: Til}
+ data/translations/de.yaml view
@@ -0,0 +1,21 @@+Abstract: Zusammenfassung+Appendix: Anhang+Bibliography: Literaturverzeichnis+Cc: Verteiler+Chapter: Kapitel+Contents: Inhaltsverzeichnis+Encl: Anlage(n)+Figure: Abbildung+Glossary: Glossar+Index: Index+ListOfFigures: Abbildungsverzeichnis+ListOfTables: Tabellenverzeichnis+Page: Seite+Part: Teil+Preface: Vorwort+Proof: Beweis+References: Literatur+See: siehe+SeeAlso: siehe auch+Table: Tabelle+To: An
+ data/translations/el.yaml view
@@ -0,0 +1,21 @@+Abstract: Περίληψη+Appendix: Παράρτημα+Bibliography: Βιβλιογραφία+Cc: Κοινοποίηση+Chapter: Κεφάλαιο+Contents: Περιεχόμενα+Encl: Συνημμένα+Figure: Σχήμα+Glossary: Γλωσσάρι+Index: Ευρετήριο+ListOfFigures: Κατάλογος σχημάτων+ListOfTables: Κατάλογος πινάκων+Page: Σελίδα+Part: Μέρος+Preface: Πρόλογος+Proof: Απόδειξη+References: Αναφορές+See: βλέπε+SeeAlso: βλέπε επίσης+Table: Πίνακας+To: Προς
+ data/translations/en.yaml view
@@ -0,0 +1,22 @@+Abstract: Abstract+Appendix: Appendix+Bibliography: Bibliography+Cc: cc+Chapter: Chapter+Contents: Contents+Encl: encl+Figure: Figure+Glossary: Glossary+Index: Index+ListOfFigures: ListOfFigures+ListOfTables: ListOfTables+Page: page+Part: Part+Preface: Preface+Proof: Proof+References: References+See: see+SeeAlso: see also+Table: Table+To: To+Listing: Listing
+ data/translations/eo.yaml view
@@ -0,0 +1,20 @@+Abstract: Resumo+Appendix: Apendico+Bibliography: Bibliografio+Cc: Kopie al+Chapter: Ĉapitro+Contents: Enhavo+Encl: Aldono(j)+Figure: Figuro+Glossary: Glosaro+Index: Indekso+ListOfFigures: Listo de figuroj+ListOfTables: Listo de tabeloj+Page: Paĝo+Preface: Antaŭparolo+Proof: Pruvo+References: Citaĵoj+See: vidu+SeeAlso: Parto+Table: Tabelo+To: Al
+ data/translations/es.yaml view
@@ -0,0 +1,21 @@+Abstract: Resumen+Appendix: Apéndice+Bibliography: Bibliografía+Cc: Copia a+Chapter: Capítulo+Contents: Índice general+Encl: Adjunto(s)+Figure: Figura+Glossary: Glosario+Index: Índice alfabético+ListOfFigures: Índice de figuras+ListOfTables: Índice de cuadros+Page: Página+Part: Parte+Preface: Prefacio+Proof: Prueba+References: Referencias+See: véase+SeeAlso: véase también+Table: Cuadro+To: A
+ data/translations/et.yaml view
@@ -0,0 +1,20 @@+Abstract: Kokkuvõte+Appendix: Lisa+Bibliography: Kirjandus+Cc: Koopia(d)+Chapter: Peatükk+Contents: Sisukord+Encl: Lisa(d)+Figure: Joonis+Glossary: Glossary+Index: Indeks+ListOfFigures: Joonised+ListOfTables: Tabelid+Page: Lk.+Part: Osa+Preface: Sissejuhatus+Proof: Korrektuur+References: Viited+See: vt.+SeeAlso: vt. ka+Table: Tabel
+ data/translations/eu.yaml view
@@ -0,0 +1,21 @@+Abstract: Laburpena+Appendix: Eranskina+Bibliography: Bibliografia+Cc: Kopia+Chapter: Kapitulua+Contents: Gaien Aurkibidea+Encl: Erantsia+Figure: Irudia+Glossary: Glosarioa+Index: Kontzeptuen Aurkibidea+ListOfFigures: Irudien Zerrenda+ListOfTables: Taulen Zerrenda+Page: Orria+Part: Atala+Preface: Hitzaurrea+Proof: Frogapena+References: Erreferentziak+See: Ikusi+SeeAlso: Ikusi, halaber+Table: Taula+To: Nori
+ data/translations/fa.yaml view
@@ -0,0 +1,21 @@+Abstract: چکیﺪﻫ+Appendix: پیﻮﺴﺗ+Bibliography: کﺕﺎﺑc>ﻧﺎﻤﻫ+Cc: ﺭﻮﻧﻮﺸﺗ+Chapter: ﻒﺼﻟ+Contents: ﻒﻫﺮﺴﺗ ﻢﻃﺎﻠﺑ+Encl: پیﻮﺴﺗ+Figure: ﺶﻜﻟ+Glossary: ﺩﺎﻨﺷc>ﻧﺎﻤﻫ+Index: ﻦﻣﺍیﻩ+ListOfFigures: ﻝیﺲﺗ ﺖﺻﺍﻭیﺭ+ListOfTables: ﻝیﺲﺗ ﺝﺩﺍﻮﻟ+Page: ﺺﻔﺣﺓ+Part: ﺐﺨﺷ+Preface: پیﺵگﻒﺗﺍﺭ+Proof: ﺏﺮﻫﺎﻧ+References: ﻡﺭﺎﺠﻋ+See: ﺐﺑیﻥیﺩ+SeeAlso: ﻥیﺯ ﺐﺑیﻥیﺩ+Table: ﺝﺩﻮﻟ+To: ﺐﻫ
+ data/translations/fi.yaml view
@@ -0,0 +1,21 @@+Abstract: Tiivistelmä+Appendix: Liite+Bibliography: Kirjallisuutta+Cc: Jakelu+Chapter: Luku+Contents: Sisältö+Encl: Liitteet+Figure: Kuva+Glossary: Sanasto+Index: Hakemisto+ListOfFigures: Kuvat+ListOfTables: Taulukot+Page: Sivu+Part: Osa+Preface: Esipuhe+Proof: Todistus+References: Viitteet+See: katso+SeeAlso: katso myös+Table: Taulukko+To: Vastaanottaja
+ data/translations/fr.yaml view
@@ -0,0 +1,20 @@+Abstract: Résumé+Appendix: Annexe+Bibliography: Bibliographie+Cc: Copie à+Chapter: Chaptire+Contents: Table des matières+Figure: Fig.+Glossary:+Index: Index+ListOfFigures: Table des figures+ListOfTables: Liste des tableaux+Page: page+Part: partie+Preface: Préface+Proof: Démonstration+References: Références+See: voir+SeeAlso: voir aussi+Table: Tab.+To:
+ data/translations/he.yaml view
@@ -0,0 +1,22 @@+Abstract: תקציר+Appendix: נספח+Bibliography: ביבליוגרפיה+Cc: העתקים+Chapter: פרק+Contents: תוכן העניינים+Encl: רצ"ב+Figure: איור+Glossary: מילון מונחים}+Index: מפתח+ListOfFigures: רשימת האיורים+ListOfTables: רשימת הטבלאות+Page: עמוד+Part: חלק+Preface: מבוא+Proof: הוכחה}+Ps: נ.ב.+References: מקורות+See: ראה+SeeAlso: ראה גם}+Table: טבלה+To: אל
+ data/translations/hi.yaml view
@@ -0,0 +1,20 @@+Abstract: सारांश+Appendix: परिशिष्ट+Bibliography: संदर ग्रन्थ}+Cc: +Chapter: अध्याय+Contents: विषय सूची+Encl: +Figure: चित्र}+Headpage: पृषठ+Index: सूची+ListOfFigures: चित्रों की सूची+ListOfTables: तालिकाओं की सूची+Page: पृषठ+Part: खणड+Preface: प्रस्तावना}+References: हवाले+See: देखिए+SeeAlso: और देखिए+Table: तालिका+To: 
+ data/translations/hr.yaml view
@@ -0,0 +1,21 @@+Abstract: Sažetak+Appendix: Dodatak+Bibliography: Bibliografija+Cc: Kopija+Chapter: Poglavlje+Contents: Sadržaj+Encl: Prilozi+Figure: Slika+Glossary: Pojmovnik+Index: Kazalo+ListOfFigures: Popis slika+ListOfTables: Popis tablica+Page: Stranica+Part: Dio+Preface: Predgovor+Proof: Dokaz+References: Literatura+See: Vidjeti+SeeAlso: Također vidjeti+Table: Tablica+To: Prima
+ data/translations/hu.yaml view
@@ -0,0 +1,21 @@+Abstract: Kivonat+Appendix: Függelék+Bibliography: Irodalomjegyzék+Cc: Körlevél–címzettek+Chapter: fejezet+Contents: Tartalomjegyzék+Encl: Melléklet+Figure: ábra+Glossary: Szójegyzék+Index: Tárgymutató+ListOfFigures: Ábrák jegyzéke+ListOfTables: Táblázatok jegyzéke+Page: oldal+Part: rész+Preface: Előszó+Proof: Bizonyítás+References: Hivatkozások+See: lásd+SeeAlso: lásd még+Table: táblázat+To: Címzett
+ data/translations/is.yaml view
@@ -0,0 +1,21 @@+Abstract: Útdráttur+Appendix: Viðauki+Bibliography: Heimildir+Cc: Samrit+Chapter: Kafli+Contents: Efnisyfirlit+Encl: Hjálagt+Figure: Mynd+Glossary: Orðalisti+Index: Atriðisorðaskrá+ListOfFigures: Myndaskrá+ListOfTables: Töfluskrá+Page: Blaðsíða+Part: Hluti+Preface: Formáli+Proof: Sönnun+References: Heimildir+See: Sjá+SeeAlso: Sjá einnig+Table: Tafla+To: Til:
+ data/translations/it.yaml view
@@ -0,0 +1,21 @@+Abstract: Sommario+Appendix: Appendice+Bibliography: Bibliografia+Cc: e p. c.+Chapter: Capitolo+Contents: Indice+Encl: Allegati+Figure: Figura+Glossary: Glossario+Index: Indice analitico+ListOfFigures: Elenco delle figure+ListOfTables: Elenco delle tabelle+Page: Pag.+Part: Parte+Preface: Prefazione+Proof: Dimostrazione+References: Riferimenti bibliografici+See: vedi+SeeAlso: vedi anche+Table: Tabella+To: Per
+ data/translations/km.yaml view
@@ -0,0 +1,21 @@+Abstract: សង្ខេប+Appendix: សេចក្ដីបន្ថែម+Bibliography: គន្ថនិទ្ទេស+Cc: ចម្លងជួន+Chapter: ជំពូក+Contents: មាតិការ+Encl: ឯកសារភ្ជាប់+Figure: រូប+Glossary: សទានុក្រម+Index: សន្ទស្សន៍+ListOfFigures: បញ្ជីរូបភាព+ListOfTables: បញ្ជីតារាង+Page: ទំព័រ+Part: ផ្នែក+Preface: អារម្ភកថា+Proof: សម្រាយ+References: ឯកសារយោង+See: មើល+SeeAlso: មើលបន្ថែម+Table: តារាង+To: ផ្ញើរទៅ
+ data/translations/ko.yaml view
@@ -0,0 +1,17 @@+Abstract: 요약+Appendix: 부록+Bibliography: 참고문헌+Cc: 사본+Chapter: 장+Contents: 차례+Encl: 동봉+Figure: 그림+Index: 찾아보기+ListOfFigures: 그림 차례+ListOfTables: 표 차례+Page: 페이지+Preface: 서문+Proof: 증명+References: 참고문헌+Table: 표+To: 수신:
+ data/translations/lo.yaml view
@@ -0,0 +1,21 @@+Abstract: ບົດຫຍໍ້ຄວາມ+Appendix: ພາກຄັດຕິດ+Bibliography: ເອກະສານອ້າງອີງ+Cc: ສໍາເນົາເຖິງ+Chapter: ບົດທີ+Contents: ສາລະບານ+Encl: ເອກະສານປະກອບ+Figure: ຮູບທີ+Glossary: ປະມວນສັບ+Index: ດັດຊະນີ+ListOfFigures: ສາລະບານຮູບ+ListOfTables: ສາລະບານຕາຕະລາງ+Page: ໜ້າ+Part: ພາກ+Preface: ຄໍານໍາ+Proof: ຂໍ້ພິສູດ+References: ໜັງສືອ້າງອີງ+See: ອ່ານ+SeeAlso: ອ່ານເພີ່ມ+Table: ຕາຕະລາງທີ+To: ຮຽນ
+ data/translations/lt.yaml view
@@ -0,0 +1,21 @@+Abstract: Santrauka+Appendix: Priedas+Bibliography: Literatūra+Cc: Kopijos+Chapter: Skyrius+Contents: Turinys+Encl: Įdėta+Figure: pav.+Glossary: Terminų žodynas+Index: Rodyklė+ListOfFigures: Iliustracijų sąrašas+ListOfTables: Lentelių sąrašas+Page: puslapis+Part: Dalis+Preface: Pratarmė+Proof: Įrodymas+References: Literatūra+See: žiūrėk+SeeAlso: taip pat+Table: lentelė+To: Kam
+ data/translations/lv.yaml view
@@ -0,0 +1,20 @@+Abstract: Anotācija+Appendix: Pielikums+Bibliography: Literatūra+Cc: cc+Chapter: Nodaļa+Contents: Saturs+Encl: encl+Figure: Att.+Index: Index+ListOfFigures: Attēlu saraksts+ListOfTables: Tabulu saraksts+Page: lpp.+Part: Daļa+Preface: Priekšvārds+Proof: Pierādījums+References: Literatūras saraksts+See: sk.+SeeAlso: sk. arī+Table: Tabula+To: To
+ data/translations/nl.yaml view
@@ -0,0 +1,21 @@+Abstract: Samenvatting+Appendix: Bijlage+Bibliography: Bibliografie+Cc: cc+Chapter: Hoofdstuk+Contents: Inhoudsopgave+Encl: Bijlage(n)+Figure: Figuur+Glossary: Verklarende woordenlijst+Index: Index+ListOfFigures: Lijst van figuren+ListOfTables: Lijst van tabellen+Page: Pagina+Part: Deel+Preface: Voorwoord+Proof: Bewijs+References: Referenties+See: zie+SeeAlso: zie ook+Table: Tabel+To: Aan
+ data/translations/no.yaml view
@@ -0,0 +1,21 @@+Abstract: Sammendrag+Appendix: Tillegg+Bibliography: Bibliografi+Cc: Kopi sendt+Chapter: Kapittel+Contents: Innhold+Encl: Vedlegg+Figure: Figur+Glossary: Ordliste+Index: Register+ListOfFigures: Figurer+ListOfTables: Tabeller+Page: Side+Part: Del+Preface: Forord+Proof: Bevis+References: Referanser+See: Se+SeeAlso: Se også+Table: Tabell+To: Til
+ data/translations/pl.yaml view
@@ -0,0 +1,21 @@+Abstract: Streszczenie+Appendix: Dodatek+Bibliography: Bibliografia+Cc: Kopie:+Chapter: Rozdział+Contents: Spis treści+Encl: Załącznik+Figure: Rysunek+Glossary: Glossary+Index: Indeks+ListOfFigures: Spis rysunków+ListOfTables: Spis tabel+Page: Strona+Part: Część+Preface: Przedmowa+Proof: Dowód+References: Literatura+See: Zobacz+SeeAlso: Zobacz też+Table: Tabela+To: Do
+ data/translations/pt.yaml view
@@ -0,0 +1,21 @@+Abstract: Resumo+Appendix: Apêndice+Bibliography: Bibliografia+Cc: Com cópia a+Chapter: Capítulo+Contents: Conteúdo+Encl: Anexo+Figure: Figura+Glossary: Glossário+Index: Índice+ListOfFigures: Lista de Figuras+ListOfTables: Lista de Tabelas+Page: Página+Part: Parte+Preface: Prefácio+Proof: Demonstração+References: Referências+See: ver+SeeAlso: ver também+Table: Tabela+To: Para
+ data/translations/rm.yaml view
@@ -0,0 +1,21 @@+Abstract: Recapitulaziun+Appendix: Appendix+Bibliography: Index bibliografic+Cc: Copia a+Chapter: Chapitel+Contents: Tavla dal cuntegn+Encl: Agiunta(s)+Figure: Figura+Glossary: Glossari+Index: Register da materias+ListOfFigures: Tavla da las figuras+ListOfTables: Tavla da las tabellas+Page: pagina+Part: Part+Preface: Prefaziun+Proof: Demonstraziun+References: Bibliografia+See: vesair+SeeAlso: vesair era+Table: Tabella+To: A
+ data/translations/ro.yaml view
@@ -0,0 +1,21 @@+Abstract: Rezumat+Appendix: Anexa+Bibliography: Bibliografie+Cc: Copie+Chapter: Capitolul+Contents: Cuprins+Encl: Anexă+Figure: Figura+Glossary: Glosar+Index: Glosar+ListOfFigures: Listă de figuri+ListOfTables: Listă de tabele+Page: Pagina+Part: Partea+Preface: Prefață+Proof: Demonstrație+References: Bibliografie+See: Vezi+SeeAlso: Vezi de asemenea+Table: Tabela+To: Pentru
+ data/translations/ru.yaml view
@@ -0,0 +1,21 @@+Abstract: Аннотація+Appendix: Приложеніе+Author: Именной указатель+Bibliography: Библіографія+Cc: исх.+Chapter: Глава+Contents: Оглавленіе+Encl: вкл.+Figure: Рис.+Index: Предмѣтный указатель+ListOfFigures: Списокъ иллюстрацій+ListOfTables: Списокъ таблицъ+Page: с.+Part: Часть+Preface: Предисловіе+Proof: Доказательство+References: Примѣчанія+See: см.+SeeAlso: см. также+Table: Таблица+To: вх.
+ data/translations/sk.yaml view
@@ -0,0 +1,21 @@+Abstract: Abstrakt+Appendix: Dodatok+Bibliography: Literatúra+Cc: cc.+Chapter: Kapitola+Contents: Obsah+Encl: Prílohy+Figure: Obrázok+Glossary: Slovník+Index: Index+ListOfFigures: Zoznam obrázkov+ListOfTables: Zoznam tabuliek+Page: Strana+Part: Časť+Preface: Úvod+Proof: Dôkaz+References: Referencie+See: viď+SeeAlso: viď tiež+Table: Tabuľka+To: Pre
+ data/translations/sl.yaml view
@@ -0,0 +1,21 @@+Abstract: Povzetek+Appendix: Dodatek+Bibliography: Literatura+Cc: Kopije+Chapter: Poglavje+Contents: Kazalo+Encl: Priloge+Figure: Slika+Glossary: Slovar+Index: Stvarno kazalo+ListOfFigures: Slike+ListOfTables: Tabele+Page: Stran+Part: Del+Preface: Predgovor+Proof: Dokaz+References: Literatura+See: glej+SeeAlso: glej tudi+Table: Tabela+To: Prejme
+ data/translations/sq.yaml view
@@ -0,0 +1,18 @@+Abstract: Përmbledhja+Appendix: Shtesa+Bibliography: Bibliografia+Chapter: Kapitulli+Contents: Përmbajta+Figure: Figura+Glossary: Përhasja e Fjalëve+Index: Indeksi+ListOfFigures: Figurat+ListOfTables: Tabelat+Page: Faqe+Part: Pjesa+Preface: Parathenia+Proof: Vërtetim+References: Referencat+See: shiko+SeeAlso: shiko dhe+Table: Tabela
+ data/translations/sr-cyrl.yaml view
@@ -0,0 +1,21 @@+Abstract: Сажетак+Appendix: Додатак+Bibliography: Литература+Cc: Копије+Chapter: Глава+Contents: Садржај+Encl: Прилози+Figure: Слика+Glossary: Речник непознатих речи+Index: Регистар+ListOfFigures: Списак слика+ListOfTables: Списак табела+Page: Страна+Part: Део+Preface: Предговор+Proof: Доказ+References: Библиографија+See: Види+SeeAlso: Види такође+Table: Табела+To: Прима
+ data/translations/sr.yaml view
@@ -0,0 +1,21 @@+Abstract: Sažetak+Appendix: Dodatak+Bibliography: Literatura+Cc: Kopije+Chapter: Glava+Contents: Sadržaj+Encl: Prilozi+Figure: Slika+Glossary: Rečnik nepoznatih reči+Index: Registar+ListOfFigures: Spisak slika+ListOfTables: Spisak tabela+Page: Strana+Part: Deo+Preface: Predgovor+Proof: Dokaz+References: Bibliografija+See: Vidi+SeeAlso: Vidi takođe+Table: Tabela+To: Prima
+ data/translations/sv.yaml view
@@ -0,0 +1,21 @@+Abstract: Sammanfattning+Appendix: Bilaga+Bibliography: Litteraturförteckning+Cc: Kopia för kännedom+Chapter: Kapitel+Contents: Innehåll+Encl: Bil.+Figure: Figur+Glossary: Ordlista+Index: Sakregister+ListOfFigures: Figurer+ListOfTables: Tabeller+Page: Sida+Part: Del+Preface: Förord+Proof: Bevis+References: Referenser+See: se+SeeAlso: se även+Table: Tabell+To: Till
+ data/translations/th.yaml view
@@ -0,0 +1,20 @@+Abstract: บทคัดย่อ+Appendix: ภาคผนวก+Bibliography: บรรณานุกรม+Cc: สำเนาถึง+Chapter: บทที่+Contents: สารบัญ+Encl: สิ่งที่แนบมาด้วย+Figure: รูปที่+Index: ดรรชนี+ListOfFigures: สารบัญรูป+ListOfTables: สารบัญตาราง+Page: หน้า+Part: ภาค+Preface: คำนำ+Proof: พิสูจน์+References: หนังสืออ้างอิง+See: ดู+SeeAlso: ดูเพิ่มเติม+Table: ตารางที่+To: เรียน
+ data/translations/tr.yaml view
@@ -0,0 +1,22 @@+Abstract: Özet+Appendix: Ek+Bibliography: Kaynakça+Cc: Diğer Alıcılar+Chapter: Bölüm+Contents: İçindekiler+Encl: İlişik+Figure: Şekil+Glossary: Lügatçe+Index: Dizin+ListOfFigures: Şekil Listesi+ListOfTables: Tablo Listesi+Page: Sayfa+Part: Kısım+Preface: Önsöz+Proof: Kanıt+References: Kaynaklar+See: bkz.+SeeAlso: ayrıca bkz.+Subject: İlgili+Table: Tablo+To: Alıcı
+ data/translations/uk.yaml view
@@ -0,0 +1,22 @@+Abstract: Анотація+Appendix: Додаток+Author: Іменний покажчик}% babel has "Їменний покажчик"+Bibliography: Бібліоґрафія+Cc: копія+Chapter: Розділ+Contents: Зміст+Encl: вкладка+Figure: Рис.+Glossary: Словник термінів+Index: Покажчик+ListOfFigures: Перелік ілюстрацій+ListOfTables: Перелік таблиць+Page: с.+Part: Частина+Preface: Вступ+Proof: Доведення+References: Література+See: див.+SeeAlso: див. також+Table: Табл.+To: До
+ data/translations/ur.yaml view
@@ -0,0 +1,22 @@+Abstract: ﻢﻠﺨّﺻ+Appendix: ﺾﻣیﻡہ+Bibliography: کﺕﺎﺑیﺎﺗ+Cc: ﻦﻘﻟ+Chapter: ﺏﺎﺑ+Contents: ﻑہﺮﺴﺗ ﻊﻧﻭﺎﻧﺎﺗ+Encl: ﻢﻨﺴﻟک+Figure: ﺶﻜﻟ+Glossary: ﻞﻐﺗ+Index: ﺎﺷﺍﺭیہ+ListOfFigures: ﻑہﺮﺴﺗ ﺎﺷکﺎﻟ+ListOfTables: ﻑہﺮﺴﺗ ﺝﺩﺍﻮﻟ+Page: ﺺﻔﺣہ+Part: ﺢﺻّہ+Preface: ﺩیﺏﺍچہ+Proof: ﺚﺑﻮﺗ+References: ﺡﻭﺎﻟہ ﺝﺎﺗ+Section: ﻒﺼﻟ+See: ﻡﻼﺤﻇہ ہﻭ+SeeAlso: ﺍیﺽﺍً+Table: ﺝﺩﻮﻟ+To: ﺐﻣﻼﺤﻇہ
+ data/translations/vi.yaml view
@@ -0,0 +1,21 @@+Abstract: Tóm tắt nội dung+Also: Xem thêm+Appendix: Phụ lục+Bib: Tài liệu tham khảo+Cc: Cùng gửi+Chapter: Chương+Contents: Mục lục+Encl: Kèm theo+Figure: Hình+Glossary: Từ điển chú giải+Headto: Gửi+Index: Chỉ mục+Listfigure: Danh sách hình vẽ+Listtable: Danh sách bẳng+Page: Trang+Part: Phần+Preface: Lời nói đầu+Proof: Chứng minh+References: Tài liệu+See: Xem+Table: Bẳng
man/pandoc.1 view
@@ -1,5 +1,5 @@ .\"t-.TH PANDOC 1 "January 29, 2017" "pandoc 1.19.2.4"+.TH PANDOC 1 "October 27, 2017" "pandoc 2.0" .SH NAME pandoc - general markup converter .SH SYNOPSIS@@ -11,17 +11,19 @@ another, and a command\-line tool that uses this library. It can read Markdown, CommonMark, PHP Markdown Extra, GitHub\-Flavored Markdown, MultiMarkdown, and (subsets of) Textile, reStructuredText,-HTML, LaTeX, MediaWiki markup, TWiki markup, Haddock markup, OPML, Emacs-Org mode, DocBook, txt2tags, EPUB, ODT and Word docx; and it can write-plain text, Markdown, CommonMark, PHP Markdown Extra, GitHub\-Flavored-Markdown, MultiMarkdown, reStructuredText, XHTML, HTML5, LaTeX-(including \f[C]beamer\f[] slide shows), ConTeXt, RTF, OPML, DocBook,-OpenDocument, ODT, Word docx, GNU Texinfo, MediaWiki markup, DokuWiki-markup, ZimWiki markup, Haddock markup, EPUB (v2 or v3), FictionBook2,-Textile, groff man pages, Emacs Org mode, AsciiDoc, InDesign ICML, TEI-Simple, and Slidy, Slideous, DZSlides, reveal.js or S5 HTML slide shows.-It can also produce PDF output on systems where LaTeX, ConTeXt, or-\f[C]wkhtmltopdf\f[] is installed.+HTML, LaTeX, MediaWiki markup, TWiki markup, TikiWiki markup, Creole+1.0, Haddock markup, OPML, Emacs Org mode, DocBook, Muse, txt2tags,+Vimwiki, EPUB, ODT, and Word docx; and it can write plain text,+Markdown, CommonMark, PHP Markdown Extra, GitHub\-Flavored Markdown,+MultiMarkdown, reStructuredText, XHTML, HTML5, LaTeX (including+\f[C]beamer\f[] slide shows), ConTeXt, RTF, OPML, DocBook, OpenDocument,+ODT, Word docx, GNU Texinfo, MediaWiki markup, DokuWiki markup, ZimWiki+markup, Haddock markup, EPUB (v2 or v3), FictionBook2, Textile, groff+man, groff ms, Emacs Org mode, AsciiDoc, InDesign ICML, TEI Simple, Muse+and Slidy, Slideous, DZSlides, reveal.js or S5 HTML slide shows.+It can also produce PDF output on systems where LaTeX, ConTeXt,+\f[C]pdfroff\f[], \f[C]wkhtmltopdf\f[], \f[C]prince\f[], or+\f[C]weasyprint\f[] is installed. .PP Pandoc's enhanced version of Markdown includes syntax for footnotes, tables, flexible ordered lists, definition lists, fenced code blocks,@@ -55,9 +57,10 @@ \f[I]stdin\f[]. Otherwise, the \f[I]input\-files\f[] are concatenated (with a blank line between each) and used as input.-Output goes to \f[I]stdout\f[] by default (though output to-\f[I]stdout\f[] is disabled for the \f[C]odt\f[], \f[C]docx\f[],-\f[C]epub\f[], and \f[C]epub3\f[] output formats).+Output goes to \f[I]stdout\f[] by default (though output to the terminal+is disabled for the \f[C]odt\f[], \f[C]docx\f[], \f[C]epub2\f[], and+\f[C]epub3\f[] output formats, unless it is forced using+\f[C]\-o\ \-\f[]). For output to a file, use the \f[C]\-o\f[] option: .IP .nf@@ -89,6 +92,16 @@ \f[] .fi .PP+It is possible to supply a custom User\-Agent string or other header+when requesting a document from a URL:+.IP+.nf+\f[C]+pandoc\ \-f\ html\ \-t\ markdown\ \-\-request\-header\ User\-Agent:"Mozilla/5.0"\ \\+\ \ http://www.fsf.org+\f[]+.fi+.PP If multiple input files are given, \f[C]pandoc\f[] will concatenate them all (with blank lines between them) before parsing. This feature is disabled for binary input formats such as \f[C]EPUB\f[],@@ -161,7 +174,7 @@ .PP To produce a PDF, specify an output file with a \f[C]\&.pdf\f[] extension.-By default, pandoc will use LaTeX to convert it to PDF:+By default, pandoc will use LaTeX to create the PDF: .IP .nf \f[C]@@ -170,38 +183,45 @@ .fi .PP Production of a PDF requires that a LaTeX engine be installed (see-\f[C]\-\-latex\-engine\f[], below), and assumes that the following LaTeX+\f[C]\-\-pdf\-engine\f[], below), and assumes that the following LaTeX packages are available: \f[C]amsfonts\f[], \f[C]amsmath\f[],-\f[C]lm\f[], \f[C]ifxetex\f[], \f[C]ifluatex\f[], \f[C]eurosym\f[],-\f[C]listings\f[] (if the \f[C]\-\-listings\f[] option is used),-\f[C]fancyvrb\f[], \f[C]longtable\f[], \f[C]booktabs\f[],-\f[C]graphicx\f[] and \f[C]grffile\f[] (if the document contains-images), \f[C]hyperref\f[], \f[C]ulem\f[], \f[C]geometry\f[] (with the+\f[C]lm\f[], \f[C]unicode\-math\f[], \f[C]ifxetex\f[],+\f[C]ifluatex\f[], \f[C]listings\f[] (if the \f[C]\-\-listings\f[]+option is used), \f[C]fancyvrb\f[], \f[C]longtable\f[],+\f[C]booktabs\f[], \f[C]graphicx\f[] and \f[C]grffile\f[] (if the+document contains images), \f[C]hyperref\f[], \f[C]xcolor\f[] (with+\f[C]colorlinks\f[]), \f[C]ulem\f[], \f[C]geometry\f[] (with the \f[C]geometry\f[] variable set), \f[C]setspace\f[] (with \f[C]linestretch\f[]), and \f[C]babel\f[] (with \f[C]lang\f[]). The use of \f[C]xelatex\f[] or \f[C]lualatex\f[] as the LaTeX engine-requires \f[C]fontspec\f[]; \f[C]xelatex\f[] uses \f[C]mathspec\f[],-\f[C]polyglossia\f[] (with \f[C]lang\f[]), \f[C]xecjk\f[], and-\f[C]bidi\f[] (with the \f[C]dir\f[] variable set).+requires \f[C]fontspec\f[].+\f[C]xelatex\f[] uses \f[C]polyglossia\f[] (with \f[C]lang\f[]),+\f[C]xecjk\f[], and \f[C]bidi\f[] (with the \f[C]dir\f[] variable set).+If the \f[C]mathspec\f[] variable is set, \f[C]xelatex\f[] will use+\f[C]mathspec\f[] instead of \f[C]unicode\-math\f[]. The \f[C]upquote\f[] and \f[C]microtype\f[] packages are used if-available, and \f[C]csquotes\f[] will be used for smart punctuation if+available, and \f[C]csquotes\f[] will be used for [smart punctuation] if added to the template or included in any header file. The \f[C]natbib\f[], \f[C]biblatex\f[], \f[C]bibtex\f[], and \f[C]biber\f[] packages can optionally be used for citation rendering. These are included with all recent versions of TeX Live. .PP-Alternatively, pandoc can use ConTeXt or \f[C]wkhtmltopdf\f[] to create-a PDF.+Alternatively, pandoc can use ConTeXt, \f[C]pdfroff\f[], or any of the+following HTML/CSS\-to\-PDF\-engines, to create a PDF:+\f[C]wkhtmltopdf\f[], \f[C]weasyprint\f[] or \f[C]prince\f[]. To do this, specify an output file with a \f[C]\&.pdf\f[] extension, as-before, but add \f[C]\-t\ context\f[] or \f[C]\-t\ html5\f[] to the-command line.+before, but add the \f[C]\-\-pdf\-engine\f[] option or+\f[C]\-t\ context\f[], \f[C]\-t\ html\f[], or \f[C]\-t\ ms\f[] to the+command line (\f[C]\-t\ html\f[] defaults to+\f[C]\-\-pdf\-engine=wkhtmltopdf\f[]). .PP PDF output can be controlled using variables for LaTeX (if LaTeX is used) and variables for ConTeXt (if ConTeXt is used).+When using an HTML/CSS\-to\-PDF\-engine, \f[C]\-\-css\f[] affects the+output. If \f[C]wkhtmltopdf\f[] is used, then the variables \f[C]margin\-left\f[], \f[C]margin\-right\f[], \f[C]margin\-top\f[],-\f[C]margin\-bottom\f[], and \f[C]papersize\f[] will affect the output,-as will \f[C]\-\-css\f[].+\f[C]margin\-bottom\f[], and \f[C]papersize\f[] will affect the output. .SH OPTIONS .SS General options .TP@@ -210,18 +230,21 @@ \f[I]FORMAT\f[] can be \f[C]native\f[] (native Haskell), \f[C]json\f[] (JSON version of native AST), \f[C]markdown\f[] (pandoc's extended Markdown), \f[C]markdown_strict\f[] (original unextended Markdown),-\f[C]markdown_phpextra\f[] (PHP Markdown Extra),-\f[C]markdown_github\f[] (GitHub\-Flavored Markdown),-\f[C]markdown_mmd\f[] (MultiMarkdown), \f[C]commonmark\f[] (CommonMark-Markdown), \f[C]textile\f[] (Textile), \f[C]rst\f[] (reStructuredText),-\f[C]html\f[] (HTML), \f[C]docbook\f[] (DocBook), \f[C]t2t\f[]-(txt2tags), \f[C]docx\f[] (docx), \f[C]odt\f[] (ODT), \f[C]epub\f[]-(EPUB), \f[C]opml\f[] (OPML), \f[C]org\f[] (Emacs Org mode),-\f[C]mediawiki\f[] (MediaWiki markup), \f[C]twiki\f[] (TWiki markup),-\f[C]haddock\f[] (Haddock markup), or \f[C]latex\f[] (LaTeX).-If \f[C]+lhs\f[] is appended to \f[C]markdown\f[], \f[C]rst\f[],-\f[C]latex\f[], or \f[C]html\f[], the input will be treated as literate-Haskell source: see Literate Haskell support, below.+\f[C]markdown_phpextra\f[] (PHP Markdown Extra), \f[C]markdown_mmd\f[]+(MultiMarkdown), \f[C]gfm\f[] (GitHub\-Flavored Markdown),+\f[C]commonmark\f[] (CommonMark Markdown), \f[C]textile\f[] (Textile),+\f[C]rst\f[] (reStructuredText), \f[C]html\f[] (HTML), \f[C]docbook\f[]+(DocBook), \f[C]t2t\f[] (txt2tags), \f[C]docx\f[] (docx), \f[C]odt\f[]+(ODT), \f[C]epub\f[] (EPUB), \f[C]opml\f[] (OPML), \f[C]org\f[] (Emacs+Org mode), \f[C]mediawiki\f[] (MediaWiki markup), \f[C]twiki\f[] (TWiki+markup), \f[C]tikiwiki\f[] (TikiWiki markup), \f[C]creole\f[] (Creole+1.0), \f[C]haddock\f[] (Haddock markup), or \f[C]latex\f[] (LaTeX).+(\f[C]markdown_github\f[] provides deprecated and less accurate suppport+for Github\-Flavored Markdown; please use \f[C]gfm\f[] instead, unless+you need to use extensions other than \f[C]smart\f[].) If \f[C]+lhs\f[]+is appended to \f[C]markdown\f[], \f[C]rst\f[], \f[C]latex\f[], or+\f[C]html\f[], the input will be treated as literate Haskell source: see+Literate Haskell support, below. Markdown syntax extensions can be individually enabled or disabled by appending \f[C]+EXTENSION\f[] or \f[C]\-EXTENSION\f[] to the format name.@@ -241,31 +264,36 @@ (JSON version of native AST), \f[C]plain\f[] (plain text), \f[C]markdown\f[] (pandoc's extended Markdown), \f[C]markdown_strict\f[] (original unextended Markdown), \f[C]markdown_phpextra\f[] (PHP Markdown-Extra), \f[C]markdown_github\f[] (GitHub\-Flavored Markdown),-\f[C]markdown_mmd\f[] (MultiMarkdown), \f[C]commonmark\f[] (CommonMark-Markdown), \f[C]rst\f[] (reStructuredText), \f[C]html\f[] (XHTML),-\f[C]html5\f[] (HTML5), \f[C]latex\f[] (LaTeX), \f[C]beamer\f[] (LaTeX-beamer slide show), \f[C]context\f[] (ConTeXt), \f[C]man\f[] (groff-man), \f[C]mediawiki\f[] (MediaWiki markup), \f[C]dokuwiki\f[] (DokuWiki+Extra), \f[C]markdown_mmd\f[] (MultiMarkdown), \f[C]gfm\f[]+(GitHub\-Flavored Markdown), \f[C]commonmark\f[] (CommonMark Markdown),+\f[C]rst\f[] (reStructuredText), \f[C]html4\f[] (XHTML 1.0+Transitional), \f[C]html\f[] or \f[C]html5\f[] (HTML5/XHTML polyglot+markup), \f[C]latex\f[] (LaTeX), \f[C]beamer\f[] (LaTeX beamer slide+show), \f[C]context\f[] (ConTeXt), \f[C]man\f[] (groff man),+\f[C]mediawiki\f[] (MediaWiki markup), \f[C]dokuwiki\f[] (DokuWiki markup), \f[C]zimwiki\f[] (ZimWiki markup), \f[C]textile\f[] (Textile), \f[C]org\f[] (Emacs Org mode), \f[C]texinfo\f[] (GNU Texinfo),-\f[C]opml\f[] (OPML), \f[C]docbook\f[] (DocBook 4), \f[C]docbook5\f[]-(DocBook 5), \f[C]opendocument\f[] (OpenDocument), \f[C]odt\f[]-(OpenOffice text document), \f[C]docx\f[] (Word docx), \f[C]haddock\f[]-(Haddock markup), \f[C]rtf\f[] (rich text format), \f[C]epub\f[] (EPUB-v2 book), \f[C]epub3\f[] (EPUB v3), \f[C]fb2\f[] (FictionBook2 e\-book),-\f[C]asciidoc\f[] (AsciiDoc), \f[C]icml\f[] (InDesign ICML),+\f[C]opml\f[] (OPML), \f[C]docbook\f[] or \f[C]docbook4\f[] (DocBook 4),+\f[C]docbook5\f[] (DocBook 5), \f[C]jats\f[] (JATS XML),+\f[C]opendocument\f[] (OpenDocument), \f[C]odt\f[] (OpenOffice text+document), \f[C]docx\f[] (Word docx), \f[C]haddock\f[] (Haddock markup),+\f[C]rtf\f[] (rich text format), \f[C]epub2\f[] (EPUB v2 book),+\f[C]epub\f[] or \f[C]epub3\f[] (EPUB v3), \f[C]fb2\f[] (FictionBook2+e\-book), \f[C]asciidoc\f[] (AsciiDoc), \f[C]icml\f[] (InDesign ICML), \f[C]tei\f[] (TEI Simple), \f[C]slidy\f[] (Slidy HTML and JavaScript slide show), \f[C]slideous\f[] (Slideous HTML and JavaScript slide show), \f[C]dzslides\f[] (DZSlides HTML5 + JavaScript slide show), \f[C]revealjs\f[] (reveal.js HTML5 + JavaScript slide show), \f[C]s5\f[] (S5 HTML and JavaScript slide show), or the path of a custom lua writer (see Custom writers, below).-Note that \f[C]odt\f[], \f[C]epub\f[], and \f[C]epub3\f[] output will-not be directed to \f[I]stdout\f[]; an output filename must be specified-using the \f[C]\-o/\-\-output\f[] option.+(\f[C]markdown_github\f[] provides deprecated and less accurate suppport+for Github\-Flavored Markdown; please use \f[C]gfm\f[] instead, unless+you use extensions that do not work with \f[C]gfm\f[].) Note that+\f[C]odt\f[], \f[C]epub\f[], and \f[C]epub3\f[] output will not be+directed to \f[I]stdout\f[]; an output filename must be specified using+the \f[C]\-o/\-\-output\f[] option. If \f[C]+lhs\f[] is appended to \f[C]markdown\f[], \f[C]rst\f[],-\f[C]latex\f[], \f[C]beamer\f[], \f[C]html\f[], or \f[C]html5\f[], the+\f[C]latex\f[], \f[C]beamer\f[], \f[C]html4\f[], or \f[C]html5\f[], the output will be rendered as literate Haskell source: see Literate Haskell support, below. Markdown syntax extensions can be individually enabled or disabled by@@ -278,9 +306,9 @@ .TP .B \f[C]\-o\f[] \f[I]FILE\f[], \f[C]\-\-output=\f[]\f[I]FILE\f[] Write output to \f[I]FILE\f[] instead of \f[I]stdout\f[].-If \f[I]FILE\f[] is \f[C]\-\f[], output will go to \f[I]stdout\f[].-(Exception: if the output format is \f[C]odt\f[], \f[C]docx\f[],-\f[C]epub\f[], or \f[C]epub3\f[], output to stdout is disabled.)+If \f[I]FILE\f[] is \f[C]\-\f[], output will go to \f[I]stdout\f[], even+if a non\-textual format (\f[C]docx\f[], \f[C]odt\f[], \f[C]epub2\f[],+\f[C]epub3\f[]) is specified. .RS .RE .TP@@ -288,7 +316,7 @@ Specify the user data directory to search for pandoc data files. If this option is not specified, the default user data directory will be used.-This is, in Unix:+This is, in UNIX: .RS .IP .nf@@ -340,6 +368,23 @@ .RS .RE .TP+.B \f[C]\-\-quiet\f[]+Suppress warning messages.+.RS+.RE+.TP+.B \f[C]\-\-fail\-if\-warnings\f[]+Exit with error status if there are any warnings.+.RS+.RE+.TP+.B \f[C]\-\-log=\f[]\f[I]FILE\f[]+Write log messages in machine\-readable JSON format to \f[I]FILE\f[].+All messages above DEBUG level will be written, regardless of verbosity+settings (\f[C]\-\-verbose\f[], \f[C]\-\-quiet\f[]).+.RS+.RE+.TP .B \f[C]\-\-list\-input\-formats\f[] List supported input formats, one per line. .RS@@ -379,41 +424,6 @@ .RE .SS Reader options .TP-.B \f[C]\-R\f[], \f[C]\-\-parse\-raw\f[]-Parse untranslatable HTML codes and LaTeX environments as raw HTML or-LaTeX, instead of ignoring them.-Affects only HTML and LaTeX input.-Raw HTML can be printed in Markdown, reStructuredText, Emacs Org mode,-HTML, Slidy, Slideous, DZSlides, reveal.js, and S5 output; raw LaTeX can-be printed in Markdown, reStructuredText, Emacs Org mode, LaTeX, and-ConTeXt output.-The default is for the readers to omit untranslatable HTML codes and-LaTeX environments.-(The LaTeX reader does pass through untranslatable LaTeX-\f[I]commands\f[], even if \f[C]\-R\f[] is not specified.)-.RS-.RE-.TP-.B \f[C]\-S\f[], \f[C]\-\-smart\f[]-Produce typographically correct output, converting straight quotes to-curly quotes, \f[C]\-\-\-\f[] to em\-dashes, \f[C]\-\-\f[] to-en\-dashes, and \f[C]\&...\f[] to ellipses.-Nonbreaking spaces are inserted after certain abbreviations, such as-\[lq]Mr.\[rq] (Note: This option is selected automatically when the-output format is \f[C]latex\f[] or \f[C]context\f[], unless-\f[C]\-\-no\-tex\-ligatures\f[] is used.-It has no effect for \f[C]latex\f[] input.)-.RS-.RE-.TP-.B \f[C]\-\-old\-dashes\f[]-Selects the pandoc <= 1.8.2.1 behavior for parsing smart dashes:-\f[C]\-\f[] before a numeral is an en\-dash, and \f[C]\-\-\f[] is an-em\-dash.-This option is selected automatically for \f[C]textile\f[] input.-.RS-.RE-.TP .B \f[C]\-\-base\-header\-level=\f[]\f[I]NUMBER\f[] Specify the base level for headers (defaults to 1). .RS@@ -476,17 +486,50 @@ Those who would prefer to write filters in python can use the module \f[C]pandocfilters\f[], installable from PyPI. There are also pandoc filter libraries in PHP, perl, and-javascript/node.js.+JavaScript/node.js. .PP In order of preference, pandoc will look for filters in .IP "1." 3 a specified full or relative path (executable or non\-executable) .IP "2." 3-\f[C]$DATADIR/filters\f[] (executable or non\-executable)+\f[C]$DATADIR/filters\f[] (executable or non\-executable) where+\f[C]$DATADIR\f[] is the user data directory (see+\f[C]\-\-data\-dir\f[], above). .IP "3." 3 \f[C]$PATH\f[] (executable only) .RE .TP+.B \f[C]\-\-lua\-filter=\f[]\f[I]SCRIPT\f[]+Transform the document in a similar fashion as JSON filters (see+\f[C]\-\-filter\f[]), but use pandoc's build\-in lua filtering system.+The given lua script is expected to return a list of lua filters which+will be applied in order.+Each lua filter must contain element\-transforming functions indexed by+the name of the AST element on which the filter function should be+applied.+.RS+.PP+The \f[C]pandoc\f[] lua module provides helper functions for element+creation.+It is always loaded into the script's lua environment.+.PP+The following is an example lua script for macro\-expansion:+.IP+.nf+\f[C]+function\ expand_hello_world(inline)+\ \ if\ inline.c\ ==\ \[aq]{{helloworld}}\[aq]\ then+\ \ \ \ return\ pandoc.Emph{\ pandoc.Str\ "Hello,\ World"\ }+\ \ else+\ \ \ \ return\ inline+\ \ end+end++return\ {{Str\ =\ expand_hello_world}}+\f[]+.fi+.RE+.TP .B \f[C]\-M\f[] \f[I]KEY\f[][\f[C]=\f[]\f[I]VAL\f[]], \f[C]\-\-metadata=\f[]\f[I]KEY\f[][\f[C]:\f[]\f[I]VAL\f[]] Set the metadata field \f[I]KEY\f[] to the value \f[I]VAL\f[]. A value specified on the command line overrides a value specified in the@@ -501,13 +544,6 @@ .RS .RE .TP-.B \f[C]\-\-normalize\f[]-Normalize the document after reading: merge adjacent \f[C]Str\f[] or-\f[C]Emph\f[] elements, for example, and remove repeated-\f[C]Space\f[]s.-.RS-.RE-.TP .B \f[C]\-p\f[], \f[C]\-\-preserve\-tabs\f[] Preserve tabs instead of converting them to spaces (the default). Note that this will only affect tabs in literal code spans and code@@ -539,12 +575,31 @@ .RE .TP .B \f[C]\-\-extract\-media=\f[]\f[I]DIR\f[]-Extract images and other media contained in a docx or epub container to-the path \f[I]DIR\f[], creating it if necessary, and adjust the images-references in the document so they point to the extracted files.-This option only affects the docx and epub readers.+Extract images and other media contained in or linked from the source+document to the path \f[I]DIR\f[], creating it if necessary, and adjust+the images references in the document so they point to the extracted+files.+If the source format is a binary container (docx, epub, or odt), the+media is extracted from the container and the original filenames are+used.+Otherwise the media is read from the file system or downloaded, and new+filenames are constructed based on SHA1 hashes of the contents. .RS .RE+.TP+.B \f[C]\-\-abbreviations=\f[]\f[I]FILE\f[]+Specifies a custom abbreviations file, with abbreviations one to a line.+If this option is not specified, pandoc will read the data file+\f[C]abbreviations\f[] from the user data directory or fall back on a+system default.+To see the system default, use+\f[C]pandoc\ \-\-print\-default\-data\-file=abbreviations\f[].+The only use pandoc makes of this list is in the Markdown reader.+Strings ending in a period that are found in this list will be followed+by a nonbreaking space, so that the period will not produce+sentence\-ending space in formats like LaTeX.+.RS+.RE .SS General writer options .TP .B \f[C]\-s\f[], \f[C]\-\-standalone\f[]@@ -595,6 +650,14 @@ .RS .RE .TP+.B \f[C]\-\-eol=crlf\f[]|\f[C]lf\f[]|\f[C]native\f[]+Manually specify line endings: \f[C]crlf\f[] (Windows), \f[C]lf\f[]+(macOS/Linux/UNIX), or \f[C]native\f[] (line endings appropriate to the+OS on which pandoc is being run).+The default is \f[C]native\f[].+.RS+.RE+.TP .B \f[C]\-\-dpi\f[]=\f[I]NUMBER\f[] Specify the dpi (dots per inch) value for conversion from pixels to inch/centimeters and vice versa.@@ -617,11 +680,6 @@ .RS .RE .TP-.B \f[C]\-\-no\-wrap\f[]-Deprecated synonym for \f[C]\-\-wrap=none\f[].-.RS-.RE-.TP .B \f[C]\-\-columns=\f[]\f[I]NUMBER\f[] Specify length of lines in characters. This affects text wrapping in the generated source code (see@@ -633,11 +691,11 @@ .TP .B \f[C]\-\-toc\f[], \f[C]\-\-table\-of\-contents\f[] Include an automatically generated table of contents (or, in the case of-\f[C]latex\f[], \f[C]context\f[], \f[C]docx\f[], and \f[C]rst\f[], an-instruction to create one) in the output document.-This option has no effect on \f[C]man\f[], \f[C]docbook\f[],-\f[C]docbook5\f[], \f[C]slidy\f[], \f[C]slideous\f[], \f[C]s5\f[], or-\f[C]odt\f[] output.+\f[C]latex\f[], \f[C]context\f[], \f[C]docx\f[], \f[C]odt\f[],+\f[C]opendocument\f[], \f[C]rst\f[], or \f[C]ms\f[], an instruction to+create one) in the output document.+This option has no effect on \f[C]man\f[], \f[C]docbook4\f[],+\f[C]docbook5\f[], or \f[C]jats\f[] output. .RS .RE .TP@@ -649,13 +707,21 @@ .RS .RE .TP+.B \f[C]\-\-strip\-comments\f[]+Strip out HTML comments in the Markdown or Textile source, rather than+passing them on to Markdown, Textile or HTML output as raw HTML.+This does not apply to HTML comments inside raw HTML blocks when the+\f[C]markdown_in_html_blocks\f[] extension is not set.+.RS+.RE+.TP .B \f[C]\-\-no\-highlight\f[] Disables syntax highlighting for code blocks and inlines, even when a language attribute is given. .RS .RE .TP-.B \f[C]\-\-highlight\-style=\f[]\f[I]STYLE\f[]+.B \f[C]\-\-highlight\-style=\f[]\f[I]STYLE\f[]|\f[I]FILE\f[] Specifies the coloring style to be used in highlighted source code. Options are \f[C]pygments\f[] (the default), \f[C]kate\f[], \f[C]monochrome\f[], \f[C]breezeDark\f[], \f[C]espresso\f[],@@ -664,8 +730,23 @@ highlighting, below. See also \f[C]\-\-list\-highlight\-styles\f[]. .RS+.PP+Instead of a \f[I]STYLE\f[] name, a JSON file with extension+\f[C]\&.theme\f[] may be supplied.+This will be parsed as a KDE syntax highlighting theme and (if valid)+used as the highlighting style.+To see a sample theme that can be modified,+\f[C]pandoc\ \-\-print\-default\-data\-file\ default.theme\f[]. .RE .TP+.B \f[C]\-\-syntax\-definition=\f[]\f[I]FILE\f[]+Instructs pandoc to load a KDE XML syntax definition file, which will be+used for syntax highlighting of appropriately marked code blocks.+This can be used to add support for new languages or to use altered+syntax definitions for existing languages.+.RS+.RE+.TP .B \f[C]\-H\f[] \f[I]FILE\f[], \f[C]\-\-include\-in\-header=\f[]\f[I]FILE\f[] Include contents of \f[I]FILE\f[], verbatim, at the end of the header. This can be used, for example, to include special CSS or JavaScript in@@ -698,6 +779,26 @@ Implies \f[C]\-\-standalone\f[]. .RS .RE+.TP+.B \f[C]\-\-resource\-path=\f[]\f[I]SEARCHPATH\f[]+List of paths to search for images and other resources.+The paths should be separated by \f[C]:\f[] on Linux, UNIX, and macOS+systems, and by \f[C];\f[] on Windows.+If \f[C]\-\-resource\-path\f[] is not specified, the default resource+path is the working directory.+Note that, if \f[C]\-\-resource\-path\f[] is specified, the working+directory must be explicitly listed or it will not be searched.+For example: \f[C]\-\-resource\-path=.:test\f[] will search the working+directory and the \f[C]test\f[] subdirectory, in that order.+.RS+.RE+.TP+.B \f[C]\-\-request\-header=\f[]\f[I]NAME\f[]\f[C]:\f[]\f[I]VAL\f[]+Set the request header \f[I]NAME\f[] to the value \f[I]VAL\f[] when+making HTTP requests (for example, when a URL is given on the command+line, or when resources used in a document must be downloaded).+.RS+.RE .SS Options affecting specific writers .TP .B \f[C]\-\-self\-contained\f[]@@ -708,17 +809,20 @@ that it needs no external files and no net access to be displayed properly by a browser. This option works only with HTML output formats, including-\f[C]html\f[], \f[C]html5\f[], \f[C]html+lhs\f[], \f[C]html5+lhs\f[],+\f[C]html4\f[], \f[C]html5\f[], \f[C]html+lhs\f[], \f[C]html5+lhs\f[], \f[C]s5\f[], \f[C]slidy\f[], \f[C]slideous\f[], \f[C]dzslides\f[], and \f[C]revealjs\f[]. Scripts, images, and stylesheets at absolute URLs will be downloaded; those at relative URLs will be sought relative to the working directory (if the first source file is local) or relative to the base URL (if the first source file is remote).+Elements with the attribute \f[C]data\-external="1"\f[] will be left+alone; the documents they link to will not be incorporated in the+document. Limitation: resources that are loaded dynamically through JavaScript cannot be incorporated; as a result, \f[C]\-\-self\-contained\f[] does-not work with \f[C]\-\-mathjax\f[], and some advanced features (-e.g.\ zoom or speaker notes) may not work in an offline+not work with \f[C]\-\-mathjax\f[], and some advanced features+(e.g.\ zoom or speaker notes) may not work in an offline \[lq]self\-contained\[rq] \f[C]reveal.js\f[] slide show. .RS .RE@@ -730,8 +834,8 @@ .TP .B \f[C]\-\-ascii\f[] Use only ASCII characters in output.-Currently supported only for HTML output (which uses numerical entities-instead of UTF\-8 when this option is selected).+Currently supported only for HTML and DocBook output (which uses+numerical entities instead of UTF\-8 when this option is selected). .RS .RE .TP@@ -760,11 +864,6 @@ .RS .RE .TP-.B \f[C]\-\-chapters\f[]-Deprecated synonym for \f[C]\-\-top\-level\-division=chapter\f[].-.RS-.RE-.TP .B \f[C]\-\-top\-level\-division=[default|section|chapter|part]\f[] Treat top\-level headers as the given division type in LaTeX, ConTeXt, DocBook, and TEI output.@@ -805,25 +904,6 @@ .RS .RE .TP-.B \f[C]\-\-no\-tex\-ligatures\f[]-Do not use the TeX ligatures for quotation marks, apostrophes, and-dashes (\f[C]`...\[aq]\f[], \f[C]``..\[aq]\[aq]\f[], \f[C]\-\-\f[],-\f[C]\-\-\-\f[]) when writing or reading LaTeX or ConTeXt.-In reading LaTeX, parse the characters \f[C]`\f[], \f[C]\[aq]\f[], and-\f[C]\-\f[] literally, rather than parsing ligatures for quotation marks-and dashes.-In writing LaTeX or ConTeXt, print unicode quotation mark and dash-characters literally, rather than converting them to the standard ASCII-TeX ligatures.-Note: normally \f[C]\-\-smart\f[] is selected automatically for LaTeX-and ConTeXt output, but it must be specified explicitly if-\f[C]\-\-no\-tex\-ligatures\f[] is selected.-If you use literal curly quotes, dashes, and ellipses in your source,-then you may want to use \f[C]\-\-no\-tex\-ligatures\f[] without-\f[C]\-\-smart\f[].-.RS-.RE-.TP .B \f[C]\-\-listings\f[] Use the \f[C]listings\f[] package for LaTeX code blocks .RS@@ -842,6 +922,8 @@ Headers above this level in the hierarchy are used to divide the slide show into sections; headers below this level create subheads within a slide.+Note that content that is not contained under slide\-level headers will+not appear in the slide show. The default is to set the slide level based on the contents of the document; see Structuring the slide show. .RS@@ -867,8 +949,9 @@ .RE .TP .B \f[C]\-\-id\-prefix=\f[]\f[I]STRING\f[]-Specify a prefix to be added to all automatically generated identifiers-in HTML and DocBook output, and to footnote numbers in Markdown output.+Specify a prefix to be added to all identifiers and internal links in+HTML and DocBook output, and to footnote numbers in Markdown and Haddock+output. This is useful for preventing duplicate identifiers when generating fragments to be included in other pages. .RS@@ -887,29 +970,20 @@ This option can be used repeatedly to include multiple files. They will be included in the order specified. .RS+.PP+A stylesheet is required for generating EPUB.+If none is provided using this option (or the \f[C]stylesheet\f[]+metadata field), pandoc will look for a file \f[C]epub.css\f[] in the+user data directory (see \f[C]\-\-data\-dir\f[]).+If it is not found there, sensible defaults will be used. .RE .TP-.B \f[C]\-\-reference\-odt=\f[]\f[I]FILE\f[]-Use the specified file as a style reference in producing an ODT.-For best results, the reference ODT should be a modified version of an-ODT produced using pandoc.-The contents of the reference ODT are ignored, but its stylesheets are-used in the new ODT.-If no reference ODT is specified on the command line, pandoc will look-for a file \f[C]reference.odt\f[] in the user data directory (see-\f[C]\-\-data\-dir\f[]).-If this is not found either, sensible defaults will be used.+.B \f[C]\-\-reference\-doc=\f[]\f[I]FILE\f[]+Use the specified file as a style reference in producing a docx or ODT+file. .RS-.PP-To produce a custom \f[C]reference.odt\f[], first get a copy of the-default \f[C]reference.odt\f[]:-\f[C]pandoc\ \-\-print\-default\-data\-file\ reference.odt\ >\ custom\-reference.odt\f[].-Then open \f[C]custom\-reference.docx\f[] in LibreOffice, modify the-styles as you wish, and save the file.-.RE .TP-.B \f[C]\-\-reference\-docx=\f[]\f[I]FILE\f[]-Use the specified file as a style reference in producing a docx file.+.B Docx For best results, the reference docx should be a modified version of a docx file produced using pandoc. The contents of the reference docx are ignored, but its stylesheets and@@ -930,20 +1004,31 @@ the styles used by pandoc: [paragraph] Normal, Body Text, First Paragraph, Compact, Title, Subtitle, Author, Date, Abstract, Bibliography, Heading 1, Heading 2, Heading 3, Heading 4, Heading 5,-Heading 6, Block Text, Footnote Text, Definition Term, Definition,-Caption, Table Caption, Image Caption, Figure, Figure With Caption, TOC-Heading; [character] Default Paragraph Font, Body Text Char, Verbatim-Char, Footnote Reference, Hyperlink; [table] Normal Table.+Heading 6, Heading 7, Heading 8, Heading 9, Block Text, Footnote Text,+Definition Term, Definition, Caption, Table Caption, Image Caption,+Figure, Captioned Figure, TOC Heading; [character] Default Paragraph+Font, Body Text Char, Verbatim Char, Footnote Reference, Hyperlink;+[table] Table. .RE .TP-.B \f[C]\-\-epub\-stylesheet=\f[]\f[I]FILE\f[]-Use the specified CSS file to style the EPUB.-If no stylesheet is specified, pandoc will look for a file-\f[C]epub.css\f[] in the user data directory (see+.B ODT+For best results, the reference ODT should be a modified version of an+ODT produced using pandoc.+The contents of the reference ODT are ignored, but its stylesheets are+used in the new ODT.+If no reference ODT is specified on the command line, pandoc will look+for a file \f[C]reference.odt\f[] in the user data directory (see \f[C]\-\-data\-dir\f[]).-If it is not found there, sensible defaults will be used.+If this is not found either, sensible defaults will be used. .RS+.PP+To produce a custom \f[C]reference.odt\f[], first get a copy of the+default \f[C]reference.odt\f[]:+\f[C]pandoc\ \-\-print\-default\-data\-file\ reference.odt\ >\ custom\-reference.odt\f[].+Then open \f[C]custom\-reference.odt\f[] in LibreOffice, modify the+styles as you wish, and save the file. .RE+.RE .TP .B \f[C]\-\-epub\-cover\-image=\f[]\f[I]FILE\f[] Use the specified image as the EPUB cover.@@ -989,7 +1074,7 @@ them or put the whole filename in single quotes, to prevent them from being interpreted by the shell. To use the embedded fonts, you will need to add declarations like the-following to your CSS (see \f[C]\-\-epub\-stylesheet\f[]):+following to your CSS (see \f[C]\-\-css\f[]): .RS .IP .nf@@ -1035,17 +1120,25 @@ .RS .RE .TP-.B \f[C]\-\-latex\-engine=pdflatex\f[]|\f[C]lualatex\f[]|\f[C]xelatex\f[]-Use the specified LaTeX engine when producing PDF output.+.B \f[C]\-\-epub\-subdirectory=\f[]\f[I]DIRNAME\f[]+Specify the subdirectory in the OCF container that is to hold the+EPUB\-specific contents.+The default is \f[C]EPUB\f[].+To put the EPUB contents in the top level, use an empty string.+.RS+.RE+.TP+.B \f[C]\-\-pdf\-engine=pdflatex\f[]|\f[C]lualatex\f[]|\f[C]xelatex\f[]|\f[C]wkhtmltopdf\f[]|\f[C]weasyprint\f[]|\f[C]prince\f[]|\f[C]context\f[]|\f[C]pdfroff\f[]+Use the specified engine when producing PDF output. The default is \f[C]pdflatex\f[]. If the engine is not in your PATH, the full path of the engine may be specified here. .RS .RE .TP-.B \f[C]\-\-latex\-engine\-opt=\f[]\f[I]STRING\f[]+.B \f[C]\-\-pdf\-engine\-opt=\f[]\f[I]STRING\f[] Use the given string as a command\-line argument to the-\f[C]latex\-engine\f[].+\f[C]pdf\-engine\f[]. If used multiple times, the arguments are provided with spaces between them. Note that no check for duplicate options is done.@@ -1115,12 +1208,10 @@ .RS .RE .TP-.B \f[C]\-\-mathml\f[][\f[C]=\f[]\f[I]URL\f[]]-Convert TeX math to MathML (in \f[C]docbook\f[], \f[C]docbook5\f[],-\f[C]html\f[] and \f[C]html5\f[]).-In standalone \f[C]html\f[] output, a small JavaScript (or a link to-such a script if a \f[I]URL\f[] is supplied) will be inserted that-allows the MathML to be viewed on some browsers.+.B \f[C]\-\-mathml\f[]+Convert TeX math to MathML (in \f[C]docbook4\f[], \f[C]docbook5\f[],+\f[C]jats\f[], \f[C]html4\f[] and \f[C]html5\f[]).+This is the default in \f[C]odt\f[] output. .RS .RE .TP@@ -1170,7 +1261,7 @@ .TP .B \f[C]\-\-katex\f[][\f[C]=\f[]\f[I]URL\f[]] Use KaTeX to display embedded TeX math in HTML output.-The \f[I]URL\f[] should point to the \f[C]katex.js\f[] load script.+The \f[I]URL\f[] is the base URL for the KaTeX library. If a \f[I]URL\f[] is not provided, a link to the KaTeX CDN will be inserted. Note: KaTeX seems to work best with \f[C]html5\f[] output.@@ -1252,7 +1343,7 @@ use \f[C]\-t\ context\f[]). .IP \[bu] 2 \f[C]docx\f[] has no template (however, you can use-\f[C]\-\-reference\-docx\f[] to customize the output).+\f[C]\-\-reference\-doc\f[] to customize the output). .PP Templates contain \f[I]variables\f[], which allow for the inclusion of arbitrary information at any point in the file.@@ -1266,6 +1357,29 @@ These vary somewhat depending on the output format, but include metadata fields as well as the following: .TP+.B \f[C]sourcefile\f[], \f[C]outputfile\f[]+source and destination filenames, as given on the command line.+\f[C]sourcefile\f[] can also be a list if input comes from multiple+files, or empty if input is from stdin.+You can use the following snippet in your template to distinguish them:+.RS+.IP+.nf+\f[C]+$if(sourcefile)$+$for(sourcefile)$+$sourcefile$+$endfor$+$else$+(stdin)+$endif$+\f[]+.fi+.PP+Similarly, \f[C]outputfile\f[] can be \f[C]\-\f[] if output goes to the+terminal.+.RE+.TP .B \f[C]title\f[], \f[C]author\f[], \f[C]date\f[] allow identification of basic aspects of the document. Included in PDF metadata through LaTeX and ConTeXt.@@ -1322,7 +1436,8 @@ .RE .TP .B \f[C]toc\-title\f[]-title of table of contents (works only with EPUB and docx)+title of table of contents (works only with EPUB, opendocument, odt,+docx) .RS .RE .TP@@ -1344,7 +1459,8 @@ .RE .TP .B \f[C]meta\-json\f[]-JSON representation of all of the document's metadata+JSON representation of all of the document's metadata.+Field values are transformed to the selected output format. .RS .RE .SS Language variables@@ -1391,16 +1507,26 @@ Algorithm. .PP When using LaTeX for bidirectional documents, only the \f[C]xelatex\f[]-engine is fully supported (use \f[C]\-\-latex\-engine=xelatex\f[]).+engine is fully supported (use \f[C]\-\-pdf\-engine=xelatex\f[]). .RE .SS Variables for slides .PP Variables are available for producing slide shows with pandoc, including all reveal.js configuration options. .TP+.B \f[C]titlegraphic\f[]+title graphic for Beamer documents+.RS+.RE+.TP+.B \f[C]logo\f[]+logo for Beamer documents+.RS+.RE+.TP .B \f[C]slidy\-url\f[] base URL for Slidy documents (defaults to-\f[C]http://www.w3.org/Talks/Tools/Slidy2\f[])+\f[C]https://www.w3.org/Talks/Tools/Slidy2\f[]) .RS .RE .TP@@ -1448,17 +1574,11 @@ .RS .RE .TP-.B \f[C]colorlinks\f[]-add color to link text; automatically enabled if any of-\f[C]linkcolor\f[], \f[C]citecolor\f[], \f[C]urlcolor\f[], or-\f[C]toccolor\f[] are set (for beamer only).-.RS-.RE-.TP-.B \f[C]linkcolor\f[], \f[C]citecolor\f[], \f[C]urlcolor\f[], \f[C]toccolor\f[]-color for internal links, citation links, external links, and links in-table of contents: uses any of the predefined LaTeX colors (for beamer-only).+.B \f[C]aspectratio\f[]+aspect ratio of slides (for beamer only, \f[C]1610\f[] for 16:10,+\f[C]169\f[] for 16:9, \f[C]149\f[] for 14:9, \f[C]141\f[] for 1.41:1,+\f[C]54\f[] for 5:4, \f[C]43\f[] for 4:3 which is the default, and+\f[C]32\f[] for 3:2). .RS .RE .SS Variables for LaTeX@@ -1467,7 +1587,7 @@ .TP .B \f[C]papersize\f[] paper size, e.g.-\f[C]letter\f[], \f[C]A4\f[]+\f[C]letter\f[], \f[C]a4\f[] .RS .RE .TP@@ -1561,7 +1681,8 @@ .TP .B \f[C]linkcolor\f[], \f[C]citecolor\f[], \f[C]urlcolor\f[], \f[C]toccolor\f[] color for internal links, citation links, external links, and links in-table of contents: uses any of the predefined LaTeX colors+table of contents: uses options allowed by \f[C]xcolor\f[], including+the \f[C]dvipsnames\f[], \f[C]svgnames\f[], and \f[C]x11names\f[] lists .RS .RE .TP@@ -1630,6 +1751,11 @@ list of options for biblatex. .RS .RE+.TP+.B \f[C]natbiboptions\f[]+list of options for natbib.+.RS+.RE .SS Variables for ConTeXt .TP .B \f[C]papersize\f[]@@ -1745,6 +1871,31 @@ if \f[C]true\f[] (the default), hyphenation will be used .RS .RE+.SS Variables for ms+.TP+.B \f[C]pointsize\f[]+point size (e.g.+\f[C]10p\f[])+.RS+.RE+.TP+.B \f[C]lineheight\f[]+line height (e.g.+\f[C]12p\f[])+.RS+.RE+.TP+.B \f[C]fontfamily\f[]+font family (e.g.+\f[C]T\f[] or \f[C]P\f[])+.RS+.RE+.TP+.B \f[C]indent\f[]+paragraph indent (e.g.+\f[C]2m\f[])+.RS+.RE .SS Using variables in templates .PP Variable names are sequences of alphanumerics, \f[C]\-\f[], and@@ -1818,6 +1969,9 @@ modifying your custom templates accordingly. An easy way to do this is to fork the pandoc\-templates repository and merge in changes after each pandoc release.+.PP+Templates may contain comments: anything on a line after \f[C]$\-\-\f[]+will be treated as a comment and ignored. .SH PANDOC'S MARKDOWN .PP Pandoc understands an extended and slightly revised version of John@@ -1925,6 +2079,12 @@ #22,\ for\ example,\ and\ #5. \f[] .fi+.SS Extension: \f[C]space_in_atx_header\f[]+.PP+Many Markdown implementations do not require a space between the opening+\f[C]#\f[]s of an ATX header and the header text, so that+\f[C]#5\ bolt\f[] and \f[C]#hashtag\f[] count as headers.+With this extension, pandoc does require the space. .SS Header identifiers .SS Extension: \f[C]header_attributes\f[] .PP@@ -2065,9 +2225,9 @@ .PP If the \f[C]\-\-section\-divs\f[] option is specified, then each section will be wrapped in a \f[C]div\f[] (or a \f[C]section\f[], if-\f[C]\-\-html5\f[] was specified), and the identifier will be attached-to the enclosing \f[C]<div>\f[] (or \f[C]<section>\f[]) tag rather than-the header itself.+\f[C]html5\f[] was specified), and the identifier will be attached to+the enclosing \f[C]<div>\f[] (or \f[C]<section>\f[]) tag rather than the+header itself. This allows entire sections to be manipulated using JavaScript or treated differently in CSS. .SS Extension: \f[C]implicit_header_references\f[]@@ -2285,10 +2445,10 @@ \f[C]numberLines\f[] are classes, and \f[C]startFrom\f[] is an attribute with value \f[C]100\f[]. Some output formats can use this information to do syntax highlighting.-Currently, the only output formats that uses this information are HTML-and LaTeX.-If highlighting is supported for your output format and language, then-the code block above will appear highlighted, with numbered lines.+Currently, the only output formats that uses this information are HTML,+LaTeX, Docx, and Ms.\ If highlighting is supported for your output+format and language, then the code block above will appear highlighted,+with numbered lines. (To see which languages are supported, type \f[C]pandoc\ \-\-list\-highlight\-languages\f[].) Otherwise, the code block above will appear as follows:@@ -2420,14 +2580,13 @@ *\ and\ my\ second. \f[] .fi-.SS The four\-space rule+.SS Block content in list items .PP A list item may contain multiple paragraphs and other block\-level content. However, subsequent paragraphs must be preceded by a blank line and-indented four spaces or a tab.-The list will look better if the first paragraph is aligned with the-rest:+indented to line up with the first non\-space content after the list+marker. .IP .nf \f[C]@@ -2442,21 +2601,35 @@ \f[] .fi .PP+Exception: if the list marker is followed by an indented code block,+which must begin 5 spaces after the list marker, then subsequent+paragraphs must begin two columns after the last character of the list+marker:+.IP+.nf+\f[C]+*\ \ \ \ \ code++\ \ continuation\ paragraph+\f[]+.fi+.PP List items may include other lists. In this case the preceding blank line is optional.-The nested list must be indented four spaces or one tab:+The nested list must be indented to line up with the first non\-space+character after the list marker of the containing list item. .IP .nf \f[C] *\ fruits-\ \ \ \ +\ apples-\ \ \ \ \ \ \ \ \-\ macintosh-\ \ \ \ \ \ \ \ \-\ red\ delicious-\ \ \ \ +\ pears-\ \ \ \ +\ peaches+\ \ +\ apples+\ \ \ \ \-\ macintosh+\ \ \ \ \-\ red\ delicious+\ \ +\ pears+\ \ +\ peaches *\ vegetables-\ \ \ \ +\ broccoli-\ \ \ \ +\ chard+\ \ +\ broccoli+\ \ +\ chard \f[] .fi .PP@@ -2477,18 +2650,6 @@ list\ item. \f[] .fi-.PP-\f[B]Note:\f[] Although the four\-space rule for continuation paragraphs-comes from the official Markdown syntax guide, the reference-implementation, \f[C]Markdown.pl\f[], does not follow it.-So pandoc will give different results than \f[C]Markdown.pl\f[] when-authors have indented continuation paragraphs fewer than four spaces.-.PP-The Markdown syntax guide is not explicit whether the four\-space rule-applies to \f[I]all\f[] block\-level content in a list item; it only-mentions paragraphs and code blocks.-But it implies that the rule applies to all block\-level content-(including nested lists), and pandoc interprets it that way. .SS Ordered lists .PP Ordered lists work just like bulleted lists, except that the items begin@@ -2953,6 +3114,15 @@ +\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+ \f[] .fi+.SS Grid Table Limitations+.PP+Pandoc does not support grid tables with row spans or column spans.+This means that neither variable numbers of columns across rows nor+variable numbers of rows across columns are supported by Pandoc.+All grid tables must have the same number of columns in each row, and+the same number of rows in each column.+For example, the Docutils sample grid tables will not render as expected+with Pandoc. .SS Extension: \f[C]pipe_tables\f[] .PP Pipe tables look like this:@@ -3164,7 +3334,8 @@ Thus, for example, if a title contains a colon, it must be quoted. The pipe character (\f[C]|\f[]) can be used to begin an indented block that will be interpreted literally, without need for escaping.-This form is necessary when the field contains blank lines:+This form is necessary when the field contains blank lines or+block\-level formatting: .IP .nf \f[C]@@ -3283,19 +3454,6 @@ indicating hard line breaks using two trailing spaces on a line. .PP Backslash escapes do not work in verbatim contexts.-.SS Smart punctuation-.SS Extension-.PP-If the \f[C]\-\-smart\f[] option is specified, pandoc will produce-typographically correct output, converting straight quotes to curly-quotes, \f[C]\-\-\-\f[] to em\-dashes, \f[C]\-\-\f[] to en\-dashes, and-\f[C]\&...\f[] to ellipses.-Nonbreaking spaces are inserted after certain abbreviations, such as-\[lq]Mr.\[rq]-.PP-Note: if your LaTeX template or any included header file call for the-\f[C]csquotes\f[] package, pandoc will detect this automatically and use-\f[C]\\enquote{...}\f[] for quoted text. .SS Inline formatting .SS Emphasis .PP@@ -3483,12 +3641,17 @@ .RS .RE .TP-.B RTF, OpenDocument, ODT+.B RTF, OpenDocument It will be rendered, if possible, using Unicode characters, and will otherwise appear verbatim. .RS .RE .TP+.B ODT+It will be rendered, if possible, using MathML.+.RS+.RE+.TP .B DocBook If the \f[C]\-\-mathml\f[] flag is used, it will be rendered using MathML in an \f[C]inlineequation\f[] or \f[C]informalequation\f[] tag.@@ -3560,7 +3723,9 @@ converted to \f[C]<img>\f[] tags that link to an external script that converts formulas to images. The formula will be URL\-encoded and concatenated with the URL provided.-If no URL is specified, the CodeCogs will be used+For SVG images you can for example use+\f[C]\-\-webtex\ https://latex.codecogs.com/svg.latex?\f[].+If no URL is specified, the CodeCogs URL generating PNGs will be used (\f[C]https://latex.codecogs.com/png.latex?\f[]). .IP "7." 3 If the \f[C]\-\-mathjax\f[] option is used, TeX math will be displayed@@ -3642,7 +3807,49 @@ For the most part this should give the same output as \f[C]raw_html\f[], but it makes it easier to write pandoc filters to manipulate groups of inlines.-.SS Raw TeX+.SS Extension: \f[C]fenced_divs\f[]+.PP+Allow special fenced syntax for native \f[C]Div\f[] blocks.+A Div starts with a fence containing at least three consecutive colons+plus some attributes.+The attributes may optionally be followed by another string of+consecutive colons.+The attribute syntax is exactly as in fenced code blocks (see+[Extension\-fenced_code_attributes], above).+As with fenced code blocks, one can use either attributes in curly+braces or a single unbraced word, which will be treated as a class name.+The Div ends with another line containing a string of at least three+consecutive colons.+The fenced Div should be separated by blank lines from preceding and+following blocks.+.PP+Example:+.IP+.nf+\f[C]+:::::\ {#special\ .sidebar}+Here\ is\ a\ paragraph.++And\ another.+:::::+\f[]+.fi+.PP+Fenced divs can be nested.+Opening fences are distinguished because they \f[I]must\f[] have+attributes:+.IP+.nf+\f[C]+:::\ Warning\ ::::::+This\ is\ a\ warning.++:::\ Danger+This\ is\ a\ warning\ within\ a\ warning.+:::+::::::::::::::::::+\f[]+.fi .SS Extension: \f[C]raw_tex\f[] .PP In addition to raw HTML, pandoc allows raw LaTeX, TeX, and ConTeXt to be@@ -3675,6 +3882,40 @@ .PP Inline LaTeX is ignored in output formats other than Markdown, LaTeX, Emacs Org mode, and ConTeXt.+.SS Generic raw attribute+.SS Extension: \f[C]raw_attribute\f[]+.PP+Inline spans and fenced code blocks with a special kind of attribute+will be parsed as raw content with the designated format.+For example, the following produces a raw groff \f[C]ms\f[] block:+.IP+.nf+\f[C]+```{=ms}+\&.MYMACRO+blah\ blah+```+\f[]+.fi+.PP+And the following produces a raw \f[C]html\f[] inline element:+.IP+.nf+\f[C]+This\ is\ `<a>html</a>`{=html}+\f[]+.fi+.PP+The format name should match the target format name (see+\f[C]\-t/\-\-to\f[], above, for a list, or use+\f[C]pandoc\ \-\-list\-output\-formats\f[]).+.PP+This extension presupposes that the relevant kind of inline code or+fenced code block is enabled.+Thus, for example, to use a raw attribute with a backtick code block,+\f[C]backtick_code_blocks\f[] must be enabled.+.PP+The raw attribute cannot be combined with regular attributes. .SS LaTeX macros .SS Extension: \f[C]latex_macros\f[] .PP@@ -3742,10 +3983,11 @@ .PP The link consists of link text in square brackets, followed by a label in square brackets.-(There can be space between the two.) The link definition consists of-the bracketed label, followed by a colon and a space, followed by the-URL, and optionally (after a space) a link title either in quotes or in-parentheses.+(There cannot be space between the two unless the+\f[C]spaced_reference_links\f[] extension is enabled.) The link+definition consists of the bracketed label, followed by a colon and a+space, followed by the URL, and optionally (after a space) a link title+either in quotes or in parentheses. The label must not be parseable as a citation (assuming the \f[C]citations\f[] extension is enabled): citations take precedence over link labels.@@ -3866,10 +4108,8 @@ .fi .SS Extension: \f[C]implicit_figures\f[] .PP-An image occurring by itself in a paragraph will be rendered as a figure-with a caption. (In LaTeX, a figure environment will be used; in HTML,-the image will be placed in a \f[C]div\f[] with class \f[C]figure\f[],-together with a caption in a \f[C]p\f[] with class \f[C]caption\f[].)+An image with nonempty alt text, occurring by itself in a paragraph,+will be rendered as a figure with a caption. The image's alt text will be used as the caption. .IP .nf@@ -3878,6 +4118,11 @@ \f[] .fi .PP+How this is rendered depends on the output format.+Some output formats (e.g.\ RTF) do not yet support figures.+In those formats, you'll just get an image in a paragraph by itself,+with no caption.+.PP If you just want a regular inline image, just make sure it is not the only thing in the paragraph. One way to do this is to insert a nonbreaking space after the image:@@ -3887,6 +4132,10 @@ ![This\ image\ won\[aq]t\ be\ a\ figure](/url/of/image.png)\\\  \f[] .fi+.PP+Note that in reveal.js slide shows, an image in a paragraph by itself+that has the \f[C]stretch\f[] class will fill the screen, and the+caption and figure tags will be omitted. .SS Extension: \f[C]link_attributes\f[] .PP Attributes can be set on links and images:@@ -4006,6 +4255,31 @@ .fi .PP Inline and regular footnotes may be mixed freely.+.SS Typography+.SS Extension: \f[C]smart\f[]+.PP+Interpret straight quotes as curly quotes, \f[C]\-\-\-\f[] as+em\-dashes, \f[C]\-\-\f[] as en\-dashes, and \f[C]\&...\f[] as ellipses.+Nonbreaking spaces are inserted after certain abbreviations, such as+\[lq]Mr.\[rq] This option currently affects the input formats+\f[C]markdown\f[], \f[C]commonmark\f[], \f[C]latex\f[],+\f[C]mediawiki\f[], \f[C]org\f[], \f[C]rst\f[], and \f[C]twiki\f[], and+the output formats \f[C]markdown\f[], \f[C]latex\f[], and+\f[C]context\f[].+.PP+Note: If you are \f[I]writing\f[] Markdown, then the \f[C]smart\f[]+extension has the reverse effect: what would have been curly quotes+comes out straight.+.PP+In LaTeX, \f[C]smart\f[] means to use the standard TeX ligatures for+quotation marks (\f[C]``\f[] and \f[C]\[aq]\[aq]\f[] for double quotes,+\f[C]`\f[] and \f[C]\[aq]\f[] for single quotes) and dashes+(\f[C]\-\-\f[] for en\-dash and \f[C]\-\-\-\f[] for em\-dash).+If \f[C]smart\f[] is disabled, then in reading LaTeX pandoc will parse+these characters literally.+In writing LaTeX, enabling \f[C]smart\f[] tells pandoc to use the+ligatures when possible; if \f[C]smart\f[] is disabled pandoc will use+unicode quotation mark and dash characters. .SS Citations .SS Extension: \f[C]citations\f[] .PP@@ -4311,6 +4585,13 @@ name, where \f[C]EXTENSION\f[] is the name of the extension. Thus, for example, \f[C]markdown+hard_line_breaks\f[] is Markdown with hard line breaks.+.SS Extension: \f[C]old_dashes\f[]+.PP+Selects the pandoc <= 1.8.2.1 behavior for parsing smart dashes:+\f[C]\-\f[] before a numeral is an en\-dash, and \f[C]\-\-\f[] is an+em\-dash.+This option only has an effect if \f[C]smart\f[] is enabled.+It is selected automatically for \f[C]textile\f[] input. .SS Extension: \f[C]angle_brackets_escapable\f[] .PP Allow \f[C]<\f[] and \f[C]>\f[] to be backslash\-escaped, as they can be@@ -4320,6 +4601,20 @@ .PP Allow a list to occur right after a paragraph, with no intervening blank space.+.SS Extension: \f[C]four_space_rule\f[]+.PP+Selects the pandoc <= 2.0 behavior for parsing lists, so that four+spaces indent are needed for list item continuation paragraphs.+.SS Extension: \f[C]spaced_reference_links\f[]+.PP+Allow whitespace between the two components of a reference link, for+example,+.IP+.nf+\f[C]+[foo]\ [bar].+\f[]+.fi .SS Extension: \f[C]hard_line_breaks\f[] .PP Causes all newlines within a paragraph to be interpreted as hard line@@ -4445,17 +4740,19 @@ \f[C]markdown_attribute\f[], \f[C]fenced_code_blocks\f[], \f[C]definition_lists\f[], \f[C]intraword_underscores\f[], \f[C]header_attributes\f[], \f[C]link_attributes\f[],-\f[C]abbreviations\f[], \f[C]shortcut_reference_links\f[].+\f[C]abbreviations\f[], \f[C]shortcut_reference_links\f[],+\f[C]spaced_reference_links\f[]. .RS .RE .TP-.B \f[C]markdown_github\f[] (GitHub\-Flavored Markdown)+.B \f[C]markdown_github\f[] (deprecated GitHub\-Flavored Markdown) \f[C]pipe_tables\f[], \f[C]raw_html\f[], \f[C]fenced_code_blocks\f[],-\f[C]auto_identifiers\f[], \f[C]ascii_identifiers\f[],+\f[C]gfm_auto_identifiers\f[], \f[C]ascii_identifiers\f[], \f[C]backtick_code_blocks\f[], \f[C]autolink_bare_uris\f[],-\f[C]intraword_underscores\f[], \f[C]strikeout\f[],-\f[C]hard_line_breaks\f[], \f[C]emoji\f[],-\f[C]shortcut_reference_links\f[], \f[C]angle_brackets_escapable\f[].+\f[C]space_in_atx_header\f[], \f[C]intraword_underscores\f[],+\f[C]strikeout\f[], \f[C]emoji\f[], \f[C]shortcut_reference_links\f[],+\f[C]angle_brackets_escapable\f[],+\f[C]lists_without_preceding_blankline\f[]. .RS .RE .TP@@ -4466,14 +4763,36 @@ \f[C]footnotes\f[], \f[C]definition_lists\f[], \f[C]all_symbols_escapable\f[], \f[C]implicit_header_references\f[], \f[C]auto_identifiers\f[], \f[C]mmd_header_identifiers\f[],-\f[C]shortcut_reference_links\f[].+\f[C]shortcut_reference_links\f[], \f[C]implicit_figures\f[],+\f[C]superscript\f[], \f[C]subscript\f[], \f[C]backtick_code_blocks\f[],+\f[C]spaced_reference_links\f[], \f[C]raw_attribute\f[]. .RS .RE .TP .B \f[C]markdown_strict\f[] (Markdown.pl)-\f[C]raw_html\f[]+\f[C]raw_html\f[], \f[C]shortcut_reference_links\f[],+\f[C]spaced_reference_links\f[]. .RS .RE+.PP+We also support \f[C]gfm\f[] (GitHub\-Flavored Markdown) as a set of+extensions on \f[C]commonmark\f[]:+.PP+: \f[C]pipe_tables\f[], \f[C]raw_html\f[], \f[C]fenced_code_blocks\f[],+\f[C]auto_identifiers\f[], \f[C]ascii_identifiers\f[],+\f[C]backtick_code_blocks\f[], \f[C]autolink_bare_uris\f[],+\f[C]intraword_underscores\f[], \f[C]strikeout\f[],+\f[C]hard_line_breaks\f[], \f[C]emoji\f[],+\f[C]shortcut_reference_links\f[], \f[C]angle_brackets_escapable\f[].+.IP+.nf+\f[C]+These\ can\ all\ be\ individually\ disabled.\ Note,\ however,\ that+`commonmark`\ and\ `gfm`\ have\ limited\ support\ for\ extensions:+extensions\ other\ than\ those\ listed\ above\ (and\ `smart`)\ will\ have+no\ effect\ on\ `commonmark`\ or\ `gfm`.+\f[]+.fi .SS Extensions with formats other than Markdown .PP Some of the extensions discussed above can be used with formats other@@ -4593,6 +4912,9 @@ \[lq]title slides,\[rq] which just contain the section title and help to break the slide show into sections. .IP \[bu] 2+Content \f[I]above\f[] the slide level will not appear in the slide+show.+.IP \[bu] 2 A title page is constructed automatically from the document's title block, if present. (In the case of beamer, this can be disabled by commenting out some@@ -4759,6 +5081,8 @@ \ \ text:\ doi:10.234234.234/33 publisher:\ \ My\ Press rights:\ ©\ 2007\ John\ Smith,\ CC\ BY\-NC+ibooks:+\ \ version:\ 1.3.4 \&... \f[] .fi@@ -4863,6 +5187,27 @@ \f[C]spine\f[] element. .RS .RE+.TP+.B \f[C]ibooks\f[]+iBooks\-specific metadata, with the following fields:+.RS+.IP \[bu] 2+\f[C]version\f[]: (string)+.IP \[bu] 2+\f[C]specified\-fonts\f[]: \f[C]true\f[]|\f[C]false\f[] (default+\f[C]false\f[])+.IP \[bu] 2+\f[C]ipad\-orientation\-lock\f[]:+\f[C]portrait\-only\f[]|\f[C]landscape\-only\f[]+.IP \[bu] 2+\f[C]iphone\-orientation\-lock\f[]:+\f[C]portrait\-only\f[]|\f[C]landscape\-only\f[]+.IP \[bu] 2+\f[C]binding\f[]: \f[C]true\f[]|\f[C]false\f[] (default \f[C]true\f[])+.IP \[bu] 2+\f[C]scroll\-axis\f[]:+\f[C]vertical\f[]|\f[C]horizontal\f[]|\f[C]default\f[]+.RE .SS Linked media .PP By default, pandoc will download linked media (including audio and@@ -4887,7 +5232,7 @@ If you append \f[C]+lhs\f[] (or \f[C]+literate_haskell\f[]) to an appropriate input or output format (\f[C]markdown\f[], \f[C]markdown_strict\f[], \f[C]rst\f[], or \f[C]latex\f[] for input or-output; \f[C]beamer\f[], \f[C]html\f[] or \f[C]html5\f[] for output+output; \f[C]beamer\f[], \f[C]html4\f[] or \f[C]html5\f[] for output only), pandoc will treat the document as literate Haskell source. This means that .IP \[bu] 2@@ -4940,12 +5285,16 @@ .PP writes HTML with the Haskell code in bird tracks, so it can be copied and pasted as literate Haskell source.+.PP+Note that GHC expects the bird tracks in the first column, so indentend+literate code blocks (e.g.\ inside an itemized environment) will not be+picked up by the Haskell compiler. .SH SYNTAX HIGHLIGHTING .PP Pandoc will automatically highlight syntax in fenced code blocks that are marked with a language name.-The Haskell library highlighting\-kate is used for highlighting, which-works in HTML, Docx, and LaTeX/PDF output.+The Haskell library skylighting is used for highlighting, which works in+HTML, Docx, Ms, and LaTeX/PDF output. To see a list of language names that pandoc will recognize, type \f[C]pandoc\ \-\-list\-highlight\-languages\f[]. .PP@@ -5038,55 +5387,11 @@ .fi .SH AUTHORS .PP-© 2006\-2016 John MacFarlane (jgm\@berkeley.edu).+Copyright 2006\-2017 John MacFarlane (jgm\@berkeley.edu). Released under the GPL, version 2 or greater. This software carries no warranty of any kind.-(See COPYRIGHT for full copyright and warranty notices.)-.PP-Contributors include Arata Mizuki, Aaron Wolen, Albert Krewinkel, Alex-Ivkin, Alex Vong, Alexander Kondratskiy, Alexander Sulfrian, Alexander V-Vershilov, Alfred Wechselberger, Andreas Lööw, Andrew Dunning, Antoine-Latter, Arata Mizuki, Arlo O'Keeffe, Artyom Kazak, B.-Scott Michel, Ben Gamari, Beni Cherniavsky\-Paskin, Benoit Schweblin,-Bjorn Buckwalter, Bradley Kuhn, Brent Yorgey, Bryan O'Sullivan, Caleb-McDaniel, Calvin Beck, Carlos Sosa, Chris Black, Christian Conkle,-Christoffer Ackelman, Christoffer Sawicki, Clare Macrae, Clint Adams,-Conal Elliott, Craig S.-Bosma, Daniel Bergey, Daniel T.-Staal, Daniele D'Orazio, David Lazar, David Röthlisberger, Denis-Laxalde, Douglas Calvert, Emanuel Evans, Emily Eisenberg, Eric Kow, Eric-Seidel, Felix Yan, Florian Eitel, François Gannaz, Freiric Barral,-Freirich Raabe, Frerich Raabe, Fyodor Sheremetyev, Gabor Pali, Gavin-Beatty, Gottfried Haider, Greg Maslov, Greg Rundlett, Grégory Bataille,-Gwern Branwen, Hans\-Peter Deifel, Henrik Tramberend, Henry de Valence,-Hubert Plociniczak, Ilya V.-Portnov, Ivo Clarysse, J.-Lewis Muir, Jaime Marquínez Ferrándiz, Jakob Voß, James Aspnes, Jamie F.-Olson, Jan Larres, Jan Schulz, Jason Ronallo, Jeff Arnold, Jeff-Runningen, Jens Petersen, Jesse Rosenthal, Joe Hillenbrand, John-MacFarlane, John Muccigrosso, Jonas Smedegaard, Jonathan Daugherty, Jose-Luis Duran, Josef Svenningsson, Julien Cretel, Juliusz Gonera, Justin-Bogner, Jérémy Bobbio, Kelsey Hightower, Kolen Cheung, Konstantin Zudov,-Kristof Bastiaensen, Lars\-Dominik Braun, Luke Plant, Mark Szepieniec,-Mark Wright, Martin Linn, Masayoshi Takahashi, Matej Kollar, Mathias-Schenner, Mathieu Duponchelle, Matthew Eddey, Matthew Pickering,-Matthias C.-M.-Troffaes, Mauro Bieg, Max Bolingbroke, Max Rydahl Andersen, Merijn-Verstraaten, Michael Beaumont, Michael Chladek, Michael Snoyman, Michael-Thompson, MinRK, Morton Fox, Nathan Gass, Neil Mayhew, Nick Bart,-Nicolas Kaiser, Nikolay Yakimov, Oliver Matthews, Ophir Lifshitz, Pablo-Rodríguez, Paul Rivier, Paulo Tanimoto, Peter Wang, Philippe Ombredanne,-Phillip Alday, Prayag Verma, Puneeth Chaganti, Ralf Stephan, Raniere-Silva, Recai Oktaş, RyanGlScott, Scott Morrison, Sergei Trofimovich,-Sergey Astanin, Shahbaz Youssefi, Shaun Attfield, Sidarth Kapur,-Sidharth Kapur, Simon Hengel, Sumit Sahrawat, Thomas Hodgson, Thomas-Weißschuh, Tim Lin, Timothy Humphries, Tiziano Müller, Todd Sifleet, Tom-Leese, Uli Köhler, Václav Zeman, Viktor Kronvall, Vincent, Václav-Haisman, Václav Zeman, Wandmalfarbe, Waldir Pimenta, Wikiwide, Xavier-Olive, bumper314, csforste, infinity0x, nkalvi, qerub, robabla,-roblabla, rodja.trappe, rski, shreevatsa.public, takahashim, tgkokk,-thsutton.+(See COPYRIGHT for full copyright and warranty notices.) For a full list+of contributors, see the file AUTHORS.md in the pandoc source code. .PP The Pandoc source code and all documentation may be downloaded from <http://pandoc.org>.
pandoc.cabal view
@@ -1,31 +1,32 @@-Name:            pandoc-Version:         1.19.2.4-Cabal-Version:   >= 1.10-Build-Type:      Custom-License:         GPL-License-File:    COPYING.md-Copyright:       (c) 2006-2017 John MacFarlane-Author:          John MacFarlane <jgm@berkeley.edu>-Maintainer:      John MacFarlane <jgm@berkeley.edu>-Bug-Reports:     https://github.com/jgm/pandoc/issues-Stability:       alpha-Homepage:        http://pandoc.org-Category:        Text-Tested-With:     GHC == 7.8.4, GHC == 7.10.2, GHC == 8.0.1-Synopsis:        Conversion between markup formats-Description:     Pandoc is a Haskell library for converting from one markup+name:            pandoc+version:         2.0+cabal-version:   >= 1.10+build-type:      Custom+license:         GPL+license-file:    COPYING.md+copyright:       (c) 2006-2017 John MacFarlane+author:          John MacFarlane <jgm@berkeley.edu>+maintainer:      John MacFarlane <jgm@berkeley.edu>+bug-reports:     https://github.com/jgm/pandoc/issues+stability:       alpha+homepage:        http://pandoc.org+category:        Text+tested-with:     GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.2, GHC == 8.2.1+synopsis:        Conversion between markup formats+description:     Pandoc is a Haskell library for converting from one markup                  format to another, and a command-line tool that uses                  this library. It can read several dialects of Markdown and                  (subsets of) HTML, reStructuredText, LaTeX, DocBook,-                 MediaWiki markup, TWiki markup, Haddock markup, OPML,-                 Emacs Org-Mode, txt2tags, Word Docx, ODT, and Textile, and-                 it can write Markdown, reStructuredText, XHTML, HTML 5,-                 LaTeX, ConTeXt, DocBook, OPML, TEI, OpenDocument, ODT,-                 Word docx, RTF, MediaWiki, DokuWiki, ZimWiki, Textile,-                 groff man pages, plain text, Emacs Org-Mode, AsciiDoc,-                 Haddock markup, EPUB (v2 and v3), FictionBook2, InDesign ICML,-                 and several kinds of HTML/javascript slide shows (S5, Slidy,-                 Slideous, DZSlides, reveal.js).+                 MediaWiki markup, TWiki markup, TikiWiki markup, Creole 1.0,+                 Haddock markup, OPML, Emacs Org-Mode, Emacs Muse, txt2tags,+                 Vimwiki, Word Docx, ODT, and Textile, and it can write+                 Markdown, reStructuredText, XHTML, HTML 5, LaTeX, ConTeXt,+                 DocBook, JATS, OPML, TEI, OpenDocument, ODT, Word docx,+                 RTF, MediaWiki, DokuWiki, ZimWiki, Textile, groff man,+                 groff ms, plain text, Emacs Org-Mode, AsciiDoc,+                 Haddock markup, EPUB (v2 and v3), FictionBook2, InDesign+                 ICML, Muse, and several kinds of HTML/JavaScript slide+                 shows (S5, Slidy, Slideous, DZSlides, reveal.js).                  .                  In contrast to most existing tools for converting Markdown                  to HTML, pandoc has a modular design: it consists of a set of@@ -34,14 +35,14 @@                  which convert this native representation into a target                  format. Thus, adding an input or output format requires                  only adding a reader or writer.-Data-Files:+data-files:                  -- templates-                 data/templates/default.html+                 data/templates/default.html4                  data/templates/default.html5-                 data/templates/default.docbook+                 data/templates/default.docbook4                  data/templates/default.docbook5+                 data/templates/default.jats                  data/templates/default.tei-                 data/templates/default.beamer                  data/templates/default.opendocument                  data/templates/default.icml                  data/templates/default.opml@@ -49,7 +50,9 @@                  data/templates/default.context                  data/templates/default.texinfo                  data/templates/default.man+                 data/templates/default.ms                  data/templates/default.markdown+                 data/templates/default.muse                  data/templates/default.commonmark                  data/templates/default.rst                  data/templates/default.plain@@ -66,8 +69,10 @@                  data/templates/default.haddock                  data/templates/default.textile                  data/templates/default.org-                 data/templates/default.epub+                 data/templates/default.epub2                  data/templates/default.epub3+                 -- translations+                 data/translations/*.yaml                  -- source files for reference.docx                  data/docx/[Content_Types].xml                  data/docx/_rels/.rels@@ -99,15 +104,24 @@                  data/LaTeXMathML.js                  -- data for dzslides writer                  data/dzslides/template.html+                 -- default abbreviations file+                 data/abbreviations                  -- sample lua custom writer                  data/sample.lua+                 -- pandoc lua module+                 data/pandoc.lua+                 -- sample highlighting theme+                 data/default.theme                  -- bash completion template                  data/bash_completion.tpl+                 -- jats csl+                 data/jats.csl                  -- documentation                  MANUAL.txt, COPYRIGHT-Extra-Source-Files:+extra-source-files:                  -- documentation-                 INSTALL.md, BUGS, README.md, CONTRIBUTING.md, changelog+                 INSTALL.md, AUTHORS.md, README.md,+                 CONTRIBUTING.md, BUGS, changelog,                  man/pandoc.1                  -- stack build plan                  stack.yaml@@ -120,166 +134,193 @@                  trypandoc/Makefile                  trypandoc/index.html                  -- tests-                 tests/bodybg.gif-                 tests/*.native-                 tests/docbook-reader.docbook-                 tests/docbook-xref.docbook-                 tests/html-reader.html-                 tests/opml-reader.opml-                 tests/haddock-reader.haddock-                 tests/insert-                 tests/lalune.jpg-                 tests/movie.jpg-                 tests/media/rId25.jpg-                 tests/media/rId26.jpg-                 tests/media/rId27.jpg-                 tests/latex-reader.latex-                 tests/textile-reader.textile-                 tests/markdown-reader-more.txt-                 tests/markdown-citations.txt-                 tests/textile-reader.textile-                 tests/mediawiki-reader.wiki-                 tests/rst-reader.rst-                 tests/s5-basic.html-                 tests/s5-fancy.html-                 tests/s5-fragment.html-                 tests/s5-inserts.html-                 tests/tables.context-                 tests/tables.docbook-                 tests/tables.docbook5-                 tests/tables.dokuwiki-                 tests/tables.zimwiki-                 tests/tables.icml-                 tests/tables.html-                 tests/tables.latex-                 tests/tables.man-                 tests/tables.plain-                 tests/tables.markdown-                 tests/tables.mediawiki-                 tests/tables.tei-                 tests/tables.textile-                 tests/tables.opendocument-                 tests/tables.org-                 tests/tables.asciidoc-                 tests/tables.haddock-                 tests/tables.texinfo-                 tests/tables.rst-                 tests/tables.rtf-                 tests/tables.txt-                 tests/tables.fb2-                 tests/testsuite.txt-                 tests/writer.latex-                 tests/writer.context-                 tests/writer.docbook-                 tests/writer.docbook5-                 tests/writer.html-                 tests/writer.man-                 tests/writer.markdown-                 tests/writer.plain-                 tests/writer.mediawiki-                 tests/writer.textile-                 tests/writer.opendocument-                 tests/writer.org-                 tests/writer.asciidoc-                 tests/writer.haddock-                 tests/writer.rst-                 tests/writer.icml-                 tests/writer.rtf-                 tests/writer.tei-                 tests/writer.texinfo-                 tests/writer.fb2-                 tests/writer.opml-                 tests/writer.dokuwiki-                 tests/writer.zimwiki-                 tests/writers-lang-and-dir.latex-                 tests/writers-lang-and-dir.context-                 tests/dokuwiki_inline_formatting.dokuwiki-                 tests/lhs-test.markdown-                 tests/lhs-test.markdown+lhs-                 tests/lhs-test.rst-                 tests/lhs-test.rst+lhs-                 tests/lhs-test.latex-                 tests/lhs-test.latex+lhs-                 tests/lhs-test.html-                 tests/lhs-test.html+lhs-                 tests/lhs-test.fragment.html+lhs-                 tests/pipe-tables.txt-                 tests/dokuwiki_external_images.dokuwiki-                 tests/dokuwiki_external_images.native-                 tests/dokuwiki_multiblock_table.dokuwiki-                 tests/dokuwiki_multiblock_table.native-                 tests/fb2/*.markdown-                 tests/fb2/*.fb2-                 tests/fb2/images-embedded.html-                 tests/fb2/images-embedded.fb2-                 tests/fb2/test-small.png-                 tests/fb2/test.jpg-                 tests/docx/*.docx-                 tests/docx/*.native-                 tests/epub/*.epub-                 tests/epub/*.native-                 tests/txt2tags.t2t-                 tests/twiki-reader.twiki-                 tests/odt/odt/*.odt-                 tests/odt/markdown/*.md-                 tests/odt/native/*.native-Source-repository head+                 test/bodybg.gif+                 test/*.native+                 test/command/*.md+                 test/command/3533-rst-csv-tables.csv+                 test/command/3880.txt+                 test/command/abbrevs+                 test/command/SVG_logo-without-xml-declaration.svg+                 test/command/SVG_logo.svg+                 test/command/corrupt.svg+                 test/command/inkscape-cube.svg+                 test/command/sub-file-chapter-1.tex+                 test/command/sub-file-chapter-2.tex+                 test/command/3510-subdoc.org+                 test/command/3510-export.latex+                 test/command/3510-src.hs+                 test/command/3971b.tex+                 test/docbook-reader.docbook+                 test/docbook-xref.docbook+                 test/html-reader.html+                 test/opml-reader.opml+                 test/haddock-reader.haddock+                 test/insert+                 test/lalune.jpg+                 test/movie.jpg+                 test/media/rId25.jpg+                 test/media/rId26.jpg+                 test/media/rId27.jpg+                 test/latex-reader.latex+                 test/textile-reader.textile+                 test/markdown-reader-more.txt+                 test/markdown-citations.txt+                 test/textile-reader.textile+                 test/mediawiki-reader.wiki+                 test/vimwiki-reader.wiki+                 test/creole-reader.txt+                 test/creole-reader.native+                 test/rst-reader.rst+                 test/s5-basic.html+                 test/s5-fancy.html+                 test/s5-fragment.html+                 test/s5-inserts.html+                 test/tables.context+                 test/tables.docbook4+                 test/tables.docbook5+                 test/tables.jats+                 test/tables.dokuwiki+                 test/tables.zimwiki+                 test/tables.icml+                 test/tables.html4+                 test/tables.html5+                 test/tables.latex+                 test/tables.man+                 test/tables.ms+                 test/tables.plain+                 test/tables.markdown+                 test/tables.mediawiki+                 test/tables.tei+                 test/tables.textile+                 test/tables.opendocument+                 test/tables.org+                 test/tables.asciidoc+                 test/tables.haddock+                 test/tables.texinfo+                 test/tables.rst+                 test/tables.rtf+                 test/tables.txt+                 test/tables.fb2+                 test/tables.muse+                 test/testsuite.txt+                 test/writer.latex+                 test/writer.context+                 test/writer.docbook4+                 test/writer.docbook5+                 test/writer.jats+                 test/writer.html4+                 test/writer.html5+                 test/writer.man+                 test/writer.ms+                 test/writer.markdown+                 test/writer.plain+                 test/writer.mediawiki+                 test/writer.textile+                 test/writer.opendocument+                 test/writer.org+                 test/writer.asciidoc+                 test/writer.haddock+                 test/writer.rst+                 test/writer.icml+                 test/writer.rtf+                 test/writer.tei+                 test/writer.texinfo+                 test/writer.fb2+                 test/writer.opml+                 test/writer.dokuwiki+                 test/writer.zimwiki+                 test/writer.muse+                 test/writers-lang-and-dir.latex+                 test/writers-lang-and-dir.context+                 test/dokuwiki_inline_formatting.dokuwiki+                 test/lhs-test.markdown+                 test/lhs-test.markdown+lhs+                 test/lhs-test.rst+                 test/lhs-test.rst+lhs+                 test/lhs-test.latex+                 test/lhs-test.latex+lhs+                 test/lhs-test.html+                 test/lhs-test.html+lhs+                 test/lhs-test.fragment.html+lhs+                 test/pipe-tables.txt+                 test/dokuwiki_external_images.dokuwiki+                 test/dokuwiki_external_images.native+                 test/dokuwiki_multiblock_table.dokuwiki+                 test/dokuwiki_multiblock_table.native+                 test/fb2/*.markdown+                 test/fb2/*.fb2+                 test/fb2/images-embedded.html+                 test/fb2/images-embedded.fb2+                 test/fb2/test-small.png+                 test/fb2/test.jpg+                 test/docx/*.docx+                 test/docx/*.native+                 test/epub/*.epub+                 test/epub/*.native+                 test/txt2tags.t2t+                 test/twiki-reader.twiki+                 test/tikiwiki-reader.tikiwiki+                 test/odt/odt/*.odt+                 test/odt/markdown/*.md+                 test/odt/native/*.native+                 test/lua/*.lua+source-repository head   type:          git   location:      git://github.com/jgm/pandoc.git -Flag embed_data_files+flag static+  Description:   Use static linking for pandoc executable.+  Default:       False++flag embed_data_files   Description:   Embed data files in binary for relocatable executable.   Default:       False -Flag trypandoc+flag trypandoc   Description:   Build trypandoc cgi executable.   Default:       False -Flag weigh-pandoc+flag weigh-pandoc   Description:   Build weigh-pandoc to measure memory usage.   Default:       False -Flag https-  Description:   Enable support for downloading of resources over https.-  Default:       True--Flag network-uri+flag network-uri   Description:   Get Network.URI from the network-uri package   Default:       True -Flag old-locale+flag old-locale   Description:   Use old-locale and time < 1.5   Default:       False  custom-setup-  setup-depends: base,-                 Cabal+  setup-depends: base, Cabal -Library-  Build-Depends: base >= 4.7 && <5,+library+  build-depends: base >= 4.7 && < 5,                  syb >= 0.1 && < 0.8,-                 containers >= 0.1 && < 0.6,+                 containers >= 0.4.2.1 && < 0.6,                  unordered-containers >= 0.2 && < 0.3,-                 array >= 0.3 && < 0.6,                  parsec >= 3.1 && < 3.2,                  mtl >= 2.2 && < 2.3,                  filepath >= 1.1 && < 1.5,-                 process >= 1 && < 1.7,+                 process >= 1.2.3 && < 1.7,                  directory >= 1 && < 1.4,                  bytestring >= 0.9 && < 0.11,                  text >= 0.11 && < 1.3,+                 safe >= 0.3 && < 0.4,                  zip-archive >= 0.2.3.4 && < 0.4,                  HTTP >= 4000.0.5 && < 4000.4,-                 texmath >= 0.9 && < 0.10,+                 texmath >= 0.9.4.1 && < 0.10,                  xml >= 1.3.12 && < 1.4,+                 split >= 0.2 && < 0.3,                  random >= 1 && < 1.2,-                 extensible-exceptions >= 0.1 && < 0.2,-                 pandoc-types >= 1.17 && < 1.17.1,+                 pandoc-types >= 1.17.2 && < 1.18,                  aeson >= 0.7 && < 1.3,+                 aeson-pretty >= 0.8 && < 0.9,                  tagsoup >= 0.13.7 && < 0.15,                  base64-bytestring >= 0.1 && < 1.1,                  zlib >= 0.5 && < 0.7,-                 skylighting >= 0.1.1.4 && < 0.2,+                 skylighting >= 0.4.2 && <0.5,                  data-default >= 0.4 && < 0.8,                  temporary >= 1.1 && < 1.3,                  blaze-html >= 0.5 && < 0.10,@@ -287,75 +328,85 @@                  yaml >= 0.8.8.2 && < 0.9,                  scientific >= 0.2 && < 0.4,                  vector >= 0.10 && < 0.13,-                 hslua >= 0.3 && < 0.5,-                 binary >= 0.5 && < 0.10,+                 hslua >= 0.9 && < 0.10,+                 binary >= 0.5 && < 0.9,                  SHA >= 1.6 && < 1.7,                  haddock-library >= 1.1 && < 1.5,-                 old-time,                  deepseq >= 1.3 && < 1.5,                  JuicyPixels >= 3.1.6.1 && < 3.3,-                 filemanip >= 0.3 && < 0.4,-                 cmark >= 0.5 && < 0.6,-                 doctemplates >= 0.1 && < 0.2,-                 ghc-prim >= 0.2+                 Glob >= 0.7 && < 0.10,+                 cmark-gfm >= 0.1.1 && < 0.2,+                 doctemplates >= 0.2.1 && < 0.3,+                 http-client >= 0.4.30 && < 0.6,+                 http-client-tls >= 0.2.4 && < 0.4,+                 http-types >= 0.8 && < 0.10,+                 case-insensitive >= 1.2 && < 1.3+  if os(windows)+    cpp-options:      -D_WINDOWS+  else+    build-depends:  unix >= 2.4 && < 2.8   if flag(old-locale)-     Build-Depends: old-locale >= 1 && < 1.1,+     build-depends: old-locale >= 1 && < 1.1,                     time >= 1.2 && < 1.5   else-     Build-Depends: time >= 1.5 && < 1.9+     build-depends: time >= 1.5 && < 1.9   if flag(network-uri)-     Build-Depends: network-uri >= 2.6 && < 2.7, network >= 2.6+     build-depends: network-uri >= 2.6 && < 2.7, network >= 2.6   else-     Build-Depends: network >= 2 && < 2.6-  if flag(https)-     Build-Depends: http-client >= 0.4.30 && < 0.6,-                    http-client-tls >= 0.2.4 && < 0.4,-                    http-types >= 0.8 && < 0.10-     cpp-options:   -DHTTP_CLIENT+     build-depends: network >= 2 && < 2.6   if flag(embed_data_files)      cpp-options:   -DEMBED_DATA_FILES-     Build-Tools:   hsb2hs >= 0.3.1+     build-depends: file-embed >= 0.0 && < 0.1      other-modules: Text.Pandoc.Data   if os(windows)-    Cpp-options:      -D_WINDOWS-  Ghc-Options:   -Wall -fno-warn-unused-do-bind-  Ghc-Prof-Options: -fprof-auto-exported-  Default-Language: Haskell98-  Other-Extensions:   PatternGuards, OverloadedStrings,+    cpp-options:      -D_WINDOWS+  ghc-options:   -Wall -fno-warn-unused-do-bind+  ghc-prof-options: -fprof-auto-exported+  default-language: Haskell98+  other-extensions:   PatternGuards, OverloadedStrings,                       ScopedTypeVariables, GeneralizedNewtypeDeriving,                       RelaxedPolyRec, DeriveDataTypeable, TypeSynonymInstances,                       FlexibleInstances-  Hs-Source-Dirs:  src+  hs-source-dirs:  src   if impl(ghc < 7.10)-     Hs-Source-Dirs: prelude-     Other-Modules:  Prelude+     hs-source-dirs: prelude+     other-modules:  Prelude -  Exposed-Modules: Text.Pandoc,+  exposed-modules: Text.Pandoc,+                   Text.Pandoc.App,                    Text.Pandoc.Options,+                   Text.Pandoc.Extensions,                    Text.Pandoc.Pretty,                    Text.Pandoc.Shared,                    Text.Pandoc.MediaBag,                    Text.Pandoc.Error,+                   Text.Pandoc.Readers,                    Text.Pandoc.Readers.HTML,                    Text.Pandoc.Readers.LaTeX,+                   Text.Pandoc.Readers.LaTeX.Types,                    Text.Pandoc.Readers.Markdown,                    Text.Pandoc.Readers.CommonMark,+                   Text.Pandoc.Readers.Creole,                    Text.Pandoc.Readers.MediaWiki,+                   Text.Pandoc.Readers.Vimwiki,                    Text.Pandoc.Readers.RST,                    Text.Pandoc.Readers.Org,                    Text.Pandoc.Readers.DocBook,                    Text.Pandoc.Readers.OPML,-                   Text.Pandoc.Readers.TeXMath,                    Text.Pandoc.Readers.Textile,                    Text.Pandoc.Readers.Native,                    Text.Pandoc.Readers.Haddock,                    Text.Pandoc.Readers.TWiki,+                   Text.Pandoc.Readers.TikiWiki,                    Text.Pandoc.Readers.Txt2Tags,                    Text.Pandoc.Readers.Docx,                    Text.Pandoc.Readers.Odt,                    Text.Pandoc.Readers.EPUB,+                   Text.Pandoc.Readers.Muse,+                   Text.Pandoc.Writers,                    Text.Pandoc.Writers.Native,                    Text.Pandoc.Writers.Docbook,+                   Text.Pandoc.Writers.JATS,                    Text.Pandoc.Writers.OPML,                    Text.Pandoc.Writers.HTML,                    Text.Pandoc.Writers.ICML,@@ -364,6 +415,7 @@                    Text.Pandoc.Writers.OpenDocument,                    Text.Pandoc.Writers.Texinfo,                    Text.Pandoc.Writers.Man,+                   Text.Pandoc.Writers.Ms,                    Text.Pandoc.Writers.Markdown,                    Text.Pandoc.Writers.CommonMark,                    Text.Pandoc.Writers.Haddock,@@ -381,14 +433,26 @@                    Text.Pandoc.Writers.EPUB,                    Text.Pandoc.Writers.FB2,                    Text.Pandoc.Writers.TEI,+                   Text.Pandoc.Writers.Muse,+                   Text.Pandoc.Writers.Math,+                   Text.Pandoc.Writers.Shared,+                   Text.Pandoc.Lua,                    Text.Pandoc.PDF,                    Text.Pandoc.UTF8,                    Text.Pandoc.Templates,                    Text.Pandoc.XML,                    Text.Pandoc.SelfContained,+                   Text.Pandoc.Highlighting,+                   Text.Pandoc.Logging,                    Text.Pandoc.Process,-                   Text.Pandoc.CSS-  Other-Modules:   Text.Pandoc.Readers.Docx.Lists,+                   Text.Pandoc.MIME,+                   Text.Pandoc.Parsing,+                   Text.Pandoc.Asciify,+                   Text.Pandoc.Emoji,+                   Text.Pandoc.ImageSize,+                   Text.Pandoc.BCP47,+                   Text.Pandoc.Class+  other-modules:   Text.Pandoc.Readers.Docx.Lists,                    Text.Pandoc.Readers.Docx.Combine,                    Text.Pandoc.Readers.Docx.Parse,                    Text.Pandoc.Readers.Docx.Util,@@ -406,127 +470,108 @@                    Text.Pandoc.Readers.Odt.Arrows.Utils,                    Text.Pandoc.Readers.Org.BlockStarts,                    Text.Pandoc.Readers.Org.Blocks,+                   Text.Pandoc.Readers.Org.DocumentTree,                    Text.Pandoc.Readers.Org.ExportSettings,                    Text.Pandoc.Readers.Org.Inlines,                    Text.Pandoc.Readers.Org.Meta,                    Text.Pandoc.Readers.Org.ParserState,                    Text.Pandoc.Readers.Org.Parsing,                    Text.Pandoc.Readers.Org.Shared,-                   Text.Pandoc.Writers.Shared,-                   Text.Pandoc.Asciify,-                   Text.Pandoc.MIME,-                   Text.Pandoc.Emoji,-                   Text.Pandoc.Parsing,+                   Text.Pandoc.Lua.PandocModule,+                   Text.Pandoc.Lua.StackInstances,+                   Text.Pandoc.Lua.Util,+                   Text.Pandoc.CSS,+                   Text.Pandoc.CSV,                    Text.Pandoc.UUID,-                   Text.Pandoc.ImageSize,+                   Text.Pandoc.Translations,                    Text.Pandoc.Slides,-                   Text.Pandoc.Highlighting,                    Text.Pandoc.Compat.Time,                    Paths_pandoc -  Buildable:       True--Executable pandoc-  Build-Depends: pandoc,-                 pandoc-types >= 1.17 && < 1.18,-                 base >= 4.2 && <5,-                 directory >= 1.2 && < 1.4,-                 filepath >= 1.1 && < 1.5,-                 text >= 0.11 && < 1.3,-                 bytestring >= 0.9 && < 0.11,-                 extensible-exceptions >= 0.1 && < 0.2,-                 skylighting >= 0.1.1.5 && < 0.2,-                 aeson >= 0.7.0.5 && < 1.2,-                 yaml >= 0.8.8.2 && < 0.9,-                 containers >= 0.1 && < 0.6,-                 skylighting >= 0.1.1.4 && < 0.2,-                 texmath >= 0.9 && < 0.10,-                 HTTP >= 4000.0.5 && < 4000.4-  if flag(network-uri)-     Build-Depends: network-uri >= 2.6 && < 2.7, network >= 2.6-  else-     Build-Depends: network >= 2 && < 2.6-  Ghc-Options:   -rtsopts -with-rtsopts=-K16m -Wall -fno-warn-unused-do-bind-  Ghc-Prof-Options: -fprof-auto-exported -rtsopts -with-rtsopts=-K16m-  if os(windows)-    Cpp-options:      -D_WINDOWS-  else-    Build-Depends:  unix >= 2.4 && < 2.8+  buildable:       True -  Default-Language: Haskell98-  Other-Extensions: PatternGuards, OverloadedStrings,+executable pandoc+  build-depends: pandoc, base >= 4.7 && < 5+  ghc-options:   -rtsopts -with-rtsopts=-K16m -Wall -fno-warn-unused-do-bind+  ghc-prof-options: -fprof-auto-exported -rtsopts -with-rtsopts=-K16m+  if flag(static)+    ld-options:     -static+  default-language: Haskell98+  other-extensions: PatternGuards, OverloadedStrings,                     ScopedTypeVariables, GeneralizedNewtypeDeriving,                     RelaxedPolyRec, DeriveDataTypeable, TypeSynonymInstances,                     FlexibleInstances-  Hs-Source-Dirs:  .+  hs-source-dirs:  .   if impl(ghc < 7.10)-     Hs-Source-Dirs: prelude-     Other-Modules:  Prelude-  Main-Is:         pandoc.hs-  Buildable:       True-  Other-Modules:   Paths_pandoc+     hs-source-dirs: prelude+     other-modules:  Prelude+  main-is:         pandoc.hs+  buildable:       True+  other-modules:   Paths_pandoc -Executable trypandoc-  Main-Is:         trypandoc.hs-  Hs-Source-Dirs:  trypandoc+executable trypandoc+  main-is:         trypandoc.hs+  hs-source-dirs:  trypandoc   if impl(ghc < 7.10)-     Hs-Source-Dirs: prelude-     Other-Modules:  Prelude+     hs-source-dirs: prelude+     other-modules:  Prelude   default-language: Haskell2010   if flag(trypandoc)-    Build-Depends: base, aeson, pandoc,+    build-depends: base, aeson, pandoc,                    text, wai-extra, wai >= 0.3, http-types-    Buildable:     True+    buildable:     True   else-    Buildable:     False+    buildable:     False -Executable weigh-pandoc-  Main-Is:         weigh-pandoc.hs-  Hs-Source-Dirs:  benchmark+executable weigh-pandoc+  main-is:         weigh-pandoc.hs+  hs-source-dirs:  benchmark   if impl(ghc < 7.10)-     Hs-Source-Dirs: prelude-     Other-Modules:  Prelude+     hs-source-dirs: prelude+     other-modules:  Prelude   if flag(weigh-pandoc)-     Build-Depends:   pandoc,+     build-depends:   pandoc,                       base >= 4.2 && < 5,-                      weigh >= 0.0 && < 0.1-     Buildable:       True+                      text,+                      weigh >= 0.0 && < 0.1,+                      mtl >= 2.2 && < 2.3+     buildable:       True   else-    Buildable:     False-  Ghc-Options:   -rtsopts -Wall -fno-warn-unused-do-bind-  Default-Language: Haskell98+    buildable:     False+  ghc-options:   -rtsopts -Wall -fno-warn-unused-do-bind+  default-language: Haskell98 -Test-Suite test-pandoc-  Type:           exitcode-stdio-1.0-  Main-Is:        test-pandoc.hs-  Hs-Source-Dirs: tests+test-suite test-pandoc+  type:           exitcode-stdio-1.0+  main-is:        test-pandoc.hs+  hs-source-dirs: test   if impl(ghc < 7.10)-     Hs-Source-Dirs: prelude-     Other-Modules:  Prelude-  Build-Depends:  base >= 4.2 && < 5,-                  syb >= 0.1 && < 0.8,+     hs-source-dirs: prelude+     other-modules:  Prelude+  build-depends:  base >= 4.2 && < 5,                   pandoc,-                  pandoc-types >= 1.17 && < 1.18,+                  pandoc-types >= 1.17.2 && < 1.18,                   bytestring >= 0.9 && < 0.11,                   text >= 0.11 && < 1.3,                   directory >= 1 && < 1.4,                   filepath >= 1.1 && < 1.5,-                  process >= 1 && < 1.7,-                  skylighting >= 0.1.1.3 && < 0.2,+                  hslua >= 0.9 && < 0.10,+                  process >= 1.2.3 && < 1.7,+                  temporary >= 1.1 && < 1.3,                   Diff >= 0.2 && < 0.4,-                  test-framework >= 0.3 && < 0.9,-                  test-framework-hunit >= 0.2 && < 0.4,-                  test-framework-quickcheck2 >= 0.2.9 && < 0.4,+                  tasty >= 0.11 && < 0.12,+                  tasty-hunit >= 0.9 && < 0.10,+                  tasty-quickcheck >= 0.8 && < 0.10,+                  tasty-golden >= 2.3 && < 2.4,                   QuickCheck >= 2.4 && < 2.11,-                  HUnit >= 1.2 && < 1.7,-                  containers >= 0.1 && < 0.6,-                  ansi-terminal >= 0.5 && < 0.8,-                  executable-path >= 0.0 && < 0.4,+                  containers >= 0.4.2.1 && < 0.6,+                  executable-path >= 0.0 && < 0.1,                   zip-archive >= 0.2.3.4 && < 0.4-  Other-Modules:  Tests.Old+  other-modules:  Tests.Old+                  Tests.Command                   Tests.Helpers+                  Tests.Lua                   Tests.Shared-                  Tests.Walk                   Tests.Readers.LaTeX                   Tests.Readers.HTML                   Tests.Readers.Markdown@@ -536,30 +581,35 @@                   Tests.Readers.Odt                   Tests.Readers.Txt2Tags                   Tests.Readers.EPUB+                  Tests.Readers.Muse+                  Tests.Readers.Creole                   Tests.Writers.Native                   Tests.Writers.ConTeXt                   Tests.Writers.Docbook                   Tests.Writers.HTML                   Tests.Writers.Markdown+                  Tests.Writers.Org                   Tests.Writers.Plain                   Tests.Writers.AsciiDoc                   Tests.Writers.LaTeX                   Tests.Writers.Docx                   Tests.Writers.RST                   Tests.Writers.TEI-  Ghc-Options:  -rtsopts -Wall -fno-warn-unused-do-bind -threaded-  Default-Language: Haskell98+                  Tests.Writers.Muse+  ghc-options:  -rtsopts -Wall -fno-warn-unused-do-bind -threaded+  default-language: Haskell98  benchmark benchmark-pandoc-  Type:            exitcode-stdio-1.0-  Main-Is:         benchmark-pandoc.hs-  Hs-Source-Dirs:  benchmark+  type:            exitcode-stdio-1.0+  main-is:         benchmark-pandoc.hs+  hs-source-dirs:  benchmark   if impl(ghc < 7.10)-     Hs-Source-Dirs: prelude-     Other-Modules:  Prelude-  Build-Depends:   pandoc,+     hs-source-dirs: prelude+     other-modules:  Prelude+  build-depends:   pandoc,+                   time, bytestring, containers,                    base >= 4.2 && < 5,-                   syb >= 0.1 && < 0.8,+                   text >= 0.11 && < 1.3,                    criterion >= 1.0 && < 1.3-  Ghc-Options:   -rtsopts -Wall -fno-warn-unused-do-bind-  Default-Language: Haskell98+  ghc-options:   -rtsopts -Wall -fno-warn-unused-do-bind+  default-language: Haskell98
pandoc.hs view
@@ -1,1516 +1,38 @@-{-# LANGUAGE CPP, TupleSections, ScopedTypeVariables, PatternGuards #-}-{--Copyright (C) 2006-2016 John MacFarlane <jgm@berkeley.edu>--This program is free software; you can redistribute it and/or modify-it under the terms of the GNU General Public License as published by-the Free Software Foundation; either version 2 of the License, or-(at your option) any later version.--This program is distributed in the hope that it will be useful,-but WITHOUT ANY WARRANTY; without even the implied warranty of-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the-GNU General Public License for more details.--You should have received a copy of the GNU General Public License-along with this program; if not, write to the Free Software-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA--}--{- |-   Module      : Main-   Copyright   : Copyright (C) 2006-2016 John MacFarlane-   License     : GNU GPL, version 2 or above--   Maintainer  : John MacFarlane <jgm@berkeley@edu>-   Stability   : alpha-   Portability : portable--Parses command-line options and calls the appropriate readers and-writers.--}-module Main where-import Text.Pandoc-import Text.Pandoc.Builder (setMeta)-import Text.Pandoc.PDF (makePDF)-import Text.Pandoc.Walk (walk)-import Text.Pandoc.Readers.LaTeX (handleIncludes)-import Text.Pandoc.Shared ( tabFilter, readDataFileUTF8, readDataFile,-                            safeRead, headerShift, normalize, err, warn,-                            openURL )-import Text.Pandoc.MediaBag ( mediaDirectory, extractMediaBag, MediaBag )-import Text.Pandoc.XML ( toEntities )-import Text.Pandoc.SelfContained ( makeSelfContained )-import Text.Pandoc.Process (pipeProcess)-import Skylighting ( defaultSyntaxMap, Syntax(..), Style, tango, pygments,-         espresso, zenburn, kate, haddock, breezeDark, monochrome )-import System.Environment ( getArgs, getProgName, getEnvironment )-import System.Exit ( ExitCode (..), exitSuccess )-import System.FilePath-import System.Console.GetOpt-import qualified Data.Set as Set-import Data.Char ( toLower, toUpper )-import Data.List ( intercalate, isPrefixOf, isSuffixOf, sort )-import System.Directory ( getAppUserDataDirectory, findExecutable,-                          doesFileExist, Permissions(..), getPermissions )-import System.IO ( stdout, stderr )-import System.IO.Error ( isDoesNotExistError )-import qualified Control.Exception as E-import Control.Exception.Extensible ( throwIO )-import qualified Text.Pandoc.UTF8 as UTF8-import Control.Monad (when, unless, (>=>))-import Data.Maybe (fromMaybe, isNothing, isJust)-import Data.Foldable (foldrM)-import Network.URI (parseURI, isURI, URI(..))-import qualified Data.ByteString.Lazy as B-import qualified Data.ByteString as BS-import Data.Aeson (eitherDecode', encode)-import qualified Data.Map as M-import Data.Yaml (decode)-import qualified Data.Yaml as Yaml-import qualified Data.Text as T-import Control.Applicative ((<|>))-import Text.Pandoc.Readers.Txt2Tags (getT2TMeta)-import Paths_pandoc (getDataDir)-import Text.Printf (printf)-#ifndef _WINDOWS-import System.Posix.Terminal (queryTerminal)-import System.Posix.IO (stdOutput)-#endif--type Transform = Pandoc -> Pandoc--copyrightMessage :: String-copyrightMessage = intercalate "\n" [-  "",-  "Copyright (C) 2006-2016 John MacFarlane",-  "Web:  http://pandoc.org",-  "This is free software; see the source for copying conditions.",-  "There is no warranty, not even for merchantability or fitness",-  "for a particular purpose." ]--compileInfo :: String-compileInfo =-  "\nCompiled with pandoc-types " ++ VERSION_pandoc_types ++ ", texmath " ++-  VERSION_texmath ++ ", skylighting " ++ VERSION_skylighting---- | Converts a list of strings into a single string with the items printed as--- comma separated words in lines with a maximum line length.-wrapWords :: Int -> Int -> [String] -> String-wrapWords indent c = wrap' (c - indent) (c - indent)-  where-    wrap'   _       _      []   = ""-    wrap' cols remaining (x:xs)-      | remaining == cols =-            x ++ wrap' cols (remaining - length x) xs-      | (length x + 1) > remaining =-            ",\n" ++ replicate indent ' ' ++ x ++-            wrap' cols (cols - length x) xs-      | otherwise =-            ", "  ++ x ++-            wrap' cols (remaining - length x - 2) xs--isTextFormat :: String -> Bool-isTextFormat s = s `notElem` ["odt","docx","epub","epub3"]--externalFilter :: FilePath -> [String] -> Pandoc -> IO Pandoc-externalFilter f args' d = do-  exists <- doesFileExist f-  isExecutable <- if exists-                     then executable <$> getPermissions f-                     else return True-  let (f', args'') = if exists-                        then case map toLower (takeExtension f) of-                                  _ | isExecutable -> ("." </> f, args')-                                  ".py"  -> ("python", f:args')-                                  ".hs"  -> ("runhaskell", f:args')-                                  ".pl"  -> ("perl", f:args')-                                  ".rb"  -> ("ruby", f:args')-                                  ".php" -> ("php", f:args')-                                  ".js"  -> ("node", f:args')-                                  _      -> (f, args')-                        else (f, args')-  unless (exists && isExecutable) $ do-    mbExe <- findExecutable f'-    when (isNothing mbExe) $-      err 83 $ "Error running filter " ++ f ++  ":\n" ++-               "Could not find executable '" ++ f' ++ "'."-  env <- getEnvironment-  let env' = Just $ ("PANDOC_VERSION", pandocVersion) : env-  (exitcode, outbs, errbs) <- E.handle filterException $-                              pipeProcess env' f' args'' $ encode d-  unless (B.null errbs) $ B.hPutStr stderr errbs-  case exitcode of-       ExitSuccess    -> return $ either error id $ eitherDecode' outbs-       ExitFailure ec -> err 83 $ "Error running filter " ++ f ++ "\n" ++-                                  "Filter returned error status " ++ show ec- where filterException :: E.SomeException -> IO a-       filterException e = err 83 $ "Error running filter " ++ f ++ "\n" ++-                                       show e--highlightingStyles :: [(String, Style)]-highlightingStyles =-  [("pygments", pygments),-   ("tango", tango),-   ("espresso", espresso),-   ("zenburn", zenburn),-   ("kate", kate),-   ("monochrome", monochrome),-   ("breezedark", breezeDark),-   ("haddock", haddock)]---- | Data structure for command line options.-data Opt = Opt-    { optTabStop           :: Int     -- ^ Number of spaces per tab-    , optPreserveTabs      :: Bool    -- ^ Preserve tabs instead of converting to spaces-    , optStandalone        :: Bool    -- ^ Include header, footer-    , optReader            :: String  -- ^ Reader format-    , optWriter            :: String  -- ^ Writer format-    , optParseRaw          :: Bool    -- ^ Parse unconvertable HTML and TeX-    , optTableOfContents   :: Bool    -- ^ Include table of contents-    , optTransforms        :: [Transform]  -- ^ Doc transforms to apply-    , optTemplate          :: Maybe FilePath  -- ^ Custom template-    , optVariables         :: [(String,String)] -- ^ Template variables to set-    , optMetadata          :: M.Map String MetaValue -- ^ Metadata fields to set-    , optOutputFile        :: String  -- ^ Name of output file-    , optNumberSections    :: Bool    -- ^ Number sections in LaTeX-    , optNumberOffset      :: [Int]   -- ^ Starting number for sections-    , optSectionDivs       :: Bool    -- ^ Put sections in div tags in HTML-    , optIncremental       :: Bool    -- ^ Use incremental lists in Slidy/Slideous/S5-    , optSelfContained     :: Bool    -- ^ Make HTML accessible offline-    , optSmart             :: Bool    -- ^ Use smart typography-    , optOldDashes         :: Bool    -- ^ Parse dashes like pandoc <=1.8.2.1-    , optHtml5             :: Bool    -- ^ Produce HTML5 in HTML-    , optHtmlQTags         :: Bool    -- ^ Use <q> tags in HTML-    , optHighlight         :: Bool    -- ^ Highlight source code-    , optHighlightStyle    :: Style   -- ^ Style to use for highlighted code-    , optTopLevelDivision  :: TopLevelDivision -- ^ Type of the top-level divisions-    , optHTMLMathMethod    :: HTMLMathMethod -- ^ Method to print HTML math-    , optReferenceODT      :: Maybe FilePath -- ^ Path of reference.odt-    , optReferenceDocx     :: Maybe FilePath -- ^ Path of reference.docx-    , optEpubStylesheet    :: Maybe String   -- ^ EPUB stylesheet-    , optEpubMetadata      :: String  -- ^ EPUB metadata-    , optEpubFonts         :: [FilePath] -- ^ EPUB fonts to embed-    , optEpubChapterLevel  :: Int     -- ^ Header level at which to split chapters-    , optTOCDepth          :: Int     -- ^ Number of levels to include in TOC-    , optDumpArgs          :: Bool    -- ^ Output command-line arguments-    , optIgnoreArgs        :: Bool    -- ^ Ignore command-line arguments-    , optVerbose           :: Bool    -- ^ Verbose diagnostic output-    , optReferenceLinks    :: Bool    -- ^ Use reference links in writing markdown, rst-    , optReferenceLocation :: ReferenceLocation -- ^ location for footnotes and link references in markdown output-    , optDpi               :: Int     -- ^ Dpi-    , optWrapText          :: WrapOption  -- ^ Options for wrapping text-    , optColumns           :: Int     -- ^ Line length in characters-    , optFilters           :: [FilePath] -- ^ Filters to apply-    , optEmailObfuscation  :: ObfuscationMethod-    , optIdentifierPrefix  :: String-    , optIndentedCodeClasses :: [String] -- ^ Default classes for indented code blocks-    , optDataDir           :: Maybe FilePath-    , optCiteMethod        :: CiteMethod -- ^ Method to output cites-    , optListings          :: Bool       -- ^ Use listings package for code blocks-    , optLaTeXEngine       :: String     -- ^ Program to use for latex -> pdf-    , optLaTeXEngineArgs   :: [String]   -- ^ Flags to pass to the latex-engine-    , optSlideLevel        :: Maybe Int  -- ^ Header level that creates slides-    , optSetextHeaders     :: Bool       -- ^ Use atx headers for markdown level 1-2-    , optAscii             :: Bool       -- ^ Use ascii characters only in html-    , optTeXLigatures      :: Bool       -- ^ Use TeX ligatures for quotes/dashes-    , optDefaultImageExtension :: String -- ^ Default image extension-    , optExtractMedia      :: Maybe FilePath -- ^ Path to extract embedded media-    , optTrace             :: Bool       -- ^ Print debug information-    , optTrackChanges      :: TrackChanges -- ^ Accept or reject MS Word track-changes.-    , optFileScope        :: Bool         -- ^ Parse input files before combining-    , optKaTeXStylesheet   :: Maybe String     -- ^ Path to stylesheet for KaTeX-    , optKaTeXJS           :: Maybe String     -- ^ Path to js file for KaTeX-    }---- | Defaults for command-line options.-defaultOpts :: Opt-defaultOpts = Opt-    { optTabStop               = 4-    , optPreserveTabs          = False-    , optStandalone            = False-    , optReader                = ""    -- null for default reader-    , optWriter                = ""    -- null for default writer-    , optParseRaw              = False-    , optTableOfContents       = False-    , optTransforms            = []-    , optTemplate              = Nothing-    , optVariables             = []-    , optMetadata              = M.empty-    , optOutputFile            = "-"    -- "-" means stdout-    , optNumberSections        = False-    , optNumberOffset          = [0,0,0,0,0,0]-    , optSectionDivs           = False-    , optIncremental           = False-    , optSelfContained         = False-    , optSmart                 = False-    , optOldDashes             = False-    , optHtml5                 = False-    , optHtmlQTags             = False-    , optHighlight             = True-    , optHighlightStyle        = pygments-    , optTopLevelDivision      = TopLevelDefault-    , optHTMLMathMethod        = PlainMath-    , optReferenceODT          = Nothing-    , optReferenceDocx         = Nothing-    , optEpubStylesheet        = Nothing-    , optEpubMetadata          = ""-    , optEpubFonts             = []-    , optEpubChapterLevel      = 1-    , optTOCDepth              = 3-    , optDumpArgs              = False-    , optIgnoreArgs            = False-    , optVerbose               = False-    , optReferenceLinks        = False-    , optReferenceLocation     = EndOfDocument-    , optDpi                   = 96-    , optWrapText              = WrapAuto-    , optColumns               = 72-    , optFilters               = []-    , optEmailObfuscation      = NoObfuscation-    , optIdentifierPrefix      = ""-    , optIndentedCodeClasses   = []-    , optDataDir               = Nothing-    , optCiteMethod            = Citeproc-    , optListings              = False-    , optLaTeXEngine           = "pdflatex"-    , optLaTeXEngineArgs       = []-    , optSlideLevel            = Nothing-    , optSetextHeaders         = True-    , optAscii                 = False-    , optTeXLigatures          = True-    , optDefaultImageExtension = ""-    , optExtractMedia          = Nothing-    , optTrace                 = False-    , optTrackChanges          = AcceptChanges-    , optFileScope            = False-    , optKaTeXStylesheet       = Nothing-    , optKaTeXJS               = Nothing-    }---- | A list of functions, each transforming the options data structure---   in response to a command-line option.-options :: [OptDescr (Opt -> IO Opt)]-options =-    [ Option "fr" ["from","read"]-                 (ReqArg-                  (\arg opt -> return opt { optReader = arg })-                  "FORMAT")-                 ""--    , Option "tw" ["to","write"]-                 (ReqArg-                  (\arg opt -> return opt { optWriter = arg })-                  "FORMAT")-                 ""--    , Option "o" ["output"]-                 (ReqArg-                  (\arg opt -> return opt { optOutputFile = arg })-                  "FILENAME")-                 "" -- "Name of output file"--    , Option "" ["data-dir"]-                 (ReqArg-                  (\arg opt -> return opt { optDataDir = Just arg })-                 "DIRECTORY") -- "Directory containing pandoc data files."-                ""--    , Option "R" ["parse-raw"]-                 (NoArg-                  (\opt -> return opt { optParseRaw = True }))-                 "" -- "Parse untranslatable HTML codes and LaTeX environments as raw"--    , Option "S" ["smart"]-                 (NoArg-                  (\opt -> return opt { optSmart = True }))-                 "" -- "Use smart quotes, dashes, and ellipses"--    , Option "" ["old-dashes"]-                 (NoArg-                  (\opt -> return opt { optSmart = True-                                      , optOldDashes = True }))-                 "" -- "Use smart quotes, dashes, and ellipses"--    , Option "" ["base-header-level"]-                 (ReqArg-                  (\arg opt ->-                      case safeRead arg of-                           Just t | t > 0 -> do-                               let oldTransforms = optTransforms opt-                               let shift = t - 1-                               return opt{ optTransforms =-                                           headerShift shift : oldTransforms }-                           _              -> err 19-                                       "base-header-level must be a number > 0")-                  "NUMBER")-                 "" -- "Headers base level"--     , Option "" ["indented-code-classes"]-                  (ReqArg-                   (\arg opt -> return opt { optIndentedCodeClasses = words $-                                             map (\c -> if c == ',' then ' ' else c) arg })-                   "STRING")-                  "" -- "Classes (whitespace- or comma-separated) to use for indented code-blocks"--    , Option "F" ["filter"]-                 (ReqArg-                  (\arg opt -> return opt { optFilters = arg : optFilters opt })-                  "PROGRAM")-                 "" -- "External JSON filter"--    , Option "" ["normalize"]-                 (NoArg-                  (\opt -> return opt { optTransforms =-                                   normalize : optTransforms opt } ))-                 "" -- "Normalize the Pandoc AST"--    , Option "p" ["preserve-tabs"]-                 (NoArg-                  (\opt -> return opt { optPreserveTabs = True }))-                 "" -- "Preserve tabs instead of converting to spaces"--    , Option "" ["tab-stop"]-                 (ReqArg-                  (\arg opt ->-                      case safeRead arg of-                           Just t | t > 0 -> return opt { optTabStop = t }-                           _              -> err 31-                                          "tab-stop must be a number greater than 0")-                  "NUMBER")-                 "" -- "Tab stop (default 4)"--    , Option "" ["track-changes"]-                 (ReqArg-                  (\arg opt -> do-                     action <- case arg of-                            "accept" -> return AcceptChanges-                            "reject" -> return RejectChanges-                            "all"    -> return AllChanges-                            _        -> err 6-                               ("Unknown option for track-changes: " ++ arg)-                     return opt { optTrackChanges = action })-                  "accept|reject|all")-                 "" -- "Accepting or reject MS Word track-changes.""--    , Option "" ["file-scope"]-                 (NoArg-                  (\opt -> return opt { optFileScope = True }))-                 "" -- "Parse input files before combining"--    , Option "" ["extract-media"]-                 (ReqArg-                  (\arg opt ->-                    return opt { optExtractMedia = Just arg })-                  "PATH")-                 "" -- "Directory to which to extract embedded media"--    , Option "s" ["standalone"]-                 (NoArg-                  (\opt -> return opt { optStandalone = True }))-                 "" -- "Include needed header and footer on output"--    , Option "" ["template"]-                 (ReqArg-                  (\arg opt ->-                     return opt{ optTemplate = Just arg,-                                 optStandalone = True })-                  "FILENAME")-                 "" -- "Use custom template"--    , Option "M" ["metadata"]-                 (ReqArg-                  (\arg opt -> do-                     let (key,val) = case break (`elem` ":=") arg of-                                       (k,_:v) -> (k, readMetaValue v)-                                       (k,_)   -> (k, MetaBool True)-                     return opt{ optMetadata = addMetadata key val-                                             $ optMetadata opt })-                  "KEY[:VALUE]")-                 ""--    , Option "V" ["variable"]-                 (ReqArg-                  (\arg opt -> do-                     let (key,val) = case break (`elem` ":=") arg of-                                       (k,_:v) -> (k,v)-                                       (k,_)   -> (k,"true")-                     return opt{ optVariables = (key,val) : optVariables opt })-                  "KEY[:VALUE]")-                 ""--    , Option "D" ["print-default-template"]-                 (ReqArg-                  (\arg _ -> do-                     templ <- getDefaultTemplate Nothing arg-                     case templ of-                          Right t -> UTF8.hPutStr stdout t-                          Left e  -> error $ show e-                     exitSuccess)-                  "FORMAT")-                 "" -- "Print default template for FORMAT"--    , Option "" ["print-default-data-file"]-                 (ReqArg-                  (\arg _ -> do-                     readDataFile Nothing arg >>= BS.hPutStr stdout-                     exitSuccess)-                  "FILE")-                  "" -- "Print default data file"--    , Option "" ["dpi"]-                 (ReqArg-                  (\arg opt ->-                    case safeRead arg of-                         Just t | t > 0 -> return opt { optDpi = t }-                         _              -> err 31-                                        "dpi must be a number greater than 0")-                  "NUMBER")-                 "" -- "Dpi (default 96)"--    , Option "" ["no-wrap"]-                 (NoArg-                  (\opt -> do warn $ "--no-wrap is deprecated. " ++-                                     "Use --wrap=none or --wrap=preserve instead."-                              return opt { optWrapText = WrapNone }))-                 ""--    , Option "" ["wrap"]-                 (ReqArg-                  (\arg opt ->-                    case safeRead ("Wrap" ++ uppercaseFirstLetter arg) of-                          Just o   -> return opt { optWrapText = o }-                          Nothing  -> err 77 "--wrap must be auto, none, or preserve")-                 "auto|none|preserve")-                 "" -- "Option for wrapping text in output"--    , Option "" ["columns"]-                 (ReqArg-                  (\arg opt ->-                      case safeRead arg of-                           Just t | t > 0 -> return opt { optColumns = t }-                           _              -> err 33-                                   "columns must be a number greater than 0")-                 "NUMBER")-                 "" -- "Length of line in characters"--    , Option "" ["toc", "table-of-contents"]-                (NoArg-                 (\opt -> return opt { optTableOfContents = True }))-               "" -- "Include table of contents"--    , Option "" ["toc-depth"]-                 (ReqArg-                  (\arg opt ->-                      case safeRead arg of-                           Just t | t >= 1 && t <= 6 ->-                                    return opt { optTOCDepth = t }-                           _      -> err 57-                                    "TOC level must be a number between 1 and 6")-                 "NUMBER")-                 "" -- "Number of levels to include in TOC"--    , Option "" ["no-highlight"]-                (NoArg-                 (\opt -> return opt { optHighlight = False }))-                 "" -- "Don't highlight source code"--    , Option "" ["highlight-style"]-                (ReqArg-                 (\arg opt -> do-                   case lookup (map toLower arg) highlightingStyles of-                         Just s -> return opt{ optHighlightStyle = s }-                         Nothing -> err 39 $ "Unknown style: " ++ arg)-                 "STYLE")-                 "" -- "Style for highlighted code"--    , Option "H" ["include-in-header"]-                 (ReqArg-                  (\arg opt -> do-                     text <- UTF8.readFile arg-                     -- add new ones to end, so they're included in order specified-                     let newvars = optVariables opt ++ [("header-includes",text)]-                     return opt { optVariables = newvars,-                                  optStandalone = True })-                  "FILENAME")-                 "" -- "File to include at end of header (implies -s)"--    , Option "B" ["include-before-body"]-                 (ReqArg-                  (\arg opt -> do-                     text <- UTF8.readFile arg-                     -- add new ones to end, so they're included in order specified-                     let newvars = optVariables opt ++ [("include-before",text)]-                     return opt { optVariables = newvars,-                                  optStandalone = True })-                  "FILENAME")-                 "" -- "File to include before document body"--    , Option "A" ["include-after-body"]-                 (ReqArg-                  (\arg opt -> do-                     text <- UTF8.readFile arg-                     -- add new ones to end, so they're included in order specified-                     let newvars = optVariables opt ++ [("include-after",text)]-                     return opt { optVariables = newvars,-                                  optStandalone = True })-                  "FILENAME")-                 "" -- "File to include after document body"--    , Option "" ["self-contained"]-                 (NoArg-                  (\opt -> return opt { optSelfContained = True,-                                        optStandalone = True }))-                 "" -- "Make slide shows include all the needed js and css"--    , Option "" ["html-q-tags"]-                 (NoArg-                  (\opt ->-                     return opt { optHtmlQTags = True }))-                 "" -- "Use <q> tags for quotes in HTML"--    , Option "" ["ascii"]-                 (NoArg-                  (\opt -> return opt { optAscii = True }))-                 ""  -- "Use ascii characters only in HTML output"--    , Option "" ["reference-links"]-                 (NoArg-                  (\opt -> return opt { optReferenceLinks = True } ))-                 "" -- "Use reference links in parsing HTML"--    , Option "" ["reference-location"]-                 (ReqArg-                  (\arg opt -> do-                     action <- case arg of-                            "block"    -> return EndOfBlock-                            "section"  -> return EndOfSection-                            "document" -> return EndOfDocument-                            _        -> err 6-                               ("Unknown option for reference-location: " ++ arg)-                     return opt { optReferenceLocation = action })-                  "block|section|document")-                 "" -- "Accepting or reject MS Word track-changes.""--    , Option "" ["atx-headers"]-                 (NoArg-                  (\opt -> return opt { optSetextHeaders = False } ))-                 "" -- "Use atx-style headers for markdown"--    , Option "" ["chapters"]-                 (NoArg-                  (\opt -> do warn $ "--chapters is deprecated. " ++-                                     "Use --top-level-division=chapter instead."-                              return opt { optTopLevelDivision = TopLevelChapter }))-                 "" -- "Use chapter for top-level sections in LaTeX, DocBook"--    , Option "" ["top-level-division"]-                 (ReqArg-                  (\arg opt -> do-                      let tldName = "TopLevel" ++ uppercaseFirstLetter arg-                      case safeRead tldName of-                        Just tlDiv -> return opt { optTopLevelDivision = tlDiv }-                        _       -> err 76 ("Top-level division must be " ++-                                           "section,  chapter, part, or default"))-                   "section|chapter|part")-                 "" -- "Use top-level division type in LaTeX, ConTeXt, DocBook"--    , Option "N" ["number-sections"]-                 (NoArg-                  (\opt -> return opt { optNumberSections = True }))-                 "" -- "Number sections in LaTeX"--    , Option "" ["number-offset"]-                 (ReqArg-                  (\arg opt ->-                      case safeRead ('[':arg ++ "]") of-                           Just ns -> return opt { optNumberOffset = ns,-                                                   optNumberSections = True }-                           _      -> err 57 "could not parse number-offset")-                 "NUMBERS")-                 "" -- "Starting number for sections, subsections, etc."--    , Option "" ["no-tex-ligatures"]-                 (NoArg-                  (\opt -> return opt { optTeXLigatures = False }))-                 "" -- "Don't use tex ligatures for quotes, dashes"--    , Option "" ["listings"]-                 (NoArg-                  (\opt -> return opt { optListings = True }))-                 "" -- "Use listings package for LaTeX code blocks"--    , Option "i" ["incremental"]-                 (NoArg-                  (\opt -> return opt { optIncremental = True }))-                 "" -- "Make list items display incrementally in Slidy/Slideous/S5"--    , Option "" ["slide-level"]-                 (ReqArg-                  (\arg opt ->-                      case safeRead arg of-                           Just t | t >= 1 && t <= 6 ->-                                    return opt { optSlideLevel = Just t }-                           _      -> err 39-                                    "slide level must be a number between 1 and 6")-                 "NUMBER")-                 "" -- "Force header level for slides"--    , Option "" ["section-divs"]-                 (NoArg-                  (\opt -> return opt { optSectionDivs = True }))-                 "" -- "Put sections in div tags in HTML"--    , Option "" ["default-image-extension"]-                 (ReqArg-                  (\arg opt -> return opt { optDefaultImageExtension = arg })-                   "extension")-                  "" -- "Default extension for extensionless images"--    , Option "" ["email-obfuscation"]-                 (ReqArg-                  (\arg opt -> do-                     method <- case arg of-                            "references" -> return ReferenceObfuscation-                            "javascript" -> return JavascriptObfuscation-                            "none"       -> return NoObfuscation-                            _            -> err 6-                               ("Unknown obfuscation method: " ++ arg)-                     return opt { optEmailObfuscation = method })-                  "none|javascript|references")-                 "" -- "Method for obfuscating email in HTML"--     , Option "" ["id-prefix"]-                  (ReqArg-                   (\arg opt -> return opt { optIdentifierPrefix = arg })-                   "STRING")-                  "" -- "Prefix to add to automatically generated HTML identifiers"--    , Option "T" ["title-prefix"]-                 (ReqArg-                  (\arg opt -> do-                    let newvars = ("title-prefix", arg) : optVariables opt-                    return opt { optVariables = newvars,-                                 optStandalone = True })-                  "STRING")-                 "" -- "String to prefix to HTML window title"--    , Option "c" ["css"]-                 (ReqArg-                  (\arg opt -> do-                     -- add new link to end, so it is included in proper order-                     let newvars = optVariables opt ++ [("css",arg)]-                     return opt { optVariables = newvars,-                                  optStandalone = True })-                  "URL")-                 "" -- "Link to CSS style sheet"--    , Option "" ["reference-odt"]-                 (ReqArg-                  (\arg opt ->-                    return opt { optReferenceODT = Just arg })-                  "FILENAME")-                 "" -- "Path of custom reference.odt"--    , Option "" ["reference-docx"]-                 (ReqArg-                  (\arg opt ->-                    return opt { optReferenceDocx = Just arg })-                  "FILENAME")-                 "" -- "Path of custom reference.docx"--    , Option "" ["epub-stylesheet"]-                 (ReqArg-                  (\arg opt -> do-                     text <- UTF8.readFile arg-                     return opt { optEpubStylesheet = Just text })-                  "FILENAME")-                 "" -- "Path of epub.css"--    , Option "" ["epub-cover-image"]-                 (ReqArg-                  (\arg opt ->-                     return opt { optVariables =-                                 ("epub-cover-image", arg) : optVariables opt })-                  "FILENAME")-                 "" -- "Path of epub cover image"--    , Option "" ["epub-metadata"]-                 (ReqArg-                  (\arg opt -> do-                     text <- UTF8.readFile arg-                     return opt { optEpubMetadata = text })-                  "FILENAME")-                 "" -- "Path of epub metadata file"--    , Option "" ["epub-embed-font"]-                 (ReqArg-                  (\arg opt ->-                     return opt{ optEpubFonts = arg : optEpubFonts opt })-                  "FILE")-                 "" -- "Directory of fonts to embed"--    , Option "" ["epub-chapter-level"]-                 (ReqArg-                  (\arg opt ->-                      case safeRead arg of-                           Just t | t >= 1 && t <= 6 ->-                                    return opt { optEpubChapterLevel = t }-                           _      -> err 59-                                    "chapter level must be a number between 1 and 6")-                 "NUMBER")-                 "" -- "Header level at which to split chapters in EPUB"--    , Option "" ["latex-engine"]-                 (ReqArg-                  (\arg opt -> do-                     let b = takeBaseName arg-                     if b `elem` ["pdflatex", "lualatex", "xelatex"]-                        then return opt { optLaTeXEngine = arg }-                        else err 45 "latex-engine must be pdflatex, lualatex, or xelatex.")-                  "PROGRAM")-                 "" -- "Name of latex program to use in generating PDF"--    , Option "" ["latex-engine-opt"]-                 (ReqArg-                  (\arg opt -> do-                      let oldArgs = optLaTeXEngineArgs opt-                      return opt { optLaTeXEngineArgs = arg : oldArgs })-                  "STRING")-                 "" -- "Flags to pass to the LaTeX engine, all instances of this option are accumulated and used"--    , Option "" ["bibliography"]-                 (ReqArg-                  (\arg opt -> return opt{ optMetadata = addMetadata-                                             "bibliography" (readMetaValue arg)-                                             $ optMetadata opt-                                         })-                   "FILE")-                 ""--     , Option "" ["csl"]-                 (ReqArg-                  (\arg opt ->-                     return opt{ optMetadata = addMetadata "csl"-                                               (readMetaValue arg)-                                               $ optMetadata opt })-                   "FILE")-                 ""--     , Option "" ["citation-abbreviations"]-                 (ReqArg-                  (\arg opt ->-                     return opt{ optMetadata = addMetadata-                                               "citation-abbreviations"-                                               (readMetaValue arg)-                                               $ optMetadata opt })-                   "FILE")-                 ""--    , Option "" ["natbib"]-                 (NoArg-                  (\opt -> return opt { optCiteMethod = Natbib }))-                 "" -- "Use natbib cite commands in LaTeX output"--    , Option "" ["biblatex"]-                 (NoArg-                  (\opt -> return opt { optCiteMethod = Biblatex }))-                 "" -- "Use biblatex cite commands in LaTeX output"--    , Option "m" ["latexmathml", "asciimathml"]-                 (OptArg-                  (\arg opt ->-                      return opt { optHTMLMathMethod = LaTeXMathML arg })-                  "URL")-                 "" -- "Use LaTeXMathML script in html output"--    , Option "" ["mathml"]-                 (OptArg-                  (\arg opt ->-                      return opt { optHTMLMathMethod = MathML arg })-                   "URL")-                 "" -- "Use mathml for HTML math"--    , Option "" ["mimetex"]-                 (OptArg-                  (\arg opt -> do-                      let url' = case arg of-                                      Just u   -> u ++ "?"-                                      Nothing  -> "/cgi-bin/mimetex.cgi?"-                      return opt { optHTMLMathMethod = WebTeX url' })-                  "URL")-                 "" -- "Use mimetex for HTML math"--    , Option "" ["webtex"]-                 (OptArg-                  (\arg opt -> do-                      let url' = fromMaybe "https://latex.codecogs.com/png.latex?" arg-                      return opt { optHTMLMathMethod = WebTeX url' })-                  "URL")-                 "" -- "Use web service for HTML math"--    , Option "" ["jsmath"]-                 (OptArg-                  (\arg opt -> return opt { optHTMLMathMethod = JsMath arg})-                  "URL")-                 "" -- "Use jsMath for HTML math"--    , Option "" ["mathjax"]-                 (OptArg-                  (\arg opt -> do-                      let url' = fromMaybe "https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_CHTML-full" arg-                      return opt { optHTMLMathMethod = MathJax url'})-                  "URL")-                 "" -- "Use MathJax for HTML math"-    , Option "" ["katex"]-                 (OptArg-                  (\arg opt ->-                      return opt-                        { optKaTeXJS =-                           arg <|> Just "https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.6.0/katex.min.js"})-                  "URL")-                  "" -- Use KaTeX for HTML Math--    , Option "" ["katex-stylesheet"]-                 (ReqArg-                  (\arg opt ->-                      return opt { optKaTeXStylesheet = Just arg })-                 "URL")-                 "" -- Set the KaTeX Stylesheet location--    , Option "" ["gladtex"]-                 (NoArg-                  (\opt -> return opt { optHTMLMathMethod = GladTeX }))-                 "" -- "Use gladtex for HTML math"--    , Option "" ["trace"]-                 (NoArg-                  (\opt -> return opt { optTrace = True }))-                 "" -- "Turn on diagnostic tracing in readers."--    , Option "" ["dump-args"]-                 (NoArg-                  (\opt -> return opt { optDumpArgs = True }))-                 "" -- "Print output filename and arguments to stdout."--    , Option "" ["ignore-args"]-                 (NoArg-                  (\opt -> return opt { optIgnoreArgs = True }))-                 "" -- "Ignore command-line arguments."--    , Option "" ["verbose"]-                 (NoArg-                  (\opt -> return opt { optVerbose = True }))-                 "" -- "Verbose diagnostic output."--    , Option "" ["bash-completion"]-                 (NoArg-                  (\_ -> do-                     ddir <- getDataDir-                     tpl <- readDataFileUTF8 Nothing "bash_completion.tpl"-                     let optnames (Option shorts longs _ _) =-                           map (\c -> ['-',c]) shorts ++-                           map ("--" ++) longs-                     let allopts = unwords (concatMap optnames options)-                     UTF8.hPutStrLn stdout $ printf tpl allopts-                         (unwords (map fst readers))-                         (unwords (map fst writers))-                         (unwords $ map fst highlightingStyles)-                         ddir-                     exitSuccess ))-                 "" -- "Print bash completion script"--    , Option "" ["list-input-formats"]-                 (NoArg-                  (\_ -> do-                     let readers'names = sort (map fst readers)-                     mapM_ (UTF8.hPutStrLn stdout) readers'names-                     exitSuccess ))-                 ""--    , Option "" ["list-output-formats"]-                 (NoArg-                  (\_ -> do-                     let writers'names = sort (map fst writers)-                     mapM_ (UTF8.hPutStrLn stdout) writers'names-                     exitSuccess ))-                 ""--    , Option "" ["list-extensions"]-                 (NoArg-                  (\_ -> do-                     let showExt x = drop 4 (show x) ++-                                       if x `Set.member` pandocExtensions-                                          then " +"-                                          else " -"-                     mapM_ (UTF8.hPutStrLn stdout . showExt)-                               ([minBound..maxBound] :: [Extension])-                     exitSuccess ))-                 ""--    , Option "" ["list-highlight-languages"]-                 (NoArg-                  (\_ -> do-                     let langs = [ T.unpack (T.toLower (sShortname s))-                                 | s <- M.elems defaultSyntaxMap-                                 , sShortname s `notElem`-                                    [T.pack "Alert", T.pack "Alert_indent"]-                                 ]-                     mapM_ (UTF8.hPutStrLn stdout) langs-                     exitSuccess ))-                 ""--    , Option "" ["list-highlight-styles"]-                 (NoArg-                  (\_ -> do-                     mapM_ (UTF8.hPutStrLn stdout) $-                           map fst highlightingStyles-                     exitSuccess ))-                 ""--    , Option "v" ["version"]-                 (NoArg-                  (\_ -> do-                     prg <- getProgName-                     defaultDatadir <- E.catch-                            (getAppUserDataDirectory "pandoc")-                            (\e -> let _ = (e :: E.SomeException)-                                   in  return "")-                     UTF8.hPutStrLn stdout (prg ++ " " ++ pandocVersion ++-                       compileInfo ++ "\nDefault user data directory: " ++-                       defaultDatadir ++ copyrightMessage)-                     exitSuccess ))-                 "" -- "Print version"--    , Option "h" ["help"]-                 (NoArg-                  (\_ -> do-                     prg <- getProgName-                     UTF8.hPutStr stdout (usageMessage prg options)-                     exitSuccess ))-                 "" -- "Show help"--    ]---addMetadata :: String -> MetaValue -> M.Map String MetaValue-            -> M.Map String MetaValue-addMetadata k v m = case M.lookup k m of-                         Nothing -> M.insert k v m-                         Just (MetaList xs) -> M.insert k-                                              (MetaList (xs ++ [v])) m-                         Just x -> M.insert k (MetaList [v, x]) m--readMetaValue :: String -> MetaValue-readMetaValue s = case decode (UTF8.fromString s) of-                       Just (Yaml.String t) -> MetaString $ T.unpack t-                       Just (Yaml.Bool b)   -> MetaBool b-                       _                    -> MetaString s---- Returns usage message-usageMessage :: String -> [OptDescr (Opt -> IO Opt)] -> String-usageMessage programName = usageInfo (programName ++ " [OPTIONS] [FILES]")---- Determine default reader based on source file extensions-defaultReaderName :: String -> [FilePath] -> String-defaultReaderName fallback [] = fallback-defaultReaderName fallback (x:xs) =-  case takeExtension (map toLower x) of-    ".xhtml"    -> "html"-    ".html"     -> "html"-    ".htm"      -> "html"-    ".md"       -> "markdown"-    ".markdown" -> "markdown"-    ".tex"      -> "latex"-    ".latex"    -> "latex"-    ".ltx"      -> "latex"-    ".rst"      -> "rst"-    ".org"      -> "org"-    ".lhs"      -> "markdown+lhs"-    ".db"       -> "docbook"-    ".opml"     -> "opml"-    ".wiki"     -> "mediawiki"-    ".dokuwiki" -> "dokuwiki"-    ".textile"  -> "textile"-    ".native"   -> "native"-    ".json"     -> "json"-    ".docx"     -> "docx"-    ".t2t"      -> "t2t"-    ".epub"     -> "epub"-    ".odt"      -> "odt"-    ".pdf"      -> "pdf"  -- so we get an "unknown reader" error-    ".doc"      -> "doc"  -- so we get an "unknown reader" error-    _           -> defaultReaderName fallback xs---- Returns True if extension of first source is .lhs-lhsExtension :: [FilePath] -> Bool-lhsExtension (x:_) = takeExtension x == ".lhs"-lhsExtension _ = False---- Determine default writer based on output file extension-defaultWriterName :: FilePath -> String-defaultWriterName "-" = "html" -- no output file-defaultWriterName x =-  case takeExtension (map toLower x) of-    ""          -> "markdown" -- empty extension-    ".tex"      -> "latex"-    ".latex"    -> "latex"-    ".ltx"      -> "latex"-    ".context"  -> "context"-    ".ctx"      -> "context"-    ".rtf"      -> "rtf"-    ".rst"      -> "rst"-    ".s5"       -> "s5"-    ".native"   -> "native"-    ".json"     -> "json"-    ".txt"      -> "markdown"-    ".text"     -> "markdown"-    ".md"       -> "markdown"-    ".markdown" -> "markdown"-    ".textile"  -> "textile"-    ".lhs"      -> "markdown+lhs"-    ".texi"     -> "texinfo"-    ".texinfo"  -> "texinfo"-    ".db"       -> "docbook"-    ".odt"      -> "odt"-    ".docx"     -> "docx"-    ".epub"     -> "epub"-    ".org"      -> "org"-    ".asciidoc" -> "asciidoc"-    ".adoc"     -> "asciidoc"-    ".pdf"      -> "latex"-    ".fb2"      -> "fb2"-    ".opml"     -> "opml"-    ".icml"     -> "icml"-    ".tei.xml"  -> "tei"-    ".tei"      -> "tei"-    ['.',y] | y `elem` ['1'..'9'] -> "man"-    _           -> "html"---- Transformations of a Pandoc document post-parsing:--extractMedia :: MediaBag -> FilePath -> Pandoc -> IO Pandoc-extractMedia media dir d =-  case [fp | (fp, _, _) <- mediaDirectory media] of-        []  -> return d-        fps -> do-          extractMediaBag True dir media-          return $ walk (adjustImagePath dir fps) d--adjustImagePath :: FilePath -> [FilePath] -> Inline -> Inline-adjustImagePath dir paths (Image attr lab (src, tit))-   | src `elem` paths = Image attr lab (dir ++ "/" ++ src, tit)-adjustImagePath _ _ x = x--adjustMetadata :: M.Map String MetaValue -> Pandoc -> IO Pandoc-adjustMetadata metadata d = return $ M.foldWithKey setMeta d metadata--applyTransforms :: [Transform] -> Pandoc -> IO Pandoc-applyTransforms transforms d = return $ foldr ($) d transforms--  -- First we check to see if a filter is found.  If not, and if it's-  -- not an absolute path, we check to see whether it's in `userdir/filters`.-  -- If not, we leave it unchanged.-expandFilterPath :: Maybe FilePath -> FilePath -> IO FilePath-expandFilterPath mbDatadir fp = do-  fpExists <- doesFileExist fp-  if fpExists-     then return fp-     else case mbDatadir of-               Just datadir | isRelative fp -> do-                 let filterPath = (datadir </> "filters" </> fp)-                 filterPathExists <- doesFileExist filterPath-                 if filterPathExists-                    then return filterPath-                    else return fp-               _ -> return fp--applyFilters :: Maybe FilePath -> [FilePath] -> [String] -> Pandoc -> IO Pandoc-applyFilters mbDatadir filters args d = do-  expandedFilters <- mapM (expandFilterPath mbDatadir) filters-  foldrM ($) d $ map (flip externalFilter args) expandedFilters--uppercaseFirstLetter :: String -> String-uppercaseFirstLetter (c:cs) = toUpper c : cs-uppercaseFirstLetter [] = []--main :: IO ()-main = do--  rawArgs <- map UTF8.decodeArg <$> getArgs-  prg <- getProgName--  let (actions, args, errors) = getOpt Permute options rawArgs--  unless (null errors) $-     err 2 $ concat $ errors ++-        ["Try " ++ prg ++ " --help for more information."]--  -- thread option data structure through all supplied option actions-  opts <- foldl (>>=) (return defaultOpts) actions-  convertWithOpts opts args--convertWithOpts :: Opt -> [FilePath] -> IO ()-convertWithOpts opts args = do-  let Opt    {  optTabStop               = tabStop-              , optPreserveTabs          = preserveTabs-              , optStandalone            = standalone-              , optReader                = readerName-              , optWriter                = writerName-              , optParseRaw              = parseRaw-              , optVariables             = variables-              , optMetadata              = metadata-              , optTableOfContents       = toc-              , optTransforms            = transforms-              , optTemplate              = templatePath-              , optOutputFile            = outputFile-              , optNumberSections        = numberSections-              , optNumberOffset          = numberFrom-              , optSectionDivs           = sectionDivs-              , optIncremental           = incremental-              , optSelfContained         = selfContained-              , optSmart                 = smart-              , optOldDashes             = oldDashes-              , optHtml5                 = html5-              , optHtmlQTags             = htmlQTags-              , optHighlight             = highlight-              , optHighlightStyle        = highlightStyle-              , optTopLevelDivision      = topLevelDivision-              , optHTMLMathMethod        = mathMethod'-              , optReferenceODT          = referenceODT-              , optReferenceDocx         = referenceDocx-              , optEpubStylesheet        = epubStylesheet-              , optEpubMetadata          = epubMetadata-              , optEpubFonts             = epubFonts-              , optEpubChapterLevel      = epubChapterLevel-              , optTOCDepth              = epubTOCDepth-              , optDumpArgs              = dumpArgs-              , optIgnoreArgs            = ignoreArgs-              , optVerbose               = verbose-              , optReferenceLinks        = referenceLinks-              , optReferenceLocation     = referenceLocation-              , optDpi                   = dpi-              , optWrapText              = wrap-              , optColumns               = columns-              , optFilters               = filters-              , optEmailObfuscation      = obfuscationMethod-              , optIdentifierPrefix      = idPrefix-              , optIndentedCodeClasses   = codeBlockClasses-              , optDataDir               = mbDataDir-              , optCiteMethod            = citeMethod-              , optListings              = listings-              , optLaTeXEngine           = latexEngine-              , optLaTeXEngineArgs       = latexEngineArgs-              , optSlideLevel            = slideLevel-              , optSetextHeaders         = setextHeaders-              , optAscii                 = ascii-              , optTeXLigatures          = texLigatures-              , optDefaultImageExtension = defaultImageExtension-              , optExtractMedia          = mbExtractMedia-              , optTrace                 = trace-              , optTrackChanges          = trackChanges-              , optFileScope            = fileScope-              , optKaTeXStylesheet       = katexStylesheet-              , optKaTeXJS               = katexJS-             } = opts--  when dumpArgs $-    do UTF8.hPutStrLn stdout outputFile-       mapM_ (UTF8.hPutStrLn stdout) args-       exitSuccess--  let csscdn = "https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.6.0/katex.min.css"-  let mathMethod =-        case (katexJS, katexStylesheet) of-            (Nothing, _) -> mathMethod'-            (Just js, ss) -> KaTeX js (fromMaybe csscdn ss)---  -- --bibliography implies -F pandoc-citeproc for backwards compatibility:-  let needsCiteproc = isJust (M.lookup "bibliography" (optMetadata opts)) &&-                      optCiteMethod opts `notElem` [Natbib, Biblatex] &&-                      "pandoc-citeproc" `notElem` map takeBaseName filters-  let filters' = if needsCiteproc then "pandoc-citeproc" : filters-                                  else filters--  let sources = if ignoreArgs then [] else args--  datadir <- case mbDataDir of-                  Nothing   -> E.catch-                                 (Just <$> getAppUserDataDirectory "pandoc")-                                 (\e -> let _ = (e :: E.SomeException)-                                        in  return Nothing)-                  Just _    -> return mbDataDir--  -- assign reader and writer based on options and filenames-  let readerName' = case map toLower readerName of-                          []       -> defaultReaderName-                                      (if any isURI sources-                                          then "html"-                                          else "markdown") sources-                          "html4"  -> "html"-                          x        -> x--  let writerName' = case map toLower writerName of-                          []        -> defaultWriterName outputFile-                          "epub2"   -> "epub"-                          "html4"   -> "html"-                          x         -> x-  let format = takeWhile (`notElem` ['+','-'])-                       $ takeFileName writerName'  -- in case path to lua script--  let pdfOutput = map toLower (takeExtension outputFile) == ".pdf"--  let laTeXOutput = format `elem` ["latex", "beamer"]-  let conTeXtOutput = format == "context"-  let html5Output = format == "html5"--  let laTeXInput = "latex" `isPrefixOf` readerName' ||-                    "beamer" `isPrefixOf` readerName'--  writer <- if ".lua" `isSuffixOf` format-               -- note:  use non-lowercased version writerName-               then return $ IOStringWriter $ writeCustom writerName-               else case getWriter writerName' of-                         Left e  -> err 9 $-                           if format == "pdf"-                              then e ++-                               "\nTo create a pdf with pandoc, use " ++-                               "the latex or beamer writer and specify\n" ++-                               "an output file with .pdf extension " ++-                               "(pandoc -t latex -o filename.pdf)."-                              else e-                         Right w -> return w--  reader <- if "t2t" == readerName'-              then (mkStringReader .-                    readTxt2Tags) <$>-                      getT2TMeta sources outputFile-              else case getReader readerName' of-                Right r  -> return r-                Left e   -> err 7 e'-                  where e' = case readerName' of-                                  "pdf" -> e ++-                                     "\nPandoc can convert to PDF, but not from PDF."-                                  "doc" -> e ++-                                     "\nPandoc can convert from DOCX, but not from DOC.\nTry using Word to save your DOC file as DOCX, and convert that with pandoc."-                                  _ -> e--  let standalone' = standalone || not (isTextFormat format) || pdfOutput--  templ <- case templatePath of-                _ | not standalone' -> return Nothing-                Nothing -> do-                           deftemp <- getDefaultTemplate datadir format-                           case deftemp of-                                 Left e   -> throwIO e-                                 Right t  -> return (Just t)-                Just tp -> do-                           -- strip off extensions-                           let tp' = case takeExtension tp of-                                          ""   -> tp <.> format-                                          _    -> tp-                           Just <$> E.catch (UTF8.readFile tp')-                             (\e -> if isDoesNotExistError e-                                       then E.catch-                                             (readDataFileUTF8 datadir-                                                ("templates" </> tp'))-                                             (\e' -> let _ = (e' :: E.SomeException)-                                                     in throwIO e')-                                       else throwIO e)--  variables' <- case mathMethod of-                      LaTeXMathML Nothing -> do-                         s <- readDataFileUTF8 datadir "LaTeXMathML.js"-                         return $ ("mathml-script", s) : variables-                      _ -> return variables--  variables'' <- if format == "dzslides"-                    then do-                        dztempl <- readDataFileUTF8 datadir-                                     ("dzslides" </> "template.html")-                        let dzline = "<!-- {{{{ dzslides core"-                        let dzcore = unlines-                                   $ dropWhile (not . (dzline `isPrefixOf`))-                                   $ lines dztempl-                        return $ ("dzslides-core", dzcore) : variables'-                    else return variables'--  let sourceURL = case sources of-                    []    -> Nothing-                    (x:_) -> case parseURI x of-                                Just u-                                  | uriScheme u `elem` ["http:","https:"] ->-                                      Just $ show u{ uriQuery = "",-                                                     uriFragment = "" }-                                _ -> Nothing--  let readerOpts = def{ readerSmart = if laTeXInput-                                         then texLigatures-                                         else smart || (texLigatures &&-                                               (laTeXOutput || conTeXtOutput))-                      , readerStandalone = standalone'-                      , readerParseRaw = parseRaw-                      , readerColumns = columns-                      , readerTabStop = tabStop-                      , readerOldDashes = oldDashes-                      , readerIndentedCodeClasses = codeBlockClasses-                      , readerApplyMacros = not laTeXOutput-                      , readerDefaultImageExtension = defaultImageExtension-                      , readerTrace = trace-                      , readerTrackChanges = trackChanges-                      , readerFileScope   = fileScope-                      }--#ifdef _WINDOWS-  let istty = True-#else-  istty <- queryTerminal stdOutput-#endif-  when (istty && not (isTextFormat format) && outputFile == "-") $-    err 5 $ "Cannot write " ++ format ++ " output to stdout.\n" ++-            "Specify an output file using the -o option."--  let readSources [] = mapM readSource ["-"]-      readSources srcs = mapM readSource srcs-      readSource "-" = UTF8.getContents-      readSource src = case parseURI src of-                            Just u | uriScheme u `elem` ["http:","https:"] ->-                                       readURI src-                                   | uriScheme u == "file:" ->-                                       UTF8.readFile (uriPath u)-                            _       -> UTF8.readFile src-      readURI src = do-        res <- openURL src-        case res of-             Left e        -> throwIO e-             Right (bs,_)  -> return $ UTF8.toString bs--  let readFiles [] = error "Cannot read archive from stdin"-      readFiles [x] = B.readFile x-      readFiles (x:xs) = mapM_ (warn . ("Ignoring: " ++)) xs >> B.readFile x--  let convertTabs = tabFilter (if preserveTabs || readerName' == "t2t"-                                 then 0-                                 else tabStop)--  let handleIncludes' :: String -> IO (Either PandocError String)-      handleIncludes' = if readerName' `elem`  ["latex", "latex+lhs"]-                               then handleIncludes-                               else return . Right--  let sourceToDoc :: [FilePath] -> IO (Pandoc, MediaBag)-      sourceToDoc sources' = fmap handleError $-        case reader of-          StringReader r-> do-            srcs <- convertTabs . intercalate "\n" <$> readSources sources'-            doc <- handleIncludes' srcs-            either (return . Left) (\s -> fmap (,mempty) <$> r readerOpts s) doc-          ByteStringReader r -> readFiles sources' >>= r readerOpts--  -- We parse first if (1) fileScope is set, (2), it's a binary-  -- reader, or (3) we're reading JSON. This is easier to do of an AND-  -- of negatives as opposed to an OR of positives, so we do default-  -- parsing if it's a StringReader AND (fileScope is set AND it's not-  -- a JSON reader).-  (doc, media) <- case reader of-    (StringReader _) | not fileScope && readerName' /= "json" ->-                         sourceToDoc sources-    _ | null sources -> sourceToDoc sources-    _  -> do pairs <- mapM (\s -> sourceToDoc [s]) sources-             return (mconcat $ map fst pairs, mconcat $ map snd pairs)--  let writerOptions = def { writerTemplate         = templ,-                            writerVariables        = variables'',-                            writerTabStop          = tabStop,-                            writerTableOfContents  = toc,-                            writerHTMLMathMethod   = mathMethod,-                            writerIncremental      = incremental,-                            writerCiteMethod       = citeMethod,-                            writerIgnoreNotes      = False,-                            writerNumberSections   = numberSections,-                            writerNumberOffset     = numberFrom,-                            writerSectionDivs      = sectionDivs,-                            writerReferenceLinks   = referenceLinks,-                            writerReferenceLocation = referenceLocation,-                            writerDpi              = dpi,-                            writerWrapText         = wrap,-                            writerColumns          = columns,-                            writerEmailObfuscation = obfuscationMethod,-                            writerIdentifierPrefix = idPrefix,-                            writerSourceURL        = sourceURL,-                            writerUserDataDir      = datadir,-                            writerHtml5            = html5,-                            writerHtmlQTags        = htmlQTags,-                            writerTopLevelDivision = topLevelDivision,-                            writerListings         = listings,-                            writerBeamer           = False,-                            writerSlideLevel       = slideLevel,-                            writerHighlight        = highlight,-                            writerHighlightStyle   = highlightStyle,-                            writerSetextHeaders    = setextHeaders,-                            writerTeXLigatures     = texLigatures,-                            writerEpubMetadata     = epubMetadata,-                            writerEpubStylesheet   = epubStylesheet,-                            writerEpubFonts        = epubFonts,-                            writerEpubChapterLevel = epubChapterLevel,-                            writerTOCDepth         = epubTOCDepth,-                            writerReferenceODT     = referenceODT,-                            writerReferenceDocx    = referenceDocx,-                            writerMediaBag         = media,-                            writerVerbose          = verbose,-                            writerLaTeXArgs        = latexEngineArgs-                          }---  doc' <- (maybe return (extractMedia media) mbExtractMedia >=>-           adjustMetadata metadata >=>-           applyTransforms transforms >=>-           applyFilters datadir filters' [format]) doc--  let writeFnBinary :: FilePath -> B.ByteString -> IO ()-      writeFnBinary "-" = B.putStr-      writeFnBinary f   = B.writeFile (UTF8.encodePath f)--  let writerFn :: FilePath -> String -> IO ()-      writerFn "-" = UTF8.putStr-      writerFn f   = UTF8.writeFile f--  case writer of-    IOStringWriter f -> f writerOptions doc' >>= writerFn outputFile-    IOByteStringWriter f -> f writerOptions doc' >>= writeFnBinary outputFile-    PureStringWriter f-      | pdfOutput -> do-              -- make sure writer is latex or beamer or context or html5-              unless (laTeXOutput || conTeXtOutput || html5Output) $-                err 47 $ "cannot produce pdf output with " ++ format ++-                         " writer"--              let pdfprog = case () of-                              _ | conTeXtOutput -> "context"-                              _ | html5Output   -> "wkhtmltopdf"-                              _                 -> latexEngine-              -- check for pdf creating program-              mbPdfProg <- findExecutable pdfprog-              when (isNothing mbPdfProg) $-                   err 41 $ pdfprog ++ " not found. " ++-                     pdfprog ++ " is needed for pdf output."--              res <- makePDF pdfprog f writerOptions doc'-              case res of-                   Right pdf -> writeFnBinary outputFile pdf-                   Left err' -> do-                     B.hPutStr stderr err'-                     B.hPut stderr $ B.pack [10]-                     err 43 "Error producing PDF"-      | otherwise -> selfcontain (f writerOptions doc' ++-                                  ['\n' | not standalone'])-                      >>= writerFn outputFile . handleEntities-          where htmlFormat = format `elem`-                  ["html","html5","s5","slidy","slideous","dzslides","revealjs"]-                selfcontain = if selfContained && htmlFormat-                                 then makeSelfContained writerOptions-                                 else return-                handleEntities = if htmlFormat && ascii-                                    then toEntities-                                    else id+{-+Copyright (C) 2006-2017 John MacFarlane <jgm@berkeley.edu>++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation; either version 2 of the License, or+(at your option) any later version.++This program is distributed in the hope that it will be useful,+but WITHOUT ANY WARRANTY; without even the implied warranty of+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+GNU General Public License for more details.++You should have received a copy of the GNU General Public License+along with this program; if not, write to the Free Software+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+-}++{- |+   Module      : Main+   Copyright   : Copyright (C) 2006-2017 John MacFarlane+   License     : GNU GPL, version 2 or above++   Maintainer  : John MacFarlane <jgm@berkeley@edu>+   Stability   : alpha+   Portability : portable++Parses command-line options and calls the appropriate readers and+writers.+-}+module Main where+import qualified Control.Exception as E+import Text.Pandoc.App (convertWithOpts, defaultOpts, options, parseOptions)+import Text.Pandoc.Error (handleError)++main :: IO ()+main = E.catch (parseOptions options defaultOpts >>= convertWithOpts)+          (handleError . Left)
src/Text/Pandoc.hs view
@@ -1,6 +1,8 @@-{-# LANGUAGE ScopedTypeVariables, FlexibleInstances #-}+{-# LANGUAGE FlexibleInstances   #-}+{-# LANGUAGE GADTs               #-}+{-# LANGUAGE ScopedTypeVariables #-} {--Copyright (C) 2006-2016 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2006-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -19,7 +21,7 @@  {- |    Module      : Text.Pandoc-   Copyright   : Copyright (C) 2006-2016 John MacFarlane+   Copyright   : Copyright (C) 2006-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -37,17 +39,18 @@  > module Main where > import Text.Pandoc->-> markdownToRST :: String -> String-> markdownToRST =->   writeRST def {writerReferenceLinks = True} .->   handleError . readMarkdown def+> import Data.Text (Text)+> import qualified Data.Text.IO as T >-> main = getContents >>= putStrLn . markdownToRST+> mdToRST :: Text -> IO Text+> mdToRST txt = runIOorExplode $+>   readMarkdown def txt+>   >>= writeRST def{ writerReferenceLinks = True } -Note:  all of the readers assume that the input text has @'\n'@-line endings.  So if you get your input text from a web form,-you should remove @'\r'@ characters using @filter (/='\r')@.+>+> main :: IO ()+> main = do+>   T.getContents >>= mdToRST >>= T.putStrLn  -} @@ -59,332 +62,29 @@                , module Text.Pandoc.Generic                -- * Options                , module Text.Pandoc.Options+               -- * Logging+               , module Text.Pandoc.Logging+               -- * Typeclass+               , module Text.Pandoc.Class                -- * Error handling                , module Text.Pandoc.Error-               -- * Lists of readers and writers-               , readers-               , writers                -- * Readers: converting /to/ Pandoc format-               , Reader (..)-               , mkStringReader-               , readDocx-               , readOdt-               , readMarkdown-               , readCommonMark-               , readMediaWiki-               , readRST-               , readOrg-               , readLaTeX-               , readHtml-               , readTextile-               , readDocBook-               , readOPML-               , readHaddock-               , readNative-               , readJSON-               , readTWiki-               , readTxt2Tags-               , readTxt2TagsNoMacros-               , readEPUB+               , module Text.Pandoc.Readers                -- * Writers: converting /from/ Pandoc format-              , Writer (..)-               , writeNative-               , writeJSON-               , writeMarkdown-               , writePlain-               , writeRST-               , writeLaTeX-               , writeConTeXt-               , writeTexinfo-               , writeHtml-               , writeHtmlString-               , writeICML-               , writeDocbook-               , writeOPML-               , writeOpenDocument-               , writeMan-               , writeMediaWiki-               , writeDokuWiki-               , writeZimWiki-               , writeTextile-               , writeRTF-               , writeODT-               , writeDocx-               , writeEPUB-               , writeFB2-               , writeOrg-               , writeAsciiDoc-               , writeHaddock-               , writeCommonMark-               , writeCustom-               , writeTEI+               , module Text.Pandoc.Writers                -- * Rendering templates and default templates                , module Text.Pandoc.Templates                -- * Miscellaneous-               , getReader-               , getWriter-               , getDefaultExtensions-               , ToJsonFilter(..)                , pandocVersion              ) where +import Text.Pandoc.Class import Text.Pandoc.Definition+import Text.Pandoc.Error import Text.Pandoc.Generic-import Text.Pandoc.JSON-import Text.Pandoc.Readers.Markdown-import Text.Pandoc.Readers.CommonMark-import Text.Pandoc.Readers.MediaWiki-import Text.Pandoc.Readers.RST-import Text.Pandoc.Readers.Org-import Text.Pandoc.Readers.DocBook-import Text.Pandoc.Readers.OPML-import Text.Pandoc.Readers.LaTeX-import Text.Pandoc.Readers.HTML-import Text.Pandoc.Readers.Textile-import Text.Pandoc.Readers.Native-import Text.Pandoc.Readers.Haddock-import Text.Pandoc.Readers.TWiki-import Text.Pandoc.Readers.Docx-import Text.Pandoc.Readers.Odt-import Text.Pandoc.Readers.Txt2Tags-import Text.Pandoc.Readers.EPUB-import Text.Pandoc.Writers.Native-import Text.Pandoc.Writers.Markdown-import Text.Pandoc.Writers.RST-import Text.Pandoc.Writers.LaTeX-import Text.Pandoc.Writers.ConTeXt-import Text.Pandoc.Writers.Texinfo-import Text.Pandoc.Writers.HTML-import Text.Pandoc.Writers.ODT-import Text.Pandoc.Writers.Docx-import Text.Pandoc.Writers.EPUB-import Text.Pandoc.Writers.FB2-import Text.Pandoc.Writers.ICML-import Text.Pandoc.Writers.Docbook-import Text.Pandoc.Writers.OPML-import Text.Pandoc.Writers.OpenDocument-import Text.Pandoc.Writers.Man-import Text.Pandoc.Writers.RTF-import Text.Pandoc.Writers.MediaWiki-import Text.Pandoc.Writers.DokuWiki-import Text.Pandoc.Writers.ZimWiki-import Text.Pandoc.Writers.Textile-import Text.Pandoc.Writers.Org-import Text.Pandoc.Writers.AsciiDoc-import Text.Pandoc.Writers.Haddock-import Text.Pandoc.Writers.CommonMark-import Text.Pandoc.Writers.Custom-import Text.Pandoc.Writers.TEI-import Text.Pandoc.Templates+import Text.Pandoc.Logging import Text.Pandoc.Options-import Text.Pandoc.Shared (safeRead, warn, mapLeft, pandocVersion)-import Text.Pandoc.MediaBag (MediaBag)-import Text.Pandoc.Error-import Data.Aeson-import qualified Data.ByteString.Lazy as BL-import Data.List (intercalate)-import Data.Set (Set)-import qualified Data.Set as Set-import Text.Parsec-import Text.Parsec.Error-import qualified Text.Pandoc.UTF8 as UTF8--parseFormatSpec :: String-                -> Either ParseError (String, Set Extension -> Set Extension)-parseFormatSpec = parse formatSpec ""-  where formatSpec = do-          name <- formatName-          extMods <- many extMod-          return (name, \x -> foldl (flip ($)) x extMods)-        formatName = many1 $ noneOf "-+"-        extMod = do-          polarity <- oneOf "-+"-          name <- many $ noneOf "-+"-          ext <- case safeRead ("Ext_" ++ name) of-                       Just n  -> return n-                       Nothing-                         | name == "lhs" -> return Ext_literate_haskell-                         | otherwise -> fail $ "Unknown extension: " ++ name-          return $ case polarity of-                        '-'  -> Set.delete ext-                        _    -> Set.insert ext---data Reader = StringReader (ReaderOptions -> String -> IO (Either PandocError Pandoc))-              | ByteStringReader (ReaderOptions -> BL.ByteString -> IO (Either PandocError (Pandoc,MediaBag)))--mkStringReader :: (ReaderOptions -> String -> Either PandocError Pandoc) -> Reader-mkStringReader r = StringReader (\o s -> return $ r o s)--mkStringReaderWithWarnings :: (ReaderOptions -> String -> Either PandocError (Pandoc, [String])) -> Reader-mkStringReaderWithWarnings r  = StringReader $ \o s ->-  case r o s of-    Left err -> return $ Left err-    Right (doc, warnings) -> do-      mapM_ warn warnings-      return (Right doc)--mkBSReader :: (ReaderOptions -> BL.ByteString -> Either PandocError (Pandoc, MediaBag)) -> Reader-mkBSReader r = ByteStringReader (\o s -> return $ r o s)--mkBSReaderWithWarnings :: (ReaderOptions -> BL.ByteString -> Either PandocError (Pandoc, MediaBag, [String])) -> Reader-mkBSReaderWithWarnings r = ByteStringReader $ \o s ->-  case r o s of-    Left err -> return $ Left err-    Right (doc, mediaBag, warnings) -> do-      mapM_ warn warnings-      return $ Right (doc, mediaBag)---- | Association list of formats and readers.-readers :: [(String, Reader)]-readers = [ ("native"       , StringReader $ \_ s -> return $ readNative s)-           ,("json"         , mkStringReader readJSON )-           ,("markdown"     , mkStringReaderWithWarnings readMarkdownWithWarnings)-           ,("markdown_strict" , mkStringReaderWithWarnings readMarkdownWithWarnings)-           ,("markdown_phpextra" , mkStringReaderWithWarnings readMarkdownWithWarnings)-           ,("markdown_github" , mkStringReaderWithWarnings readMarkdownWithWarnings)-           ,("markdown_mmd",  mkStringReaderWithWarnings readMarkdownWithWarnings)-           ,("commonmark"   , mkStringReader readCommonMark)-           ,("rst"          , mkStringReaderWithWarnings readRSTWithWarnings )-           ,("mediawiki"    , mkStringReader readMediaWiki)-           ,("docbook"      , mkStringReader readDocBook)-           ,("opml"         , mkStringReader readOPML)-           ,("org"          , mkStringReader readOrg)-           ,("textile"      , mkStringReader readTextile) -- TODO : textile+lhs-           ,("html"         , mkStringReader readHtml)-           ,("latex"        , mkStringReader readLaTeX)-           ,("haddock"      , mkStringReader readHaddock)-           ,("twiki"        , mkStringReader readTWiki)-           ,("docx"         , mkBSReaderWithWarnings readDocxWithWarnings)-           ,("odt"          , mkBSReader readOdt)-           ,("t2t"          , mkStringReader readTxt2TagsNoMacros)-           ,("epub"         , mkBSReader readEPUB)-           ]--data Writer = PureStringWriter   (WriterOptions -> Pandoc -> String)-            | IOStringWriter     (WriterOptions -> Pandoc -> IO String)-            | IOByteStringWriter (WriterOptions -> Pandoc -> IO BL.ByteString)---- | Association list of formats and writers.-writers :: [ ( String, Writer ) ]-writers = [-   ("native"       , PureStringWriter writeNative)-  ,("json"         , PureStringWriter writeJSON)-  ,("docx"         , IOByteStringWriter writeDocx)-  ,("odt"          , IOByteStringWriter writeODT)-  ,("epub"         , IOByteStringWriter $ \o ->-                      writeEPUB o{ writerEpubVersion = Just EPUB2 })-  ,("epub3"        , IOByteStringWriter $ \o ->-                       writeEPUB o{ writerEpubVersion = Just EPUB3 })-  ,("fb2"          , IOStringWriter writeFB2)-  ,("html"         , PureStringWriter writeHtmlString)-  ,("html5"        , PureStringWriter $ \o ->-     writeHtmlString o{ writerHtml5 = True })-  ,("icml"         , IOStringWriter writeICML)-  ,("s5"           , PureStringWriter $ \o ->-     writeHtmlString o{ writerSlideVariant = S5Slides-                      , writerTableOfContents = False })-  ,("slidy"        , PureStringWriter $ \o ->-     writeHtmlString o{ writerSlideVariant = SlidySlides })-  ,("slideous"     , PureStringWriter $ \o ->-     writeHtmlString o{ writerSlideVariant = SlideousSlides })-  ,("dzslides"     , PureStringWriter $ \o ->-     writeHtmlString o{ writerSlideVariant = DZSlides-                      , writerHtml5 = True })-  ,("revealjs"      , PureStringWriter $ \o ->-     writeHtmlString o{ writerSlideVariant = RevealJsSlides-                      , writerHtml5 = True })-  ,("docbook"      , PureStringWriter writeDocbook)-  ,("docbook5"     , PureStringWriter $ \o ->-     writeDocbook o{ writerDocbook5 = True })-  ,("opml"         , PureStringWriter writeOPML)-  ,("opendocument" , PureStringWriter writeOpenDocument)-  ,("latex"        , PureStringWriter writeLaTeX)-  ,("beamer"       , PureStringWriter $ \o ->-     writeLaTeX o{ writerBeamer = True })-  ,("context"      , PureStringWriter writeConTeXt)-  ,("texinfo"      , PureStringWriter writeTexinfo)-  ,("man"          , PureStringWriter writeMan)-  ,("markdown"     , PureStringWriter writeMarkdown)-  ,("markdown_strict" , PureStringWriter writeMarkdown)-  ,("markdown_phpextra" , PureStringWriter writeMarkdown)-  ,("markdown_github" , PureStringWriter writeMarkdown)-  ,("markdown_mmd" , PureStringWriter writeMarkdown)-  ,("plain"        , PureStringWriter writePlain)-  ,("rst"          , PureStringWriter writeRST)-  ,("mediawiki"    , PureStringWriter writeMediaWiki)-  ,("dokuwiki"     , PureStringWriter writeDokuWiki)-  ,("zimwiki"      , PureStringWriter writeZimWiki)-  ,("textile"      , PureStringWriter writeTextile)-  ,("rtf"          , IOStringWriter writeRTFWithEmbeddedImages)-  ,("org"          , PureStringWriter writeOrg)-  ,("asciidoc"     , PureStringWriter writeAsciiDoc)-  ,("haddock"      , PureStringWriter writeHaddock)-  ,("commonmark"   , PureStringWriter writeCommonMark)-  ,("tei"          , PureStringWriter writeTEI)-  ]--getDefaultExtensions :: String -> Set Extension-getDefaultExtensions "markdown_strict" = strictExtensions-getDefaultExtensions "markdown_phpextra" = phpMarkdownExtraExtensions-getDefaultExtensions "markdown_mmd" = multimarkdownExtensions-getDefaultExtensions "markdown_github" = githubMarkdownExtensions-getDefaultExtensions "markdown"        = pandocExtensions-getDefaultExtensions "plain"           = plainExtensions-getDefaultExtensions "org"             = Set.fromList [Ext_citations,-                                                       Ext_auto_identifiers]-getDefaultExtensions "textile"         = Set.fromList [Ext_auto_identifiers]-getDefaultExtensions "html"            = Set.fromList [Ext_auto_identifiers,-                                                       Ext_native_divs,-                                                       Ext_native_spans]-getDefaultExtensions "html5"           = getDefaultExtensions "html"-getDefaultExtensions "epub"            = Set.fromList [Ext_raw_html,-                                                       Ext_native_divs,-                                                       Ext_native_spans,-                                                       Ext_epub_html_exts]-getDefaultExtensions _                 = Set.fromList [Ext_auto_identifiers]---- | Retrieve reader based on formatSpec (format+extensions).-getReader :: String -> Either String Reader-getReader s =-  case parseFormatSpec s of-       Left e  -> Left $ intercalate "\n" [m | Message m <- errorMessages e]-       Right (readerName, setExts) ->-           case lookup readerName readers of-                   Nothing  -> Left $ "Unknown reader: " ++ readerName-                   Just  (StringReader r)  -> Right $ StringReader $ \o ->-                                  r o{ readerExtensions = setExts $-                                            getDefaultExtensions readerName }-                   Just (ByteStringReader r) -> Right $ ByteStringReader $ \o ->-                                  r o{ readerExtensions = setExts $-                                            getDefaultExtensions readerName }---- | Retrieve writer based on formatSpec (format+extensions).-getWriter :: String -> Either String Writer-getWriter s-  = case parseFormatSpec s of-         Left e  -> Left $ intercalate "\n" [m | Message m <- errorMessages e]-         Right (writerName, setExts) ->-             case lookup writerName writers of-                     Nothing -> Left $ "Unknown writer: " ++ writerName-                     Just (PureStringWriter r) -> Right $ PureStringWriter $-                             \o -> r o{ writerExtensions = setExts $-                                              getDefaultExtensions writerName }-                     Just (IOStringWriter r) -> Right $ IOStringWriter $-                             \o -> r o{ writerExtensions = setExts $-                                              getDefaultExtensions writerName }-                     Just (IOByteStringWriter r) -> Right $ IOByteStringWriter $-                             \o -> r o{ writerExtensions = setExts $-                                              getDefaultExtensions writerName }--{-# DEPRECATED toJsonFilter "Use 'toJSONFilter' from 'Text.Pandoc.JSON' instead" #-}--- | Deprecated.  Use @toJSONFilter@ from @Text.Pandoc.JSON@ instead.-class ToJSONFilter a => ToJsonFilter a-  where toJsonFilter :: a -> IO ()-        toJsonFilter = toJSONFilter--readJSON :: ReaderOptions -> String -> Either PandocError Pandoc-readJSON _ = mapLeft ParseFailure . eitherDecode' . UTF8.fromStringLazy--writeJSON :: WriterOptions -> Pandoc -> String-writeJSON _ = UTF8.toStringLazy . encode+import Text.Pandoc.Readers+import Text.Pandoc.Shared (pandocVersion)+import Text.Pandoc.Templates+import Text.Pandoc.Writers
+ src/Text/Pandoc/App.hs view
@@ -0,0 +1,1657 @@+{-# LANGUAGE CPP                 #-}+{-# LANGUAGE DeriveGeneric       #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TupleSections       #-}+{-+Copyright (C) 2006-2017 John MacFarlane <jgm@berkeley.edu>++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation; either version 2 of the License, or+(at your option) any later version.++This program is distributed in the hope that it will be useful,+but WITHOUT ANY WARRANTY; without even the implied warranty of+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+GNU General Public License for more details.++You should have received a copy of the GNU General Public License+along with this program; if not, write to the Free Software+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+-}++{- |+   Module      : Text.Pandoc.App+   Copyright   : Copyright (C) 2006-2017 John MacFarlane+   License     : GNU GPL, version 2 or above++   Maintainer  : John MacFarlane <jgm@berkeley@edu>+   Stability   : alpha+   Portability : portable++Does a pandoc conversion based on command-line options.+-}+module Text.Pandoc.App (+            convertWithOpts+          , Opt(..)+          , defaultOpts+          , parseOptions+          , options+          , applyFilters+          , applyLuaFilters+          ) where+import qualified Control.Exception as E+import Control.Monad+import Control.Monad.Except (catchError, throwError)+import Control.Monad.Trans+import Data.Aeson (FromJSON (..), ToJSON (..), defaultOptions, eitherDecode',+                   encode, genericToEncoding)+import qualified Data.ByteString as BS+import qualified Data.ByteString.Lazy as B+import Data.Char (toLower, toUpper)+import Data.Foldable (foldrM)+import Data.List (find, intercalate, isPrefixOf, isSuffixOf, sort)+import qualified Data.Map as M+import Data.Maybe (fromMaybe, isJust, isNothing)+import Data.Monoid+import qualified Data.Set as Set+import Data.Text (Text)+import qualified Data.Text as T+import Data.Yaml (decode)+import qualified Data.Yaml as Yaml+import GHC.Generics+import Network.URI (URI (..), parseURI)+import Paths_pandoc (getDataDir)+import Skylighting (Style, Syntax (..), defaultSyntaxMap, parseTheme)+import Skylighting.Parser (addSyntaxDefinition, missingIncludes,+                           parseSyntaxDefinition)+import System.Console.GetOpt+import System.Directory (Permissions (..), doesFileExist, findExecutable,+                         getAppUserDataDirectory, getPermissions)+import System.Environment (getArgs, getEnvironment, getProgName)+import System.Exit (ExitCode (..), exitSuccess)+import System.FilePath+import System.IO (nativeNewline, stdout)+import qualified System.IO as IO (Newline (..))+import System.IO.Error (isDoesNotExistError)+import Text.Pandoc+import Text.Pandoc.BCP47 (Lang (..), parseBCP47)+import Text.Pandoc.Builder (setMeta)+import Text.Pandoc.Highlighting (highlightingStyles)+import Text.Pandoc.Lua (LuaException (..), runLuaFilter)+import Text.Pandoc.PDF (makePDF)+import Text.Pandoc.Process (pipeProcess)+import Text.Pandoc.SelfContained (makeDataURI, makeSelfContained)+import Text.Pandoc.Shared (eastAsianLineBreakFilter, headerShift, isURI, ordNub,+                           safeRead, tabFilter)+import qualified Text.Pandoc.UTF8 as UTF8+import Text.Pandoc.Writers.Math (defaultKaTeXURL, defaultMathJaxURL)+import Text.Pandoc.XML (toEntities)+import Text.Printf+#ifndef _WINDOWS+import System.Posix.IO (stdOutput)+import System.Posix.Terminal (queryTerminal)+#endif++data LineEnding = LF | CRLF | Native deriving (Show, Generic)++instance ToJSON LineEnding where+  toEncoding = genericToEncoding defaultOptions+instance FromJSON LineEnding++parseOptions :: [OptDescr (Opt -> IO Opt)] -> Opt -> IO Opt+parseOptions options' defaults = do+  rawArgs <- map UTF8.decodeArg <$> getArgs+  prg <- getProgName++  let (actions, args, unrecognizedOpts, errors) =+           getOpt' Permute options' rawArgs++  let unknownOptionErrors =+       foldr (handleUnrecognizedOption . takeWhile (/= '=')) []+       unrecognizedOpts++  unless (null errors && null unknownOptionErrors) $+     E.throwIO $ PandocOptionError $+        concat errors ++ unlines unknownOptionErrors +++        ("Try " ++ prg ++ " --help for more information.")++  -- thread option data structure through all supplied option actions+  opts <- foldl (>>=) (return defaults) actions+  return (opts{ optInputFiles = args })++latexEngines :: [String]+latexEngines  = ["pdflatex", "lualatex", "xelatex"]++htmlEngines :: [String]+htmlEngines  = ["wkhtmltopdf", "weasyprint", "prince"]++engines :: [(String, String)]+engines = map ("html",) htmlEngines +++          map ("html5",) htmlEngines +++          map ("latex",) latexEngines +++          map ("beamer",) latexEngines +++          [ ("ms", "pdfroff")+          , ("context", "context")+          ]++pdfEngines :: [String]+pdfEngines = ordNub $ map snd engines++pdfWriterAndProg :: Maybe String              -- ^ user-specified writer name+                 -> Maybe String              -- ^ user-specified pdf-engine+                 -> IO (String, Maybe String) -- ^ IO (writerName, maybePdfEngineProg)+pdfWriterAndProg mWriter mEngine = do+  let panErr msg = liftIO $ E.throwIO $ PandocAppError msg+  case go (baseWriterName <$> mWriter) mEngine of+      Right (writ, prog) -> return (writ, Just prog)+      Left err           -> panErr err+    where+      go Nothing Nothing       = Right ("latex", "pdflatex")+      go (Just writer) Nothing = (writer,) <$> engineForWriter writer+      go Nothing (Just engine) = (,engine) <$> writerForEngine engine+      go (Just writer) (Just engine) =+           case find (== (writer, engine)) engines of+                Just _  -> Right (writer, engine)+                Nothing -> Left $ "pdf-engine " ++ engine +++                           " is not compatible with output format " ++ writer++      writerForEngine eng = case [f | (f,e) <- engines, e == eng] of+                                 fmt : _ -> Right fmt+                                 []      -> Left $+                                   "pdf-engine " ++ eng ++ " not known"++      engineForWriter w = case [e |  (f,e) <- engines, f == w] of+                                eng : _ -> Right eng+                                []      -> Left $+                                   "cannot produce pdf output from " ++ w++convertWithOpts :: Opt -> IO ()+convertWithOpts opts = do+  let outputFile = fromMaybe "-" (optOutputFile opts)+  let filters = optFilters opts+  let verbosity = optVerbosity opts++  when (optDumpArgs opts) $+    do UTF8.hPutStrLn stdout outputFile+       mapM_ (UTF8.hPutStrLn stdout) (optInputFiles opts)+       exitSuccess++  epubMetadata <- case optEpubMetadata opts of+                         Nothing -> return Nothing+                         Just fp -> Just <$> UTF8.readFile fp++  -- --bibliography implies -F pandoc-citeproc for backwards compatibility:+  let needsCiteproc = isJust (lookup "bibliography" (optMetadata opts)) &&+                      optCiteMethod opts `notElem` [Natbib, Biblatex] &&+                      "pandoc-citeproc" `notElem` map takeBaseName filters+  let filters' = if needsCiteproc then "pandoc-citeproc" : filters+                                  else filters++  let sources = case optInputFiles opts of+                     []  -> ["-"]+                     xs | optIgnoreArgs opts -> ["-"]+                        | otherwise  -> xs++  datadir <- case optDataDir opts of+                  Nothing   -> E.catch+                                 (Just <$> getAppUserDataDirectory "pandoc")+                                 (\e -> let _ = (e :: E.SomeException)+                                        in  return Nothing)+                  Just _    -> return $ optDataDir opts++  -- assign reader and writer based on options and filenames+  let readerName =  fromMaybe ( defaultReaderName+                  (if any isURI sources+                      then "html"+                      else "markdown") sources) (optReader opts)++  let nonPdfWriterName Nothing  = defaultWriterName outputFile+      nonPdfWriterName (Just x) = x++  let pdfOutput = map toLower (takeExtension outputFile) == ".pdf"+  (writerName, maybePdfProg) <-+    if pdfOutput+       then pdfWriterAndProg (optWriter opts) (optPdfEngine opts)+       else return (nonPdfWriterName $ optWriter opts, Nothing)++  let format = baseWriterName+                 $ takeFileName writerName  -- in case path to lua script++  -- disabling the custom writer for now+  (writer, writerExts) <-+            if ".lua" `isSuffixOf` format+               -- note:  use non-lowercased version writerName+               then return (TextWriter+                       (\o d -> liftIO $ writeCustom writerName o d)+                               :: Writer PandocIO, mempty)+               else case getWriter writerName of+                         Left e  -> E.throwIO $ PandocAppError $+                           if format == "pdf"+                              then e +++                               "\nTo create a pdf using pandoc, use " +++                               "-t latex|beamer|context|ms|html5" +++                               "\nand specify an output file with " +++                               ".pdf extension (-o filename.pdf)."+                              else e+                         Right (w, es) -> return (w :: Writer PandocIO, es)++  -- TODO: we have to get the input and the output into the state for+  -- the sake of the text2tags reader.+  (reader, readerExts) <-+           case getReader readerName of+                Right (r, es) -> return (r :: Reader PandocIO, es)+                Left e   -> E.throwIO $ PandocAppError e'+                  where e' = case readerName of+                                  "pdf" -> e +++                                     "\nPandoc can convert to PDF, but not from PDF."+                                  "doc" -> e +++                                     "\nPandoc can convert from DOCX, but not from DOC.\nTry using Word to save your DOC file as DOCX, and convert that with pandoc."+                                  _ -> e++  let standalone = optStandalone opts || not (isTextFormat format) || pdfOutput+  let addStringAsVariable varname s vars = return $ (varname, s) : vars++  highlightStyle <- lookupHighlightStyle $ optHighlightStyle opts+  let addSyntaxMap existingmap f = do+        res <- parseSyntaxDefinition f+        case res of+              Left errstr -> E.throwIO $ PandocSyntaxMapError errstr+              Right syn   -> return $ addSyntaxDefinition syn existingmap++  syntaxMap <- foldM addSyntaxMap defaultSyntaxMap+                     (optSyntaxDefinitions opts)++  case missingIncludes (M.elems syntaxMap) of+       [] -> return ()+       xs -> E.throwIO $ PandocSyntaxMapError $+                "Missing syntax definitions:\n" +++                unlines (map+                  (\(syn,dep) -> (T.unpack syn ++ " requires " +++                    T.unpack dep ++ " through IncludeRules.")) xs)++  -- We don't want to send output to the terminal if the user+  -- does 'pandoc -t docx input.txt'; though we allow them to+  -- force this with '-o -'.  On posix systems, we detect+  -- when stdout is being piped and allow output to stdout+  -- in that case, but on Windows we can't.+#ifdef _WINDOWS+  let istty = True+#else+  istty <- queryTerminal stdOutput+#endif+  when (not (isTextFormat format) && istty && isNothing ( optOutputFile opts)) $+    E.throwIO $ PandocAppError $+            "Cannot write " ++ format ++ " output to terminal.\n" +++            "Specify an output file using the -o option, or " +++            "use '-o -' to force output to stdout."++  let convertTabs = tabFilter (if optPreserveTabs opts || readerName == "t2t"+                                  then 0+                                  else optTabStop opts)++      readSources :: [FilePath] -> PandocIO Text+      readSources srcs = convertTabs . T.intercalate (T.pack "\n") <$>+                            mapM readSource srcs++  let runIO' :: PandocIO a -> IO a+      runIO' f = do+        (res, reports) <- runIOorExplode $ do+                             setTrace (optTrace opts)+                             setVerbosity verbosity+                             x <- f+                             rs <- getLog+                             return (x, rs)+        case optLogFile opts of+             Nothing      -> return ()+             Just logfile -> B.writeFile logfile (encodeLogMessages reports)+        let isWarning msg = messageVerbosity msg == WARNING+        when (optFailIfWarnings opts && any isWarning reports) $+            E.throwIO PandocFailOnWarningError+        return res++  let eol = case optEol opts of+                 CRLF   -> IO.CRLF+                 LF     -> IO.LF+                 Native -> nativeNewline++  -- note: this reverses the list constructed in option parsing,+  -- which in turn was reversed from the command-line order,+  -- so we end up with the correct order in the variable list:+  let withList _ [] vars     = return vars+      withList f (x:xs) vars = f x vars >>= withList f xs++  let addContentsAsVariable varname fp vars = do+             s <- UTF8.toString <$> readFileStrict fp+             return $ (varname, s) : vars++  runIO' $ do+    setUserDataDir datadir+    setInputFiles (optInputFiles opts)+    setOutputFile (optOutputFile opts)++    variables <-+        withList (addStringAsVariable "sourcefile")+                 (reverse $ optInputFiles opts)+                 (("outputfile", fromMaybe "-" (optOutputFile opts))+                  : optVariables opts)+                 -- we reverse this list because, unlike+                 -- the other option lists here, it is+                 -- not reversed when parsed from CLI arguments.+                 -- See withList, above.+        >>=+        withList (addContentsAsVariable "include-before")+                 (optIncludeBeforeBody opts)+        >>=+        withList (addContentsAsVariable "include-after")+                 (optIncludeAfterBody opts)+        >>=+        withList (addContentsAsVariable "header-includes")+                 (optIncludeInHeader opts)+        >>=+        withList (addStringAsVariable "css") (optCss opts)+        >>=+        maybe return (addStringAsVariable "title-prefix")+                     (optTitlePrefix opts)+        >>=+        maybe return (addStringAsVariable "epub-cover-image")+                     (optEpubCoverImage opts)+        >>=+        (\vars -> case optHTMLMathMethod opts of+                       LaTeXMathML Nothing -> do+                          s <- UTF8.toString <$> readDataFile "LaTeXMathML.js"+                          return $ ("mathml-script", s) : vars+                       _ -> return vars)+        >>=+        (\vars ->  if format == "dzslides"+                      then do+                          dztempl <- UTF8.toString <$> readDataFile+                                       ("dzslides" </> "template.html")+                          let dzline = "<!-- {{{{ dzslides core"+                          let dzcore = unlines+                                     $ dropWhile (not . (dzline `isPrefixOf`))+                                     $ lines dztempl+                          return $ ("dzslides-core", dzcore) : vars+                      else return vars)++    abbrevs <- (Set.fromList . filter (not . null) . lines) <$>+               case optAbbreviations opts of+                    Nothing -> UTF8.toString <$> readDataFile "abbreviations"+                    Just f  -> UTF8.toString <$> readFileStrict f++    templ <- case optTemplate opts of+                    _ | not standalone -> return Nothing+                    Nothing -> Just <$> getDefaultTemplate format+                    Just tp -> do+                      -- strip off extensions+                      let tp' = case takeExtension tp of+                                     "" -> tp <.> format+                                     _  -> tp+                      Just . UTF8.toString <$>+                            (readFileStrict tp' `catchError`+                             (\e ->+                                 case e of+                                      PandocIOError _ e' |+                                        isDoesNotExistError e' ->+                                         readDataFile ("templates" </> tp')+                                      _ -> throwError e))++    metadata <- if format == "jats" &&+                   isNothing (lookup "csl" (optMetadata opts)) &&+                   isNothing (lookup "citation-style" (optMetadata opts))+                   then do+                     jatsCSL <- readDataFile "jats.csl"+                     let jatsEncoded = makeDataURI+                                         ("application/xml", jatsCSL)+                     return $ ("csl", jatsEncoded) : optMetadata opts+                   else return $ optMetadata opts++    case lookup "lang" (optMetadata opts) of+           Just l  -> case parseBCP47 l of+                           Left _   -> return ()+                           Right l' -> setTranslations l'+           Nothing -> setTranslations $ Lang "en" "" "US" []++    let writerOptions = def {+            writerTemplate         = templ+          , writerVariables        = variables+          , writerTabStop          = optTabStop opts+          , writerTableOfContents  = optTableOfContents opts+          , writerHTMLMathMethod   = optHTMLMathMethod opts+          , writerIncremental      = optIncremental opts+          , writerCiteMethod       = optCiteMethod opts+          , writerNumberSections   = optNumberSections opts+          , writerNumberOffset     = optNumberOffset opts+          , writerSectionDivs      = optSectionDivs opts+          , writerExtensions       = writerExts+          , writerReferenceLinks   = optReferenceLinks opts+          , writerReferenceLocation = optReferenceLocation opts+          , writerDpi              = optDpi opts+          , writerWrapText         = optWrapText opts+          , writerColumns          = optColumns opts+          , writerEmailObfuscation = optEmailObfuscation opts+          , writerIdentifierPrefix = optIdentifierPrefix opts+          , writerHtmlQTags        = optHtmlQTags opts+          , writerTopLevelDivision = optTopLevelDivision opts+          , writerListings         = optListings opts+          , writerSlideLevel       = optSlideLevel opts+          , writerHighlightStyle   = highlightStyle+          , writerSetextHeaders    = optSetextHeaders opts+          , writerEpubSubdirectory = optEpubSubdirectory opts+          , writerEpubMetadata     = epubMetadata+          , writerEpubFonts        = optEpubFonts opts+          , writerEpubChapterLevel = optEpubChapterLevel opts+          , writerTOCDepth         = optTOCDepth opts+          , writerReferenceDoc     = optReferenceDoc opts+          , writerSyntaxMap        = syntaxMap+          }++    let readerOpts = def{+            readerStandalone = standalone+          , readerColumns = optColumns opts+          , readerTabStop = optTabStop opts+          , readerIndentedCodeClasses = optIndentedCodeClasses opts+          , readerDefaultImageExtension =+             optDefaultImageExtension opts+          , readerTrackChanges = optTrackChanges opts+          , readerAbbreviations = abbrevs+          , readerExtensions = readerExts+          , readerStripComments = optStripComments opts+          }++    let transforms = (case optBaseHeaderLevel opts of+                          x | x > 1     -> (headerShift (x - 1) :)+                            | otherwise -> id) $+                     (if extensionEnabled Ext_east_asian_line_breaks+                            readerExts &&+                         not (extensionEnabled Ext_east_asian_line_breaks+                              writerExts &&+                              writerWrapText writerOptions == WrapPreserve)+                         then (eastAsianLineBreakFilter :)+                         else id)+                     []++    let sourceToDoc :: [FilePath] -> PandocIO Pandoc+        sourceToDoc sources' =+           case reader of+                TextReader r+                  | optFileScope opts || readerName == "json" ->+                      mconcat <$> mapM (readSource >=> r readerOpts) sources+                  | otherwise ->+                      readSources sources' >>= r readerOpts+                ByteStringReader r ->+                  mconcat <$> mapM (readFile' >=> r readerOpts) sources+++    when (readerName == "markdown_github" ||+          writerName == "markdown_github") $+      report $ Deprecated "markdown_github" "Use gfm instead."++    setResourcePath (optResourcePath opts)+    mapM_ (uncurry setRequestHeader) (optRequestHeaders opts)++    doc <- sourceToDoc sources >>=+              (   (if isJust (optExtractMedia opts)+                      then fillMediaBag+                      else return)+              >=> return . flip (foldr addMetadata) metadata+              >=> applyLuaFilters datadir (optLuaFilters opts) format+              >=> maybe return extractMedia (optExtractMedia opts)+              >=> applyTransforms transforms+              >=> applyFilters readerOpts datadir filters' [format]+              )++    case writer of+      ByteStringWriter f -> f writerOptions doc >>= writeFnBinary outputFile+      TextWriter f -> case maybePdfProg of+        Just pdfProg -> do+                res <- makePDF pdfProg (optPdfEngineArgs opts) f+                        writerOptions doc+                case res of+                     Right pdf -> writeFnBinary outputFile pdf+                     Left err' -> liftIO $+                       E.throwIO $ PandocPDFError (UTF8.toStringLazy err')+        Nothing -> do+                let htmlFormat = format `elem`+                      ["html","html4","html5","s5","slidy",+                       "slideous","dzslides","revealjs"]+                    handleEntities = if (htmlFormat ||+                                         format == "docbook4" ||+                                         format == "docbook5" ||+                                         format == "docbook") && optAscii opts+                                     then toEntities+                                     else id+                    addNl = if standalone+                               then id+                               else (<> T.singleton '\n')+                output <- (addNl . handleEntities) <$> f writerOptions doc+                writerFn eol outputFile =<<+                  if optSelfContained opts && htmlFormat+                     -- TODO not maximally efficient; change type+                     -- of makeSelfContained so it works w/ Text+                     then T.pack <$> makeSelfContained (T.unpack output)+                     else return output++type Transform = Pandoc -> Pandoc++isTextFormat :: String -> Bool+isTextFormat s = s `notElem` ["odt","docx","epub","epub3"]++externalFilter :: MonadIO m+               => ReaderOptions -> FilePath -> [String] -> Pandoc -> m Pandoc+externalFilter ropts f args' d = liftIO $ do+  exists <- doesFileExist f+  isExecutable <- if exists+                     then executable <$> getPermissions f+                     else return True+  let (f', args'') = if exists+                        then case map toLower (takeExtension f) of+                                  _      | isExecutable -> ("." </> f, args')+                                  ".py"  -> ("python", f:args')+                                  ".hs"  -> ("runhaskell", f:args')+                                  ".pl"  -> ("perl", f:args')+                                  ".rb"  -> ("ruby", f:args')+                                  ".php" -> ("php", f:args')+                                  ".js"  -> ("node", f:args')+                                  ".r"   -> ("Rscript", f:args')+                                  _      -> (f, args')+                        else (f, args')+  unless (exists && isExecutable) $ do+    mbExe <- findExecutable f'+    when (isNothing mbExe) $+      E.throwIO $ PandocFilterError f ("Could not find executable " ++ f')+  env <- getEnvironment+  let env' = Just+           ( ("PANDOC_VERSION", pandocVersion)+           : ("PANDOC_READER_OPTIONS", UTF8.toStringLazy (encode ropts))+           : env )+  (exitcode, outbs) <- E.handle filterException $+                              pipeProcess env' f' args'' $ encode d+  case exitcode of+       ExitSuccess    -> either (E.throwIO . PandocFilterError f)+                                   return $ eitherDecode' outbs+       ExitFailure ec -> E.throwIO $ PandocFilterError f+                           ("Filter returned error status " ++ show ec)+ where filterException :: E.SomeException -> IO a+       filterException e = E.throwIO $ PandocFilterError f (show e)++-- | Data structure for command line options.+data Opt = Opt+    { optTabStop               :: Int     -- ^ Number of spaces per tab+    , optPreserveTabs          :: Bool    -- ^ Preserve tabs instead of converting to spaces+    , optStandalone            :: Bool    -- ^ Include header, footer+    , optReader                :: Maybe String  -- ^ Reader format+    , optWriter                :: Maybe String  -- ^ Writer format+    , optTableOfContents       :: Bool    -- ^ Include table of contents+    , optBaseHeaderLevel       :: Int     -- ^ Base header level+    , optTemplate              :: Maybe FilePath  -- ^ Custom template+    , optVariables             :: [(String,String)] -- ^ Template variables to set+    , optMetadata              :: [(String, String)] -- ^ Metadata fields to set+    , optOutputFile            :: Maybe FilePath  -- ^ Name of output file+    , optInputFiles            :: [FilePath] -- ^ Names of input files+    , optNumberSections        :: Bool    -- ^ Number sections in LaTeX+    , optNumberOffset          :: [Int]   -- ^ Starting number for sections+    , optSectionDivs           :: Bool    -- ^ Put sections in div tags in HTML+    , optIncremental           :: Bool    -- ^ Use incremental lists in Slidy/Slideous/S5+    , optSelfContained         :: Bool    -- ^ Make HTML accessible offline+    , optHtmlQTags             :: Bool    -- ^ Use <q> tags in HTML+    , optHighlightStyle        :: Maybe String -- ^ Style to use for highlighted code+    , optSyntaxDefinitions     :: [FilePath]  -- ^ xml syntax defs to load+    , optTopLevelDivision      :: TopLevelDivision -- ^ Type of the top-level divisions+    , optHTMLMathMethod        :: HTMLMathMethod -- ^ Method to print HTML math+    , optAbbreviations         :: Maybe FilePath -- ^ Path to abbrevs file+    , optReferenceDoc          :: Maybe FilePath -- ^ Path of reference doc+    , optEpubSubdirectory      :: String -- ^ EPUB subdir in OCF container+    , optEpubMetadata          :: Maybe FilePath   -- ^ EPUB metadata+    , optEpubFonts             :: [FilePath] -- ^ EPUB fonts to embed+    , optEpubChapterLevel      :: Int     -- ^ Header level at which to split chapters+    , optEpubCoverImage        :: Maybe FilePath -- ^ Cover image for epub+    , optTOCDepth              :: Int     -- ^ Number of levels to include in TOC+    , optDumpArgs              :: Bool    -- ^ Output command-line arguments+    , optIgnoreArgs            :: Bool    -- ^ Ignore command-line arguments+    , optVerbosity             :: Verbosity  -- ^ Verbosity of diagnostic output+    , optTrace                 :: Bool  -- ^ Enable tracing+    , optLogFile               :: Maybe FilePath -- ^ File to write JSON log output+    , optFailIfWarnings        :: Bool    -- ^ Fail on warnings+    , optReferenceLinks        :: Bool    -- ^ Use reference links in writing markdown, rst+    , optReferenceLocation     :: ReferenceLocation -- ^ location for footnotes and link references in markdown output+    , optDpi                   :: Int     -- ^ Dpi+    , optWrapText              :: WrapOption  -- ^ Options for wrapping text+    , optColumns               :: Int     -- ^ Line length in characters+    , optFilters               :: [FilePath] -- ^ Filters to apply+    , optLuaFilters            :: [FilePath] -- ^ Lua filters to apply+    , optEmailObfuscation      :: ObfuscationMethod+    , optIdentifierPrefix      :: String+    , optIndentedCodeClasses   :: [String] -- ^ Default classes for indented code blocks+    , optDataDir               :: Maybe FilePath+    , optCiteMethod            :: CiteMethod -- ^ Method to output cites+    , optListings              :: Bool       -- ^ Use listings package for code blocks+    , optPdfEngine             :: Maybe String -- ^ Program to use for latex/html -> pdf+    , optPdfEngineArgs         :: [String]   -- ^ Flags to pass to the engine+    , optSlideLevel            :: Maybe Int  -- ^ Header level that creates slides+    , optSetextHeaders         :: Bool       -- ^ Use atx headers for markdown level 1-2+    , optAscii                 :: Bool       -- ^ Use ascii characters only in html+    , optDefaultImageExtension :: String -- ^ Default image extension+    , optExtractMedia          :: Maybe FilePath -- ^ Path to extract embedded media+    , optTrackChanges          :: TrackChanges -- ^ Accept or reject MS Word track-changes.+    , optFileScope             :: Bool         -- ^ Parse input files before combining+    , optTitlePrefix           :: Maybe String     -- ^ Prefix for title+    , optCss                   :: [FilePath]       -- ^ CSS files to link to+    , optIncludeBeforeBody     :: [FilePath]       -- ^ Files to include before+    , optIncludeAfterBody      :: [FilePath]       -- ^ Files to include after body+    , optIncludeInHeader       :: [FilePath]       -- ^ Files to include in header+    , optResourcePath          :: [FilePath] -- ^ Path to search for images etc+    , optRequestHeaders        :: [(String, String)] -- ^ Headers for HTTP requests+    , optEol                   :: LineEnding -- ^ Style of line-endings to use+    , optStripComments         :: Bool       -- ^ Skip HTML comments+    } deriving (Generic, Show)++instance ToJSON Opt where+  toEncoding = genericToEncoding defaultOptions+instance FromJSON Opt++-- | Defaults for command-line options.+defaultOpts :: Opt+defaultOpts = Opt+    { optTabStop               = 4+    , optPreserveTabs          = False+    , optStandalone            = False+    , optReader                = Nothing+    , optWriter                = Nothing+    , optTableOfContents       = False+    , optBaseHeaderLevel       = 1+    , optTemplate              = Nothing+    , optVariables             = []+    , optMetadata              = []+    , optOutputFile            = Nothing+    , optInputFiles            = []+    , optNumberSections        = False+    , optNumberOffset          = [0,0,0,0,0,0]+    , optSectionDivs           = False+    , optIncremental           = False+    , optSelfContained         = False+    , optHtmlQTags             = False+    , optHighlightStyle        = Just "pygments"+    , optSyntaxDefinitions     = []+    , optTopLevelDivision      = TopLevelDefault+    , optHTMLMathMethod        = PlainMath+    , optAbbreviations         = Nothing+    , optReferenceDoc          = Nothing+    , optEpubSubdirectory      = "EPUB"+    , optEpubMetadata          = Nothing+    , optEpubFonts             = []+    , optEpubChapterLevel      = 1+    , optEpubCoverImage        = Nothing+    , optTOCDepth              = 3+    , optDumpArgs              = False+    , optIgnoreArgs            = False+    , optVerbosity             = WARNING+    , optTrace                 = False+    , optLogFile               = Nothing+    , optFailIfWarnings        = False+    , optReferenceLinks        = False+    , optReferenceLocation     = EndOfDocument+    , optDpi                   = 96+    , optWrapText              = WrapAuto+    , optColumns               = 72+    , optFilters               = []+    , optLuaFilters            = []+    , optEmailObfuscation      = NoObfuscation+    , optIdentifierPrefix      = ""+    , optIndentedCodeClasses   = []+    , optDataDir               = Nothing+    , optCiteMethod            = Citeproc+    , optListings              = False+    , optPdfEngine             = Nothing+    , optPdfEngineArgs         = []+    , optSlideLevel            = Nothing+    , optSetextHeaders         = True+    , optAscii                 = False+    , optDefaultImageExtension = ""+    , optExtractMedia          = Nothing+    , optTrackChanges          = AcceptChanges+    , optFileScope             = False+    , optTitlePrefix           = Nothing+    , optCss                   = []+    , optIncludeBeforeBody     = []+    , optIncludeAfterBody      = []+    , optIncludeInHeader       = []+    , optResourcePath          = ["."]+    , optRequestHeaders        = []+    , optEol                   = Native+    , optStripComments          = False+    }++addMetadata :: (String, String) -> Pandoc -> Pandoc+addMetadata (k, v) (Pandoc meta bs) = Pandoc meta' bs+  where meta' = case lookupMeta k meta of+                      Nothing -> setMeta k v' meta+                      Just (MetaList xs) ->+                                 setMeta k (MetaList (xs ++ [v'])) meta+                      Just x  -> setMeta k (MetaList [x, v']) meta+        v' = readMetaValue v++readMetaValue :: String -> MetaValue+readMetaValue s = case decode (UTF8.fromString s) of+                       Just (Yaml.String t) -> MetaString $ T.unpack t+                       Just (Yaml.Bool b)   -> MetaBool b+                       _                    -> MetaString s++-- Determine default reader based on source file extensions+defaultReaderName :: String -> [FilePath] -> String+defaultReaderName fallback [] = fallback+defaultReaderName fallback (x:xs) =+  case takeExtension (map toLower x) of+    ".xhtml"    -> "html"+    ".html"     -> "html"+    ".htm"      -> "html"+    ".md"       -> "markdown"+    ".markdown" -> "markdown"+    ".tex"      -> "latex"+    ".latex"    -> "latex"+    ".ltx"      -> "latex"+    ".rst"      -> "rst"+    ".org"      -> "org"+    ".lhs"      -> "markdown+lhs"+    ".db"       -> "docbook"+    ".opml"     -> "opml"+    ".wiki"     -> "mediawiki"+    ".dokuwiki" -> "dokuwiki"+    ".textile"  -> "textile"+    ".native"   -> "native"+    ".json"     -> "json"+    ".docx"     -> "docx"+    ".t2t"      -> "t2t"+    ".epub"     -> "epub"+    ".odt"      -> "odt"+    ".pdf"      -> "pdf"  -- so we get an "unknown reader" error+    ".doc"      -> "doc"  -- so we get an "unknown reader" error+    _           -> defaultReaderName fallback xs++-- Determine default writer based on output file extension+defaultWriterName :: FilePath -> String+defaultWriterName "-" = "html" -- no output file+defaultWriterName x =+  case takeExtension (map toLower x) of+    ""          -> "markdown" -- empty extension+    ".tex"      -> "latex"+    ".latex"    -> "latex"+    ".ltx"      -> "latex"+    ".context"  -> "context"+    ".ctx"      -> "context"+    ".rtf"      -> "rtf"+    ".rst"      -> "rst"+    ".s5"       -> "s5"+    ".native"   -> "native"+    ".json"     -> "json"+    ".txt"      -> "markdown"+    ".text"     -> "markdown"+    ".md"       -> "markdown"+    ".markdown" -> "markdown"+    ".textile"  -> "textile"+    ".lhs"      -> "markdown+lhs"+    ".texi"     -> "texinfo"+    ".texinfo"  -> "texinfo"+    ".db"       -> "docbook"+    ".odt"      -> "odt"+    ".docx"     -> "docx"+    ".epub"     -> "epub"+    ".org"      -> "org"+    ".asciidoc" -> "asciidoc"+    ".adoc"     -> "asciidoc"+    ".fb2"      -> "fb2"+    ".opml"     -> "opml"+    ".icml"     -> "icml"+    ".tei.xml"  -> "tei"+    ".tei"      -> "tei"+    ".ms"       -> "ms"+    ".roff"     -> "ms"+    ['.',y]     | y `elem` ['1'..'9'] -> "man"+    _           -> "html"++-- Transformations of a Pandoc document post-parsing:++applyTransforms :: Monad m => [Transform] -> Pandoc -> m Pandoc+applyTransforms transforms d = return $ foldr ($) d transforms++  -- First we check to see if a filter is found.  If not, and if it's+  -- not an absolute path, we check to see whether it's in `userdir/filters`.+  -- If not, we leave it unchanged.+expandFilterPath :: MonadIO m => Maybe FilePath -> FilePath -> m FilePath+expandFilterPath mbDatadir fp = liftIO $ do+  fpExists <- doesFileExist fp+  if fpExists+     then return fp+     else case mbDatadir of+               Just datadir | isRelative fp -> do+                 let filterPath = datadir </> "filters" </> fp+                 filterPathExists <- doesFileExist filterPath+                 if filterPathExists+                    then return filterPath+                    else return fp+               _ -> return fp++applyLuaFilters :: Maybe FilePath -> [FilePath] -> String -> Pandoc+                -> PandocIO Pandoc+applyLuaFilters mbDatadir filters format d = do+  expandedFilters <- mapM (expandFilterPath mbDatadir) filters+  let go f d' = do+        res <- runLuaFilter mbDatadir f format d'+        case res of+          Right x               -> return x+          Left (LuaException s) -> E.throw (PandocFilterError f s)+  foldrM ($) d $ map go expandedFilters++applyFilters :: MonadIO m+             => ReaderOptions+             -> Maybe FilePath+             -> [FilePath]+             -> [String]+             -> Pandoc+             -> m Pandoc+applyFilters ropts mbDatadir filters args d = do+  expandedFilters <- mapM (expandFilterPath mbDatadir) filters+  foldrM ($) d $ map (flip (externalFilter ropts) args) expandedFilters++readSource :: FilePath -> PandocIO Text+readSource "-" = liftIO (UTF8.toText <$> BS.getContents)+readSource src = case parseURI src of+                      Just u | uriScheme u `elem` ["http:","https:"] ->+                                 readURI src+                             | uriScheme u == "file:" ->+                                 liftIO $ UTF8.toText <$>+                                    BS.readFile (uriPath u)+                      _       -> liftIO $ UTF8.toText <$>+                                    BS.readFile src++readURI :: FilePath -> PandocIO Text+readURI src = UTF8.toText . fst <$> openURL src++readFile' :: MonadIO m => FilePath -> m B.ByteString+readFile' "-" = liftIO B.getContents+readFile' f   = liftIO $ B.readFile f++writeFnBinary :: MonadIO m => FilePath -> B.ByteString -> m ()+writeFnBinary "-" = liftIO . B.putStr+writeFnBinary f   = liftIO . B.writeFile (UTF8.encodePath f)++writerFn :: MonadIO m => IO.Newline -> FilePath -> Text -> m ()+-- TODO this implementation isn't maximally efficient:+writerFn eol "-" = liftIO . UTF8.putStrWith eol . T.unpack+writerFn eol f   = liftIO . UTF8.writeFileWith eol f . T.unpack++lookupHighlightStyle :: Maybe String -> IO (Maybe Style)+lookupHighlightStyle Nothing = return Nothing+lookupHighlightStyle (Just s)+  | takeExtension s == ".theme" = -- attempt to load KDE theme+    do contents <- B.readFile s+       case parseTheme contents of+            Left _    -> E.throwIO $ PandocOptionError $+                           "Could not read highlighting theme " ++ s+            Right sty -> return (Just sty)+  | otherwise =+  case lookup (map toLower s) highlightingStyles of+       Just sty -> return (Just sty)+       Nothing  -> E.throwIO $ PandocOptionError $+                      "Unknown highlight-style " ++ s++-- | A list of functions, each transforming the options data structure+--   in response to a command-line option.+options :: [OptDescr (Opt -> IO Opt)]+options =+    [ Option "fr" ["from","read"]+                 (ReqArg+                  (\arg opt -> return opt { optReader =+                                              Just (map toLower arg) })+                  "FORMAT")+                 ""++    , Option "tw" ["to","write"]+                 (ReqArg+                  (\arg opt -> return opt { optWriter =+                                              Just (map toLower arg) })+                  "FORMAT")+                 ""++    , Option "o" ["output"]+                 (ReqArg+                  (\arg opt -> return opt { optOutputFile = Just arg })+                  "FILE")+                 "" -- "Name of output file"++    , Option "" ["data-dir"]+                 (ReqArg+                  (\arg opt -> return opt { optDataDir = Just arg })+                 "DIRECTORY") -- "Directory containing pandoc data files."+                ""++    , Option "" ["base-header-level"]+                 (ReqArg+                  (\arg opt ->+                      case safeRead arg of+                           Just t | t > 0 && t < 6 ->+                               return opt{ optBaseHeaderLevel = t }+                           _              -> E.throwIO $ PandocOptionError+                                               "base-header-level must be 1-5")+                  "NUMBER")+                 "" -- "Headers base level"++     , Option "" ["indented-code-classes"]+                  (ReqArg+                   (\arg opt -> return opt { optIndentedCodeClasses = words $+                                             map (\c -> if c == ',' then ' ' else c) arg })+                   "STRING")+                  "" -- "Classes (whitespace- or comma-separated) to use for indented code-blocks"++    , Option "F" ["filter"]+                 (ReqArg+                  (\arg opt -> return opt { optFilters = arg : optFilters opt })+                  "PROGRAM")+                 "" -- "External JSON filter"++    , Option "" ["lua-filter"]+                 (ReqArg+                  (\arg opt -> return opt { optLuaFilters = arg : optLuaFilters opt })+                  "SCRIPTPATH")+                 "" -- "Lua filter"++    , Option "p" ["preserve-tabs"]+                 (NoArg+                  (\opt -> return opt { optPreserveTabs = True }))+                 "" -- "Preserve tabs instead of converting to spaces"++    , Option "" ["tab-stop"]+                 (ReqArg+                  (\arg opt ->+                      case safeRead arg of+                           Just t | t > 0 -> return opt { optTabStop = t }+                           _              -> E.throwIO $ PandocOptionError+                                  "tab-stop must be a number greater than 0")+                  "NUMBER")+                 "" -- "Tab stop (default 4)"++    , Option "" ["track-changes"]+                 (ReqArg+                  (\arg opt -> do+                     action <- case arg of+                            "accept" -> return AcceptChanges+                            "reject" -> return RejectChanges+                            "all"    -> return AllChanges+                            _        -> E.throwIO $ PandocOptionError+                               ("Unknown option for track-changes: " ++ arg)+                     return opt { optTrackChanges = action })+                  "accept|reject|all")+                 "" -- "Accepting or reject MS Word track-changes.""++    , Option "" ["file-scope"]+                 (NoArg+                  (\opt -> return opt { optFileScope = True }))+                 "" -- "Parse input files before combining"++    , Option "" ["extract-media"]+                 (ReqArg+                  (\arg opt ->+                    return opt { optExtractMedia = Just arg })+                  "PATH")+                 "" -- "Directory to which to extract embedded media"++    , Option "s" ["standalone"]+                 (NoArg+                  (\opt -> return opt { optStandalone = True }))+                 "" -- "Include needed header and footer on output"++    , Option "" ["template"]+                 (ReqArg+                  (\arg opt ->+                     return opt{ optTemplate = Just arg,+                                 optStandalone = True })+                  "FILE")+                 "" -- "Use custom template"++    , Option "M" ["metadata"]+                 (ReqArg+                  (\arg opt -> do+                     let (key, val) = splitField arg+                     return opt{ optMetadata = (key, val) : optMetadata opt })+                  "KEY[:VALUE]")+                 ""++    , Option "V" ["variable"]+                 (ReqArg+                  (\arg opt -> do+                     let (key, val) = splitField arg+                     return opt{ optVariables = (key, val) : optVariables opt })+                  "KEY[:VALUE]")+                 ""++    , Option "D" ["print-default-template"]+                 (ReqArg+                  (\arg _ -> do+                     templ <- runIO $ do+                                setUserDataDir Nothing+                                getDefaultTemplate arg+                     case templ of+                          Right t -> UTF8.hPutStr stdout t+                          Left e  -> E.throwIO e+                     exitSuccess)+                  "FORMAT")+                 "" -- "Print default template for FORMAT"++    , Option "" ["print-default-data-file"]+                 (ReqArg+                  (\arg _ -> do+                     runIOorExplode $+                       readDefaultDataFile arg >>= liftIO . BS.hPutStr stdout+                     exitSuccess)+                  "FILE")+                  "" -- "Print default data file"++    , Option "" ["dpi"]+                 (ReqArg+                  (\arg opt ->+                    case safeRead arg of+                         Just t | t > 0 -> return opt { optDpi = t }+                         _              -> E.throwIO $ PandocOptionError+                                        "dpi must be a number greater than 0")+                  "NUMBER")+                 "" -- "Dpi (default 96)"++    , Option "" ["eol"]+                 (ReqArg+                  (\arg opt ->+                    case toLower <$> arg of+                      "crlf"   -> return opt { optEol = CRLF }+                      "lf"     -> return opt { optEol = LF }+                      "native" -> return opt { optEol = Native }+                      -- mac-syntax (cr) is not supported in ghc-base.+                      _      -> E.throwIO $ PandocOptionError+                                "--eol must be crlf, lf, or native")+                  "crlf|lf|native")+                 "" -- "EOL (default OS-dependent)"++    , Option "" ["wrap"]+                 (ReqArg+                  (\arg opt ->+                    case safeRead ("Wrap" ++ uppercaseFirstLetter arg) of+                          Just o   -> return opt { optWrapText = o }+                          Nothing  -> E.throwIO $ PandocOptionError+                                     "--wrap must be auto, none, or preserve")+                 "auto|none|preserve")+                 "" -- "Option for wrapping text in output"++    , Option "" ["columns"]+                 (ReqArg+                  (\arg opt ->+                      case safeRead arg of+                           Just t | t > 0 -> return opt { optColumns = t }+                           _              -> E.throwIO $ PandocOptionError+                                   "columns must be a number greater than 0")+                 "NUMBER")+                 "" -- "Length of line in characters"++    , Option "" ["strip-comments"]+                (NoArg+                 (\opt -> return opt { optStripComments = True }))+               "" -- "Strip HTML comments"++    , Option "" ["toc", "table-of-contents"]+                (NoArg+                 (\opt -> return opt { optTableOfContents = True }))+               "" -- "Include table of contents"++    , Option "" ["toc-depth"]+                 (ReqArg+                  (\arg opt ->+                      case safeRead arg of+                           Just t | t >= 1 && t <= 6 ->+                                    return opt { optTOCDepth = t }+                           _      -> E.throwIO $ PandocOptionError+                                    "TOC level must be a number between 1 and 6")+                 "NUMBER")+                 "" -- "Number of levels to include in TOC"++    , Option "" ["no-highlight"]+                (NoArg+                 (\opt -> return opt { optHighlightStyle = Nothing }))+                 "" -- "Don't highlight source code"++    , Option "" ["highlight-style"]+                (ReqArg+                 (\arg opt -> return opt{ optHighlightStyle = Just arg })+                 "STYLE")+                 "" -- "Style for highlighted code"++    , Option "" ["syntax-definition"]+                (ReqArg+                 (\arg opt -> return opt{ optSyntaxDefinitions = arg :+                                             optSyntaxDefinitions opt })+                 "FILE")+                "" -- "Syntax definition (xml) file"++    , Option "H" ["include-in-header"]+                 (ReqArg+                  (\arg opt -> return opt{ optIncludeInHeader =+                                              arg : optIncludeInHeader opt,+                                            optStandalone = True })+                  "FILE")+                 "" -- "File to include at end of header (implies -s)"++    , Option "B" ["include-before-body"]+                 (ReqArg+                  (\arg opt -> return opt{ optIncludeBeforeBody =+                                              arg : optIncludeBeforeBody opt,+                                           optStandalone = True })+                  "FILE")+                 "" -- "File to include before document body"++    , Option "A" ["include-after-body"]+                 (ReqArg+                  (\arg opt -> return opt{ optIncludeAfterBody =+                                              arg : optIncludeAfterBody opt,+                                           optStandalone = True })+                  "FILE")+                 "" -- "File to include after document body"++    , Option "" ["resource-path"]+                (ReqArg+                  (\arg opt -> return opt { optResourcePath =+                                   splitSearchPath arg })+                   "SEARCHPATH")+                  "" -- "Paths to search for images and other resources"++    , Option "" ["request-header"]+                 (ReqArg+                  (\arg opt -> do+                     let (key, val) = splitField arg+                     return opt{ optRequestHeaders =+                       (key, val) : optRequestHeaders opt })+                  "NAME:VALUE")+                 ""++    , Option "" ["self-contained"]+                 (NoArg+                  (\opt -> return opt { optSelfContained = True,+                                        optStandalone = True }))+                 "" -- "Make slide shows include all the needed js and css"++    , Option "" ["html-q-tags"]+                 (NoArg+                  (\opt ->+                     return opt { optHtmlQTags = True }))+                 "" -- "Use <q> tags for quotes in HTML"++    , Option "" ["ascii"]+                 (NoArg+                  (\opt -> return opt { optAscii = True }))+                 ""  -- "Use ascii characters only in HTML output"++    , Option "" ["reference-links"]+                 (NoArg+                  (\opt -> return opt { optReferenceLinks = True } ))+                 "" -- "Use reference links in parsing HTML"++    , Option "" ["reference-location"]+                 (ReqArg+                  (\arg opt -> do+                     action <- case arg of+                            "block"    -> return EndOfBlock+                            "section"  -> return EndOfSection+                            "document" -> return EndOfDocument+                            _        -> E.throwIO $ PandocOptionError+                               ("Unknown option for reference-location: " ++ arg)+                     return opt { optReferenceLocation = action })+                  "block|section|document")+                 "" -- "Accepting or reject MS Word track-changes.""++    , Option "" ["atx-headers"]+                 (NoArg+                  (\opt -> return opt { optSetextHeaders = False } ))+                 "" -- "Use atx-style headers for markdown"++    , Option "" ["top-level-division"]+                 (ReqArg+                  (\arg opt -> do+                      let tldName = "TopLevel" ++ uppercaseFirstLetter arg+                      case safeRead tldName of+                        Just tlDiv -> return opt { optTopLevelDivision = tlDiv }+                        _       -> E.throwIO $ PandocOptionError+                                     ("Top-level division must be " +++                                      "section,  chapter, part, or default"))+                   "section|chapter|part")+                 "" -- "Use top-level division type in LaTeX, ConTeXt, DocBook"++    , Option "N" ["number-sections"]+                 (NoArg+                  (\opt -> return opt { optNumberSections = True }))+                 "" -- "Number sections in LaTeX"++    , Option "" ["number-offset"]+                 (ReqArg+                  (\arg opt ->+                      case safeRead ('[':arg ++ "]") of+                           Just ns -> return opt { optNumberOffset = ns,+                                                   optNumberSections = True }+                           _      -> E.throwIO $ PandocOptionError+                                       "could not parse number-offset")+                 "NUMBERS")+                 "" -- "Starting number for sections, subsections, etc."++    , Option "" ["listings"]+                 (NoArg+                  (\opt -> return opt { optListings = True }))+                 "" -- "Use listings package for LaTeX code blocks"++    , Option "i" ["incremental"]+                 (NoArg+                  (\opt -> return opt { optIncremental = True }))+                 "" -- "Make list items display incrementally in Slidy/Slideous/S5"++    , Option "" ["slide-level"]+                 (ReqArg+                  (\arg opt ->+                      case safeRead arg of+                           Just t | t >= 1 && t <= 6 ->+                                    return opt { optSlideLevel = Just t }+                           _      -> E.throwIO $ PandocOptionError+                                    "slide level must be a number between 1 and 6")+                 "NUMBER")+                 "" -- "Force header level for slides"++    , Option "" ["section-divs"]+                 (NoArg+                  (\opt -> return opt { optSectionDivs = True }))+                 "" -- "Put sections in div tags in HTML"++    , Option "" ["default-image-extension"]+                 (ReqArg+                  (\arg opt -> return opt { optDefaultImageExtension = arg })+                   "extension")+                  "" -- "Default extension for extensionless images"++    , Option "" ["email-obfuscation"]+                 (ReqArg+                  (\arg opt -> do+                     method <- case arg of+                            "references" -> return ReferenceObfuscation+                            "javascript" -> return JavascriptObfuscation+                            "none"       -> return NoObfuscation+                            _            -> E.throwIO $ PandocOptionError+                               ("Unknown obfuscation method: " ++ arg)+                     return opt { optEmailObfuscation = method })+                  "none|javascript|references")+                 "" -- "Method for obfuscating email in HTML"++     , Option "" ["id-prefix"]+                  (ReqArg+                   (\arg opt -> return opt { optIdentifierPrefix = arg })+                   "STRING")+                  "" -- "Prefix to add to automatically generated HTML identifiers"++    , Option "T" ["title-prefix"]+                 (ReqArg+                  (\arg opt -> do+                    let newvars = ("title-prefix", arg) : optVariables opt+                    return opt { optVariables = newvars,+                                 optStandalone = True })+                  "STRING")+                 "" -- "String to prefix to HTML window title"++    , Option "c" ["css"]+                 (ReqArg+                  (\arg opt -> return opt{ optCss = arg : optCss opt })+                  -- add new link to end, so it is included in proper order+                  "URL")+                 "" -- "Link to CSS style sheet"++    , Option "" ["reference-doc"]+                 (ReqArg+                  (\arg opt ->+                    return opt { optReferenceDoc = Just arg })+                  "FILE")+                 "" -- "Path of custom reference doc"++    , Option "" ["epub-subdirectory"]+             (ReqArg+                  (\arg opt ->+                     return opt { optEpubSubdirectory = arg })+                  "DIRNAME")+                 "" -- "Name of subdirectory for epub content in OCF container"++    , Option "" ["epub-cover-image"]+                 (ReqArg+                  (\arg opt ->+                     return opt { optVariables =+                                 ("epub-cover-image", arg) : optVariables opt })+                  "FILE")+                 "" -- "Path of epub cover image"++    , Option "" ["epub-metadata"]+                 (ReqArg+                  (\arg opt -> return opt { optEpubMetadata = Just arg })+                  "FILE")+                 "" -- "Path of epub metadata file"++    , Option "" ["epub-embed-font"]+                 (ReqArg+                  (\arg opt ->+                     return opt{ optEpubFonts = arg : optEpubFonts opt })+                  "FILE")+                 "" -- "Directory of fonts to embed"++    , Option "" ["epub-chapter-level"]+                 (ReqArg+                  (\arg opt ->+                      case safeRead arg of+                           Just t | t >= 1 && t <= 6 ->+                                    return opt { optEpubChapterLevel = t }+                           _      -> E.throwIO $ PandocOptionError+                                    "chapter level must be a number between 1 and 6")+                 "NUMBER")+                 "" -- "Header level at which to split chapters in EPUB"++    , Option "" ["pdf-engine"]+                 (ReqArg+                  (\arg opt -> do+                     let b = takeBaseName arg+                     if b `elem` pdfEngines+                        then return opt { optPdfEngine = Just arg }+                        else E.throwIO $ PandocOptionError $ "pdf-engine must be one of "+                               ++ intercalate ", " pdfEngines)+                  "PROGRAM")+                 "" -- "Name of program to use in generating PDF"++    , Option "" ["pdf-engine-opt"]+                 (ReqArg+                  (\arg opt -> do+                      let oldArgs = optPdfEngineArgs opt+                      return opt { optPdfEngineArgs = arg : oldArgs })+                  "STRING")+                 "" -- "Flags to pass to the PDF-engine, all instances of this option are accumulated and used"++    , Option "" ["bibliography"]+                 (ReqArg+                  (\arg opt -> return opt{ optMetadata =+                                 ("bibliography", arg) : optMetadata opt })+                   "FILE")+                 ""++     , Option "" ["csl"]+                 (ReqArg+                  (\arg opt ->+                     return opt{ optMetadata =+                                   ("csl", arg) : optMetadata opt })+                   "FILE")+                 ""++     , Option "" ["citation-abbreviations"]+                 (ReqArg+                  (\arg opt ->+                     return opt{ optMetadata =+                              ("citation-abbreviations", arg): optMetadata opt })+                   "FILE")+                 ""++    , Option "" ["natbib"]+                 (NoArg+                  (\opt -> return opt { optCiteMethod = Natbib }))+                 "" -- "Use natbib cite commands in LaTeX output"++    , Option "" ["biblatex"]+                 (NoArg+                  (\opt -> return opt { optCiteMethod = Biblatex }))+                 "" -- "Use biblatex cite commands in LaTeX output"++    , Option "m" ["latexmathml", "asciimathml"]+                 (OptArg+                  (\arg opt ->+                      return opt { optHTMLMathMethod = LaTeXMathML arg })+                  "URL")+                 "" -- "Use LaTeXMathML script in html output"++    , Option "" ["mathml"]+                 (NoArg+                  (\opt ->+                      return opt { optHTMLMathMethod = MathML }))+                 "" -- "Use mathml for HTML math"++    , Option "" ["mimetex"]+                 (OptArg+                  (\arg opt -> do+                      let url' = case arg of+                                      Just u  -> u ++ "?"+                                      Nothing -> "/cgi-bin/mimetex.cgi?"+                      return opt { optHTMLMathMethod = WebTeX url' })+                  "URL")+                 "" -- "Use mimetex for HTML math"++    , Option "" ["webtex"]+                 (OptArg+                  (\arg opt -> do+                      let url' = fromMaybe "https://latex.codecogs.com/png.latex?" arg+                      return opt { optHTMLMathMethod = WebTeX url' })+                  "URL")+                 "" -- "Use web service for HTML math"++    , Option "" ["jsmath"]+                 (OptArg+                  (\arg opt -> return opt { optHTMLMathMethod = JsMath arg})+                  "URL")+                 "" -- "Use jsMath for HTML math"++    , Option "" ["mathjax"]+                 (OptArg+                  (\arg opt -> do+                      let url' = fromMaybe (defaultMathJaxURL +++                                  "MathJax.js?config=TeX-AMS_CHTML-full") arg+                      return opt { optHTMLMathMethod = MathJax url'})+                  "URL")+                 "" -- "Use MathJax for HTML math"+    , Option "" ["katex"]+                 (OptArg+                  (\arg opt ->+                      return opt+                        { optHTMLMathMethod = KaTeX $+                           fromMaybe defaultKaTeXURL arg })+                  "URL")+                  "" -- Use KaTeX for HTML Math++    , Option "" ["gladtex"]+                 (NoArg+                  (\opt -> return opt { optHTMLMathMethod = GladTeX }))+                 "" -- "Use gladtex for HTML math"++    , Option "" ["abbreviations"]+                (ReqArg+                 (\arg opt -> return opt { optAbbreviations = Just arg })+                "FILE")+                "" -- "Specify file for custom abbreviations"++    , Option "" ["trace"]+                 (NoArg+                  (\opt -> return opt { optTrace = True }))+                 "" -- "Turn on diagnostic tracing in readers."++    , Option "" ["dump-args"]+                 (NoArg+                  (\opt -> return opt { optDumpArgs = True }))+                 "" -- "Print output filename and arguments to stdout."++    , Option "" ["ignore-args"]+                 (NoArg+                  (\opt -> return opt { optIgnoreArgs = True }))+                 "" -- "Ignore command-line arguments."++    , Option "" ["verbose"]+                 (NoArg+                  (\opt -> return opt { optVerbosity = INFO }))+                 "" -- "Verbose diagnostic output."++    , Option "" ["quiet"]+                 (NoArg+                  (\opt -> return opt { optVerbosity = ERROR }))+                 "" -- "Suppress warnings."++    , Option "" ["fail-if-warnings"]+                 (NoArg+                  (\opt -> return opt { optFailIfWarnings = True }))+                 "" -- "Exit with error status if there were  warnings."++    , Option "" ["log"]+                 (ReqArg+                  (\arg opt -> return opt{ optLogFile = Just arg })+                "FILE")+                "" -- "Log messages in JSON format to this file."++    , Option "" ["bash-completion"]+                 (NoArg+                  (\_ -> do+                     ddir <- getDataDir+                     tpl <- runIOorExplode $+                              UTF8.toString <$>+                                readDefaultDataFile "bash_completion.tpl"+                     let optnames (Option shorts longs _ _) =+                           map (\c -> ['-',c]) shorts +++                           map ("--" ++) longs+                     let allopts = unwords (concatMap optnames options)+                     UTF8.hPutStrLn stdout $ printf tpl allopts+                         (unwords readersNames)+                         (unwords writersNames)+                         (unwords $ map fst highlightingStyles)+                         ddir+                     exitSuccess ))+                 "" -- "Print bash completion script"++    , Option "" ["list-input-formats"]+                 (NoArg+                  (\_ -> do+                     mapM_ (UTF8.hPutStrLn stdout) readersNames+                     exitSuccess ))+                 ""++    , Option "" ["list-output-formats"]+                 (NoArg+                  (\_ -> do+                     mapM_ (UTF8.hPutStrLn stdout) writersNames+                     exitSuccess ))+                 ""++    , Option "" ["list-extensions"]+                 (NoArg+                  (\_ -> do+                     let showExt x = drop 4 (show x) +++                                       if extensionEnabled x pandocExtensions+                                          then " +"+                                          else " -"+                     mapM_ (UTF8.hPutStrLn stdout . showExt)+                               ([minBound..maxBound] :: [Extension])+                     exitSuccess ))+                 ""++    , Option "" ["list-highlight-languages"]+                 (NoArg+                  (\_ -> do+                     let langs = [ T.unpack (T.toLower (sShortname s))+                                 | s <- M.elems defaultSyntaxMap+                                 , sShortname s `notElem`+                                    [T.pack "Alert", T.pack "Alert_indent"]+                                 ]+                     mapM_ (UTF8.hPutStrLn stdout) langs+                     exitSuccess ))+                 ""++    , Option "" ["list-highlight-styles"]+                 (NoArg+                  (\_ -> do+                     mapM_ (UTF8.hPutStrLn stdout . fst) highlightingStyles+                     exitSuccess ))+                 ""++    , Option "v" ["version"]+                 (NoArg+                  (\_ -> do+                     prg <- getProgName+                     defaultDatadir <- E.catch+                            (getAppUserDataDirectory "pandoc")+                            (\e -> let _ = (e :: E.SomeException)+                                   in  return "")+                     UTF8.hPutStrLn stdout (prg ++ " " ++ pandocVersion +++                       compileInfo ++ "\nDefault user data directory: " +++                       defaultDatadir ++ copyrightMessage)+                     exitSuccess ))+                 "" -- "Print version"++    , Option "h" ["help"]+                 (NoArg+                  (\_ -> do+                     prg <- getProgName+                     UTF8.hPutStr stdout (usageMessage prg options)+                     exitSuccess ))+                 "" -- "Show help"++    ]++-- Returns usage message+usageMessage :: String -> [OptDescr (Opt -> IO Opt)] -> String+usageMessage programName = usageInfo (programName ++ " [OPTIONS] [FILES]")++copyrightMessage :: String+copyrightMessage = intercalate "\n" [+  "",+  "Copyright (C) 2006-2017 John MacFarlane",+  "Web:  http://pandoc.org",+  "This is free software; see the source for copying conditions.",+  "There is no warranty, not even for merchantability or fitness",+  "for a particular purpose." ]++compileInfo :: String+compileInfo =+  "\nCompiled with pandoc-types " ++ VERSION_pandoc_types ++ ", texmath " +++  VERSION_texmath ++ ", skylighting " ++ VERSION_skylighting++handleUnrecognizedOption :: String -> [String] -> [String]+handleUnrecognizedOption "--smart" =+  (("--smart/-S has been removed.  Use +smart or -smart extension instead.\n" +++    "For example: pandoc -f markdown+smart -t markdown-smart.") :)+handleUnrecognizedOption "--normalize" =+  ("--normalize has been removed.  Normalization is now automatic." :)+handleUnrecognizedOption "-S" = handleUnrecognizedOption "--smart"+handleUnrecognizedOption "--old-dashes" =+  ("--old-dashes has been removed.  Use +old_dashes extension instead." :)+handleUnrecognizedOption "--no-wrap" =+  ("--no-wrap has been removed.  Use --wrap=none instead." :)+handleUnrecognizedOption "--latex-engine" =+  ("--latex-engine has been removed.  Use --pdf-engine instead." :)+handleUnrecognizedOption "--latex-engine-opt" =+  ("--latex-engine-opt has been removed.  Use --pdf-engine-opt instead." :)+handleUnrecognizedOption "--chapters" =+  ("--chapters has been removed. Use --top-level-division=chapter instead." :)+handleUnrecognizedOption "--reference-docx" =+  ("--reference-docx has been removed. Use --reference-doc instead." :)+handleUnrecognizedOption "--reference-odt" =+  ("--reference-odt has been removed. Use --reference-doc instead." :)+handleUnrecognizedOption "--parse-raw" =+  ("--parse-raw/-R has been removed. Use +raw_html or +raw_tex extension.\n" :)+handleUnrecognizedOption "--epub-stylesheet" =+  ("--epub-stylesheet has been removed. Use --css instead.\n" :)+handleUnrecognizedOption "-R" = handleUnrecognizedOption "--parse-raw"+handleUnrecognizedOption x =+  (("Unknown option " ++ x ++ ".") :)++uppercaseFirstLetter :: String -> String+uppercaseFirstLetter (c:cs) = toUpper c : cs+uppercaseFirstLetter []     = []++readersNames :: [String]+readersNames = sort (map fst (readers :: [(String, Reader PandocIO)]))++writersNames :: [String]+writersNames = sort (map fst (writers :: [(String, Writer PandocIO)]))++splitField :: String -> (String, String)+splitField s =+  case break (`elem` ":=") s of+       (k,_:v) -> (k,v)+       (k,[])  -> (k,"true")++baseWriterName :: String -> String+baseWriterName = takeWhile (\c -> c /= '+' && c /= '-')
src/Text/Pandoc/Asciify.hs view
@@ -1,5 +1,5 @@ {--Copyright (C) 2013-2016 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2013-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -18,7 +18,7 @@  {- |    Module      : Text.Pandoc.Asciify-   Copyright   : Copyright (C) 2013-2016 John MacFarlane+   Copyright   : Copyright (C) 2013-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -30,8 +30,8 @@ -} module Text.Pandoc.Asciify (toAsciiChar) where-import qualified Data.Map as M import Data.Char (isAscii)+import qualified Data.Map as M  toAsciiChar :: Char -> Maybe Char toAsciiChar c | isAscii c = Just c
+ src/Text/Pandoc/BCP47.hs view
@@ -0,0 +1,125 @@+{-+Copyright (C) 2017 John MacFarlane <jgm@berkeley.edu>++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation; either version 2 of the License, or+(at your option) any later version.++This program is distributed in the hope that it will be useful,+but WITHOUT ANY WARRANTY; without even the implied warranty of+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+GNU General Public License for more details.++You should have received a copy of the GNU General Public License+along with this program; if not, write to the Free Software+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+-}++{- |+   Module      : Text.Pandoc.BCP47+   Copyright   : Copyright (C) 2017 John MacFarlane+   License     : GNU GPL, version 2 or above++   Maintainer  : John MacFarlane <jgm@berkeley.edu>+   Stability   : alpha+   Portability : portable++Functions for parsing and rendering BCP47 language identifiers.+-}+module Text.Pandoc.BCP47 (+                       getLang+                     , parseBCP47+                     , Lang(..)+                     , renderLang+                     )+where+import Control.Monad (guard)+import Data.Char (isAlphaNum, isAscii, isLetter, isLower, isUpper, toLower,+                  toUpper)+import Data.List (intercalate)+import Text.Pandoc.Definition+import Text.Pandoc.Options+import qualified Text.Parsec as P++-- | Represents BCP 47 language/country code.+data Lang = Lang{ langLanguage :: String+                , langScript   :: String+                , langRegion   :: String+                , langVariants :: [String] }+                deriving (Eq, Ord, Show)++-- | Render a Lang as BCP 47.+renderLang :: Lang -> String+renderLang lang = intercalate "-" (langLanguage lang : filter (not . null)+                    ([langScript lang, langRegion lang] ++ langVariants lang))++-- | Get the contents of the `lang` metadata field or variable.+getLang :: WriterOptions -> Meta -> Maybe String+getLang opts meta =+  case lookup "lang" (writerVariables opts) of+        Just s -> Just s+        _      ->+          case lookupMeta "lang" meta of+               Just (MetaInlines [Str s]) -> Just s+               Just (MetaString s)        -> Just s+               _                          -> Nothing++-- | Parse a BCP 47 string as a Lang.  Currently we parse+-- extensions and private-use fields as "variants," even+-- though officially they aren't.+parseBCP47 :: String -> Either String Lang+parseBCP47 lang =+  case P.parse bcp47 "lang" lang of+       Right r -> Right r+       Left e  -> Left $ show e+  where bcp47 = do+          language <- pLanguage+          script <- P.option "" pScript+          region <- P.option "" pRegion+          variants <- P.many (pVariant P.<|> pExtension P.<|> pPrivateUse)+          P.eof+          return Lang{   langLanguage = language+                       , langScript = script+                       , langRegion = region+                       , langVariants = variants }+        asciiLetter = P.satisfy (\c -> isAscii c && isLetter c)+        pLanguage = do+          cs <- P.many1 asciiLetter+          let lcs = length cs+          guard $ lcs == 2 || lcs == 3+          return $ map toLower cs+        pScript = P.try $ do+          P.char '-'+          x <- P.satisfy (\c -> isAscii c && isLetter c && isUpper c)+          xs <- P.count 3+                 (P.satisfy (\c -> isAscii c && isLetter c && isLower c))+          return $ map toLower (x:xs)+        pRegion = P.try $ do+          P.char '-'+          cs <- P.many1 asciiLetter+          let lcs = length cs+          guard $ lcs == 2 || lcs == 3+          return $ map toUpper cs+        pVariant = P.try $ do+          P.char '-'+          ds <- P.option "" (P.count 1 P.digit)+          cs <- P.many1 asciiLetter+          let var = ds ++ cs+          guard $ if null ds+                     then length var >= 5 && length var <= 8+                     else length var == 4+          return $ map toLower var+        pExtension = P.try $ do+          P.char '-'+          cs <- P.many1 $ P.satisfy (\c -> isAscii c && isAlphaNum c)+          guard $ length cs >= 2 && length cs <= 8+          return $ map toLower cs+        pPrivateUse = P.try $ do+          P.char '-'+          P.char 'x'+          P.char '-'+          cs <- P.many1 $ P.satisfy (\c -> isAscii c && isAlphaNum c)+          guard $ not (null cs) && length cs <= 8+          let var = "x-" ++ cs+          return $ map toLower var
src/Text/Pandoc/CSS.hs view
@@ -11,7 +11,7 @@ ruleParser :: Parser (String, String) ruleParser = do     p <- many1 (noneOf ":")  <* char ':'-    v <- many1 (noneOf ":;") <* (optional $ char ';') <* spaces+    v <- many1 (noneOf ":;") <* optional (char ';') <* spaces     return (trim p, trim v)  styleAttrParser :: Parser [(String, String)]@@ -25,14 +25,14 @@  eitherToMaybe :: Either a b -> Maybe b eitherToMaybe (Right x) = Just x-eitherToMaybe _ = Nothing+eitherToMaybe _         = Nothing  -- | takes a list of keys/properties and a CSS string and -- returns the corresponding key-value-pairs. pickStylesToKVs :: [String] -> String -> [(String, String)] pickStylesToKVs props styleAttr =   case parse styleAttrParser "" styleAttr of-    Left _ -> []+    Left _       -> []     Right styles -> filter (\s -> fst s `elem` props) styles  -- | takes a list of key/property synonyms and a CSS string and maybe
+ src/Text/Pandoc/CSV.hs view
@@ -0,0 +1,102 @@+{-+Copyright (C) 2017 John MacFarlane <jgm@berkeley.edu>++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation; either version 2 of the License, or+(at your option) any later version.++This program is distributed in the hope that it will be useful,+but WITHOUT ANY WARRANTY; without even the implied warranty of+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+GNU General Public License for more details.++You should have received a copy of the GNU General Public License+along with this program; if not, write to the Free Software+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+-}++{- |+   Module      : Text.Pandoc.CSV+   Copyright   : Copyright (C) 2017 John MacFarlane <jgm@berkeley.edu>+   License     : GNU GPL, version 2 or above+   Maintainer  : John MacFarlane <jgm@berkeley.edu>+   Stability   : alpha+   Portability : portable++Simple CSV parser.+-}++module Text.Pandoc.CSV (+  CSVOptions(..),+  defaultCSVOptions,+  parseCSV,+  ParseError+) where++import Control.Monad (void)+import Data.Text (Text)+import qualified Data.Text as T+import Text.Parsec+import Text.Parsec.Text (Parser)++data CSVOptions = CSVOptions{+    csvDelim     :: Char+  , csvQuote     :: Char+  , csvKeepSpace :: Bool -- treat whitespace following delim as significant+  , csvEscape    :: Maybe Char -- default is to double up quote+} deriving (Read, Show)++defaultCSVOptions :: CSVOptions+defaultCSVOptions = CSVOptions{+    csvDelim = ','+  , csvQuote = '"'+  , csvKeepSpace = False+  , csvEscape = Nothing }++parseCSV :: CSVOptions -> Text -> Either ParseError [[Text]]+parseCSV opts t = parse (pCSV opts) "csv" t++pCSV :: CSVOptions -> Parser [[Text]]+pCSV opts =+  (pCSVRow opts `sepEndBy` endline) <* (spaces *> eof)++pCSVRow :: CSVOptions -> Parser [Text]+pCSVRow opts = notFollowedBy blank >> pCSVCell opts `sepBy` pCSVDelim opts++blank :: Parser ()+blank = try $ spaces >> (() <$ endline <|> eof)++pCSVCell :: CSVOptions -> Parser Text+pCSVCell opts = pCSVQuotedCell opts <|> pCSVUnquotedCell opts++pCSVQuotedCell :: CSVOptions -> Parser Text+pCSVQuotedCell opts = do+  char (csvQuote opts)+  res <- many (satisfy (\c -> c /= csvQuote opts &&+                              Just c /= csvEscape opts) <|> escaped opts)+  char (csvQuote opts)+  return $ T.pack res++escaped :: CSVOptions -> Parser Char+escaped opts =+  case csvEscape opts of+       Nothing -> try $ char (csvQuote opts) >> char (csvQuote opts)+       Just c  -> try $ char c >> noneOf "\r\n"++pCSVUnquotedCell :: CSVOptions -> Parser Text+pCSVUnquotedCell opts = T.pack <$>+  many (satisfy (\c -> c /= csvDelim opts && c /= '\r' && c /= '\n'+                  && c /= csvQuote opts))++pCSVDelim :: CSVOptions -> Parser ()+pCSVDelim opts = do+  char (csvDelim opts)+  if csvKeepSpace opts+     then return ()+     else skipMany (oneOf " \t")++endline :: Parser ()+endline = do+  optional (void $ char '\r')+  void $ char '\n'
+ src/Text/Pandoc/Class.hs view
@@ -0,0 +1,999 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE ScopedTypeVariables #-}+#if MIN_VERSION_base(4,8,0)+#else+{-# LANGUAGE OverlappingInstances #-}+#endif++{-+Copyright (C) 2016-17 Jesse Rosenthal <jrosenthal@jhu.edu>+and John MacFarlane.++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation; either version 2 of the License, or+(at your option) any later version.++This program is distributed in the hope that it will be useful,+but WITHOUT ANY WARRANTY; without even the implied warranty of+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+GNU General Public License for more details.++You should have received a copy of the GNU General Public License+along with this program; if not, write to the Free Software+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+-}++{- |+   Module      : Text.Pandoc.Class+   Copyright   : Copyright (C) 2016-17 Jesse Rosenthal, John MacFarlane+   License     : GNU GPL, version 2 or above++   Maintainer  : Jesse Rosenthal <jrosenthal@jhu.edu>+   Stability   : alpha+   Portability : portable++This module defines a type class, 'PandocMonad', for pandoc readers+and writers. A pure instance 'PandocPure' and an impure instance+'PandocIO' are provided.  This allows users of the library to choose+whether they want conversions to perform IO operations (such as+reading include files or images).+-}++module Text.Pandoc.Class ( PandocMonad(..)+                         , CommonState(..)+                         , PureState(..)+                         , getPureState+                         , getsPureState+                         , putPureState+                         , modifyPureState+                         , getPOSIXTime+                         , getZonedTime+                         , readFileFromDirs+                         , report+                         , setTrace+                         , setRequestHeader+                         , getLog+                         , setVerbosity+                         , getVerbosity+                         , getMediaBag+                         , setMediaBag+                         , insertMedia+                         , setUserDataDir+                         , getUserDataDir+                         , fetchItem+                         , getInputFiles+                         , setInputFiles+                         , getOutputFile+                         , setOutputFile+                         , setResourcePath+                         , getResourcePath+                         , PandocIO(..)+                         , PandocPure(..)+                         , FileTree(..)+                         , FileInfo(..)+                         , addToFileTree+                         , runIO+                         , runIOorExplode+                         , runPure+                         , readDefaultDataFile+                         , readDataFile+                         , fetchMediaResource+                         , fillMediaBag+                         , extractMedia+                         , toLang+                         , setTranslations+                         , translateTerm+                         , Translations+                         ) where++import Prelude hiding (readFile)+import System.Random (StdGen, next, mkStdGen)+import qualified System.Random as IO (newStdGen)+import Codec.Archive.Zip+import qualified Data.CaseInsensitive as CI+import Data.Unique (hashUnique)+import Data.List (stripPrefix)+import qualified Data.Unique as IO (newUnique)+import qualified Text.Pandoc.UTF8 as UTF8+import qualified System.Directory as Directory+import Text.Pandoc.Compat.Time (UTCTime)+import Text.Pandoc.Logging+import Text.Parsec (ParsecT, getPosition, sourceLine, sourceName)+import qualified Text.Pandoc.Compat.Time as IO (getCurrentTime)+import Text.Pandoc.MIME (MimeType, getMimeType, extensionFromMimeType)+import Text.Pandoc.Definition+import Data.Digest.Pure.SHA (sha1, showDigest)+import Data.Maybe (fromMaybe)+import Data.Time.Clock.POSIX ( utcTimeToPOSIXSeconds+                             , posixSecondsToUTCTime+                             , POSIXTime )+import Data.Time.LocalTime (TimeZone, ZonedTime, utcToZonedTime, utc)+import Data.ByteString.Base64 (decodeLenient)+import Network.URI ( escapeURIString, nonStrictRelativeTo,+                     unEscapeString, parseURIReference, isAllowedInURI,+                     parseURI, URI(..) )+import Network.HTTP.Client+       (httpLbs, responseBody, responseHeaders,+        Request(port, host, requestHeaders), parseRequest, newManager)+import Network.HTTP.Client.Internal (addProxy)+import Network.HTTP.Client.TLS (tlsManagerSettings)+import System.Environment (getEnv)+import Network.HTTP.Types.Header ( hContentType )+import Network (withSocketsDo)+import Data.ByteString.Lazy (toChunks)+import qualified Control.Exception as E+import qualified Data.Time.LocalTime as IO (getCurrentTimeZone)+import Text.Pandoc.MediaBag (MediaBag, lookupMedia, mediaDirectory)+import Text.Pandoc.Walk (walkM, walk)+import qualified Text.Pandoc.MediaBag as MB+import qualified Data.ByteString as B+import qualified Data.ByteString.Lazy as BL+import qualified System.Environment as IO (lookupEnv)+import System.FilePath.Glob (match, compile)+import System.Directory (createDirectoryIfMissing, getDirectoryContents,+                          doesDirectoryExist)+import System.FilePath ((</>), (<.>), takeDirectory,+         takeExtension, dropExtension, isRelative, normalise)+import qualified System.FilePath.Glob as IO (glob)+import qualified System.Directory as IO (getModificationTime)+import Control.Monad as M (fail)+import Control.Monad.State.Strict+import Control.Monad.Except+import Data.Word (Word8)+import Data.Default+import System.IO.Error+import System.IO (stderr)+import qualified Data.Map as M+import Text.Pandoc.Error+import Text.Pandoc.BCP47 (Lang(..), parseBCP47, renderLang)+import Text.Pandoc.Translations (Term(..), Translations, lookupTerm,+                                 readTranslations)+import qualified Debug.Trace+#ifdef EMBED_DATA_FILES+import Text.Pandoc.Data (dataFiles)+import qualified System.FilePath.Posix as Posix+import System.FilePath (splitDirectories)+#else+import qualified Paths_pandoc as Paths+#endif++-- | The PandocMonad typeclass contains all the potentially+-- IO-related functions used in pandoc's readers and writers.+-- Instances of this typeclass may implement these functions+-- in IO (as in 'PandocIO') or using an internal state that+-- represents a file system, time, and so on (as in 'PandocPure').+class (Functor m, Applicative m, Monad m, MonadError PandocError m)+      => PandocMonad m where+  -- | Lookup an environment variable.+  lookupEnv :: String -> m (Maybe String)+  -- | Get the current (UTC) time.+  getCurrentTime :: m UTCTime+  -- | Get the locale's time zone.+  getCurrentTimeZone :: m TimeZone+  -- | Return a new generator for random numbers.+  newStdGen :: m StdGen+  -- | Return a new unique integer.+  newUniqueHash :: m Int+  -- | Retrieve contents and mime type from a URL, raising+  -- an error on failure.+  openURL :: String -> m (B.ByteString, Maybe MimeType)+  -- | Read the lazy ByteString contents from a file path,+  -- raising an error on failure.+  readFileLazy :: FilePath -> m BL.ByteString+  -- | Read the strict ByteString contents from a file path,+  -- raising an error on failure.+  readFileStrict :: FilePath -> m B.ByteString+  -- | Return a list of paths that match a glob, relative to+  -- the working directory.  See 'System.FilePath.Glob' for+  -- the glob syntax.+  glob :: String -> m [FilePath]+  -- | Returns True if file exists.+  fileExists :: FilePath -> m Bool+  -- | Returns the path of data file.+  getDataFileName :: FilePath -> m FilePath+  -- | Return the modification time of a file.+  getModificationTime :: FilePath -> m UTCTime+  -- | Get the value of the 'CommonState' used by all instances+  -- of 'PandocMonad'.+  getCommonState :: m CommonState+  -- | Set the value of the 'CommonState' used by all instances+  -- of 'PandocMonad'.+  -- | Get the value of a specific field of 'CommonState'.+  putCommonState :: CommonState -> m ()+  -- | Get the value of a specific field of 'CommonState'.+  getsCommonState :: (CommonState -> a) -> m a+  getsCommonState f = f <$> getCommonState+  -- | Modify the 'CommonState'.+  modifyCommonState :: (CommonState -> CommonState) -> m ()+  modifyCommonState f = getCommonState >>= putCommonState . f+  -- Output a log message.+  logOutput :: LogMessage -> m ()+  -- Output a debug message to sterr, using 'Debug.Trace.trace',+  -- if tracing is enabled.  Note: this writes to stderr even in+  -- pure instances.+  trace :: String -> m ()+  trace msg = do+    tracing <- getsCommonState stTrace+    when tracing $ Debug.Trace.trace ("[trace] " ++ msg) (return ())++-- * Functions defined for all PandocMonad instances++-- | Set the verbosity level.+setVerbosity :: PandocMonad m => Verbosity -> m ()+setVerbosity verbosity =+  modifyCommonState $ \st -> st{ stVerbosity = verbosity }++-- | Get the verbosity level.+getVerbosity :: PandocMonad m => m Verbosity+getVerbosity = getsCommonState stVerbosity++-- Get the accomulated log messages (in temporal order).+getLog :: PandocMonad m => m [LogMessage]+getLog = reverse <$> getsCommonState stLog++-- | Log a message using 'logOutput'.  Note that 'logOutput' is+-- called only if the verbosity level exceeds the level of the+-- message, but the message is added to the list of log messages+-- that will be retrieved by 'getLog' regardless of its verbosity level.+report :: PandocMonad m => LogMessage -> m ()+report msg = do+  verbosity <- getsCommonState stVerbosity+  let level = messageVerbosity msg+  when (level <= verbosity) $ logOutput msg+  modifyCommonState $ \st -> st{ stLog = msg : stLog st }++-- | Determine whether tracing is enabled.  This affects+-- the behavior of 'trace'.  If tracing is not enabled,+-- 'trace' does nothing.+setTrace :: PandocMonad m => Bool -> m ()+setTrace useTracing = modifyCommonState $ \st -> st{stTrace = useTracing}++-- | Set request header to use in HTTP requests.+setRequestHeader :: PandocMonad m+                 => String  -- ^ Header name+                 -> String  -- ^ Value+                 -> m ()+setRequestHeader name val = modifyCommonState $ \st ->+  st{ stRequestHeaders =+       (name, val) : filter (\(n,_) -> n /= name) (stRequestHeaders st)  }++-- | Initialize the media bag.+setMediaBag :: PandocMonad m => MediaBag -> m ()+setMediaBag mb = modifyCommonState $ \st -> st{stMediaBag = mb}++-- Retrieve the media bag.+getMediaBag :: PandocMonad m => m MediaBag+getMediaBag = getsCommonState stMediaBag++-- Insert an item into the media bag.+insertMedia :: PandocMonad m => FilePath -> Maybe MimeType -> BL.ByteString -> m ()+insertMedia fp mime bs = do+  mb <- getMediaBag+  let mb' = MB.insertMedia fp mime bs mb+  setMediaBag mb'++-- Retrieve the input filenames.+getInputFiles :: PandocMonad m => m [FilePath]+getInputFiles = getsCommonState stInputFiles++-- Set the input filenames.+setInputFiles :: PandocMonad m => [FilePath] -> m ()+setInputFiles fs = do+  let sourceURL = case fs of+                    []    -> Nothing+                    (x:_) -> case parseURI x of+                                Just u+                                  | uriScheme u `elem` ["http:","https:"] ->+                                      Just $ show u{ uriQuery = "",+                                                     uriFragment = "" }+                                _ -> Nothing++  modifyCommonState $ \st -> st{ stInputFiles = fs+                               , stSourceURL = sourceURL }++-- Retrieve the output filename.+getOutputFile :: PandocMonad m => m (Maybe FilePath)+getOutputFile = getsCommonState stOutputFile++-- Set the output filename.+setOutputFile :: PandocMonad m => Maybe FilePath -> m ()+setOutputFile mbf = modifyCommonState $ \st -> st{ stOutputFile = mbf }++-- Retrieve the resource path searched by 'fetchItem'.+getResourcePath :: PandocMonad m => m [FilePath]+getResourcePath = getsCommonState stResourcePath++-- Set the resource path searched by 'fetchItem'.+setResourcePath :: PandocMonad m => [FilePath] -> m ()+setResourcePath ps = modifyCommonState $ \st -> st{stResourcePath = ps}++-- Get the POSIX time.+getPOSIXTime :: PandocMonad m => m POSIXTime+getPOSIXTime = utcTimeToPOSIXSeconds <$> getCurrentTime++-- Get the zoned time.+getZonedTime :: PandocMonad m => m ZonedTime+getZonedTime = do+  t <- getCurrentTime+  tz <- getCurrentTimeZone+  return $ utcToZonedTime tz t++-- | Read file, checking in any number of directories.+readFileFromDirs :: PandocMonad m => [FilePath] -> FilePath -> m (Maybe String)+readFileFromDirs [] _ = return Nothing+readFileFromDirs (d:ds) f = catchError+    ((Just . UTF8.toStringLazy) <$> readFileLazy (d </> f))+    (\_ -> readFileFromDirs ds f)++--++-- | 'CommonState' represents state that is used by all+-- instances of 'PandocMonad'.  Normally users should not+-- need to interact with it directly; instead, auxiliary+-- functions like 'setVerbosity' and 'withMediaBag' should be used.+data CommonState = CommonState { stLog          :: [LogMessage]+                                 -- ^ A list of log messages in reverse order+                               , stUserDataDir  :: Maybe FilePath+                                 -- ^ Directory to search for data files+                               , stSourceURL    :: Maybe String+                                 -- ^ Absolute URL + dir of 1st source file+                               , stRequestHeaders :: [(String, String)]+                                 -- ^ Headers to add for HTTP requests+                               , stMediaBag     :: MediaBag+                                 -- ^ Media parsed from binary containers+                               , stTranslations :: Maybe+                                                  (Lang, Maybe Translations)+                                 -- ^ Translations for localization+                               , stInputFiles   :: [FilePath]+                                 -- ^ List of input files from command line+                               , stOutputFile   :: Maybe FilePath+                                 -- ^ Output file from command line+                               , stResourcePath :: [FilePath]+                                 -- ^ Path to search for resources like+                                 -- included images+                               , stVerbosity    :: Verbosity+                                 -- ^ Verbosity level+                               , stTrace        :: Bool+                                 -- ^ Controls whether tracing messages are+                                 -- issued.+                               }++instance Default CommonState where+  def = CommonState { stLog = []+                    , stUserDataDir = Nothing+                    , stSourceURL = Nothing+                    , stRequestHeaders = []+                    , stMediaBag = mempty+                    , stTranslations = Nothing+                    , stInputFiles = []+                    , stOutputFile = Nothing+                    , stResourcePath = ["."]+                    , stVerbosity = WARNING+                    , stTrace = False+                    }++-- | Convert BCP47 string to a Lang, issuing warning+-- if there are problems.+toLang :: PandocMonad m => Maybe String -> m (Maybe Lang)+toLang Nothing = return Nothing+toLang (Just s) =+  case parseBCP47 s of+       Left _ -> do+         report $ InvalidLang s+         return Nothing+       Right l -> return (Just l)++-- | Select the language to use with 'translateTerm'.+-- Note that this does not read a translation file;+-- that is only done the first time 'translateTerm' is+-- used.+setTranslations :: PandocMonad m => Lang -> m ()+setTranslations lang =+  modifyCommonState $ \st -> st{ stTranslations = Just (lang, Nothing) }++-- | Load term map.+getTranslations :: PandocMonad m => m Translations+getTranslations = do+  mbtrans <- getsCommonState stTranslations+  case mbtrans of+       Nothing -> return mempty  -- no language defined+       Just (_, Just t) -> return t+       Just (lang, Nothing) -> do  -- read from file+         let translationFile = "translations/" ++ renderLang lang ++ ".yaml"+         let fallbackFile = "translations/" ++ langLanguage lang ++ ".yaml"+         let getTrans fp = do+               bs <- readDataFile fp+               case readTranslations (UTF8.toString bs) of+                    Left e   -> do+                      report $ CouldNotLoadTranslations (renderLang lang)+                        (fp ++ ": " ++ e)+                      -- make sure we don't try again...+                      modifyCommonState $ \st ->+                        st{ stTranslations = Nothing }+                      return mempty+                    Right t -> do+                      modifyCommonState $ \st ->+                                  st{ stTranslations = Just (lang, Just t) }+                      return t+         catchError (getTrans translationFile)+           (\_ ->+             catchError (getTrans fallbackFile)+               (\e -> do+                 report $ CouldNotLoadTranslations (renderLang lang)+                          $ case e of+                               PandocCouldNotFindDataFileError _ ->+                                 "data file " ++ fallbackFile ++ " not found"+                               _ -> ""+                 -- make sure we don't try again...+                 modifyCommonState $ \st -> st{ stTranslations = Nothing }+                 return mempty))++-- | Get a translation from the current term map.+-- Issue a warning if the term is not defined.+translateTerm :: PandocMonad m => Term -> m String+translateTerm term = do+  translations <- getTranslations+  case lookupTerm term translations of+       Just s -> return s+       Nothing -> do+         report $ NoTranslation (show term)+         return ""++-- | Evaluate a 'PandocIO' operation.+runIO :: PandocIO a -> IO (Either PandocError a)+runIO ma = flip evalStateT def $ runExceptT $ unPandocIO ma++-- | Evaluate a 'PandocIO' operation, handling any errors+-- by exiting with an appropriate message and error status. +runIOorExplode :: PandocIO a -> IO a+runIOorExplode ma = runIO ma >>= handleError++newtype PandocIO a = PandocIO {+  unPandocIO :: ExceptT PandocError (StateT CommonState IO) a+  } deriving ( MonadIO+             , Functor+             , Applicative+             , Monad+             , MonadError PandocError+             )++-- | Utility function to lift IO errors into 'PandocError's.+liftIOError :: (String -> IO a) -> String -> PandocIO a+liftIOError f u = do+  res <- liftIO $ tryIOError $ f u+  case res of+         Left e  -> throwError $ PandocIOError u e+         Right r -> return r++instance PandocMonad PandocIO where+  lookupEnv = liftIO . IO.lookupEnv+  getCurrentTime = liftIO IO.getCurrentTime+  getCurrentTimeZone = liftIO IO.getCurrentTimeZone+  newStdGen = liftIO IO.newStdGen+  newUniqueHash = hashUnique <$> liftIO IO.newUnique++  openURL u+   | Just u'' <- stripPrefix "data:" u = do+       let mime     = takeWhile (/=',') u''+       let contents = UTF8.fromString $+                       unEscapeString $ drop 1 $ dropWhile (/=',') u''+       return (decodeLenient contents, Just mime)+   | otherwise = do+       let toReqHeader (n, v) = (CI.mk (UTF8.fromString n), UTF8.fromString v)+       customHeaders <- map toReqHeader <$> getsCommonState stRequestHeaders+       report $ Fetching u+       res <- liftIO $ E.try $ withSocketsDo $ do+         let parseReq = parseRequest+         proxy <- tryIOError (getEnv "http_proxy")+         let addProxy' x = case proxy of+                              Left _ -> return x+                              Right pr -> parseReq pr >>= \r ->+                                  return (addProxy (host r) (port r) x)+         req <- parseReq u >>= addProxy'+         let req' = req{requestHeaders = customHeaders ++ requestHeaders req}+         resp <- newManager tlsManagerSettings >>= httpLbs req'+         return (B.concat $ toChunks $ responseBody resp,+                 UTF8.toString `fmap` lookup hContentType (responseHeaders resp))++       case res of+            Right r -> return r+            Left e  -> throwError $ PandocHttpError u e++  readFileLazy s = liftIOError BL.readFile s+  readFileStrict s = liftIOError B.readFile s++  glob = liftIOError IO.glob+  fileExists = liftIOError Directory.doesFileExist+#ifdef EMBED_DATA_FILES+  getDataFileName = return+#else+  getDataFileName = liftIOError Paths.getDataFileName+#endif+  getModificationTime = liftIOError IO.getModificationTime+  getCommonState = PandocIO $ lift get+  putCommonState x = PandocIO $ lift $ put x+  logOutput msg = liftIO $ do+    UTF8.hPutStr stderr $+        "[" ++ show (messageVerbosity msg) ++ "] "+    alertIndent $ lines $ showLogMessage msg++alertIndent :: [String] -> IO ()+alertIndent [] = return ()+alertIndent (l:ls) = do+  UTF8.hPutStrLn stderr l+  mapM_ go ls+  where go l' = do UTF8.hPutStr stderr "  "+                   UTF8.hPutStrLn stderr l'++-- | Specialized version of parseURIReference that disallows+-- single-letter schemes.  Reason:  these are usually windows absolute+-- paths.+parseURIReference' :: String -> Maybe URI+parseURIReference' s =+  case parseURIReference s of+       Just u+         | length (uriScheme u) > 2  -> Just u+         | null (uriScheme u)        -> Just u  -- protocol-relative+       _                             -> Nothing++-- | Set the user data directory in common state.+setUserDataDir :: PandocMonad m+               => Maybe FilePath+               -> m ()+setUserDataDir mbfp = modifyCommonState $ \st -> st{ stUserDataDir = mbfp }++-- | Get the user data directory from common state.+getUserDataDir :: PandocMonad m+               => m (Maybe FilePath)+getUserDataDir = getsCommonState stUserDataDir++-- | Fetch an image or other item from the local filesystem or the net.+-- Returns raw content and maybe mime type.+fetchItem :: PandocMonad m+          => String+          -> m (B.ByteString, Maybe MimeType)+fetchItem s = do+  mediabag <- getMediaBag+  case lookupMedia s mediabag of+    Just (mime, bs) -> return (BL.toStrict bs, Just mime)+    Nothing -> downloadOrRead s++downloadOrRead :: PandocMonad m+               => String+               -> m (B.ByteString, Maybe MimeType)+downloadOrRead s = do+  sourceURL <- getsCommonState stSourceURL+  case (sourceURL >>= parseURIReference' .+                       ensureEscaped, ensureEscaped s) of+    (Just u, s') -> -- try fetching from relative path at source+       case parseURIReference' s' of+            Just u' -> openURL $ show $ u' `nonStrictRelativeTo` u+            Nothing -> openURL s' -- will throw error+    (Nothing, s'@('/':'/':_)) ->  -- protocol-relative URI+       case parseURIReference' s' of+            Just u' -> openURL $ show $ u' `nonStrictRelativeTo` httpcolon+            Nothing -> openURL s' -- will throw error+    (Nothing, s') ->+       case parseURI s' of  -- requires absolute URI+            -- We don't want to treat C:/ as a scheme:+            Just u' | length (uriScheme u') > 2 -> openURL (show u')+            Just u' | uriScheme u' == "file:" ->+                 readLocalFile $ dropWhile (=='/') (uriPath u')+            _ -> readLocalFile fp -- get from local file system+   where readLocalFile f = do+             resourcePath <- getResourcePath+             cont <- if isRelative f+                        then withPaths resourcePath readFileStrict f+                        else readFileStrict f+             return (cont, mime)+         httpcolon = URI{ uriScheme = "http:",+                          uriAuthority = Nothing,+                          uriPath = "",+                          uriQuery = "",+                          uriFragment = "" }+         dropFragmentAndQuery = takeWhile (\c -> c /= '?' && c /= '#')+         fp = unEscapeString $ dropFragmentAndQuery s+         mime = case takeExtension fp of+                     ".gz" -> getMimeType $ dropExtension fp+                     ".svgz" -> getMimeType $ dropExtension fp ++ ".svg"+                     x     -> getMimeType x+         ensureEscaped = escapeURIString isAllowedInURI . map convertSlash+         convertSlash '\\' = '/'+         convertSlash x    = x++-- Retrieve default reference.docx.+getDefaultReferenceDocx :: PandocMonad m => m Archive+getDefaultReferenceDocx = do+  let paths = ["[Content_Types].xml",+               "_rels/.rels",+               "docProps/app.xml",+               "docProps/core.xml",+               "word/document.xml",+               "word/fontTable.xml",+               "word/footnotes.xml",+               "word/numbering.xml",+               "word/settings.xml",+               "word/webSettings.xml",+               "word/styles.xml",+               "word/_rels/document.xml.rels",+               "word/_rels/footnotes.xml.rels",+               "word/theme/theme1.xml"]+  let toLazy = BL.fromChunks . (:[])+  let pathToEntry path = do+        epochtime <- (floor . utcTimeToPOSIXSeconds) <$> getCurrentTime+        contents <- toLazy <$> readDataFile ("docx/" ++ path)+        return $ toEntry path epochtime contents+  datadir <- getUserDataDir+  mbArchive <- case datadir of+                    Nothing   -> return Nothing+                    Just d    -> do+                       exists <- fileExists (d </> "reference.docx")+                       if exists+                          then return (Just (d </> "reference.docx"))+                          else return Nothing+  case mbArchive of+     Just arch -> toArchive <$> readFileLazy arch+     Nothing   -> foldr addEntryToArchive emptyArchive <$>+                     mapM pathToEntry paths++-- Retrieve default reference.odt.+getDefaultReferenceODT :: PandocMonad m => m Archive+getDefaultReferenceODT = do+  let paths = ["mimetype",+               "manifest.rdf",+               "styles.xml",+               "content.xml",+               "meta.xml",+               "settings.xml",+               "Configurations2/accelerator/current.xml",+               "Thumbnails/thumbnail.png",+               "META-INF/manifest.xml"]+  let pathToEntry path = do epochtime <- floor `fmap` getPOSIXTime+                            contents <- (BL.fromChunks . (:[])) `fmap`+                                          readDataFile ("odt/" ++ path)+                            return $ toEntry path epochtime contents+  datadir <- getUserDataDir+  mbArchive <- case datadir of+                    Nothing   -> return Nothing+                    Just d    -> do+                       exists <- fileExists (d </> "reference.odt")+                       if exists+                          then return (Just (d </> "reference.odt"))+                          else return Nothing+  case mbArchive of+     Just arch -> toArchive <$> readFileLazy arch+     Nothing   -> foldr addEntryToArchive emptyArchive <$>+                     mapM pathToEntry paths++-- | Read file from user data directory or,+-- if not found there, from Cabal data directory.+readDataFile :: PandocMonad m => FilePath -> m B.ByteString+readDataFile fname = do+  datadir <- getUserDataDir+  case datadir of+       Nothing -> readDefaultDataFile fname+       Just userDir -> do+         exists <- fileExists (userDir </> fname)+         if exists+            then readFileStrict (userDir </> fname)+            else readDefaultDataFile fname++-- | Read file from from Cabal data directory.+readDefaultDataFile :: PandocMonad m => FilePath -> m B.ByteString+readDefaultDataFile "reference.docx" =+  (B.concat . BL.toChunks . fromArchive) <$> getDefaultReferenceDocx+readDefaultDataFile "reference.odt" =+  (B.concat . BL.toChunks . fromArchive) <$> getDefaultReferenceODT+readDefaultDataFile fname =+#ifdef EMBED_DATA_FILES+  case lookup (makeCanonical fname) dataFiles of+    Nothing       -> throwError $ PandocCouldNotFindDataFileError fname+    Just contents -> return contents+  where makeCanonical = Posix.joinPath . transformPathParts . splitDirectories+        transformPathParts = reverse . foldl go []+        go as     "."  = as+        go (_:as) ".." = as+        go as     x    = x : as+#else+  getDataFileName fname' >>= checkExistence >>= readFileStrict+    where fname' = if fname == "MANUAL.txt" then fname else "data" </> fname++checkExistence :: PandocMonad m => FilePath -> m FilePath+checkExistence fn = do+  exists <- fileExists fn+  if exists+     then return fn+     else throwError $ PandocCouldNotFindDataFileError fn+#endif++withPaths :: PandocMonad m => [FilePath] -> (FilePath -> m a) -> FilePath -> m a+withPaths [] _ fp = throwError $ PandocResourceNotFound fp+withPaths (p:ps) action fp =+  catchError (action (p </> fp))+             (\_ -> withPaths ps action fp)++-- | Fetch local or remote resource (like an image) and provide data suitable+-- for adding it to the MediaBag.+fetchMediaResource :: PandocMonad m+              => String -> m (FilePath, Maybe MimeType, BL.ByteString)+fetchMediaResource src = do+  (bs, mt) <- downloadOrRead src+  let ext = fromMaybe (takeExtension src)+                      (mt >>= extensionFromMimeType)+  let bs' = BL.fromChunks [bs]+  let basename = showDigest $ sha1 bs'+  let fname = basename <.> ext+  return (fname, mt, bs')++-- | Traverse tree, filling media bag for any images that+-- aren't already in the media bag.+fillMediaBag :: PandocMonad m => Pandoc -> m Pandoc+fillMediaBag d = walkM handleImage d+  where handleImage :: PandocMonad m => Inline -> m Inline+        handleImage (Image attr lab (src, tit)) = catchError+          (do mediabag <- getMediaBag+              case lookupMedia src mediabag of+                Just (_, _) -> return $ Image attr lab (src, tit)+                Nothing -> do+                  (fname, mt, bs) <- fetchMediaResource src+                  insertMedia fname mt bs+                  return $ Image attr lab (fname, tit))+          (\e ->+              case e of+                PandocResourceNotFound _ -> do+                  report $ CouldNotFetchResource src+                            "replacing image with description"+                  -- emit alt text+                  return $ Span ("",["image"],[]) lab+                PandocHttpError u er -> do+                  report $ CouldNotFetchResource u+                            (show er ++ "\rReplacing image with description.")+                  -- emit alt text+                  return $ Span ("",["image"],[]) lab+                _ -> throwError e)+        handleImage x = return x++-- | Extract media from the mediabag into a directory.+extractMedia :: FilePath -> Pandoc -> PandocIO Pandoc+extractMedia dir d = do+  media <- getMediaBag+  case [fp | (fp, _, _) <- mediaDirectory media] of+        []  -> return d+        fps -> do+          mapM_ (writeMedia dir media) fps+          return $ walk (adjustImagePath dir fps) d++-- Write the contents of a media bag to a path.+writeMedia :: FilePath -> MediaBag -> FilePath -> PandocIO ()+writeMedia dir mediabag subpath = do+  -- we join and split to convert a/b/c to a\b\c on Windows;+  -- in zip containers all paths use /+  let fullpath = dir </> normalise subpath+  let mbcontents = lookupMedia subpath mediabag+  case mbcontents of+       Nothing -> throwError $ PandocResourceNotFound subpath+       Just (_, bs) -> do+         report $ Extracting fullpath+         liftIOError (createDirectoryIfMissing True) (takeDirectory fullpath)+         liftIOError (\p -> BL.writeFile p bs) fullpath++adjustImagePath :: FilePath -> [FilePath] -> Inline -> Inline+adjustImagePath dir paths (Image attr lab (src, tit))+   | src `elem` paths = Image attr lab (dir ++ "/" ++ src, tit)+adjustImagePath _ _ x = x++-- | The 'PureState' contains ersatz representations+-- of things that would normally be obtained through IO.+data PureState = PureState { stStdGen     :: StdGen+                           , stWord8Store :: [Word8] -- should be+                                                     -- inifinite,+                                                     -- i.e. [1..]+                           , stUniqStore  :: [Int] -- should be+                                                   -- inifinite and+                                                   -- contain every+                                                   -- element at most+                                                   -- once, e.g. [1..]+                           , stEnv :: [(String, String)]+                           , stTime :: UTCTime+                           , stTimeZone :: TimeZone+                           , stReferenceDocx :: Archive+                           , stReferenceODT :: Archive+                           , stFiles :: FileTree+                           , stUserDataFiles :: FileTree+                           , stCabalDataFiles :: FileTree+                           }++instance Default PureState where+  def = PureState { stStdGen = mkStdGen 1848+                  , stWord8Store = [1..]+                  , stUniqStore = [1..]+                  , stEnv = [("USER", "pandoc-user")]+                  , stTime = posixSecondsToUTCTime 0+                  , stTimeZone = utc+                  , stReferenceDocx = emptyArchive+                  , stReferenceODT = emptyArchive+                  , stFiles = mempty+                  , stUserDataFiles = mempty+                  , stCabalDataFiles = mempty+                  }+++getPureState :: PandocPure PureState+getPureState = PandocPure $ lift $ lift get++getsPureState :: (PureState -> a) -> PandocPure a+getsPureState f = f <$> getPureState++putPureState :: PureState -> PandocPure ()+putPureState ps= PandocPure $ lift $ lift $ put ps++modifyPureState :: (PureState -> PureState) -> PandocPure ()+modifyPureState f = PandocPure $ lift $ lift $ modify f+++data FileInfo = FileInfo { infoFileMTime :: UTCTime+                         , infoFileContents :: B.ByteString+                         }++newtype FileTree = FileTree {unFileTree :: M.Map FilePath FileInfo}+  deriving (Monoid)++getFileInfo :: FilePath -> FileTree -> Maybe FileInfo+getFileInfo fp tree = M.lookup fp $ unFileTree tree++-- | Add the specified file to the FileTree. If file+-- is a directory, add its contents recursively.+addToFileTree :: FileTree -> FilePath -> IO FileTree+addToFileTree (FileTree treemap) fp = do+  isdir <- doesDirectoryExist fp+  if isdir+     then do -- recursively add contents of directories+       let isSpecial ".." = True+           isSpecial "."  = True+           isSpecial _    = False+       fs <- (map (fp </>) . filter (not . isSpecial)) <$> getDirectoryContents fp+       foldM addToFileTree (FileTree treemap) fs+     else do+       contents <- B.readFile fp+       mtime <- IO.getModificationTime fp+       return $ FileTree $+                M.insert fp FileInfo{ infoFileMTime = mtime+                                    , infoFileContents = contents } treemap++newtype PandocPure a = PandocPure {+  unPandocPure :: ExceptT PandocError+                  (StateT CommonState (State PureState)) a+  } deriving ( Functor+             , Applicative+             , Monad+             , MonadError PandocError+             )++-- Run a 'PandocPure' operation.+runPure :: PandocPure a -> Either PandocError a+runPure x = flip evalState def $+            flip evalStateT def $+            runExceptT $+            unPandocPure x++instance PandocMonad PandocPure where+  lookupEnv s = do+    env <- getsPureState stEnv+    return (lookup s env)++  getCurrentTime = getsPureState stTime++  getCurrentTimeZone = getsPureState stTimeZone++  newStdGen = do+    g <- getsPureState stStdGen+    let (_, nxtGen) = next g+    modifyPureState $ \st -> st { stStdGen = nxtGen }+    return g++  newUniqueHash = do+    uniqs <- getsPureState stUniqStore+    case uniqs of+      u : us -> do+        modifyPureState $ \st -> st { stUniqStore = us }+        return u+      _ -> M.fail "uniq store ran out of elements"+  openURL u = throwError $ PandocResourceNotFound u+  readFileLazy fp = do+    fps <- getsPureState stFiles+    case infoFileContents <$> getFileInfo fp fps of+      Just bs -> return (BL.fromStrict bs)+      Nothing -> throwError $ PandocResourceNotFound fp+  readFileStrict fp = do+    fps <- getsPureState stFiles+    case infoFileContents <$> getFileInfo fp fps of+      Just bs -> return bs+      Nothing -> throwError $ PandocResourceNotFound fp++  glob s = do+    FileTree ftmap <- getsPureState stFiles+    return $ filter (match (compile s)) $ M.keys ftmap++  fileExists fp = do+    fps <- getsPureState stFiles+    case getFileInfo fp fps of+         Nothing -> return False+         Just _  -> return True++  getDataFileName fp = return $ "data/" ++ fp++  getModificationTime fp = do+    fps <- getsPureState stFiles+    case infoFileMTime <$> getFileInfo fp fps of+      Just tm -> return tm+      Nothing -> throwError $ PandocIOError fp+                    (userError "Can't get modification time")++  getCommonState = PandocPure $ lift get+  putCommonState x = PandocPure $ lift $ put x++  logOutput _msg = return ()++-- This requires UndecidableInstances.  We could avoid that+-- by repeating the definitions below for every monad transformer+-- we use: ReaderT, WriterT, StateT, RWST.  But this seems to+-- be harmless.+instance (MonadTrans t, PandocMonad m, Functor (t m),+          MonadError PandocError (t m), Monad (t m),+          Applicative (t m)) => PandocMonad (t m) where+  lookupEnv = lift . lookupEnv+  getCurrentTime = lift getCurrentTime+  getCurrentTimeZone = lift getCurrentTimeZone+  newStdGen = lift newStdGen+  newUniqueHash = lift newUniqueHash+  openURL = lift . openURL+  readFileLazy = lift . readFileLazy+  readFileStrict = lift . readFileStrict+  glob = lift . glob+  fileExists = lift . fileExists+  getDataFileName = lift . getDataFileName+  getModificationTime = lift . getModificationTime+  getCommonState = lift getCommonState+  putCommonState = lift . putCommonState+  logOutput = lift . logOutput++#if MIN_VERSION_base(4,8,0)+instance {-# OVERLAPS #-} PandocMonad m => PandocMonad (ParsecT s st m) where+#else+instance PandocMonad m => PandocMonad (ParsecT s st m) where+#endif+  lookupEnv = lift . lookupEnv+  getCurrentTime = lift getCurrentTime+  getCurrentTimeZone = lift getCurrentTimeZone+  newStdGen = lift newStdGen+  newUniqueHash = lift newUniqueHash+  openURL = lift . openURL+  readFileLazy = lift . readFileLazy+  readFileStrict = lift . readFileStrict+  glob = lift . glob+  fileExists = lift . fileExists+  getDataFileName = lift . getDataFileName+  getModificationTime = lift . getModificationTime+  getCommonState = lift getCommonState+  putCommonState = lift . putCommonState+  trace msg = do+    tracing <- getsCommonState stTrace+    when tracing $ do+      pos <- getPosition+      Debug.Trace.trace+        ("[trace] Parsed " ++ msg ++ " at line " +++            show (sourceLine pos) +++            if sourceName pos == "chunk"+               then " of chunk"+               else "")+        (return ())+  logOutput = lift . logOutput
+ src/Text/Pandoc/Data.hs view
@@ -0,0 +1,21 @@+{-# LANGUAGE TemplateHaskell #-}++module Text.Pandoc.Data (dataFiles) where++import qualified Data.ByteString as B+import Data.FileEmbed+import System.FilePath (splitDirectories)+import qualified System.FilePath.Posix as Posix++-- We ensure that the data files are stored using Posix+-- path separators (/), even on Windows.+dataFiles :: [(FilePath, B.ByteString)]+dataFiles = map (\(fp, contents) ->+  (Posix.joinPath (splitDirectories fp), contents)) dataFiles'++dataFiles' :: [(FilePath, B.ByteString)]+dataFiles' = ("MANUAL.txt", $(embedFile "MANUAL.txt")) :+             -- handle the hidden file separately, since embedDir doesn't+             -- include it:+             ("docx/_rels/.rels", $(embedFile "data/docx/_rels/.rels")) :+             $(embedDir "data")
− src/Text/Pandoc/Data.hsb
@@ -1,15 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}--- to be processed using hsb2hs-module Text.Pandoc.Data (dataFiles) where-import qualified Data.ByteString as B-import System.FilePath (splitDirectories)-import qualified System.FilePath.Posix as Posix---- We ensure that the data files are stored using Posix--- path separators (/), even on Windows.-dataFiles :: [(FilePath, B.ByteString)]-dataFiles = map (\(fp, contents) ->-  (Posix.joinPath (splitDirectories fp), contents)) dataFiles'--dataFiles' :: [(FilePath, B.ByteString)]-dataFiles' = ("MANUAL.txt", %blob "MANUAL.txt") : %blobs "data"
src/Text/Pandoc/Emoji.hs view
@@ -903,4 +903,3 @@   ,("zero","0\65039\8419")   ,("zzz","\128164")   ]-
src/Text/Pandoc/Error.hs view
@@ -1,6 +1,7 @@-{-# LANGUAGE DeriveDataTypeable, DeriveGeneric #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric      #-} {--Copyright (C) 2006-2016 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2006-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -18,7 +19,7 @@ -} {- |    Module      : Text.Pandoc.Error-   Copyright   : Copyright (C) 2006-2016 John MacFarlane+   Copyright   : Copyright (C) 2006-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -29,40 +30,94 @@ during parsing.  -}-module Text.Pandoc.Error (PandocError(..), handleError) where+module Text.Pandoc.Error (+  PandocError(..),+  handleError) where +import Control.Exception (Exception)+import Data.Typeable (Typeable)+import GHC.Generics (Generic)+import Network.HTTP.Client (HttpException)+import System.Exit (ExitCode (..), exitWith)+import System.IO (stderr)+import qualified Text.Pandoc.UTF8 as UTF8 import Text.Parsec.Error import Text.Parsec.Pos hiding (Line)-import GHC.Generics (Generic)-import Data.Generics (Typeable)-import Control.Exception (Exception)  type Input = String -data PandocError = -- | Generic parse failure-                   ParseFailure String-                 -- | Error thrown by a Parsec parser-                 | ParsecError Input ParseError+data PandocError = PandocIOError String IOError+                 | PandocHttpError String HttpException+                 | PandocShouldNeverHappenError String+                 | PandocSomeError String+                 | PandocParseError String+                 | PandocParsecError Input ParseError+                 | PandocMakePDFError String+                 | PandocOptionError String+                 | PandocSyntaxMapError String+                 | PandocFailOnWarningError+                 | PandocPDFProgramNotFoundError String+                 | PandocPDFError String+                 | PandocFilterError String String+                 | PandocCouldNotFindDataFileError String+                 | PandocResourceNotFound String+                 | PandocTemplateError String+                 | PandocAppError String+                 | PandocEpubSubdirectoryError String+                 | PandocMacroLoop String                  deriving (Show, Typeable, Generic)  instance Exception PandocError --- | An unsafe method to handle `PandocError`s.-handleError :: Either PandocError a -> a-handleError (Right r) = r-handleError (Left err) =-  case err of-    ParseFailure string -> error string-    ParsecError input err' ->+-- | Handle PandocError by exiting with an error message.+handleError :: Either PandocError a -> IO a+handleError (Right r) = return r+handleError (Left e) =+  case e of+    PandocIOError _ err' -> ioError err'+    PandocHttpError u err' -> err 61 $+      "Could not fetch " ++ u ++ "\n" ++ show err'+    PandocShouldNeverHappenError s -> err 62 s+    PandocSomeError s -> err 63 s+    PandocParseError s -> err 64 s+    PandocParsecError input err' ->         let errPos = errorPos err'             errLine = sourceLine errPos             errColumn = sourceColumn errPos             ls = lines input ++ [""]             errorInFile = if length ls > errLine - 1-                            then concat ["\n", (ls !! (errLine - 1))+                            then concat ["\n", ls !! (errLine - 1)                                         ,"\n", replicate (errColumn - 1) ' '                                         ,"^"]                         else ""-        in  error $ "\nError at " ++ show  err'-                ++ errorInFile+        in  err 65 $ "\nError at " ++ show  err' +++                     -- if error comes from a chunk or included file,+                     -- then we won't get the right text this way:+                     if sourceName errPos == "source"+                        then errorInFile+                        else ""+    PandocMakePDFError s -> err 65 s+    PandocOptionError s -> err 2 s+    PandocSyntaxMapError s -> err 67 s+    PandocFailOnWarningError -> err 3 "Failing because there were warnings."+    PandocPDFProgramNotFoundError pdfprog -> err 47 $+        pdfprog ++ " not found. Please select a different --pdf-engine or install " ++ pdfprog+    PandocPDFError logmsg -> err 43 $ "Error producing PDF.\n" ++ logmsg+    PandocFilterError filtername msg -> err 83 $ "Error running filter " +++        filtername ++ ":\n" ++ msg+    PandocCouldNotFindDataFileError fn -> err 97 $+        "Could not find data file " ++ fn+    PandocResourceNotFound fn -> err 99 $+        "File " ++ fn ++ " not found in resource path"+    PandocTemplateError s -> err 5 s+    PandocAppError s -> err 1 s+    PandocEpubSubdirectoryError s -> err 31 $+      "EPUB subdirectory name '" ++ s ++ "' contains illegal characters"+    PandocMacroLoop s -> err 91 $+      "Loop encountered in expanding macro " ++ s +err :: Int -> String -> IO a+err exitCode msg = do+  UTF8.hPutStrLn stderr msg+  exitWith $ ExitFailure exitCode+  return undefined
+ src/Text/Pandoc/Extensions.hs view
@@ -0,0 +1,371 @@+{-+Copyright (C) 2012-2017 John MacFarlane <jgm@berkeley.edu>++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation; either version 2 of the License, or+(at your option) any later version.++This program is distributed in the hope that it will be useful,+but WITHOUT ANY WARRANTY; without even the implied warranty of+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+GNU General Public License for more details.++You should have received a copy of the GNU General Public License+along with this program; if not, write to the Free Software+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric      #-}++{- |+   Module      : Text.Pandoc.Extensions+   Copyright   : Copyright (C) 2012-2017 John MacFarlane+   License     : GNU GPL, version 2 or above++   Maintainer  : John MacFarlane <jgm@berkeley.edu>+   Stability   : alpha+   Portability : portable++Data structures and functions for representing markup extensions.+-}+module Text.Pandoc.Extensions ( Extension(..)+                              , Extensions+                              , emptyExtensions+                              , extensionsFromList+                              , parseFormatSpec+                              , extensionEnabled+                              , enableExtension+                              , disableExtension+                              , getDefaultExtensions+                              , pandocExtensions+                              , plainExtensions+                              , strictExtensions+                              , phpMarkdownExtraExtensions+                              , githubMarkdownExtensions+                              , multimarkdownExtensions )+where+import Data.Aeson (FromJSON (..), ToJSON (..), defaultOptions,+                   genericToEncoding)+import Data.Bits (clearBit, setBit, testBit, (.|.))+import Data.Data (Data)+import Data.Typeable (Typeable)+import GHC.Generics (Generic)+import Text.Pandoc.Shared (safeRead)+import Text.Parsec++newtype Extensions = Extensions Integer+  deriving (Show, Read, Eq, Ord, Data, Typeable, Generic)++instance ToJSON Extensions where+  toEncoding = genericToEncoding defaultOptions+instance FromJSON Extensions++instance Monoid Extensions where+  mempty = Extensions 0+  mappend (Extensions a) (Extensions b) = Extensions (a .|. b)++extensionsFromList :: [Extension] -> Extensions+extensionsFromList = foldr enableExtension emptyExtensions++emptyExtensions :: Extensions+emptyExtensions = Extensions 0++extensionEnabled :: Extension -> Extensions -> Bool+extensionEnabled x (Extensions exts) = testBit exts (fromEnum x)++enableExtension :: Extension -> Extensions -> Extensions+enableExtension x (Extensions exts) = Extensions (setBit exts (fromEnum x))++disableExtension :: Extension -> Extensions -> Extensions+disableExtension x (Extensions exts) = Extensions (clearBit exts (fromEnum x))++-- | Individually selectable syntax extensions.+data Extension =+      Ext_footnotes           -- ^ Pandoc/PHP/MMD style footnotes+    | Ext_inline_notes        -- ^ Pandoc-style inline notes+    | Ext_pandoc_title_block  -- ^ Pandoc title block+    | Ext_yaml_metadata_block -- ^ YAML metadata block+    | Ext_mmd_title_block     -- ^ Multimarkdown metadata block+    | Ext_table_captions      -- ^ Pandoc-style table captions+    | Ext_implicit_figures    -- ^ A paragraph with just an image is a figure+    | Ext_simple_tables       -- ^ Pandoc-style simple tables+    | Ext_multiline_tables    -- ^ Pandoc-style multiline tables+    | Ext_grid_tables         -- ^ Grid tables (pandoc, reST)+    | Ext_pipe_tables         -- ^ Pipe tables (as in PHP markdown extra)+    | Ext_citations           -- ^ Pandoc/citeproc citations+    | Ext_raw_tex             -- ^ Allow raw TeX (other than math)+    | Ext_raw_html            -- ^ Allow raw HTML+    | Ext_tex_math_dollars    -- ^ TeX math between $..$ or $$..$$+    | Ext_tex_math_single_backslash  -- ^ TeX math btw \(..\) \[..\]+    | Ext_tex_math_double_backslash  -- ^ TeX math btw \\(..\\) \\[..\\]+    | Ext_latex_macros        -- ^ Parse LaTeX macro definitions (for math only)+    | Ext_fenced_code_blocks  -- ^ Parse fenced code blocks+    | Ext_fenced_code_attributes  -- ^ Allow attributes on fenced code blocks+    | Ext_backtick_code_blocks    -- ^ GitHub style ``` code blocks+    | Ext_inline_code_attributes  -- ^ Allow attributes on inline code+    | Ext_raw_attribute           -- ^ Allow explicit raw blocks/inlines+    | Ext_markdown_in_html_blocks -- ^ Interpret as markdown inside HTML blocks+    | Ext_native_divs             -- ^ Use Div blocks for contents of <div> tags+    | Ext_fenced_divs             -- ^ Allow fenced div syntax :::+    | Ext_native_spans            -- ^ Use Span inlines for contents of <span>+    | Ext_bracketed_spans         -- ^ Bracketed spans with attributes+    | Ext_markdown_attribute      -- ^ Interpret text inside HTML as markdown+                                  --   iff container has attribute 'markdown'+    | Ext_escaped_line_breaks     -- ^ Treat a backslash at EOL as linebreak+    | Ext_link_attributes         -- ^ link and image attributes+    | Ext_mmd_link_attributes     -- ^ MMD style reference link attributes+    | Ext_autolink_bare_uris  -- ^ Make all absolute URIs into links+    | Ext_fancy_lists         -- ^ Enable fancy list numbers and delimiters+    | Ext_lists_without_preceding_blankline -- ^ Allow lists without preceding blank+    | Ext_four_space_rule     -- ^ Require 4-space indent for list contents+    | Ext_startnum            -- ^ Make start number of ordered list significant+    | Ext_definition_lists    -- ^ Definition lists as in pandoc, mmd, php+    | Ext_compact_definition_lists  -- ^ Definition lists without+                               -- space between items, and disallow laziness+    | Ext_example_lists       -- ^ Markdown-style numbered examples+    | Ext_all_symbols_escapable  -- ^ Make all non-alphanumerics escapable+    | Ext_angle_brackets_escapable  -- ^ Make < and > escapable+    | Ext_intraword_underscores  -- ^ Treat underscore inside word as literal+    | Ext_blank_before_blockquote -- ^ Require blank line before a blockquote+    | Ext_blank_before_header     -- ^ Require blank line before a header+    | Ext_space_in_atx_header -- ^ Require space between # and header text+    | Ext_strikeout           -- ^ Strikeout using ~~this~~ syntax+    | Ext_superscript         -- ^ Superscript using ^this^ syntax+    | Ext_subscript           -- ^ Subscript using ~this~ syntax+    | Ext_hard_line_breaks    -- ^ All newlines become hard line breaks+    | Ext_ignore_line_breaks  -- ^ Newlines in paragraphs are ignored+    | Ext_east_asian_line_breaks  -- ^ Newlines in paragraphs are ignored between+                              -- East Asian wide characters+    | Ext_literate_haskell    -- ^ Enable literate Haskell conventions+    | Ext_abbreviations       -- ^ PHP markdown extra abbreviation definitions+    | Ext_emoji               -- ^ Support emoji like :smile:+    | Ext_auto_identifiers    -- ^ Automatic identifiers for headers+    | Ext_gfm_auto_identifiers  -- ^ Automatic identifiers for headers,+                                -- using GitHub's method for generating identifiers+    | Ext_ascii_identifiers   -- ^ ascii-only identifiers for headers+    | Ext_header_attributes   -- ^ Explicit header attributes {#id .class k=v}+    | Ext_mmd_header_identifiers -- ^ Multimarkdown style header identifiers [myid]+    | Ext_implicit_header_references -- ^ Implicit reference links for headers+    | Ext_line_blocks         -- ^ RST style line blocks+    | Ext_epub_html_exts      -- ^ Recognise the EPUB extended version of HTML+    | Ext_shortcut_reference_links -- ^ Shortcut reference links+    | Ext_smart               -- ^ "Smart" quotes, apostrophes, ellipses, dashes+    | Ext_old_dashes          -- ^ -- = em, - before number = en+    | Ext_spaced_reference_links -- ^ Allow space between two parts of ref link+    deriving (Show, Read, Enum, Eq, Ord, Bounded, Data, Typeable, Generic)++instance ToJSON Extension where+  toEncoding = genericToEncoding defaultOptions+instance FromJSON Extension++-- | Extensions to be used with pandoc-flavored markdown.+pandocExtensions :: Extensions+pandocExtensions = extensionsFromList+  [ Ext_footnotes+  , Ext_inline_notes+  , Ext_pandoc_title_block+  , Ext_yaml_metadata_block+  , Ext_table_captions+  , Ext_implicit_figures+  , Ext_simple_tables+  , Ext_multiline_tables+  , Ext_grid_tables+  , Ext_pipe_tables+  , Ext_citations+  , Ext_raw_tex+  , Ext_raw_html+  , Ext_tex_math_dollars+  , Ext_latex_macros+  , Ext_fenced_code_blocks+  , Ext_fenced_code_attributes+  , Ext_backtick_code_blocks+  , Ext_inline_code_attributes+  , Ext_raw_attribute+  , Ext_markdown_in_html_blocks+  , Ext_native_divs+  , Ext_fenced_divs+  , Ext_native_spans+  , Ext_bracketed_spans+  , Ext_escaped_line_breaks+  , Ext_fancy_lists+  , Ext_startnum+  , Ext_definition_lists+  , Ext_example_lists+  , Ext_all_symbols_escapable+  , Ext_intraword_underscores+  , Ext_blank_before_blockquote+  , Ext_blank_before_header+  , Ext_space_in_atx_header+  , Ext_strikeout+  , Ext_superscript+  , Ext_subscript+  , Ext_auto_identifiers+  , Ext_header_attributes+  , Ext_link_attributes+  , Ext_implicit_header_references+  , Ext_line_blocks+  , Ext_shortcut_reference_links+  , Ext_smart+  ]++-- | Extensions to be used with plain text output.+plainExtensions :: Extensions+plainExtensions = extensionsFromList+  [ Ext_table_captions+  , Ext_implicit_figures+  , Ext_simple_tables+  , Ext_multiline_tables+  , Ext_grid_tables+  , Ext_latex_macros+  , Ext_fancy_lists+  , Ext_startnum+  , Ext_definition_lists+  , Ext_example_lists+  , Ext_intraword_underscores+  , Ext_blank_before_blockquote+  , Ext_blank_before_header+  , Ext_strikeout+  ]++-- | Extensions to be used with github-flavored markdown.+phpMarkdownExtraExtensions :: Extensions+phpMarkdownExtraExtensions = extensionsFromList+  [ Ext_footnotes+  , Ext_pipe_tables+  , Ext_raw_html+  , Ext_markdown_attribute+  , Ext_fenced_code_blocks+  , Ext_definition_lists+  , Ext_intraword_underscores+  , Ext_header_attributes+  , Ext_link_attributes+  , Ext_abbreviations+  , Ext_shortcut_reference_links+  , Ext_spaced_reference_links+  ]++-- | Extensions to be used with github-flavored markdown.+githubMarkdownExtensions :: Extensions+githubMarkdownExtensions = extensionsFromList+  [ Ext_angle_brackets_escapable+  , Ext_pipe_tables+  , Ext_raw_html+  , Ext_fenced_code_blocks+  , Ext_gfm_auto_identifiers+  , Ext_ascii_identifiers+  , Ext_backtick_code_blocks+  , Ext_autolink_bare_uris+  , Ext_space_in_atx_header+  , Ext_intraword_underscores+  , Ext_strikeout+  , Ext_emoji+  , Ext_lists_without_preceding_blankline+  , Ext_shortcut_reference_links+  ]++-- | Extensions to be used with multimarkdown.+multimarkdownExtensions :: Extensions+multimarkdownExtensions = extensionsFromList+  [ Ext_pipe_tables+  , Ext_raw_html+  , Ext_markdown_attribute+  , Ext_mmd_link_attributes+  -- , Ext_raw_tex+  -- Note: MMD's raw TeX syntax requires raw TeX to be+  -- enclosed in HTML comment+  , Ext_tex_math_double_backslash+  , Ext_intraword_underscores+  , Ext_mmd_title_block+  , Ext_footnotes+  , Ext_definition_lists+  , Ext_all_symbols_escapable+  , Ext_implicit_header_references+  , Ext_shortcut_reference_links+  , Ext_auto_identifiers+  , Ext_mmd_header_identifiers+  , Ext_implicit_figures+  -- Note: MMD's syntax for superscripts and subscripts+  -- is a bit more permissive than pandoc's, allowing+  -- e^2 and a~1 instead of e^2^ and a~1~, so even with+  -- these options we don't have full support for MMD+  -- superscripts and subscripts, but there's no reason+  -- not to include these:+  , Ext_superscript+  , Ext_subscript+  , Ext_backtick_code_blocks+  , Ext_spaced_reference_links+  -- So far only in dev version of mmd:+  , Ext_raw_attribute+  ]++-- | Language extensions to be used with strict markdown.+strictExtensions :: Extensions+strictExtensions = extensionsFromList+  [ Ext_raw_html+  , Ext_shortcut_reference_links+  , Ext_spaced_reference_links+  ]++-- | Default extensions from format-describing string.+getDefaultExtensions :: String -> Extensions+getDefaultExtensions "markdown_strict" = strictExtensions+getDefaultExtensions "markdown_phpextra" = phpMarkdownExtraExtensions+getDefaultExtensions "markdown_mmd" = multimarkdownExtensions+getDefaultExtensions "markdown_github" = githubMarkdownExtensions+getDefaultExtensions "markdown"        = pandocExtensions+getDefaultExtensions "plain"           = plainExtensions+getDefaultExtensions "gfm"             = githubMarkdownExtensions+getDefaultExtensions "org"             = extensionsFromList+                                          [Ext_citations,+                                           Ext_auto_identifiers]+getDefaultExtensions "html"            = extensionsFromList+                                          [Ext_auto_identifiers,+                                           Ext_native_divs,+                                           Ext_native_spans]+getDefaultExtensions "html4"           = getDefaultExtensions "html"+getDefaultExtensions "html5"           = getDefaultExtensions "html"+getDefaultExtensions "epub"            = extensionsFromList+                                          [Ext_raw_html,+                                           Ext_native_divs,+                                           Ext_native_spans,+                                           Ext_epub_html_exts]+getDefaultExtensions "epub2"           = getDefaultExtensions "epub"+getDefaultExtensions "epub3"           = getDefaultExtensions "epub"+getDefaultExtensions "latex"           = extensionsFromList+                                          [Ext_smart,+                                           Ext_latex_macros,+                                           Ext_auto_identifiers]+getDefaultExtensions "context"         = extensionsFromList+                                          [Ext_smart,+                                           Ext_auto_identifiers]+getDefaultExtensions "textile"         = extensionsFromList+                                          [Ext_old_dashes,+                                           Ext_smart,+                                           Ext_raw_html,+                                           Ext_auto_identifiers]+getDefaultExtensions _                 = extensionsFromList+                                          [Ext_auto_identifiers]++-- | Parse a format-specifying string into a markup format and a function that+-- takes Extensions and enables and disables extensions as defined in the format+-- spec.+parseFormatSpec :: String+                -> Either ParseError (String, Extensions -> Extensions)+parseFormatSpec = parse formatSpec ""+  where formatSpec = do+          name <- formatName+          extMods <- many extMod+          return (name, \x -> foldl (flip ($)) x extMods)+        formatName = many1 $ noneOf "-+"+        extMod = do+          polarity <- oneOf "-+"+          name <- many $ noneOf "-+"+          ext <- case safeRead ("Ext_" ++ name) of+                       Just n  -> return n+                       Nothing+                         | name == "lhs" -> return Ext_literate_haskell+                         | otherwise -> fail $ "Unknown extension: " ++ name+          return $ case polarity of+                        '-' -> disableExtension ext+                        _   -> enableExtension ext
src/Text/Pandoc/Highlighting.hs view
@@ -1,5 +1,5 @@ {--Copyright (C) 2008-2016 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2008-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -18,7 +18,7 @@  {- |    Module      : Text.Pandoc.Highlighting-   Copyright   : Copyright (C) 2008-2016 John MacFarlane+   Copyright   : Copyright (C) 2008-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -28,7 +28,8 @@ Exports functions for syntax highlighting. -} -module Text.Pandoc.Highlighting ( languages+module Text.Pandoc.Highlighting ( highlightingStyles+                                , languages                                 , languagesByExtension                                 , highlight                                 , formatLaTeXInline@@ -48,15 +49,26 @@                                 , fromListingsLanguage                                 , toListingsLanguage                                 ) where-import Text.Pandoc.Definition-import Text.Pandoc.Shared (safeRead)-import Skylighting-import Data.Maybe (fromMaybe)+import Control.Monad import Data.Char (toLower) import qualified Data.Map as M-import Control.Monad+import Data.Maybe (fromMaybe) import qualified Data.Text as T+import Skylighting+import Text.Pandoc.Definition+import Text.Pandoc.Shared (safeRead) +highlightingStyles :: [(String, Style)]+highlightingStyles =+  [("pygments", pygments),+   ("tango", tango),+   ("espresso", espresso),+   ("zenburn", zenburn),+   ("kate", kate),+   ("monochrome", monochrome),+   ("breezedark", breezeDark),+   ("haddock", haddock)]+ languages :: [String] languages = [T.unpack (T.toLower (sName s)) | s <- M.elems defaultSyntaxMap] @@ -64,34 +76,34 @@ languagesByExtension ext =   [T.unpack (T.toLower (sName s)) | s <- syntaxesByExtension defaultSyntaxMap ext] -highlight :: (FormatOptions -> [SourceLine] -> a) -- ^ Formatter+highlight :: SyntaxMap+          -> (FormatOptions -> [SourceLine] -> a) -- ^ Formatter           -> Attr   -- ^ Attributes of the CodeBlock           -> String -- ^ Raw contents of the CodeBlock-          -> Maybe a -- ^ Maybe the formatted result-highlight formatter (_, classes, keyvals) rawCode =+          -> Either String a+highlight syntaxmap formatter (_, classes, keyvals) rawCode =   let firstNum = fromMaybe 1 (safeRead (fromMaybe "1" $ lookup "startFrom" keyvals))       fmtOpts = defaultFormatOpts{                   startNumber = firstNum,                   numberLines = any (`elem`                         ["number","numberLines", "number-lines"]) classes }-      tokenizeOpts = TokenizerConfig{ syntaxMap = defaultSyntaxMap+      tokenizeOpts = TokenizerConfig{ syntaxMap = syntaxmap                                     , traceOutput = False }       classes' = map T.pack classes       rawCode' = T.pack rawCode-  in  case msum (map (\l -> lookupSyntax l defaultSyntaxMap) classes') of+  in  case msum (map (`lookupSyntax` syntaxmap) classes') of             Nothing-              | numberLines fmtOpts -> Just+              | numberLines fmtOpts -> Right                               $ formatter fmtOpts{ codeClasses = [],                                                    containerClasses = classes' }-                              $ map (\ln -> [(NormalTok, ln)]) $ T.lines rawCode'-              | otherwise  -> Nothing+                              $ map (\ln -> [(NormalTok, ln)])+                              $ T.lines rawCode'+              | otherwise  -> Left ""             Just syntax  ->-              case tokenize tokenizeOpts syntax rawCode' of-                   Right slines -> Just $-                         formatter fmtOpts{ codeClasses =-                                               [T.toLower (sShortname syntax)],-                                            containerClasses = classes' } slines-                   Left _ -> Nothing+              formatter fmtOpts{ codeClasses =+                                   [T.toLower (sShortname syntax)],+                                  containerClasses = classes' } <$>+                tokenize tokenizeOpts syntax rawCode'  -- Functions for correlating latex listings package's language names -- with skylighting language names:
src/Text/Pandoc/ImageSize.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings, ScopedTypeVariables, CPP #-} {-# OPTIONS_GHC -fno-warn-type-defaults #-} {--  Copyright (C) 2011-2016 John MacFarlane <jgm@berkeley.edu>+  Copyright (C) 2011-2017 John MacFarlane <jgm@berkeley.edu>      This program is free software; you can redistribute it and/or modify     it under the terms of the GNU General Public License as published by@@ -20,7 +20,7 @@  {- | Module      : Text.Pandoc.ImageSize-Copyright   : Copyright (C) 2011-2016 John MacFarlane+Copyright   : Copyright (C) 2011-2017 John MacFarlane License     : GNU GPL, version 2 or above  Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -38,8 +38,12 @@                              , Dimension(..)                              , Direction(..)                              , dimension+                             , lengthToDim+                             , scaleDimension                              , inInch+                             , inPixel                              , inPoints+                             , inEm                              , numUnit                              , showInInch                              , showInPixel@@ -53,11 +57,13 @@ import Data.Bits import Data.Binary import Data.Binary.Get-import Text.Pandoc.Shared (safeRead, hush)+import Text.Pandoc.Shared (safeRead) import Data.Default (Default) import Numeric (showFFloat) import Text.Pandoc.Definition import Text.Pandoc.Options+import qualified Text.Pandoc.UTF8 as UTF8+import qualified Text.XML.Light as Xml import qualified Data.Map as M import Control.Monad.Except import Data.Maybe (fromMaybe)@@ -65,7 +71,7 @@ -- quick and dirty functions to get image sizes -- algorithms borrowed from wwwis.pl -data ImageType = Png | Gif | Jpeg | Pdf | Eps deriving Show+data ImageType = Png | Gif | Jpeg | Svg | Pdf | Eps deriving Show data Direction = Width | Height instance Show Direction where   show Width  = "width"@@ -75,11 +81,14 @@                | Centimeter Double                | Inch Double                | Percent Double+               | Em Double+ instance Show Dimension where   show (Pixel a)      = show   a ++ "px"   show (Centimeter a) = showFl a ++ "cm"   show (Inch a)       = showFl a ++ "in"   show (Percent a)    = show   a ++ "%"+  show (Em a)         = showFl a ++ "em"  data ImageSize = ImageSize{                      pxX   :: Integer@@ -91,8 +100,14 @@   def = ImageSize 300 200 72 72  showFl :: (RealFloat a) => a -> String-showFl a = showFFloat (Just 5) a ""+showFl a = removeExtra0s $ showFFloat (Just 5) a "" +removeExtra0s :: String -> String+removeExtra0s s =+  case dropWhile (=='0') $ reverse s of+       '.':xs -> reverse xs+       xs     -> reverse xs+ imageType :: ByteString -> Maybe ImageType imageType img = case B.take 4 img of                      "\x89\x50\x4e\x47" -> return Png@@ -100,17 +115,25 @@                      "\xff\xd8\xff\xe0" -> return Jpeg  -- JFIF                      "\xff\xd8\xff\xe1" -> return Jpeg  -- Exif                      "%PDF"             -> return Pdf+                     "<svg"             -> return Svg+                     "<?xm"+                       | findSvgTag img+                                        -> return Svg                      "%!PS"-                       | (B.take 4 $ B.drop 1 $ B.dropWhile (/=' ') img) == "EPSF"+                       |  B.take 4 (B.drop 1 $ B.dropWhile (/=' ') img) == "EPSF"                                         -> return Eps                      _                  -> mzero -imageSize :: ByteString -> Either String ImageSize-imageSize img =+findSvgTag :: ByteString -> Bool+findSvgTag img = "<svg" `B.isInfixOf` img || "<SVG" `B.isInfixOf` img++imageSize :: WriterOptions -> ByteString -> Either String ImageSize+imageSize opts img =   case imageType img of        Just Png  -> mbToEither "could not determine PNG size" $ pngSize img        Just Gif  -> mbToEither "could not determine GIF size" $ gifSize img        Just Jpeg -> jpegSize img+       Just Svg  -> mbToEither "could not determine SVG size" $ svgSize opts img        Just Eps  -> mbToEither "could not determine EPS size" $ epsSize img        Just Pdf  -> Left "could not determine PDF size" -- TODO        Nothing   -> Left "could not determine image type"@@ -145,7 +168,7 @@     (Nothing, Nothing) -> sizeInPoints s   where     ratio = fromIntegral (pxX s) / fromIntegral (pxY s)-    getDim dir = case (dimension dir attr) of+    getDim dir = case dimension dir attr of                    Just (Percent _) -> Nothing                    Just dim         -> Just $ inPoints opts dim                    Nothing          -> Nothing@@ -153,14 +176,29 @@ inPoints :: WriterOptions -> Dimension -> Double inPoints opts dim = 72 * inInch opts dim +inEm :: WriterOptions -> Dimension -> Double+inEm opts dim = (64/11) * inInch opts dim+ inInch :: WriterOptions -> Dimension -> Double inInch opts dim =   case dim of-    (Pixel a)      -> fromIntegral a / (fromIntegral $ writerDpi opts)+    (Pixel a)      -> fromIntegral a / fromIntegral (writerDpi opts)     (Centimeter a) -> a * 0.3937007874     (Inch a)       -> a     (Percent _)    -> 0+    (Em a)         -> a * (11/64) +inPixel :: WriterOptions -> Dimension -> Integer+inPixel opts dim =+  case dim of+    (Pixel a)      -> a+    (Centimeter a) -> floor $ dpi * a * 0.3937007874 :: Integer+    (Inch a)       -> floor $ dpi * a :: Integer+    (Percent _)    -> 0+    (Em a)         -> floor $ dpi * a * (11/64) :: Integer+  where+    dpi = fromIntegral $ writerDpi opts+ -- | Convert a Dimension to a String denoting its equivalent in inches, for example "2.00000". -- Note: Dimensions in percentages are converted to the empty string. showInInch :: WriterOptions -> Dimension -> String@@ -170,14 +208,8 @@ -- | Convert a Dimension to a String denoting its equivalent in pixels, for example "600". -- Note: Dimensions in percentages are converted to the empty string. showInPixel :: WriterOptions -> Dimension -> String-showInPixel opts dim =-  case dim of-    (Pixel a)      -> show a-    (Centimeter a) -> show (floor $ dpi * a * 0.3937007874 :: Int)-    (Inch a)       -> show (floor $ dpi * a :: Int)-    (Percent _)    -> ""-  where-    dpi = fromIntegral $ writerDpi opts+showInPixel _ (Percent _) = ""+showInPixel opts dim = show $ inPixel opts dim  -- | Maybe split a string into a leading number and trailing unit, e.g. "3cm" to Just (3.0, "cm") numUnit :: String -> Maybe (Double, String)@@ -187,6 +219,16 @@         Just n  -> Just (n, unit)         Nothing -> Nothing +-- | Scale a dimension by a factor.+scaleDimension :: Double -> Dimension -> Dimension+scaleDimension factor dim =+  case dim of+        Pixel x      -> Pixel (round $ factor * fromIntegral x)+        Centimeter x -> Centimeter (factor * x)+        Inch x       -> Inch (factor * x)+        Percent x    -> Percent (factor * x)+        Em x         -> Em (factor * x)+ -- | Read a Dimension from an Attr attribute. -- `dimension Width attr` might return `Just (Pixel 3)` or for example `Just (Centimeter 2.0)`, etc. dimension :: Direction -> Attr -> Maybe Dimension@@ -195,13 +237,11 @@     Width  -> extractDim "width"     Height -> extractDim "height"   where-    extractDim key =-      case lookup key kvs of-        Just str ->-          case numUnit str of-            Just (num, unit) -> toDim num unit-            Nothing -> Nothing-        Nothing  -> Nothing+    extractDim key = lookup key kvs >>= lengthToDim++lengthToDim :: String -> Maybe Dimension+lengthToDim s = numUnit s >>= uncurry toDim+  where     toDim a "cm"   = Just $ Centimeter a     toDim a "mm"   = Just $ Centimeter (a / 10)     toDim a "in"   = Just $ Inch a@@ -209,6 +249,9 @@     toDim a "%"    = Just $ Percent a     toDim a "px"   = Just $ Pixel (floor a::Integer)     toDim a ""     = Just $ Pixel (floor a::Integer)+    toDim a "pt"   = Just $ Inch (a / 72)+    toDim a "pc"   = Just $ Inch (a / 6)+    toDim a "em"   = Just $ Em a     toDim _ _      = Nothing  epsSize :: ByteString -> Maybe ImageSize@@ -218,7 +261,7 @@   case ls' of        []    -> mzero        (x:_) -> case B.words x of-                     (_:_:_:ux:uy:[]) -> do+                     [_, _, _, ux, uy] -> do                         ux' <- safeRead $ B.unpack ux                         uy' <- safeRead $ B.unpack uy                         return ImageSize{@@ -236,27 +279,26 @@   let (i, rest') = B.splitAt 4 $ B.drop 4 rest   guard $ i == "MHDR" || i == "IHDR"   let (sizes, rest'') = B.splitAt 8 rest'-  (x,y) <- case map fromIntegral $ unpack $ sizes of+  (x,y) <- case map fromIntegral $unpack sizes of                 ([w1,w2,w3,w4,h1,h2,h3,h4] :: [Integer]) -> return-                    ((shift w1 24) + (shift w2 16) + (shift w3 8) + w4,-                     (shift h1 24) + (shift h2 16) + (shift h3 8) + h4)-                _ -> (hush . Left) "PNG parse error"+                    (shift w1 24 + shift w2 16 + shift w3 8 + w4,+                     shift h1 24 + shift h2 16 + shift h3 8 + h4)+                _ -> Nothing -- "PNG parse error"   let (dpix, dpiy) = findpHYs rest''-  return $ ImageSize { pxX  = x, pxY = y, dpiX = dpix, dpiY = dpiy }+  return ImageSize { pxX  = x, pxY = y, dpiX = dpix, dpiY = dpiy }  findpHYs :: ByteString -> (Integer, Integer)-findpHYs x =-  if B.null x || "IDAT" `B.isPrefixOf` x-     then (72,72) -- default, no pHYs-     else if "pHYs" `B.isPrefixOf` x-          then let [x1,x2,x3,x4,y1,y2,y3,y4,u] = map fromIntegral-                                               $ unpack $ B.take 9 $ B.drop 4 x-                   factor = if u == 1 -- dots per meter-                               then \z -> z * 254 `div` 10000-                               else const 72-               in  ( factor $ (shift x1 24) + (shift x2 16) + (shift x3 8) + x4,-                     factor $ (shift y1 24) + (shift y2 16) + (shift y3 8) + y4 )-          else findpHYs $ B.drop 1 x  -- read another byte+findpHYs x+  | B.null x || "IDAT" `B.isPrefixOf` x = (72,72)+  | "pHYs" `B.isPrefixOf` x =+    let [x1,x2,x3,x4,y1,y2,y3,y4,u] =+          map fromIntegral $ unpack $ B.take 9 $ B.drop 4 x+        factor = if u == 1 -- dots per meter+                    then \z -> z * 254 `div` 10000+                    else const 72+    in  ( factor $ (shift x1 24) + (shift x2 16) + (shift x3 8) + x4,+          factor $ (shift y1 24) + (shift y2 16) + (shift y3 8) + y4 )+  | otherwise = findpHYs $ B.drop 1 x  -- read another byte  gifSize :: ByteString -> Maybe ImageSize gifSize img = do@@ -269,8 +311,24 @@                           dpiX = 72,                           dpiY = 72                           }-       _             -> (hush . Left) "GIF parse error"+       _             -> Nothing -- "GIF parse error" +svgSize :: WriterOptions -> ByteString -> Maybe ImageSize+svgSize opts img = do+  doc <- Xml.parseXMLDoc $ UTF8.toString img+  let dpi = fromIntegral $ writerDpi opts+  let dirToInt dir = do+        dim <- Xml.findAttrBy (== Xml.QName dir Nothing Nothing) doc >>= lengthToDim+        return $ inPixel opts dim+  w <- dirToInt "width"+  h <- dirToInt "height"+  return ImageSize {+    pxX  = w+  , pxY  = h+  , dpiX = dpi+  , dpiY = dpi+  }+ jpegSize :: ByteString -> Either String ImageSize jpegSize img =   let (hdr, rest) = B.splitAt 4 img@@ -284,16 +342,16 @@ jfifSize :: ByteString -> Either String ImageSize jfifSize rest =   let [dpiDensity,dpix1,dpix2,dpiy1,dpiy2] = map fromIntegral-                                           $ unpack $ B.take 5 $ B.drop 9 $ rest+                                           $ unpack $ B.take 5 $B.drop 9 rest       factor = case dpiDensity of                     1 -> id-                    2 -> \x -> (x * 254 `div` 10)+                    2 -> \x -> x * 254 `div` 10                     _ -> const 72       dpix = factor (shift dpix1 8 + dpix2)       dpiy = factor (shift dpiy1 8 + dpiy2)   in case findJfifSize rest of        Left msg    -> Left msg-       Right (w,h) -> Right $ ImageSize { pxX = w+       Right (w,h) ->Right ImageSize { pxX = w                                         , pxY = h                                         , dpiX = dpix                                         , dpiY = dpiy }@@ -327,7 +385,7 @@   exifSize :: ByteString -> Either String ImageSize-exifSize bs = runGet' header $ bl+exifSize bs =runGet' header bl   where bl = BL.fromChunks [bs]         header = runExceptT $ exifHeader bl -- NOTE:  It would be nicer to do@@ -397,14 +455,13 @@                                Left msg -> throwError msg                                Right x  -> return x        return (tag, payload)-  entries <- sequence $ replicate (fromIntegral numentries) ifdEntry+  entries <- replicateM (fromIntegral numentries) ifdEntry   subentries <- case lookup ExifOffset entries of                       Just (UnsignedLong offset') -> do                         pos <- lift bytesRead                         lift $ skip (fromIntegral offset' - (fromIntegral pos - 8))                         numsubentries <- lift getWord16-                        sequence $-                           replicate (fromIntegral numsubentries) ifdEntry+                        replicateM (fromIntegral numsubentries) ifdEntry                       _ -> return []   let allentries = entries ++ subentries   (wdth, hght) <- case (lookup ExifImageWidth allentries,@@ -415,13 +472,13 @@                             -- we return a default width and height when                             -- the exif header doesn't contain these   let resfactor = case lookup ResolutionUnit allentries of-                        Just (UnsignedShort 1) -> (100 / 254)+                        Just (UnsignedShort 1) -> 100 / 254                         _ -> 1   let xres = maybe 72 (\(UnsignedRational x) -> floor $ x * resfactor)              $ lookup XResolution allentries   let yres = maybe 72 (\(UnsignedRational x) -> floor $ x * resfactor)              $ lookup YResolution allentries-  return $ ImageSize{+  return ImageSize{                     pxX  = wdth                   , pxY  = hght                   , dpiX = xres
+ src/Text/Pandoc/Logging.hs view
@@ -0,0 +1,339 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric      #-}+{-# LANGUAGE OverloadedStrings  #-}+{-+Copyright (C) 2016-17 John MacFarlane <jgm@berkeley.edu>++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation; either version 2 of the License, or+(at your option) any later version.++This program is distributed in the hope that it will be useful,+but WITHOUT ANY WARRANTY; without even the implied warranty of+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+GNU General Public License for more details.++You should have received a copy of the GNU General Public License+along with this program; if not, write to the Free Software+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+-}+{- |+   Module      : Text.Pandoc.Logging+   Copyright   : Copyright (C) 2006-2017 John MacFarlane+   License     : GNU GPL, version 2 or above++   Maintainer  : John MacFarlane <jgm@berkeley.edu>+   Stability   : alpha+   Portability : portable++This module provides data types and functions for warnings+and info messages.++-}+module Text.Pandoc.Logging (+    Verbosity(..)+  , LogMessage(..)+  , encodeLogMessages+  , showLogMessage+  , messageVerbosity+  ) where++import Control.Monad (mzero)+import Data.Aeson+import Data.Aeson.Encode.Pretty (Config (..), defConfig, encodePretty',+                                 keyOrder)+import qualified Data.ByteString.Lazy as BL+import Data.Data (Data, toConstr)+import qualified Data.Text as Text+import Data.Typeable (Typeable)+import GHC.Generics (Generic)+import Text.Pandoc.Definition+import Text.Parsec.Pos++-- | Verbosity level.+data Verbosity = ERROR | WARNING | INFO+     deriving (Show, Read, Eq, Data, Enum, Ord, Bounded, Typeable, Generic)++instance ToJSON Verbosity where+  toJSON x = toJSON (show x)+instance FromJSON Verbosity where+  parseJSON (String t) =+    case t of+         "ERROR"   -> return ERROR+         "WARNING" -> return WARNING+         "INFO"    -> return INFO+         _         -> mzero+  parseJSON _      =  mzero++data LogMessage =+    SkippedContent String SourcePos+  | CouldNotParseYamlMetadata String SourcePos+  | DuplicateLinkReference String SourcePos+  | DuplicateNoteReference String SourcePos+  | NoteDefinedButNotUsed String SourcePos+  | DuplicateIdentifier String SourcePos+  | ReferenceNotFound String SourcePos+  | CircularReference String SourcePos+  | UndefinedToggle String SourcePos+  | ParsingUnescaped String SourcePos+  | CouldNotLoadIncludeFile String SourcePos+  | MacroAlreadyDefined String SourcePos+  | InlineNotRendered Inline+  | BlockNotRendered Block+  | DocxParserWarning String+  | CouldNotFetchResource String String+  | CouldNotDetermineImageSize String String+  | CouldNotConvertImage String String+  | CouldNotDetermineMimeType String+  | CouldNotConvertTeXMath String String+  | CouldNotParseCSS String+  | Fetching String+  | Extracting String+  | NoTitleElement String+  | NoLangSpecified+  | InvalidLang String+  | CouldNotHighlight String+  | MissingCharacter String+  | Deprecated String String+  | NoTranslation String+  | CouldNotLoadTranslations String String+  deriving (Show, Eq, Data, Ord, Typeable, Generic)++instance ToJSON LogMessage where+  toJSON x = object $+    "verbosity" .= toJSON (messageVerbosity x) :+    "type" .= toJSON (show $ toConstr x) :+    case x of+      SkippedContent s pos ->+           ["contents" .= Text.pack s,+            "source" .= Text.pack (sourceName pos),+            "line" .= sourceLine pos,+            "column" .= sourceColumn pos]+      CouldNotParseYamlMetadata s pos ->+           ["message" .= Text.pack s,+            "source" .= Text.pack (sourceName pos),+            "line" .= toJSON (sourceLine pos),+            "column" .= toJSON (sourceColumn pos)]+      DuplicateLinkReference s pos ->+           ["contents" .= Text.pack s,+            "source" .= Text.pack (sourceName pos),+            "line" .= toJSON (sourceLine pos),+            "column" .= toJSON (sourceColumn pos)]+      NoteDefinedButNotUsed s pos ->+           ["key" .= Text.pack s,+            "source" .= Text.pack (sourceName pos),+            "line" .= toJSON (sourceLine pos),+            "column" .= toJSON (sourceColumn pos)]+      DuplicateNoteReference s pos ->+           ["contents" .= Text.pack s,+            "source" .= Text.pack (sourceName pos),+            "line" .= toJSON (sourceLine pos),+            "column" .= toJSON (sourceColumn pos)]+      DuplicateIdentifier s pos ->+           ["contents" .= Text.pack s,+            "source" .= Text.pack (sourceName pos),+            "line" .= toJSON (sourceLine pos),+            "column" .= toJSON (sourceColumn pos)]+      ReferenceNotFound s pos ->+           ["contents" .= Text.pack s,+            "source" .= Text.pack (sourceName pos),+            "line" .= toJSON (sourceLine pos),+            "column" .= toJSON (sourceColumn pos)]+      CircularReference s pos ->+           ["contents" .= Text.pack s,+            "source" .= Text.pack (sourceName pos),+            "line" .= toJSON (sourceLine pos),+            "column" .= toJSON (sourceColumn pos)]+      UndefinedToggle s pos ->+           ["contents" .= Text.pack s,+            "source" .= Text.pack (sourceName pos),+            "line" .= toJSON (sourceLine pos),+            "column" .= toJSON (sourceColumn pos)]+      ParsingUnescaped s pos ->+           ["contents" .= Text.pack s,+            "source" .= Text.pack (sourceName pos),+            "line" .= toJSON (sourceLine pos),+            "column" .= toJSON (sourceColumn pos)]+      CouldNotLoadIncludeFile fp pos ->+           ["path" .= Text.pack fp,+            "source" .= Text.pack (sourceName pos),+            "line" .= toJSON (sourceLine pos),+            "column" .= toJSON (sourceColumn pos)]+      MacroAlreadyDefined name pos ->+           ["name" .= Text.pack name,+            "source" .= Text.pack (sourceName pos),+            "line" .= toJSON (sourceLine pos),+            "column" .= toJSON (sourceColumn pos)]+      InlineNotRendered il ->+           ["contents" .= toJSON il]+      BlockNotRendered bl ->+           ["contents" .= toJSON bl]+      DocxParserWarning s ->+           ["contents" .= Text.pack s]+      CouldNotFetchResource fp s ->+           ["path" .= Text.pack fp,+            "message" .= Text.pack s]+      CouldNotDetermineImageSize fp s ->+           ["path" .= Text.pack fp,+            "message" .= Text.pack s]+      CouldNotConvertImage fp s ->+           ["path" .= Text.pack fp,+            "message" .= Text.pack s]+      CouldNotDetermineMimeType fp ->+           ["path" .= Text.pack fp]+      CouldNotConvertTeXMath s msg ->+           ["contents" .= Text.pack s,+            "message" .= Text.pack msg]+      CouldNotParseCSS msg ->+           ["message" .= Text.pack msg]+      Fetching fp ->+           ["path" .= Text.pack fp]+      Extracting fp ->+           ["path" .= Text.pack fp]+      NoTitleElement fallback ->+           ["fallback" .= Text.pack fallback]+      NoLangSpecified -> []+      InvalidLang s ->+           ["lang" .= Text.pack s]+      CouldNotHighlight msg ->+           ["message" .= Text.pack msg]+      MissingCharacter msg ->+           ["message" .= Text.pack msg]+      Deprecated thing msg ->+           ["thing" .= Text.pack thing,+            "message" .= Text.pack msg]+      NoTranslation term ->+           ["term" .= Text.pack term]+      CouldNotLoadTranslations lang msg ->+           ["lang" .= Text.pack lang,+            "message" .= Text.pack msg]+++showPos :: SourcePos -> String+showPos pos = sn ++ "line " +++     show (sourceLine pos) ++ " column " ++ show (sourceColumn pos)+  where sn = if sourceName pos == "source" || sourceName pos == ""+                then ""+                else sourceName pos ++ " "++encodeLogMessages :: [LogMessage] -> BL.ByteString+encodeLogMessages ms =+  encodePretty' defConfig{ confCompare =+      keyOrder [ "type", "verbosity", "contents", "message", "path",+                 "source", "line", "column" ] } ms++showLogMessage :: LogMessage -> String+showLogMessage msg =+  case msg of+       SkippedContent s pos ->+         "Skipped '" ++ s ++ "' at " ++ showPos pos+       CouldNotParseYamlMetadata s pos ->+         "Could not parse YAML metadata at " ++ showPos pos +++           if null s then "" else (": " ++ s)+       DuplicateLinkReference s pos ->+         "Duplicate link reference '" ++ s ++ "' at " ++ showPos pos+       DuplicateNoteReference s pos ->+         "Duplicate note reference '" ++ s ++ "' at " ++ showPos pos+       NoteDefinedButNotUsed s pos ->+         "Note with key '" ++ s ++ "' defined at " ++ showPos pos +++           " but not used."+       DuplicateIdentifier s pos ->+         "Duplicate identifier '" ++ s ++ "' at " ++ showPos pos+       ReferenceNotFound s pos ->+         "Reference not found for '" ++ s ++ "' at " ++ showPos pos+       CircularReference s pos ->+         "Circular reference '" ++ s ++ "' at " ++ showPos pos+       UndefinedToggle s pos ->+         "Undefined toggle '" ++ s ++ "' at " ++ showPos pos+       ParsingUnescaped s pos ->+         "Parsing unescaped '" ++ s ++ "' at " ++ showPos pos+       CouldNotLoadIncludeFile fp pos ->+         "Could not load include file '" ++ fp ++ "' at " ++ showPos pos+       MacroAlreadyDefined name pos ->+         "Macro '" ++ name ++ "' already defined, ignoring at " ++ showPos pos+       InlineNotRendered il ->+         "Not rendering " ++ show il+       BlockNotRendered bl ->+         "Not rendering " ++ show bl+       DocxParserWarning s ->+         "Docx parser warning: " ++ s+       CouldNotFetchResource fp s ->+         "Could not fetch resource '" ++ fp ++ "'" +++           if null s then "" else (": " ++ s)+       CouldNotDetermineImageSize fp s ->+         "Could not determine image size for '" ++ fp ++ "'" +++           if null s then "" else (": " ++ s)+       CouldNotConvertImage fp s ->+         "Could not convert image '" ++ fp ++ "'" +++           if null s then "" else (": " ++ s)+       CouldNotDetermineMimeType fp ->+         "Could not determine mime type for '" ++ fp ++ "'"+       CouldNotConvertTeXMath s m ->+         "Could not convert TeX math '" ++ s ++ "', rendering as TeX" +++           if null m then "" else (':':'\n':m)+       CouldNotParseCSS m ->+         "Could not parse CSS" ++ if null m then "" else (':':'\n':m)+       Fetching fp ->+         "Fetching " ++ fp ++ "..."+       Extracting fp ->+         "Extracting " ++ fp ++ "..."+       NoTitleElement fallback ->+         "This document format requires a nonempty <title> element.\n" +++         "Please specify either 'title' or 'pagetitle' in the metadata.\n" +++         "Falling back to '" ++ fallback ++ "'"+       NoLangSpecified ->+         "No value for 'lang' was specified in the metadata.\n" +++         "It is recommended that lang be specified for this format."+       InvalidLang s ->+         "Invalid 'lang' value '" ++ s ++ "'.\n" +++         "Use an IETF language tag like 'en-US'."+       CouldNotHighlight m ->+         "Could not highlight code block:\n" ++ m+       MissingCharacter m ->+         "Missing character: " ++ m+       Deprecated t m ->+         "Deprecated: " ++ t +++         if null m+            then ""+            else ". " ++ m+       NoTranslation t ->+         "The term " ++ t ++ " has no translation defined."+       CouldNotLoadTranslations lang m ->+         "Could not load translations for " ++ lang +++           if null m then "" else ('\n':m)++messageVerbosity:: LogMessage -> Verbosity+messageVerbosity msg =+  case msg of+       SkippedContent{}             -> INFO+       CouldNotParseYamlMetadata{}  -> WARNING+       DuplicateLinkReference{}     -> WARNING+       DuplicateNoteReference{}     -> WARNING+       NoteDefinedButNotUsed{}      -> WARNING+       DuplicateIdentifier{}        -> WARNING+       ReferenceNotFound{}          -> WARNING+       CircularReference{}          -> WARNING+       UndefinedToggle{}            -> WARNING+       CouldNotLoadIncludeFile{}    -> WARNING+       MacroAlreadyDefined{}        -> WARNING+       ParsingUnescaped{}           -> INFO+       InlineNotRendered{}          -> INFO+       BlockNotRendered{}           -> INFO+       DocxParserWarning{}          -> INFO+       CouldNotFetchResource{}      -> WARNING+       CouldNotDetermineImageSize{} -> WARNING+       CouldNotConvertImage{}       -> WARNING+       CouldNotDetermineMimeType{}  -> WARNING+       CouldNotConvertTeXMath{}     -> WARNING+       CouldNotParseCSS{}           -> WARNING+       Fetching{}                   -> INFO+       Extracting{}                 -> INFO+       NoTitleElement{}             -> WARNING+       NoLangSpecified              -> INFO+       InvalidLang{}                -> WARNING+       CouldNotHighlight{}          -> WARNING+       MissingCharacter{}           -> WARNING+       Deprecated{}                 -> WARNING+       NoTranslation{}              -> WARNING+       CouldNotLoadTranslations{}   -> WARNING
+ src/Text/Pandoc/Lua.hs view
@@ -0,0 +1,250 @@+{-# LANGUAGE CPP                   #-}+{-# LANGUAGE FlexibleContexts      #-}+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables   #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+{-+Copyright © 2017 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation; either version 2 of the License, or+(at your option) any later version.++This program is distributed in the hope that it will be useful,+but WITHOUT ANY WARRANTY; without even the implied warranty of+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+GNU General Public License for more details.++You should have received a copy of the GNU General Public License+along with this program; if not, write to the Free Software+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+-}+{- |+   Module      : Text.Pandoc.Lua+   Copyright   : Copyright © 2017 Albert Krewinkel+   License     : GNU GPL, version 2 or above++   Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>+   Stability   : alpha++Pandoc lua utils.+-}+module Text.Pandoc.Lua (LuaException (..), pushPandocModule, runLuaFilter) where++import Control.Monad (mplus, unless, when, (>=>))+import Control.Monad.Identity (Identity)+import Control.Monad.Trans (MonadIO (..))+import Data.Data (Data, DataType, dataTypeConstrs, dataTypeName, dataTypeOf,+                  showConstr, toConstr, tyconUQname)+import Data.Foldable (foldrM)+import Data.IORef (IORef, newIORef, readIORef)+import Data.Map (Map)+import Data.Maybe (isJust)+import Foreign.Lua (FromLuaStack (peek), Lua, LuaException (..), StackIndex,+                    Status (OK), ToLuaStack (push))+import Text.Pandoc.Class (CommonState, PandocIO, getCommonState, getMediaBag,+                          setMediaBag)+import Text.Pandoc.Definition+import Text.Pandoc.Lua.PandocModule (pushMediaBagModule, pushPandocModule)+import Text.Pandoc.MediaBag (MediaBag)+import Text.Pandoc.Walk (walkM)++import qualified Data.Map as Map+import qualified Foreign.Lua as Lua++runLuaFilter :: Maybe FilePath -> FilePath -> String+             -> Pandoc -> PandocIO (Either LuaException Pandoc)+runLuaFilter datadir filterPath format pd = do+  commonState <- getCommonState+  mediaBag <- getMediaBag+  mediaBagRef <- liftIO (newIORef mediaBag)+  res <- liftIO . Lua.runLuaEither $+         runLuaFilter' commonState datadir filterPath format mediaBagRef pd+  newMediaBag <- liftIO (readIORef mediaBagRef)+  setMediaBag newMediaBag+  return res++runLuaFilter' :: CommonState+              -> Maybe FilePath -> FilePath -> String -> IORef MediaBag+              -> Pandoc -> Lua Pandoc+runLuaFilter' commonState datadir filterPath format mbRef pd = do+  Lua.openlibs+  -- store module in global "pandoc"+  pushPandocModule datadir+  Lua.setglobal "pandoc"+  addMediaBagModule+  registerFormat+  top <- Lua.gettop+  stat <- Lua.dofile filterPath+  if stat /= OK+    then do+      luaErrMsg <- peek (-1) <* Lua.pop 1+      Lua.throwLuaError luaErrMsg+    else do+      newtop <- Lua.gettop+      -- Use the implicitly defined global filter if nothing was returned+      when (newtop - top < 1) pushGlobalFilter+      luaFilters <- peek (-1)+      runAll luaFilters pd+ where+  addMediaBagModule = do+    Lua.getglobal "pandoc"+    push "mediabag"+    pushMediaBagModule commonState mbRef+    Lua.rawset (-3)+  registerFormat = do+    push format+    Lua.setglobal "FORMAT"+++pushGlobalFilter :: Lua ()+pushGlobalFilter = do+  Lua.newtable+  Lua.getglobal' "pandoc.global_filter"+  Lua.call 0 1+  Lua.rawseti (-2) 1++runAll :: [LuaFilter] -> Pandoc -> Lua Pandoc+runAll = foldr ((>=>) . walkMWithLuaFilter) return++walkMWithLuaFilter :: LuaFilter -> Pandoc -> Lua Pandoc+walkMWithLuaFilter (LuaFilter fnMap) =+  walkInlines >=> walkBlocks >=> walkMeta >=> walkPandoc+ where+    walkInlines :: Pandoc -> Lua Pandoc+    walkInlines =+      if hasOneOf inlineFilterNames+      then walkM (mconcatMapM (tryFilter fnMap :: Inline -> Lua [Inline]))+      else return++    walkBlocks :: Pandoc -> Lua Pandoc+    walkBlocks =+      if hasOneOf blockFilterNames+      then walkM (mconcatMapM (tryFilter fnMap :: Block -> Lua [Block]))+      else return++    walkMeta :: Pandoc -> Lua Pandoc+    walkMeta =+      case Map.lookup "Meta" fnMap of+        Just fn -> walkM (\(Pandoc meta blocks) -> do+                             meta' <- runFilterFunction fn meta *> singleElement meta+                             return $ Pandoc meta' blocks)+        Nothing -> return++    walkPandoc :: Pandoc -> Lua Pandoc+    walkPandoc =+      case foldl mplus Nothing (map (`Map.lookup` fnMap) pandocFilterNames) of+        Just fn -> \x -> runFilterFunction fn x *> singleElement x+        Nothing -> return++    mconcatMapM f = fmap mconcat . mapM f+    hasOneOf = any (\k -> isJust (Map.lookup k fnMap))++constructorsFor :: DataType -> [String]+constructorsFor x = map show (dataTypeConstrs x)++inlineFilterNames :: [String]+inlineFilterNames = "Inline" : constructorsFor (dataTypeOf (Str []))++blockFilterNames :: [String]+blockFilterNames = "Block" : constructorsFor (dataTypeOf (Para []))++metaFilterName :: String+metaFilterName = "Meta"++pandocFilterNames :: [String]+pandocFilterNames = ["Pandoc", "Doc"]++type FunctionMap = Map String LuaFilterFunction+newtype LuaFilter = LuaFilter FunctionMap+newtype LuaFilterFunction = LuaFilterFunction { functionIndex :: Int }++-- | Try running a filter for the given element+tryFilter :: (Data a, FromLuaStack a, ToLuaStack a)+          => FunctionMap -> a -> Lua [a]+tryFilter fnMap x =+  let filterFnName = showConstr (toConstr x)+      catchAllName = tyconUQname $ dataTypeName (dataTypeOf x)+  in+  case Map.lookup filterFnName fnMap `mplus` Map.lookup catchAllName fnMap of+    Just fn -> runFilterFunction fn x *> elementOrList x+    Nothing -> return [x]++instance FromLuaStack LuaFilter where+  peek idx =+    let constrs = metaFilterName : pandocFilterNames+                  ++ blockFilterNames+                  ++ inlineFilterNames+        fn c acc = do+          Lua.getfield idx c+          filterFn <- Lua.tryLua (peek (-1))+          Lua.pop 1+          return $ case filterFn of+            Left _  -> acc+            Right f -> (c, f) : acc+    in LuaFilter . Map.fromList <$> foldrM fn [] constrs++-- | Push a value to the stack via a lua filter function. The filter function is+-- called with given element as argument and is expected to return an element.+-- Alternatively, the function can return nothing or nil, in which case the+-- element is left unchanged.+runFilterFunction :: ToLuaStack a => LuaFilterFunction -> a -> Lua ()+runFilterFunction lf x = do+  pushFilterFunction lf+  push x+  z <- Lua.pcall 1 1 Nothing+  when (z /= OK) $ do+    let addPrefix = ("Error while running filter function: " ++)+    Lua.throwTopMessageAsError' addPrefix++elementOrList :: FromLuaStack a => a -> Lua [a]+elementOrList x = do+  let topOfStack = Lua.StackIndex (-1)+  elementUnchanged <- Lua.isnil topOfStack+  if elementUnchanged+    then [x] <$ Lua.pop 1+    else do+       mbres <- Lua.peekEither topOfStack+       case mbres of+         Right res -> [res] <$ Lua.pop 1+         Left _    -> Lua.toList topOfStack <* Lua.pop 1++singleElement :: FromLuaStack a => a -> Lua a+singleElement x = do+  elementUnchanged <- Lua.isnil (-1)+  if elementUnchanged+    then x <$ Lua.pop 1+    else do+    mbres <- Lua.peekEither (-1)+    case mbres of+      Right res -> res <$ Lua.pop 1+      Left err  -> do+        Lua.pop 1+        Lua.throwLuaError $+          "Error while trying to get a filter's return " +++          "value from lua stack.\n" ++ err++-- | Push the filter function to the top of the stack.+pushFilterFunction :: LuaFilterFunction -> Lua ()+pushFilterFunction lf =+  -- The function is stored in a lua registry table, retrieve it from there.+  Lua.rawgeti Lua.registryindex (functionIndex lf)++registerFilterFunction :: StackIndex -> Lua LuaFilterFunction+registerFilterFunction idx = do+  isFn <- Lua.isfunction idx+  unless isFn . Lua.throwLuaError $ "Not a function at index " ++ show idx+  Lua.pushvalue idx+  refIdx <- Lua.ref Lua.registryindex+  return $ LuaFilterFunction refIdx++instance (FromLuaStack a) => FromLuaStack (Identity a) where+  peek = fmap return . peek++instance ToLuaStack LuaFilterFunction where+  push = pushFilterFunction++instance FromLuaStack LuaFilterFunction where+  peek = registerFilterFunction
+ src/Text/Pandoc/Lua/PandocModule.hs view
@@ -0,0 +1,185 @@+{-+Copyright © 2017 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation; either version 2 of the License, or+(at your option) any later version.++This program is distributed in the hope that it will be useful,+but WITHOUT ANY WARRANTY; without even the implied warranty of+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+GNU General Public License for more details.++You should have received a copy of the GNU General Public License+along with this program; if not, write to the Free Software+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+-}+{-# LANGUAGE CPP #-}+{- |+   Module      : Text.Pandoc.Lua.PandocModule+   Copyright   : Copyright © 2017 Albert Krewinkel+   License     : GNU GPL, version 2 or above++   Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>+   Stability   : alpha++Pandoc module for lua.+-}+module Text.Pandoc.Lua.PandocModule+  ( pushPandocModule+  , pushMediaBagModule+  ) where++import Control.Monad (unless, zipWithM_)+import Data.ByteString.Char8 (unpack)+import Data.Default (Default (..))+import Data.Digest.Pure.SHA (sha1, showDigest)+import Data.IORef+import Data.Maybe (fromMaybe)+import Data.Text (pack)+import Foreign.Lua (FromLuaStack, Lua, NumResults, liftIO)+import Foreign.Lua.FunctionCalling (ToHaskellFunction)+import System.Exit (ExitCode (..))+import Text.Pandoc.Class (CommonState (..), fetchItem, putCommonState,+                          readDataFile, runIO, runIOorExplode, setMediaBag,+                          setUserDataDir)+import Text.Pandoc.Lua.StackInstances ()+import Text.Pandoc.MIME (MimeType)+import Text.Pandoc.Options (ReaderOptions (readerExtensions))+import Text.Pandoc.Process (pipeProcess)+import Text.Pandoc.Readers (Reader (..), getReader)++import qualified Data.ByteString.Lazy as BL+import qualified Foreign.Lua as Lua+import qualified Text.Pandoc.MediaBag as MB++-- | Push the "pandoc" on the lua stack.+pushPandocModule :: Maybe FilePath -> Lua ()+pushPandocModule datadir = do+  script <- liftIO (pandocModuleScript datadir)+  status <- Lua.loadstring script+  unless (status /= Lua.OK) $ Lua.call 0 1+  addFunction "_pipe" pipeFn+  addFunction "_read" readDoc+  addFunction "sha1" sha1HashFn++-- | Get the string representation of the pandoc module+pandocModuleScript :: Maybe FilePath -> IO String+pandocModuleScript datadir = unpack <$>+  runIOorExplode (setUserDataDir datadir >> readDataFile "pandoc.lua")++readDoc :: String -> String -> Lua NumResults+readDoc formatSpec content = do+  case getReader formatSpec of+    Left  s      -> Lua.push s -- Unknown reader+    Right (reader, es) ->+      case reader of+        TextReader r -> do+          res <- liftIO $ runIO $ r def{ readerExtensions = es } (pack content)+          case res of+            Left s   -> Lua.push $ show s -- error while reading+            Right pd -> Lua.push pd       -- success, push Pandoc+        _  -> Lua.push "Only string formats are supported at the moment."+  return 1++--+-- MediaBag submodule+--+pushMediaBagModule :: CommonState -> IORef MB.MediaBag -> Lua ()+pushMediaBagModule commonState mediaBagRef = do+  Lua.newtable+  addFunction "insert" (insertMediaFn mediaBagRef)+  addFunction "lookup" (lookupMediaFn mediaBagRef)+  addFunction "list" (mediaDirectoryFn mediaBagRef)+  addFunction "fetch" (fetch commonState mediaBagRef)+  return ()++addFunction :: ToHaskellFunction a => String -> a -> Lua ()+addFunction name fn = do+  Lua.push name+  Lua.pushHaskellFunction fn+  Lua.rawset (-3)++sha1HashFn :: BL.ByteString+           -> Lua NumResults+sha1HashFn contents = do+  Lua.push $ showDigest (sha1 contents)+  return 1++pipeFn :: String+       -> [String]+       -> BL.ByteString+       -> Lua NumResults+pipeFn command args input = do+  (ec, output) <- liftIO $ pipeProcess Nothing command args input+  Lua.push $ case ec of+                  ExitSuccess   -> 0+                  ExitFailure n -> n+  Lua.push output+  return 2++insertMediaFn :: IORef MB.MediaBag+              -> FilePath+              -> OrNil MimeType+              -> BL.ByteString+              -> Lua NumResults+insertMediaFn mbRef fp nilOrMime contents = do+  liftIO . modifyIORef' mbRef $+    MB.insertMedia fp (toMaybe nilOrMime) contents+  return 0++lookupMediaFn :: IORef MB.MediaBag+              -> FilePath+              -> Lua NumResults+lookupMediaFn mbRef fp = do+  res <- MB.lookupMedia fp <$> liftIO (readIORef mbRef)+  case res of+    Nothing -> Lua.pushnil *> return 1+    Just (mimeType, contents) -> do+      Lua.push mimeType+      Lua.push contents+      return 2++mediaDirectoryFn :: IORef MB.MediaBag+                 -> Lua NumResults+mediaDirectoryFn mbRef = do+  dirContents <- MB.mediaDirectory <$> liftIO (readIORef mbRef)+  Lua.newtable+  zipWithM_ addEntry [1..] dirContents+  return 1+ where+  addEntry :: Int -> (FilePath, MimeType, Int) -> Lua ()+  addEntry idx (fp, mimeType, contentLength) = do+    Lua.newtable+    Lua.push "path" *> Lua.push fp *> Lua.rawset (-3)+    Lua.push "type" *> Lua.push mimeType *> Lua.rawset (-3)+    Lua.push "length" *> Lua.push contentLength *> Lua.rawset (-3)+    Lua.rawseti (-2) idx++fetch :: CommonState+      -> IORef MB.MediaBag+      -> String+      -> Lua NumResults+fetch commonState mbRef src = do+  mediaBag <- liftIO $ readIORef mbRef+  (bs, mimeType) <- liftIO . runIOorExplode $ do+    putCommonState commonState+    setMediaBag mediaBag+    fetchItem src+  Lua.push $ fromMaybe "" mimeType+  Lua.push bs+  return 2 -- returns 2 values: contents, mimetype++--+-- Helper types and orphan instances+--++newtype OrNil a = OrNil { toMaybe :: Maybe a }++instance FromLuaStack a => FromLuaStack (OrNil a) where+  peek idx = do+    noValue <- Lua.isnil idx+    if noValue+      then return (OrNil Nothing)+      else OrNil . Just <$> Lua.peek idx
+ src/Text/Pandoc/Lua/StackInstances.hs view
@@ -0,0 +1,310 @@+{-+Copyright © 2012-2017 John MacFarlane <jgm@berkeley.edu>+            2017 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation; either version 2 of the License, or+(at your option) any later version.++This program is distributed in the hope that it will be useful,+but WITHOUT ANY WARRANTY; without even the implied warranty of+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+GNU General Public License for more details.++You should have received a copy of the GNU General Public License+along with this program; if not, write to the Free Software+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE LambdaCase        #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+{- |+   Module      : Text.Pandoc.Lua.StackInstances+   Copyright   : © 2012-2017 John MacFarlane+                 © 2017 Albert Krewinkel+   License     : GNU GPL, version 2 or above++   Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>+   Stability   : alpha++StackValue instances for pandoc types.+-}+module Text.Pandoc.Lua.StackInstances () where++import Control.Applicative ((<|>))+import Foreign.Lua (FromLuaStack (peek), Lua, LuaInteger, LuaNumber, StackIndex,+                    ToLuaStack (push), Type (..), throwLuaError, tryLua)+import Text.Pandoc.Definition+import Text.Pandoc.Lua.Util (addValue, adjustIndexBy, getTable,+                             pushViaConstructor)+import Text.Pandoc.Shared (safeRead)++import qualified Foreign.Lua as Lua++instance ToLuaStack Pandoc where+  push (Pandoc meta blocks) = do+    Lua.newtable+    addValue "blocks" blocks+    addValue "meta"   meta++instance FromLuaStack Pandoc where+  peek idx = do+    blocks <- getTable idx "blocks"+    meta   <- getTable idx "meta"+    return $ Pandoc meta blocks++instance ToLuaStack Meta where+  push (Meta mmap) = push mmap+instance FromLuaStack Meta where+  peek idx = Meta <$> peek idx++instance ToLuaStack MetaValue where+  push = pushMetaValue+instance FromLuaStack MetaValue where+  peek = peekMetaValue++instance ToLuaStack Block where+  push = pushBlock++instance FromLuaStack Block where+  peek = peekBlock++-- Inline+instance ToLuaStack Inline where+  push = pushInline++instance FromLuaStack Inline where+  peek = peekInline++-- Citation+instance ToLuaStack Citation where+  push (Citation cid prefix suffix mode noteNum hash) =+    pushViaConstructor "Citation" cid mode prefix suffix noteNum hash++instance FromLuaStack Citation where+  peek idx = do+    id' <- getTable idx "citationId"+    prefix <- getTable idx "citationPrefix"+    suffix <- getTable idx "citationSuffix"+    mode <- getTable idx "citationMode"+    num <- getTable idx "citationNoteNum"+    hash <- getTable idx "citationHash"+    return $ Citation id' prefix suffix mode num hash++instance ToLuaStack Alignment where+  push = push . show+instance FromLuaStack Alignment where+  peek idx = safeRead' =<< peek idx++instance ToLuaStack CitationMode where+  push = push . show+instance FromLuaStack CitationMode where+  peek idx = safeRead' =<< peek idx++instance ToLuaStack Format where+  push (Format f) = push f+instance FromLuaStack Format where+  peek idx = Format <$> peek idx++instance ToLuaStack ListNumberDelim where+  push = push . show+instance FromLuaStack ListNumberDelim where+  peek idx = safeRead' =<< peek idx++instance ToLuaStack ListNumberStyle where+  push = push . show+instance FromLuaStack ListNumberStyle where+  peek idx = safeRead' =<< peek idx++instance ToLuaStack MathType where+  push = push . show+instance FromLuaStack MathType where+  peek idx = safeRead' =<< peek idx++instance ToLuaStack QuoteType where+  push = push . show+instance FromLuaStack QuoteType where+  peek idx = safeRead' =<< peek idx++instance ToLuaStack Double where+  push = push . (realToFrac :: Double -> LuaNumber)+instance FromLuaStack Double where+  peek = fmap (realToFrac :: LuaNumber -> Double) . peek++instance ToLuaStack Int where+  push = push . (fromIntegral :: Int -> LuaInteger)+instance FromLuaStack Int where+  peek = fmap (fromIntegral :: LuaInteger-> Int) . peek++safeRead' :: Read a => String -> Lua a+safeRead' s = case safeRead s of+  Nothing -> throwLuaError ("Could not read: " ++ s)+  Just x  -> return x++-- | Push an meta value element to the top of the lua stack.+pushMetaValue :: MetaValue -> Lua ()+pushMetaValue = \case+  MetaBlocks blcks  -> pushViaConstructor "MetaBlocks" blcks+  MetaBool bool     -> push bool+  MetaInlines inlns -> pushViaConstructor "MetaInlines" inlns+  MetaList metalist -> pushViaConstructor "MetaList" metalist+  MetaMap metamap   -> pushViaConstructor "MetaMap" metamap+  MetaString str    -> push str++-- | Interpret the value at the given stack index as meta value.+peekMetaValue :: StackIndex -> Lua MetaValue+peekMetaValue idx = do+  -- Get the contents of an AST element.+  let elementContent :: FromLuaStack a => Lua a+      elementContent = peek idx+  luatype <- Lua.ltype idx+  case luatype of+    TypeBoolean -> MetaBool <$> peek idx+    TypeString  -> MetaString <$> peek idx+    TypeTable   -> do+      tag <- tryLua $ getTag idx+      case tag of+        Right "MetaBlocks"  -> MetaBlocks  <$> elementContent+        Right "MetaBool"    -> MetaBool    <$> elementContent+        Right "MetaMap"     -> MetaMap     <$> elementContent+        Right "MetaInlines" -> MetaInlines <$> elementContent+        Right "MetaList"    -> MetaList    <$> elementContent+        Right "MetaString"  -> MetaString  <$> elementContent+        Right t             -> throwLuaError ("Unknown meta tag: " ++ t)+        Left _ -> do+          -- no meta value tag given, try to guess.+          len <- Lua.rawlen idx+          if len <= 0+            then MetaMap <$> peek idx+            else  (MetaInlines <$> peek idx)+                  <|> (MetaBlocks <$> peek idx)+                  <|> (MetaList <$> peek idx)+    _        -> throwLuaError "could not get meta value"++-- | Push an block element to the top of the lua stack.+pushBlock :: Block -> Lua ()+pushBlock = \case+  BlockQuote blcks         -> pushViaConstructor "BlockQuote" blcks+  BulletList items         -> pushViaConstructor "BulletList" items+  CodeBlock attr code      -> pushViaConstructor "CodeBlock" code (LuaAttr attr)+  DefinitionList items     -> pushViaConstructor "DefinitionList" items+  Div attr blcks           -> pushViaConstructor "Div" blcks (LuaAttr attr)+  Header lvl attr inlns    -> pushViaConstructor "Header" lvl inlns (LuaAttr attr)+  HorizontalRule           -> pushViaConstructor "HorizontalRule"+  LineBlock blcks          -> pushViaConstructor "LineBlock" blcks+  OrderedList lstAttr list -> pushViaConstructor "OrderedList" list lstAttr+  Null                     -> pushViaConstructor "Null"+  Para blcks               -> pushViaConstructor "Para" blcks+  Plain blcks              -> pushViaConstructor "Plain" blcks+  RawBlock f cs            -> pushViaConstructor "RawBlock" f cs+  Table capt aligns widths headers rows ->+    pushViaConstructor "Table" capt aligns widths headers rows++-- | Return the value at the given index as block if possible.+peekBlock :: StackIndex -> Lua Block+peekBlock idx = do+  tag <- getTag idx+  case tag of+      "BlockQuote"     -> BlockQuote <$> elementContent+      "BulletList"     -> BulletList <$> elementContent+      "CodeBlock"      -> withAttr CodeBlock <$> elementContent+      "DefinitionList" -> DefinitionList <$> elementContent+      "Div"            -> withAttr Div <$> elementContent+      "Header"         -> (\(lvl, LuaAttr attr, lst) -> Header lvl attr lst)+                          <$> elementContent+      "HorizontalRule" -> return HorizontalRule+      "LineBlock"      -> LineBlock <$> elementContent+      "OrderedList"    -> uncurry OrderedList <$> elementContent+      "Null"           -> return Null+      "Para"           -> Para <$> elementContent+      "Plain"          -> Plain <$> elementContent+      "RawBlock"       -> uncurry RawBlock <$> elementContent+      "Table"          -> (\(capt, aligns, widths, headers, body) ->+                                  Table capt aligns widths headers body)+                          <$> elementContent+      _ -> throwLuaError ("Unknown block type: " ++ tag)+ where+   -- Get the contents of an AST element.+   elementContent :: FromLuaStack a => Lua a+   elementContent = getTable idx "c"++-- | Push an inline element to the top of the lua stack.+pushInline :: Inline -> Lua ()+pushInline = \case+  Cite citations lst       -> pushViaConstructor "Cite" lst citations+  Code attr lst            -> pushViaConstructor "Code" lst (LuaAttr attr)+  Emph inlns               -> pushViaConstructor "Emph" inlns+  Image attr alt (src,tit) -> pushViaConstructor "Image" alt src tit (LuaAttr attr)+  LineBreak                -> pushViaConstructor "LineBreak"+  Link attr lst (src,tit)  -> pushViaConstructor "Link" lst src tit (LuaAttr attr)+  Note blcks               -> pushViaConstructor "Note" blcks+  Math mty str             -> pushViaConstructor "Math" mty str+  Quoted qt inlns          -> pushViaConstructor "Quoted" qt inlns+  RawInline f cs           -> pushViaConstructor "RawInline" f cs+  SmallCaps inlns          -> pushViaConstructor "SmallCaps" inlns+  SoftBreak                -> pushViaConstructor "SoftBreak"+  Space                    -> pushViaConstructor "Space"+  Span attr inlns          -> pushViaConstructor "Span" inlns (LuaAttr attr)+  Str str                  -> pushViaConstructor "Str" str+  Strikeout inlns          -> pushViaConstructor "Strikeout" inlns+  Strong inlns             -> pushViaConstructor "Strong" inlns+  Subscript inlns          -> pushViaConstructor "Subscript" inlns+  Superscript inlns        -> pushViaConstructor "Superscript" inlns++-- | Return the value at the given index as inline if possible.+peekInline :: StackIndex -> Lua Inline+peekInline idx = do+  tag <- getTag idx+  case tag of+    "Cite"       -> uncurry Cite <$> elementContent+    "Code"       -> withAttr Code <$> elementContent+    "Emph"       -> Emph <$> elementContent+    "Image"      -> (\(LuaAttr attr, lst, tgt) -> Image attr lst tgt)+                    <$> elementContent+    "Link"       -> (\(LuaAttr attr, lst, tgt) -> Link attr lst tgt)+                    <$> elementContent+    "LineBreak"  -> return LineBreak+    "Note"       -> Note <$> elementContent+    "Math"       -> uncurry Math <$> elementContent+    "Quoted"     -> uncurry Quoted <$> elementContent+    "RawInline"  -> uncurry RawInline <$> elementContent+    "SmallCaps"  -> SmallCaps <$> elementContent+    "SoftBreak"  -> return SoftBreak+    "Space"      -> return Space+    "Span"       -> withAttr Span <$> elementContent+    "Str"        -> Str <$> elementContent+    "Strikeout"  -> Strikeout <$> elementContent+    "Strong"     -> Strong <$> elementContent+    "Subscript"  -> Subscript <$> elementContent+    "Superscript"-> Superscript <$> elementContent+    _ -> throwLuaError ("Unknown inline type: " ++ tag)+ where+   -- Get the contents of an AST element.+   elementContent :: FromLuaStack a => Lua a+   elementContent = getTable idx "c"++getTag :: StackIndex -> Lua String+getTag idx = do+  top <- Lua.gettop+  hasMT <- Lua.getmetatable idx+  push "tag"+  if hasMT then Lua.rawget (-2) else Lua.rawget (idx `adjustIndexBy` 1)+  r <- tryLua (peek (-1))+  Lua.settop top+  case r of+    Left (Lua.LuaException err) -> throwLuaError err+    Right res                   -> return res++withAttr :: (Attr -> a -> b) -> (LuaAttr, a) -> b+withAttr f (attributes, x) = f (fromLuaAttr attributes) x++-- | Wrapper for Attr+newtype LuaAttr = LuaAttr { fromLuaAttr :: Attr }++instance ToLuaStack LuaAttr where+  push (LuaAttr (id', classes, kv)) =+    pushViaConstructor "Attr" id' classes kv++instance FromLuaStack LuaAttr where+  peek idx = LuaAttr <$> peek idx
+ src/Text/Pandoc/Lua/Util.hs view
@@ -0,0 +1,109 @@+{-+Copyright © 2012-2017 John MacFarlane <jgm@berkeley.edu>+            2017 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation; either version 2 of the License, or+(at your option) any later version.++This program is distributed in the hope that it will be useful,+but WITHOUT ANY WARRANTY; without even the implied warranty of+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+GNU General Public License for more details.++You should have received a copy of the GNU General Public License+along with this program; if not, write to the Free Software+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+-}+{-# LANGUAGE FlexibleInstances #-}+{- |+   Module      : Text.Pandoc.Lua.Util+   Copyright   : © 2012–2017 John MacFarlane,+                 © 2017 Albert Krewinkel+   License     : GNU GPL, version 2 or above++   Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>+   Stability   : alpha++Lua utility functions.+-}+module Text.Pandoc.Lua.Util+  ( adjustIndexBy+  , getTable+  , addValue+  , getRawInt+  , setRawInt+  , addRawInt+  , PushViaCall+  , pushViaCall+  , pushViaConstructor+  ) where++import Foreign.Lua (FromLuaStack (..), Lua, NumArgs, StackIndex,+                    ToLuaStack (..), getglobal')+import Foreign.Lua.Api (call, pop, rawget, rawgeti, rawset, rawseti)++-- | Adjust the stack index, assuming that @n@ new elements have been pushed on+-- the stack.+adjustIndexBy :: StackIndex -> StackIndex -> StackIndex+adjustIndexBy idx n =+  if idx < 0+  then idx - n+  else idx++-- | Get value behind key from table at given index.+getTable :: (ToLuaStack a, FromLuaStack b) => StackIndex -> a -> Lua b+getTable idx key = do+  push key+  rawget (idx `adjustIndexBy` 1)+  peek (-1) <* pop 1++-- | Add a key-value pair to the table at the top of the stack+addValue :: (ToLuaStack a, ToLuaStack b) => a -> b -> Lua ()+addValue key value = do+  push key+  push value+  rawset (-3)++-- | Get value behind key from table at given index.+getRawInt :: FromLuaStack a => StackIndex -> Int -> Lua a+getRawInt idx key =+  rawgeti idx key+  *> peek (-1)+  <* pop 1++-- | Set numeric key/value in table at the given index+setRawInt :: ToLuaStack a => StackIndex -> Int -> a -> Lua ()+setRawInt idx key value = do+  push value+  rawseti (idx `adjustIndexBy` 1) key++-- | Set numeric key/value in table at the top of the stack.+addRawInt :: ToLuaStack a => Int -> a -> Lua ()+addRawInt = setRawInt (-1)++-- | Helper class for pushing a single value to the stack via a lua function.+-- See @pushViaCall@.+class PushViaCall a where+  pushViaCall' :: String -> Lua () -> NumArgs -> a++instance PushViaCall (Lua ()) where+  pushViaCall' fn pushArgs num = do+    getglobal' fn+    pushArgs+    call num 1++instance (ToLuaStack a, PushViaCall b) => PushViaCall (a -> b) where+  pushViaCall' fn pushArgs num x =+    pushViaCall' fn (pushArgs *> push x) (num + 1)++-- | Push an value to the stack via a lua function. The lua function is called+-- with all arguments that are passed to this function and is expected to return+-- a single value.+pushViaCall :: PushViaCall a => String -> a+pushViaCall fn = pushViaCall' fn (return ()) 0++-- | Call a pandoc element constructor within lua, passing all given arguments.+pushViaConstructor :: PushViaCall a => String -> a+pushViaConstructor pandocFn = pushViaCall ("pandoc." ++ pandocFn)
src/Text/Pandoc/MIME.hs view
@@ -1,5 +1,5 @@ {--Copyright (C) 2011-2016 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2011-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -18,7 +18,7 @@  {- |    Module      : Text.Pandoc.MIME-   Copyright   : Copyright (C) 2011-2016 John MacFarlane+   Copyright   : Copyright (C) 2011-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -29,11 +29,11 @@ -} module Text.Pandoc.MIME ( MimeType, getMimeType, getMimeTypeDef,                           extensionFromMimeType )where-import System.FilePath-import Data.Char ( toLower )+import Data.Char (toLower) import Data.List (isPrefixOf, isSuffixOf)-import Data.Maybe (fromMaybe) import qualified Data.Map as M+import Data.Maybe (fromMaybe)+import System.FilePath  type MimeType = String @@ -168,6 +168,7 @@            ,("emb","chemical/x-embl-dl-nucleotide")            ,("embl","chemical/x-embl-dl-nucleotide")            ,("emf","image/x-emf")+           ,("emz","application/x-msmetafile")            ,("eml","message/rfc822")            ,("ent","chemical/x-ncbi-asn1-ascii")            ,("eot","application/vnd.ms-fontobject")@@ -243,7 +244,7 @@            ,("jpeg","image/jpeg")            ,("jfif","image/jpeg")            ,("jpg","image/jpeg")-           ,("js","application/x-javascript")+           ,("js","application/javascript")            ,("kar","audio/midi")            ,("key","application/pgp-keys")            ,("kil","application/x-killustrator")@@ -524,4 +525,3 @@            ,("zip","application/zip")            ,("zmt","chemical/x-mopac-input")            ]-
src/Text/Pandoc/MediaBag.hs view
@@ -1,6 +1,7 @@-{-# LANGUAGE GeneralizedNewtypeDeriving, DeriveDataTypeable #-}+{-# LANGUAGE DeriveDataTypeable         #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-} {--Copyright (C) 2014 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2014-2015, 2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -19,7 +20,7 @@  {- |    Module      : Text.Pandoc.MediaBag-   Copyright   : Copyright (C) 2014 John MacFarlane+   Copyright   : Copyright (C) 2014-2015, 2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -34,20 +35,15 @@                      lookupMedia,                      insertMedia,                      mediaDirectory,-                     extractMediaBag                      ) where-import System.FilePath-import qualified System.FilePath.Posix as Posix-import System.Directory (createDirectoryIfMissing)-import qualified Data.Map as M import qualified Data.ByteString.Lazy as BL-import Control.Monad (when)-import Text.Pandoc.MIME (MimeType, getMimeTypeDef)-import qualified Text.Pandoc.UTF8 as UTF8-import Data.Maybe (fromMaybe)-import System.IO (stderr) import Data.Data (Data)+import qualified Data.Map as M+import Data.Maybe (fromMaybe) import Data.Typeable (Typeable)+import System.FilePath+import qualified System.FilePath.Posix as Posix+import Text.Pandoc.MIME (MimeType, getMimeTypeDef)  -- | A container for a collection of binary resources, with names and -- mime types.  Note that a 'MediaBag' is a Monoid, so 'mempty'@@ -70,8 +66,8 @@   MediaBag (M.insert (splitDirectories fp) (mime, contents) mediamap)   where mime = fromMaybe fallback mbMime         fallback = case takeExtension fp of-                        ".gz"   -> getMimeTypeDef $ dropExtension fp-                        _       -> getMimeTypeDef fp+                        ".gz" -> getMimeTypeDef $ dropExtension fp+                        _     -> getMimeTypeDef fp  -- | Lookup a media item in a 'MediaBag', returning mime type and contents. lookupMedia :: FilePath@@ -83,27 +79,5 @@ -- their corresponding mime types and the lengths in bytes of the contents. mediaDirectory :: MediaBag -> [(String, MimeType, Int)] mediaDirectory (MediaBag mediamap) =-  M.foldWithKey (\fp (mime,contents) ->-      (((Posix.joinPath fp), mime, fromIntegral $ BL.length contents):)) [] mediamap---- | Extract contents of MediaBag to a given directory.  Print informational--- messages if 'verbose' is true.-extractMediaBag :: Bool-                -> FilePath-                -> MediaBag-                -> IO ()-extractMediaBag verbose dir (MediaBag mediamap) = do-  sequence_ $ M.foldWithKey-     (\fp (_ ,contents) ->-        ((writeMedia verbose dir (Posix.joinPath fp, contents)):)) [] mediamap--writeMedia :: Bool -> FilePath -> (FilePath, BL.ByteString) -> IO ()-writeMedia verbose dir (subpath, bs) = do-  -- we join and split to convert a/b/c to a\b\c on Windows;-  -- in zip containers all paths use /-  let fullpath = dir </> normalise subpath-  createDirectoryIfMissing True $ takeDirectory fullpath-  when verbose $ UTF8.hPutStrLn stderr $ "pandoc: extracting " ++ fullpath-  BL.writeFile fullpath bs--+  M.foldrWithKey (\fp (mime,contents) ->+      ((Posix.joinPath fp, mime, fromIntegral $ BL.length contents):)) [] mediamap
src/Text/Pandoc/Options.hs view
@@ -1,6 +1,7 @@-{-# LANGUAGE DeriveDataTypeable, DeriveGeneric #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric      #-} {--Copyright (C) 2012-2016 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2012-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -19,7 +20,7 @@  {- |    Module      : Text.Pandoc.Options-   Copyright   : Copyright (C) 2012-2016 John MacFarlane+   Copyright   : Copyright (C) 2012-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -29,13 +30,7 @@ Data structures and functions for representing parser and writer options. -}-module Text.Pandoc.Options ( Extension(..)-                           , pandocExtensions-                           , plainExtensions-                           , strictExtensions-                           , phpMarkdownExtraExtensions-                           , githubMarkdownExtensions-                           , multimarkdownExtensions+module Text.Pandoc.Options ( module Text.Pandoc.Extensions                            , ReaderOptions(..)                            , HTMLMathMethod (..)                            , CiteMethod (..)@@ -50,248 +45,55 @@                            , def                            , isEnabled                            ) where-import Data.Set (Set)-import qualified Data.Set as Set-import Data.Default-import Text.Pandoc.Highlighting (Style, pygments)-import Text.Pandoc.MediaBag (MediaBag)+import Data.Aeson (FromJSON (..), ToJSON (..), defaultOptions,+                   genericToEncoding) import Data.Data (Data)+import Data.Default+import qualified Data.Set as Set import Data.Typeable (Typeable) import GHC.Generics (Generic)---- | Individually selectable syntax extensions.-data Extension =-      Ext_footnotes           -- ^ Pandoc/PHP/MMD style footnotes-    | Ext_inline_notes        -- ^ Pandoc-style inline notes-    | Ext_pandoc_title_block  -- ^ Pandoc title block-    | Ext_yaml_metadata_block -- ^ YAML metadata block-    | Ext_mmd_title_block     -- ^ Multimarkdown metadata block-    | Ext_table_captions      -- ^ Pandoc-style table captions-    | Ext_implicit_figures    -- ^ A paragraph with just an image is a figure-    | Ext_simple_tables       -- ^ Pandoc-style simple tables-    | Ext_multiline_tables    -- ^ Pandoc-style multiline tables-    | Ext_grid_tables         -- ^ Grid tables (pandoc, reST)-    | Ext_pipe_tables         -- ^ Pipe tables (as in PHP markdown extra)-    | Ext_citations           -- ^ Pandoc/citeproc citations-    | Ext_raw_tex             -- ^ Allow raw TeX (other than math)-    | Ext_raw_html            -- ^ Allow raw HTML-    | Ext_tex_math_dollars    -- ^ TeX math between $..$ or $$..$$-    | Ext_tex_math_single_backslash  -- ^ TeX math btw \(..\) \[..\]-    | Ext_tex_math_double_backslash  -- ^ TeX math btw \\(..\\) \\[..\\]-    | Ext_latex_macros        -- ^ Parse LaTeX macro definitions (for math only)-    | Ext_fenced_code_blocks  -- ^ Parse fenced code blocks-    | Ext_fenced_code_attributes  -- ^ Allow attributes on fenced code blocks-    | Ext_backtick_code_blocks    -- ^ GitHub style ``` code blocks-    | Ext_inline_code_attributes  -- ^ Allow attributes on inline code-    | Ext_markdown_in_html_blocks -- ^ Interpret as markdown inside HTML blocks-    | Ext_native_divs             -- ^ Use Div blocks for contents of <div> tags-    | Ext_native_spans            -- ^ Use Span inlines for contents of <span>-    | Ext_bracketed_spans         -- ^ Bracketed spans with attributes-    | Ext_markdown_attribute      -- ^ Interpret text inside HTML as markdown-                                  --   iff container has attribute 'markdown'-    | Ext_escaped_line_breaks     -- ^ Treat a backslash at EOL as linebreak-    | Ext_link_attributes         -- ^ link and image attributes-    | Ext_mmd_link_attributes     -- ^ MMD style reference link attributes-    | Ext_autolink_bare_uris  -- ^ Make all absolute URIs into links-    | Ext_fancy_lists         -- ^ Enable fancy list numbers and delimiters-    | Ext_lists_without_preceding_blankline -- ^ Allow lists without preceding blank-    | Ext_startnum            -- ^ Make start number of ordered list significant-    | Ext_definition_lists    -- ^ Definition lists as in pandoc, mmd, php-    | Ext_compact_definition_lists  -- ^ Definition lists without-                               -- space between items, and disallow laziness-    | Ext_example_lists       -- ^ Markdown-style numbered examples-    | Ext_all_symbols_escapable  -- ^ Make all non-alphanumerics escapable-    | Ext_angle_brackets_escapable  -- ^ Make < and > escapable-    | Ext_intraword_underscores  -- ^ Treat underscore inside word as literal-    | Ext_blank_before_blockquote -- ^ Require blank line before a blockquote-    | Ext_blank_before_header     -- ^ Require blank line before a header-    | Ext_strikeout           -- ^ Strikeout using ~~this~~ syntax-    | Ext_superscript         -- ^ Superscript using ^this^ syntax-    | Ext_subscript           -- ^ Subscript using ~this~ syntax-    | Ext_hard_line_breaks    -- ^ All newlines become hard line breaks-    | Ext_ignore_line_breaks  -- ^ Newlines in paragraphs are ignored-    | Ext_east_asian_line_breaks  -- ^ Newlines in paragraphs are ignored between-                              -- East Asian wide characters-    | Ext_literate_haskell    -- ^ Enable literate Haskell conventions-    | Ext_abbreviations       -- ^ PHP markdown extra abbreviation definitions-    | Ext_emoji               -- ^ Support emoji like :smile:-    | Ext_auto_identifiers    -- ^ Automatic identifiers for headers-    | Ext_ascii_identifiers   -- ^ ascii-only identifiers for headers-    | Ext_header_attributes   -- ^ Explicit header attributes {#id .class k=v}-    | Ext_mmd_header_identifiers -- ^ Multimarkdown style header identifiers [myid]-    | Ext_implicit_header_references -- ^ Implicit reference links for headers-    | Ext_line_blocks         -- ^ RST style line blocks-    | Ext_epub_html_exts      -- ^ Recognise the EPUB extended version of HTML-    | Ext_shortcut_reference_links -- ^ Shortcut reference links-    deriving (Show, Read, Enum, Eq, Ord, Bounded, Data, Typeable, Generic)--pandocExtensions :: Set Extension-pandocExtensions = Set.fromList-  [ Ext_footnotes-  , Ext_inline_notes-  , Ext_pandoc_title_block-  , Ext_yaml_metadata_block-  , Ext_table_captions-  , Ext_implicit_figures-  , Ext_simple_tables-  , Ext_multiline_tables-  , Ext_grid_tables-  , Ext_pipe_tables-  , Ext_citations-  , Ext_raw_tex-  , Ext_raw_html-  , Ext_tex_math_dollars-  , Ext_latex_macros-  , Ext_fenced_code_blocks-  , Ext_fenced_code_attributes-  , Ext_backtick_code_blocks-  , Ext_inline_code_attributes-  , Ext_markdown_in_html_blocks-  , Ext_native_divs-  , Ext_native_spans-  , Ext_bracketed_spans-  , Ext_escaped_line_breaks-  , Ext_fancy_lists-  , Ext_startnum-  , Ext_definition_lists-  , Ext_example_lists-  , Ext_all_symbols_escapable-  , Ext_intraword_underscores-  , Ext_blank_before_blockquote-  , Ext_blank_before_header-  , Ext_strikeout-  , Ext_superscript-  , Ext_subscript-  , Ext_auto_identifiers-  , Ext_header_attributes-  , Ext_link_attributes-  , Ext_implicit_header_references-  , Ext_line_blocks-  , Ext_shortcut_reference_links-  ]--plainExtensions :: Set Extension-plainExtensions = Set.fromList-  [ Ext_table_captions-  , Ext_implicit_figures-  , Ext_simple_tables-  , Ext_multiline_tables-  , Ext_grid_tables-  , Ext_latex_macros-  , Ext_fancy_lists-  , Ext_startnum-  , Ext_definition_lists-  , Ext_example_lists-  , Ext_intraword_underscores-  , Ext_blank_before_blockquote-  , Ext_blank_before_header-  , Ext_strikeout-  ]--phpMarkdownExtraExtensions :: Set Extension-phpMarkdownExtraExtensions = Set.fromList-  [ Ext_footnotes-  , Ext_pipe_tables-  , Ext_raw_html-  , Ext_markdown_attribute-  , Ext_fenced_code_blocks-  , Ext_definition_lists-  , Ext_intraword_underscores-  , Ext_header_attributes-  , Ext_link_attributes-  , Ext_abbreviations-  , Ext_shortcut_reference_links-  ]--githubMarkdownExtensions :: Set Extension-githubMarkdownExtensions = Set.fromList-  [ Ext_angle_brackets_escapable-  , Ext_pipe_tables-  , Ext_raw_html-  , Ext_fenced_code_blocks-  , Ext_auto_identifiers-  , Ext_ascii_identifiers-  , Ext_backtick_code_blocks-  , Ext_autolink_bare_uris-  , Ext_intraword_underscores-  , Ext_strikeout-  , Ext_hard_line_breaks-  , Ext_emoji-  , Ext_lists_without_preceding_blankline-  , Ext_shortcut_reference_links-  ]--multimarkdownExtensions :: Set Extension-multimarkdownExtensions = Set.fromList-  [ Ext_pipe_tables-  , Ext_raw_html-  , Ext_markdown_attribute-  , Ext_mmd_link_attributes-  -- , Ext_raw_tex-  -- Note: MMD's raw TeX syntax requires raw TeX to be-  -- enclosed in HTML comment-  , Ext_tex_math_double_backslash-  , Ext_intraword_underscores-  , Ext_mmd_title_block-  , Ext_footnotes-  , Ext_definition_lists-  , Ext_all_symbols_escapable-  , Ext_implicit_header_references-  , Ext_auto_identifiers-  , Ext_mmd_header_identifiers-  , Ext_implicit_figures-  -- Note: MMD's syntax for superscripts and subscripts-  -- is a bit more permissive than pandoc's, allowing-  -- e^2 and a~1 instead of e^2^ and a~1~, so even with-  -- these options we don't have full support for MMD-  -- superscripts and subscripts, but there's no reason-  -- not to include these:-  , Ext_superscript-  , Ext_subscript-  ]--strictExtensions :: Set Extension-strictExtensions = Set.fromList-  [ Ext_raw_html-  , Ext_shortcut_reference_links-  ]+import Skylighting (SyntaxMap, defaultSyntaxMap)+import Text.Pandoc.Extensions+import Text.Pandoc.Highlighting (Style, pygments)  data ReaderOptions = ReaderOptions{-         readerExtensions      :: Set Extension  -- ^ Syntax extensions-       , readerSmart           :: Bool -- ^ Smart punctuation-       , readerStandalone      :: Bool -- ^ Standalone document with header-       , readerParseRaw        :: Bool -- ^ Parse raw HTML, LaTeX-       , readerColumns         :: Int  -- ^ Number of columns in terminal-       , readerTabStop         :: Int  -- ^ Tab stop-       , readerOldDashes       :: Bool -- ^ Use pandoc <= 1.8.2.1 behavior-                                       --   in parsing dashes; -- is em-dash;-                                       --   - before numerial is en-dash-       , readerApplyMacros     :: Bool -- ^ Apply macros to TeX math-       , readerIndentedCodeClasses :: [String] -- ^ Default classes for+         readerExtensions            :: Extensions  -- ^ Syntax extensions+       , readerStandalone            :: Bool -- ^ Standalone document with header+       , readerColumns               :: Int  -- ^ Number of columns in terminal+       , readerTabStop               :: Int  -- ^ Tab stop+       , readerIndentedCodeClasses   :: [String] -- ^ Default classes for                                        -- indented code blocks+       , readerAbbreviations         :: Set.Set String -- ^ Strings to treat as abbreviations        , readerDefaultImageExtension :: String -- ^ Default extension for images-       , readerTrace           :: Bool -- ^ Print debugging info-       , readerTrackChanges    :: TrackChanges-       , readerFileScope      :: Bool -- ^ Parse before combining+       , readerTrackChanges          :: TrackChanges -- ^ Track changes setting for docx+       , readerStripComments         :: Bool -- ^ Strip HTML comments instead of parsing as raw HTML } deriving (Show, Read, Data, Typeable, Generic) +instance ToJSON ReaderOptions where+  toEncoding = genericToEncoding defaultOptions+instance FromJSON ReaderOptions+ instance Default ReaderOptions   where def = ReaderOptions{-                 readerExtensions            = pandocExtensions-               , readerSmart                 = False+                 readerExtensions            = emptyExtensions                , readerStandalone            = False-               , readerParseRaw              = False                , readerColumns               = 80                , readerTabStop               = 4-               , readerOldDashes             = False-               , readerApplyMacros           = True                , readerIndentedCodeClasses   = []+               , readerAbbreviations         = defaultAbbrevs                , readerDefaultImageExtension = ""-               , readerTrace                 = False                , readerTrackChanges          = AcceptChanges-               , readerFileScope             = False+               , readerStripComments         = False                } +defaultAbbrevs :: Set.Set String+defaultAbbrevs = Set.fromList+                 [ "Mr.", "Mrs.", "Ms.", "Capt.", "Dr.", "Prof.",+                   "Gen.", "Gov.", "e.g.", "i.e.", "Sgt.", "St.",+                   "vol.", "vs.", "Sen.", "Rep.", "Pres.", "Hon.",+                   "Rev.", "Ph.D.", "M.D.", "M.A.", "p.", "pp.",+                   "ch.", "sec.", "cf.", "cp."]+ -- -- Writer options --@@ -303,22 +105,34 @@                     | JsMath (Maybe String)       -- url of jsMath load script                     | GladTeX                     | WebTeX String               -- url of TeX->image script.-                    | MathML (Maybe String)       -- url of MathMLinHTML.js+                    | MathML                     | MathJax String              -- url of MathJax.js-                    | KaTeX String String -- url of stylesheet and katex.js+                    | KaTeX String                -- url of KaTeX files                     deriving (Show, Read, Eq, Data, Typeable, Generic) +instance ToJSON HTMLMathMethod where+  toEncoding = genericToEncoding defaultOptions+instance FromJSON HTMLMathMethod+ data CiteMethod = Citeproc                        -- use citeproc to render them                   | Natbib                        -- output natbib cite commands                   | Biblatex                      -- output biblatex cite commands                 deriving (Show, Read, Eq, Data, Typeable, Generic) +instance ToJSON CiteMethod where+  toEncoding = genericToEncoding defaultOptions+instance FromJSON CiteMethod+ -- | Methods for obfuscating email addresses in HTML. data ObfuscationMethod = NoObfuscation                        | ReferenceObfuscation                        | JavascriptObfuscation                        deriving (Show, Read, Eq, Data, Typeable, Generic) +instance ToJSON ObfuscationMethod where+  toEncoding = genericToEncoding defaultOptions+instance FromJSON ObfuscationMethod+ -- | Varieties of HTML slide shows. data HTMLSlideVariant = S5Slides                       | SlidySlides@@ -328,18 +142,30 @@                       | NoSlides                       deriving (Show, Read, Eq, Data, Typeable, Generic) +instance ToJSON HTMLSlideVariant where+  toEncoding = genericToEncoding defaultOptions+instance FromJSON HTMLSlideVariant+ -- | Options for accepting or rejecting MS Word track-changes. data TrackChanges = AcceptChanges                   | RejectChanges                   | AllChanges                   deriving (Show, Read, Eq, Data, Typeable, Generic) +instance ToJSON TrackChanges where+  toEncoding = genericToEncoding defaultOptions+instance FromJSON TrackChanges+ -- | Options for wrapping text in the output. data WrapOption = WrapAuto        -- ^ Automatically wrap to width                 | WrapNone        -- ^ No non-semantic newlines                 | WrapPreserve    -- ^ Preserve wrapping of input source                 deriving (Show, Read, Eq, Data, Typeable, Generic) +instance ToJSON WrapOption where+  toEncoding = genericToEncoding defaultOptions+instance FromJSON WrapOption+ -- | Options defining the type of top-level headers. data TopLevelDivision = TopLevelPart      -- ^ Top-level headers become parts                       | TopLevelChapter   -- ^ Top-level headers become chapters@@ -348,59 +174,55 @@                                           --   heuristics                       deriving (Show, Read, Eq, Data, Typeable, Generic) +instance ToJSON TopLevelDivision where+  toEncoding = genericToEncoding defaultOptions+instance FromJSON TopLevelDivision+ -- | Locations for footnotes and references in markdown output data ReferenceLocation = EndOfBlock    -- ^ End of block                        | EndOfSection  -- ^ prior to next section header (or end of document)                        | EndOfDocument -- ^ at end of document                        deriving (Show, Read, Eq, Data, Typeable, Generic) +instance ToJSON ReferenceLocation where+  toEncoding = genericToEncoding defaultOptions+instance FromJSON ReferenceLocation+ -- | Options for writers data WriterOptions = WriterOptions-  { writerTemplate         :: Maybe String -- ^ Template to use-  , writerVariables        :: [(String, String)] -- ^ Variables to set in template-  , writerTabStop          :: Int    -- ^ Tabstop for conversion btw spaces and tabs-  , writerTableOfContents  :: Bool   -- ^ Include table of contents-  , writerSlideVariant     :: HTMLSlideVariant -- ^ Are we writing S5, Slidy or Slideous?-  , writerIncremental      :: Bool   -- ^ True if lists should be incremental-  , writerHTMLMathMethod   :: HTMLMathMethod  -- ^ How to print math in HTML-  , writerIgnoreNotes      :: Bool   -- ^ Ignore footnotes (used in making toc)-  , writerNumberSections   :: Bool   -- ^ Number sections in LaTeX-  , writerNumberOffset     :: [Int]  -- ^ Starting number for section, subsection, ...-  , writerSectionDivs      :: Bool   -- ^ Put sections in div tags in HTML-  , writerExtensions       :: Set Extension -- ^ Markdown extensions that can be used-  , writerReferenceLinks   :: Bool   -- ^ Use reference links in writing markdown, rst-  , writerDpi              :: Int    -- ^ Dpi for pixel to/from inch/cm conversions-  , writerWrapText         :: WrapOption  -- ^ Option for wrapping text-  , writerColumns          :: Int    -- ^ Characters in a line (for text wrapping)-  , writerEmailObfuscation :: ObfuscationMethod -- ^ How to obfuscate emails-  , writerIdentifierPrefix :: String -- ^ Prefix for section & note ids in HTML+  { writerTemplate          :: Maybe String -- ^ Template to use+  , writerVariables         :: [(String, String)] -- ^ Variables to set in template+  , writerTabStop           :: Int    -- ^ Tabstop for conversion btw spaces and tabs+  , writerTableOfContents   :: Bool   -- ^ Include table of contents+  , writerIncremental       :: Bool   -- ^ True if lists should be incremental+  , writerHTMLMathMethod    :: HTMLMathMethod  -- ^ How to print math in HTML+  , writerNumberSections    :: Bool   -- ^ Number sections in LaTeX+  , writerNumberOffset      :: [Int]  -- ^ Starting number for section, subsection, ...+  , writerSectionDivs       :: Bool   -- ^ Put sections in div tags in HTML+  , writerExtensions        :: Extensions -- ^ Markdown extensions that can be used+  , writerReferenceLinks    :: Bool   -- ^ Use reference links in writing markdown, rst+  , writerDpi               :: Int    -- ^ Dpi for pixel to/from inch/cm conversions+  , writerWrapText          :: WrapOption  -- ^ Option for wrapping text+  , writerColumns           :: Int    -- ^ Characters in a line (for text wrapping)+  , writerEmailObfuscation  :: ObfuscationMethod -- ^ How to obfuscate emails+  , writerIdentifierPrefix  :: String -- ^ Prefix for section & note ids in HTML                                      -- and for footnote marks in markdown-  , writerSourceURL        :: Maybe String  -- ^ Absolute URL + directory of 1st source file-  , writerUserDataDir      :: Maybe FilePath -- ^ Path of user data directory-  , writerCiteMethod       :: CiteMethod -- ^ How to print cites-  , writerDocbook5         :: Bool       -- ^ Produce DocBook5-  , writerHtml5            :: Bool       -- ^ Produce HTML5-  , writerHtmlQTags        :: Bool       -- ^ Use @<q>@ tags for quotes in HTML-  , writerBeamer           :: Bool       -- ^ Produce beamer LaTeX slide show-  , writerSlideLevel       :: Maybe Int  -- ^ Force header level of slides-  , writerTopLevelDivision :: TopLevelDivision -- ^ Type of top-level divisions-  , writerListings         :: Bool       -- ^ Use listings package for code-  , writerHighlight        :: Bool       -- ^ Highlight source code-  , writerHighlightStyle   :: Style      -- ^ Style to use for highlighting-  , writerSetextHeaders    :: Bool       -- ^ Use setext headers for levels 1-2 in markdown-  , writerTeXLigatures     :: Bool       -- ^ Use tex ligatures quotes, dashes in latex-  , writerEpubVersion      :: Maybe EPUBVersion -- ^ Nothing or EPUB version-  , writerEpubMetadata     :: String     -- ^ Metadata to include in EPUB-  , writerEpubStylesheet   :: Maybe String -- ^ EPUB stylesheet specified at command line-  , writerEpubFonts        :: [FilePath] -- ^ Paths to fonts to embed-  , writerEpubChapterLevel :: Int            -- ^ Header level for chapters (separate files)-  , writerTOCDepth         :: Int            -- ^ Number of levels to include in TOC-  , writerReferenceODT     :: Maybe FilePath -- ^ Path to reference ODT if specified-  , writerReferenceDocx    :: Maybe FilePath -- ^ Path to reference DOCX if specified-  , writerMediaBag         :: MediaBag       -- ^ Media collected by docx or epub reader-  , writerVerbose          :: Bool           -- ^ Verbose debugging output-  , writerLaTeXArgs        :: [String]       -- ^ Flags to pass to latex-engine+  , writerCiteMethod        :: CiteMethod -- ^ How to print cites+  , writerHtmlQTags         :: Bool       -- ^ Use @<q>@ tags for quotes in HTML+  , writerSlideLevel        :: Maybe Int  -- ^ Force header level of slides+  , writerTopLevelDivision  :: TopLevelDivision -- ^ Type of top-level divisions+  , writerListings          :: Bool       -- ^ Use listings package for code+  , writerHighlightStyle    :: Maybe Style  -- ^ Style to use for highlighting+                                           -- (Nothing = no highlighting)+  , writerSetextHeaders     :: Bool       -- ^ Use setext headers for levels 1-2 in markdown+  , writerEpubSubdirectory  :: String       -- ^ Subdir for epub in OCF+  , writerEpubMetadata      :: Maybe String -- ^ Metadata to include in EPUB+  , writerEpubFonts         :: [FilePath] -- ^ Paths to fonts to embed+  , writerEpubChapterLevel  :: Int            -- ^ Header level for chapters (separate files)+  , writerTOCDepth          :: Int            -- ^ Number of levels to include in TOC+  , writerReferenceDoc      :: Maybe FilePath -- ^ Path to reference document if specified   , writerReferenceLocation :: ReferenceLocation    -- ^ Location of footnotes and references for writing markdown+  , writerSyntaxMap         :: SyntaxMap   } deriving (Show, Data, Typeable, Generic)  instance Default WriterOptions where@@ -408,48 +230,35 @@                       , writerVariables        = []                       , writerTabStop          = 4                       , writerTableOfContents  = False-                      , writerSlideVariant     = NoSlides                       , writerIncremental      = False                       , writerHTMLMathMethod   = PlainMath-                      , writerIgnoreNotes      = False                       , writerNumberSections   = False                       , writerNumberOffset     = [0,0,0,0,0,0]                       , writerSectionDivs      = False-                      , writerExtensions       = pandocExtensions+                      , writerExtensions       = emptyExtensions                       , writerReferenceLinks   = False                       , writerDpi              = 96                       , writerWrapText         = WrapAuto                       , writerColumns          = 72                       , writerEmailObfuscation = NoObfuscation                       , writerIdentifierPrefix = ""-                      , writerSourceURL        = Nothing-                      , writerUserDataDir      = Nothing                       , writerCiteMethod       = Citeproc-                      , writerDocbook5         = False-                      , writerHtml5            = False                       , writerHtmlQTags        = False-                      , writerBeamer           = False                       , writerSlideLevel       = Nothing                       , writerTopLevelDivision = TopLevelDefault                       , writerListings         = False-                      , writerHighlight        = False-                      , writerHighlightStyle   = pygments+                      , writerHighlightStyle   = Just pygments                       , writerSetextHeaders    = True-                      , writerTeXLigatures     = True-                      , writerEpubVersion      = Nothing-                      , writerEpubMetadata     = ""-                      , writerEpubStylesheet   = Nothing+                      , writerEpubSubdirectory = "EPUB"+                      , writerEpubMetadata     = Nothing                       , writerEpubFonts        = []                       , writerEpubChapterLevel = 1                       , writerTOCDepth         = 3-                      , writerReferenceODT     = Nothing-                      , writerReferenceDocx    = Nothing-                      , writerMediaBag         = mempty-                      , writerVerbose          = False-                      , writerLaTeXArgs        = []+                      , writerReferenceDoc     = Nothing                       , writerReferenceLocation = EndOfDocument+                      , writerSyntaxMap        = defaultSyntaxMap                       }  -- | Returns True if the given extension is enabled. isEnabled :: Extension -> WriterOptions -> Bool-isEnabled ext opts = ext `Set.member` (writerExtensions opts)+isEnabled ext opts = ext `extensionEnabled` (writerExtensions opts)
src/Text/Pandoc/PDF.hs view
@@ -1,6 +1,8 @@-{-# LANGUAGE OverloadedStrings, CPP, ScopedTypeVariables #-}+{-# LANGUAGE CPP                 #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE ScopedTypeVariables #-} {--Copyright (C) 2012-2016 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2012-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -19,7 +21,7 @@  {- |    Module      : Text.Pandoc.PDF-   Copyright   : Copyright (C) 2012-2016 John MacFarlane+   Copyright   : Copyright (C) 2012-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -30,49 +32,60 @@ -} module Text.Pandoc.PDF ( makePDF ) where +import qualified Codec.Picture as JP+import qualified Control.Exception as E+import Control.Monad (unless, when)+import Control.Monad.Trans (MonadIO (..))+import qualified Data.ByteString as BS import Data.ByteString.Lazy (ByteString)-import qualified Data.ByteString.Lazy as B+import qualified Data.ByteString.Lazy as BL import qualified Data.ByteString.Lazy.Char8 as BC-import qualified Data.ByteString as BS+import Data.Maybe (fromMaybe) import Data.Monoid ((<>))-import System.Exit (ExitCode (..))-import System.FilePath-import System.IO (stderr, stdout)-import System.IO.Temp (withTempFile)+import Data.Text (Text)+import qualified Data.Text as T+import qualified Data.Text.IO as TextIO import System.Directory-import Data.Digest.Pure.SHA (showDigest, sha1) import System.Environment-import Control.Monad (unless, when, (<=<))-import qualified Control.Exception as E-import Data.List (isInfixOf)-import Data.Maybe (fromMaybe)-import qualified Text.Pandoc.UTF8 as UTF8+import System.Exit (ExitCode (..))+import System.FilePath+import System.IO (stdout)+import System.IO.Temp (withTempDirectory, withTempFile)+#if MIN_VERSION_base(4,8,3)+import System.IO.Error (IOError, isDoesNotExistError)+#else+import System.IO.Error (isDoesNotExistError)+#endif import Text.Pandoc.Definition+import Text.Pandoc.Error (PandocError (PandocPDFProgramNotFoundError))+import Text.Pandoc.MIME (getMimeType)+import Text.Pandoc.Options (HTMLMathMethod (..), WriterOptions (..))+import Text.Pandoc.Process (pipeProcess)+import Text.Pandoc.Shared (inDirectory, stringify, withTempDir)+import qualified Text.Pandoc.UTF8 as UTF8 import Text.Pandoc.Walk (walkM)-import Text.Pandoc.Shared (fetchItem', warn, withTempDir, inDirectory,-                           stringify) import Text.Pandoc.Writers.Shared (getField, metaToJSON)-import Text.Pandoc.Options (WriterOptions(..), HTMLMathMethod(..))-import Text.Pandoc.MIME (extensionFromMimeType, getMimeType)-import Text.Pandoc.Process (pipeProcess)-import qualified Data.ByteString.Lazy as BL-import qualified Codec.Picture as JP #ifdef _WINDOWS import Data.List (intercalate) #endif+import Text.Pandoc.Class (PandocIO, extractMedia, fillMediaBag, getCommonState,+                          getVerbosity, putCommonState, report, runIO,+                          runIOorExplode, setVerbosity)+import Text.Pandoc.Logging  #ifdef _WINDOWS changePathSeparators :: FilePath -> FilePath changePathSeparators = intercalate "/" . splitDirectories #endif -makePDF :: String              -- ^ pdf creator (pdflatex, lualatex,-                               -- xelatex, context, wkhtmltopdf)-        -> (WriterOptions -> Pandoc -> String)  -- ^ writer+makePDF :: String              -- ^ pdf creator (pdflatex, lualatex, xelatex,+                               -- wkhtmltopdf, weasyprint, prince, context, pdfroff)+        -> [String]            -- ^ arguments to pass to pdf creator+        -> (WriterOptions -> Pandoc -> PandocIO Text)  -- ^ writer         -> WriterOptions       -- ^ options         -> Pandoc              -- ^ document-        -> IO (Either ByteString ByteString)-makePDF "wkhtmltopdf" writer opts doc@(Pandoc meta _) = do+        -> PandocIO (Either ByteString ByteString)+makePDF "wkhtmltopdf" pdfargs writer opts doc@(Pandoc meta _) = do   let mathArgs = case writerHTMLMathMethod opts of                  -- with MathJax, wait til all math is rendered:                       MathJax _ -> ["--run-script", "MathJax.Hub.Register.StartupHook('End Typeset', function() { window.status = 'mathjax_loaded' });",@@ -80,8 +93,7 @@                       _ -> []   meta' <- metaToJSON opts (return . stringify) (return . stringify) meta   let toArgs (f, mbd) = maybe [] (\d -> ['-':'-':f, d]) mbd-  let args   = mathArgs ++-               concatMap toArgs+  let args   = pdfargs ++ mathArgs ++ concatMap toArgs                  [("page-size", getField "papersize" meta')                  ,("title", getField "title" meta')                  ,("margin-bottom", fromMaybe (Just "1.2in")@@ -93,54 +105,56 @@                  ,("margin-left", fromMaybe (Just "1.25in")                             (getField "margin-left" meta'))                  ]-  let source = writer opts doc-  html2pdf (writerVerbose opts) args source-makePDF program writer opts doc = withTempDir "tex2pdf." $ \tmpdir -> do-  doc' <- handleImages opts tmpdir doc-  let source = writer opts doc'-      args   = writerLaTeXArgs opts-  case takeBaseName program of-     "context" -> context2pdf (writerVerbose opts) tmpdir source-     prog | prog `elem` ["pdflatex", "lualatex", "xelatex"]-         -> tex2pdf' (writerVerbose opts) args tmpdir program source-     _ -> return $ Left $ UTF8.fromStringLazy $ "Unknown program " ++ program+  source <- writer opts doc+  verbosity <- getVerbosity+  liftIO $ html2pdf verbosity "wkhtmltopdf" args source+makePDF "weasyprint" pdfargs writer opts doc = do+  source <- writer opts doc+  verbosity <- getVerbosity+  liftIO $ html2pdf verbosity "weasyprint" pdfargs source+makePDF "prince" pdfargs writer opts doc = do+  source <- writer opts doc+  verbosity <- getVerbosity+  liftIO $ html2pdf verbosity "prince" pdfargs source+makePDF "pdfroff" pdfargs writer opts doc = do+  source <- writer opts doc+  let args   = ["-ms", "-mpdfmark", "-e", "-t", "-k", "-KUTF-8", "-i",+                "--no-toc-relocation"] ++ pdfargs+  verbosity <- getVerbosity+  liftIO $ ms2pdf verbosity args source+makePDF program pdfargs writer opts doc = do+  let withTemp = if takeBaseName program == "context"+                    then withTempDirectory "."+                    else withTempDir+  commonState <- getCommonState+  verbosity <- getVerbosity+  liftIO $ withTemp "tex2pdf." $ \tmpdir -> do+    source <- runIOorExplode $ do+                putCommonState commonState+                doc' <- handleImages tmpdir doc+                writer opts doc'+    case takeBaseName program of+       "context" -> context2pdf verbosity tmpdir source+       prog | prog `elem` ["pdflatex", "lualatex", "xelatex"]+           -> tex2pdf' verbosity pdfargs tmpdir program source+       _ -> return $ Left $ UTF8.fromStringLazy $ "Unknown program " ++ program -handleImages :: WriterOptions-             -> FilePath      -- ^ temp dir to store images+handleImages :: FilePath      -- ^ temp dir to store images              -> Pandoc        -- ^ document-             -> IO Pandoc-handleImages opts tmpdir = walkM (convertImages tmpdir) <=< walkM (handleImage' opts tmpdir)--handleImage' :: WriterOptions-             -> FilePath-             -> Inline-             -> IO Inline-handleImage' opts tmpdir (Image attr ils (src,tit)) = do-    exists <- doesFileExist src-    if exists-       then return $ Image attr ils (src,tit)-       else do-         res <- fetchItem' (writerMediaBag opts) (writerSourceURL opts) src-         case res of-              Right (contents, Just mime) -> do-                let ext = fromMaybe (takeExtension src) $-                          extensionFromMimeType mime-                let basename = showDigest $ sha1 $ BL.fromChunks [contents]-                let fname = tmpdir </> basename <.> ext-                BS.writeFile fname contents-                return $ Image attr ils (fname,tit)-              _ -> do-                warn $ "Could not find image `" ++ src ++ "', skipping..."-                -- return alt text-                return $ Emph ils-handleImage' _ _ x = return x+             -> PandocIO Pandoc+handleImages tmpdir doc =+  fillMediaBag doc >>=+    extractMedia tmpdir >>=+    walkM (convertImages tmpdir) -convertImages :: FilePath -> Inline -> IO Inline+convertImages :: FilePath -> Inline -> PandocIO Inline convertImages tmpdir (Image attr ils (src, tit)) = do-  img <- convertImage tmpdir src+  img <- liftIO $ convertImage tmpdir src   newPath <-     case img of-      Left e -> src <$ warn e+      Left e -> do+        report $ CouldNotConvertImage src e+        return src       Right fp -> return fp   return (Image attr ils (newPath, tit)) convertImages _ x = return x@@ -152,29 +166,43 @@     Just "image/png" -> doNothing     Just "image/jpeg" -> doNothing     Just "application/pdf" -> doNothing+    Just "image/svg+xml" -> E.catch (do+      (exit, _) <- pipeProcess Nothing "rsvg-convert"+                     ["-f","pdf","-a","-o",pdfOut,fname] BL.empty+      if exit == ExitSuccess+         then return $ Right pdfOut+         else return $ Left "conversion from SVG failed")+      (\(e :: E.SomeException) -> return $ Left $+          "check that rsvg2pdf is in path.\n" +++          show e)     _ -> JP.readImage fname >>= \res ->           case res of-               Left _    -> return $ Left $ "Unable to convert `" ++-                               fname ++ "' for use with pdflatex."+               Left e    -> return $ Left e                Right img ->-                 E.catch (Right fileOut <$ JP.savePngImage fileOut img) $+                 E.catch (Right pngOut <$ JP.savePngImage pngOut img) $                      \(e :: E.SomeException) -> return (Left (show e))   where-    fileOut = replaceDirectory (replaceExtension fname ".png") tmpdir+    pngOut = replaceDirectory (replaceExtension fname ".png") tmpdir+    pdfOut = replaceDirectory (replaceExtension fname ".pdf") tmpdir     mime = getMimeType fname     doNothing = return (Right fname) -tex2pdf' :: Bool                            -- ^ Verbose output+tex2pdf' :: Verbosity                       -- ^ Verbosity level          -> [String]                        -- ^ Arguments to the latex-engine          -> FilePath                        -- ^ temp directory for output          -> String                          -- ^ tex program-         -> String                          -- ^ tex source+         -> Text                            -- ^ tex source          -> IO (Either ByteString ByteString)-tex2pdf' verbose args tmpDir program source = do-  let numruns = if "\\tableofcontents" `isInfixOf` source+tex2pdf' verbosity args tmpDir program source = do+  let numruns = if "\\tableofcontents" `T.isInfixOf` source                    then 3  -- to get page numbers                    else 2  -- 1 run won't give you PDF bookmarks-  (exit, log', mbPdf) <- runTeXProgram verbose program args 1 numruns tmpDir source+  (exit, log', mbPdf) <- E.catch+    (runTeXProgram verbosity program args 1 numruns tmpDir source)+    (\(e :: IOError) -> if isDoesNotExistError e+                           then E.throwIO $+                                 PandocPDFProgramNotFoundError program+                           else E.throwIO e)   case (exit, mbPdf) of        (ExitFailure _, _)      -> do           let logmsg = extractMsg log'@@ -182,12 +210,27 @@                 case logmsg of                      x | "! Package inputenc Error" `BC.isPrefixOf` x                            && program /= "xelatex"-                       -> "\nTry running pandoc with --latex-engine=xelatex."+                       -> "\nTry running pandoc with --pdf-engine=xelatex."                      _ -> ""           return $ Left $ logmsg <> extramsg        (ExitSuccess, Nothing)  -> return $ Left ""-       (ExitSuccess, Just pdf) -> return $ Right pdf+       (ExitSuccess, Just pdf) -> do+          missingCharacterWarnings verbosity log'+          return $ Right pdf +missingCharacterWarnings :: Verbosity -> ByteString -> IO ()+missingCharacterWarnings verbosity log' = do+  let ls = BC.lines log'+  let isMissingCharacterWarning = BC.isPrefixOf "Missing character: "+  let warnings = [ UTF8.toStringLazy (BC.drop 19 l)+                 | l <- ls+                 , isMissingCharacterWarning l+                 ]+  runIO $ do+    setVerbosity verbosity+    mapM_ (report . MissingCharacter) warnings+  return ()+ -- parsing output  extractMsg :: ByteString -> ByteString@@ -212,12 +255,12 @@ -- Run a TeX program on an input bytestring and return (exit code, -- contents of stdout, contents of produced PDF if any).  Rerun -- a fixed number of times to resolve references.-runTeXProgram :: Bool -> String -> [String] -> Int -> Int -> FilePath -> String-              -> IO (ExitCode, ByteString, Maybe ByteString)-runTeXProgram verbose program args runNumber numRuns tmpDir source = do+runTeXProgram :: Verbosity -> String -> [String] -> Int -> Int -> FilePath+              -> Text -> IO (ExitCode, ByteString, Maybe ByteString)+runTeXProgram verbosity program args runNumber numRuns tmpDir source = do     let file = tmpDir </> "input.tex"     exists <- doesFileExist file-    unless exists $ UTF8.writeFile file source+    unless exists $ BS.writeFile file $ UTF8.fromText source #ifdef _WINDOWS     -- note:  we want / even on Windows, for TexLive     let tmpDir' = changePathSeparators tmpDir@@ -234,7 +277,7 @@           $ lookup "TEXINPUTS" env'     let env'' = ("TEXINPUTS", texinputs) :                   [(k,v) | (k,v) <- env', k /= "TEXINPUTS"]-    when (verbose && runNumber == 1) $ do+    when (verbosity >= INFO && runNumber == 1) $ do       putStrLn "[makePDF] temp dir:"       putStrLn tmpDir'       putStrLn "[makePDF] Command line:"@@ -244,16 +287,15 @@       mapM_ print env''       putStr "\n"       putStrLn $ "[makePDF] Contents of " ++ file' ++ ":"-      B.readFile file' >>= B.putStr+      BL.readFile file' >>= BL.putStr       putStr "\n"-    (exit, out, err) <- pipeProcess (Just env'') program programArgs BL.empty-    when verbose $ do+    (exit, out) <- pipeProcess (Just env'') program programArgs BL.empty+    when (verbosity >= INFO) $ do       putStrLn $ "[makePDF] Run #" ++ show runNumber-      B.hPutStr stdout out-      B.hPutStr stderr err+      BL.hPutStr stdout out       putStr "\n"     if runNumber <= numRuns-       then runTeXProgram verbose program args (runNumber + 1) numRuns tmpDir source+       then runTeXProgram verbosity program args (runNumber + 1) numRuns tmpDir source        else do          let pdfFile = replaceDirectory (replaceExtension file ".pdf") tmpDir          pdfExists <- doesFileExist pdfFile@@ -261,36 +303,75 @@                    -- We read PDF as a strict bytestring to make sure that the                    -- temp directory is removed on Windows.                    -- See https://github.com/jgm/pandoc/issues/1192.-                   then (Just . B.fromChunks . (:[])) `fmap` BS.readFile pdfFile+                   then (Just . BL.fromChunks . (:[])) `fmap` BS.readFile pdfFile                    else return Nothing-         return (exit, out <> err, pdf)+         -- Note that some things like Missing character warnings+         -- appear in the log but not on stderr, so we prefer the log:+         let logFile = replaceExtension file ".log"+         logExists <- doesFileExist logFile+         log' <- if logExists+                    then BL.readFile logFile+                    else return out+         return (exit, log', pdf) -html2pdf  :: Bool         -- ^ Verbose output-          -> [String]     -- ^ Args to wkhtmltopdf-          -> String       -- ^ HTML5 source+ms2pdf :: Verbosity+       -> [String]+       -> Text+       -> IO (Either ByteString ByteString)+ms2pdf verbosity args source = do+  env' <- getEnvironment+  when (verbosity >= INFO) $ do+    putStrLn "[makePDF] Command line:"+    putStrLn $ "pdfroff " ++ " " ++ unwords (map show args)+    putStr "\n"+    putStrLn "[makePDF] Environment:"+    mapM_ print env'+    putStr "\n"+    putStrLn "[makePDF] Contents:\n"+    putStr $ T.unpack source+    putStr "\n"+  (exit, out) <- E.catch+    (pipeProcess (Just env') "pdfroff" args+                     (BL.fromStrict $ UTF8.fromText source))+    (\(e :: IOError) -> if isDoesNotExistError e+                           then E.throwIO $+                                  PandocPDFProgramNotFoundError "pdfroff"+                           else E.throwIO e)+  when (verbosity >= INFO) $ do+    BL.hPutStr stdout out+    putStr "\n"+  return $ case exit of+             ExitFailure _ -> Left out+             ExitSuccess   -> Right out++html2pdf  :: Verbosity    -- ^ Verbosity level+          -> String       -- ^ Program (wkhtmltopdf, weasyprint or prince)+          -> [String]     -- ^ Args to program+          -> Text         -- ^ HTML5 source           -> IO (Either ByteString ByteString)-html2pdf verbose args source = do-  file <- withTempFile "." "html2pdf.html" $ \fp _ -> return fp+html2pdf verbosity program args source = do   pdfFile <- withTempFile "." "html2pdf.pdf" $ \fp _ -> return fp-  UTF8.writeFile file source-  let programArgs = args ++ [file, pdfFile]+  let pdfFileArgName = ["-o" | program == "prince"]+  let programArgs = args ++ ["-"] ++ pdfFileArgName ++ [pdfFile]   env' <- getEnvironment-  when verbose $ do+  when (verbosity >= INFO) $ do     putStrLn "[makePDF] Command line:"-    putStrLn $ "wkhtmltopdf" ++ " " ++ unwords (map show programArgs)+    putStrLn $ program ++ " " ++ unwords (map show programArgs)     putStr "\n"     putStrLn "[makePDF] Environment:"     mapM_ print env'     putStr "\n"-    putStrLn $ "[makePDF] Contents of " ++ file ++ ":"-    B.readFile file >>= B.putStr+    putStrLn "[makePDF] Contents of intermediate HTML:"+    TextIO.putStr source     putStr "\n"-  (exit, out, err) <- pipeProcess (Just env') "wkhtmltopdf"-                              programArgs BL.empty-  removeFile file-  when verbose $ do-    B.hPutStr stdout out-    B.hPutStr stderr err+  (exit, out) <- E.catch+    (pipeProcess (Just env') program programArgs $ BL.fromStrict $ UTF8.fromText source)+    (\(e :: IOError) -> if isDoesNotExistError e+                           then E.throwIO $+                                  PandocPDFProgramNotFoundError program+                           else E.throwIO e)+  when (verbosity >= INFO) $ do+    BL.hPutStr stdout out     putStr "\n"   pdfExists <- doesFileExist pdfFile   mbPdf <- if pdfExists@@ -298,23 +379,22 @@             -- temp directory is removed on Windows.             -- See https://github.com/jgm/pandoc/issues/1192.             then do-              res <- (Just . B.fromChunks . (:[])) `fmap` BS.readFile pdfFile+              res <- (Just . BL.fromChunks . (:[])) `fmap` BS.readFile pdfFile               removeFile pdfFile               return res             else return Nothing-  let log' = out <> err   return $ case (exit, mbPdf) of-             (ExitFailure _, _)      -> Left log'+             (ExitFailure _, _)      -> Left out              (ExitSuccess, Nothing)  -> Left ""              (ExitSuccess, Just pdf) -> Right pdf -context2pdf :: Bool         -- ^ Verbose output+context2pdf :: Verbosity    -- ^ Verbosity level             -> FilePath     -- ^ temp directory for output-            -> String       -- ^ ConTeXt source+            -> Text         -- ^ ConTeXt source             -> IO (Either ByteString ByteString)-context2pdf verbose tmpDir source = inDirectory tmpDir $ do+context2pdf verbosity tmpDir source = inDirectory tmpDir $ do   let file = "input.tex"-  UTF8.writeFile file source+  BS.writeFile file $ UTF8.fromText source #ifdef _WINDOWS   -- note:  we want / even on Windows, for TexLive   let tmpDir' = changePathSeparators tmpDir@@ -323,27 +403,26 @@ #endif   let programArgs = "--batchmode" : [file]   env' <- getEnvironment-  let sep = [searchPathSeparator]-  let texinputs = maybe (".." ++ sep) ((".." ++ sep) ++)-        $ lookup "TEXINPUTS" env'-  let env'' = ("TEXINPUTS", texinputs) :-                [(k,v) | (k,v) <- env', k /= "TEXINPUTS"]-  when verbose $ do+  when (verbosity >= INFO) $ do     putStrLn "[makePDF] temp dir:"     putStrLn tmpDir'     putStrLn "[makePDF] Command line:"     putStrLn $ "context" ++ " " ++ unwords (map show programArgs)     putStr "\n"     putStrLn "[makePDF] Environment:"-    mapM_ print env''+    mapM_ print env'     putStr "\n"     putStrLn $ "[makePDF] Contents of " ++ file ++ ":"-    B.readFile file >>= B.putStr+    BL.readFile file >>= BL.putStr     putStr "\n"-  (exit, out, err) <- pipeProcess (Just env'') "context" programArgs BL.empty-  when verbose $ do-    B.hPutStr stdout out-    B.hPutStr stderr err+  (exit, out) <- E.catch+    (pipeProcess (Just env') "context" programArgs BL.empty)+    (\(e :: IOError) -> if isDoesNotExistError e+                           then E.throwIO $+                                  PandocPDFProgramNotFoundError "context"+                           else E.throwIO e)+  when (verbosity >= INFO) $ do+    BL.hPutStr stdout out     putStr "\n"   let pdfFile = replaceExtension file ".pdf"   pdfExists <- doesFileExist pdfFile@@ -351,13 +430,11 @@             -- We read PDF as a strict bytestring to make sure that the             -- temp directory is removed on Windows.             -- See https://github.com/jgm/pandoc/issues/1192.-            then (Just . B.fromChunks . (:[])) `fmap` BS.readFile pdfFile+            then (Just . BL.fromChunks . (:[])) `fmap` BS.readFile pdfFile             else return Nothing-  let log' = out <> err   case (exit, mbPdf) of        (ExitFailure _, _)      -> do-          let logmsg = extractConTeXtMsg log'+          let logmsg = extractConTeXtMsg out           return $ Left logmsg        (ExitSuccess, Nothing)  -> return $ Left ""        (ExitSuccess, Just pdf) -> return $ Right pdf-
src/Text/Pandoc/Parsing.hs view
@@ -1,11 +1,12 @@-{-# LANGUAGE-  FlexibleContexts-, GeneralizedNewtypeDeriving-, TypeSynonymInstances-, MultiParamTypeClasses-, FlexibleInstances #-}+{-# LANGUAGE ExplicitForAll             #-}+{-# LANGUAGE FlexibleContexts           #-}+{-# LANGUAGE FlexibleInstances          #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE IncoherentInstances        #-}+{-# LANGUAGE MultiParamTypeClasses      #-}+{-# LANGUAGE TypeSynonymInstances       #-} {--Copyright (C) 2006-2016 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2006-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -24,7 +25,7 @@  {- |    Module      : Text.Pandoc.Parsing-   Copyright   : Copyright (C) 2006-2016 John MacFarlane+   Copyright   : Copyright (C) 2006-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -33,7 +34,11 @@  A utility library with parsers used in pandoc readers. -}-module Text.Pandoc.Parsing ( anyLine,+module Text.Pandoc.Parsing ( takeWhileP,+                             takeP,+                             anyLine,+                             anyLineNewline,+                             indentWith,                              many1Till,                              notFollowedBy',                              oneOfStrings,@@ -43,9 +48,12 @@                              skipSpaces,                              blankline,                              blanklines,+                             gobbleSpaces,+                             gobbleAtMostSpaces,                              enclosed,                              stringAnyCase,                              parseFromString,+                             parseFromString',                              lineClump,                              charsInBalanced,                              romanNumeral,@@ -64,20 +72,24 @@                              tableWith,                              widthsFromIndices,                              gridTableWith,+                             gridTableWith',                              readWith,-                             readWithWarnings,                              readWithM,                              testStringWith,                              guardEnabled,                              guardDisabled,                              updateLastStrPos,                              notAfterString,+                             logMessage,+                             reportLogMessages,                              ParserState (..),                              HasReaderOptions (..),                              HasHeaderMap (..),                              HasIdentifierList (..),                              HasMacros (..),+                             HasLogMessages (..),                              HasLastStrPosition (..),+                             HasIncludeFiles (..),                              defaultParserState,                              HeaderType (..),                              ParserContext (..),@@ -100,20 +112,26 @@                              dash,                              nested,                              citeKey,-                             macro,-                             applyMacros',                              Parser,                              ParserT,-                             F(..),+                             F,+                             Future(..),                              runF,                              askF,                              asksF,+                             returnF,+                             trimInlinesF,                              token,+                             (<+?>),+                             extractIdClass,+                             insertIncludedFile,+                             insertIncludedFileF,                              -- * Re-exports from Text.Pandoc.Parsec                              Stream,                              runParser,                              runParserT,                              parse,+                             tokenPrim,                              anyToken,                              getInput,                              setInput,@@ -163,60 +181,104 @@                              setSourceColumn,                              setSourceLine,                              newPos,-                             addWarning,-                             (<+?>),-                             extractIdClass+                             Line,+                             Column                              ) where +import Control.Monad.Identity+import Control.Monad.Reader+import Data.Char (chr, isAlphaNum, isAscii, isHexDigit, isPunctuation, isSpace,+                  ord, toLower, toUpper)+import Data.Default+import Data.List (intercalate, isSuffixOf, transpose)+import qualified Data.Map as M+import Data.Maybe (catMaybes)+import Data.Monoid ((<>))+import qualified Data.Set as Set+import Data.Text (Text)+import Text.HTML.TagSoup.Entity (lookupEntity)+import Text.Pandoc.Asciify (toAsciiChar)+import Text.Pandoc.Builder (Blocks, HasMeta (..), Inlines, trimInlines)+import qualified Text.Pandoc.Builder as B+import Text.Pandoc.Class (PandocMonad, readFileFromDirs, report) import Text.Pandoc.Definition+import Text.Pandoc.Logging import Text.Pandoc.Options-import Text.Pandoc.Builder (Blocks, Inlines, rawBlock, HasMeta(..))-import qualified Text.Pandoc.Builder as B-import Text.Pandoc.XML (fromEntities)+import Text.Pandoc.Readers.LaTeX.Types (Macro)+import Text.Pandoc.Shared import qualified Text.Pandoc.UTF8 as UTF8 (putStrLn)+import Text.Pandoc.XML (fromEntities) import Text.Parsec hiding (token)-import Text.Parsec.Pos (newPos)-import Data.Char ( toLower, toUpper, ord, chr, isAscii, isAlphaNum,-                   isHexDigit, isSpace, isPunctuation )-import Data.List ( intercalate, transpose, isSuffixOf )-import Text.Pandoc.Shared-import qualified Data.Map as M-import Text.TeXMath.Readers.TeX.Macros (applyMacros, Macro,-                                        parseMacroDefinitions)-import Text.HTML.TagSoup.Entity ( lookupEntity )-import Text.Pandoc.Asciify (toAsciiChar)-import Data.Monoid ((<>))-import Data.Default-import qualified Data.Set as Set-import Control.Monad.Reader-import Control.Monad.Identity-import Data.Maybe (catMaybes)+import Text.Parsec.Pos (initialPos, newPos, updatePosString) +import Control.Monad.Except import Text.Pandoc.Error  type Parser t s = Parsec t s  type ParserT = ParsecT -newtype F a = F { unF :: Reader ParserState a } deriving (Monad, Applicative, Functor)+-- | Reader monad wrapping the parser state. This is used to possibly delay+-- evaluation until all relevant information has been parsed and made available+-- in the parser state.+newtype Future s a = Future { runDelayed :: Reader s a }+  deriving (Monad, Applicative, Functor) -runF :: F a -> ParserState -> a-runF = runReader . unF+type F = Future ParserState -askF :: F ParserState-askF = F ask+runF :: Future s a -> s -> a+runF = runReader . runDelayed -asksF :: (ParserState -> a) -> F a-asksF f = F $ asks f+askF :: Future s s+askF = Future ask -instance Monoid a => Monoid (F a) where+asksF :: (s -> a) -> Future s a+asksF f = Future $ asks f++returnF :: Monad m => a -> m (Future s a)+returnF = return . return++trimInlinesF :: Future s Inlines -> Future s Inlines+trimInlinesF = liftM trimInlines++instance Monoid a => Monoid (Future s a) where   mempty = return mempty   mappend = liftM2 mappend   mconcat = liftM mconcat . sequence +-- | Parse characters while a predicate is true.+takeWhileP :: Monad m+           => (Char -> Bool)+           -> ParserT [Char] st m [Char]+takeWhileP f = do+  -- faster than 'many (satisfy f)'+  inp <- getInput+  pos <- getPosition+  let (xs, rest) = span f inp+  -- needed to persuade parsec that this won't match an empty string:+  anyChar+  setInput rest+  setPosition $ updatePosString pos xs+  return xs++-- Parse n characters of input (or the rest of the input if+-- there aren't n characters).+takeP :: Monad m => Int -> ParserT [Char] st m [Char]+takeP n = do+  guard (n > 0)+  -- faster than 'count n anyChar'+  inp <- getInput+  pos <- getPosition+  let (xs, rest) = splitAt n inp+  -- needed to persuade parsec that this won't match an empty string:+  anyChar+  setInput rest+  setPosition $ updatePosString pos xs+  return xs+ -- | Parse any line of text-anyLine :: Stream [Char] m Char => ParserT [Char] st m [Char]+anyLine :: Monad m => ParserT [Char] st m [Char] anyLine = do   -- This is much faster than:   -- manyTill anyChar newline@@ -231,12 +293,28 @@          return this        _ -> mzero +-- | Parse any line, include the final newline in the output+anyLineNewline :: Monad m => ParserT [Char] st m [Char]+anyLineNewline = (++ "\n") <$> anyLine++-- | Parse indent by specified number of spaces (or equiv. tabs)+indentWith :: Stream s m Char+           => HasReaderOptions st+           => Int -> ParserT s st m [Char]+indentWith num = do+  tabStop <- getOption readerTabStop+  if (num < tabStop)+     then count num (char ' ')+     else choice [ try (count num (char ' '))+                 , try (char '\t' >> indentWith (num - tabStop)) ]+ -- | Like @manyTill@, but reads at least one item.-many1Till :: Stream s m t+many1Till :: (Show end, Stream s m t)           => ParserT s st m a           -> ParserT s st m end           -> ParserT s st m [a] many1Till p end = do+         notFollowedBy' end          first <- p          rest <- manyTill p end          return (first:rest)@@ -300,8 +378,38 @@ blanklines :: Stream s m Char => ParserT s st m [Char] blanklines = many1 blankline +-- | Gobble n spaces; if tabs are encountered, expand them+-- and gobble some or all of their spaces, leaving the rest.+gobbleSpaces :: (HasReaderOptions st, Monad m)+             => Int -> ParserT [Char] st m ()+gobbleSpaces 0 = return ()+gobbleSpaces n+  | n < 0     = error "gobbleSpaces called with negative number"+  | otherwise = try $ do+      char ' ' <|> eatOneSpaceOfTab+      gobbleSpaces (n - 1)++eatOneSpaceOfTab :: (HasReaderOptions st, Monad m) => ParserT [Char] st m Char+eatOneSpaceOfTab = do+  char '\t'+  tabstop <- getOption readerTabStop+  inp <- getInput+  setInput $ replicate (tabstop - 1) ' ' ++ inp+  return ' '++-- | Gobble up to n spaces; if tabs are encountered, expand them+-- and gobble some or all of their spaces, leaving the rest.+gobbleAtMostSpaces :: (HasReaderOptions st, Monad m)+                   => Int -> ParserT [Char] st m Int+gobbleAtMostSpaces 0 = return 0+gobbleAtMostSpaces n+  | n < 0     = error "gobbleAtMostSpaces called with negative number"+  | otherwise = option 0 $ do+      char ' ' <|> eatOneSpaceOfTab+      (+ 1) <$> gobbleAtMostSpaces (n - 1)+ -- | Parses material enclosed between start and end parsers.-enclosed :: Stream s  m Char => ParserT s st m t   -- ^ start parser+enclosed :: (Show end, Stream s  m Char) => ParserT s st m t   -- ^ start parser          -> ParserT s st m end  -- ^ end parser          -> ParserT s st m a    -- ^ content parser (to be used repeatedly)          -> ParserT s st m [a]@@ -317,9 +425,13 @@   return (firstChar:rest)  -- | Parse contents of 'str' using 'parser' and return result.-parseFromString :: Monad m => ParserT String st m a -> String -> ParserT String st m a+parseFromString :: Monad m+                => ParserT [Char] st m a+                -> String+                -> ParserT [Char] st m a parseFromString parser str = do   oldPos <- getPosition+  setPosition $ initialPos "chunk"   oldInput <- getInput   setInput str   result <- parser@@ -329,10 +441,22 @@   setPosition oldPos   return result +-- | Like 'parseFromString' but specialized for 'ParserState'.+-- This resets 'stateLastStrPos', which is almost always what we want.+parseFromString' :: Monad m+                 => ParserT String ParserState m a+                 -> String+                 -> ParserT String ParserState m a+parseFromString' parser str = do+  oldStrPos <- stateLastStrPos <$> getState+  res <- parseFromString parser str+  updateState $ \st -> st{ stateLastStrPos = oldStrPos }+  return res+ -- | Parse raw line block up to and including blank lines.-lineClump :: Stream [Char] m Char => ParserT [Char] st m String+lineClump :: Monad m => ParserT [Char] st m String lineClump = blanklines-          <|> (many1 (notFollowedBy blankline >> anyLine) >>= return . unlines)+          <|> (unlines <$> many1 (notFollowedBy blankline >> anyLine))  -- | Parse a string of characters between an open character -- and a close character, including text between balanced@@ -424,39 +548,16 @@        sepby1 p sep      = (:) <$> p <*> (many (try $ sep >> p))  --- Schemes from http://www.iana.org/assignments/uri-schemes.html plus--- the unofficial schemes coap, doi, javascript, isbn, pmid-schemes :: [String]-schemes = ["coap","doi","javascript","aaa","aaas","about","acap","cap","cid",-           "crid","data","dav","dict","dns","file","ftp","geo","go","gopher",-           "h323","http","https","iax","icap","im","imap","info","ipp","iris",-           "iris.beep","iris.xpc","iris.xpcs","iris.lwz","ldap","mailto","mid",-           "msrp","msrps","mtqp","mupdate","news","nfs","ni","nih","nntp",-           "opaquelocktoken","pop","pres","rtsp","service","session","shttp","sieve",-           "sip","sips","sms","snmp","soap.beep","soap.beeps","tag","tel","telnet",-           "tftp","thismessage","tn3270","tip","tv","urn","vemmi","ws","wss","xcon",-           "xcon-userid","xmlrpc.beep","xmlrpc.beeps","xmpp","z39.50r","z39.50s",-           "adiumxtra","afp","afs","aim","apt","attachment","aw","beshare","bitcoin",-           "bolo","callto","chrome","chrome-extension","com-eventbrite-attendee",-           "content", "cvs","dlna-playsingle","dlna-playcontainer","dtn","dvb",-           "ed2k","facetime","feed","finger","fish","gg","git","gizmoproject",-           "gtalk","hcp","icon","ipn","irc","irc6","ircs","itms","jar","jms",-           "keyparc","lastfm","ldaps","magnet","maps","market","message","mms",-           "ms-help","msnim","mumble","mvn","notes","oid","palm","paparazzi",-           "platform","proxy","psyc","query","res","resource","rmi","rsync",-           "rtmp","secondlife","sftp","sgn","skype","smb","soldat","spotify",-           "ssh","steam","svn","teamspeak","things","udp","unreal","ut2004",-           "ventrilo","view-source","webcal","wtai","wyciwyg","xfire","xri",-           "ymsgr", "isbn", "pmid"]- uriScheme :: Stream s m Char => ParserT s st m String-uriScheme = oneOfStringsCI schemes+uriScheme = oneOfStringsCI (Set.toList schemes)  -- | Parses a URI. Returns pair of original and URI-escaped version.-uri :: Stream [Char] m Char => ParserT [Char] st m (String, String)+uri :: Monad m => ParserT [Char] st m (String, String) uri = try $ do   scheme <- uriScheme   char ':'+  -- Avoid parsing e.g. "**Notes:**" as a raw URI:+  notFollowedBy (oneOf "*_]")   -- We allow sentence punctuation except at the end, since   -- we don't want the trailing '.' in 'http://google.com.' We want to allow   -- http://en.wikipedia.org/wiki/State_of_emergency_(disambiguation)@@ -556,7 +657,9 @@  -- | Applies a parser and returns the raw string that was parsed, -- along with the value produced by the parser.-withRaw :: Stream [Char] m Char => ParsecT [Char] st m a -> ParsecT [Char] st m (a, [Char])+withRaw :: Monad m+        => ParsecT [Char] st m a+        -> ParsecT [Char] st m (a, [Char]) withRaw parser = do   pos1 <- getPosition   inp <- getInput@@ -566,9 +669,9 @@   let (l2,c2) = (sourceLine pos2, sourceColumn pos2)   let inplines = take ((l2 - l1) + 1) $ lines inp   let raw = case inplines of-                []   -> ""-                [l]  -> take (c2 - c1) l-                ls   -> unlines (init ls) ++ take (c2 - 1) (last ls)+                []  -> ""+                [l] -> take (c2 - c1) l+                ls  -> unlines (init ls) ++ take (c2 - 1) (last ls)   return (result, raw)  -- | Parses backslash, then applies character parser.@@ -584,11 +687,11 @@   ent <- many1Till nonspaceChar (char ';')   let ent' = case ent of                   '#':'X':xs -> '#':'x':xs  -- workaround tagsoup bug-                  '#':_  -> ent-                  _      -> ent ++ ";"+                  '#':_      -> ent+                  _          -> ent ++ ";"   case lookupEntity ent' of-       Just (c : _)  -> return c-       _             -> fail "entity not found"+       Just (c : _) -> return c+       _            -> fail "entity not found"  -- | Parses an uppercase roman numeral and returns (UpperRoman, number). upperRoman :: Stream s m Char => ParserT s st m (ListNumberStyle, Int)@@ -717,7 +820,7 @@   c <- characterReference   return $ Str [c] -lineBlockLine :: Stream [Char] m Char => ParserT [Char] st m String+lineBlockLine :: Monad m => ParserT [Char] st m String lineBlockLine = try $ do   char '|'   char ' '@@ -727,33 +830,48 @@   continuations <- many (try $ char ' ' >> anyLine)   return $ white ++ unwords (line : continuations) -blankLineBlockLine :: Stream [Char] m Char => ParserT [Char] st m Char+blankLineBlockLine :: Stream s m Char => ParserT s st m Char blankLineBlockLine = try (char '|' >> blankline)  -- | Parses an RST-style line block and returns a list of strings.-lineBlockLines :: Stream [Char] m Char => ParserT [Char] st m [String]+lineBlockLines :: Monad m => ParserT [Char] st m [String] lineBlockLines = try $ do   lines' <- many1 (lineBlockLine <|> ((:[]) <$> blankLineBlockLine))-  skipMany1 $ blankline <|> blankLineBlockLine+  skipMany $ blankline   return lines'  -- | Parse a table using 'headerParser', 'rowParser', -- 'lineParser', and 'footerParser'.-tableWith :: Stream s m Char-          => ParserT s ParserState m ([[Block]], [Alignment], [Int])-          -> ([Int] -> ParserT s ParserState m [[Block]])-          -> ParserT s ParserState m sep-          -> ParserT s ParserState m end-          -> ParserT s ParserState m Block+tableWith :: (Stream s m Char, HasReaderOptions st,+              Functor mf, Applicative mf, Monad mf)+          => ParserT s st m (mf [Blocks], [Alignment], [Int])+          -> ([Int] -> ParserT s st m (mf [Blocks]))+          -> ParserT s st m sep+          -> ParserT s st m end+          -> ParserT s st m (mf Blocks) tableWith headerParser rowParser lineParser footerParser = try $ do+  (aligns, widths, heads, rows) <- tableWith' headerParser rowParser+                                                lineParser footerParser+  return $ B.table mempty (zip aligns widths) <$> heads <*> rows++type TableComponents mf = ([Alignment], [Double], mf [Blocks], mf [[Blocks]])++tableWith' :: (Stream s m Char, HasReaderOptions st,+               Functor mf, Applicative mf, Monad mf)+           => ParserT s st m (mf [Blocks], [Alignment], [Int])+           -> ([Int] -> ParserT s st m (mf [Blocks]))+           -> ParserT s st m sep+           -> ParserT s st m end+           -> ParserT s st m (TableComponents mf)+tableWith' headerParser rowParser lineParser footerParser = try $ do     (heads, aligns, indices) <- headerParser-    lines' <- rowParser indices `sepEndBy1` lineParser+    lines' <- sequence <$> rowParser indices `sepEndBy1` lineParser     footerParser     numColumns <- getOption readerColumns     let widths = if (indices == [])                     then replicate (length aligns) 0.0                     else widthsFromIndices numColumns indices-    return $ Table [] aligns widths heads lines'+    return $ (aligns, widths, heads, lines')  -- Calculate relative widths of table columns, based on indices widthsFromIndices :: Int      -- Number of columns on terminal@@ -786,25 +904,44 @@ -- (which may be grid), then the rows, -- which may be grid, separated by blank lines, and -- ending with a footer (dashed line followed by blank line).-gridTableWith :: Stream [Char] m Char-              => ParserT [Char] ParserState m [Block]   -- ^ Block list parser-              -> Bool                                -- ^ Headerless table-              -> ParserT [Char] ParserState m Block+gridTableWith :: (Monad m, HasReaderOptions st,+                  Functor mf, Applicative mf, Monad mf)+              => ParserT [Char] st m (mf Blocks)  -- ^ Block list parser+              -> Bool                             -- ^ Headerless table+              -> ParserT [Char] st m (mf Blocks) gridTableWith blocks headless =   tableWith (gridTableHeader headless blocks) (gridTableRow blocks)             (gridTableSep '-') gridTableFooter +gridTableWith' :: (Monad m, HasReaderOptions st,+                   Functor mf, Applicative mf, Monad mf)+               => ParserT [Char] st m (mf Blocks)  -- ^ Block list parser+               -> Bool                             -- ^ Headerless table+               -> ParserT [Char] st m (TableComponents mf)+gridTableWith' blocks headless =+  tableWith' (gridTableHeader headless blocks) (gridTableRow blocks)+             (gridTableSep '-') gridTableFooter+ gridTableSplitLine :: [Int] -> String -> [String] gridTableSplitLine indices line = map removeFinalBar $ tail $   splitStringByIndices (init indices) $ trimr line -gridPart :: Stream s m Char => Char -> ParserT s st m (Int, Int)+gridPart :: Stream s m Char => Char -> ParserT s st m ((Int, Int), Alignment) gridPart ch = do+  leftColon <- option False (True <$ char ':')   dashes <- many1 (char ch)+  rightColon <- option False (True <$ char ':')   char '+'-  return (length dashes, length dashes + 1)+  let lengthDashes = length dashes + (if leftColon then 1 else 0) ++                       (if rightColon then 1 else 0)+  let alignment = case (leftColon, rightColon) of+                       (True, True)   -> AlignCenter+                       (True, False)  -> AlignLeft+                       (False, True)  -> AlignRight+                       (False, False) -> AlignDefault+  return ((lengthDashes, lengthDashes + 1), alignment) -gridDashedLines :: Stream s m Char => Char -> ParserT s st m [(Int,Int)]+gridDashedLines :: Stream s m Char => Char -> ParserT s st m [((Int, Int), Alignment)] gridDashedLines ch = try $ char '+' >> many1 (gridPart ch) <* blankline  removeFinalBar :: String -> String@@ -812,14 +949,14 @@   reverse . dropWhile (`elem` " \t") . dropWhile (=='|') . reverse  -- | Separator between rows of grid table.-gridTableSep :: Stream s m Char => Char -> ParserT s ParserState m Char+gridTableSep :: Stream s m Char => Char -> ParserT s st m Char gridTableSep ch = try $ gridDashedLines ch >> return '\n'  -- | Parse header for a grid table.-gridTableHeader :: Stream [Char] m Char+gridTableHeader :: (Monad m, Functor mf, Applicative mf, Monad mf)                 => Bool -- ^ Headerless table-                -> ParserT [Char] ParserState m [Block]-                -> ParserT [Char] ParserState m ([[Block]], [Alignment], [Int])+                -> ParserT [Char] st m (mf Blocks)+                -> ParserT [Char] st m (mf [Blocks], [Alignment], [Int]) gridTableHeader headless blocks = try $ do   optional blanklines   dashes <- gridDashedLines '-'@@ -828,62 +965,63 @@                     else many1                          (notFollowedBy (gridTableSep '=') >> char '|' >>                            many1Till anyChar newline)-  if headless-     then return ()-     else gridTableSep '=' >> return ()-  let lines'   = map snd dashes+  underDashes <- if headless+                    then return dashes+                    else gridDashedLines '='+  guard $ length dashes == length underDashes+  let lines'   = map (snd . fst) underDashes   let indices  = scanl (+) 0 lines'-  let aligns   = replicate (length lines') AlignDefault-  -- RST does not have a notion of alignments+  let aligns   = map snd underDashes   let rawHeads = if headless-                    then replicate (length dashes) ""-                    else map (intercalate " ") $ transpose+                    then replicate (length underDashes) ""+                    else map (unlines . map trim) $ transpose                        $ map (gridTableSplitLine indices) rawContent-  heads <- mapM (parseFromString blocks) $ map trim rawHeads+  heads <- fmap sequence $ mapM (parseFromString blocks . trim) rawHeads   return (heads, aligns, indices) -gridTableRawLine :: Stream s m Char => [Int] -> ParserT s ParserState m [String]+gridTableRawLine :: Stream s m Char => [Int] -> ParserT s st m [String] gridTableRawLine indices = do   char '|'   line <- many1Till anyChar newline   return (gridTableSplitLine indices line)  -- | Parse row of grid table.-gridTableRow :: Stream [Char]  m Char-             => ParserT [Char] ParserState m [Block]+gridTableRow :: (Monad m, Functor mf, Applicative mf, Monad mf)+             => ParserT [Char] st m (mf Blocks)              -> [Int]-             -> ParserT [Char] ParserState m [[Block]]+             -> ParserT [Char] st m (mf [Blocks]) gridTableRow blocks indices = do   colLines <- many1 (gridTableRawLine indices)   let cols = map ((++ "\n") . unlines . removeOneLeadingSpace) $                transpose colLines-  mapM (liftM compactifyCell . parseFromString blocks) cols+      compactifyCell bs = case compactify [bs] of+                            []  -> mempty+                            x:_ -> x+  cells <- sequence <$> mapM (parseFromString blocks) cols+  return $ fmap (map compactifyCell) cells  removeOneLeadingSpace :: [String] -> [String] removeOneLeadingSpace xs =   if all startsWithSpace xs      then map (drop 1) xs      else xs-   where startsWithSpace ""     = True+   where startsWithSpace ""    = True          startsWithSpace (y:_) = y == ' ' -compactifyCell :: [Block] -> [Block]-compactifyCell bs = head $ compactify [bs]- -- | Parse footer for a grid table.-gridTableFooter :: Stream s m Char => ParserT s ParserState m [Char]+gridTableFooter :: Stream s m Char => ParserT s st m [Char] gridTableFooter = blanklines  ---  -- | Removes the ParsecT layer from the monad transformer stack-readWithM :: (Monad m)-          => ParserT [Char] st m a       -- ^ parser+readWithM :: Monad m+          => ParserT [Char] st m a    -- ^ parser           -> st                       -- ^ initial state           -> String                   -- ^ input           -> m (Either PandocError a) readWithM parser state input =-    mapLeft (ParsecError input) `liftM` runParserT parser state "source" input+    mapLeft (PandocParsecError input) `liftM` runParserT parser state "source" input   -- | Parse a string with a given parser and state@@ -893,17 +1031,8 @@          -> Either PandocError a readWith p t inp = runIdentity $ readWithM p t inp -readWithWarnings :: Parser [Char] ParserState a-                    -> ParserState-                    -> String-                    -> Either PandocError (a, [String])-readWithWarnings p = readWith $ do-         doc <- p-         warnings <- stateWarnings <$> getState-         return (doc, warnings)- -- | Parse a string with @parser@ (for testing).-testStringWith :: (Show a)+testStringWith :: Show a                => ParserT [Char] ParserState Identity a                -> [Char]                -> IO ()@@ -912,34 +1041,37 @@  -- | Parsing options. data ParserState = ParserState-    { stateOptions         :: ReaderOptions, -- ^ User options-      stateParserContext   :: ParserContext, -- ^ Inside list?-      stateQuoteContext    :: QuoteContext,  -- ^ Inside quoted environment?-      stateAllowLinks      :: Bool,          -- ^ Allow parsing of links-      stateMaxNestingLevel :: Int,           -- ^ Max # of nested Strong/Emph-      stateLastStrPos      :: Maybe SourcePos, -- ^ Position after last str parsed-      stateKeys            :: KeyTable,      -- ^ List of reference keys-      stateHeaderKeys      :: KeyTable,      -- ^ List of implicit header ref keys-      stateSubstitutions   :: SubstTable,    -- ^ List of substitution references-      stateNotes           :: NoteTable,     -- ^ List of notes (raw bodies)-      stateNotes'          :: NoteTable',    -- ^ List of notes (parsed bodies)-      stateMeta            :: Meta,          -- ^ Document metadata-      stateMeta'           :: F Meta,        -- ^ Document metadata-      stateHeaderTable     :: [HeaderType],  -- ^ Ordered list of header types used-      stateHeaders         :: M.Map Inlines String, -- ^ List of headers and ids (used for implicit ref links)-      stateIdentifiers     :: Set.Set String, -- ^ Header identifiers used-      stateNextExample     :: Int,           -- ^ Number of next example-      stateExamples        :: M.Map String Int, -- ^ Map from example labels to numbers-      stateHasChapters     :: Bool,          -- ^ True if \chapter encountered-      stateMacros          :: [Macro],       -- ^ List of macros defined so far-      stateRstDefaultRole  :: String,        -- ^ Current rST default interpreted text role-      stateRstCustomRoles  :: M.Map String (String, Maybe String, Attr), -- ^ Current rST custom text roles+    { stateOptions           :: ReaderOptions, -- ^ User options+      stateParserContext     :: ParserContext, -- ^ Inside list?+      stateQuoteContext      :: QuoteContext,  -- ^ Inside quoted environment?+      stateAllowLinks        :: Bool,          -- ^ Allow parsing of links+      stateMaxNestingLevel   :: Int,           -- ^ Max # of nested Strong/Emph+      stateLastStrPos        :: Maybe SourcePos, -- ^ Position after last str parsed+      stateKeys              :: KeyTable,      -- ^ List of reference keys+      stateHeaderKeys        :: KeyTable,      -- ^ List of implicit header ref keys+      stateSubstitutions     :: SubstTable,    -- ^ List of substitution references+      stateNotes             :: NoteTable,     -- ^ List of notes (raw bodies)+      stateNotes'            :: NoteTable',    -- ^ List of notes (parsed bodies)+      stateNoteRefs          :: Set.Set String, -- ^ List of note references used+      stateMeta              :: Meta,          -- ^ Document metadata+      stateMeta'             :: F Meta,        -- ^ Document metadata+      stateCitations         :: M.Map String String, -- ^ RST-style citations+      stateHeaderTable       :: [HeaderType],  -- ^ Ordered list of header types used+      stateHeaders           :: M.Map Inlines String, -- ^ List of headers and ids (used for implicit ref links)+      stateIdentifiers       :: Set.Set String, -- ^ Header identifiers used+      stateNextExample       :: Int,           -- ^ Number of next example+      stateExamples          :: M.Map String Int, -- ^ Map from example labels to numbers+      stateMacros            :: M.Map Text Macro, -- ^ Table of macros defined so far+      stateRstDefaultRole    :: String,        -- ^ Current rST default interpreted text role+      stateRstCustomRoles    :: M.Map String (String, Maybe String, Attr), -- ^ Current rST custom text roles       -- Triple represents: 1) Base role, 2) Optional format (only for :raw:       -- roles), 3) Additional classes (rest of Attr is unused)).-      stateCaption         :: Maybe Inlines, -- ^ Caption in current environment-      stateInHtmlBlock     :: Maybe String,  -- ^ Tag type of HTML block being parsed-      stateMarkdownAttribute :: Bool,        -- ^ True if in markdown=1 context-      stateWarnings        :: [String]       -- ^ Warnings generated by the parser+      stateCaption           :: Maybe Inlines, -- ^ Caption in current environment+      stateInHtmlBlock       :: Maybe String,  -- ^ Tag type of HTML block being parsed+      stateFencedDivLevel    :: Int,           -- ^ Depth of fenced div+      stateContainers        :: [String],      -- ^ parent include files+      stateLogMessages       :: [LogMessage],  -- ^ log messages+      stateMarkdownAttribute :: Bool         -- ^ True if in markdown=1 context     }  instance Default ParserState where@@ -957,6 +1089,9 @@   -- default   getOption  f         = (f . extractReaderOptions) <$> getState +instance HasReaderOptions ParserState where+  extractReaderOptions = stateOptions+ class HasQuoteContext st m where   getQuoteContext :: (Stream s m t) => ParsecT s st m QuoteContext   withQuoteContext :: QuoteContext -> ParsecT s st m a -> ParsecT s st m a@@ -972,9 +1107,6 @@     setState newState { stateQuoteContext = oldQuoteContext }     return result -instance HasReaderOptions ParserState where-  extractReaderOptions = stateOptions- class HasHeaderMap st where   extractHeaderMap  :: st -> M.Map Inlines String   updateHeaderMap   :: (M.Map Inlines String -> M.Map Inlines String) ->@@ -993,8 +1125,8 @@   updateIdentifierList f st = st{ stateIdentifiers = f $ stateIdentifiers st }  class HasMacros st where-  extractMacros         :: st -> [Macro]-  updateMacros          :: ([Macro] -> [Macro]) -> st -> st+  extractMacros         :: st -> M.Map Text Macro+  updateMacros          :: (M.Map Text Macro -> M.Map Text Macro) -> st -> st  instance HasMacros ParserState where   extractMacros        = stateMacros@@ -1008,6 +1140,24 @@   setLastStrPos pos st = st{ stateLastStrPos = Just pos }   getLastStrPos st     = stateLastStrPos st +class HasLogMessages st where+  addLogMessage :: LogMessage -> st -> st+  getLogMessages :: st -> [LogMessage]++instance HasLogMessages ParserState where+  addLogMessage msg st = st{ stateLogMessages = msg : stateLogMessages st }+  getLogMessages st = reverse $ stateLogMessages st++class HasIncludeFiles st where+  getIncludeFiles :: st -> [String]+  addIncludeFile :: String -> st -> st+  dropLatestIncludeFile :: st -> st++instance HasIncludeFiles ParserState where+  getIncludeFiles = stateContainers+  addIncludeFile f s = s{ stateContainers = f : stateContainers s }+  dropLatestIncludeFile s = s { stateContainers = drop 1 $ stateContainers s }+ defaultParserState :: ParserState defaultParserState =     ParserState { stateOptions         = def,@@ -1020,30 +1170,45 @@                   stateHeaderKeys      = M.empty,                   stateSubstitutions   = M.empty,                   stateNotes           = [],-                  stateNotes'          = [],+                  stateNotes'          = M.empty,+                  stateNoteRefs        = Set.empty,                   stateMeta            = nullMeta,                   stateMeta'           = return nullMeta,+                  stateCitations       = M.empty,                   stateHeaderTable     = [],                   stateHeaders         = M.empty,                   stateIdentifiers     = Set.empty,                   stateNextExample     = 1,                   stateExamples        = M.empty,-                  stateHasChapters     = False,-                  stateMacros          = [],+                  stateMacros          = M.empty,                   stateRstDefaultRole  = "title-reference",                   stateRstCustomRoles  = M.empty,                   stateCaption         = Nothing,                   stateInHtmlBlock     = Nothing,-                  stateMarkdownAttribute = False,-                  stateWarnings        = []}+                  stateFencedDivLevel  = 0,+                  stateContainers      = [],+                  stateLogMessages     = [],+                  stateMarkdownAttribute = False+                  } +-- | Add a log message.+logMessage :: (Stream s m a, HasLogMessages st)+           => LogMessage -> ParserT s st m ()+logMessage msg = updateState (addLogMessage msg)++-- | Report all the accumulated log messages, according to verbosity level.+reportLogMessages :: (PandocMonad m, HasLogMessages st) => ParserT s st m ()+reportLogMessages = do+  msgs <- getLogMessages <$> getState+  mapM_ report msgs+ -- | Succeed only if the extension is enabled. guardEnabled :: (Stream s m a,  HasReaderOptions st) => Extension -> ParserT s st m ()-guardEnabled ext = getOption readerExtensions >>= guard . Set.member ext+guardEnabled ext = getOption readerExtensions >>= guard . extensionEnabled ext  -- | Succeed only if the extension is disabled. guardDisabled :: (Stream s m a, HasReaderOptions st) => Extension -> ParserT s st m ()-guardDisabled ext = getOption readerExtensions >>= guard . not . Set.member ext+guardDisabled ext = getOption readerExtensions >>= guard . not . extensionEnabled ext  -- | Update the position on which the last string ended. updateLastStrPos :: (Stream s m a, HasLastStrPosition st) => ParserT s st m ()@@ -1074,7 +1239,8 @@  type NoteTable = [(String, String)] -type NoteTable' = [(String, F Blocks)]  -- used in markdown reader+type NoteTable' = M.Map String (SourcePos, F Blocks)+-- used in markdown reader  newtype Key = Key String deriving (Show, Read, Eq, Ord) @@ -1091,17 +1257,20 @@ --  with its associated identifier.  If the identifier is null --  and the auto_identifers extension is set, generate a new --  unique identifier, and update the list of identifiers---  in state.-registerHeader :: (Stream s m a, HasReaderOptions st, HasHeaderMap st, HasIdentifierList st)+--  in state.  Issue a warning if an explicit identifier+--  is encountered that duplicates an earlier identifier+--  (explict or automatically generated).+registerHeader :: (Stream s m a, HasReaderOptions st,+                    HasHeaderMap st, HasLogMessages st, HasIdentifierList st)                => Attr -> Inlines -> ParserT s st m Attr registerHeader (ident,classes,kvs) header' = do   ids <- extractIdentifierList <$> getState   exts <- getOption readerExtensions   let insert' = M.insertWith (\_new old -> old)-  if null ident && Ext_auto_identifiers `Set.member` exts+  if null ident && Ext_auto_identifiers `extensionEnabled` exts      then do        let id' = uniqueIdent (B.toList header') ids-       let id'' = if Ext_ascii_identifiers `Set.member` exts+       let id'' = if Ext_ascii_identifiers `extensionEnabled` exts                      then catMaybes $ map toAsciiChar id'                      else id'        updateState $ updateIdentifierList $ Set.insert id'@@ -1109,19 +1278,19 @@        updateState $ updateHeaderMap $ insert' header' id'        return (id'',classes,kvs)      else do-        unless (null ident) $+        unless (null ident) $ do+          when (ident `Set.member` ids) $ do+            pos <- getPosition+            logMessage $ DuplicateIdentifier ident pos+          updateState $ updateIdentifierList $ Set.insert ident           updateState $ updateHeaderMap $ insert' header' ident         return (ident,classes,kvs) --- | Fail unless we're in "smart typography" mode.-failUnlessSmart :: (Stream s m a, HasReaderOptions st) => ParserT s st m ()-failUnlessSmart = getOption readerSmart >>= guard- smartPunctuation :: (HasReaderOptions st, HasLastStrPosition st, HasQuoteContext st m, Stream s m Char)                  => ParserT s st m Inlines                  -> ParserT s st m Inlines smartPunctuation inlineParser = do-  failUnlessSmart+  guardEnabled Ext_smart   choice [ quoted inlineParser, apostrophe, dash, ellipses ]  apostrophe :: Stream s m Char => ParserT s st m Inlines@@ -1195,7 +1364,7 @@ dash :: (HasReaderOptions st, Stream s m Char)      => ParserT s st m Inlines dash = try $ do-  oldDashes <- getOption readerOldDashes+  oldDashes <- extensionEnabled Ext_old_dashes <$> getOption readerExtensions   if oldDashes      then do        char '-'@@ -1241,43 +1410,6 @@       -> ParsecT s st m a token pp pos match = tokenPrim pp (\_ t _ -> pos t) match ------ Macros------- | Parse a \newcommand or \renewcommand macro definition.-macro :: (Stream [Char] m Char, HasMacros st, HasReaderOptions st)-      => ParserT [Char] st m Blocks-macro = do-  apply <- getOption readerApplyMacros-  inp <- getInput-  case parseMacroDefinitions inp of-       ([], _)    -> mzero-       (ms, rest) -> do def' <- count (length inp - length rest) anyChar-                        if apply-                           then do-                             updateState $ \st ->-                               updateMacros (ms ++) st-                             return mempty-                           else return $ rawBlock "latex" def'---- | Apply current macros to string.-applyMacros' :: (HasReaderOptions st, HasMacros st, Stream [Char] m Char)-             => String-             -> ParserT [Char] st m String-applyMacros' target = do-  apply <- getOption readerApplyMacros-  if apply-     then do macros <- extractMacros <$> getState-             return $ applyMacros macros target-     else return target---- | Append a warning to the log.-addWarning :: Maybe SourcePos -> String -> Parser [Char] ParserState ()-addWarning mbpos msg =-  updateState $ \st -> st{-    stateWarnings = (msg ++ maybe "" (\pos -> " " ++ show pos) mbpos) :-                     stateWarnings st } infixr 5 <+?> (<+?>) :: (Monoid a) => ParserT s st m a -> ParserT s st m a -> ParserT s st m a a <+?> b = a >>= flip fmap (try b <|> return mempty) . (<>)@@ -1292,3 +1424,48 @@                Just cl -> words cl                Nothing -> cls     kvs'  = filter (\(k,_) -> k /= "id" || k /= "class") kvs++insertIncludedFile' :: (PandocMonad m, HasIncludeFiles st,+                        Functor mf, Applicative mf, Monad mf)+                    => ParserT [a] st m (mf Blocks)+                    -> (String -> [a])+                    -> [FilePath] -> FilePath+                    -> ParserT [a] st m (mf Blocks)+insertIncludedFile' blocks totoks dirs f = do+  oldPos <- getPosition+  oldInput <- getInput+  containers <- getIncludeFiles <$> getState+  when (f `elem` containers) $+    throwError $ PandocParseError $ "Include file loop at " ++ show oldPos+  updateState $ addIncludeFile f+  mbcontents <- readFileFromDirs dirs f+  contents <- case mbcontents of+                   Just s -> return s+                   Nothing -> do+                     report $ CouldNotLoadIncludeFile f oldPos+                     return ""+  setPosition $ newPos f 1 1+  setInput $ totoks contents+  bs <- blocks+  setInput oldInput+  setPosition oldPos+  updateState dropLatestIncludeFile+  return bs++-- | Parse content of include file as blocks. Circular includes result in an+-- @PandocParseError@.+insertIncludedFile :: (PandocMonad m, HasIncludeFiles st)+                   => ParserT [a] st m Blocks+                   -> (String -> [a])+                   -> [FilePath] -> FilePath+                   -> ParserT [a] st m Blocks+insertIncludedFile blocks totoks dirs f =+  runIdentity <$> insertIncludedFile' (Identity <$> blocks) totoks dirs f++-- | Parse content of include file as future blocks. Circular includes result in+-- an @PandocParseError@.+insertIncludedFileF :: (PandocMonad m, HasIncludeFiles st)+                    => ParserT String st m (Future st Blocks)+                    -> [FilePath] -> FilePath+                    -> ParserT String st m (Future st Blocks)+insertIncludedFileF p = insertIncludedFile' p id
src/Text/Pandoc/Pretty.hs view
@@ -1,6 +1,7 @@-{-# LANGUAGE GeneralizedNewtypeDeriving, CPP #-}+{-# LANGUAGE CPP                        #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-} {--Copyright (C) 2010-2016 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2010-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -19,7 +20,7 @@  {- |    Module      : Text.Pandoc.Pretty-   Copyright   : Copyright (C) 2010-2016 John MacFarlane+   Copyright   : Copyright (C) 2010-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -76,22 +77,24 @@      )  where-import Data.Sequence (Seq, fromList, (<|), singleton, mapWithIndex, viewl, ViewL(..))-import qualified Data.Sequence as Seq+import Control.Monad+import Control.Monad.State.Strict+import Data.Char (isSpace) import Data.Foldable (toList) import Data.List (intersperse)-import Data.String-import Control.Monad.State-import Data.Char (isSpace) import Data.Monoid ((<>))+import Data.Sequence (Seq, ViewL (..), fromList, mapWithIndex, singleton, viewl,+                      (<|))+import qualified Data.Sequence as Seq+import Data.String  data RenderState a = RenderState{-         output       :: [a]        -- ^ In reverse order-       , prefix       :: String-       , usePrefix    :: Bool-       , lineLength   :: Maybe Int  -- ^ 'Nothing' means no wrapping-       , column       :: Int-       , newlines     :: Int        -- ^ Number of preceding newlines+         output     :: [a]        -- ^ In reverse order+       , prefix     :: String+       , usePrefix  :: Bool+       , lineLength :: Maybe Int  -- ^ 'Nothing' means no wrapping+       , column     :: Int+       , newlines   :: Int        -- ^ Number of preceding newlines        }  type DocState a = State (RenderState a) ()@@ -106,10 +109,10 @@        | CarriageReturn        | NewLine        | BlankLines Int  -- number of blank lines-       deriving (Show)+       deriving (Show, Eq)  newtype Doc = Doc { unDoc :: Seq D }-              deriving (Monoid, Show)+              deriving (Monoid, Show, Eq)  instance IsString Doc where   fromString = text@@ -142,11 +145,10 @@ -- between them. infixr 6 <+> (<+>) :: Doc -> Doc -> Doc-(<+>) x y = if isEmpty x-               then y-               else if isEmpty y-                    then x-                    else x <> space <> y+(<+>) x y+  | isEmpty x = y+  | isEmpty y = x+  | otherwise = x <> space <> y  -- | Same as 'cat', but putting breakable spaces between the -- 'Doc's.@@ -156,20 +158,18 @@ infixr 5 $$ -- | @a $$ b@ puts @a@ above @b@. ($$) :: Doc -> Doc -> Doc-($$) x y = if isEmpty x-              then y-              else if isEmpty y-                   then x-                   else x <> cr <> y+($$) x y+  | isEmpty x = y+  | isEmpty y = x+  | otherwise = x <> cr <> y  infixr 5 $+$ -- | @a $+$ b@ puts @a@ above @b@, with a blank line between. ($+$) :: Doc -> Doc -> Doc-($+$) x y = if isEmpty x-               then y-               else if isEmpty y-                    then x-                    else x <> blankline <> y+($+$) x y+  | isEmpty x = y+  | isEmpty y = x+  | otherwise = x <> blankline <> y  -- | List version of '$$'. vcat :: [Doc] -> Doc@@ -184,21 +184,21 @@ nestle (Doc d) = Doc $ go d   where go x = case viewl x of                (BlankLines _ :< rest) -> go rest-               (NewLine :< rest)   -> go rest-               _                   -> x+               (NewLine :< rest)      -> go rest+               _                      -> x  -- | Chomps trailing blank space off of a 'Doc'. chomp :: Doc -> Doc chomp d = Doc (fromList dl')   where dl = toList (unDoc d)         dl' = reverse $ go $ reverse dl-        go [] = []-        go (BreakingSpace : xs) = go xs+        go []                    = []+        go (BreakingSpace : xs)  = go xs         go (CarriageReturn : xs) = go xs-        go (NewLine : xs) = go xs-        go (BlankLines _ : xs) = go xs-        go (Prefixed s d' : xs) = Prefixed s (chomp d') : xs-        go xs = xs+        go (NewLine : xs)        = go xs+        go (BlankLines _ : xs)   = go xs+        go (Prefixed s d' : xs)  = Prefixed s (chomp d') : xs+        go xs                    = xs  outp :: (IsString a) => Int -> String -> DocState a outp off s | off < 0 = do  -- offset < 0 means newline characters@@ -215,9 +215,9 @@ outp off s = do           -- offset >= 0 (0 might be combining char)   st' <- get   let pref = prefix st'-  when (column st' == 0 && usePrefix st' && not (null pref)) $ do+  when (column st' == 0 && usePrefix st' && not (null pref)) $     modify $ \st -> st{ output = fromString pref : output st-                      , column = column st + realLength pref }+                    , column = column st + realLength pref }   modify $ \st -> st{ output = fromString s : output st                     , column = column st + off                     , newlines = 0 }@@ -306,10 +306,10 @@ renderList (BreakingSpace : BlankLines n : xs) = renderList (BlankLines n:xs) renderList (BreakingSpace : BreakingSpace : xs) = renderList (BreakingSpace:xs) renderList (BreakingSpace : xs) = do-  let isText (Text _ _)       = True-      isText (Block _ _)      = True-      isText (AfterBreak _)   = True-      isText _                = False+  let isText (Text _ _)     = True+      isText (Block _ _)    = True+      isText (AfterBreak _) = True+      isText _              = False   let isBreakingSpace BreakingSpace = True       isBreakingSpace _             = False   let xs' = dropWhile isBreakingSpace xs@@ -326,9 +326,7 @@  renderList (AfterBreak s : xs) = do   st <- get-  if newlines st > 0-     then outp (realLength s) s-     else return ()+  when (newlines st > 0) $ outp (realLength s) s   renderList xs  renderList (Block i1 s1 : Block i2 s2  : xs) =@@ -342,7 +340,7 @@   let oldPref = prefix st   case column st - realLength oldPref of         n | n > 0 -> modify $ \s -> s{ prefix = oldPref ++ replicate n ' ' }-        _         -> return ()+        _ -> return ()   renderList $ intersperse CarriageReturn (map (Text 0) lns)   modify $ \s -> s{ prefix = oldPref }   renderList xs@@ -362,10 +360,10 @@           sp xs = if addSpace then (' ' : xs) else xs  offsetOf :: D -> Int-offsetOf (Text o _)       = o-offsetOf (Block w _)      = w-offsetOf BreakingSpace    = 1-offsetOf _                = 0+offsetOf (Text o _)    = o+offsetOf (Block w _)   = w+offsetOf BreakingSpace = 1+offsetOf _             = 0  -- | A literal string. text :: String -> Doc@@ -396,8 +394,8 @@ blankline :: Doc blankline = Doc $ singleton (BlankLines 1) --- | Inserts a blank lines unless they exists already.--- (@blanklines m <> blanklines n@ has the same effect as @blankline (max m n)@.+-- | Inserts blank lines unless they exist already.+-- (@blanklines m <> blanklines n@ has the same effect as @blanklines (max m n)@. blanklines :: Int -> Doc blanklines n = Doc $ singleton (BlankLines n) @@ -430,7 +428,7 @@ nowrap :: Doc -> Doc nowrap doc = Doc $ mapWithIndex replaceSpace $ unDoc doc   where replaceSpace _ BreakingSpace = Text 1 " "-        replaceSpace _ x = x+        replaceSpace _ x             = x  -- | Content to print only if it comes at the beginning of a line, -- to be used e.g. for escaping line-initial `.` in groff man.@@ -440,8 +438,8 @@ -- | Returns the width of a 'Doc'. offset :: Doc -> Int offset d = case map realLength . lines . render Nothing $ d of-                []    -> 0-                os    -> maximum os+                [] -> 0+                os -> maximum os  -- | Returns the minimal width of a 'Doc' when reflowed at breakable spaces. minOffset :: Doc -> Int@@ -466,7 +464,7 @@  block :: (String -> String) -> Int -> Doc -> Doc block filler width d-  | width < 1 && not (isEmpty d) = error "Text.Pandoc.Pretty.block: width < 1"+  | width < 1 && not (isEmpty d) = block filler 1 d   | otherwise                    = Doc $ singleton $ Block width $ map filler                                  $ chop width $ render (Just width) d @@ -554,4 +552,4 @@ -- | Get real length of string, taking into account combining and double-wide -- characters. realLength :: String -> Int-realLength = foldr (\a b -> charWidth a + b) 0+realLength = sum . map charWidth
src/Text/Pandoc/Process.hs view
@@ -1,5 +1,5 @@ {--Copyright (C) 2013-2016 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2013-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -18,7 +18,7 @@  {- |    Module      : Text.Pandoc.Process-   Copyright   : Copyright (C) 2013-2016 John MacFarlane+   Copyright   : Copyright (C) 2013-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -29,22 +29,22 @@ -} module Text.Pandoc.Process (pipeProcess) where-import System.Process-import System.Exit (ExitCode (..))+import Control.Concurrent (forkIO, newEmptyMVar, putMVar, takeMVar) import Control.Exception-import System.IO (hClose, hFlush)-import Control.Concurrent (putMVar, takeMVar, newEmptyMVar, forkIO) import Control.Monad (unless) import qualified Data.ByteString.Lazy as BL+import System.Exit (ExitCode (..))+import System.IO (hClose, hFlush)+import System.Process  {- | Version of 'System.Process.readProcessWithExitCode' that uses lazy bytestrings instead of strings and allows setting environment variables.  @readProcessWithExitCode@ creates an external process, reads its-standard output and standard error strictly, waits until the process-terminates, and then returns the 'ExitCode' of the process,-the standard output, and the standard error.+standard output strictly, waits until the process+terminates, and then returns the 'ExitCode' of the process+and the standard output.  stderr is inherited from the parent.  If an asynchronous exception is thrown to the thread executing @readProcessWithExitCode@, the forked process will be terminated and@@ -57,25 +57,21 @@     -> FilePath                 -- ^ Filename of the executable (see 'proc' for details)     -> [String]                 -- ^ any arguments     -> BL.ByteString            -- ^ standard input-    -> IO (ExitCode,BL.ByteString,BL.ByteString) -- ^ exitcode, stdout, stderr+    -> IO (ExitCode,BL.ByteString) -- ^ exitcode, stdout pipeProcess mbenv cmd args input =     mask $ \restore -> do-      (Just inh, Just outh, Just errh, pid) <- createProcess (proc cmd args)+      (Just inh, Just outh, Nothing, pid) <- createProcess (proc cmd args)                                                    { env     = mbenv,                                                      std_in  = CreatePipe,                                                      std_out = CreatePipe,-                                                     std_err = CreatePipe }+                                                     std_err = Inherit }       flip onException-        (do hClose inh; hClose outh; hClose errh;+        (do hClose inh; hClose outh;             terminateProcess pid; waitForProcess pid) $ restore $ do         -- fork off a thread to start consuming stdout         out <- BL.hGetContents outh         waitOut <- forkWait $ evaluate $ BL.length out -        -- fork off a thread to start consuming stderr-        err <- BL.hGetContents errh-        waitErr <- forkWait $ evaluate $ BL.length err-         -- now write and flush any input         let writeInput = do               unless (BL.null input) $ do@@ -87,15 +83,13 @@          -- wait on the output         waitOut-        waitErr          hClose outh-        hClose errh          -- wait on the process         ex <- waitForProcess pid -        return (ex, out, err)+        return (ex, out)  forkWait :: IO a -> IO (IO a) forkWait a = do
+ src/Text/Pandoc/Readers.hs view
@@ -0,0 +1,157 @@+{-# LANGUAGE FlexibleInstances   #-}+{-# LANGUAGE GADTs               #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-+Copyright (C) 2006-2017 John MacFarlane <jgm@berkeley.edu>++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation; either version 2 of the License, or+(at your option) any later version.++This program is distributed in the hope that it will be useful,+but WITHOUT ANY WARRANTY; without even the implied warranty of+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+GNU General Public License for more details.++You should have received a copy of the GNU General Public License+along with this program; if not, write to the Free Software+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+-}++{- |+   Module      : Text.Pandoc.Readers+   Copyright   : Copyright (C) 2006-2017 John MacFarlane+   License     : GNU GPL, version 2 or above++   Maintainer  : John MacFarlane <jgm@berkeley.edu>+   Stability   : alpha+   Portability : portable++This helper module exports the readers.++Note:  all of the readers assume that the input text has @'\n'@+line endings.  So if you get your input text from a web form,+you should remove @'\r'@ characters using @filter (/='\r')@.++-}++module Text.Pandoc.Readers+  (+    -- * Readers: converting /to/ Pandoc format+    Reader (..)+  , readers+  , readDocx+  , readOdt+  , readMarkdown+  , readCommonMark+  , readCreole+  , readMediaWiki+  , readVimwiki+  , readRST+  , readOrg+  , readLaTeX+  , readHtml+  , readTextile+  , readDocBook+  , readOPML+  , readHaddock+  , readNative+  , readJSON+  , readTWiki+  , readTikiWiki+  , readTxt2Tags+  , readEPUB+  , readMuse+  -- * Miscellaneous+  , getReader+  , getDefaultExtensions+  ) where++import Control.Monad.Except (throwError)+import Data.Aeson+import qualified Data.ByteString.Lazy as BL+import Data.List (intercalate)+import Data.Text (Text)+import Text.Pandoc.Class+import Text.Pandoc.Definition+import Text.Pandoc.Error+import Text.Pandoc.Extensions+import Text.Pandoc.Options+import Text.Pandoc.Readers.CommonMark+import Text.Pandoc.Readers.Creole+import Text.Pandoc.Readers.DocBook+import Text.Pandoc.Readers.Docx+import Text.Pandoc.Readers.EPUB+import Text.Pandoc.Readers.Haddock+import Text.Pandoc.Readers.HTML+import Text.Pandoc.Readers.LaTeX+import Text.Pandoc.Readers.Markdown+import Text.Pandoc.Readers.MediaWiki+import Text.Pandoc.Readers.Muse+import Text.Pandoc.Readers.Native+import Text.Pandoc.Readers.Odt+import Text.Pandoc.Readers.OPML+import Text.Pandoc.Readers.Org+import Text.Pandoc.Readers.RST+import Text.Pandoc.Readers.Textile+import Text.Pandoc.Readers.TikiWiki+import Text.Pandoc.Readers.TWiki+import Text.Pandoc.Readers.Txt2Tags+import Text.Pandoc.Readers.Vimwiki+import Text.Pandoc.Shared (mapLeft)+import qualified Text.Pandoc.UTF8 as UTF8+import Text.Parsec.Error++data Reader m = TextReader (ReaderOptions -> Text -> m Pandoc)+              | ByteStringReader (ReaderOptions -> BL.ByteString -> m Pandoc)++-- | Association list of formats and readers.+readers :: PandocMonad m => [(String, Reader m)]+readers = [ ("native"       , TextReader readNative)+           ,("json"         , TextReader $ \o s ->+                                               case readJSON o s of+                                                 Right doc -> return doc+                                                 Left _ -> throwError $ PandocParseError "JSON parse error")+           ,("markdown"     , TextReader readMarkdown)+           ,("markdown_strict" , TextReader readMarkdown)+           ,("markdown_phpextra" , TextReader readMarkdown)+           ,("markdown_github" , TextReader readMarkdown)+           ,("markdown_mmd",  TextReader readMarkdown)+           ,("commonmark"   , TextReader readCommonMark)+           ,("creole"       , TextReader readCreole)+           ,("gfm"          , TextReader readCommonMark)+           ,("rst"          , TextReader readRST)+           ,("mediawiki"    , TextReader readMediaWiki)+           ,("vimwiki"      , TextReader readVimwiki)+           ,("docbook"      , TextReader readDocBook)+           ,("opml"         , TextReader readOPML)+           ,("org"          , TextReader readOrg)+           ,("textile"      , TextReader readTextile) -- TODO : textile+lhs+           ,("html"         , TextReader readHtml)+           ,("latex"        , TextReader readLaTeX)+           ,("haddock"      , TextReader readHaddock)+           ,("twiki"        , TextReader readTWiki)+           ,("tikiwiki"     , TextReader readTikiWiki)+           ,("docx"         , ByteStringReader readDocx)+           ,("odt"          , ByteStringReader readOdt)+           ,("t2t"          , TextReader readTxt2Tags)+           ,("epub"         , ByteStringReader readEPUB)+           ,("muse"         , TextReader readMuse)+           ]++-- | Retrieve reader, extensions based on formatSpec (format+extensions).+getReader :: PandocMonad m => String -> Either String (Reader m, Extensions)+getReader s =+  case parseFormatSpec s of+       Left e  -> Left $ intercalate "\n" [m | Message m <- errorMessages e]+       Right (readerName, setExts) ->+           case lookup readerName readers of+                   Nothing  -> Left $ "Unknown reader: " ++ readerName+                   Just  r  -> Right (r, setExts $+                                        getDefaultExtensions readerName)++-- | Read pandoc document from JSON format.+readJSON :: ReaderOptions -> Text -> Either PandocError Pandoc+readJSON _ =+  mapLeft PandocParseError . eitherDecode' . BL.fromStrict . UTF8.fromText
src/Text/Pandoc/Readers/CommonMark.hs view
@@ -1,5 +1,5 @@ {--Copyright (C) 2015 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2015-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -18,7 +18,7 @@  {- |    Module      : Text.Pandoc.Readers.CommonMark-   Copyright   : Copyright (C) 2015 John MacFarlane+   Copyright   : Copyright (C) 2015-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -32,48 +32,98 @@ module Text.Pandoc.Readers.CommonMark (readCommonMark) where -import CMark-import Data.Text (unpack, pack)+import CMarkGFM+import Control.Monad.State+import Data.Char (isAlphaNum, isLetter, isSpace, toLower) import Data.List (groupBy)+import qualified Data.Map as Map+import Data.Text (Text, unpack)+import Text.Pandoc.Class (PandocMonad) import Text.Pandoc.Definition+import Text.Pandoc.Emoji (emojis) import Text.Pandoc.Options-import Text.Pandoc.Error+import Text.Pandoc.Shared (stringify)+import Text.Pandoc.Walk (walkM)  -- | Parse a CommonMark formatted string into a 'Pandoc' structure.-readCommonMark :: ReaderOptions -> String -> Either PandocError Pandoc-readCommonMark opts = Right . nodeToPandoc . commonmarkToNode opts' . pack-  where opts' = if readerSmart opts-                   then [optNormalize, optSmart]-                   else [optNormalize]+readCommonMark :: PandocMonad m => ReaderOptions -> Text -> m Pandoc+readCommonMark opts s = return $+  (if enabled Ext_gfm_auto_identifiers opts+      then addHeaderIdentifiers+      else id) $+  nodeToPandoc opts $ commonmarkToNode opts' exts s+  where opts' = [ optSmart | enabled Ext_smart opts ]+        exts = [ extStrikethrough | enabled Ext_strikeout opts ] +++               [ extTable | enabled Ext_pipe_tables opts ] +++               [ extAutolink | enabled Ext_autolink_bare_uris opts ] -nodeToPandoc :: Node -> Pandoc-nodeToPandoc (Node _ DOCUMENT nodes) =-  Pandoc nullMeta $ foldr addBlock [] nodes-nodeToPandoc n =  -- shouldn't happen-  Pandoc nullMeta $ foldr addBlock [] [n]+-- | Returns True if the given extension is enabled.+enabled :: Extension -> ReaderOptions -> Bool+enabled ext opts = ext `extensionEnabled` (readerExtensions opts) -addBlocks :: [Node] -> [Block]-addBlocks = foldr addBlock []+convertEmojis :: String -> String+convertEmojis (':':xs) =+   case break (==':') xs of+        (ys,':':zs) ->+           case Map.lookup ys emojis of+                Just s  -> s ++ convertEmojis zs+                Nothing -> ':' : ys ++ convertEmojis (':':zs)+        _ -> ':':xs+convertEmojis (x:xs) = x : convertEmojis xs+convertEmojis [] = [] -addBlock :: Node -> [Block] -> [Block]-addBlock (Node _ PARAGRAPH nodes) =-  (Para (addInlines nodes) :)-addBlock (Node _ THEMATIC_BREAK _) =+addHeaderIdentifiers :: Pandoc -> Pandoc+addHeaderIdentifiers doc = evalState (walkM addHeaderId doc) mempty++addHeaderId :: Block -> State (Map.Map String Int) Block+addHeaderId (Header lev (_,classes,kvs) ils) = do+  idmap <- get+  let ident = toIdent ils+  ident' <- case Map.lookup ident idmap of+                 Nothing -> do+                   put (Map.insert ident 1 idmap)+                   return ident+                 Just i -> do+                   put (Map.adjust (+ 1) ident idmap)+                   return (ident ++ "-" ++ show i)+  return $ Header lev (ident',classes,kvs) ils+addHeaderId x = return x++toIdent :: [Inline] -> String+toIdent =   map (\c -> if isSpace c then '-' else c)+          . filter (\c -> isLetter c || isAlphaNum c || isSpace c ||+                           c == '_' || c == '-')+          . map toLower . stringify++nodeToPandoc :: ReaderOptions -> Node -> Pandoc+nodeToPandoc opts (Node _ DOCUMENT nodes) =+  Pandoc nullMeta $ foldr (addBlock opts) [] nodes+nodeToPandoc opts n =  -- shouldn't happen+  Pandoc nullMeta $ foldr (addBlock opts) [] [n]++addBlocks :: ReaderOptions -> [Node] -> [Block]+addBlocks opts = foldr (addBlock opts) []++addBlock :: ReaderOptions -> Node -> [Block] -> [Block]+addBlock opts (Node _ PARAGRAPH nodes) =+  (Para (addInlines opts nodes) :)+addBlock _ (Node _ THEMATIC_BREAK _) =   (HorizontalRule :)-addBlock (Node _ BLOCK_QUOTE nodes) =-  (BlockQuote (addBlocks nodes) :)-addBlock (Node _ (HTML_BLOCK t) _) =-  (RawBlock (Format "html") (unpack t) :)+addBlock opts (Node _ BLOCK_QUOTE nodes) =+  (BlockQuote (addBlocks opts nodes) :)+addBlock opts (Node _ (HTML_BLOCK t) _)+  | enabled Ext_raw_html opts = (RawBlock (Format "html") (unpack t) :)+  | otherwise                 = id -- Note:  the cmark parser will never generate CUSTOM_BLOCK, -- so we don't need to handle it:-addBlock (Node _ (CUSTOM_BLOCK _onEnter _onExit) _nodes) =+addBlock _ (Node _ (CUSTOM_BLOCK _onEnter _onExit) _nodes) =   id-addBlock (Node _ (CODE_BLOCK info t) _) =+addBlock _ (Node _ (CODE_BLOCK info t) _) =   (CodeBlock ("", take 1 (words (unpack info)), []) (unpack t) :)-addBlock (Node _ (HEADING lev) nodes) =-  (Header lev ("",[],[]) (addInlines nodes) :)-addBlock (Node _ (LIST listAttrs) nodes) =-  (constructor (map (setTightness . addBlocks . children) nodes) :)+addBlock opts (Node _ (HEADING lev) nodes) =+  (Header lev ("",[],[]) (addInlines opts nodes) :)+addBlock opts (Node _ (LIST listAttrs) nodes) =+  (constructor (map (setTightness . addBlocks opts . children) nodes) :)   where constructor = case listType listAttrs of                        BULLET_LIST  -> BulletList                        ORDERED_LIST -> OrderedList@@ -82,46 +132,108 @@         setTightness = if listTight listAttrs                            then map paraToPlain                            else id-        paraToPlain (Para xs) = Plain (xs)+        paraToPlain (Para xs) = Plain xs         paraToPlain x         = x         delim = case listDelim listAttrs of-                     PERIOD_DELIM  -> Period-                     PAREN_DELIM   -> OneParen-addBlock (Node _ ITEM _) = id -- handled in LIST-addBlock _ = id+                     PERIOD_DELIM -> Period+                     PAREN_DELIM  -> OneParen+addBlock opts (Node _ (TABLE alignments) nodes) =+  (Table [] aligns widths headers rows :)+  where aligns = map fromTableCellAlignment alignments+        fromTableCellAlignment NoAlignment   = AlignDefault+        fromTableCellAlignment LeftAligned   = AlignLeft+        fromTableCellAlignment RightAligned  = AlignRight+        fromTableCellAlignment CenterAligned = AlignCenter+        widths = replicate numcols 0.0+        numcols = if null rows'+                     then 0+                     else maximum $ map length rows'+        rows' = map toRow $ filter isRow nodes+        (headers, rows) = case rows' of+                               (h:rs) -> (h, rs)+                               []     -> ([], [])+        isRow (Node _ TABLE_ROW _) = True+        isRow _                    = False+        isCell (Node _ TABLE_CELL _) = True+        isCell _                     = False+        toRow (Node _ TABLE_ROW ns) = map toCell $ filter isCell ns+        toRow (Node _ t _) = error $ "toRow encountered non-row " ++ show t+        toCell (Node _ TABLE_CELL []) = []+        toCell (Node _ TABLE_CELL (n:ns))+          | isBlockNode n = addBlocks opts (n:ns)+          | otherwise     = [Plain (addInlines opts (n:ns))]+        toCell (Node _ t _) = error $ "toCell encountered non-cell " ++ show t+addBlock _ (Node _ TABLE_ROW _) = id -- handled in TABLE+addBlock _ (Node _ TABLE_CELL _) = id -- handled in TABLE+addBlock _ _ = id +isBlockNode :: Node -> Bool+isBlockNode (Node _ nodetype _) =+  case nodetype of+       DOCUMENT          -> True+       THEMATIC_BREAK    -> True+       PARAGRAPH         -> True+       BLOCK_QUOTE       -> True+       HTML_BLOCK _      -> True+       CUSTOM_BLOCK _ _  -> True+       CODE_BLOCK _ _    -> True+       HEADING _         -> True+       LIST _            -> True+       ITEM              -> True+       TEXT _            -> False+       SOFTBREAK         -> False+       LINEBREAK         -> False+       HTML_INLINE _     -> False+       CUSTOM_INLINE _ _ -> False+       CODE _            -> False+       EMPH              -> False+       STRONG            -> False+       LINK _ _          -> False+       IMAGE _ _         -> False+       STRIKETHROUGH     -> False+       TABLE _           -> False+       TABLE_ROW         -> False+       TABLE_CELL        -> False+ children :: Node -> [Node] children (Node _ _ ns) = ns -addInlines :: [Node] -> [Inline]-addInlines = foldr addInline []+addInlines :: ReaderOptions -> [Node] -> [Inline]+addInlines opts = foldr (addInline opts) [] -addInline :: Node -> [Inline] -> [Inline]-addInline (Node _ (TEXT t) _) = (map toinl clumps ++)+addInline :: ReaderOptions -> Node -> [Inline] -> [Inline]+addInline opts (Node _ (TEXT t) _) = (map toinl clumps ++)   where raw = unpack t         clumps = groupBy samekind raw         samekind ' ' ' ' = True         samekind ' ' _   = False         samekind _   ' ' = False         samekind _  _    = True-        toinl (' ':_)    = Space-        toinl xs         = Str xs-addInline (Node _ LINEBREAK _) = (LineBreak :)-addInline (Node _ SOFTBREAK _) = (SoftBreak :)-addInline (Node _ (HTML_INLINE t) _) =-  (RawInline (Format "html") (unpack t) :)+        toinl (' ':_) = Space+        toinl xs      = Str $ if enabled Ext_emoji opts+                                 then convertEmojis xs+                                 else xs+addInline _ (Node _ LINEBREAK _) = (LineBreak :)+addInline opts (Node _ SOFTBREAK _)+  | enabled Ext_hard_line_breaks opts = (LineBreak :)+  | otherwise                           = (SoftBreak :)+addInline opts (Node _ (HTML_INLINE t) _)+  | enabled Ext_raw_html opts = (RawInline (Format "html") (unpack t) :)+  | otherwise                 = id -- Note:  the cmark parser will never generate CUSTOM_BLOCK, -- so we don't need to handle it:-addInline (Node _ (CUSTOM_INLINE _onEnter _onExit) _nodes) =+addInline _ (Node _ (CUSTOM_INLINE _onEnter _onExit) _nodes) =   id-addInline (Node _ (CODE t) _) =+addInline _ (Node _ (CODE t) _) =   (Code ("",[],[]) (unpack t) :)-addInline (Node _ EMPH nodes) =-  (Emph (addInlines nodes) :)-addInline (Node _ STRONG nodes) =-  (Strong (addInlines nodes) :)-addInline (Node _ (LINK url title) nodes) =-  (Link nullAttr (addInlines nodes) (unpack url, unpack title) :)-addInline (Node _ (IMAGE url title) nodes) =-  (Image nullAttr (addInlines nodes) (unpack url, unpack title) :)-addInline _ = id+addInline opts (Node _ EMPH nodes) =+  (Emph (addInlines opts nodes) :)+addInline opts (Node _ STRONG nodes) =+  (Strong (addInlines opts nodes) :)+addInline opts (Node _ STRIKETHROUGH nodes) =+  (Strikeout (addInlines opts nodes) :)+addInline opts (Node _ (LINK url title) nodes) =+  (Link nullAttr (addInlines opts nodes) (unpack url, unpack title) :)+addInline opts (Node _ (IMAGE url title) nodes) =+  (Image nullAttr (addInlines opts nodes) (unpack url, unpack title) :)+addInline _ _ = id
+ src/Text/Pandoc/Readers/Creole.hs view
@@ -0,0 +1,318 @@+{-+  Copyright (C) 2017 Sascha Wilde <wilde@sha-bang.de>++  partly based on all the other readers, especialy the work by+  John MacFarlane <jgm@berkeley.edu> and+  Alexander Sulfrian <alexander.sulfrian@fu-berlin.de>+  all bugs are solely created by me.++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation; either version 2 of the License, or+(at your option) any later version.++This program is distributed in the hope that it will be useful,+but WITHOUT ANY WARRANTY; without even the implied warranty of+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+GNU General Public License for more details.++You should have received a copy of the GNU General Public License+along with this program; if not, write to the Free Software+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+-}++{- |+   Module      : Text.Pandoc.Readers.Creole+   Copyright   : Copyright (C) 2017 Sascha Wilde+   License     : GNU GPL, version 2 or above++   Maintainer  : Sascha Wilde <wilde@sha-bang.de>+   Stability   : WIP+   Portability : portable++Conversion of creole text to 'Pandoc' document.+-}+module Text.Pandoc.Readers.Creole ( readCreole+                                  ) where++import Control.Monad.Except (guard, liftM2, throwError)+import qualified Data.Foldable as F+import Data.Maybe (fromMaybe)+import Data.Monoid+import Data.Text (Text)+import qualified Data.Text as T+import qualified Text.Pandoc.Builder as B+import Text.Pandoc.Class (PandocMonad (..))+import Text.Pandoc.Definition+import Text.Pandoc.Options+import Text.Pandoc.Parsing hiding (enclosed)+import Text.Pandoc.Shared (crFilter)+++-- | Read creole from an input string and return a Pandoc document.+readCreole :: PandocMonad m+          => ReaderOptions+          -> Text+          -> m Pandoc+readCreole opts s = do+  res <- readWithM parseCreole def{ stateOptions = opts }+             (T.unpack (crFilter s) ++ "\n\n")+  case res of+       Left e  -> throwError e+       Right d -> return d++type CRLParser = ParserT [Char] ParserState++--+-- Utility funcitons+--++(<+>) :: (Monad m, Monoid a) => m a -> m a -> m a+(<+>) = liftM2 (<>)++-- we have to redefine `enclosed' from Text.Pandoc.Parsing, because it+-- assumes, that there can't be a space after the start parser, but+-- with creole this is possible.+enclosed :: (Show end, PandocMonad m) => CRLParser m start   -- ^ start parser+         -> CRLParser m end  -- ^ end parser+         -> CRLParser m a    -- ^ content parser (to be used repeatedly)+         -> CRLParser m [a]+enclosed start end parser = try $ start >> many1Till parser end++--+-- main parser+--++specialChars :: [Char]+specialChars = "*/~{}\\|[]()<>\"'"++parseCreole :: PandocMonad m => CRLParser m Pandoc+parseCreole = do+  bs <- mconcat <$> many block+  spaces+  eof+  return $ B.doc bs+++--+-- block parsers+--++block :: PandocMonad m => CRLParser m B.Blocks+block = do+  res <- mempty <$ skipMany1 blankline+         <|> nowiki+         <|> header+         <|> horizontalRule+         <|> anyList 1+         <|> table+         <|> para+  skipMany blankline+  return res++nowiki :: PandocMonad m => CRLParser m B.Blocks+nowiki = try $ fmap (B.codeBlock . mconcat) (nowikiStart >> manyTill content nowikiEnd)+  where+    content = brackets <|> line+    brackets = try $ option "" ((:[]) <$> newline)+               <+> (char ' ' >> (many (char ' ') <+> string "}}}") <* eol)+    line = option "" ((:[]) <$> newline) <+> manyTill anyChar eol+    eol = lookAhead $ try $ nowikiEnd <|> newline+    nowikiStart = optional newline >> string "{{{" >> skipMany spaceChar >> newline+    nowikiEnd = try $ linebreak >> string "}}}" >> skipMany spaceChar >> newline++header :: PandocMonad m => CRLParser m B.Blocks+header = try $ do+  skipSpaces+  level <-+    fmap length (many1 (char '='))+  guard $ level <= 6+  skipSpaces+  content <- B.str <$> manyTill (noneOf "\n") headerEnd+  return $ B.header level content+  where+    headerEnd = try $ skipSpaces >> many (char '=') >> skipSpaces >> newline++unorderedList :: PandocMonad m => Int -> CRLParser m B.Blocks+unorderedList = list '*' B.bulletList++orderedList :: PandocMonad m => Int -> CRLParser m B.Blocks+orderedList = list '#' B.orderedList++anyList :: PandocMonad m => Int -> CRLParser m B.Blocks+anyList n = unorderedList n <|> orderedList n++anyListItem :: PandocMonad m => Int -> CRLParser m B.Blocks+anyListItem n = listItem '*' n <|> listItem '#' n++list :: PandocMonad m => Char -> ([B.Blocks] -> B.Blocks) -> Int -> CRLParser m B.Blocks+list c f n =+  fmap f (many1 (itemPlusSublist <|> listItem c n))+  where itemPlusSublist = try $ listItem c n <+> anyList (n+1)++listItem :: PandocMonad m => Char -> Int -> CRLParser m B.Blocks+listItem c n =+  fmap (B.plain . B.trimInlines .mconcat) (listStart >> many1Till inline itemEnd)+  where+    listStart = try $ optional newline >> skipSpaces >> count n (char c)+                >> lookAhead (noneOf [c]) >> skipSpaces+    itemEnd = endOfParaElement <|> nextItem n+              <|> if n < 3 then nextItem (n+1)+                  else nextItem (n+1) <|> nextItem (n-1)+    nextItem x = lookAhead $ try $ blankline >> anyListItem x >> return mempty++table :: PandocMonad m => CRLParser m B.Blocks+table = try $ do+  headers <- optionMaybe headerRow+  rows <- many1 row+  return $ B.simpleTable (fromMaybe [mempty] headers) rows+  where+    headerRow = try $ skipSpaces >> many1Till headerCell rowEnd+    headerCell = B.plain . B.trimInlines . mconcat+                 <$> (string "|=" >> many1Till inline cellEnd)+    row = try $ skipSpaces >> many1Till cell rowEnd+    cell = B.plain . B.trimInlines . mconcat+           <$> (char '|' >> many1Till inline cellEnd)+    rowEnd = try $ optional (char '|') >> skipSpaces >> newline+    cellEnd = lookAhead $ try $ char '|' <|> rowEnd++para :: PandocMonad m => CRLParser m B.Blocks+para = fmap (result . mconcat) (many1Till inline endOfParaElement)+ where+   result content   = if F.all (==Space) content+                      then mempty+                      else B.para $ B.trimInlines content++endOfParaElement :: PandocMonad m => CRLParser m ()+endOfParaElement = lookAhead $ endOfInput <|> endOfPara+                   <|> startOfList <|> startOfTable+                   <|> startOfHeader <|> hr <|> startOfNowiki+  where+   endOfInput    = try $ skipMany blankline >> skipSpaces >> eof+   endOfPara     = try $ blankline >> skipMany1 blankline+   startOf      :: PandocMonad m => CRLParser m a -> CRLParser m ()+   startOf p     = try $ blankline >> p >> return mempty+   startOfList   = startOf $ anyList 1+   startOfTable  =startOf table+   startOfHeader = startOf header+   startOfNowiki = startOf nowiki+   hr            = startOf horizontalRule++horizontalRule :: PandocMonad m => CRLParser m B.Blocks+horizontalRule = try $ skipSpaces >> string "----" >> skipSpaces >> newline+                 >> return B.horizontalRule++--+-- inline parsers+--++inline :: PandocMonad m => CRLParser m B.Inlines+inline = choice [ whitespace+                , escapedLink+                , escapedChar+                , link+                , inlineNowiki+                , placeholder+                , image+                , forcedLinebreak+                , bold+                , finalBold+                , italics+                , finalItalics+                , str+                , symbol+                ] <?> "inline"++escapedChar :: PandocMonad m => CRLParser m B.Inlines+escapedChar =+  fmap (B.str . (:[])) (try $ char '~' >> noneOf "\t\n ")++escapedLink :: PandocMonad m => CRLParser m B.Inlines+escapedLink = try $ do+  char '~'+  (orig, _) <- uri+  return $ B.str orig++image :: PandocMonad m => CRLParser m B.Inlines+image = try $ do+  (orig, src) <- wikiImg+  return $ B.image src "" (B.str orig)+  where+    linkSrc = many $ noneOf "|}\n\r\t"+    linkDsc = char '|' >> many (noneOf "}\n\r\t")+    wikiImg = try $ do+      string "{{"+      src <- linkSrc+      dsc <- option "" linkDsc+      string "}}"+      return (dsc, src)++link :: PandocMonad m => CRLParser m B.Inlines+link = try $ do+  (orig, src) <- uriLink <|> wikiLink+  return $ B.link src "" orig+  where+    linkSrc = many $ noneOf "|]\n\r\t"+    linkDsc :: PandocMonad m => String -> CRLParser m B.Inlines+    linkDsc otxt = B.str+                   <$> try (option otxt+                         (char '|' >> many (noneOf "]\n\r\t")))+    linkImg = try $ char '|' >> image+    wikiLink = try $ do+      string "[["+      src <- linkSrc+      dsc <- linkImg <|> linkDsc src+      string "]]"+      return (dsc, src)+    uriLink = try $ do+      (orig, src) <- uri+      return (B.str orig, src)++inlineNowiki :: PandocMonad m => CRLParser m B.Inlines+inlineNowiki = B.code <$> (start >> manyTill (noneOf "\n\r") end)+  where+    start = try $ string "{{{"+    end = try $ string "}}}" >> lookAhead (noneOf "}")++placeholder :: PandocMonad m => CRLParser m B.Inlines+-- The semantics of the placeholder is basicallly implementation+-- dependent, so there is no way to DTRT for all cases.+-- So for now we just drop them.+placeholder = B.text <$> try (string "<<<" >> manyTill anyChar (string ">>>")+              >> return "")++whitespace :: PandocMonad m => CRLParser m B.Inlines+whitespace = lb <|> regsp+  where lb = try $ skipMany spaceChar >> linebreak >> return B.space+        regsp = try $ skipMany1 spaceChar >> return B.space++linebreak :: PandocMonad m => CRLParser m B.Inlines+linebreak = newline >> notFollowedBy newline >> (lastNewline <|> innerNewline)+  where lastNewline  = eof >> return mempty+        innerNewline = return B.space++symbol :: PandocMonad m => CRLParser m B.Inlines+symbol = fmap (B.str . (:[])) (oneOf specialChars)++str :: PandocMonad m => CRLParser m B.Inlines+str = let strChar = noneOf ("\t\n " ++ specialChars) in+        fmap B.str (many1 strChar)++bold :: PandocMonad m => CRLParser m B.Inlines+bold = B.strong . mconcat <$>+       enclosed (string "**") (try $ string "**") inline++italics :: PandocMonad m => CRLParser m B.Inlines+italics = B.emph . mconcat <$>+          enclosed (string "//") (try $ string "//") inline++finalBold :: PandocMonad m => CRLParser m B.Inlines+finalBold = B.strong . mconcat <$>+            try (string "**" >> many1Till inline endOfParaElement)++finalItalics :: PandocMonad m => CRLParser m B.Inlines+finalItalics = B.emph . mconcat <$>+               try (string "//" >> many1Till inline endOfParaElement)++forcedLinebreak :: PandocMonad m => CRLParser m B.Inlines+forcedLinebreak = try $ string "\\\\" >> return B.linebreak
src/Text/Pandoc/Readers/DocBook.hs view
@@ -1,22 +1,22 @@+{-# LANGUAGE ExplicitForAll #-} module Text.Pandoc.Readers.DocBook ( readDocBook ) where-import Data.Char (toUpper)-import Text.Pandoc.Shared (safeRead)-import Text.Pandoc.Options-import Text.Pandoc.Definition-import Text.Pandoc.Builder-import Text.XML.Light-import Text.HTML.TagSoup.Entity (lookupEntity)+import Control.Monad.State.Strict+import Data.Char (isSpace, toUpper)+import Data.Default import Data.Either (rights)+import Data.Foldable (asum) import Data.Generics-import Data.Char (isSpace)-import Control.Monad.State import Data.List (intersperse) import Data.Maybe (fromMaybe)+import Data.Text (Text)+import qualified Data.Text as T+import Text.HTML.TagSoup.Entity (lookupEntity)+import Text.Pandoc.Builder+import Text.Pandoc.Class (PandocMonad)+import Text.Pandoc.Options+import Text.Pandoc.Shared (crFilter, safeRead) import Text.TeXMath (readMathML, writeTeX)-import Text.Pandoc.Error (PandocError)-import Control.Monad.Except-import Data.Default-import Data.Foldable (asum)+import Text.XML.Light  {- @@ -50,7 +50,7 @@ [x] author - The name of an individual author [ ] authorblurb - A short description or note about an author [x] authorgroup - Wrapper for author information when a document has-    multiple authors or collabarators+    multiple authors or collaborators [x] authorinitials - The initials or other short identifier for an author [o] beginpage - The location of a page break in a print version of the document [ ] bibliocoverage - The spatial or temporal coverage of a document@@ -502,7 +502,7 @@ [x] ?asciidoc-br? - line break from asciidoc docbook output -} -type DB = ExceptT PandocError (State DBState)+type DB m = StateT DBState m  data DBState = DBState{ dbSectionLevel :: Int                       , dbQuoteType    :: QuoteType@@ -523,10 +523,12 @@                , dbContent = [] }  -readDocBook :: ReaderOptions -> String -> Either PandocError Pandoc-readDocBook _ inp  = (\blocks -> Pandoc (dbMeta st') (toList . mconcat $ blocks)) <$>  bs-  where (bs , st') = flip runState (def{ dbContent = tree }) . runExceptT . mapM parseBlock $ tree-        tree = normalizeTree . parseXML . handleInstructions $ inp+readDocBook :: PandocMonad m => ReaderOptions -> Text -> m Pandoc+readDocBook _ inp = do+  let tree = normalizeTree . parseXML . handleInstructions+               $ T.unpack $ crFilter inp+  (bs, st') <- flip runStateT (def{ dbContent = tree }) $ mapM parseBlock tree+  return $ Pandoc (dbMeta st') (toList . mconcat $ bs)  -- We treat <?asciidoc-br?> specially (issue #1236), converting it -- to <br/>, since xml-light doesn't parse the instruction correctly.@@ -536,12 +538,12 @@ handleInstructions xs = case break (=='<') xs of                              (ys, [])     -> ys                              ([], '<':zs) -> '<' : handleInstructions zs-                             (ys, zs) -> ys ++ handleInstructions zs+                             (ys, zs)     -> ys ++ handleInstructions zs -getFigure :: Element -> DB Blocks+getFigure :: PandocMonad m => Element -> DB m Blocks getFigure e = do   tit <- case filterChild (named "title") e of-              Just t -> getInlines t+              Just t  -> getInlines t               Nothing -> return mempty   modify $ \st -> st{ dbFigureTitle = tit }   res <- getBlocks e@@ -564,14 +566,12 @@         go xs = xs  convertEntity :: String -> String-convertEntity e = maybe (map toUpper e) id (lookupEntity e)+convertEntity e = Data.Maybe.fromMaybe (map toUpper e) (lookupEntity e)  -- convenience function to get an attribute value, defaulting to "" attrValue :: String -> Element -> String attrValue attr elt =-  case lookupAttrBy (\x -> qName x == attr) (elAttribs elt) of-    Just z  -> z-    Nothing -> ""+  fromMaybe "" (lookupAttrBy (\x -> qName x == attr) (elAttribs elt))  -- convenience function named :: String -> Element -> Bool@@ -579,20 +579,20 @@  -- -acceptingMetadata :: DB a -> DB a+acceptingMetadata :: PandocMonad m => DB m a -> DB m a acceptingMetadata p = do   modify (\s -> s { dbAcceptsMeta = True } )   res <- p   modify (\s -> s { dbAcceptsMeta = False })   return res -checkInMeta :: Monoid a => DB () -> DB a+checkInMeta :: (PandocMonad m, Monoid a) => DB m () -> DB m a checkInMeta p = do   accepts <- dbAcceptsMeta <$> get   when accepts p   return mempty -addMeta :: ToMetaValue a => String -> a -> DB ()+addMeta :: PandocMonad m => ToMetaValue a => String -> a -> DB m () addMeta field val = modify (setMeta field val)  instance HasMeta DBState where@@ -631,7 +631,7 @@ -- function that is used by both mediaobject (in parseBlock) -- and inlinemediaobject (in parseInline) -- A DocBook mediaobject is a wrapper around a set of alternative presentations-getMediaobject :: Element -> DB Inlines+getMediaobject :: PandocMonad m => Element -> DB m Inlines getMediaobject e = do   (imageUrl, attr) <-     case filterChild (named "imageobject") e of@@ -651,18 +651,20 @@                                             || named "textobject" x                                             || named "alt" x) el of                         Nothing -> return mempty-                        Just z  -> mconcat <$> (mapM parseInline $ elContent z)+                        Just z  -> mconcat <$>+                                         mapM parseInline (elContent z)   figTitle <- gets dbFigureTitle   let (caption, title) = if isNull figTitle                             then (getCaption e, "")                             else (return figTitle, "fig:")-  liftM (imageWith attr imageUrl title) caption+  fmap (imageWith attr imageUrl title) caption -getBlocks :: Element -> DB Blocks-getBlocks e =  mconcat <$> (mapM parseBlock $ elContent e)+getBlocks :: PandocMonad m => Element -> DB m Blocks+getBlocks e =  mconcat <$>+                 mapM parseBlock (elContent e)  -parseBlock :: Content -> DB Blocks+parseBlock :: PandocMonad m => Content -> DB m Blocks parseBlock (Text (CData CDataRaw _ _)) = return mempty -- DOCTYPE parseBlock (Text (CData _ s _)) = if all isSpace s                                      then return mempty@@ -795,15 +797,16 @@                     return $ p <> b <> x          codeBlockWithLang = do            let classes' = case attrValue "language" e of-                                ""   -> []-                                x    -> [x]+                                "" -> []+                                x  -> [x]            return $ codeBlockWith (attrValue "id" e, classes', [])                   $ trimNl $ strContentRecursive e          parseBlockquote = do             attrib <- case filterChild (named "attribution") e of                              Nothing  -> return mempty                              Just z   -> (para . (str "— " <>) . mconcat)-                                         <$> (mapM parseInline $ elContent z)+                                         <$>+                                              mapM parseInline (elContent z)             contents <- getBlocks e             return $ blockQuote (contents <> attrib)          listitems = mapM getBlocks $ filterChildren (named "listitem") e@@ -868,11 +871,11 @@                                                       || x == '.') w                                                 Nothing -> 0 :: Double                       let numrows = case bodyrows of-                                         []   -> 0-                                         xs   -> maximum $ map length xs+                                         [] -> 0+                                         xs -> maximum $ map length xs                       let aligns = case colspecs of-                                     []  -> replicate numrows AlignDefault-                                     cs  -> map toAlignment cs+                                     [] -> replicate numrows AlignDefault+                                     cs -> map toAlignment cs                       let widths = case colspecs of                                      []  -> replicate numrows 0                                      cs  -> let ws = map toWidth cs@@ -892,7 +895,7 @@                      headerText <- case filterChild (named "title") e `mplus`                                         (filterChild (named "info") e >>=                                             filterChild (named "title")) of-                                      Just t -> getInlines t+                                      Just t  -> getInlines t                                       Nothing -> return mempty                      modify $ \st -> st{ dbSectionLevel = n }                      b <- getBlocks e@@ -902,8 +905,9 @@          lineItems = mapM getInlines $ filterChildren (named "line") e          metaBlock = acceptingMetadata (getBlocks e) >> return mempty -getInlines :: Element -> DB Inlines-getInlines e' = (trimInlines . mconcat) <$> (mapM parseInline $ elContent e')+getInlines :: PandocMonad m => Element -> DB m Inlines+getInlines e' = (trimInlines . mconcat) <$>+                 mapM parseInline (elContent e')  strContentRecursive :: Element -> String strContentRecursive = strContent .@@ -913,10 +917,10 @@ elementToStr (Elem e') = Text $ CData CDataText (strContentRecursive e') Nothing elementToStr x = x -parseInline :: Content -> DB Inlines+parseInline :: PandocMonad m => Content -> DB m Inlines parseInline (Text (CData _ s _)) = return $ text s parseInline (CRef ref) =-  return $ maybe (text $ map toUpper ref) (text) $ lookupEntity ref+  return $ maybe (text $ map toUpper ref) text $ lookupEntity ref parseInline (Elem e) =   case qName (elName e) of         "equation" -> equation displayMath@@ -957,8 +961,10 @@         "userinput" -> codeWithLang         "varargs" -> return $ code "(...)"         "keycap" -> return (str $ strContent e)-        "keycombo" -> keycombo <$> (mapM parseInline $ elContent e)-        "menuchoice" -> menuchoice <$> (mapM parseInline $+        "keycombo" -> keycombo <$>+                         mapM parseInline (elContent e)+        "menuchoice" -> menuchoice <$>+                         mapM parseInline (                                         filter isGuiMenu $ elContent e)         "xref" -> do             content <- dbContent <$> get@@ -977,17 +983,18 @@              ils <- innerInlines              let href = case findAttr (QName "href" (Just "http://www.w3.org/1999/xlink") Nothing) e of                                Just h -> h-                               _      -> ('#' : attrValue "linkend" e)+                               _      -> '#' : attrValue "linkend" e              let ils' = if ils == mempty then str href else ils              let attr = (attrValue "id" e, words $ attrValue "role" e, [])              return $ linkWith attr href "" ils'         "foreignphrase" -> emph <$> innerInlines         "emphasis" -> case attrValue "role" e of-                             "bold"   -> strong <$> innerInlines-                             "strong" -> strong <$> innerInlines+                             "bold"          -> strong <$> innerInlines+                             "strong"        -> strong <$> innerInlines                              "strikethrough" -> strikeout <$> innerInlines-                             _        -> emph <$> innerInlines-        "footnote" -> (note . mconcat) <$> (mapM parseBlock $ elContent e)+                             _               -> emph <$> innerInlines+        "footnote" -> (note . mconcat) <$>+                         mapM parseBlock (elContent e)         "title" -> return mempty         "affiliation" -> return mempty         -- Note: this isn't a real docbook tag; it's what we convert@@ -996,7 +1003,7 @@         "br" -> return linebreak         _          -> innerInlines    where innerInlines = (trimInlines . mconcat) <$>-                          (mapM parseInline $ elContent e)+                          mapM parseInline (elContent e)          equation constructor = return $ mconcat $            map (constructor . writeTeX)            $ rights
src/Text/Pandoc/Readers/Docx.hs view
@@ -1,7 +1,9 @@-{-# LANGUAGE PatternGuards, OverloadedStrings, CPP #-}+{-# LANGUAGE CPP               #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternGuards     #-}  {--Copyright (C) 2014-2016 Jesse Rosenthal <jrosenthal@jhu.edu>+Copyright (C) 2014-2017 Jesse Rosenthal <jrosenthal@jhu.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -20,7 +22,7 @@  {- |    Module      : Text.Pandoc.Readers.Docx-   Copyright   : Copyright (C) 2014-2016 Jesse Rosenthal+   Copyright   : Copyright (C) 2014-2017 Jesse Rosenthal    License     : GNU GPL, version 2 or above     Maintainer  : Jesse Rosenthal <jrosenthal@jhu.edu>@@ -50,12 +52,13 @@ * Inlines    - [X] Str-  - [X] Emph (italics and underline both read as Emph)+  - [X] Emph   - [X] Strong   - [X] Strikeout   - [X] Superscript   - [X] Subscript   - [X] SmallCaps+  - [-] Underline (was previously converted to Emph)   - [ ] Quoted   - [ ] Cite   - [X] Code (styled with `VerbatimChar`)@@ -64,64 +67,60 @@   - [X] Math   - [X] Link (links to an arbitrary bookmark create a span with the target as         id and "anchor" class)-  - [X] Image +  - [X] Image   - [X] Note (Footnotes and Endnotes are silently combined.) -}  module Text.Pandoc.Readers.Docx-       ( readDocxWithWarnings-       , readDocx+       ( readDocx        ) where  import Codec.Archive.Zip-import Text.Pandoc.Definition-import Text.Pandoc.Options+import Control.Monad.Reader+import Control.Monad.State.Strict+import qualified Data.ByteString.Lazy as B+import Data.Default (Default)+import Data.List (delete, intersect)+import qualified Data.Map as M+import Data.Sequence (ViewL (..), viewl)+import qualified Data.Sequence as Seq+import qualified Data.Set as Set import Text.Pandoc.Builder-import Text.Pandoc.Walk-import Text.Pandoc.Readers.Docx.Parse-import Text.Pandoc.Readers.Docx.Lists+-- import Text.Pandoc.Definition+import Text.Pandoc.MediaBag (MediaBag)+import Text.Pandoc.Options import Text.Pandoc.Readers.Docx.Combine+import Text.Pandoc.Readers.Docx.Lists+import Text.Pandoc.Readers.Docx.Parse import Text.Pandoc.Shared-import Text.Pandoc.MediaBag (insertMedia, MediaBag)-import Data.List (delete, intersect)+import Text.Pandoc.Walk import Text.TeXMath (writeTeX)-import Data.Default (Default)-import qualified Data.ByteString.Lazy as B-import qualified Data.Map as M-import qualified Data.Set as Set-import Control.Monad.Reader-import Control.Monad.State-import Data.Sequence (ViewL(..), viewl)-import qualified Data.Sequence as Seq (null) #if !(MIN_VERSION_base(4,8,0)) import Data.Traversable (traverse) #endif-+import Control.Monad.Except (throwError)+import Text.Pandoc.Class (PandocMonad)+import qualified Text.Pandoc.Class as P import Text.Pandoc.Error-import Control.Monad.Except+import Text.Pandoc.Logging -readDocxWithWarnings :: ReaderOptions-                     -> B.ByteString-                     -> Either PandocError (Pandoc, MediaBag, [String])-readDocxWithWarnings opts bytes+readDocx :: PandocMonad m+         => ReaderOptions+         -> B.ByteString+         -> m Pandoc+readDocx opts bytes   | Right archive <- toArchiveOrFail bytes   , Right (docx, parserWarnings) <- archiveToDocxWithWarnings archive = do-      (meta, blks, mediaBag, warnings) <- docxToOutput opts docx-      return (Pandoc meta blks, mediaBag, parserWarnings ++ warnings)-readDocxWithWarnings _ _ =-  Left (ParseFailure "couldn't parse docx file")--readDocx :: ReaderOptions-         -> B.ByteString-         -> Either PandocError (Pandoc, MediaBag)-readDocx opts bytes = do-  (pandoc, mediaBag, _) <- readDocxWithWarnings opts bytes-  return (pandoc, mediaBag)+      mapM_ (P.report . DocxParserWarning) parserWarnings+      (meta, blks) <- docxToOutput opts docx+      return $ Pandoc meta blks+readDocx _ _ =+  throwError $ PandocSomeError "couldn't parse docx file"  data DState = DState { docxAnchorMap :: M.Map String String-                     , docxMediaBag      :: MediaBag-                     , docxDropCap       :: Inlines-                     , docxWarnings      :: [String]+                     , docxMediaBag  :: MediaBag+                     , docxDropCap   :: Inlines+                     , docxWarnings  :: [String]                      }  instance Default DState where@@ -131,21 +130,16 @@                , docxWarnings  = []                } -data DEnv = DEnv { docxOptions  :: ReaderOptions+data DEnv = DEnv { docxOptions       :: ReaderOptions                  , docxInHeaderBlock :: Bool }  instance Default DEnv where   def = DEnv def False -type DocxContext = ExceptT PandocError (ReaderT DEnv (State DState))--evalDocxContext :: DocxContext a -> DEnv -> DState -> Either PandocError a-evalDocxContext ctx env st = flip evalState st . flip runReaderT env . runExceptT $ ctx+type DocxContext m = ReaderT DEnv (StateT DState m) -addDocxWarning :: String -> DocxContext ()-addDocxWarning msg = do-  warnings <- gets docxWarnings-  modify $ \s -> s {docxWarnings = msg : warnings}+evalDocxContext :: PandocMonad m => DocxContext m a -> DEnv -> DState -> m a+evalDocxContext ctx env st = flip evalStateT st $flip runReaderT env ctx  -- This is empty, but we put it in for future-proofing. spansToKeep :: [String]@@ -162,7 +156,7 @@                         , ("Abstract", "abstract")]  sepBodyParts :: [BodyPart] -> ([BodyPart], [BodyPart])-sepBodyParts = span (\bp -> (isMetaPar bp || isEmptyPar bp))+sepBodyParts = span (\bp -> isMetaPar bp || isEmptyPar bp)  isMetaPar :: BodyPart -> Bool isMetaPar (Paragraph pPr _) =@@ -174,12 +168,12 @@   all isEmptyParPart parParts   where     isEmptyParPart (PlainRun (Run _ runElems)) = all isEmptyElem runElems-    isEmptyParPart _ = False+    isEmptyParPart _                           = False     isEmptyElem (TextRun s) = trim s == ""     isEmptyElem _           = True isEmptyPar _ = False -bodyPartsToMeta' :: [BodyPart] -> DocxContext (M.Map String MetaValue)+bodyPartsToMeta' :: PandocMonad m => [BodyPart] -> DocxContext m (M.Map String MetaValue) bodyPartsToMeta' [] = return M.empty bodyPartsToMeta' (bp : bps)   | (Paragraph pPr parParts) <- bp@@ -189,13 +183,13 @@     remaining <- bodyPartsToMeta' bps     let       f (MetaInlines ils) (MetaInlines ils') = MetaBlocks [Para ils, Para ils']-      f (MetaInlines ils) (MetaBlocks blks) = MetaBlocks ((Para ils) : blks)+      f (MetaInlines ils) (MetaBlocks blks) = MetaBlocks (Para ils : blks)       f m (MetaList mv) = MetaList (m : mv)       f m n             = MetaList [m, n]     return $ M.insertWith f metaField (MetaInlines (toList inlines)) remaining bodyPartsToMeta' (_ : bps) = bodyPartsToMeta' bps -bodyPartsToMeta :: [BodyPart] -> DocxContext Meta+bodyPartsToMeta :: PandocMonad m => [BodyPart] -> DocxContext m Meta bodyPartsToMeta bps = do   mp <- bodyPartsToMeta' bps   let mp' =@@ -208,7 +202,7 @@ fixAuthors (MetaBlocks blks) =   MetaList $ map g $ filter f blks     where f (Para _) = True-          f _          = False+          f _        = False           g (Para ils) = MetaInlines ils           g _          = MetaInlines [] fixAuthors mv = mv@@ -220,28 +214,28 @@ codeDivs = ["SourceCode"]  runElemToInlines :: RunElem -> Inlines-runElemToInlines (TextRun s) = text s-runElemToInlines (LnBrk) = linebreak-runElemToInlines (Tab) = space-runElemToInlines (SoftHyphen) = text "\xad"-runElemToInlines (NoBreakHyphen) = text "\x2011"+runElemToInlines (TextRun s)   = text s+runElemToInlines LnBrk         = linebreak+runElemToInlines Tab           = space+runElemToInlines SoftHyphen    = text "\xad"+runElemToInlines NoBreakHyphen = text "\x2011"  runElemToString :: RunElem -> String-runElemToString (TextRun s) = s-runElemToString (LnBrk) = ['\n']-runElemToString (Tab) = ['\t']-runElemToString (SoftHyphen) = ['\xad']-runElemToString (NoBreakHyphen) = ['\x2011']+runElemToString (TextRun s)   = s+runElemToString LnBrk         = ['\n']+runElemToString Tab           = ['\t']+runElemToString SoftHyphen    = ['\xad']+runElemToString NoBreakHyphen = ['\x2011']  runToString :: Run -> String runToString (Run _ runElems) = concatMap runElemToString runElems-runToString _ = ""+runToString _                = ""  parPartToString :: ParPart -> String-parPartToString (PlainRun run) = runToString run+parPartToString (PlainRun run)             = runToString run parPartToString (InternalHyperLink _ runs) = concatMap runToString runs parPartToString (ExternalHyperLink _ runs) = concatMap runToString runs-parPartToString _ = ""+parPartToString _                          = ""  blacklistedCharStyles :: [String] blacklistedCharStyles = ["Hyperlink"]@@ -280,24 +274,24 @@   , s `elem` spansToKeep =     let rPr' = rPr{rStyle = Nothing}     in-     (spanWith ("", [s], [])) . (runStyleToTransform rPr')+     spanWith ("", [s], []) . runStyleToTransform rPr'   | Just True <- isItalic rPr =-      emph . (runStyleToTransform rPr {isItalic = Nothing})+      emph . runStyleToTransform rPr {isItalic = Nothing}   | Just True <- isBold rPr =-      strong . (runStyleToTransform rPr {isBold = Nothing})+      strong . runStyleToTransform rPr {isBold = Nothing}   | Just True <- isSmallCaps rPr =-      smallcaps . (runStyleToTransform rPr {isSmallCaps = Nothing})+      smallcaps . runStyleToTransform rPr {isSmallCaps = Nothing}   | Just True <- isStrike rPr =-      strikeout . (runStyleToTransform rPr {isStrike = Nothing})+      strikeout . runStyleToTransform rPr {isStrike = Nothing}   | Just SupScrpt <- rVertAlign rPr =-      superscript . (runStyleToTransform rPr {rVertAlign = Nothing})+      superscript . runStyleToTransform rPr {rVertAlign = Nothing}   | Just SubScrpt <- rVertAlign rPr =-      subscript . (runStyleToTransform rPr {rVertAlign = Nothing})+      subscript . runStyleToTransform rPr {rVertAlign = Nothing}   | Just "single" <- rUnderline rPr =-      emph . (runStyleToTransform rPr {rUnderline = Nothing})+      underlineSpan . runStyleToTransform rPr {rUnderline = Nothing}   | otherwise = id -runToInlines :: Run -> DocxContext Inlines+runToInlines :: PandocMonad m => Run -> DocxContext m Inlines runToInlines (Run rs runElems)   | Just (s, _) <- rStyle rs   , s `elem` codeStyles =@@ -312,14 +306,13 @@     let ils = smushInlines (map runElemToInlines runElems)     return $ (runStyleToTransform $ resolveDependentRunStyle rs) ils runToInlines (Footnote bps) = do-  blksList <- smushBlocks <$> (mapM bodyPartToBlocks bps)+  blksList <- smushBlocks <$> mapM bodyPartToBlocks bps   return $ note blksList runToInlines (Endnote bps) = do-  blksList <- smushBlocks <$> (mapM bodyPartToBlocks bps)+  blksList <- smushBlocks <$> mapM bodyPartToBlocks bps   return $ note blksList runToInlines (InlineDrawing fp title alt bs ext) = do-  mediaBag <- gets docxMediaBag-  modify $ \s -> s { docxMediaBag = insertMedia fp Nothing bs mediaBag }+  (lift . lift) $ P.insertMedia fp Nothing bs   return $ imageWith (extentToAttr ext) fp title $ text alt runToInlines InlineChart = return $ spanWith ("", ["chart"], []) $ text "[CHART]" @@ -330,18 +323,19 @@     showDim d = show (d / 914400) ++ "in" extentToAttr _ = nullAttr -blocksToInlinesWarn :: String -> Blocks -> DocxContext Inlines+blocksToInlinesWarn :: PandocMonad m => String -> Blocks -> DocxContext m Inlines blocksToInlinesWarn cmtId blks = do   let blkList = toList blks       notParaOrPlain :: Block -> Bool-      notParaOrPlain (Para _) = False+      notParaOrPlain (Para _)  = False       notParaOrPlain (Plain _) = False-      notParaOrPlain _ = True-  when (not $ null $ filter notParaOrPlain blkList)-    (addDocxWarning $ "Docx comment " ++ cmtId ++ " will not retain formatting")+      notParaOrPlain _         = True+  unless (null $ filter notParaOrPlain blkList) $+    lift $ P.report $ DocxParserWarning $+      "Docx comment " ++ cmtId ++ " will not retain formatting"   return $ fromList $ blocksToInlines blkList -parPartToInlines :: ParPart -> DocxContext Inlines+parPartToInlines :: PandocMonad m => ParPart -> DocxContext m Inlines parPartToInlines (PlainRun r) = runToInlines r parPartToInlines (Insertion _ author date runs) = do   opts <- asks docxOptions@@ -396,17 +390,16 @@     -- are not defined in pandoc, it seems like a necessary evil to     -- avoid an extra pass.     let newAnchor =-          if not inHdrBool && anchor `elem` (M.elems anchorMap)+          if not inHdrBool && anchor `elem` M.elems anchorMap           then uniqueIdent [Str anchor] (Set.fromList $ M.elems anchorMap)           else anchor     unless inHdrBool       (modify $ \s -> s { docxAnchorMap = M.insert anchor newAnchor anchorMap})     return $ spanWith (newAnchor, ["anchor"], []) mempty parPartToInlines (Drawing fp title alt bs ext) = do-  mediaBag <- gets docxMediaBag-  modify $ \s -> s { docxMediaBag = insertMedia fp Nothing bs mediaBag }+  (lift . lift) $ P.insertMedia fp Nothing bs   return $ imageWith (extentToAttr ext) fp title $ text alt-parPartToInlines Chart = do+parPartToInlines Chart =   return $ spanWith ("", ["chart"], []) $ text "[CHART]" parPartToInlines (InternalHyperLink anchor runs) = do   ils <- smushInlines <$> mapM runToInlines runs@@ -414,8 +407,10 @@ parPartToInlines (ExternalHyperLink target runs) = do   ils <- smushInlines <$> mapM runToInlines runs   return $ link target "" ils-parPartToInlines (PlainOMath exps) = do+parPartToInlines (PlainOMath exps) =   return $ math $ writeTeX exps+parPartToInlines (SmartTag runs) = do+  smushInlines <$> mapM runToInlines runs  isAnchorSpan :: Inline -> Bool isAnchorSpan (Span (_, classes, kvs) _) =@@ -426,10 +421,10 @@ dummyAnchors :: [String] dummyAnchors = ["_GoBack"] -makeHeaderAnchor :: Blocks -> DocxContext Blocks+makeHeaderAnchor :: PandocMonad m => Blocks -> DocxContext m Blocks makeHeaderAnchor bs = traverse makeHeaderAnchor' bs -makeHeaderAnchor' :: Block -> DocxContext Block+makeHeaderAnchor' :: PandocMonad m => Block -> DocxContext m Block -- If there is an anchor already there (an anchor span in the header, -- to be exact), we rename and associate the new id with the old one. makeHeaderAnchor' (Header n (ident, classes, kvs) ils)@@ -458,27 +453,28 @@ -- Rewrite a standalone paragraph block as a plain singleParaToPlain :: Blocks -> Blocks singleParaToPlain blks-  | (Para (ils) :< seeq) <- viewl $ unMany blks+  | (Para ils :< seeq) <- viewl $ unMany blks   , Seq.null seeq =       singleton $ Plain ils singleParaToPlain blks = blks -cellToBlocks :: Cell -> DocxContext Blocks+cellToBlocks :: PandocMonad m => Cell -> DocxContext m Blocks cellToBlocks (Cell bps) = do   blks <- smushBlocks <$> mapM bodyPartToBlocks bps   return $ fromList $ blocksToDefinitions $ blocksToBullets $ toList blks -rowToBlocksList :: Row -> DocxContext [Blocks]+rowToBlocksList :: PandocMonad m => Row -> DocxContext m [Blocks] rowToBlocksList (Row cells) = do   blksList <- mapM cellToBlocks cells   return $ map singleParaToPlain blksList -trimLineBreaks :: [Inline] -> [Inline]-trimLineBreaks [] = []-trimLineBreaks (LineBreak : ils) = trimLineBreaks ils-trimLineBreaks ils-  | (LineBreak : ils') <- reverse ils = trimLineBreaks (reverse ils')-trimLineBreaks ils = ils+-- like trimInlines, but also take out linebreaks+trimSps :: Inlines -> Inlines+trimSps (Many ils) = Many $ Seq.dropWhileL isSp $Seq.dropWhileR isSp ils+  where isSp Space     = True+        isSp SoftBreak = True+        isSp LineBreak = True+        isSp _         = False  parStyleToTransform :: ParagraphStyle -> (Blocks -> Blocks) parStyleToTransform pPr@@ -486,17 +482,17 @@   , c `elem` divsToKeep =     let pPr' = pPr { pStyle = cs }     in-     (divWith ("", [c], [])) . (parStyleToTransform pPr')+     divWith ("", [c], []) . parStyleToTransform pPr'   | (c:cs) <- pStyle pPr,     c `elem` listParagraphDivs =       let pPr' = pPr { pStyle = cs, indentation = Nothing}       in-       (divWith ("", [c], [])) . (parStyleToTransform pPr')+       divWith ("", [c], []) . parStyleToTransform pPr'   | (_:cs) <- pStyle pPr   , Just True <- pBlockQuote pPr =     let pPr' = pPr { pStyle = cs }     in-     blockQuote . (parStyleToTransform pPr')+     blockQuote . parStyleToTransform pPr'   | (_:cs) <- pStyle pPr =       let pPr' = pPr { pStyle = cs}       in@@ -507,18 +503,18 @@     let pPr' = pPr { indentation = Nothing }     in      case (left - hang) > 0 of-       True -> blockQuote . (parStyleToTransform pPr')+       True  -> blockQuote . (parStyleToTransform pPr')        False -> parStyleToTransform pPr'   | null (pStyle pPr),     Just left <- indentation pPr >>= leftParIndent =       let pPr' = pPr { indentation = Nothing }       in        case left > 0 of-         True -> blockQuote . (parStyleToTransform pPr')+         True  -> blockQuote . (parStyleToTransform pPr')          False -> parStyleToTransform pPr' parStyleToTransform _ = id -bodyPartToBlocks :: BodyPart -> DocxContext Blocks+bodyPartToBlocks :: PandocMonad m => BodyPart -> DocxContext m Blocks bodyPartToBlocks (Paragraph pPr parparts)   | not $ null $ codeDivs `intersect` (pStyle pPr) =     return@@ -526,13 +522,12 @@     $ codeBlock     $ concatMap parPartToString parparts   | Just (style, n) <- pHeading pPr = do-    ils <- local (\s-> s{docxInHeaderBlock=True}) $+    ils <-local (\s-> s{docxInHeaderBlock=True})            (smushInlines <$> mapM parPartToInlines parparts)     makeHeaderAnchor $       headerWith ("", delete style (pStyle pPr), []) n ils   | otherwise = do-    ils <- smushInlines <$> mapM parPartToInlines parparts >>=-           (return . fromList . trimLineBreaks . normalizeSpaces . toList)+    ils <- (trimSps . smushInlines) <$> mapM parPartToInlines parparts     dropIls <- gets docxDropCap     let ils' = dropIls <> ils     if dropCap pPr@@ -541,7 +536,7 @@       else do modify $ \s -> s { docxDropCap = mempty }               return $ case isNull ils' of                 True -> mempty-                _ -> parStyleToTransform pPr $ para ils'+                _    -> parStyleToTransform pPr $ para ils' bodyPartToBlocks (ListItem pPr numId lvl (Just levelInfo) parparts) = do   let     kvs = case levelInfo of@@ -549,7 +544,7 @@                                    , ("num-id", numId)                                    , ("format", fmt)                                    , ("text", txt)-                                   , ("start", (show start))+                                   , ("start", show start)                                    ]        (_, fmt, txt, Nothing)    -> [ ("level", lvl)@@ -559,8 +554,8 @@                                    ]   blks <- bodyPartToBlocks (Paragraph pPr parparts)   return $ divWith ("", ["list-item"], kvs) blks-bodyPartToBlocks (ListItem pPr _ _ _ parparts) = -  let pPr' = pPr {pStyle = "ListParagraph": (pStyle pPr)}+bodyPartToBlocks (ListItem pPr _ _ _ parparts) =+  let pPr' = pPr {pStyle = "ListParagraph": pStyle pPr}   in     bodyPartToBlocks $ Paragraph pPr' parparts bodyPartToBlocks (Tbl _ _ _ []) =@@ -572,12 +567,12 @@              | otherwise -> (Just r, rs)         False -> (Nothing, r:rs) -  cells <- mapM rowToBlocksList rows        +  cells <- mapM rowToBlocksList rows    let width = case cells of         r':_ -> length r'         -- shouldn't happen-        []   -> 0               +        []   -> 0    hdrCells <- case hdr of     Just r' -> rowToBlocksList r'@@ -592,36 +587,34 @@       widths = replicate width 0 :: [Double]    return $ table caption (zip alignments widths) hdrCells cells-bodyPartToBlocks (OMathPara e) = do+bodyPartToBlocks (OMathPara e) =   return $ para $ displayMath (writeTeX e)   -- replace targets with generated anchors.-rewriteLink' :: Inline -> DocxContext Inline+rewriteLink' :: PandocMonad m => Inline -> DocxContext m Inline rewriteLink' l@(Link attr ils ('#':target, title)) = do   anchorMap <- gets docxAnchorMap   return $ case M.lookup target anchorMap of-    Just newTarget -> (Link attr ils ('#':newTarget, title))+    Just newTarget -> Link attr ils ('#':newTarget, title)     Nothing        -> l rewriteLink' il = return il -rewriteLinks :: [Block] -> DocxContext [Block]+rewriteLinks :: PandocMonad m => [Block] -> DocxContext m [Block] rewriteLinks = mapM (walkM rewriteLink') -bodyToOutput :: Body -> DocxContext (Meta, [Block], MediaBag, [String])+bodyToOutput :: PandocMonad m => Body -> DocxContext m (Meta, [Block]) bodyToOutput (Body bps) = do   let (metabps, blkbps) = sepBodyParts bps   meta <- bodyPartsToMeta metabps   blks <- smushBlocks <$> mapM bodyPartToBlocks blkbps   blks' <- rewriteLinks $ blocksToDefinitions $ blocksToBullets $ toList blks-  mediaBag <- gets docxMediaBag-  warnings <- gets docxWarnings-  return $ (meta,-            blks',-            mediaBag,-            warnings)+  return (meta, blks') -docxToOutput :: ReaderOptions -> Docx -> Either PandocError (Meta, [Block], MediaBag, [String])+docxToOutput :: PandocMonad m+             => ReaderOptions+             -> Docx+             -> m (Meta, [Block]) docxToOutput opts (Docx (Document _ body)) =   let dEnv   = def { docxOptions  = opts} in    evalDocxContext (bodyToOutput body) dEnv def
src/Text/Pandoc/Readers/Docx/Combine.hs view
@@ -1,15 +1,16 @@-{-# LANGUAGE TypeSynonymInstances, FlexibleInstances,-    PatternGuards #-}+{-# LANGUAGE FlexibleInstances    #-}+{-# LANGUAGE PatternGuards        #-}+{-# LANGUAGE TypeSynonymInstances #-}  module Text.Pandoc.Readers.Docx.Combine ( smushInlines                                         , smushBlocks                                         )        where -import Text.Pandoc.Builder import Data.List-import Data.Sequence (ViewR(..), ViewL(..), viewl, viewr, (><), (|>))+import Data.Sequence (ViewL (..), ViewR (..), viewl, viewr, (><), (|>)) import qualified Data.Sequence as Seq (null)+import Text.Pandoc.Builder  data Modifier a = Modifier (a -> a)                 | AttrModifier (Attr -> a -> a) Attr@@ -35,16 +36,16 @@       right = case viewr contents of         (_ :> Space) -> space         _            -> mempty in-  (left, (stackInlines fs $ trimInlines . Many $ contents), right)+  (left, stackInlines fs $ trimInlines . Many $ contents, right)  stackInlines :: [Modifier Inlines] -> Inlines -> Inlines stackInlines [] ms = ms stackInlines (NullModifier : fs) ms = stackInlines fs ms-stackInlines ((Modifier f) : fs) ms =+stackInlines (Modifier f : fs) ms =   if isEmpty ms   then stackInlines fs ms   else f $ stackInlines fs ms-stackInlines ((AttrModifier f attr) : fs) ms = f attr $ stackInlines fs ms+stackInlines (AttrModifier f attr : fs) ms = f attr $ stackInlines fs ms  unstackInlines :: Inlines -> ([Modifier Inlines], Inlines) unstackInlines ms = case ilModifier ms of@@ -56,15 +57,15 @@ ilModifier :: Inlines -> Modifier Inlines ilModifier ils = case viewl (unMany ils) of   (x :< xs) | Seq.null xs -> case x of-    (Emph _)        -> Modifier emph-    (Strong _)      -> Modifier strong-    (SmallCaps _)   -> Modifier smallcaps-    (Strikeout _)   -> Modifier strikeout-    (Superscript _) -> Modifier superscript-    (Subscript _)   -> Modifier subscript+    (Emph _)          -> Modifier emph+    (Strong _)        -> Modifier strong+    (SmallCaps _)     -> Modifier smallcaps+    (Strikeout _)     -> Modifier strikeout+    (Superscript _)   -> Modifier superscript+    (Subscript _)     -> Modifier subscript     (Link attr _ tgt) -> Modifier $ linkWith attr (fst tgt) (snd tgt)-    (Span attr _)   -> AttrModifier spanWith attr-    _               -> NullModifier+    (Span attr _)     -> AttrModifier spanWith attr+    _                 -> NullModifier   _ -> NullModifier  ilInnards :: Inlines -> Inlines@@ -78,25 +79,25 @@     (Subscript lst)   -> fromList lst     (Link _ lst _)    -> fromList lst     (Span _ lst)      -> fromList lst-    _        -> ils+    _                 -> ils   _          -> ils  inlinesL :: Inlines -> (Inlines, Inlines) inlinesL ils = case viewl $ unMany ils of   (s :< sq) -> (singleton s, Many sq)-  _          -> (mempty, ils)+  _         -> (mempty, ils)  inlinesR :: Inlines -> (Inlines, Inlines) inlinesR ils = case viewr $ unMany ils of   (sq :> s) -> (Many sq, singleton s)-  _          -> (ils, mempty)+  _         -> (ils, mempty)  combineInlines :: Inlines -> Inlines -> Inlines combineInlines x y =   let (xs', x') = inlinesR x       (y', ys') = inlinesL y   in-   xs' <> (combineSingletonInlines x' y') <> ys'+   xs' <> combineSingletonInlines x' y' <> ys'  combineSingletonInlines :: Inlines -> Inlines -> Inlines combineSingletonInlines x y =@@ -113,10 +114,10 @@             stackInlines (x_rem_attr ++ y_rem_attr) mempty           | isEmpty xs ->             let (sp, y') = spaceOutInlinesL y in-            (stackInlines x_rem_attr mempty) <> sp <> y'+            stackInlines x_rem_attr mempty <> sp <> y'           | isEmpty ys ->             let (x', sp) = spaceOutInlinesR x in-            x' <> sp <> (stackInlines y_rem_attr mempty)+            x' <> sp <> stackInlines y_rem_attr mempty           | otherwise ->               let (x', xsp) = spaceOutInlinesR x                   (ysp, y') = spaceOutInlinesL y@@ -129,15 +130,15 @@  combineBlocks :: Blocks -> Blocks -> Blocks combineBlocks bs cs-  | bs' :> (BlockQuote bs'') <- viewr (unMany bs)-  , (BlockQuote cs'') :< cs' <- viewl (unMany cs) =-      Many $ (bs' |> (BlockQuote (bs'' <> cs''))) >< cs'+  | bs' :> BlockQuote bs'' <- viewr (unMany bs)+  , BlockQuote cs'' :< cs' <- viewl (unMany cs) =+      Many $ (bs' |> BlockQuote (bs'' <> cs'')) >< cs' combineBlocks bs cs = bs <> cs  instance (Monoid a, Eq a) => Eq (Modifier a) where-  (Modifier f) == (Modifier g) = (f mempty == g mempty)-  (AttrModifier f attr) == (AttrModifier g attr') = (f attr mempty == g attr' mempty)-  (NullModifier) == (NullModifier) = True+  (Modifier f) == (Modifier g) = f mempty == g mempty+  (AttrModifier f attr) == (AttrModifier g attr') = f attr mempty == g attr' mempty+  NullModifier == NullModifier = True   _ == _ = False  isEmpty :: (Monoid a, Eq a) => a -> Bool
src/Text/Pandoc/Readers/Docx/Lists.hs view
@@ -1,5 +1,5 @@ {--Copyright (C) 2014-2016 Jesse Rosenthal <jrosenthal@jhu.edu>+Copyright (C) 2014-2017 Jesse Rosenthal <jrosenthal@jhu.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -18,7 +18,7 @@  {- |    Module      : Text.Pandoc.Readers.Docx.Lists-   Copyright   : Copyright (C) 2014-2016 Jesse Rosenthal+   Copyright   : Copyright (C) 2014-2017 Jesse Rosenthal    License     : GNU GPL, version 2 or above     Maintainer  : Jesse Rosenthal <jrosenthal@jhu.edu>@@ -33,38 +33,33 @@                                       , listParagraphDivs                                       ) where -import Text.Pandoc.JSON-import Text.Pandoc.Generic (bottomUp)-import Text.Pandoc.Shared (trim)-import Control.Monad import Data.List import Data.Maybe+import Text.Pandoc.Generic (bottomUp)+import Text.Pandoc.JSON+import Text.Pandoc.Shared (trim)  isListItem :: Block -> Bool isListItem (Div (_, classes, _) _) | "list-item" `elem` classes = True-isListItem _ = False+isListItem _                       = False  getLevel :: Block -> Maybe Integer-getLevel (Div (_, _, kvs) _) =  liftM read $ lookup "level" kvs-getLevel _ = Nothing+getLevel (Div (_, _, kvs) _) =  fmap read $ lookup "level" kvs+getLevel _                   = Nothing  getLevelN :: Block -> Integer-getLevelN b = case getLevel b of-  Just n -> n-  Nothing -> -1+getLevelN b = fromMaybe (-1) (getLevel b)  getNumId :: Block -> Maybe Integer-getNumId (Div (_, _, kvs) _) =  liftM read $ lookup "num-id" kvs-getNumId _ = Nothing+getNumId (Div (_, _, kvs) _) =  fmap read $ lookup "num-id" kvs+getNumId _                   = Nothing  getNumIdN :: Block -> Integer-getNumIdN b = case getNumId b of-  Just n -> n-  Nothing -> -1+getNumIdN b = fromMaybe (-1) (getNumId b)  getText :: Block -> Maybe String getText (Div (_, _, kvs) _) = lookup "text" kvs-getText _ = Nothing+getText _                   = Nothing  data ListType = Itemized | Enumerated ListAttributes @@ -109,27 +104,27 @@ handleListParagraphs :: [Block] -> [Block] handleListParagraphs [] = [] handleListParagraphs (-  (Div attr1@(_, classes1, _) blks1) :-  (Div (ident2, classes2, kvs2) blks2) :+  Div attr1@(_, classes1, _) blks1 :+  Div (ident2, classes2, kvs2) blks2 :   blks   ) | "list-item" `elem` classes1 &&-    not ("list-item" `elem` classes2) &&+    notElem "list-item" classes2 &&     (not . null) (listParagraphDivs `intersect` classes2) =       -- We don't want to keep this indent.       let newDiv2 =-            (Div (ident2, classes2, filter (\kv -> fst kv /= "indent") kvs2) blks2)+            Div (ident2, classes2, filter (\kv -> fst kv /= "indent") kvs2) blks2       in-       handleListParagraphs ((Div attr1 (blks1 ++ [newDiv2])) : blks)-handleListParagraphs (blk:blks) = blk : (handleListParagraphs blks)+       handleListParagraphs (Div attr1 (blks1 ++ [newDiv2]) : blks)+handleListParagraphs (blk:blks) = blk : handleListParagraphs blks  separateBlocks' :: Block -> [[Block]] -> [[Block]]-separateBlocks' blk ([] : []) = [[blk]]-separateBlocks' b@(BulletList _) acc = (init acc) ++ [(last acc) ++ [b]]-separateBlocks' b@(OrderedList _ _) acc = (init acc) ++ [(last acc) ++ [b]]+separateBlocks' blk [[]] = [[blk]]+separateBlocks' b@(BulletList _) acc = init acc ++ [last acc ++ [b]]+separateBlocks' b@(OrderedList _ _) acc = init acc ++ [last acc ++ [b]] -- The following is for the invisible bullet lists. This is how -- pandoc-generated ooxml does multiparagraph item lists.-separateBlocks' b acc | liftM trim (getText b) == Just "" =-  (init acc) ++ [(last acc) ++ [b]]+separateBlocks' b acc | fmap trim (getText b) == Just "" =+  init acc ++ [last acc ++ [b]] separateBlocks' b acc = acc ++ [[b]]  separateBlocks :: [Block] -> [[Block]]@@ -138,63 +133,60 @@ flatToBullets' :: Integer -> [Block] -> [Block] flatToBullets' _ [] = [] flatToBullets' num xs@(b : elems)-  | getLevelN b == num = b : (flatToBullets' num elems)+  | getLevelN b == num = b : flatToBullets' num elems   | otherwise =     let bNumId = getNumIdN b         bLevel = getLevelN b         (children, remaining) =           span           (\b' ->-            ((getLevelN b') > bLevel ||-             ((getLevelN b') == bLevel && (getNumIdN b') == bNumId)))+            (getLevelN b') > bLevel ||+             ((getLevelN b') == bLevel && (getNumIdN b') == bNumId))           xs     in      case getListType b of        Just (Enumerated attr) ->-         (OrderedList attr (separateBlocks $ flatToBullets' bLevel children)) :-         (flatToBullets' num remaining)+         OrderedList attr (separateBlocks $ flatToBullets' bLevel children) :+         flatToBullets' num remaining        _ ->-         (BulletList (separateBlocks $ flatToBullets' bLevel children)) :-         (flatToBullets' num remaining)+         BulletList (separateBlocks $ flatToBullets' bLevel children) :+         flatToBullets' num remaining  flatToBullets :: [Block] -> [Block] flatToBullets elems = flatToBullets' (-1) elems  singleItemHeaderToHeader :: Block -> Block-singleItemHeaderToHeader (OrderedList _ [[h@(Header _ _ _)]]) = h-singleItemHeaderToHeader blk = blk+singleItemHeaderToHeader (OrderedList _ [[h@Header{}]]) = h+singleItemHeaderToHeader blk                            = blk   blocksToBullets :: [Block] -> [Block] blocksToBullets blks =   map singleItemHeaderToHeader $-  bottomUp removeListDivs $-  flatToBullets $ (handleListParagraphs blks)+  bottomUp removeListDivs $flatToBullets (handleListParagraphs blks)  plainParaInlines :: Block -> [Inline] plainParaInlines (Plain ils) = ils-plainParaInlines (Para ils) = ils-plainParaInlines _ = []+plainParaInlines (Para ils)  = ils+plainParaInlines _           = []  blocksToDefinitions' :: [([Inline], [[Block]])] -> [Block] -> [Block] -> [Block] blocksToDefinitions' []     acc [] = reverse acc blocksToDefinitions' defAcc acc [] =-  reverse $ (DefinitionList (reverse defAcc)) : acc+  reverse $ DefinitionList (reverse defAcc) : acc blocksToDefinitions' defAcc acc-  ((Div (_, classes1, _) blks1) : (Div (ident2, classes2, kvs2) blks2) : blks)+  (Div (_, classes1, _) blks1 : Div (ident2, classes2, kvs2) blks2 : blks)   | "DefinitionTerm" `elem` classes1 && "Definition"  `elem` classes2 =     let remainingAttr2 = (ident2, delete "Definition" classes2, kvs2)-        pair = case remainingAttr2 == ("", [], []) of-          True -> (concatMap plainParaInlines blks1, [blks2])-          False -> (concatMap plainParaInlines blks1, [[Div remainingAttr2 blks2]])+        pair = if remainingAttr2 == ("", [], []) then (concatMap plainParaInlines blks1, [blks2]) else (concatMap plainParaInlines blks1, [[Div remainingAttr2 blks2]])     in      blocksToDefinitions' (pair : defAcc) acc blks blocksToDefinitions' defAcc acc-  ((Div (ident2, classes2, kvs2) blks2) : blks)+  (Div (ident2, classes2, kvs2) blks2 : blks)   | (not . null) defAcc && "Definition"  `elem` classes2 =     let remainingAttr2 = (ident2, delete "Definition" classes2, kvs2)         defItems2 = case remainingAttr2 == ("", [], []) of-          True -> blks2+          True  -> blks2           False -> [Div remainingAttr2 blks2]         ((defTerm, defItems):defs) = defAcc         defAcc' = case null defItems of@@ -205,18 +197,18 @@ blocksToDefinitions' [] acc (b:blks) =   blocksToDefinitions' [] (b:acc) blks blocksToDefinitions' defAcc acc (b:blks) =-  blocksToDefinitions' [] (b : (DefinitionList (reverse defAcc)) : acc) blks+  blocksToDefinitions' [] (b : DefinitionList (reverse defAcc) : acc) blks  removeListDivs' :: Block -> [Block] removeListDivs' (Div (ident, classes, kvs) blks)   | "list-item" `elem` classes =     case delete "list-item" classes of-      [] -> blks-      classes' -> [Div (ident, classes', kvs) $ blks]+      []       -> blks+      classes' -> [Div (ident, classes', kvs) blks] removeListDivs' (Div (ident, classes, kvs) blks)   | not $ null $ listParagraphDivs `intersect` classes =     case classes \\ listParagraphDivs of-      [] -> blks+      []       -> blks       classes' -> [Div (ident, classes', kvs) blks] removeListDivs' blk = [blk] 
src/Text/Pandoc/Readers/Docx/Parse.hs view
@@ -1,7 +1,9 @@-{-# LANGUAGE PatternGuards, ViewPatterns, FlexibleInstances #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE PatternGuards     #-}+{-# LANGUAGE ViewPatterns      #-}  {--Copyright (C) 2014-2016 Jesse Rosenthal <jrosenthal@jhu.edu>+Copyright (C) 2014-2017 Jesse Rosenthal <jrosenthal@jhu.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -20,7 +22,7 @@  {- |  Module : Text.Pandoc.Readers.Docx.Parse- Copyright : Copyright (C) 2014-2016 Jesse Rosenthal+ Copyright : Copyright (C) 2014-2017 Jesse Rosenthal  License : GNU GPL, version 2 or above   Maintainer : Jesse Rosenthal <jrosenthal@jhu.edu>@@ -53,24 +55,24 @@                                       , archiveToDocxWithWarnings                                       ) where import Codec.Archive.Zip-import Text.XML.Light-import Data.Maybe-import Data.List-import System.FilePath+import Control.Applicative ((<|>))+import Control.Monad.Except+import Control.Monad.Reader+import Control.Monad.State.Strict import Data.Bits ((.|.)) import qualified Data.ByteString.Lazy as B-import qualified Text.Pandoc.UTF8 as UTF8-import Control.Monad.Reader-import Control.Monad.State-import Control.Applicative ((<|>))+import Data.Char (chr, ord, readLitChar)+import Data.List import qualified Data.Map as M-import Control.Monad.Except-import Text.Pandoc.Shared (safeRead, filteredFilesFromArchive)-import Text.TeXMath.Readers.OMML (readOMML)-import Text.TeXMath.Unicode.Fonts (getUnicode, stringToFont, Font(..))-import Text.TeXMath (Exp)+import Data.Maybe+import System.FilePath import Text.Pandoc.Readers.Docx.Util-import Data.Char (readLitChar, ord, chr, isDigit)+import Text.Pandoc.Shared (filteredFilesFromArchive, safeRead)+import qualified Text.Pandoc.UTF8 as UTF8+import Text.TeXMath (Exp)+import Text.TeXMath.Readers.OMML (readOMML)+import Text.TeXMath.Unicode.Fonts (Font (..), getUnicode, stringToFont)+import Text.XML.Light  data ReaderEnv = ReaderEnv { envNotes         :: Notes                            , envComments      :: Comments@@ -97,7 +99,7 @@  maybeToD :: Maybe a -> D a maybeToD (Just a) = return a-maybeToD Nothing = throwError DocxError+maybeToD Nothing  = throwError DocxError  eitherToD :: Either a b -> D b eitherToD (Right b) = return b@@ -160,12 +162,12 @@ data Comments = Comments NameSpaces (M.Map String Element)               deriving Show -data ParIndentation = ParIndentation { leftParIndent :: Maybe Integer-                                     , rightParIndent :: Maybe Integer+data ParIndentation = ParIndentation { leftParIndent    :: Maybe Integer+                                     , rightParIndent   :: Maybe Integer                                      , hangingParIndent :: Maybe Integer}                       deriving Show -data ParagraphStyle = ParagraphStyle { pStyle :: [String]+data ParagraphStyle = ParagraphStyle { pStyle      :: [String]                                      , indentation :: Maybe ParIndentation                                      , dropCap     :: Bool                                      , pHeading    :: Maybe (String, Int)@@ -218,6 +220,7 @@              | Drawing FilePath String String B.ByteString Extent -- title, alt              | Chart                                              -- placeholder for now              | PlainOMath [Exp]+             | SmartTag [Run]              deriving Show  data Run = Run RunStyle [RunElem]@@ -233,19 +236,19 @@ data VertAlign = BaseLn | SupScrpt | SubScrpt                deriving Show -data RunStyle = RunStyle { isBold :: Maybe Bool-                         , isItalic :: Maybe Bool+data RunStyle = RunStyle { isBold      :: Maybe Bool+                         , isItalic    :: Maybe Bool                          , isSmallCaps :: Maybe Bool-                         , isStrike :: Maybe Bool-                         , rVertAlign :: Maybe VertAlign-                         , rUnderline :: Maybe String-                         , rStyle :: Maybe CharStyle}+                         , isStrike    :: Maybe Bool+                         , rVertAlign  :: Maybe VertAlign+                         , rUnderline  :: Maybe String+                         , rStyle      :: Maybe CharStyle}                 deriving Show -data ParStyleData = ParStyleData { headingLev :: Maybe (String, Int)+data ParStyleData = ParStyleData { headingLev   :: Maybe (String, Int)                                  , isBlockQuote :: Maybe Bool-                                 , numInfo :: Maybe (String, String)-                                 , psStyle :: Maybe ParStyle}+                                 , numInfo      :: Maybe (String, String)+                                 , psStyle      :: Maybe ParStyle}                     deriving Show  defaultRunStyle :: RunStyle@@ -294,14 +297,13 @@   entry <- maybeToD $ findEntryByPath "word/document.xml" zf   docElem <- maybeToD $ (parseXMLDoc . UTF8.toStringLazy . fromEntry) entry   let namespaces = elemToNameSpaces docElem-  bodyElem <- maybeToD $ findChild (elemName namespaces "w" "body") docElem+  bodyElem <- maybeToD $ findChildByName namespaces "w" "body" docElem   body <- elemToBody namespaces bodyElem   return $ Document namespaces body  elemToBody :: NameSpaces -> Element -> D Body elemToBody ns element | isElem ns "w" "body" element =-  mapD (elemToBodyPart ns) (elChildren element) >>=-  (\bps -> return $ Body bps)+  fmap Body (mapD (elemToBodyPart ns) (elChildren element)) elemToBody _ _ = throwError WrongElem  archiveToStyles :: Archive -> (CharStyleMap, ParStyleMap)@@ -322,15 +324,15 @@ isBasedOnStyle :: (ElemToStyle a) => NameSpaces -> Element -> Maybe a -> Bool isBasedOnStyle ns element parentStyle   | isElem ns "w" "style" element-  , Just styleType <- findAttr (elemName ns "w" "type") element+  , Just styleType <- findAttrByName ns "w" "type" element   , styleType == cStyleType parentStyle-  , Just basedOnVal <- findChild (elemName ns "w" "basedOn") element >>=-                       findAttr (elemName ns "w" "val")-  , Just ps <- parentStyle = (basedOnVal == getStyleId ps)+  , Just basedOnVal <- findChildByName ns "w" "basedOn" element >>=+                       findAttrByName ns "w" "val"+  , Just ps <- parentStyle = basedOnVal == getStyleId ps   | isElem ns "w" "style" element-  , Just styleType <- findAttr (elemName ns "w" "type") element+  , Just styleType <- findAttrByName ns "w" "type" element   , styleType == cStyleType parentStyle-  , Nothing <- findChild (elemName ns "w" "basedOn") element+  , Nothing <- findChildByName ns "w" "basedOn" element   , Nothing <- parentStyle = True   | otherwise = False @@ -343,8 +345,8 @@   cStyleType _ = "character"   elemToStyle ns element parentStyle     | isElem ns "w" "style" element-    , Just "character" <- findAttr (elemName ns "w" "type") element-    , Just styleId <- findAttr (elemName ns "w" "styleId") element =+    , Just "character" <- findAttrByName ns "w" "type" element+    , Just styleId <- findAttrByName ns "w" "styleId" element =       Just (styleId, elemToRunStyle ns element parentStyle)     | otherwise = Nothing   getStyleId s = fst s@@ -353,8 +355,8 @@   cStyleType _ = "paragraph"   elemToStyle ns element parentStyle     | isElem ns "w" "style" element-    , Just "paragraph" <- findAttr (elemName ns "w" "type") element-    , Just styleId <- findAttr (elemName ns "w" "styleId") element =+    , Just "paragraph" <- findAttrByName ns "w" "type" element+    , Just styleId <- findAttrByName ns "w" "styleId" element =       Just (styleId, elemToParStyleData ns element parentStyle)     | otherwise = Nothing   getStyleId s = fst s@@ -368,10 +370,10 @@  buildBasedOnList :: (ElemToStyle a) => NameSpaces -> Element -> Maybe a -> [a] buildBasedOnList ns element rootStyle =-  case (getStyleChildren ns element rootStyle) of+  case getStyleChildren ns element rootStyle of     [] -> []     stys -> stys ++-            (concatMap (\s -> buildBasedOnList ns element (Just s)) stys)+            concatMap (buildBasedOnList ns element . Just) stys  archiveToNotes :: Archive -> Notes archiveToNotes zf =@@ -380,14 +382,14 @@       enElem = findEntryByPath "word/endnotes.xml" zf                >>= (parseXMLDoc . UTF8.toStringLazy . fromEntry)       fn_namespaces = case fnElem of-        Just e -> elemToNameSpaces e+        Just e  -> elemToNameSpaces e         Nothing -> []       en_namespaces = case enElem of-        Just e -> elemToNameSpaces e+        Just e  -> elemToNameSpaces e         Nothing -> []       ns = unionBy (\x y -> fst x == fst y) fn_namespaces en_namespaces-      fn = fnElem >>= (elemToNotes ns "footnote")-      en = enElem >>= (elemToNotes ns "endnote")+      fn = fnElem >>= elemToNotes ns "footnote"+      en = enElem >>= elemToNotes ns "endnote"   in    Notes ns fn en @@ -396,19 +398,19 @@   let cmtsElem = findEntryByPath "word/comments.xml" zf                >>= (parseXMLDoc . UTF8.toStringLazy . fromEntry)       cmts_namespaces = case cmtsElem of-        Just e -> elemToNameSpaces e+        Just e  -> elemToNameSpaces e         Nothing -> []-      cmts = (elemToComments cmts_namespaces) <$> cmtsElem+      cmts = elemToComments cmts_namespaces <$> cmtsElem   in     case cmts of-      Just c -> Comments cmts_namespaces c+      Just c  -> Comments cmts_namespaces c       Nothing -> Comments cmts_namespaces M.empty  filePathToRelType :: FilePath -> Maybe DocumentLocation-filePathToRelType "word/_rels/document.xml.rels" = Just InDocument+filePathToRelType "word/_rels/document.xml.rels"  = Just InDocument filePathToRelType "word/_rels/footnotes.xml.rels" = Just InFootnote-filePathToRelType "word/_rels/endnotes.xml.rels" = Just InEndnote-filePathToRelType _ = Nothing+filePathToRelType "word/_rels/endnotes.xml.rels"  = Just InEndnote+filePathToRelType _                               = Nothing  relElemToRelationship :: DocumentLocation -> Element -> Maybe Relationship relElemToRelationship relType element | qName (elName element) == "Relationship" =@@ -439,24 +441,23 @@ lookupLevel numId ilvl (Numbering _ numbs absNumbs) = do   absNumId <- lookup numId $ map (\(Numb nid absnumid) -> (nid, absnumid)) numbs   lvls <- lookup absNumId $ map (\(AbstractNumb aid ls) -> (aid, ls)) absNumbs-  lvl  <- lookup ilvl $ map (\l@(i, _, _, _) -> (i, l)) lvls-  return lvl+  lookup ilvl $ map (\l@(i, _, _, _) -> (i, l)) lvls   numElemToNum :: NameSpaces -> Element -> Maybe Numb numElemToNum ns element   | isElem ns "w" "num" element = do-      numId <- findAttr (elemName ns "w" "numId") element-      absNumId <- findChild (elemName ns "w" "abstractNumId") element-                  >>= findAttr (elemName ns "w" "val")+      numId <- findAttrByName ns "w" "numId" element+      absNumId <- findChildByName ns "w" "abstractNumId" element+                  >>= findAttrByName ns "w" "val"       return $ Numb numId absNumId numElemToNum _ _ = Nothing  absNumElemToAbsNum :: NameSpaces -> Element -> Maybe AbstractNumb absNumElemToAbsNum ns element   | isElem ns "w" "abstractNum" element = do-      absNumId <- findAttr (elemName ns "w" "abstractNumId") element-      let levelElems = findChildren (elemName ns "w" "lvl") element+      absNumId <- findAttrByName ns "w" "abstractNumId" element+      let levelElems = findChildrenByName ns "w" "lvl" element           levels = mapMaybe (levelElemToLevel ns) levelElems       return $ AbstractNumb absNumId levels absNumElemToAbsNum _ _ = Nothing@@ -464,26 +465,26 @@ levelElemToLevel :: NameSpaces -> Element -> Maybe Level levelElemToLevel ns element   | isElem ns "w" "lvl" element = do-      ilvl <- findAttr (elemName ns "w" "ilvl") element-      fmt <- findChild (elemName ns "w" "numFmt") element-             >>= findAttr (elemName ns "w" "val")-      txt <- findChild (elemName ns "w" "lvlText") element-             >>= findAttr (elemName ns "w" "val")-      let start = findChild (elemName ns "w" "start") element-                  >>= findAttr (elemName ns "w" "val")+      ilvl <- findAttrByName ns "w" "ilvl" element+      fmt <- findChildByName ns "w" "numFmt" element+             >>= findAttrByName ns "w" "val"+      txt <- findChildByName ns "w" "lvlText" element+             >>= findAttrByName ns "w" "val"+      let start = findChildByName ns "w" "start" element+                  >>= findAttrByName ns "w" "val"                   >>= (\s -> listToMaybe (map fst (reads s :: [(Integer, String)])))       return (ilvl, fmt, txt, start) levelElemToLevel _ _ = Nothing  archiveToNumbering' :: Archive -> Maybe Numbering-archiveToNumbering' zf = do+archiveToNumbering' zf =   case findEntryByPath "word/numbering.xml" zf of     Nothing -> Just $ Numbering [] [] []     Just entry -> do       numberingElem <- (parseXMLDoc . UTF8.toStringLazy . fromEntry) entry       let namespaces = elemToNameSpaces numberingElem-          numElems = findChildren (elemName namespaces "w" "num") numberingElem-          absNumElems = findChildren (elemName namespaces "w" "abstractNum") numberingElem+          numElems = findChildrenByName namespaces "w" "num" numberingElem+          absNumElems = findChildrenByName namespaces "w" "abstractNum" numberingElem           nums = mapMaybe (numElemToNum namespaces) numElems           absNums = mapMaybe (absNumElemToAbsNum namespaces) absNumElems       return $ Numbering namespaces nums absNums@@ -496,22 +497,23 @@ elemToNotes ns notetype element   | isElem ns "w" (notetype ++ "s") element =       let pairs = mapMaybe-                  (\e -> findAttr (elemName ns "w" "id") e >>=+                  (\e -> findAttrByName ns "w" "id" e >>=                          (\a -> Just (a, e)))-                  (findChildren (elemName ns "w" notetype) element)+                  (findChildrenByName ns "w" notetype element)       in-       Just $ M.fromList $ pairs+       Just $+       M.fromList pairs elemToNotes _ _ _ = Nothing  elemToComments :: NameSpaces -> Element -> M.Map String Element elemToComments ns element   | isElem ns "w" "comments" element =       let pairs = mapMaybe-                  (\e -> findAttr (elemName ns "w" "id") e >>=+                  (\e -> findAttrByName ns "w" "id" e >>=                          (\a -> Just (a, e)))-                  (findChildren (elemName ns "w" "comment") element)+                  (findChildrenByName ns "w" "comment" element)       in-       M.fromList $ pairs+       M.fromList pairs elemToComments _ _ = M.empty  @@ -520,16 +522,16 @@  elemToTblGrid :: NameSpaces -> Element -> D TblGrid elemToTblGrid ns element | isElem ns "w" "tblGrid" element =-  let cols = findChildren (elemName ns "w" "gridCol") element+  let cols = findChildrenByName ns "w" "gridCol" element   in-   mapD (\e -> maybeToD (findAttr (elemName ns "w" "val") e >>= stringToInteger))+   mapD (\e -> maybeToD (findAttrByName ns "w" "val" e >>= stringToInteger))    cols elemToTblGrid _ _ = throwError WrongElem  elemToTblLook :: NameSpaces -> Element -> D TblLook elemToTblLook ns element | isElem ns "w" "tblLook" element =-  let firstRow = findAttr (elemName ns "w" "firstRow") element-      val = findAttr (elemName ns "w" "val") element+  let firstRow = findAttrByName ns "w" "firstRow" element+      val = findAttrByName ns "w" "val" element       firstRowFmt =         case firstRow of           Just "1" -> True@@ -544,7 +546,7 @@ elemToRow :: NameSpaces -> Element -> D Row elemToRow ns element | isElem ns "w" "tr" element =   do-    let cellElems = findChildren (elemName ns "w" "tc") element+    let cellElems = findChildrenByName ns "w" "tc" element     cells <- mapD (elemToCell ns) cellElems     return $ Row cells elemToRow _ _ = throwError WrongElem@@ -560,13 +562,13 @@ elemToParIndentation ns element | isElem ns "w" "ind" element =   Just $ ParIndentation {     leftParIndent =-       findAttr (elemName ns "w" "left") element >>=+       findAttrByName ns "w" "left" element >>=        stringToInteger     , rightParIndent =-      findAttr (elemName ns "w" "right") element >>=+      findAttrByName ns "w" "right" element >>=       stringToInteger     , hangingParIndent =-      findAttr (elemName ns "w" "hanging") element >>=+      findAttrByName ns "w" "hanging" element >>=       stringToInteger} elemToParIndentation _ _ = Nothing @@ -574,7 +576,7 @@ testBitMask bitMaskS n =   case (reads ("0x" ++ bitMaskS) :: [(Int, String)]) of     []            -> False-    ((n', _) : _) -> ((n' .|. n) /= 0)+    ((n', _) : _) -> (n' .|. n) /= 0  stringToInteger :: String -> Maybe Integer stringToInteger s = listToMaybe $ map fst (reads s :: [(Integer, String)])@@ -582,7 +584,7 @@ elemToBodyPart :: NameSpaces -> Element -> D BodyPart elemToBodyPart ns element   | isElem ns "w" "p" element-  , (c:_) <- findChildren (elemName ns "m" "oMathPara") element =+  , (c:_) <- findChildrenByName ns "m" "oMathPara" element =       do         expsLst <- eitherToD $ readOMML $ showElement c         return $ OMathPara expsLst@@ -610,17 +612,17 @@         _ -> return $ Paragraph parstyle parparts elemToBodyPart ns element   | isElem ns "w" "tbl" element = do-    let caption' = findChild (elemName ns "w" "tblPr") element-                   >>= findChild (elemName ns "w" "tblCaption")-                   >>= findAttr (elemName ns "w" "val")+    let caption' = findChildByName ns "w" "tblPr" element+                   >>= findChildByName ns "w" "tblCaption"+                   >>= findAttrByName ns "w" "val"         caption = (fromMaybe "" caption')-        grid' = case findChild (elemName ns "w" "tblGrid") element of-          Just g -> elemToTblGrid ns g+        grid' = case findChildByName ns "w" "tblGrid" element of+          Just g  -> elemToTblGrid ns g           Nothing -> return []-        tblLook' = case findChild (elemName ns "w" "tblPr") element >>=-                          findChild (elemName ns "w" "tblLook")+        tblLook' = case findChildByName ns "w" "tblPr" element >>=+                          findChildByName ns "w" "tblLook"                      of-                       Just l -> elemToTblLook ns l+                       Just l  -> elemToTblLook ns l                        Nothing -> return defaultTblLook      grid <- grid'@@ -649,26 +651,22 @@  getTitleAndAlt :: NameSpaces -> Element -> (String, String) getTitleAndAlt ns element =-  let mbDocPr = findChild (elemName ns "wp" "inline") element >>=-                findChild (elemName ns "wp" "docPr")-      title = case mbDocPr >>= findAttr (elemName ns "" "title") of-                Just title' -> title'-                Nothing     -> ""-      alt = case mbDocPr >>= findAttr (elemName ns "" "descr") of-              Just alt' -> alt'-              Nothing   -> ""+  let mbDocPr = findChildByName ns "wp" "inline" element >>=+                findChildByName ns "wp" "docPr"+      title = fromMaybe "" (mbDocPr >>= findAttrByName ns "" "title")+      alt = fromMaybe "" (mbDocPr >>= findAttrByName ns "" "descr")   in (title, alt)  elemToParPart :: NameSpaces -> Element -> D ParPart elemToParPart ns element   | isElem ns "w" "r" element-  , Just drawingElem <- findChild (elemName ns "w" "drawing") element+  , Just drawingElem <- findChildByName ns "w" "drawing" element   , pic_ns <- "http://schemas.openxmlformats.org/drawingml/2006/picture"   , Just picElem <- findElement (QName "pic" (Just pic_ns) (Just "pic")) drawingElem   = let (title, alt) = getTitleAndAlt ns drawingElem         a_ns = "http://schemas.openxmlformats.org/drawingml/2006/main"         drawing = findElement (QName "blip" (Just a_ns) (Just "a")) picElem-                  >>= findAttr (elemName ns "r" "embed")+                  >>= findAttrByName ns "r" "embed"     in      case drawing of        Just s -> expandDrawingId s >>= (\(fp, bs) -> return $ Drawing fp title alt bs $ elemToExtent drawingElem)@@ -676,9 +674,9 @@ -- The below is an attempt to deal with images in deprecated vml format. elemToParPart ns element   | isElem ns "w" "r" element-  , Just _ <- findChild (elemName ns "w" "pict") element =+  , Just _ <- findChildByName ns "w" "pict" element =     let drawing = findElement (elemName ns "v" "imagedata") element-                  >>= findAttr (elemName ns "r" "id")+                  >>= findAttrByName ns "r" "id"     in      case drawing of        -- Todo: check out title and attr for deprecated format.@@ -687,86 +685,90 @@ -- Chart elemToParPart ns element   | isElem ns "w" "r" element-  , Just drawingElem <- findChild (elemName ns "w" "drawing") element+  , Just drawingElem <- findChildByName ns "w" "drawing" element   , c_ns <- "http://schemas.openxmlformats.org/drawingml/2006/chart"   , Just _ <- findElement (QName "chart" (Just c_ns) (Just "c")) drawingElem-  = return Chart                       +  = return Chart elemToParPart ns element   | isElem ns "w" "r" element =     elemToRun ns element >>= (\r -> return $ PlainRun r) elemToParPart ns element   | isElem ns "w" "ins" element || isElem ns "w" "moveTo" element-  , Just cId <- findAttr (elemName ns "w" "id") element-  , Just cAuthor <- findAttr (elemName ns "w" "author") element-  , Just cDate <- findAttr (elemName ns "w" "date") element = do+  , Just cId <- findAttrByName ns "w" "id" element+  , Just cAuthor <- findAttrByName ns "w" "author" element+  , Just cDate <- findAttrByName ns "w" "date" element = do     runs <- mapD (elemToRun ns) (elChildren element)     return $ Insertion cId cAuthor cDate runs elemToParPart ns element   | isElem ns "w" "del" element || isElem ns "w" "moveFrom" element-  , Just cId <- findAttr (elemName ns "w" "id") element-  , Just cAuthor <- findAttr (elemName ns "w" "author") element-  , Just cDate <- findAttr (elemName ns "w" "date") element = do+  , Just cId <- findAttrByName ns "w" "id" element+  , Just cAuthor <- findAttrByName ns "w" "author" element+  , Just cDate <- findAttrByName ns "w" "date" element = do     runs <- mapD (elemToRun ns) (elChildren element)     return $ Deletion cId cAuthor cDate runs elemToParPart ns element+  | isElem ns "w" "smartTag" element = do+    runs <- mapD (elemToRun ns) (elChildren element)+    return $ SmartTag runs+elemToParPart ns element   | isElem ns "w" "bookmarkStart" element-  , Just bmId <- findAttr (elemName ns "w" "id") element-  , Just bmName <- findAttr (elemName ns "w" "name") element =+  , Just bmId <- findAttrByName ns "w" "id" element+  , Just bmName <- findAttrByName ns "w" "name" element =     return $ BookMark bmId bmName elemToParPart ns element   | isElem ns "w" "hyperlink" element-  , Just relId <- findAttr (elemName ns "r" "id") element = do+  , Just relId <- findAttrByName ns "r" "id" element = do     location <- asks envLocation     runs <- mapD (elemToRun ns) (elChildren element)     rels <- asks envRelationships     case lookupRelationship location relId rels of-      Just target -> do-         case findAttr (elemName ns "w" "anchor") element of+      Just target ->+         case findAttrByName ns "w" "anchor" element of              Just anchor -> return $ ExternalHyperLink (target ++ '#':anchor) runs              Nothing -> return $ ExternalHyperLink target runs       Nothing     -> return $ ExternalHyperLink "" runs elemToParPart ns element   | isElem ns "w" "hyperlink" element-  , Just anchor <- findAttr (elemName ns "w" "anchor") element = do+  , Just anchor <- findAttrByName ns "w" "anchor" element = do     runs <- mapD (elemToRun ns) (elChildren element)     return $ InternalHyperLink anchor runs elemToParPart ns element   | isElem ns "w" "commentRangeStart" element-  , Just cmtId <- findAttr (elemName ns "w" "id") element = do+  , Just cmtId <- findAttrByName ns "w" "id" element = do       (Comments _ commentMap) <- asks envComments       case M.lookup cmtId commentMap of         Just cmtElem -> elemToCommentStart ns cmtElem-        Nothing   -> throwError WrongElem+        Nothing      -> throwError WrongElem elemToParPart ns element   | isElem ns "w" "commentRangeEnd" element-  , Just cmtId <- findAttr (elemName ns "w" "id") element =+  , Just cmtId <- findAttrByName ns "w" "id" element =     return $ CommentEnd cmtId elemToParPart ns element   | isElem ns "m" "oMath" element =-    (eitherToD $ readOMML $ showElement element) >>= (return . PlainOMath)+    fmap PlainOMath (eitherToD $ readOMML $ showElement element) elemToParPart _ _ = throwError WrongElem  elemToCommentStart :: NameSpaces -> Element -> D ParPart elemToCommentStart ns element   | isElem ns "w" "comment" element-  , Just cmtId <- findAttr (elemName ns "w" "id") element-  , Just cmtAuthor <- findAttr (elemName ns "w" "author") element-  , Just cmtDate <- findAttr (elemName ns "w" "date") element = do+  , Just cmtId <- findAttrByName ns "w" "id" element+  , Just cmtAuthor <- findAttrByName ns "w" "author" element+  , Just cmtDate <- findAttrByName ns "w" "date" element = do       bps <- mapD (elemToBodyPart ns) (elChildren element)       return $ CommentStart cmtId cmtAuthor cmtDate bps elemToCommentStart _ _ = throwError WrongElem  lookupFootnote :: String -> Notes -> Maybe Element-lookupFootnote s (Notes _ fns _) = fns >>= (M.lookup s)+lookupFootnote s (Notes _ fns _) = fns >>= M.lookup s  lookupEndnote :: String -> Notes -> Maybe Element-lookupEndnote s (Notes _ _ ens) = ens >>= (M.lookup s)+lookupEndnote s (Notes _ _ ens) = ens >>= M.lookup s  elemToExtent :: Element -> Extent elemToExtent drawingElem =   case (getDim "cx", getDim "cy") of     (Just w, Just h) -> Just (w, h)-    _ -> Nothing+    _                -> Nothing     where       wp_ns  = "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"       getDim at = findElement (QName "extent" (Just wp_ns) (Just "wp")) drawingElem@@ -794,7 +796,7 @@   = return InlineChart childElemToRun ns element   | isElem ns "w" "footnoteReference" element-  , Just fnId <- findAttr (elemName ns "w" "id") element = do+  , Just fnId <- findAttrByName ns "w" "id" element = do     notes <- asks envNotes     case lookupFootnote fnId notes of       Just e -> do bps <- local (\r -> r {envLocation=InFootnote}) $ mapD (elemToBodyPart ns) (elChildren e)@@ -802,7 +804,7 @@       Nothing  -> return $ Footnote [] childElemToRun ns element   | isElem ns "w" "endnoteReference" element-  , Just enId <- findAttr (elemName ns "w" "id") element = do+  , Just enId <- findAttrByName ns "w" "id" element = do     notes <- asks envNotes     case lookupEndnote enId notes of       Just e -> do bps <- local (\r -> r {envLocation=InEndnote}) $ mapD (elemToBodyPart ns) (elChildren e)@@ -813,8 +815,8 @@ elemToRun :: NameSpaces -> Element -> D Run elemToRun ns element   | isElem ns "w" "r" element-  , Just altCont <- findChild (elemName ns "mc" "AlternateContent") element =-    do let choices = findChildren (elemName ns "mc" "Choice") altCont+  , Just altCont <- findChildByName ns "mc" "AlternateContent" element =+    do let choices = findChildrenByName ns "mc" "Choice" altCont            choiceChildren = map head $ filter (not . null) $ map elChildren choices        outputs <- mapD (childElemToRun ns) choiceChildren        case outputs of@@ -822,15 +824,15 @@          []    -> throwError WrongElem elemToRun ns element   | isElem ns "w" "r" element-  , Just drawingElem <- findChild (elemName ns "w" "drawing") element =+  , Just drawingElem <- findChildByName ns "w" "drawing" element =     childElemToRun ns drawingElem elemToRun ns element   | isElem ns "w" "r" element-  , Just ref <- findChild (elemName ns "w" "footnoteReference") element =+  , Just ref <- findChildByName ns "w" "footnoteReference" element =     childElemToRun ns ref elemToRun ns element   | isElem ns "w" "r" element-  , Just ref <- findChild (elemName ns "w" "endnoteReference") element =+  , Just ref <- findChildByName ns "w" "endnoteReference" element =     childElemToRun ns ref elemToRun ns element   | isElem ns "w" "r" element = do@@ -856,20 +858,20 @@  elemToParagraphStyle :: NameSpaces -> Element -> ParStyleMap -> ParagraphStyle elemToParagraphStyle ns element sty-  | Just pPr <- findChild (elemName ns "w" "pPr") element =+  | Just pPr <- findChildByName ns "w" "pPr" element =     let style =           mapMaybe-          (findAttr (elemName ns "w" "val"))-          (findChildren (elemName ns "w" "pStyle") pPr)+          (findAttrByName ns "w" "val")+          (findChildrenByName ns "w" "pStyle" pPr)     in ParagraphStyle       {pStyle = style       , indentation =-          findChild (elemName ns "w" "ind") pPr >>=+          findChildByName ns "w" "ind" pPr >>=           elemToParIndentation ns       , dropCap =           case-            findChild (elemName ns "w" "framePr") pPr >>=-            findAttr (elemName ns "w" "dropCap")+            findChildByName ns "w" "framePr" pPr >>=+            findAttrByName ns "w" "dropCap"           of             Just "none" -> False             Just _      -> True@@ -883,7 +885,7 @@ checkOnOff :: NameSpaces -> Element -> QName -> Maybe Bool checkOnOff ns rPr tag   | Just t <-  findChild tag rPr-  , Just val <- findAttr (elemName ns "w" "val") t =+  , Just val <- findAttrByName ns "w" "val" t =     Just $ case val of       "true"  -> True       "false" -> False@@ -897,11 +899,11 @@  elemToRunStyleD :: NameSpaces -> Element -> D RunStyle elemToRunStyleD ns element-  | Just rPr <- findChild (elemName ns "w" "rPr") element = do+  | Just rPr <- findChildByName ns "w" "rPr" element = do     charStyles <- asks envCharStyles     let parentSty = case-          findChild (elemName ns "w" "rStyle") rPr >>=-          findAttr (elemName ns "w" "val")+          findChildByName ns "w" "rStyle" rPr >>=+          findAttrByName ns "w" "val"           of             Just styName | Just style <- M.lookup styName charStyles ->               Just (styName, style)@@ -911,7 +913,7 @@  elemToRunStyle :: NameSpaces -> Element -> Maybe CharStyle -> RunStyle elemToRunStyle ns element parentStyle-  | Just rPr <- findChild (elemName ns "w" "rPr") element =+  | Just rPr <- findChildByName ns "w" "rPr" element =     RunStyle       {         isBold = checkOnOff ns rPr (elemName ns "w" "b")@@ -919,32 +921,31 @@       , isSmallCaps = checkOnOff ns rPr (elemName ns "w" "smallCaps")       , isStrike = checkOnOff ns rPr (elemName ns "w" "strike")       , rVertAlign =-           findChild (elemName ns "w" "vertAlign") rPr >>=-           findAttr (elemName ns "w" "val") >>=+           findChildByName ns "w" "vertAlign" rPr >>=+           findAttrByName ns "w" "val" >>=            \v -> Just $ case v of              "superscript" -> SupScrpt              "subscript"   -> SubScrpt              _             -> BaseLn       , rUnderline =-          findChild (elemName ns "w" "u") rPr >>=-          findAttr (elemName ns "w" "val")+          findChildByName ns "w" "u" rPr >>=+          findAttrByName ns "w" "val"       , rStyle = parentStyle         } elemToRunStyle _ _ _ = defaultRunStyle -isNumericNotNull :: String -> Bool-isNumericNotNull str = (str /= []) && (all isDigit str)- getHeaderLevel :: NameSpaces -> Element -> Maybe (String,Int) getHeaderLevel ns element-  | Just styleId <- findAttr (elemName ns "w" "styleId") element+  | Just styleId <- findAttrByName ns "w" "styleId" element   , Just index   <- stripPrefix "Heading" styleId-  , isNumericNotNull index = Just (styleId, read index)-  | Just styleId <- findAttr (elemName ns "w" "styleId") element-  , Just index   <- findChild (elemName ns "w" "name") element >>=-                    findAttr (elemName ns "w" "val") >>=+  , Just n       <- stringToInteger index+  , n > 0 = Just (styleId, fromInteger n)+  | Just styleId <- findAttrByName ns "w" "styleId" element+  , Just index   <- findChildByName ns "w" "name" element >>=+                    findAttrByName ns "w" "val" >>=                     stripPrefix "heading "-  , isNumericNotNull index = Just (styleId, read index)+  , Just n <- stringToInteger index+  , n > 0 = Just (styleId, fromInteger n) getHeaderLevel _ _ = Nothing  blockQuoteStyleIds :: [String]@@ -955,23 +956,23 @@  getBlockQuote :: NameSpaces -> Element -> Maybe Bool getBlockQuote ns element-  | Just styleId <- findAttr (elemName ns "w" "styleId") element+  | Just styleId <- findAttrByName ns "w" "styleId" element   , styleId `elem` blockQuoteStyleIds = Just True-  | Just styleName <- findChild (elemName ns "w" "name") element >>=-                      findAttr (elemName ns "w" "val")+  | Just styleName <- findChildByName ns "w" "name" element >>=+                      findAttrByName ns "w" "val"   , styleName `elem` blockQuoteStyleNames = Just True getBlockQuote _ _ = Nothing  getNumInfo :: NameSpaces -> Element -> Maybe (String, String) getNumInfo ns element = do-  let numPr = findChild (elemName ns "w" "pPr") element >>=-              findChild (elemName ns "w" "numPr")+  let numPr = findChildByName ns "w" "pPr" element >>=+              findChildByName ns "w" "numPr"       lvl = fromMaybe "0" (numPr >>=-                           findChild (elemName ns "w" "ilvl") >>=-                           findAttr (elemName ns "w" "val"))+                           findChildByName ns "w" "ilvl" >>=+                           findAttrByName ns "w" "val")   numId <- numPr >>=-           findChild (elemName ns "w" "numId") >>=-           findAttr (elemName ns "w" "val")+           findChildByName ns "w" "numId" >>=+           findAttrByName ns "w" "val"   return (numId, lvl)  @@ -1015,10 +1016,10 @@   let [(char, _)] = readLitChar ("\\x" ++ s) in     TextRun . maybe "" (:[]) $ getUnicode font char   where-    getCodepoint = findAttr (elemName ns "w" "char") element-    getFont = stringToFont =<< findAttr (elemName ns "w" "font") element+    getCodepoint = findAttrByName ns "w" "char" element+    getFont = stringToFont =<< findAttrByName ns "w" "font" element     lowerFromPrivate ('F':xs) = '0':xs-    lowerFromPrivate xs = xs+    lowerFromPrivate xs       = xs getSymChar _ _ = TextRun ""  elemToRunElems :: NameSpaces -> Element -> D [RunElem]@@ -1029,11 +1030,10 @@        let font = do                     fontElem <- findElement (qualName "rFonts") element                     stringToFont =<<-                      (foldr (<|>) Nothing $+                      foldr (<|>) Nothing (                         map (flip findAttr fontElem . qualName) ["ascii", "hAnsi"])        local (setFont font) (mapD (elemToRunElem ns) (elChildren element)) elemToRunElems _ _ = throwError WrongElem  setFont :: Maybe Font -> ReaderEnv -> ReaderEnv setFont f s = s{envFont = f}-
src/Text/Pandoc/Readers/Docx/StyleMap.hs view
@@ -7,11 +7,11 @@                                           , hasStyleName                                           ) where -import           Text.XML.Light-import           Text.Pandoc.Readers.Docx.Util-import           Control.Monad.State-import           Data.Char  (toLower)-import qualified Data.Map                      as M+import Control.Monad.State.Strict+import Data.Char (toLower)+import qualified Data.Map as M+import Text.Pandoc.Readers.Docx.Util+import Text.XML.Light  newtype ParaStyleMap = ParaStyleMap ( M.Map String String ) newtype CharStyleMap = CharStyleMap ( M.Map String String )@@ -30,7 +30,7 @@  insert :: (StyleMap a) => Maybe String -> Maybe String -> a -> a insert (Just k) (Just v) m = alterMap (M.insert k v) m-insert _ _ m = m+insert _ _ m               = m  getStyleId :: (StyleMap a) => String -> a -> String getStyleId s = M.findWithDefault (filter (/=' ') s) (map toLower s) . getMap
src/Text/Pandoc/Readers/Docx/Util.hs view
@@ -3,10 +3,13 @@                                       , elemName                                       , isElem                                       , elemToNameSpaces+                                      , findChildByName+                                      , findChildrenByName+                                      , findAttrByName                                       ) where -import Text.XML.Light import Data.Maybe (mapMaybe)+import Text.XML.Light  type NameSpaces = [(String, String)] @@ -15,7 +18,7 @@  attrToNSPair :: Attr -> Maybe (String, String) attrToNSPair (Attr (QName s _ (Just "xmlns")) val) = Just (s, val)-attrToNSPair _ = Nothing+attrToNSPair _                                     = Nothing  elemName :: NameSpaces -> String -> String -> QName elemName ns prefix name =@@ -23,5 +26,21 @@  isElem :: NameSpaces -> String -> String -> Element -> Bool isElem ns prefix name element =-  qName (elName element) == name &&-  qURI (elName element) == lookup prefix ns+  let ns' = ns ++ elemToNameSpaces element+  in qName (elName element) == name &&+     qURI (elName element) == lookup prefix ns'++findChildByName :: NameSpaces -> String -> String -> Element -> Maybe Element+findChildByName ns pref name el =+  let ns' = ns ++ elemToNameSpaces el+  in  findChild (elemName ns' pref name) el++findChildrenByName :: NameSpaces -> String -> String -> Element -> [Element]+findChildrenByName ns pref name el =+  let ns' = ns ++ elemToNameSpaces el+  in  findChildren (elemName ns' pref name) el++findAttrByName :: NameSpaces -> String -> String -> Element -> Maybe String+findAttrByName ns pref name el =+  let ns' = ns ++ elemToNameSpaces el+  in  findAttr (elemName ns' pref name) el
src/Text/Pandoc/Readers/EPUB.hs view
@@ -1,55 +1,54 @@-{-# LANGUAGE-   ViewPatterns- , StandaloneDeriving- , TupleSections- , FlexibleContexts  #-}+{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE TupleSections    #-}+{-# LANGUAGE ViewPatterns     #-}+ module Text.Pandoc.Readers.EPUB   (readEPUB)   where -import Text.XML.Light+import Codec.Archive.Zip (Archive (..), Entry, findEntryByPath, fromEntry,+                          toArchiveOrFail)+import Control.DeepSeq (NFData, deepseq)+import Control.Monad (guard, liftM)+import Control.Monad.Except (throwError)+import qualified Data.ByteString.Lazy as BL (ByteString)+import Data.List (isInfixOf, isPrefixOf)+import qualified Data.Map as M (Map, elems, fromList, lookup)+import Data.Maybe (fromMaybe, mapMaybe)+import Data.Monoid ((<>))+import qualified Data.Text.Lazy as TL+import qualified Data.Text.Lazy.Encoding as TL+import Network.URI (unEscapeString)+import System.FilePath (dropFileName, dropFileName, normalise, splitFileName,+                        takeFileName, (</>))+import qualified Text.Pandoc.Builder as B+import Text.Pandoc.Class (PandocMonad, insertMedia) import Text.Pandoc.Definition hiding (Attr)-import Text.Pandoc.Readers.HTML (readHtml) import Text.Pandoc.Error-import Text.Pandoc.Walk (walk, query)-import Text.Pandoc.Options ( ReaderOptions(..), readerTrace)-import Text.Pandoc.Shared (escapeURI, collapseFilePath, addMetaField)-import Network.URI (unEscapeString)-import Text.Pandoc.MediaBag (MediaBag, insertMedia)-import Control.Monad.Except (MonadError, throwError, runExcept, Except)+import Text.Pandoc.Extensions (Extension (Ext_raw_html), enableExtension) import Text.Pandoc.MIME (MimeType)-import qualified Text.Pandoc.Builder as B-import Codec.Archive.Zip ( Archive (..), toArchiveOrFail, fromEntry-                         , findEntryByPath, Entry)-import qualified Data.ByteString.Lazy as BL (ByteString)-import System.FilePath ( takeFileName, (</>), dropFileName, normalise-                       , dropFileName-                       , splitFileName )+import Text.Pandoc.Options (ReaderOptions (..))+import Text.Pandoc.Readers.HTML (readHtml)+import Text.Pandoc.Shared (addMetaField, collapseFilePath, escapeURI) import qualified Text.Pandoc.UTF8 as UTF8 (toStringLazy)-import Control.Monad (guard, liftM, when)-import Data.List (isPrefixOf, isInfixOf)-import Data.Maybe (mapMaybe, fromMaybe)-import qualified Data.Map as M (Map, lookup, fromList, elems)-import Data.Monoid ((<>))-import Control.DeepSeq (deepseq, NFData)--import Debug.Trace (trace)+import Text.Pandoc.Walk (query, walk)+import Text.XML.Light  type Items = M.Map String (FilePath, MimeType) -readEPUB :: ReaderOptions -> BL.ByteString -> Either PandocError (Pandoc, MediaBag)+readEPUB :: PandocMonad m => ReaderOptions -> BL.ByteString -> m Pandoc readEPUB opts bytes = case toArchiveOrFail bytes of-  Right archive -> runEPUB $ archiveToEPUB opts $ archive-  Left  _       -> Left $ ParseFailure "Couldn't extract ePub file"+  Right archive -> archiveToEPUB opts archive+  Left  _       -> throwError $ PandocParseError "Couldn't extract ePub file" -runEPUB :: Except PandocError a -> Either PandocError a-runEPUB = runExcept+-- runEPUB :: Except PandocError a -> Either PandocError a+-- runEPUB = runExcept  -- Note that internal reference are aggresively normalised so that all ids -- are of the form "filename#id" ---archiveToEPUB :: (MonadError PandocError m) => ReaderOptions -> Archive -> m (Pandoc, MediaBag)+archiveToEPUB :: (PandocMonad m) => ReaderOptions -> Archive -> m Pandoc archiveToEPUB os archive = do   -- root is path to folder with manifest file in   (root, content) <- getManifest archive@@ -62,40 +61,36 @@   Pandoc _ bs <-       foldM' (\a b -> ((a <>) . walk (prependHash escapedSpine))         `liftM` parseSpineElem root b) mempty spine-  let ast = coverDoc <> (Pandoc meta bs)-  let mediaBag = fetchImages (M.elems items) root archive ast-  return $ (ast, mediaBag)+  let ast = coverDoc <> Pandoc meta bs+  fetchImages (M.elems items) root archive ast+  return ast   where-    os' = os {readerParseRaw = True}-    parseSpineElem :: MonadError PandocError m => FilePath -> (FilePath, MimeType) -> m Pandoc+    os' = os {readerExtensions = enableExtension Ext_raw_html (readerExtensions os)}+    parseSpineElem :: PandocMonad m => FilePath -> (FilePath, MimeType) -> m Pandoc     parseSpineElem (normalise -> r) (normalise -> path, mime) = do-      when (readerTrace os) (traceM path)       doc <- mimeToReader mime r path       let docSpan = B.doc $ B.para $ B.spanWith (takeFileName path, [], []) mempty       return $ docSpan <> doc-    mimeToReader :: MonadError PandocError m => MimeType -> FilePath -> FilePath -> m Pandoc+    mimeToReader :: PandocMonad m => MimeType -> FilePath -> FilePath -> m Pandoc     mimeToReader "application/xhtml+xml" (unEscapeString -> root)                                          (unEscapeString -> path) = do       fname <- findEntryByPathE (root </> path) archive-      html <- either throwError return .-                readHtml os' .-                  UTF8.toStringLazy $-                    fromEntry fname+      html <- readHtml os' . TL.toStrict . TL.decodeUtf8 $ fromEntry fname       return $ fixInternalReferences path html     mimeToReader s _ (unEscapeString -> path)       | s `elem` imageMimes = return $ imageToPandoc path-      | otherwise = return $ mempty+      | otherwise = return mempty  -- paths should be absolute when this function is called -- renameImages should do this-fetchImages :: [(FilePath, MimeType)]+fetchImages :: PandocMonad m+            => [(FilePath, MimeType)]             -> FilePath -- ^ Root             -> Archive             -> Pandoc-            -> MediaBag+            -> m () fetchImages mimes root arc (query iq -> links) =-    foldr (uncurry3 insertMedia) mempty-      (mapMaybe getEntry links)+    mapM_ (uncurry3 insertMedia) (mapMaybe getEntry links)   where     getEntry link =         let abslink = normalise (root </> link) in@@ -104,7 +99,7 @@  iq :: Inline -> [FilePath] iq (Image _ _ (url, _)) = [url]-iq _ = []+iq _                    = []  -- Remove relative paths renameImages :: FilePath -> Inline -> Inline@@ -121,13 +116,13 @@  type CoverImage = FilePath -parseManifest :: (MonadError PandocError m) => Element -> m (Maybe CoverImage, Items)+parseManifest :: (PandocMonad m) => Element -> m (Maybe CoverImage, Items) parseManifest content = do   manifest <- findElementE (dfName "manifest") content   let items = findChildren (dfName "item") manifest   r <- mapM parseItem items   let cover = findAttr (emptyName "href") =<< filterChild findCover manifest-  return (cover, (M.fromList r))+  return (cover, M.fromList r)   where     findCover e = maybe False (isInfixOf "cover-image")                   (findAttr (emptyName "properties") e)@@ -137,18 +132,18 @@       mime <- findAttrE (emptyName "media-type") e       return (uid, (href, mime)) -parseSpine :: MonadError PandocError m => Items -> Element -> m [(FilePath, MimeType)]+parseSpine :: PandocMonad m => Items -> Element -> m [(FilePath, MimeType)] parseSpine is e = do   spine <- findElementE (dfName "spine") e   let itemRefs = findChildren (dfName "itemref") spine-  mapM (mkE "parseSpine" . (flip M.lookup is)) $ mapMaybe parseItemRef itemRefs+  mapM (mkE "parseSpine" . flip M.lookup is) $ mapMaybe parseItemRef itemRefs   where     parseItemRef ref = do       let linear = maybe True (== "yes") (findAttr (emptyName "linear") ref)       guard linear       findAttr (emptyName "idref") ref -parseMeta :: MonadError PandocError m => Element -> m Meta+parseMeta :: PandocMonad m => Element -> m Meta parseMeta content = do   meta <- findElementE (dfName "metadata") content   let dcspace (QName _ (Just "http://purl.org/dc/elements/1.1/") (Just "dc")) = True@@ -164,29 +159,29 @@  renameMeta :: String -> String renameMeta "creator" = "author"-renameMeta s = s+renameMeta s         = s -getManifest :: MonadError PandocError m => Archive -> m (String, Element)+getManifest :: PandocMonad m => Archive -> m (String, Element) getManifest archive = do   metaEntry <- findEntryByPathE ("META-INF" </> "container.xml") archive   docElem <- (parseXMLDocE . UTF8.toStringLazy . fromEntry) metaEntry   let namespaces = mapMaybe attrToNSPair (elAttribs docElem)   ns <- mkE "xmlns not in namespaces" (lookup "xmlns" namespaces)-  as <- liftM ((map attrToPair) . elAttribs)+  as <- fmap (map attrToPair . elAttribs)     (findElementE (QName "rootfile" (Just ns) Nothing) docElem)   manifestFile <- mkE "Root not found" (lookup "full-path" as)   let rootdir = dropFileName manifestFile   --mime <- lookup "media-type" as   manifest <- findEntryByPathE manifestFile archive-  liftM ((,) rootdir) (parseXMLDocE . UTF8.toStringLazy . fromEntry $ manifest)+  fmap ((,) rootdir) (parseXMLDocE . UTF8.toStringLazy . fromEntry $ manifest)  -- Fixup  fixInternalReferences :: FilePath -> Pandoc -> Pandoc fixInternalReferences pathToFile =-  (walk $ renameImages root)-  . (walk $ fixBlockIRs filename)-  . (walk $ fixInlineIRs filename)+   walk (renameImages root)+  .  walk (fixBlockIRs filename)+  . walk (fixInlineIRs filename)   where     (root, escapeURI -> filename) = splitFileName pathToFile @@ -221,7 +216,7 @@ fixAttrs s (ident, cs, kvs) = (addHash s ident, filter (not . null) cs, removeEPUBAttrs kvs)  addHash :: String -> String -> String-addHash _ "" = ""+addHash _ ""    = "" addHash s ident = takeFileName s ++ "#" ++ ident  removeEPUBAttrs :: [(String, String)] -> [(String, String)]@@ -242,9 +237,6 @@ uncurry3 :: (a -> b -> c -> d) -> (a, b, c) -> d uncurry3 f (a, b, c) = f a b c -traceM :: Monad m => String -> m ()-traceM = flip trace (return ())- -- Utility  stripNamespace :: QName -> String@@ -252,7 +244,7 @@  attrToNSPair :: Attr -> Maybe (String, String) attrToNSPair (Attr (QName "xmlns" _ _) val) = Just ("xmlns", val)-attrToNSPair _ = Nothing+attrToNSPair _                              = Nothing  attrToPair :: Attr -> (String, String) attrToPair (Attr (QName name _ _) val) = (name, val)@@ -268,18 +260,18 @@  -- Convert Maybe interface to Either -findAttrE :: MonadError PandocError m => QName -> Element -> m String+findAttrE :: PandocMonad m => QName -> Element -> m String findAttrE q e = mkE "findAttr" $ findAttr q e -findEntryByPathE :: MonadError PandocError m => FilePath -> Archive -> m Entry+findEntryByPathE :: PandocMonad m => FilePath -> Archive -> m Entry findEntryByPathE (normalise -> path) a =   mkE ("No entry on path: " ++ path) $ findEntryByPath path a -parseXMLDocE :: MonadError PandocError m => String -> m Element+parseXMLDocE :: PandocMonad m => String -> m Element parseXMLDocE doc = mkE "Unable to parse XML doc" $ parseXMLDoc doc -findElementE :: MonadError PandocError m => QName -> Element -> m Element+findElementE :: PandocMonad m => QName -> Element -> m Element findElementE e x = mkE ("Unable to find element: " ++ show e) $ findElement e x -mkE :: MonadError PandocError m => String -> Maybe a -> m a-mkE s = maybe (throwError . ParseFailure $ s) return+mkE :: PandocMonad m => String -> Maybe a -> m a+mkE s = maybe (throwError . PandocParseError $ s) return
src/Text/Pandoc/Readers/HTML.hs view
@@ -1,7 +1,10 @@-{-# LANGUAGE FlexibleContexts, FlexibleInstances, MultiParamTypeClasses,-ViewPatterns#-}+{-# LANGUAGE FlexibleContexts      #-}+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings     #-}+{-# LANGUAGE ViewPatterns          #-} {--Copyright (C) 2006-2015 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2006-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -20,7 +23,7 @@  {- |    Module      : Text.Pandoc.Readers.HTML-   Copyright   : Copyright (C) 2006-2015 John MacFarlane+   Copyright   : Copyright (C) 2006-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -34,66 +37,78 @@                                 , htmlInBalanced                                 , isInlineTag                                 , isBlockTag+                                , NamedTag(..)                                 , isTextTag                                 , isCommentTag                                 ) where +import Control.Applicative ((<|>))+import Control.Arrow ((***))+import Control.Monad (guard, mplus, msum, mzero, unless, void)+import Control.Monad.Except (throwError)+import Control.Monad.Reader (ReaderT, ask, asks, lift, local, runReaderT)+import Data.Char (isAlphaNum, isDigit, isLetter)+import Data.Default (Default (..), def)+import Data.Foldable (for_)+import Data.List (intercalate, isPrefixOf)+import Data.List.Split (wordsBy)+import qualified Data.Map as M+import Data.Maybe (fromMaybe, isJust, isNothing)+import Data.Monoid (First (..))+import Data.Monoid ((<>))+import qualified Data.Set as Set+import Data.Text (Text)+import qualified Data.Text as T+import Network.URI (URI, nonStrictRelativeTo, parseURIReference) import Text.HTML.TagSoup import Text.HTML.TagSoup.Match-import Text.Pandoc.Definition+import Text.Pandoc.Builder (Blocks, HasMeta (..), Inlines, trimInlines) import qualified Text.Pandoc.Builder as B-import Text.Pandoc.Builder (Blocks, Inlines, trimInlines, HasMeta(..))-import Text.Pandoc.Shared ( extractSpaces, renderTags', addMetaField-                          , escapeURI, safeRead, mapLeft )-import Text.Pandoc.Options (ReaderOptions(readerParseRaw, readerTrace)-                           , Extension (Ext_epub_html_exts,-                               Ext_native_divs, Ext_native_spans))+import Text.Pandoc.Class (PandocMonad (..))+import Text.Pandoc.CSS (foldOrElse, pickStyleAttrProps)+import Text.Pandoc.Definition+import Text.Pandoc.Error+import Text.Pandoc.Logging+import Text.Pandoc.Options (Extension (Ext_epub_html_exts, Ext_native_divs, Ext_native_spans, Ext_raw_html),+                            ReaderOptions (readerExtensions, readerStripComments),+                            extensionEnabled) import Text.Pandoc.Parsing hiding ((<|>))+import Text.Pandoc.Shared (addMetaField, crFilter, escapeURI, extractSpaces,+                           safeRead, underlineSpan) import Text.Pandoc.Walk-import qualified Data.Map as M-import Data.Maybe ( fromMaybe, isJust)-import Data.List ( intercalate, isInfixOf, isPrefixOf )-import Data.Char ( isDigit )-import Control.Monad ( guard, when, mzero, void, unless )-import Control.Arrow ((***))-import Control.Applicative ( (<|>) )-import Data.Monoid (First (..))-import Text.Printf (printf)-import Debug.Trace (trace)-import Text.TeXMath (readMathML, writeTeX)-import Data.Default (Default (..), def)-import Control.Monad.Reader (Reader,ask, asks, local, runReader)-import Network.URI (URI, parseURIReference, nonStrictRelativeTo)-import Text.Pandoc.Error-import Text.Pandoc.CSS (foldOrElse, pickStyleAttrProps)-import Data.Monoid ((<>)) import Text.Parsec.Error-import qualified Data.Set as Set+import Text.TeXMath (readMathML, writeTeX)  -- | Convert HTML-formatted string to 'Pandoc' document.-readHtml :: ReaderOptions -- ^ Reader options-         -> String        -- ^ String to parse (assumes @'\n'@ line endings)-         -> Either PandocError Pandoc-readHtml opts inp =-    mapLeft (ParseFailure . getError) . flip runReader def $-      runParserT parseDoc-        (HTMLState def{ stateOptions = opts } [] Nothing Set.empty M.empty)-        "source" tags-    where tags = stripPrefixes . canonicalizeTags $-                   parseTagsOptions parseOptions{ optTagPosition = True } inp-          parseDoc = do-             blocks <- (fixPlains False) . mconcat <$> manyTill block eof-             meta <- stateMeta . parserState <$> getState-             bs' <- replaceNotes (B.toList blocks)-             return $ Pandoc meta bs'-          getError (errorMessages -> ms) = case ms of-                                                []    -> ""-                                                (m:_) -> messageString m+readHtml :: PandocMonad m+         => ReaderOptions -- ^ Reader options+         -> Text        -- ^ String to parse (assumes @'\n'@ line endings)+         -> m Pandoc+readHtml opts inp = do+  let tags = stripPrefixes . canonicalizeTags $+             parseTagsOptions parseOptions{ optTagPosition = True }+             (crFilter inp)+      parseDoc = do+        blocks <- (fixPlains False) . mconcat <$> manyTill block eof+        meta <- stateMeta . parserState <$> getState+        bs' <- replaceNotes (B.toList blocks)+        reportLogMessages+        return $ Pandoc meta bs'+      getError (errorMessages -> ms) = case ms of+                                         []    -> ""+                                         (m:_) -> messageString m+  result <- flip runReaderT def $+       runParserT parseDoc+       (HTMLState def{ stateOptions = opts } [] Nothing Set.empty M.empty [])+       "source" tags+  case result of+    Right doc -> return doc+    Left  err -> throwError $ PandocParseError $ getError err -replaceNotes :: [Block] -> TagParser [Block]+replaceNotes :: PandocMonad m => [Block] -> TagParser m [Block] replaceNotes = walkM replaceNotes' -replaceNotes' :: Inline -> TagParser Inline+replaceNotes' :: PandocMonad m => Inline -> TagParser m Inline replaceNotes' (RawInline (Format "noteref") ref) = maybe (Str "") (Note . B.toList) . lookup ref <$> getNotes   where     getNotes = noteTable <$> getState@@ -105,38 +120,46 @@      noteTable   :: [(String, Blocks)],      baseHref    :: Maybe URI,      identifiers :: Set.Set String,-     headerMap   :: M.Map Inlines String+     headerMap   :: M.Map Inlines String,+     logMessages :: [LogMessage]   }  data HTMLLocal = HTMLLocal { quoteContext :: QuoteContext-                           , inChapter :: Bool -- ^ Set if in chapter section-                           , inPlain :: Bool -- ^ Set if in pPlain+                           , inChapter    :: Bool -- ^ Set if in chapter section+                           , inPlain      :: Bool -- ^ Set if in pPlain                            } -setInChapter :: HTMLParser s a -> HTMLParser s a+setInChapter :: PandocMonad m => HTMLParser m s a -> HTMLParser m s a setInChapter = local (\s -> s {inChapter = True}) -setInPlain :: HTMLParser s a -> HTMLParser s a+setInPlain :: PandocMonad m => HTMLParser m s a -> HTMLParser m s a setInPlain = local (\s -> s {inPlain = True}) -type HTMLParser s = ParserT s HTMLState (Reader HTMLLocal)+type HTMLParser m s = ParserT s HTMLState (ReaderT HTMLLocal m) -type TagParser = HTMLParser [Tag String]+type TagParser m = HTMLParser m [Tag Text] -pBody :: TagParser Blocks+pHtml :: PandocMonad m => TagParser m Blocks+pHtml = try $ do+  (TagOpen "html" attr) <- lookAhead $ pAnyTag+  for_ (lookup "lang" attr) $+    updateState . B.setMeta "lang" . B.text . T.unpack+  pInTags "html" block++pBody :: PandocMonad m => TagParser m Blocks pBody = pInTags "body" block -pHead :: TagParser Blocks+pHead :: PandocMonad m => TagParser m Blocks pHead = pInTags "head" $ pTitle <|> pMetaTag <|> pBaseTag <|> (mempty <$ pAnyTag)   where pTitle = pInTags "title" inline >>= setTitle . trimInlines         setTitle t = mempty <$ (updateState $ B.setMeta "title" t)         pMetaTag = do-          mt <- pSatisfy (~== TagOpen "meta" [])-          let name = fromAttrib "name" mt+          mt <- pSatisfy (matchTagOpen "meta" [])+          let name = T.unpack $ fromAttrib "name" mt           if null name              then return mempty              else do-               let content = fromAttrib "content" mt+               let content = T.unpack $ fromAttrib "content" mt                updateState $ \s ->                  let ps = parserState s in                  s{ parserState = ps{@@ -144,15 +167,13 @@                                    (stateMeta ps) } }                return mempty         pBaseTag = do-          bt <- pSatisfy (~== TagOpen "base" [])+          bt <- pSatisfy (matchTagOpen "base" [])           updateState $ \st -> st{ baseHref =-               parseURIReference $ fromAttrib "href" bt }+               parseURIReference $ T.unpack $ fromAttrib "href" bt }           return mempty -block :: TagParser Blocks+block :: PandocMonad m => TagParser m Blocks block = do-  tr <- getOption readerTrace-  pos <- getPosition   res <- choice             [ eSection             , eSwitch B.para block@@ -166,60 +187,67 @@             , pList             , pHrule             , pTable+            , pHtml             , pHead             , pBody             , pDiv             , pPlain+            , pFigure             , pRawHtmlBlock             ]-  when tr $ trace (printf "line %d: %s" (sourceLine pos)-             (take 60 $ show $ B.toList res)) (return ())+  trace (take 60 $ show $ B.toList res)   return res -namespaces :: [(String, TagParser Inlines)]+namespaces :: PandocMonad m => [(String, TagParser m Inlines)] namespaces = [(mathMLNamespace, pMath True)]  mathMLNamespace :: String mathMLNamespace = "http://www.w3.org/1998/Math/MathML" -eSwitch :: Monoid a => (Inlines -> a) -> TagParser a -> TagParser a+eSwitch :: (PandocMonad m, Monoid a)+        => (Inlines -> a)+        -> TagParser m a+        -> TagParser m a eSwitch constructor parser = try $ do   guardEnabled Ext_epub_html_exts-  pSatisfy (~== TagOpen "switch" [])+  pSatisfy (matchTagOpen "switch" [])   cases <- getFirst . mconcat <$>             manyTill (First <$> (eCase <* skipMany pBlank) )-              (lookAhead $ try $ pSatisfy (~== TagOpen "default" []))+              (lookAhead $ try $ pSatisfy (matchTagOpen "default" []))   skipMany pBlank   fallback <- pInTags "default" (skipMany pBlank *> parser <* skipMany pBlank)   skipMany pBlank-  pSatisfy (~== TagClose "switch")+  pSatisfy (matchTagClose "switch")   return $ maybe fallback constructor cases -eCase :: TagParser (Maybe Inlines)+eCase :: PandocMonad m => TagParser m (Maybe Inlines) eCase = do   skipMany pBlank-  TagOpen _ attr <- lookAhead $ pSatisfy $ (~== TagOpen "case" [])+  TagOpen _ attr' <- lookAhead $ pSatisfy $ (matchTagOpen "case" [])+  let attr = toStringAttr attr'   case (flip lookup namespaces) =<< lookup "required-namespace" attr of     Just p -> Just <$> (pInTags "case" (skipMany pBlank *> p <* skipMany pBlank))-    Nothing -> Nothing <$ manyTill pAnyTag (pSatisfy (~== TagClose "case"))+    Nothing -> Nothing <$ manyTill pAnyTag (pSatisfy (matchTagClose "case")) -eFootnote :: TagParser ()+eFootnote :: PandocMonad m => TagParser m () eFootnote = try $ do   let notes = ["footnote", "rearnote"]   guardEnabled Ext_epub_html_exts-  (TagOpen tag attr) <- lookAhead $ pAnyTag+  (TagOpen tag attr') <- lookAhead $ pAnyTag+  let attr = toStringAttr attr'   guard (maybe False (flip elem notes) (lookup "type" attr))   let ident = fromMaybe "" (lookup "id" attr)   content <- pInTags tag block   addNote ident content -addNote :: String -> Blocks -> TagParser ()+addNote :: PandocMonad m => String -> Blocks -> TagParser m () addNote uid cont = updateState (\s -> s {noteTable = (uid, cont) : (noteTable s)}) -eNoteref :: TagParser Inlines+eNoteref :: PandocMonad m => TagParser m Inlines eNoteref = try $ do   guardEnabled Ext_epub_html_exts-  TagOpen tag attr <- lookAhead $ pAnyTag+  TagOpen tag attr' <- lookAhead $ pAnyTag+  let attr = toStringAttr attr'   guard (maybe False (== "noteref") (lookup "type" attr))   let ident = maybe "" (dropWhile (== '#')) (lookup "href" attr)   guard (not (null ident))@@ -227,33 +255,38 @@   return $ B.rawInline "noteref" ident  -- Strip TOC if there is one, better to generate again-eTOC :: TagParser ()+eTOC :: PandocMonad m => TagParser m () eTOC = try $ do   guardEnabled Ext_epub_html_exts   (TagOpen tag attr) <- lookAhead $ pAnyTag   guard (maybe False (== "toc") (lookup "type" attr))   void (pInTags tag block) -pList :: TagParser Blocks+pList :: PandocMonad m => TagParser m Blocks pList = pBulletList <|> pOrderedList <|> pDefinitionList -pBulletList :: TagParser Blocks+pBulletList :: PandocMonad m => TagParser m Blocks pBulletList = try $ do-  pSatisfy (~== TagOpen "ul" [])+  pSatisfy (matchTagOpen "ul" [])   let nonItem = pSatisfy (\t ->                   not (tagOpen (`elem` ["li","ol","ul","dl"]) (const True) t) &&-                  not (t ~== TagClose "ul"))+                  not (matchTagClose "ul" t))   -- note: if they have an <ol> or <ul> not in scope of a <li>,   -- treat it as a list item, though it's not valid xhtml...   skipMany nonItem   items <- manyTill (pListItem nonItem) (pCloses "ul")   return $ B.bulletList $ map (fixPlains True) items -pListItem :: TagParser a -> TagParser Blocks+pListItem :: PandocMonad m => TagParser m a -> TagParser m Blocks pListItem nonItem = do-  TagOpen _ attr <- lookAhead $ pSatisfy (~== TagOpen "li" [])-  let liDiv = maybe mempty (\x -> B.divWith (x, [], []) mempty) (lookup "id" attr)-  (liDiv <>) <$> pInTags "li" block <* skipMany nonItem+  TagOpen _ attr' <- lookAhead $ pSatisfy (matchTagOpen "li" [])+  let attr = toStringAttr attr'+  let addId ident bs = case B.toList bs of+                           (Plain ils:xs) -> B.fromList (Plain+                                [Span (ident, [], []) ils] : xs)+                           _ -> B.divWith (ident, [], []) bs+  (maybe id addId (lookup "id" attr)) <$>+    pInTags "li" block <* skipMany nonItem  parseListStyleType :: String -> ListNumberStyle parseListStyleType "lower-roman" = LowerRoman@@ -271,9 +304,10 @@ parseTypeAttr "1" = Decimal parseTypeAttr _   = DefaultStyle -pOrderedList :: TagParser Blocks+pOrderedList :: PandocMonad m => TagParser m Blocks pOrderedList = try $ do-  TagOpen _ attribs <- pSatisfy (~== TagOpen "ol" [])+  TagOpen _ attribs' <- pSatisfy (matchTagOpen "ol" [])+  let attribs = toStringAttr attribs'   let (start, style) = (sta', sty')                        where sta = fromMaybe "1" $                                    lookup "start" attribs@@ -295,23 +329,23 @@                                       ]   let nonItem = pSatisfy (\t ->                   not (tagOpen (`elem` ["li","ol","ul","dl"]) (const True) t) &&-                  not (t ~== TagClose "ol"))+                  not (matchTagClose "ol" t))   -- note: if they have an <ol> or <ul> not in scope of a <li>,   -- treat it as a list item, though it's not valid xhtml...   skipMany nonItem   items <- manyTill (pListItem nonItem) (pCloses "ol")   return $ B.orderedListWith (start, style, DefaultDelim) $ map (fixPlains True) items -pDefinitionList :: TagParser Blocks+pDefinitionList :: PandocMonad m => TagParser m Blocks pDefinitionList = try $ do-  pSatisfy (~== TagOpen "dl" [])+  pSatisfy (matchTagOpen "dl" [])   items <- manyTill pDefListItem (pCloses "dl")   return $ B.definitionList items -pDefListItem :: TagParser (Inlines, [Blocks])+pDefListItem :: PandocMonad m => TagParser m (Inlines, [Blocks]) pDefListItem = try $ do-  let nonItem = pSatisfy (\t -> not (t ~== TagOpen "dt" []) &&-                  not (t ~== TagOpen "dd" []) && not (t ~== TagClose "dl"))+  let nonItem = pSatisfy (\t -> not (matchTagOpen "dt" [] t) &&+                  not (matchTagOpen "dd" [] t) && not (matchTagClose "dl" t))   terms <- many1 (try $ skipMany nonItem >> pInTags "dt" inline)   defs  <- many1 (try $ skipMany nonItem >> pInTags "dd" block)   skipMany nonItem@@ -322,133 +356,155 @@ fixPlains inList bs = if any isParaish bs'                          then B.fromList $ map plainToPara bs'                          else bs-  where isParaish (Para _) = True-        isParaish (CodeBlock _ _) = True-        isParaish (Header _ _ _) = True-        isParaish (BlockQuote _) = True-        isParaish (BulletList _) = not inList-        isParaish (OrderedList _ _) = not inList+  where isParaish (Para _)           = True+        isParaish (CodeBlock _ _)    = True+        isParaish (Header _ _ _)     = True+        isParaish (BlockQuote _)     = True+        isParaish (BulletList _)     = not inList+        isParaish (OrderedList _ _)  = not inList         isParaish (DefinitionList _) = not inList-        isParaish _        = False+        isParaish _                  = False         plainToPara (Plain xs) = Para xs-        plainToPara x = x+        plainToPara x          = x         bs' = B.toList bs -pRawTag :: TagParser String+pRawTag :: PandocMonad m => TagParser m Text pRawTag = do   tag <- pAnyTag   let ignorable x = x `elem` ["html","head","body","!DOCTYPE","?xml"]   if tagOpen ignorable (const True) tag || tagClose ignorable tag-     then return []+     then return mempty      else return $ renderTags' [tag] -pDiv :: TagParser Blocks+pDiv :: PandocMonad m => TagParser m Blocks pDiv = try $ do   guardEnabled Ext_native_divs-  let isDivLike "div" = True+  let isDivLike "div"     = True       isDivLike "section" = True-      isDivLike _ = False-  TagOpen tag attr <- lookAhead $ pSatisfy $ tagOpen isDivLike (const True)+      isDivLike "main"    = True+      isDivLike _         = False+  TagOpen tag attr' <- lookAhead $ pSatisfy $ tagOpen isDivLike (const True)+  let attr = toStringAttr attr'   contents <- pInTags tag block   let (ident, classes, kvs) = mkAttr attr   let classes' = if tag == "section"                     then "section":classes                     else classes-  return $ B.divWith (ident, classes', kvs) contents+      kvs' = if tag == "main" && isNothing (lookup "role" kvs)+               then ("role", "main"):kvs+               else kvs+  return $ B.divWith (ident, classes', kvs') contents -pRawHtmlBlock :: TagParser Blocks+pRawHtmlBlock :: PandocMonad m => TagParser m Blocks pRawHtmlBlock = do-  raw <- pHtmlBlock "script" <|> pHtmlBlock "style" <|> pRawTag-  parseRaw <- getOption readerParseRaw-  if parseRaw && not (null raw)+  raw <- T.unpack <$> (pHtmlBlock "script" <|> pHtmlBlock "style" <|> pRawTag)+  exts <- getOption readerExtensions+  if extensionEnabled Ext_raw_html exts && not (null raw)      then return $ B.rawBlock "html" raw-     else return mempty+     else ignore raw -pHtmlBlock :: String -> TagParser String+ignore :: (Monoid a, PandocMonad m) => String -> TagParser m a+ignore raw = do+  pos <- getPosition+  -- raw can be null for tags like <!DOCTYPE>; see paRawTag+  -- in this case we don't want a warning:+  unless (null raw) $+    logMessage $ SkippedContent raw pos+  return mempty++pHtmlBlock :: PandocMonad m => Text -> TagParser m Text pHtmlBlock t = try $ do-  open <- pSatisfy (~== TagOpen t [])-  contents <- manyTill pAnyTag (pSatisfy (~== TagClose t))-  return $ renderTags' $ [open] ++ contents ++ [TagClose t]+  open <- pSatisfy (matchTagOpen t [])+  contents <- manyTill pAnyTag (pSatisfy (matchTagClose t))+  return $ renderTags' $ [open] <> contents <> [TagClose t]  -- Sets chapter context-eSection :: TagParser Blocks+eSection :: PandocMonad m => TagParser m Blocks eSection = try $ do-  let matchChapter as = maybe False (isInfixOf "chapter") (lookup "type" as)+  let matchChapter as = maybe False (T.isInfixOf "chapter") (lookup "type" as)   let sectTag = tagOpen (`elem` sectioningContent) matchChapter   TagOpen tag _ <- lookAhead $ pSatisfy sectTag   setInChapter (pInTags tag block) -headerLevel :: String -> TagParser Int+headerLevel :: PandocMonad m => Text -> TagParser m Int headerLevel tagtype = do-  let level = read (drop 1 tagtype)-  (try $ do-    guardEnabled Ext_epub_html_exts-    asks inChapter >>= guard-    return (level - 1))-    <|>-      return level+  case safeRead (T.unpack (T.drop 1 tagtype)) of+        Just level ->+          (try $ do+            guardEnabled Ext_epub_html_exts+            asks inChapter >>= guard+            return (level - 1))+            <|>+              return level+        Nothing -> fail "Could not retrieve header level" -eTitlePage :: TagParser ()+eTitlePage :: PandocMonad m => TagParser m () eTitlePage = try $ do-  let isTitlePage as = maybe False (isInfixOf "titlepage") (lookup "type" as)+  let isTitlePage as = maybe False (T.isInfixOf "titlepage") (lookup "type" as)   let groupTag = tagOpen (\x -> x `elem` groupingContent || x == "section")                           isTitlePage   TagOpen tag _ <- lookAhead $ pSatisfy groupTag   () <$ pInTags tag block -pHeader :: TagParser Blocks+pHeader :: PandocMonad m => TagParser m Blocks pHeader = try $ do-  TagOpen tagtype attr <- pSatisfy $+  TagOpen tagtype attr' <- pSatisfy $                            tagOpen (`elem` ["h1","h2","h3","h4","h5","h6"])                            (const True)-  let bodyTitle = TagOpen tagtype attr ~== TagOpen "h1" [("class","title")]+  let attr = toStringAttr attr'+  let bodyTitle = TagOpen tagtype attr' ~== TagOpen ("h1" :: Text)+                                               [("class","title")]   level <- headerLevel tagtype   contents <- trimInlines . mconcat <$> manyTill inline (pCloses tagtype <|> eof)   let ident = fromMaybe "" $ lookup "id" attr   let classes = maybe [] words $ lookup "class" attr   let keyvals = [(k,v) | (k,v) <- attr, k /= "class", k /= "id"]-  attr' <- registerHeader (ident, classes, keyvals) contents+  attr'' <- registerHeader (ident, classes, keyvals) contents   return $ if bodyTitle               then mempty  -- skip a representation of the title in the body-              else B.headerWith attr' level contents+              else B.headerWith attr'' level contents -pHrule :: TagParser Blocks+pHrule :: PandocMonad m => TagParser m Blocks pHrule = do   pSelfClosing (=="hr") (const True)   return B.horizontalRule -pTable :: TagParser Blocks+pTable :: PandocMonad m => TagParser m Blocks pTable = try $ do-  TagOpen _ _ <- pSatisfy (~== TagOpen "table" [])+  TagOpen _ _ <- pSatisfy (matchTagOpen "table" [])   skipMany pBlank   caption <- option mempty $ pInTags "caption" inline <* skipMany pBlank   widths' <- (mconcat <$> many1 pColgroup) <|> many pCol   let pTh = option [] $ pInTags "tr" (pCell "th")-      pTr = try $ skipMany pBlank >> pInTags "tr" (pCell "td" <|> pCell "th")+      pTr = try $ skipMany pBlank >>+                  pInTags "tr" (pCell "td" <|> pCell "th")       pTBody = do pOptInTag "tbody" $ many1 pTr   head'' <- pOptInTag "thead" pTh-  head'  <- pOptInTag "tbody" $ do-              if null head''-                 then pTh-                 else return head''+  head'  <- map snd <$>+             (pOptInTag "tbody" $+               if null head'' then pTh else return head'')   rowsLs <- many pTBody   rows'  <- pOptInTag "tfoot" $ many pTr-  TagClose _ <- pSatisfy (~== TagClose "table")-  let rows'' = (concat rowsLs) ++ rows'+  TagClose _ <- pSatisfy (matchTagClose "table")+  let rows'' = (concat rowsLs) <> rows'+  let rows''' = map (map snd) rows''+  -- let rows''' = map (map snd) rows''   -- fail on empty table-  guard $ not $ null head' && null rows''+  guard $ not $ null head' && null rows'''   let isSinglePlain x = case B.toList x of                              []        -> True                              [Plain _] -> True                              _         -> False-  let isSimple = all isSinglePlain $ concat (head':rows'')-  let cols = length $ if null head' then head rows'' else head'+  let isSimple = all isSinglePlain $ concat (head':rows''')+  let cols = length $ if null head' then head rows''' else head'   -- add empty cells to short rows   let addEmpties r = case cols - length r of-                           n | n > 0 -> r ++ replicate n mempty+                           n | n > 0 -> r <> replicate n mempty                              | otherwise -> r-  let rows = map addEmpties rows''-  let aligns = replicate cols AlignDefault+  let rows = map addEmpties rows'''+  let aligns = case rows'' of+                    (cs:_) -> map fst cs+                    _      -> replicate cols AlignDefault   let widths = if null widths'                   then if isSimple                        then replicate cols 0@@ -456,80 +512,113 @@                   else widths'   return $ B.table caption (zip aligns widths) head' rows -pCol :: TagParser Double+pCol :: PandocMonad m => TagParser m Double pCol = try $ do-  TagOpen _ attribs <- pSatisfy (~== TagOpen "col" [])+  TagOpen _ attribs' <- pSatisfy (matchTagOpen "col" [])+  let attribs = toStringAttr attribs'   skipMany pBlank-  optional $ pSatisfy (~== TagClose "col")+  optional $ pSatisfy (matchTagClose "col")   skipMany pBlank   return $ case lookup "width" attribs of            Nothing -> case lookup "style" attribs of                Just ('w':'i':'d':'t':'h':':':xs) | '%' `elem` xs ->                  fromMaybe 0.0 $ safeRead ('0':'.':filter-                   (`notElem` " \t\r\n%'\";") xs)+                   (`notElem` (" \t\r\n%'\";" :: [Char])) xs)                _ -> 0.0            Just x | not (null x) && last x == '%' ->              fromMaybe 0.0 $ safeRead ('0':'.':init x)            _ -> 0.0 -pColgroup :: TagParser [Double]+pColgroup :: PandocMonad m => TagParser m [Double] pColgroup = try $ do-  pSatisfy (~== TagOpen "colgroup" [])+  pSatisfy (matchTagOpen "colgroup" [])   skipMany pBlank   manyTill pCol (pCloses "colgroup" <|> eof) <* skipMany pBlank -noColOrRowSpans :: Tag String -> Bool+noColOrRowSpans :: Tag Text -> Bool noColOrRowSpans t = isNullOrOne "colspan" && isNullOrOne "rowspan"   where isNullOrOne x = case fromAttrib x t of                               ""  -> True                               "1" -> True                               _   -> False -pCell :: String -> TagParser [Blocks]+pCell :: PandocMonad m => Text -> TagParser m [(Alignment, Blocks)] pCell celltype = try $ do   skipMany pBlank+  tag <- lookAhead $+           pSatisfy (\t -> t ~== TagOpen celltype [] && noColOrRowSpans t)+  let extractAlign' []                 = ""+      extractAlign' ("text-align":x:_) = x+      extractAlign' (_:xs)             = extractAlign' xs+  let extractAlign = extractAlign' . wordsBy (`elem` [' ','\t',';',':'])+  let align = case maybeFromAttrib "align" tag `mplus`+                   (extractAlign <$> maybeFromAttrib "style" tag) of+                   Just "left"   -> AlignLeft+                   Just "right"  -> AlignRight+                   Just "center" -> AlignCenter+                   _             -> AlignDefault   res <- pInTags' celltype noColOrRowSpans block   skipMany pBlank-  return [res]+  return [(align, res)] -pBlockQuote :: TagParser Blocks+pBlockQuote :: PandocMonad m => TagParser m Blocks pBlockQuote = do   contents <- pInTags "blockquote" block   return $ B.blockQuote $ fixPlains False contents -pPlain :: TagParser Blocks+pPlain :: PandocMonad m => TagParser m Blocks pPlain = do   contents <- setInPlain $ trimInlines . mconcat <$> many1 inline   if B.isNull contents      then return mempty      else return $ B.plain contents -pPara :: TagParser Blocks+pPara :: PandocMonad m => TagParser m Blocks pPara = do   contents <- trimInlines <$> pInTags "p" inline   return $ B.para contents -pCodeBlock :: TagParser Blocks+pFigure :: PandocMonad m => TagParser m Blocks+pFigure = try $ do+  TagOpen _ _ <- pSatisfy (matchTagOpen "figure" [])+  skipMany pBlank+  let pImg  = (\x -> (Just x, Nothing)) <$>+               (pOptInTag "p" pImage <* skipMany pBlank)+      pCapt = (\x -> (Nothing, Just x)) <$>+               (pInTags "figcaption" inline <* skipMany pBlank)+      pSkip = (Nothing, Nothing) <$ pSatisfy (not . matchTagClose "figure")+  res <- many (pImg <|> pCapt <|> pSkip)+  let mbimg = msum $ map fst res+  let mbcap = msum $ map snd res+  TagClose _ <- pSatisfy (matchTagClose "figure")+  let caption = fromMaybe mempty mbcap+  case B.toList <$> mbimg of+       Just [Image attr _ (url, tit)] ->+         return $ B.para $ B.imageWith attr url ("fig:" ++ tit) caption+       _ -> mzero++pCodeBlock :: PandocMonad m => TagParser m Blocks pCodeBlock = try $ do-  TagOpen _ attr <- pSatisfy (~== TagOpen "pre" [])+  TagOpen _ attr' <- pSatisfy (matchTagOpen "pre" [])+  let attr = toStringAttr attr'   contents <- manyTill pAnyTag (pCloses "pre" <|> eof)   let rawText = concatMap tagToString contents   -- drop leading newline if any   let result' = case rawText of-                     '\n':xs  -> xs-                     _        -> rawText+                     '\n':xs -> xs+                     _       -> rawText   -- drop trailing newline if any   let result = case reverse result' of-                    '\n':_   -> init result'-                    _        -> result'+                    '\n':_ -> init result'+                    _      -> result'   return $ B.codeBlockWith (mkAttr attr) result -tagToString :: Tag String -> String-tagToString (TagText s) = s+tagToString :: Tag Text -> String+tagToString (TagText s)      = T.unpack s tagToString (TagOpen "br" _) = "\n"-tagToString _ = ""+tagToString _                = "" -inline :: TagParser Inlines+inline :: PandocMonad m => TagParser m Inlines inline = choice            [ eNoteref            , eSwitch id inline@@ -540,6 +629,7 @@            , pSuperscript            , pSubscript            , pStrikeout+           , pUnderline            , pLineBreak            , pLink            , pImage@@ -549,30 +639,31 @@            , pRawHtmlInline            ] -pLocation :: TagParser ()+pLocation :: PandocMonad m => TagParser m () pLocation = do   (TagPosition r c) <- pSat isTagPosition   setPosition $ newPos "input" r c -pSat :: (Tag String -> Bool) -> TagParser (Tag String)+pSat :: PandocMonad m => (Tag Text -> Bool) -> TagParser m (Tag Text) pSat f = do   pos <- getPosition   token show (const pos) (\x -> if f x then Just x else Nothing) -pSatisfy :: (Tag String -> Bool) -> TagParser (Tag String)+pSatisfy :: PandocMonad m => (Tag Text -> Bool) -> TagParser m (Tag Text) pSatisfy f = try $ optional pLocation >> pSat f -pAnyTag :: TagParser (Tag String)+pAnyTag :: PandocMonad m => TagParser m (Tag Text) pAnyTag = pSatisfy (const True) -pSelfClosing :: (String -> Bool) -> ([Attribute String] -> Bool)-             -> TagParser (Tag String)+pSelfClosing :: PandocMonad m+             => (Text -> Bool) -> ([Attribute Text] -> Bool)+             -> TagParser m (Tag Text) pSelfClosing f g = do   open <- pSatisfy (tagOpen f g)   optional $ pSatisfy (tagClose f)   return open -pQ :: TagParser Inlines+pQ :: PandocMonad m => TagParser m Inlines pQ = do   context <- asks quoteContext   let quoteType = case context of@@ -587,45 +678,50 @@   withQuoteContext innerQuoteContext $     pInlinesInTags "q" constructor -pEmph :: TagParser Inlines+pEmph :: PandocMonad m => TagParser m Inlines pEmph = pInlinesInTags "em" B.emph <|> pInlinesInTags "i" B.emph -pStrong :: TagParser Inlines+pStrong :: PandocMonad m => TagParser m Inlines pStrong = pInlinesInTags "strong" B.strong <|> pInlinesInTags "b" B.strong -pSuperscript :: TagParser Inlines+pSuperscript :: PandocMonad m => TagParser m Inlines pSuperscript = pInlinesInTags "sup" B.superscript -pSubscript :: TagParser Inlines+pSubscript :: PandocMonad m => TagParser m Inlines pSubscript = pInlinesInTags "sub" B.subscript -pStrikeout :: TagParser Inlines+pStrikeout :: PandocMonad m => TagParser m Inlines pStrikeout = do   pInlinesInTags "s" B.strikeout <|>     pInlinesInTags "strike" B.strikeout <|>     pInlinesInTags "del" B.strikeout <|>-    try (do pSatisfy (~== TagOpen "span" [("class","strikeout")])+    try (do pSatisfy (matchTagOpen "span" [("class","strikeout")])             contents <- mconcat <$> manyTill inline (pCloses "span")             return $ B.strikeout contents) -pLineBreak :: TagParser Inlines+pUnderline :: PandocMonad m => TagParser m Inlines+pUnderline = pInlinesInTags "u" underlineSpan <|> pInlinesInTags "ins" underlineSpan++pLineBreak :: PandocMonad m => TagParser m Inlines pLineBreak = do   pSelfClosing (=="br") (const True)   return B.linebreak  -- Unlike fromAttrib from tagsoup, this distinguishes -- between a missing attribute and an attribute with empty content.-maybeFromAttrib :: String -> Tag String -> Maybe String-maybeFromAttrib name (TagOpen _ attrs) = lookup name attrs+maybeFromAttrib :: String -> Tag Text -> Maybe String+maybeFromAttrib name (TagOpen _ attrs) =+  T.unpack <$> lookup (T.pack name) attrs maybeFromAttrib _ _ = Nothing -pLink :: TagParser Inlines+pLink :: PandocMonad m => TagParser m Inlines pLink = try $ do   tag <- pSatisfy $ tagOpenLit "a" (const True)-  let title = fromAttrib "title" tag+  let title = T.unpack $ fromAttrib "title" tag   -- take id from id attribute if present, otherwise name-  let uid = maybe (fromAttrib "name" tag) id $ maybeFromAttrib "id" tag-  let cls = words $ fromAttrib "class" tag+  let uid = maybe (T.unpack $ fromAttrib "name" tag) id $+               maybeFromAttrib "id" tag+  let cls = words $ T.unpack $ fromAttrib "class" tag   lab <- trimInlines . mconcat <$> manyTill inline (pCloses "a")   -- check for href; if href, then a link, otherwise a span   case maybeFromAttrib "href" tag of@@ -639,99 +735,114 @@                         _                   -> url'          return $ B.linkWith (uid, cls, []) (escapeURI url) title lab -pImage :: TagParser Inlines+pImage :: PandocMonad m => TagParser m Inlines pImage = do   tag <- pSelfClosing (=="img") (isJust . lookup "src")   mbBaseHref <- baseHref <$> getState-  let url' = fromAttrib "src" tag+  let url' = T.unpack $ fromAttrib "src" tag   let url = case (parseURIReference url', mbBaseHref) of                  (Just rel, Just bs) -> show (rel `nonStrictRelativeTo` bs)                  _                   -> url'-  let title = fromAttrib "title" tag-  let alt = fromAttrib "alt" tag-  let uid = fromAttrib "id" tag-  let cls = words $ fromAttrib "class" tag+  let title = T.unpack $ fromAttrib "title" tag+  let alt = T.unpack $ fromAttrib "alt" tag+  let uid = T.unpack $ fromAttrib "id" tag+  let cls = words $ T.unpack $ fromAttrib "class" tag   let getAtt k = case fromAttrib k tag of                    "" -> []-                   v  -> [(k, v)]+                   v  -> [(T.unpack k, T.unpack v)]   let kvs = concat $ map getAtt ["width", "height", "sizes", "srcset"]   return $ B.imageWith (uid, cls, kvs) (escapeURI url) title (B.text alt) -pCode :: TagParser Inlines+pCode :: PandocMonad m => TagParser m Inlines pCode = try $ do-  (TagOpen open attr) <- pSatisfy $ tagOpen (`elem` ["code","tt"]) (const True)+  (TagOpen open attr') <- pSatisfy $ tagOpen (`elem` ["code","tt"]) (const True)+  let attr = toStringAttr attr'   result <- manyTill pAnyTag (pCloses open)-  return $ B.codeWith (mkAttr attr) $ intercalate " " $ lines $ innerText result+  return $ B.codeWith (mkAttr attr) $ intercalate " " $ lines $ T.unpack $+           innerText result -pSpan :: TagParser Inlines+pSpan :: PandocMonad m => TagParser m Inlines pSpan = try $ do   guardEnabled Ext_native_spans-  TagOpen _ attr <- lookAhead $ pSatisfy $ tagOpen (=="span") (const True)+  TagOpen _ attr' <- lookAhead $ pSatisfy $ tagOpen (=="span") (const True)+  let attr = toStringAttr attr'   contents <- pInTags "span" inline-  let isSmallCaps = fontVariant == "small-caps"+  let isSmallCaps = fontVariant == "small-caps" || "smallcaps" `elem` classes                     where styleAttr   = fromMaybe "" $ lookup "style" attr                           fontVariant = fromMaybe "" $ pickStyleAttrProps ["font-variant"] styleAttr+                          classes     = fromMaybe [] $+                                          words <$> lookup "class" attr   let tag = if isSmallCaps then B.smallcaps else B.spanWith (mkAttr attr)   return $ tag contents -pRawHtmlInline :: TagParser Inlines+pRawHtmlInline :: PandocMonad m => TagParser m Inlines pRawHtmlInline = do   inplain <- asks inPlain   result <- pSatisfy (tagComment (const True))             <|> if inplain                    then pSatisfy (not . isBlockTag)                    else pSatisfy isInlineTag-  parseRaw <- getOption readerParseRaw-  if parseRaw-     then return $ B.rawInline "html" $ renderTags' [result]-     else return mempty+  exts <- getOption readerExtensions+  let raw = T.unpack $ renderTags' [result]+  if extensionEnabled Ext_raw_html exts+     then return $ B.rawInline "html" raw+     else ignore raw  mathMLToTeXMath :: String -> Either String String mathMLToTeXMath s = writeTeX <$> readMathML s -pMath :: Bool -> TagParser Inlines+toStringAttr :: [(Text, Text)] -> [(String, String)]+toStringAttr = map go+  where go (x,y) = (T.unpack x, T.unpack y)++pMath :: PandocMonad m => Bool -> TagParser m Inlines pMath inCase = try $ do-  open@(TagOpen _ attr) <- pSatisfy $ tagOpen (=="math") (const True)+  open@(TagOpen _ attr') <- pSatisfy $ tagOpen (=="math") (const True)   -- we'll assume math tags are MathML unless specially marked   -- otherwise...+  let attr = toStringAttr attr'   unless inCase $     guard (maybe True (== mathMLNamespace) (lookup "xmlns" attr))-  contents <- manyTill pAnyTag (pSatisfy (~== TagClose "math"))-  case mathMLToTeXMath (renderTags $ [open] ++ contents ++ [TagClose "math"]) of+  contents <- manyTill pAnyTag (pSatisfy (matchTagClose "math"))+  case mathMLToTeXMath (T.unpack $ renderTags $+          [open] <> contents <> [TagClose "math"]) of        Left _   -> return $ B.spanWith ("",["math"],attr) $ B.text $-                             innerText contents+                             T.unpack $ innerText contents        Right [] -> return mempty        Right x  -> return $ case lookup "display" attr of                                  Just "block" -> B.displayMath x                                  _            -> B.math x -pInlinesInTags :: String -> (Inlines -> Inlines)-               -> TagParser Inlines+pInlinesInTags :: PandocMonad m => Text -> (Inlines -> Inlines)+               -> TagParser m Inlines pInlinesInTags tagtype f = extractSpaces f <$> pInTags tagtype inline -pInTags :: (Monoid a) => String -> TagParser a -> TagParser a+pInTags :: (PandocMonad m, Monoid a) => Text -> TagParser m a -> TagParser m a pInTags tagtype parser = pInTags' tagtype (const True) parser -pInTags' :: (Monoid a) => String -> (Tag String -> Bool) -> TagParser a-                       -> TagParser a+pInTags' :: (PandocMonad m, Monoid a)+         => Text+         -> (Tag Text -> Bool)+         -> TagParser m a+         -> TagParser m a pInTags' tagtype tagtest parser = try $ do   pSatisfy (\t -> t ~== TagOpen tagtype [] && tagtest t)   mconcat <$> manyTill parser (pCloses tagtype <|> eof)  -- parses p, preceeded by an optional opening tag -- and followed by an optional closing tags-pOptInTag :: String -> TagParser a -> TagParser a+pOptInTag :: PandocMonad m => Text -> TagParser m a -> TagParser m a pOptInTag tagtype p = try $ do   skipMany pBlank-  optional $ pSatisfy (~== TagOpen tagtype [])+  optional $ pSatisfy (matchTagOpen tagtype [])   skipMany pBlank   x <- p   skipMany pBlank-  optional $ pSatisfy (~== TagClose tagtype)+  optional $ pSatisfy (matchTagClose tagtype)   skipMany pBlank   return x -pCloses :: String -> TagParser ()+pCloses :: PandocMonad m => Text -> TagParser m () pCloses tagtype = try $ do   t <- lookAhead $ pSatisfy $ \tag -> isTagClose tag || isTagOpen tag   case t of@@ -742,25 +853,31 @@        (TagClose "dl") | tagtype == "dd" -> return ()        (TagClose "table") | tagtype == "td" -> return ()        (TagClose "table") | tagtype == "tr" -> return ()+       (TagClose "td") | tagtype `Set.member` blockHtmlTags -> return ()+       (TagClose "th") | tagtype `Set.member` blockHtmlTags -> return ()+       (TagClose t') | tagtype == "p" && t' `Set.member` blockHtmlTags+                                            -> return () -- see #3794        _ -> mzero -pTagText :: TagParser Inlines+pTagText :: PandocMonad m => TagParser m Inlines pTagText = try $ do   (TagText str) <- pSatisfy isTagText   st <- getState   qu <- ask-  case flip runReader qu $ runParserT (many pTagContents) st "text" str of-       Left _        -> fail $ "Could not parse `" ++ str ++ "'"+  parsed <- lift $ lift $+            flip runReaderT qu $ runParserT (many pTagContents) st "text" str+  case parsed of+       Left _        -> throwError $ PandocParseError $ "Could not parse `" <> T.unpack str <> "'"        Right result  -> return $ mconcat result -pBlank :: TagParser ()+pBlank :: PandocMonad m => TagParser m () pBlank = try $ do   (TagText str) <- pSatisfy isTagText-  guard $ all isSpace str+  guard $ T.all isSpace str -type InlinesParser = HTMLParser String+type InlinesParser m = HTMLParser m Text -pTagContents :: InlinesParser Inlines+pTagContents :: PandocMonad m => InlinesParser m Inlines pTagContents =       B.displayMath <$> mathDisplay   <|> B.math        <$> mathInline@@ -770,7 +887,7 @@   <|> pSymbol   <|> pBad -pStr :: InlinesParser Inlines+pStr :: PandocMonad m => InlinesParser m Inlines pStr = do   result <- many1 $ satisfy $ \c ->                      not (isSpace c) && not (isSpecial c) && not (isBad c)@@ -778,24 +895,24 @@   return $ B.str result  isSpecial :: Char -> Bool-isSpecial '"' = True-isSpecial '\'' = True-isSpecial '.' = True-isSpecial '-' = True-isSpecial '$' = True+isSpecial '"'     = True+isSpecial '\''    = True+isSpecial '.'     = True+isSpecial '-'     = True+isSpecial '$'     = True isSpecial '\8216' = True isSpecial '\8217' = True isSpecial '\8220' = True isSpecial '\8221' = True-isSpecial _ = False+isSpecial _       = False -pSymbol :: InlinesParser Inlines+pSymbol :: PandocMonad m => InlinesParser m Inlines pSymbol = satisfy isSpecial >>= return . B.str . (:[])  isBad :: Char -> Bool isBad c = c >= '\128' && c <= '\159' -- not allowed in HTML -pBad :: InlinesParser Inlines+pBad :: PandocMonad m => InlinesParser m Inlines pBad = do   c <- satisfy isBad   let c' = case c of@@ -829,7 +946,7 @@                 _      -> '?'   return $ B.str [c'] -pSpace :: InlinesParser Inlines+pSpace :: PandocMonad m => InlinesParser m Inlines pSpace = many1 (satisfy isSpace) >>= \xs ->             if '\n' `elem` xs                then return B.softbreak@@ -839,86 +956,96 @@ -- Constants -- -eitherBlockOrInline :: [String]-eitherBlockOrInline = ["audio", "applet", "button", "iframe", "embed",-                       "del", "ins",-                       "progress", "map", "area", "noscript", "script",-                       "object", "svg", "video", "source"]--{--inlineHtmlTags :: [[Char]]-inlineHtmlTags = ["a", "abbr", "acronym", "b", "basefont", "bdo", "big",-                  "br", "cite", "code", "dfn", "em", "font", "i", "img",-                  "input", "kbd", "label", "q", "s", "samp", "select",-                  "small", "span", "strike", "strong", "sub", "sup",-                  "textarea", "tt", "u", "var"]--}+eitherBlockOrInline :: Set.Set Text+eitherBlockOrInline = Set.fromList+  ["audio", "applet", "button", "iframe", "embed",+   "del", "ins", "progress", "map", "area", "noscript", "script",+   "object", "svg", "video", "source"] -blockHtmlTags :: [String]-blockHtmlTags = ["?xml", "!DOCTYPE", "address", "article", "aside",-                 "blockquote", "body", "button", "canvas",-                 "caption", "center", "col", "colgroup", "dd", "dir", "div",-                 "dl", "dt", "fieldset", "figcaption", "figure",-                 "footer", "form", "h1", "h2", "h3", "h4",-                 "h5", "h6", "head", "header", "hgroup", "hr", "html",-                 "isindex", "menu", "noframes", "ol", "output", "p", "pre",-                 "section", "table", "tbody", "textarea",-                 "thead", "tfoot", "ul", "dd",-                 "dt", "frameset", "li", "tbody", "td", "tfoot",-                 "th", "thead", "tr", "script", "style"]+blockHtmlTags :: Set.Set Text+blockHtmlTags = Set.fromList+   ["?xml", "!DOCTYPE", "address", "article", "aside",+    "blockquote", "body", "canvas",+    "caption", "center", "col", "colgroup", "dd", "details",+    "dir", "div", "dl", "dt", "fieldset", "figcaption", "figure",+    "footer", "form", "h1", "h2", "h3", "h4",+    "h5", "h6", "head", "header", "hgroup", "hr", "html",+    "isindex", "main", "menu", "meta", "noframes", "ol", "output", "p", "pre",+    "section", "table", "tbody", "textarea",+    "thead", "tfoot", "ul", "dd",+    "dt", "frameset", "li", "tbody", "td", "tfoot",+    "th", "thead", "tr", "script", "style"]  -- We want to allow raw docbook in markdown documents, so we -- include docbook block tags here too.-blockDocBookTags :: [String]-blockDocBookTags = ["calloutlist", "bibliolist", "glosslist", "itemizedlist",-                    "orderedlist", "segmentedlist", "simplelist",-                    "variablelist", "caution", "important", "note", "tip",-                    "warning", "address", "literallayout", "programlisting",-                    "programlistingco", "screen", "screenco", "screenshot",-                    "synopsis", "example", "informalexample", "figure",-                    "informalfigure", "table", "informaltable", "para",-                    "simpara", "formalpara", "equation", "informalequation",-                    "figure", "screenshot", "mediaobject", "qandaset",-                    "procedure", "task", "cmdsynopsis", "funcsynopsis",-                    "classsynopsis", "blockquote", "epigraph", "msgset",-                    "sidebar", "title"]+blockDocBookTags :: Set.Set Text+blockDocBookTags = Set.fromList+   ["calloutlist", "bibliolist", "glosslist", "itemizedlist",+    "orderedlist", "segmentedlist", "simplelist",+    "variablelist", "caution", "important", "note", "tip",+    "warning", "address", "literallayout", "programlisting",+    "programlistingco", "screen", "screenco", "screenshot",+    "synopsis", "example", "informalexample", "figure",+    "informalfigure", "table", "informaltable", "para",+    "simpara", "formalpara", "equation", "informalequation",+    "figure", "screenshot", "mediaobject", "qandaset",+    "procedure", "task", "cmdsynopsis", "funcsynopsis",+    "classsynopsis", "blockquote", "epigraph", "msgset",+    "sidebar", "title"] -epubTags :: [String]-epubTags = ["case", "switch", "default"]+epubTags :: Set.Set Text+epubTags = Set.fromList ["case", "switch", "default"] -blockTags :: [String]-blockTags = blockHtmlTags ++ blockDocBookTags ++ epubTags+blockTags :: Set.Set Text+blockTags = Set.unions [blockHtmlTags, blockDocBookTags, epubTags] -isInlineTag :: Tag String -> Bool-isInlineTag t = tagOpen isInlineTagName (const True) t ||-                tagClose isInlineTagName t ||-                tagComment (const True) t-                 where isInlineTagName x = x `notElem` blockTags+class NamedTag a where+  getTagName :: a -> Maybe Text -isBlockTag :: Tag String -> Bool-isBlockTag t = tagOpen isBlockTagName (const True) t ||-               tagClose isBlockTagName t ||-               tagComment (const True) t-                 where isBlockTagName ('?':_) = True-                       isBlockTagName ('!':_) = True-                       isBlockTagName x       = x `elem` blockTags-                                             || x `elem` eitherBlockOrInline+instance NamedTag (Tag Text) where+  getTagName (TagOpen t _) = Just t+  getTagName (TagClose t)  = Just t+  getTagName _             = Nothing -isTextTag :: Tag String -> Bool+instance NamedTag (Tag String) where+  getTagName (TagOpen t _) = Just (T.pack t)+  getTagName (TagClose t)  = Just (T.pack t)+  getTagName _             = Nothing++isInlineTag :: NamedTag (Tag a) => Tag a -> Bool+isInlineTag t = isInlineTagName || isCommentTag t+                 where isInlineTagName = case getTagName t of+                                              Just x -> x+                                                  `Set.notMember` blockTags+                                              Nothing -> False++isBlockTag :: NamedTag (Tag a) => Tag a -> Bool+isBlockTag t = isBlockTagName || isTagComment t+                 where isBlockTagName =+                         case getTagName t of+                              Just x+                                | "?" `T.isPrefixOf` x -> True+                                | "!" `T.isPrefixOf` x -> True+                                | otherwise -> x `Set.member` blockTags+                                    || x `Set.member` eitherBlockOrInline+                              Nothing -> False++isTextTag :: Tag a -> Bool isTextTag = tagText (const True) -isCommentTag :: Tag String -> Bool+isCommentTag :: Tag a -> Bool isCommentTag = tagComment (const True)  -- taken from HXT and extended -- See http://www.w3.org/TR/html5/syntax.html sec 8.1.2.4 optional tags-closes :: String -> String -> Bool+closes :: Text -> Text -> Bool _ `closes` "body" = False _ `closes` "html" = False "body" `closes` "head" = True "a" `closes` "a" = True "li" `closes` "li" = True "th" `closes` t | t `elem` ["th","td"] = True+"td" `closes` t | t `elem` ["th","td"] = True "tr" `closes` t | t `elem` ["th","td","tr"] = True "dd" `closes` t | t `elem` ["dt", "dd"] = True "dt" `closes` t | t `elem` ["dt","dd"] = True@@ -926,12 +1053,12 @@ "optgroup" `closes` "optgroup" = True "optgroup" `closes` "option" = True "option" `closes` "option" = True--- http://www.w3.org/TR/html-markup/p.html+-- https://html.spec.whatwg.org/multipage/syntax.html#optional-tags x `closes` "p" | x `elem` ["address", "article", "aside", "blockquote",    "dir", "div", "dl", "fieldset", "footer", "form", "h1", "h2", "h3", "h4",-   "h5", "h6", "header", "hr", "menu", "nav", "ol", "p", "pre", "section",+   "h5", "h6", "header", "hr", "main", "menu", "nav", "ol", "p", "pre", "section",    "table", "ul"] = True-"meta" `closes` "meta" = True+_ `closes` "meta" = True "form" `closes` "form" = True "label" `closes` "label" = True "map" `closes` "map" = True@@ -942,17 +1069,18 @@ "tfoot" `closes` t | t `elem` ["thead","colgroup"] = True "tbody" `closes` t | t `elem` ["tbody","tfoot","thead","colgroup"] = True t `closes` t2 |-   t `elem` ["h1","h2","h3","h4","h5","h6","dl","ol","ul","table","div","p"] &&-   t2 `elem` ["h1","h2","h3","h4","h5","h6","p" ] = True -- not "div"+   t `elem` ["h1","h2","h3","h4","h5","h6","dl","ol","ul","table","div","main","p"] &&+   t2 `elem` ["h1","h2","h3","h4","h5","h6","p" ] = True -- not "div" or "main" t1 `closes` t2 |-   t1 `elem` blockTags &&-   t2 `notElem` (blockTags ++ eitherBlockOrInline) = True+   t1 `Set.member` blockTags &&+   t2 `Set.notMember` blockTags &&+   t2 `Set.notMember` eitherBlockOrInline = True _ `closes` _ = False  --- parsers for use in markdown, textile readers  -- | Matches a stretch of HTML in balanced tags.-htmlInBalanced :: (Monad m)+htmlInBalanced :: (HasReaderOptions st, Monad m)                => (Tag String -> Bool)                -> ParserT String st m String htmlInBalanced f = try $ do@@ -973,8 +1101,11 @@                           let cs = ec - sc                           lscontents <- unlines <$> count ls anyLine                           cscontents <- count cs anyChar-                          (_,closetag) <- htmlTag (~== TagClose tn)-                          return (lscontents ++ cscontents ++ closetag)+                          closetag <- do+                            x <- many (satisfy (/='>'))+                            char '>'+                            return (x <> ">")+                          return (lscontents <> cscontents <> closetag)                         _ -> mzero     _ -> mzero @@ -992,64 +1123,90 @@         go n (t:ts') = (t :) <$> go n ts'         go _ [] = mzero -hasTagWarning :: [Tag String] -> Bool+hasTagWarning :: [Tag a] -> Bool hasTagWarning (TagWarning _:_) = True-hasTagWarning _ = False+hasTagWarning _                = False  -- | Matches a tag meeting a certain condition.-htmlTag :: Monad m+htmlTag :: (HasReaderOptions st, Monad m)         => (Tag String -> Bool)         -> ParserT [Char] st m (Tag String, String) htmlTag f = try $ do   lookAhead (char '<')   inp <- getInput-  let (next : _) = canonicalizeTags $ parseTagsOptions-                       parseOptions{ optTagWarning = False } inp-  guard $ f next+  let ts = canonicalizeTags $ parseTagsOptions+                               parseOptions{ optTagWarning = False+                                           , optTagPosition = True }+                               (inp ++ " ") -- add space to ensure that+                               -- we get a TagPosition after the tag+  (next, ln, col) <- case ts of+                      (TagPosition{} : next : TagPosition ln col : _)+                        | f next -> return (next, ln, col)+                      _ -> mzero++  -- <www.boe.es/buscar/act.php?id=BOE-A-1996-8930#a66>+  -- should NOT be parsed as an HTML tag, see #2277,+  -- so we exclude . even though it's a valid character+  -- in XML elemnet names+  let isNameChar c = isAlphaNum c || c == ':' || c == '-' || c == '_'+  let isName s = case s of+                      []     -> False+                      (c:cs) -> isLetter c && all isNameChar cs++  let endAngle = try $ do char '>'+                          pos <- getPosition+                          guard $ (sourceLine pos == ln &&+                                   sourceColumn pos >= col) ||+                                  sourceLine pos > ln   let handleTag tagname = do-       -- <www.boe.es/buscar/act.php?id=BOE-A-1996-8930#a66>-       -- should NOT be parsed as an HTML tag, see #2277-       guard $ not ('.' `elem` tagname)+       -- basic sanity check, since the parser is very forgiving+       -- and finds tags in stuff like x<y)+       guard $ isName tagname+       guard $ not $ null tagname        -- <https://example.org> should NOT be a tag either.        -- tagsoup will parse it as TagOpen "https:" [("example.org","")]-       guard $ not (null tagname)        guard $ last tagname /= ':'-       rendered <- manyTill anyChar (char '>')-       return (next, rendered ++ ">")+       char '<'+       rendered <- manyTill anyChar endAngle+       return (next, "<" ++ rendered ++ ">")   case next of        TagComment s          | "<!--" `isPrefixOf` inp -> do-          count (length s + 4) anyChar-          skipMany (satisfy (/='>'))-          char '>'-          return (next, "<!--" ++ s ++ "-->")+          char '<'+          manyTill anyChar endAngle+          stripComments <- getOption readerStripComments+          if stripComments+             then return (next, "")+             else return (next, "<!--" <> s <> "-->")          | otherwise -> fail "bogus comment mode, HTML5 parse error"-       TagOpen tagname _attr -> handleTag tagname-       TagClose tagname -> handleTag tagname+       TagOpen tagname attr -> do+         guard $ all (isName . fst) attr+         handleTag tagname+       TagClose tagname ->+         handleTag tagname        _ -> mzero  mkAttr :: [(String, String)] -> Attr mkAttr attr = (attribsId, attribsClasses, attribsKV)   where attribsId = fromMaybe "" $ lookup "id" attr-        attribsClasses = (words $ fromMaybe "" $ lookup "class" attr) ++ epubTypes+        attribsClasses = (words $ fromMaybe "" $ lookup "class" attr) <> epubTypes         attribsKV = filter (\(k,_) -> k /= "class" && k /= "id") attr         epubTypes = words $ fromMaybe "" $ lookup "epub:type" attr  -- Strip namespace prefixes-stripPrefixes :: [Tag String] -> [Tag String]+stripPrefixes :: [Tag Text] -> [Tag Text] stripPrefixes = map stripPrefix -stripPrefix :: Tag String -> Tag String+stripPrefix :: Tag Text -> Tag Text stripPrefix (TagOpen s as) =     TagOpen (stripPrefix' s) (map (stripPrefix' *** id) as) stripPrefix (TagClose s) = TagClose (stripPrefix' s) stripPrefix x = x -stripPrefix' :: String -> String+stripPrefix' :: Text -> Text stripPrefix' s =-  case span (/= ':') s of-    (_, "") -> s-    (_, (_:ts)) -> ts+  if T.null t then s else T.drop 1 t+  where (_, t) = T.span (/= ':') s  isSpace :: Char -> Bool isSpace ' '  = True@@ -1068,9 +1225,13 @@   extractHeaderMap = headerMap   updateHeaderMap  f s = s{ headerMap = f (headerMap s) } +instance HasLogMessages HTMLState where+  addLogMessage m s = s{ logMessages = m : logMessages s }+  getLogMessages = reverse . logMessages+ -- This signature should be more general -- MonadReader HTMLLocal m => HasQuoteContext st m-instance HasQuoteContext st (Reader HTMLLocal) where+instance PandocMonad m => HasQuoteContext HTMLState (ReaderT HTMLLocal m) where   getQuoteContext = asks quoteContext   withQuoteContext q = local (\s -> s{quoteContext = q}) @@ -1088,27 +1249,40 @@   setLastStrPos s st = st {parserState = setLastStrPos s (parserState st)}   getLastStrPos = getLastStrPos . parserState +-- For now we need a special verison here; the one in Shared has String type+renderTags' :: [Tag Text] -> Text+renderTags' = renderTagsOptions+               renderOptions{ optMinimize = matchTags ["hr", "br", "img",+                                                       "meta", "link"]+                            , optRawTag   = matchTags ["script", "style"] }+              where matchTags = \tags -> flip elem tags . T.toLower + -- EPUB Specific -- ---sectioningContent :: [String]+sectioningContent :: [Text] sectioningContent = ["article", "aside", "nav", "section"]  -groupingContent :: [String]+groupingContent :: [Text] groupingContent = ["p", "hr", "pre", "blockquote", "ol"                   , "ul", "li", "dl", "dt", "dt", "dd"                   , "figure", "figcaption", "div", "main"] +matchTagClose :: Text -> (Tag Text -> Bool)+matchTagClose t = (~== TagClose t) +matchTagOpen :: Text -> [(Text, Text)] -> (Tag Text -> Bool)+matchTagOpen t as = (~== TagOpen t as)+ {-  types :: [(String, ([String], Int))] types =  -- Document divisions    map (\s -> (s, (["section", "body"], 0)))     ["volume", "part", "chapter", "division"]-  ++ -- Document section and components+  <> -- Document section and components   [     ("abstract",  ([], 0))] -}
src/Text/Pandoc/Readers/Haddock.hs view
@@ -14,33 +14,40 @@     ( readHaddock     ) where -import Text.Pandoc.Builder (Blocks, Inlines)-import qualified Text.Pandoc.Builder as B-import Data.Monoid ((<>))-import Text.Pandoc.Shared (trim, splitBy)+import Control.Monad.Except (throwError) import Data.List (intersperse, stripPrefix) import Data.Maybe (fromMaybe)-import Text.Pandoc.Definition-import Text.Pandoc.Options+import Data.Monoid ((<>))+import Data.Text (Text, unpack) import Documentation.Haddock.Parser import Documentation.Haddock.Types-import Debug.Trace (trace)-+import Text.Pandoc.Builder (Blocks, Inlines)+import qualified Text.Pandoc.Builder as B+import Text.Pandoc.Class (PandocMonad)+import Text.Pandoc.Definition import Text.Pandoc.Error+import Text.Pandoc.Options+import Text.Pandoc.Shared (crFilter, splitBy, trim) + -- | Parse Haddock markup and return a 'Pandoc' document.-readHaddock :: ReaderOptions -- ^ Reader options-            -> String        -- ^ String to parse-            -> Either PandocError Pandoc-readHaddock opts =+readHaddock :: PandocMonad m+            => ReaderOptions+            -> Text+            -> m Pandoc+readHaddock opts s = case readHaddockEither opts (unpack (crFilter s)) of+  Right result -> return result+  Left e       -> throwError e++readHaddockEither :: ReaderOptions -- ^ Reader options+                  -> String        -- ^ String to parse+                  -> Either PandocError Pandoc+readHaddockEither _opts = #if MIN_VERSION_haddock_library(1,2,0)-  Right . B.doc . docHToBlocks . trace' . _doc . parseParas+  Right . B.doc . docHToBlocks . _doc . parseParas #else-  Right .  B.doc . docHToBlocks . trace' . parseParas+  Right .  B.doc . docHToBlocks . parseParas #endif-  where trace' x = if readerTrace opts-                      then trace (show x) x-                      else x  docHToBlocks :: DocH String Identifier -> Blocks docHToBlocks d' =@@ -90,7 +97,7 @@         isPlain (Plain _) = True         isPlain _         = False         extractContents (Plain xs) = xs-        extractContents _ = []+        extractContents _          = []  docHToInlines :: Bool -> DocH String Identifier -> Inlines docHToInlines isCode d' =@@ -135,7 +142,7 @@         <> B.space         <> B.codeWith ([], ["haskell","expr"], []) (trim expression)         <> B.linebreak-        <> (mconcat $ intersperse B.linebreak $ map coder result')+        <> mconcat (intersperse B.linebreak $ map coder result')   where     -- 1. drop trailing whitespace from the prompt, remember the prefix     prefix = takeWhile (`elem` " \t") prompt
src/Text/Pandoc/Readers/LaTeX.hs view
@@ -1,1464 +1,2630 @@-{-# LANGUAGE ScopedTypeVariables, OverloadedStrings #-}-{--Copyright (C) 2006-2015 John MacFarlane <jgm@berkeley.edu>--This program is free software; you can redistribute it and/or modify-it under the terms of the GNU General Public License as published by-the Free Software Foundation; either version 2 of the License, or-(at your option) any later version.--This program is distributed in the hope that it will be useful,-but WITHOUT ANY WARRANTY; without even the implied warranty of-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the-GNU General Public License for more details.--You should have received a copy of the GNU General Public License-along with this program; if not, write to the Free Software-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA--}--{- |-   Module      : Text.Pandoc.Readers.LaTeX-   Copyright   : Copyright (C) 2006-2015 John MacFarlane-   License     : GNU GPL, version 2 or above--   Maintainer  : John MacFarlane <jgm@berkeley.edu>-   Stability   : alpha-   Portability : portable--Conversion of LaTeX to 'Pandoc' document.--}-module Text.Pandoc.Readers.LaTeX ( readLaTeX,-                                   rawLaTeXInline,-                                   rawLaTeXBlock,-                                   inlineCommand,-                                   handleIncludes-                                 ) where--import Text.Pandoc.Definition-import Text.Pandoc.Walk-import Text.Pandoc.Shared-import Text.Pandoc.Options-import Text.Pandoc.Parsing hiding ((<|>), many, optional, space,-                                   mathDisplay, mathInline)-import qualified Text.Pandoc.UTF8 as UTF8-import Data.Char ( chr, ord, isLetter, isAlphaNum )-import Control.Monad.Trans (lift)-import Control.Monad-import Text.Pandoc.Builder-import Control.Applicative ((<|>), many, optional)-import Data.Maybe (fromMaybe, maybeToList)-import System.Environment (getEnv)-import System.FilePath (replaceExtension, (</>), takeExtension, addExtension)-import Data.List (intercalate)-import qualified Data.Map as M-import qualified Control.Exception as E-import Text.Pandoc.Highlighting (fromListingsLanguage)-import Text.Pandoc.ImageSize (numUnit, showFl)-import Text.Pandoc.Error---- | Parse LaTeX from string and return 'Pandoc' document.-readLaTeX :: ReaderOptions -- ^ Reader options-          -> String        -- ^ String to parse (assumes @'\n'@ line endings)-          -> Either PandocError Pandoc-readLaTeX opts = readWith parseLaTeX def{ stateOptions = opts }--parseLaTeX :: LP Pandoc-parseLaTeX = do-  bs <- blocks-  eof-  st <- getState-  let meta = stateMeta st-  let (Pandoc _ bs') = doc bs-  return $ Pandoc meta bs'--type LP = Parser String ParserState--anyControlSeq :: LP String-anyControlSeq = do-  char '\\'-  next <- option '\n' anyChar-  case next of-       '\n'           -> return ""-       c | isLetter c -> (c:) <$> (many letter <* optional sp)-         | otherwise  -> return [c]--controlSeq :: String -> LP String-controlSeq name = try $ do-  char '\\'-  case name of-        ""   -> mzero-        [c] | not (isLetter c) -> string [c]-        cs   -> string cs <* notFollowedBy letter <* optional sp-  return name--dimenarg :: LP String-dimenarg = try $ do-  ch  <- option "" $ string "="-  num <- many1 digit-  dim <- oneOfStrings ["pt","pc","in","bp","cm","mm","dd","cc","sp"]-  return $ ch ++ num ++ dim--sp :: LP ()-sp = whitespace <|> endline--whitespace :: LP ()-whitespace = skipMany1 $ satisfy (\c -> c == ' ' || c == '\t')--endline :: LP ()-endline = try (newline >> lookAhead anyChar >> notFollowedBy blankline)--isLowerHex :: Char -> Bool-isLowerHex x = x >= '0' && x <= '9' || x >= 'a' && x <= 'f'--tildeEscape :: LP Char-tildeEscape = try $ do-  string "^^"-  c <- satisfy (\x -> x >= '\0' && x <= '\128')-  d <- if isLowerHex c-          then option "" $ count 1 (satisfy isLowerHex)-          else return ""-  if null d-     then case ord c of-           x | x >= 64 && x <= 127 -> return $ chr (x - 64)-             | otherwise           -> return $ chr (x + 64)-     else return $ chr $ read ('0':'x':c:d)--comment :: LP ()-comment = do-  char '%'-  skipMany (satisfy (/='\n'))-  optional newline-  return ()--bgroup :: LP ()-bgroup = try $ do-  skipMany (spaceChar <|> try (newline <* notFollowedBy blankline))-  () <$ char '{'-     <|> () <$ controlSeq "bgroup"-     <|> () <$ controlSeq "begingroup"--egroup :: LP ()-egroup = () <$ char '}'-     <|> () <$ controlSeq "egroup"-     <|> () <$ controlSeq "endgroup"--grouped :: Monoid a => LP a -> LP a-grouped parser = try $ bgroup *> (mconcat <$> manyTill parser egroup)--braced :: LP String-braced = bgroup *> (concat <$> manyTill-         (  many1 (satisfy (\c -> c /= '\\' && c /= '}' && c /= '{'))-        <|> try (string "\\}")-        <|> try (string "\\{")-        <|> try (string "\\\\")-        <|> ((\x -> "{" ++ x ++ "}") <$> braced)-        <|> count 1 anyChar-         ) egroup)--bracketed :: Monoid a => LP a -> LP a-bracketed parser = try $ char '[' *> (mconcat <$> manyTill parser (char ']'))--mathDisplay :: LP String -> LP Inlines-mathDisplay p = displayMath <$> (try p >>= applyMacros' . trim)--mathInline :: LP String -> LP Inlines-mathInline p = math <$> (try p >>= applyMacros')--mathChars :: LP String-mathChars =-  concat <$> many (escapedChar-               <|> (snd <$> withRaw braced)-               <|> many1 (satisfy isOrdChar))-   where escapedChar = try $ do char '\\'-                                c <- anyChar-                                return ['\\',c]-         isOrdChar '$' = False-         isOrdChar '{' = False-         isOrdChar '}' = False-         isOrdChar '\\' = False-         isOrdChar _ = True--quoted' :: (Inlines -> Inlines) -> LP String -> LP () -> LP Inlines-quoted' f starter ender = do-  startchs <- starter-  smart <- getOption readerSmart-  if smart-     then do-       ils <- many (notFollowedBy ender >> inline)-       (ender >> return (f (mconcat ils))) <|>-            (<> mconcat ils) <$>-                    lit (case startchs of-                              "``"  -> "“"-                              "`"   -> "‘"-                              _     -> startchs)-     else lit startchs--doubleQuote :: LP Inlines-doubleQuote = do-  quoted' doubleQuoted (try $ string "``") (void $ try $ string "''")-   <|> quoted' doubleQuoted (string "“")        (void $ char '”')-   -- the following is used by babel for localized quotes:-   <|> quoted' doubleQuoted (try $ string "\"`") (void $ try $ string "\"'")-   <|> quoted' doubleQuoted (string "\"")       (void $ char '"')--singleQuote :: LP Inlines-singleQuote = do-  smart <- getOption readerSmart-  if smart-     then quoted' singleQuoted (string "`") (try $ char '\'' >> notFollowedBy letter)-      <|> quoted' singleQuoted (string "‘") (try $ char '’' >> notFollowedBy letter)-     else str <$> many1 (oneOf "`\'‘’")--inline :: LP Inlines-inline = (mempty <$ comment)-     <|> (space  <$ whitespace)-     <|> (softbreak <$ endline)-     <|> inlineText-     <|> inlineCommand-     <|> inlineEnvironment-     <|> inlineGroup-     <|> (char '-' *> option (str "-")-           (char '-' *> option (str "–") (str "—" <$ char '-')))-     <|> doubleQuote-     <|> singleQuote-     <|> (str "”" <$ try (string "''"))-     <|> (str "”" <$ char '”')-     <|> (str "’" <$ char '\'')-     <|> (str "’" <$ char '’')-     <|> (str "\160" <$ char '~')-     <|> mathDisplay (string "$$" *> mathChars <* string "$$")-     <|> mathInline  (char '$' *> mathChars <* char '$')-     <|> (guardEnabled Ext_literate_haskell *> char '|' *> doLHSverb)-     <|> (str . (:[]) <$> tildeEscape)-     <|> (str . (:[]) <$> oneOf "[]")-     <|> (str . (:[]) <$> oneOf "#&~^'`\"[]") -- TODO print warning?-     -- <|> (str <$> count 1 (satisfy (\c -> c /= '\\' && c /='\n' && c /='}' && c /='{'))) -- eat random leftover characters--inlines :: LP Inlines-inlines = mconcat <$> many (notFollowedBy (char '}') *> inline)--inlineGroup :: LP Inlines-inlineGroup = do-  ils <- grouped inline-  if isNull ils-     then return mempty-     else return $ spanWith nullAttr ils-          -- we need the span so we can detitlecase bibtex entries;-          -- we need to know when something is {C}apitalized--block :: LP Blocks-block = (mempty <$ comment)-    <|> (mempty <$ ((spaceChar <|> newline) *> spaces))-    <|> environment-    <|> macro-    <|> blockCommand-    <|> paragraph-    <|> grouped block-    <|> (mempty <$ char '&')  -- loose & in table environment---blocks :: LP Blocks-blocks = mconcat <$> many block--getRawCommand :: String -> LP String-getRawCommand name' = do-  rawargs <- withRaw (many (try (optional sp *> opt)) *>-                      option "" (try (optional sp *> dimenarg)) *>-                      many braced)-  return $ '\\' : name' ++ snd rawargs--lookupListDefault :: (Ord k) => v -> [k] -> M.Map k v -> v-lookupListDefault d = (fromMaybe d .) . lookupList-  where-  lookupList l m = msum $ map (`M.lookup` m) l--blockCommand :: LP Blocks-blockCommand = try $ do-  name <- anyControlSeq-  guard $ name /= "begin" && name /= "end"-  star <- option "" (string "*" <* optional sp)-  let name' = name ++ star-  let raw = do-        rawcommand <- getRawCommand name'-        transformed <- applyMacros' rawcommand-        guard $ transformed /= rawcommand-        notFollowedBy $ parseFromString inlines transformed-        parseFromString blocks transformed-  lookupListDefault raw [name',name] blockCommands--inBrackets :: Inlines -> Inlines-inBrackets x = str "[" <> x <> str "]"---- eat an optional argument and one or more arguments in braces-ignoreInlines :: String -> (String, LP Inlines)-ignoreInlines name = (name, doraw <|> (mempty <$ optargs))-  where optargs = skipopts *> skipMany (try $ optional sp *> braced)-        contseq = '\\':name-        doraw = (rawInline "latex" . (contseq ++) . snd) <$>-                 (getOption readerParseRaw >>= guard >> withRaw optargs)--ignoreBlocks :: String -> (String, LP Blocks)-ignoreBlocks name = (name, doraw <|> (mempty <$ optargs))-  where optargs = skipopts *> skipMany (try $ optional sp *> braced)-        contseq = '\\':name-        doraw = (rawBlock "latex" . (contseq ++) . snd) <$>-                 (getOption readerParseRaw >>= guard >> withRaw optargs)--blockCommands :: M.Map String (LP Blocks)-blockCommands = M.fromList $-  [ ("par", mempty <$ skipopts)-  , ("title", mempty <$ (skipopts *>-                          (grouped inline >>= addMeta "title")-                      <|> (grouped block >>= addMeta "title")))-  , ("subtitle", mempty <$ (skipopts *> tok >>= addMeta "subtitle"))-  , ("author", mempty <$ (skipopts *> authors))-  -- -- in letter class, temp. store address & sig as title, author-  , ("address", mempty <$ (skipopts *> tok >>= addMeta "address"))-  , ("signature", mempty <$ (skipopts *> authors))-  , ("date", mempty <$ (skipopts *> tok >>= addMeta "date"))-  -- sectioning-  , ("chapter", updateState (\s -> s{ stateHasChapters = True })-                      *> section nullAttr 0)-  , ("chapter*", updateState (\s -> s{ stateHasChapters = True })-                      *> section ("",["unnumbered"],[]) 0)-  , ("section", section nullAttr 1)-  , ("section*", section ("",["unnumbered"],[]) 1)-  , ("subsection", section nullAttr 2)-  , ("subsection*", section ("",["unnumbered"],[]) 2)-  , ("subsubsection", section nullAttr 3)-  , ("subsubsection*", section ("",["unnumbered"],[]) 3)-  , ("paragraph", section nullAttr 4)-  , ("paragraph*", section ("",["unnumbered"],[]) 4)-  , ("subparagraph", section nullAttr 5)-  , ("subparagraph*", section ("",["unnumbered"],[]) 5)-  -- beamer slides-  , ("frametitle", section nullAttr 3)-  , ("framesubtitle", section nullAttr 4)-  -- letters-  , ("opening", (para . trimInlines) <$> (skipopts *> tok))-  , ("closing", skipopts *> closing)-  ---  , ("hrule", pure horizontalRule)-  , ("strut", pure mempty)-  , ("rule", skipopts *> tok *> tok *> pure horizontalRule)-  , ("item", skipopts *> looseItem)-  , ("documentclass", skipopts *> braced *> preamble)-  , ("centerline", (para . trimInlines) <$> (skipopts *> tok))-  , ("caption", skipopts *> setCaption)-  , ("PandocStartInclude", startInclude)-  , ("PandocEndInclude", endInclude)-  , ("bibliography", mempty <$ (skipopts *> braced >>=-                                addMeta "bibliography" . splitBibs))-  , ("addbibresource", mempty <$ (skipopts *> braced >>=-                                addMeta "bibliography" . splitBibs))-  ] ++ map ignoreBlocks-  -- these commands will be ignored unless --parse-raw is specified,-  -- in which case they will appear as raw latex blocks-  [ "newcommand", "renewcommand", "newenvironment", "renewenvironment"-    -- newcommand, etc. should be parsed by macro, but we need this-    -- here so these aren't parsed as inline commands to ignore-  , "special", "pdfannot", "pdfstringdef"-  , "bibliographystyle"-  , "maketitle", "makeindex", "makeglossary"-  , "addcontentsline", "addtocontents", "addtocounter"-     -- \ignore{} is used conventionally in literate haskell for definitions-     -- that are to be processed by the compiler but not printed.-  , "ignore"-  , "hyperdef"-  , "markboth", "markright", "markleft"-  , "newpage"-  ]--addMeta :: ToMetaValue a => String -> a -> LP ()-addMeta field val = updateState $ \st ->-  st{ stateMeta = addMetaField field val $ stateMeta st }--splitBibs :: String -> [Inlines]-splitBibs = map (str . flip replaceExtension "bib" . trim) . splitBy (==',')--setCaption :: LP Blocks-setCaption = do-  ils <- tok-  mblabel <- option Nothing $-               try $ spaces' >> controlSeq "label" >> (Just <$> tok)-  let ils' = case mblabel of-                  Just lab -> ils <> spanWith-                                ("",[],[("data-label", stringify lab)]) mempty-                  Nothing  -> ils-  updateState $ \st -> st{ stateCaption = Just ils' }-  return mempty--resetCaption :: LP ()-resetCaption = updateState $ \st -> st{ stateCaption = Nothing }--authors :: LP ()-authors = try $ do-  char '{'-  let oneAuthor = mconcat <$>-       many1 (notFollowedBy' (controlSeq "and") >>-               (inline <|> mempty <$ blockCommand))-               -- skip e.g. \vspace{10pt}-  auths <- sepBy oneAuthor (controlSeq "and")-  char '}'-  addMeta "author" (map trimInlines auths)--section :: Attr -> Int -> LP Blocks-section (ident, classes, kvs) lvl = do-  hasChapters <- stateHasChapters `fmap` getState-  let lvl' = if hasChapters then lvl + 1 else lvl-  skipopts-  contents <- grouped inline-  lab <- option ident $ try (spaces' >> controlSeq "label" >> spaces' >> braced)-  attr' <- registerHeader (lab, classes, kvs) contents-  return $ headerWith attr' lvl' contents--inlineCommand :: LP Inlines-inlineCommand = try $ do-  name <- anyControlSeq-  guard $ name /= "begin" && name /= "end"-  guard $ not $ isBlockCommand name-  parseRaw <- getOption readerParseRaw-  star <- option "" (string "*")-  let name' = name ++ star-  let raw = do-        rawargs <- withRaw-               (skipangles *> skipopts *> option "" dimenarg *> many braced)-        let rawcommand = '\\' : name ++ star ++ snd rawargs-        transformed <- applyMacros' rawcommand-        if transformed /= rawcommand-           then parseFromString inlines transformed-           else if parseRaw-                   then return $ rawInline "latex" rawcommand-                   else return mempty-  (lookupListDefault mzero [name',name] inlineCommands <*-      optional (try (string "{}")))-    <|> raw--unlessParseRaw :: LP ()-unlessParseRaw = getOption readerParseRaw >>= guard . not--isBlockCommand :: String -> Bool-isBlockCommand s = s `M.member` blockCommands---inlineEnvironments :: M.Map String (LP Inlines)-inlineEnvironments = M.fromList-  [ ("displaymath", mathEnv id Nothing "displaymath")-  , ("math", math <$> verbEnv "math")-  , ("equation", mathEnv id Nothing "equation")-  , ("equation*", mathEnv id Nothing "equation*")-  , ("gather", mathEnv id (Just "gathered") "gather")-  , ("gather*", mathEnv id (Just "gathered") "gather*")-  , ("multline", mathEnv id (Just "gathered") "multline")-  , ("multline*", mathEnv id (Just "gathered") "multline*")-  , ("eqnarray", mathEnv id (Just "aligned") "eqnarray")-  , ("eqnarray*", mathEnv id (Just "aligned") "eqnarray*")-  , ("align", mathEnv id (Just "aligned") "align")-  , ("align*", mathEnv id (Just "aligned") "align*")-  , ("alignat", mathEnv id (Just "aligned") "alignat")-  , ("alignat*", mathEnv id (Just "aligned") "alignat*")-  ]--inlineCommands :: M.Map String (LP Inlines)-inlineCommands = M.fromList $-  [ ("emph", extractSpaces emph <$> tok)-  , ("textit", extractSpaces emph <$> tok)-  , ("textsl", extractSpaces emph <$> tok)-  , ("textsc", extractSpaces smallcaps <$> tok)-  , ("sout", extractSpaces strikeout <$> tok)-  , ("textsuperscript", extractSpaces superscript <$> tok)-  , ("textsubscript", extractSpaces subscript <$> tok)-  , ("textbackslash", lit "\\")-  , ("backslash", lit "\\")-  , ("slash", lit "/")-  , ("textbf", extractSpaces strong <$> tok)-  , ("textnormal", extractSpaces (spanWith ("",["nodecor"],[])) <$> tok)-  , ("ldots", lit "…")-  , ("dots", lit "…")-  , ("mdots", lit "…")-  , ("sim", lit "~")-  , ("label", unlessParseRaw >> (inBrackets <$> tok))-  , ("ref", unlessParseRaw >> (inBrackets <$> tok))-  , ("noindent", unlessParseRaw >> return mempty)-  , ("textgreek", tok)-  , ("sep", lit ",")-  , ("cref", unlessParseRaw >> (inBrackets <$> tok))  -- from cleveref.sty-  , ("(", mathInline $ manyTill anyChar (try $ string "\\)"))-  , ("[", mathDisplay $ manyTill anyChar (try $ string "\\]"))-  , ("ensuremath", mathInline braced)-  , ("texorpdfstring", (\_ x -> x) <$> tok <*> tok)-  , ("P", lit "¶")-  , ("S", lit "§")-  , ("$", lit "$")-  , ("%", lit "%")-  , ("&", lit "&")-  , ("#", lit "#")-  , ("_", lit "_")-  , ("{", lit "{")-  , ("}", lit "}")-  -- old TeX commands-  , ("em", extractSpaces emph <$> inlines)-  , ("it", extractSpaces emph <$> inlines)-  , ("sl", extractSpaces emph <$> inlines)-  , ("bf", extractSpaces strong <$> inlines)-  , ("rm", inlines)-  , ("itshape", extractSpaces emph <$> inlines)-  , ("slshape", extractSpaces emph <$> inlines)-  , ("scshape", extractSpaces smallcaps <$> inlines)-  , ("bfseries", extractSpaces strong <$> inlines)-  , ("/", pure mempty) -- italic correction-  , ("aa", lit "å")-  , ("AA", lit "Å")-  , ("ss", lit "ß")-  , ("o", lit "ø")-  , ("O", lit "Ø")-  , ("L", lit "Ł")-  , ("l", lit "ł")-  , ("ae", lit "æ")-  , ("AE", lit "Æ")-  , ("oe", lit "œ")-  , ("OE", lit "Œ")-  , ("pounds", lit "£")-  , ("euro", lit "€")-  , ("copyright", lit "©")-  , ("textasciicircum", lit "^")-  , ("textasciitilde", lit "~")-  , ("H", try $ tok >>= accent hungarumlaut)-  , ("`", option (str "`") $ try $ tok >>= accent grave)-  , ("'", option (str "'") $ try $ tok >>= accent acute)-  , ("^", option (str "^") $ try $ tok >>= accent circ)-  , ("~", option (str "~") $ try $ tok >>= accent tilde)-  , ("\"", option (str "\"") $ try $ tok >>= accent umlaut)-  , (".", option (str ".") $ try $ tok >>= accent dot)-  , ("=", option (str "=") $ try $ tok >>= accent macron)-  , ("c", option (str "c") $ try $ tok >>= accent cedilla)-  , ("v", option (str "v") $ try $ tok >>= accent hacek)-  , ("u", option (str "u") $ try $ tok >>= accent breve)-  , ("i", lit "i")-  , ("\\", linebreak <$ (optional (bracketed inline) *> spaces'))-  , (",", pure mempty)-  , ("@", pure mempty)-  , (" ", lit "\160")-  , ("ps", pure $ str "PS." <> space)-  , ("TeX", lit "TeX")-  , ("LaTeX", lit "LaTeX")-  , ("bar", lit "|")-  , ("textless", lit "<")-  , ("textgreater", lit ">")-  , ("thanks", (note . mconcat) <$> (char '{' *> manyTill block (char '}')))-  , ("footnote", (note . mconcat) <$> (char '{' *> manyTill block (char '}')))-  , ("verb", doverb)-  , ("lstinline", skipopts *> doverb)-  , ("Verb", doverb)-  , ("texttt", (code . stringify . toList) <$> tok)-  , ("url", (unescapeURL <$> braced) >>= \url ->-       pure (link url "" (str url)))-  , ("href", (unescapeURL <$> braced <* optional sp) >>= \url ->-       tok >>= \lab ->-         pure (link url "" lab))-  , ("includegraphics", do options <- option [] keyvals-                           src <- unescapeURL . removeDoubleQuotes <$> braced-                           mkImage options src)-  , ("enquote", enquote)-  , ("cite", citation "cite" NormalCitation False)-  , ("Cite", citation "Cite" NormalCitation False)-  , ("citep", citation "citep" NormalCitation False)-  , ("citep*", citation "citep*" NormalCitation False)-  , ("citeal", citation "citeal" NormalCitation False)-  , ("citealp", citation "citealp" NormalCitation False)-  , ("citealp*", citation "citealp*" NormalCitation False)-  , ("autocite", citation "autocite" NormalCitation False)-  , ("smartcite", citation "smartcite" NormalCitation False)-  , ("footcite", inNote <$> citation "footcite" NormalCitation False)-  , ("parencite", citation "parencite" NormalCitation False)-  , ("supercite", citation "supercite" NormalCitation False)-  , ("footcitetext", inNote <$> citation "footcitetext" NormalCitation False)-  , ("citeyearpar", citation "citeyearpar" SuppressAuthor False)-  , ("citeyear", citation "citeyear" SuppressAuthor False)-  , ("autocite*", citation "autocite*" SuppressAuthor False)-  , ("cite*", citation "cite*" SuppressAuthor False)-  , ("parencite*", citation "parencite*" SuppressAuthor False)-  , ("textcite", citation "textcite" AuthorInText False)-  , ("citet", citation "citet" AuthorInText False)-  , ("citet*", citation "citet*" AuthorInText False)-  , ("citealt", citation "citealt" AuthorInText False)-  , ("citealt*", citation "citealt*" AuthorInText False)-  , ("textcites", citation "textcites" AuthorInText True)-  , ("cites", citation "cites" NormalCitation True)-  , ("autocites", citation "autocites" NormalCitation True)-  , ("footcites", inNote <$> citation "footcites" NormalCitation True)-  , ("parencites", citation "parencites" NormalCitation True)-  , ("supercites", citation "supercites" NormalCitation True)-  , ("footcitetexts", inNote <$> citation "footcitetexts" NormalCitation True)-  , ("Autocite", citation "Autocite" NormalCitation False)-  , ("Smartcite", citation "Smartcite" NormalCitation False)-  , ("Footcite", citation "Footcite" NormalCitation False)-  , ("Parencite", citation "Parencite" NormalCitation False)-  , ("Supercite", citation "Supercite" NormalCitation False)-  , ("Footcitetext", inNote <$> citation "Footcitetext" NormalCitation False)-  , ("Citeyearpar", citation "Citeyearpar" SuppressAuthor False)-  , ("Citeyear", citation "Citeyear" SuppressAuthor False)-  , ("Autocite*", citation "Autocite*" SuppressAuthor False)-  , ("Cite*", citation "Cite*" SuppressAuthor False)-  , ("Parencite*", citation "Parencite*" SuppressAuthor False)-  , ("Textcite", citation "Textcite" AuthorInText False)-  , ("Textcites", citation "Textcites" AuthorInText True)-  , ("Cites", citation "Cites" NormalCitation True)-  , ("Autocites", citation "Autocites" NormalCitation True)-  , ("Footcites", citation "Footcites" NormalCitation True)-  , ("Parencites", citation "Parencites" NormalCitation True)-  , ("Supercites", citation "Supercites" NormalCitation True)-  , ("Footcitetexts", inNote <$> citation "Footcitetexts" NormalCitation True)-  , ("citetext", complexNatbibCitation NormalCitation)-  , ("citeauthor", (try (tok *> optional sp *> controlSeq "citetext") *>-                        complexNatbibCitation AuthorInText)-                   <|> citation "citeauthor" AuthorInText False)-  , ("nocite", mempty <$ (citation "nocite" NormalCitation False >>=-                          addMeta "nocite"))-  ] ++ map ignoreInlines-  -- these commands will be ignored unless --parse-raw is specified,-  -- in which case they will appear as raw latex blocks:-  [ "index" ]--mkImage :: [(String, String)] -> String -> LP Inlines-mkImage options src = do-   let replaceTextwidth (k,v) = case numUnit v of-                                  Just (num, "\\textwidth") -> (k, showFl (num * 100) ++ "%")-                                  _ -> (k, v)-   let kvs = map replaceTextwidth $ filter (\(k,_) -> k `elem` ["width", "height"]) options-   let attr = ("",[], kvs)-   let alt = str "image"-   case takeExtension src of-        "" -> do-              defaultExt <- getOption readerDefaultImageExtension-              return $ imageWith attr (addExtension src defaultExt) "" alt-        _  -> return $ imageWith attr src "" alt--inNote :: Inlines -> Inlines-inNote ils =-  note $ para $ ils <> str "."--unescapeURL :: String -> String-unescapeURL ('\\':x:xs) | isEscapable x = x:unescapeURL xs-  where isEscapable c = c `elem` ("#$%&~_^\\{}" :: String)-unescapeURL (x:xs) = x:unescapeURL xs-unescapeURL [] = ""--enquote :: LP Inlines-enquote = do-  skipopts-  context <- stateQuoteContext <$> getState-  if context == InDoubleQuote-     then singleQuoted <$> withQuoteContext InSingleQuote tok-     else doubleQuoted <$> withQuoteContext InDoubleQuote tok--doverb :: LP Inlines-doverb = do-  marker <- anyChar-  code <$> manyTill (satisfy (/='\n')) (char marker)--doLHSverb :: LP Inlines-doLHSverb = codeWith ("",["haskell"],[]) <$> manyTill (satisfy (/='\n')) (char '|')--lit :: String -> LP Inlines-lit = pure . str--accent :: (Char -> String) -> Inlines -> LP Inlines-accent f ils =-  case toList ils of-       (Str (x:xs) : ys) -> return $ fromList (Str (f x ++ xs) : ys)-       []                -> mzero-       _                 -> return ils--grave :: Char -> String-grave 'A' = "À"-grave 'E' = "È"-grave 'I' = "Ì"-grave 'O' = "Ò"-grave 'U' = "Ù"-grave 'a' = "à"-grave 'e' = "è"-grave 'i' = "ì"-grave 'o' = "ò"-grave 'u' = "ù"-grave c   = [c]--acute :: Char -> String-acute 'A' = "Á"-acute 'E' = "É"-acute 'I' = "Í"-acute 'O' = "Ó"-acute 'U' = "Ú"-acute 'Y' = "Ý"-acute 'a' = "á"-acute 'e' = "é"-acute 'i' = "í"-acute 'o' = "ó"-acute 'u' = "ú"-acute 'y' = "ý"-acute 'C' = "Ć"-acute 'c' = "ć"-acute 'L' = "Ĺ"-acute 'l' = "ĺ"-acute 'N' = "Ń"-acute 'n' = "ń"-acute 'R' = "Ŕ"-acute 'r' = "ŕ"-acute 'S' = "Ś"-acute 's' = "ś"-acute 'Z' = "Ź"-acute 'z' = "ź"-acute c   = [c]--circ :: Char -> String-circ 'A' = "Â"-circ 'E' = "Ê"-circ 'I' = "Î"-circ 'O' = "Ô"-circ 'U' = "Û"-circ 'a' = "â"-circ 'e' = "ê"-circ 'i' = "î"-circ 'o' = "ô"-circ 'u' = "û"-circ 'C' = "Ĉ"-circ 'c' = "ĉ"-circ 'G' = "Ĝ"-circ 'g' = "ĝ"-circ 'H' = "Ĥ"-circ 'h' = "ĥ"-circ 'J' = "Ĵ"-circ 'j' = "ĵ"-circ 'S' = "Ŝ"-circ 's' = "ŝ"-circ 'W' = "Ŵ"-circ 'w' = "ŵ"-circ 'Y' = "Ŷ"-circ 'y' = "ŷ"-circ c   = [c]--tilde :: Char -> String-tilde 'A' = "Ã"-tilde 'a' = "ã"-tilde 'O' = "Õ"-tilde 'o' = "õ"-tilde 'I' = "Ĩ"-tilde 'i' = "ĩ"-tilde 'U' = "Ũ"-tilde 'u' = "ũ"-tilde 'N' = "Ñ"-tilde 'n' = "ñ"-tilde c   = [c]--umlaut :: Char -> String-umlaut 'A' = "Ä"-umlaut 'E' = "Ë"-umlaut 'I' = "Ï"-umlaut 'O' = "Ö"-umlaut 'U' = "Ü"-umlaut 'a' = "ä"-umlaut 'e' = "ë"-umlaut 'i' = "ï"-umlaut 'o' = "ö"-umlaut 'u' = "ü"-umlaut c   = [c]--hungarumlaut :: Char -> String-hungarumlaut 'A' = "A̋"-hungarumlaut 'E' = "E̋"-hungarumlaut 'I' = "I̋"-hungarumlaut 'O' = "Ő"-hungarumlaut 'U' = "Ű"-hungarumlaut 'Y' = "ӳ"-hungarumlaut 'a' = "a̋"-hungarumlaut 'e' = "e̋"-hungarumlaut 'i' = "i̋"-hungarumlaut 'o' = "ő"-hungarumlaut 'u' = "ű"-hungarumlaut 'y' = "ӳ"-hungarumlaut c   = [c]--dot :: Char -> String-dot 'C' = "Ċ"-dot 'c' = "ċ"-dot 'E' = "Ė"-dot 'e' = "ė"-dot 'G' = "Ġ"-dot 'g' = "ġ"-dot 'I' = "İ"-dot 'Z' = "Ż"-dot 'z' = "ż"-dot c   = [c]--macron :: Char -> String-macron 'A' = "Ā"-macron 'E' = "Ē"-macron 'I' = "Ī"-macron 'O' = "Ō"-macron 'U' = "Ū"-macron 'a' = "ā"-macron 'e' = "ē"-macron 'i' = "ī"-macron 'o' = "ō"-macron 'u' = "ū"-macron c   = [c]--cedilla :: Char -> String-cedilla 'c' = "ç"-cedilla 'C' = "Ç"-cedilla 's' = "ş"-cedilla 'S' = "Ş"-cedilla 't' = "ţ"-cedilla 'T' = "Ţ"-cedilla 'e' = "ȩ"-cedilla 'E' = "Ȩ"-cedilla 'h' = "ḩ"-cedilla 'H' = "Ḩ"-cedilla 'o' = "o̧"-cedilla 'O' = "O̧"-cedilla c   = [c]--hacek :: Char -> String-hacek 'A' = "Ǎ"-hacek 'a' = "ǎ"-hacek 'C' = "Č"-hacek 'c' = "č"-hacek 'D' = "Ď"-hacek 'd' = "ď"-hacek 'E' = "Ě"-hacek 'e' = "ě"-hacek 'G' = "Ǧ"-hacek 'g' = "ǧ"-hacek 'H' = "Ȟ"-hacek 'h' = "ȟ"-hacek 'I' = "Ǐ"-hacek 'i' = "ǐ"-hacek 'j' = "ǰ"-hacek 'K' = "Ǩ"-hacek 'k' = "ǩ"-hacek 'L' = "Ľ"-hacek 'l' = "ľ"-hacek 'N' = "Ň"-hacek 'n' = "ň"-hacek 'O' = "Ǒ"-hacek 'o' = "ǒ"-hacek 'R' = "Ř"-hacek 'r' = "ř"-hacek 'S' = "Š"-hacek 's' = "š"-hacek 'T' = "Ť"-hacek 't' = "ť"-hacek 'U' = "Ǔ"-hacek 'u' = "ǔ"-hacek 'Z' = "Ž"-hacek 'z' = "ž"-hacek c   = [c]--breve :: Char -> String-breve 'A' = "Ă"-breve 'a' = "ă"-breve 'E' = "Ĕ"-breve 'e' = "ĕ"-breve 'G' = "Ğ"-breve 'g' = "ğ"-breve 'I' = "Ĭ"-breve 'i' = "ĭ"-breve 'O' = "Ŏ"-breve 'o' = "ŏ"-breve 'U' = "Ŭ"-breve 'u' = "ŭ"-breve c   = [c]--tok :: LP Inlines-tok = try $ grouped inline <|> inlineCommand <|> str <$> count 1 inlineChar--opt :: LP Inlines-opt = bracketed inline--rawopt :: LP String-rawopt = do-  contents <- bracketed (many1 (noneOf "[]") <|> try (string "\\]") <|>-                   try (string "\\[") <|> rawopt)-  optional sp-  return $ "[" ++ contents ++ "]"--skipopts :: LP ()-skipopts = skipMany rawopt---- opts in angle brackets are used in beamer-rawangle :: LP ()-rawangle = try $ do-  char '<'-  skipMany (noneOf ">")-  char '>'-  return ()--skipangles :: LP ()-skipangles = skipMany rawangle--inlineText :: LP Inlines-inlineText = str <$> many1 inlineChar--inlineChar :: LP Char-inlineChar = noneOf "\\$%&~#{}^'`\"‘’“”-[] \t\n"--environment :: LP Blocks-environment = do-  controlSeq "begin"-  name <- braced-  M.findWithDefault mzero name environments-    <|> rawEnv name--inlineEnvironment :: LP Inlines-inlineEnvironment = try $ do-  controlSeq "begin"-  name <- braced-  M.findWithDefault mzero name inlineEnvironments--rawEnv :: String -> LP Blocks-rawEnv name = do-  parseRaw <- getOption readerParseRaw-  rawOptions <- mconcat <$> many rawopt-  let addBegin x = "\\begin{" ++ name ++ "}" ++ rawOptions ++ x-  if parseRaw-     then (rawBlock "latex" . addBegin) <$>-            (withRaw (env name blocks) >>= applyMacros' . snd)-     else env name blocks--------type IncludeParser = ParserT String [String] IO String---- | Replace "include" commands with file contents.-handleIncludes :: String -> IO (Either PandocError String)-handleIncludes s =  mapLeft (ParsecError s) <$> runParserT includeParser' [] "input" s--includeParser' :: IncludeParser-includeParser' =-  concat <$> many (comment' <|> escaped' <|> blob' <|> include'-                   <|> startMarker' <|> endMarker'-                   <|> verbCmd' <|> verbatimEnv' <|> backslash')--comment' :: IncludeParser-comment' = do-  char '%'-  xs <- manyTill anyChar newline-  return ('%':xs ++ "\n")--escaped' :: IncludeParser-escaped' = try $ string "\\%" <|> string "\\\\"--verbCmd' :: IncludeParser-verbCmd' = fmap snd <$>-  withRaw $ try $ do-             string "\\verb"-             c <- anyChar-             manyTill anyChar (char c)--verbatimEnv' :: IncludeParser-verbatimEnv' = fmap snd <$>-  withRaw $ try $ do-             string "\\begin"-             name <- braced'-             guard $ name `elem` ["verbatim", "Verbatim", "BVerbatim",-                                  "lstlisting", "minted", "alltt", "comment"]-             manyTill anyChar (try $ string $ "\\end{" ++ name ++ "}")--blob' :: IncludeParser-blob' = try $ many1 (noneOf "\\%")--backslash' :: IncludeParser-backslash' = string "\\"--braced' :: IncludeParser-braced' = try $ char '{' *> manyTill (satisfy (/='}')) (char '}')--maybeAddExtension :: String -> FilePath -> FilePath-maybeAddExtension ext fp =-  if null (takeExtension fp)-     then addExtension fp ext-     else fp--include' :: IncludeParser-include' = do-  fs' <- try $ do-              char '\\'-              name <- try (string "include")-                  <|> try (string "input")-                  <|> string "usepackage"-              -- skip options-              skipMany $ try $ char '[' *> manyTill anyChar (char ']')-              fs <- (map trim . splitBy (==',')) <$> braced'-              return $ if name == "usepackage"-                          then map (maybeAddExtension ".sty") fs-                          else map (maybeAddExtension ".tex") fs-  pos <- getPosition-  containers <- getState-  let fn = case containers of-                (f':_) -> f'-                []     -> "input"-  -- now process each include file in order...-  rest <- getInput-  results' <- forM fs' (\f -> do-    when (f `elem` containers) $-      fail "Include file loop!"-    contents <- lift $ readTeXFile f-    return $ "\\PandocStartInclude{" ++ f ++ "}" ++-             contents ++ "\\PandocEndInclude{" ++-             fn ++ "}{" ++ show (sourceLine pos) ++ "}{"-             ++ show (sourceColumn pos) ++ "}")-  setInput $ concat results' ++ rest-  return ""--startMarker' :: IncludeParser-startMarker' = try $ do-  string "\\PandocStartInclude"-  fn <- braced'-  updateState (fn:)-  setPosition $ newPos fn 1 1-  return $ "\\PandocStartInclude{" ++ fn ++ "}"--endMarker' :: IncludeParser-endMarker' = try $ do-  string "\\PandocEndInclude"-  fn <- braced'-  ln <- braced'-  co <- braced'-  updateState tail-  setPosition $ newPos fn (fromMaybe 1 $ safeRead ln) (fromMaybe 1 $ safeRead co)-  return $ "\\PandocEndInclude{" ++ fn ++ "}{" ++ ln ++ "}{" ++-               co ++ "}"--readTeXFile :: FilePath -> IO String-readTeXFile f = do-  texinputs <- E.catch (getEnv "TEXINPUTS") $ \(_ :: E.SomeException) ->-                   return "."-  let ds = splitBy (==':') texinputs-  readFileFromDirs ds f--readFileFromDirs :: [FilePath] -> FilePath -> IO String-readFileFromDirs [] _ = return ""-readFileFromDirs (d:ds) f =-  E.catch (UTF8.readFile $ d </> f) $ \(_ :: E.SomeException) ->-    readFileFromDirs ds f--------keyval :: LP (String, String)-keyval = try $ do-  key <- many1 alphaNum-  val <- option "" $ char '=' >> many1 (alphaNum <|> char '.' <|> char '\\')-  skipMany spaceChar-  optional (char ',')-  skipMany spaceChar-  return (key, val)---keyvals :: LP [(String, String)]-keyvals = try $ char '[' *> manyTill keyval (char ']')--alltt :: String -> LP Blocks-alltt t = walk strToCode <$> parseFromString blocks-  (substitute " " "\\ " $ substitute "%" "\\%" $-   intercalate "\\\\\n" $ lines t)-  where strToCode (Str s) = Code nullAttr s-        strToCode x       = x--rawLaTeXBlock :: LP String-rawLaTeXBlock = snd <$> try (withRaw (environment <|> blockCommand))--rawLaTeXInline :: LP Inline-rawLaTeXInline = do-  raw <- (snd <$> withRaw inlineCommand) <|> (snd <$> withRaw blockCommand)-  RawInline "latex" <$> applyMacros' raw--addImageCaption :: Blocks -> LP Blocks-addImageCaption = walkM go-  where go (Image attr alt (src,tit)) = do-          mbcapt <- stateCaption <$> getState-          return $ case mbcapt of-               Just ils -> Image attr (toList ils) (src, "fig:")-               Nothing  -> Image attr alt (src,tit)-        go x = return x--addTableCaption :: Blocks -> LP Blocks-addTableCaption = walkM go-  where go (Table c als ws hs rs) = do-          mbcapt <- stateCaption <$> getState-          return $ case mbcapt of-               Just ils -> Table (toList ils) als ws hs rs-               Nothing  -> Table c als ws hs rs-        go x = return x--environments :: M.Map String (LP Blocks)-environments = M.fromList-  [ ("document", env "document" blocks <* skipMany anyChar)-  , ("abstract", mempty <$ (env "abstract" blocks >>= addMeta "abstract"))-  , ("letter", env "letter" letterContents)-  , ("minipage", env "minipage" $-         skipopts *> spaces' *> optional braced *> spaces' *> blocks)-  , ("figure", env "figure" $-         resetCaption *> skipopts *> blocks >>= addImageCaption)-  , ("center", env "center" blocks)-  , ("longtable",  env "longtable" $-         resetCaption *> simpTable False >>= addTableCaption)-  , ("table",  env "table" $-         resetCaption *> skipopts *> blocks >>= addTableCaption)-  , ("tabular*", env "tabular" $ simpTable True)-  , ("tabular", env "tabular"  $ simpTable False)-  , ("quote", blockQuote <$> env "quote" blocks)-  , ("quotation", blockQuote <$> env "quotation" blocks)-  , ("verse", blockQuote <$> env "verse" blocks)-  , ("itemize", bulletList <$> listenv "itemize" (many item))-  , ("description", definitionList <$> listenv "description" (many descItem))-  , ("enumerate", orderedList')-  , ("alltt", alltt =<< verbEnv "alltt")-  , ("code", guardEnabled Ext_literate_haskell *>-      (codeBlockWith ("",["sourceCode","literate","haskell"],[]) <$>-        verbEnv "code"))-  , ("comment", mempty <$ verbEnv "comment")-  , ("verbatim", codeBlock <$> verbEnv "verbatim")-  , ("Verbatim", fancyverbEnv "Verbatim")-  , ("BVerbatim", fancyverbEnv "BVerbatim")-  , ("lstlisting", do options <- option [] keyvals-                      let kvs = [ (if k == "firstnumber"-                                      then "startFrom"-                                      else k, v) | (k,v) <- options ]-                      let classes = [ "numberLines" |-                                      lookup "numbers" options == Just "left" ]-                                 ++ maybeToList (lookup "language" options-                                         >>= fromListingsLanguage)-                      let attr = (fromMaybe "" (lookup "label" options),classes,kvs)-                      codeBlockWith attr <$> verbEnv "lstlisting")-  , ("minted",     do options <- option [] keyvals-                      lang <- grouped (many1 $ satisfy (/='}'))-                      let kvs = [ (if k == "firstnumber"-                                      then "startFrom"-                                      else k, v) | (k,v) <- options ]-                      let classes = [ lang | not (null lang) ] ++-                                    [ "numberLines" |-                                      lookup "linenos" options == Just "true" ]-                      let attr = ("",classes,kvs)-                      codeBlockWith attr <$> verbEnv "minted")-  , ("obeylines", parseFromString-                  (para . trimInlines . mconcat <$> many inline) =<<-                  intercalate "\\\\\n" . lines <$> verbEnv "obeylines")-  , ("displaymath", mathEnv para Nothing "displaymath")-  , ("equation", mathEnv para Nothing "equation")-  , ("equation*", mathEnv para Nothing "equation*")-  , ("gather", mathEnv para (Just "gathered") "gather")-  , ("gather*", mathEnv para (Just "gathered") "gather*")-  , ("multline", mathEnv para (Just "gathered") "multline")-  , ("multline*", mathEnv para (Just "gathered") "multline*")-  , ("eqnarray", mathEnv para (Just "aligned") "eqnarray")-  , ("eqnarray*", mathEnv para (Just "aligned") "eqnarray*")-  , ("align", mathEnv para (Just "aligned") "align")-  , ("align*", mathEnv para (Just "aligned") "align*")-  , ("alignat", mathEnv para (Just "aligned") "alignat")-  , ("alignat*", mathEnv para (Just "aligned") "alignat*")-  ]--letterContents :: LP Blocks-letterContents = do-  bs <- blocks-  st <- getState-  -- add signature (author) and address (title)-  let addr = case lookupMeta "address" (stateMeta st) of-                  Just (MetaBlocks [Plain xs]) ->-                     para $ trimInlines $ fromList xs-                  _ -> mempty-  return $ addr <> bs -- sig added by \closing--closing :: LP Blocks-closing = do-  contents <- tok-  st <- getState-  let extractInlines (MetaBlocks [Plain ys]) = ys-      extractInlines (MetaBlocks [Para ys ]) = ys-      extractInlines _          = []-  let sigs = case lookupMeta "author" (stateMeta st) of-                  Just (MetaList xs) ->-                    para $ trimInlines $ fromList $-                      intercalate [LineBreak] $ map extractInlines xs-                  _ -> mempty-  return $ para (trimInlines contents) <> sigs--item :: LP Blocks-item = blocks *> controlSeq "item" *> skipopts *> blocks--looseItem :: LP Blocks-looseItem = do-  ctx <- stateParserContext `fmap` getState-  if ctx == ListItemState-     then mzero-     else return mempty--descItem :: LP (Inlines, [Blocks])-descItem = do-  blocks -- skip blocks before item-  controlSeq "item"-  optional sp-  ils <- opt-  bs <- blocks-  return (ils, [bs])--env :: String -> LP a -> LP a-env name p = p <*-  (try (controlSeq "end" *> braced >>= guard . (== name))-    <?> ("\\end{" ++ name ++ "}"))--listenv :: String -> LP a -> LP a-listenv name p = try $ do-  oldCtx <- stateParserContext `fmap` getState-  updateState $ \st -> st{ stateParserContext = ListItemState }-  res <- env name p-  updateState $ \st -> st{ stateParserContext = oldCtx }-  return res--mathEnv :: (Inlines -> a) -> Maybe String -> String -> LP a-mathEnv f innerEnv name = f <$> mathDisplay (inner <$> verbEnv name)-   where inner x = case innerEnv of-                      Nothing -> x-                      Just y  -> "\\begin{" ++ y ++ "}\n" ++ x ++-                                    "\\end{" ++ y ++ "}"--verbEnv :: String -> LP String-verbEnv name = do-  skipopts-  optional blankline-  let endEnv = try $ controlSeq "end" *> braced >>= guard . (== name)-  res <- manyTill anyChar endEnv-  return $ stripTrailingNewlines res--fancyverbEnv :: String -> LP Blocks-fancyverbEnv name = do-  options <- option [] keyvals-  let kvs = [ (if k == "firstnumber"-                  then "startFrom"-                  else k, v) | (k,v) <- options ]-  let classes = [ "numberLines" |-                  lookup "numbers" options == Just "left" ]-  let attr = ("",classes,kvs)-  codeBlockWith attr <$> verbEnv name--orderedList' :: LP Blocks-orderedList' = do-  optional sp-  (_, style, delim) <- option (1, DefaultStyle, DefaultDelim) $-                              try $ char '[' *> anyOrderedListMarker <* char ']'-  spaces-  optional $ try $ controlSeq "setlength" *> grouped (controlSeq "itemindent") *> braced-  spaces-  start <- option 1 $ try $ do controlSeq "setcounter"-                               grouped (string "enum" *> many1 (oneOf "iv"))-                               optional sp-                               num <- grouped (many1 digit)-                               spaces-                               return (read num + 1 :: Int)-  bs <- listenv "enumerate" (many item)-  return $ orderedListWith (start, style, delim) bs--paragraph :: LP Blocks-paragraph = do-  x <- trimInlines . mconcat <$> many1 inline-  if x == mempty-     then return mempty-     else return $ para x--preamble :: LP Blocks-preamble = mempty <$> manyTill preambleBlock beginDoc-  where beginDoc = lookAhead $ try $ controlSeq "begin" *> string "{document}"-        preambleBlock =  void comment-                     <|> void sp-                     <|> void blanklines-                     <|> void macro-                     <|> void blockCommand-                     <|> void anyControlSeq-                     <|> void braced-                     <|> void anyChar------------- citations--addPrefix :: [Inline] -> [Citation] -> [Citation]-addPrefix p (k:ks)   = k {citationPrefix = p ++ citationPrefix k} : ks-addPrefix _ _ = []--addSuffix :: [Inline] -> [Citation] -> [Citation]-addSuffix s ks@(_:_) =-  let k = last ks-  in  init ks ++ [k {citationSuffix = citationSuffix k ++ s}]-addSuffix _ _ = []--simpleCiteArgs :: LP [Citation]-simpleCiteArgs = try $ do-  first  <- optionMaybe $ toList <$> opt-  second <- optionMaybe $ toList <$> opt-  char '{'-  optional sp-  keys <- manyTill citationLabel (char '}')-  let (pre, suf) = case (first  , second ) of-        (Just s , Nothing) -> (mempty, s )-        (Just s , Just t ) -> (s , t )-        _                  -> (mempty, mempty)-      conv k = Citation { citationId      = k-                        , citationPrefix  = []-                        , citationSuffix  = []-                        , citationMode    = NormalCitation-                        , citationHash    = 0-                        , citationNoteNum = 0-                        }-  return $ addPrefix pre $ addSuffix suf $ map conv keys--citationLabel :: LP String-citationLabel  = optional sp *>-  (many1 (satisfy isBibtexKeyChar)-          <* optional sp-          <* optional (char ',')-          <* optional sp)-  where isBibtexKeyChar c = isAlphaNum c || c `elem` (".:;?!`'()/*@_+=-[]" :: String)--cites :: CitationMode -> Bool -> LP [Citation]-cites mode multi = try $ do-  cits <- if multi-             then many1 simpleCiteArgs-             else count 1 simpleCiteArgs-  let cs = concat cits-  return $ case mode of-        AuthorInText -> case cs of-                             (c:rest) -> c {citationMode = mode} : rest-                             []       -> []-        _            -> map (\a -> a {citationMode = mode}) cs--citation :: String -> CitationMode -> Bool -> LP Inlines-citation name mode multi = do-  (c,raw) <- withRaw $ cites mode multi-  return $ cite c (rawInline "latex" $ "\\" ++ name ++ raw)--complexNatbibCitation :: CitationMode -> LP Inlines-complexNatbibCitation mode = try $ do-  let ils = (toList . trimInlines . mconcat) <$>-              many (notFollowedBy (oneOf "\\};") >> inline)-  let parseOne = try $ do-                   skipSpaces-                   pref  <- ils-                   cit' <- inline -- expect a citation-                   let citlist = toList cit'-                   cits' <- case citlist of-                                 [Cite cs _] -> return cs-                                 _           -> mzero-                   suff  <- ils-                   skipSpaces-                   optional $ char ';'-                   return $ addPrefix pref $ addSuffix suff cits'-  (c:cits, raw) <- withRaw $ grouped parseOne-  return $ cite (c{ citationMode = mode }:cits)-           (rawInline "latex" $ "\\citetext" ++ raw)---- tables--parseAligns :: LP [Alignment]-parseAligns = try $ do-  char '{'-  let maybeBar = skipMany $ sp <|> () <$ char '|' <|> () <$ (char '@' >> braced)-  maybeBar-  let cAlign = AlignCenter <$ char 'c'-  let lAlign = AlignLeft <$ char 'l'-  let rAlign = AlignRight <$ char 'r'-  let parAlign = AlignLeft <$ (char 'p' >> braced)-  let alignChar = cAlign <|> lAlign <|> rAlign <|> parAlign-  aligns' <- sepEndBy alignChar maybeBar-  spaces-  char '}'-  spaces-  return aligns'--hline :: LP ()-hline = try $ do-  spaces'-  controlSeq "hline" <|>-    -- booktabs rules:-    controlSeq "toprule" <|>-    controlSeq "bottomrule" <|>-    controlSeq "midrule" <|>-    controlSeq "endhead" <|>-    controlSeq "endfirsthead"-  spaces'-  optional $ bracketed (many1 (satisfy (/=']')))-  return ()--lbreak :: LP ()-lbreak = () <$ try (spaces' *>-                    (controlSeq "\\" <|> controlSeq "tabularnewline") <*-                    spaces')--amp :: LP ()-amp = () <$ try (spaces' *> char '&' <* spaces')--parseTableRow :: Int  -- ^ number of columns-              -> LP [Blocks]-parseTableRow cols = try $ do-  let tableCellInline = notFollowedBy (amp <|> lbreak) >> inline-  let minipage = try $ controlSeq "begin" *> string "{minipage}" *>-          env "minipage"-          (skipopts *> spaces' *> optional braced *> spaces' *> blocks)-  let tableCell = minipage <|>-            ((plain . trimInlines . mconcat) <$> many tableCellInline)-  cells' <- sepBy1 tableCell amp-  let numcells = length cells'-  guard $ numcells <= cols && numcells >= 1-  guard $ cells' /= [mempty]-  -- note:  a & b in a three-column table leaves an empty 3rd cell:-  let cells'' = cells' ++ replicate (cols - numcells) mempty-  spaces'-  return cells''--spaces' :: LP ()-spaces' = spaces *> skipMany (comment *> spaces)--simpTable :: Bool -> LP Blocks-simpTable hasWidthParameter = try $ do-  when hasWidthParameter $ () <$ (spaces' >> tok)-  skipopts-  aligns <- parseAligns-  let cols = length aligns-  optional $ controlSeq "caption" *> skipopts *> setCaption-  optional lbreak-  spaces'-  skipMany hline-  spaces'-  header' <- option [] $ try (parseTableRow cols <* lbreak <* many1 hline)-  spaces'-  rows <- sepEndBy (parseTableRow cols) (lbreak <* optional (skipMany hline))-  spaces'-  optional $ controlSeq "caption" *> skipopts *> setCaption-  optional lbreak-  spaces'-  let header'' = if null header'-                    then replicate cols mempty-                    else header'-  lookAhead $ controlSeq "end" -- make sure we're at end-  return $ table mempty (zip aligns (repeat 0)) header'' rows--startInclude :: LP Blocks-startInclude = do-  fn <- braced-  setPosition $ newPos fn 1 1-  return mempty--endInclude :: LP Blocks-endInclude = do-  fn <- braced-  ln <- braced-  co <- braced-  setPosition $ newPos fn (fromMaybe 1 $ safeRead ln) (fromMaybe 1 $ safeRead co)-  return mempty--removeDoubleQuotes :: String -> String-removeDoubleQuotes ('"':xs) =-  case reverse xs of-       '"':ys -> reverse ys-       _      -> '"':xs-removeDoubleQuotes xs = xs+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings     #-}+{-# LANGUAGE PatternGuards         #-}+{-# LANGUAGE ScopedTypeVariables   #-}+{-+Copyright (C) 2006-2017 John MacFarlane <jgm@berkeley.edu>++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation; either version 2 of the License, or+(at your option) any later version.++This program is distributed in the hope that it will be useful,+but WITHOUT ANY WARRANTY; without even the implied warranty of+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+GNU General Public License for more details.++You should have received a copy of the GNU General Public License+along with this program; if not, write to the Free Software+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+-}++{- |+   Module      : Text.Pandoc.Readers.LaTeX+   Copyright   : Copyright (C) 2006-2017 John MacFarlane+   License     : GNU GPL, version 2 or above++   Maintainer  : John MacFarlane <jgm@berkeley.edu>+   Stability   : alpha+   Portability : portable++Conversion of LaTeX to 'Pandoc' document.++-}+module Text.Pandoc.Readers.LaTeX ( readLaTeX,+                                   applyMacros,+                                   rawLaTeXInline,+                                   rawLaTeXBlock,+                                   inlineCommand+                                 ) where++import Control.Applicative (many, optional, (<|>))+import Control.Monad+import Control.Monad.Except (throwError)+import Control.Monad.Trans (lift)+import Data.Char (chr, isAlphaNum, isDigit, isLetter, ord, toLower)+import Data.Default+import Data.List (intercalate, isPrefixOf)+import qualified Data.Map as M+import Data.Maybe (fromMaybe, maybeToList)+import qualified Data.Set as Set+import Data.Text (Text)+import qualified Data.Text as T+import Safe (minimumDef)+import System.FilePath (addExtension, replaceExtension, takeExtension)+import Text.Pandoc.BCP47 (Lang (..), renderLang)+import Text.Pandoc.Builder+import Text.Pandoc.Class (PandocMonad, PandocPure, getResourcePath, lookupEnv,+                          readFileFromDirs, report, setResourcePath,+                          setTranslations, translateTerm)+import Text.Pandoc.Error (PandocError (PandocMacroLoop, PandocParseError, PandocParsecError))+import Text.Pandoc.Highlighting (fromListingsLanguage, languagesByExtension)+import Text.Pandoc.ImageSize (numUnit, showFl)+import Text.Pandoc.Logging+import Text.Pandoc.Options+import Text.Pandoc.Parsing hiding (blankline, many, mathDisplay, mathInline,+                            optional, space, spaces, withRaw, (<|>))+import Text.Pandoc.Readers.LaTeX.Types (ExpansionPoint (..), Macro (..),+                                        Tok (..), TokType (..))+import Text.Pandoc.Shared+import qualified Text.Pandoc.Translations as Translations+import Text.Pandoc.Walk+import Text.Parsec.Pos++-- for debugging:+-- import Text.Pandoc.Extensions (getDefaultExtensions)+-- import Text.Pandoc.Class (runIOorExplode, PandocIO)+-- import Debug.Trace (traceShowId)++-- | Parse LaTeX from string and return 'Pandoc' document.+readLaTeX :: PandocMonad m+          => ReaderOptions -- ^ Reader options+          -> Text        -- ^ String to parse (assumes @'\n'@ line endings)+          -> m Pandoc+readLaTeX opts ltx = do+  parsed <- runParserT parseLaTeX def{ sOptions = opts } "source"+               (tokenize "source" (crFilter ltx))+  case parsed of+    Right result -> return result+    Left e       -> throwError $ PandocParsecError (T.unpack ltx) e++parseLaTeX :: PandocMonad m => LP m Pandoc+parseLaTeX = do+  bs <- blocks+  eof+  st <- getState+  let meta = sMeta st+  let doc' = doc bs+  let headerLevel (Header n _ _) = [n]+      headerLevel _              = []+  let bottomLevel = minimumDef 1 $ query headerLevel doc'+  let adjustHeaders m (Header n attr ils) = Header (n+m) attr ils+      adjustHeaders _ x                   = x+  let (Pandoc _ bs') =+       -- handle the case where you have \part or \chapter+       (if bottomLevel < 1+           then walk (adjustHeaders (1 - bottomLevel))+           else id) $+       walk (resolveRefs (sLabels st)) doc'+  return $ Pandoc meta bs'++resolveRefs :: M.Map String [Inline] -> Inline -> Inline+resolveRefs labels x@(Link (ident,classes,kvs) _ _) =+  case (lookup "reference-type" kvs,+        lookup "reference" kvs) of+        (Just "ref", Just lab) ->+          case M.lookup lab labels of+               Just txt -> Link (ident,classes,kvs) txt ('#':lab, "")+               Nothing  -> x+        _ -> x+resolveRefs _ x = x+++-- testParser :: LP PandocIO a -> Text -> IO a+-- testParser p t = do+--   res <- runIOorExplode (runParserT p defaultLaTeXState{+--             sOptions = def{ readerExtensions =+--               enableExtension Ext_raw_tex $+--                 getDefaultExtensions "latex" }} "source" (tokenize "source" t))+--   case res of+--        Left e  -> error (show e)+--        Right r -> return r++newtype HeaderNum = HeaderNum [Int]+  deriving (Show)++renderHeaderNum :: HeaderNum -> String+renderHeaderNum (HeaderNum xs) =+  intercalate "." (map show xs)++incrementHeaderNum :: Int -> HeaderNum -> HeaderNum+incrementHeaderNum level (HeaderNum ns) = HeaderNum $+  case reverse (take level (ns ++ repeat 0)) of+       (x:xs) -> reverse (x+1 : xs)+       []     -> []  -- shouldn't happen++data LaTeXState = LaTeXState{ sOptions       :: ReaderOptions+                            , sMeta          :: Meta+                            , sQuoteContext  :: QuoteContext+                            , sMacros        :: M.Map Text Macro+                            , sContainers    :: [String]+                            , sHeaders       :: M.Map Inlines String+                            , sLogMessages   :: [LogMessage]+                            , sIdentifiers   :: Set.Set String+                            , sVerbatimMode  :: Bool+                            , sCaption       :: Maybe Inlines+                            , sInListItem    :: Bool+                            , sInTableCell   :: Bool+                            , sLastHeaderNum :: HeaderNum+                            , sLabels        :: M.Map String [Inline]+                            , sToggles       :: M.Map String Bool+                            }+     deriving Show++defaultLaTeXState :: LaTeXState+defaultLaTeXState = LaTeXState{ sOptions       = def+                              , sMeta          = nullMeta+                              , sQuoteContext  = NoQuote+                              , sMacros        = M.empty+                              , sContainers    = []+                              , sHeaders       = M.empty+                              , sLogMessages   = []+                              , sIdentifiers   = Set.empty+                              , sVerbatimMode  = False+                              , sCaption       = Nothing+                              , sInListItem    = False+                              , sInTableCell   = False+                              , sLastHeaderNum = HeaderNum []+                              , sLabels        = M.empty+                              , sToggles       = M.empty+                              }++instance PandocMonad m => HasQuoteContext LaTeXState m where+  getQuoteContext = sQuoteContext <$> getState+  withQuoteContext context parser = do+    oldState <- getState+    let oldQuoteContext = sQuoteContext oldState+    setState oldState { sQuoteContext = context }+    result <- parser+    newState <- getState+    setState newState { sQuoteContext = oldQuoteContext }+    return result++instance HasLogMessages LaTeXState where+  addLogMessage msg st = st{ sLogMessages = msg : sLogMessages st }+  getLogMessages st = reverse $ sLogMessages st++instance HasIdentifierList LaTeXState where+  extractIdentifierList     = sIdentifiers+  updateIdentifierList f st = st{ sIdentifiers = f $ sIdentifiers st }++instance HasIncludeFiles LaTeXState where+  getIncludeFiles = sContainers+  addIncludeFile f s = s{ sContainers = f : sContainers s }+  dropLatestIncludeFile s = s { sContainers = drop 1 $ sContainers s }++instance HasHeaderMap LaTeXState where+  extractHeaderMap     = sHeaders+  updateHeaderMap f st = st{ sHeaders = f $ sHeaders st }++instance HasMacros LaTeXState where+  extractMacros  st  = sMacros st+  updateMacros f st  = st{ sMacros = f (sMacros st) }++instance HasReaderOptions LaTeXState where+  extractReaderOptions = sOptions++instance HasMeta LaTeXState where+  setMeta field val st =+    st{ sMeta = setMeta field val $ sMeta st }+  deleteMeta field st =+    st{ sMeta = deleteMeta field $ sMeta st }++instance Default LaTeXState where+  def = defaultLaTeXState++type LP m = ParserT [Tok] LaTeXState m++withVerbatimMode :: PandocMonad m => LP m a -> LP m a+withVerbatimMode parser = do+  updateState $ \st -> st{ sVerbatimMode = True }+  result <- parser+  updateState $ \st -> st{ sVerbatimMode = False }+  return result++rawLaTeXParser :: (PandocMonad m, HasMacros s, HasReaderOptions s)+               => LP m a -> ParserT String s m String+rawLaTeXParser parser = do+  inp <- getInput+  let toks = tokenize "source" $ T.pack inp+  pstate <- getState+  let lstate = def{ sOptions = extractReaderOptions pstate }+  res <- lift $ runParserT ((,) <$> try (snd <$> withRaw parser) <*> getState)+            lstate "source" toks+  case res of+       Left _    -> mzero+       Right (raw, st) -> do+         updateState (updateMacros (sMacros st <>))+         takeP (T.length (untokenize raw))++applyMacros :: (PandocMonad m, HasMacros s, HasReaderOptions s)+            => String -> ParserT String s m String+applyMacros s = (guardDisabled Ext_latex_macros >> return s) <|>+   do let retokenize = doMacros 0 *>+             (toksToString <$> many (satisfyTok (const True)))+      pstate <- getState+      let lstate = def{ sOptions = extractReaderOptions pstate+                      , sMacros  = extractMacros pstate }+      res <- runParserT retokenize lstate "math" (tokenize "math" (T.pack s))+      case res of+           Left e   -> fail (show e)+           Right s' -> return s'++rawLaTeXBlock :: (PandocMonad m, HasMacros s, HasReaderOptions s)+              => ParserT String s m String+rawLaTeXBlock = do+  lookAhead (try (char '\\' >> letter))+  rawLaTeXParser (environment <|> macroDef <|> blockCommand)++rawLaTeXInline :: (PandocMonad m, HasMacros s, HasReaderOptions s)+               => ParserT String s m String+rawLaTeXInline = do+  lookAhead (try (char '\\' >> letter) <|> char '$')+  rawLaTeXParser (inlineEnvironment <|> inlineCommand')++inlineCommand :: PandocMonad m => ParserT String ParserState m Inlines+inlineCommand = do+  lookAhead (try (char '\\' >> letter) <|> char '$')+  inp <- getInput+  let toks = tokenize "chunk" $ T.pack inp+  let rawinline = do+         (il, raw) <- try $ withRaw (inlineEnvironment <|> inlineCommand')+         st <- getState+         return (il, raw, st)+  pstate <- getState+  let lstate = def{ sOptions = extractReaderOptions pstate+                  , sMacros  = extractMacros pstate }+  res <- runParserT rawinline lstate "source" toks+  case res of+       Left _ -> mzero+       Right (il, raw, s) -> do+         updateState $ updateMacros (const $ sMacros s)+         takeP (T.length (untokenize raw))+         return il++tokenize :: SourceName -> Text -> [Tok]+tokenize sourcename = totoks (initialPos sourcename)++totoks :: SourcePos -> Text -> [Tok]+totoks pos t =+  case T.uncons t of+       Nothing        -> []+       Just (c, rest)+         | c == '\n' ->+           Tok pos Newline "\n"+           : totoks (setSourceColumn (incSourceLine pos 1) 1) rest+         | isSpaceOrTab c ->+           let (sps, rest') = T.span isSpaceOrTab t+           in  Tok pos Spaces sps+               : totoks (incSourceColumn pos (T.length sps))+                 rest'+         | isAlphaNum c ->+           let (ws, rest') = T.span isAlphaNum t+           in  Tok pos Word ws+               : totoks (incSourceColumn pos (T.length ws)) rest'+         | c == '%' ->+           let (cs, rest') = T.break (== '\n') rest+           in  Tok pos Comment ("%" <> cs)+               : totoks (incSourceColumn pos (1 + T.length cs)) rest'+         | c == '\\' ->+           case T.uncons rest of+                Nothing -> [Tok pos Symbol (T.singleton c)]+                Just (d, rest')+                  | isLetterOrAt d ->+                      -- \makeatletter is common in macro defs;+                      -- ideally we should make tokenization sensitive+                      -- to \makeatletter and \makeatother, but this is+                      -- probably best for now+                      let (ws, rest'') = T.span isLetterOrAt rest+                          (ss, rest''') = T.span isSpaceOrTab rest''+                      in  Tok pos (CtrlSeq ws) ("\\" <> ws <> ss)+                          : totoks (incSourceColumn pos+                               (1 + T.length ws + T.length ss)) rest'''+                  | d == '\t' || d == '\n' ->+                      Tok pos Symbol "\\"+                      : totoks (incSourceColumn pos 1) rest+                  | otherwise  ->+                      Tok pos (CtrlSeq (T.singleton d)) (T.pack [c,d])+                      : totoks (incSourceColumn pos 2) rest'+         | c == '#' ->+           let (t1, t2) = T.span (\d -> d >= '0' && d <= '9') rest+           in  case safeRead (T.unpack t1) of+                    Just i ->+                       Tok pos (Arg i) ("#" <> t1)+                       : totoks (incSourceColumn pos (1 + T.length t1)) t2+                    Nothing ->+                       Tok pos Symbol ("#")+                       : totoks (incSourceColumn pos 1) t2+         | c == '^' ->+           case T.uncons rest of+                Just ('^', rest') ->+                  case T.uncons rest' of+                       Just (d, rest'')+                         | isLowerHex d ->+                           case T.uncons rest'' of+                                Just (e, rest''') | isLowerHex e ->+                                  Tok pos Esc2 (T.pack ['^','^',d,e])+                                  : totoks (incSourceColumn pos 4) rest'''+                                _ ->+                                  Tok pos Esc1 (T.pack ['^','^',d])+                                  : totoks (incSourceColumn pos 3) rest''+                         | d < '\128' ->+                                  Tok pos Esc1 (T.pack ['^','^',d])+                                  : totoks (incSourceColumn pos 3) rest''+                       _ -> [Tok pos Symbol ("^"),+                             Tok (incSourceColumn pos 1) Symbol ("^")]+                _ -> Tok pos Symbol ("^")+                     : totoks (incSourceColumn pos 1) rest+         | otherwise ->+           Tok pos Symbol (T.singleton c) : totoks (incSourceColumn pos 1) rest++isSpaceOrTab :: Char -> Bool+isSpaceOrTab ' '  = True+isSpaceOrTab '\t' = True+isSpaceOrTab _    = False++isLetterOrAt :: Char -> Bool+isLetterOrAt '@' = True+isLetterOrAt c   = isLetter c++isLowerHex :: Char -> Bool+isLowerHex x = x >= '0' && x <= '9' || x >= 'a' && x <= 'f'++untokenize :: [Tok] -> Text+untokenize = mconcat . map untoken++untoken :: Tok -> Text+untoken (Tok _ _ t) = t++satisfyTok :: PandocMonad m => (Tok -> Bool) -> LP m Tok+satisfyTok f =+  try $ do+    res <- tokenPrim (T.unpack . untoken) updatePos matcher+    doMacros 0 -- apply macros on remaining input stream+    return res+  where matcher t | f t       = Just t+                  | otherwise = Nothing+        updatePos :: SourcePos -> Tok -> [Tok] -> SourcePos+        updatePos _spos _ (Tok pos _ _ : _) = pos+        updatePos spos _ []                 = spos++doMacros :: PandocMonad m => Int -> LP m ()+doMacros n = do+  verbatimMode <- sVerbatimMode <$> getState+  unless verbatimMode $ do+    inp <- getInput+    case inp of+         Tok spos (CtrlSeq "begin") _ : Tok _ Symbol "{" :+          Tok _ Word name : Tok _ Symbol "}" : ts+            -> handleMacros spos name ts+         Tok spos (CtrlSeq "end") _ : Tok _ Symbol "{" :+          Tok _ Word name : Tok _ Symbol "}" : ts+            -> handleMacros spos ("end" <> name) ts+         Tok _ (CtrlSeq "expandafter") _ : t : ts+            -> do setInput ts+                  doMacros n+                  getInput >>= setInput . combineTok t+         Tok spos (CtrlSeq name) _ : ts+            -> handleMacros spos name ts+         _ -> return ()+  where combineTok (Tok spos (CtrlSeq name) x) (Tok _ Word w : ts)+          | T.all isLetterOrAt w =+            Tok spos (CtrlSeq (name <> w)) (x1 <> w <> x2) : ts+              where (x1, x2) = T.break isSpaceOrTab x+        combineTok t ts = t:ts+        handleMacros spos name ts = do+                macros <- sMacros <$> getState+                case M.lookup name macros of+                     Nothing -> return ()+                     Just (Macro expansionPoint numargs optarg newtoks) -> do+                       setInput ts+                       let getarg = spaces >> braced+                       args <- case optarg of+                                    Nothing -> count numargs getarg+                                    Just o  ->+                                       (:) <$> option o bracketedToks+                                           <*> count (numargs - 1) getarg+                       let addTok (Tok _ (Arg i) _) acc | i > 0+                                                        , i <= numargs =+                                 map (setpos spos) (args !! (i - 1)) ++ acc+                           addTok t acc = setpos spos t : acc+                       ts' <- getInput+                       setInput $ foldr addTok ts' newtoks+                       case expansionPoint of+                            ExpandWhenUsed ->+                              if n > 20  -- detect macro expansion loops+                                 then throwError $ PandocMacroLoop (T.unpack name)+                                 else doMacros (n + 1)+                            ExpandWhenDefined -> return ()+++setpos :: SourcePos -> Tok -> Tok+setpos spos (Tok _ tt txt) = Tok spos tt txt++anyControlSeq :: PandocMonad m => LP m Tok+anyControlSeq = satisfyTok isCtrlSeq+  where isCtrlSeq (Tok _ (CtrlSeq _) _) = True+        isCtrlSeq _                     = False++anySymbol :: PandocMonad m => LP m Tok+anySymbol = satisfyTok isSym+  where isSym (Tok _ Symbol _) = True+        isSym _                = False++spaces :: PandocMonad m => LP m ()+spaces = skipMany (satisfyTok (tokTypeIn [Comment, Spaces, Newline]))++spaces1 :: PandocMonad m => LP m ()+spaces1 = skipMany1 (satisfyTok (tokTypeIn [Comment, Spaces, Newline]))++tokTypeIn :: [TokType] -> Tok -> Bool+tokTypeIn toktypes (Tok _ tt _) = tt `elem` toktypes++controlSeq :: PandocMonad m => Text -> LP m Tok+controlSeq name = satisfyTok isNamed+  where isNamed (Tok _ (CtrlSeq n) _) = n == name+        isNamed _                     = False++symbol :: PandocMonad m => Char -> LP m Tok+symbol c = satisfyTok isc+  where isc (Tok _ Symbol d) = case T.uncons d of+                                    Just (c',_) -> c == c'+                                    _           -> False+        isc _ = False++symbolIn :: PandocMonad m => [Char] -> LP m Tok+symbolIn cs = satisfyTok isInCs+  where isInCs (Tok _ Symbol d) = case T.uncons d of+                                       Just (c,_) -> c `elem` cs+                                       _          -> False+        isInCs _ = False++sp :: PandocMonad m => LP m ()+sp = whitespace <|> endline++whitespace :: PandocMonad m => LP m ()+whitespace = () <$ satisfyTok isSpaceTok+  where isSpaceTok (Tok _ Spaces _) = True+        isSpaceTok _                = False++newlineTok :: PandocMonad m => LP m ()+newlineTok = () <$ satisfyTok isNewlineTok++isNewlineTok :: Tok -> Bool+isNewlineTok (Tok _ Newline _) = True+isNewlineTok _                 = False++comment :: PandocMonad m => LP m ()+comment = () <$ satisfyTok isCommentTok+  where isCommentTok (Tok _ Comment _) = True+        isCommentTok _                 = False++anyTok :: PandocMonad m => LP m Tok+anyTok = satisfyTok (const True)++endline :: PandocMonad m => LP m ()+endline = try $ do+  newlineTok+  lookAhead anyTok+  notFollowedBy blankline++blankline :: PandocMonad m => LP m ()+blankline = try $ skipMany whitespace *> newlineTok++primEscape :: PandocMonad m => LP m Char+primEscape = do+  Tok _ toktype t <- satisfyTok (tokTypeIn [Esc1, Esc2])+  case toktype of+       Esc1 -> case T.uncons (T.drop 2 t) of+                    Just (c, _)+                      | c >= '\64' && c <= '\127' -> return (chr (ord c - 64))+                      | otherwise                 -> return (chr (ord c + 64))+                    Nothing -> fail "Empty content of Esc1"+       Esc2 -> case safeRead ('0':'x':T.unpack (T.drop 2 t)) of+                    Just x  -> return (chr x)+                    Nothing -> fail $ "Could not read: " ++ T.unpack t+       _    -> fail "Expected an Esc1 or Esc2 token" -- should not happen++bgroup :: PandocMonad m => LP m Tok+bgroup = try $ do+  skipMany sp+  symbol '{' <|> controlSeq "bgroup" <|> controlSeq "begingroup"++egroup :: PandocMonad m => LP m Tok+egroup = symbol '}' <|> controlSeq "egroup" <|> controlSeq "endgroup"++grouped :: (PandocMonad m,  Monoid a) => LP m a -> LP m a+grouped parser = try $ do+  bgroup+  -- first we check for an inner 'grouped', because+  -- {{a,b}} should be parsed the same as {a,b}+  try (grouped parser <* egroup) <|> (mconcat <$> manyTill parser egroup)++braced :: PandocMonad m => LP m [Tok]+braced = bgroup *> braced' 1+  where braced' (n :: Int) =+          handleEgroup n <|> handleBgroup n <|> handleOther n+        handleEgroup n = do+          t <- egroup+          if n == 1+             then return []+             else (t:) <$> braced' (n - 1)+        handleBgroup n = do+          t <- bgroup+          (t:) <$> braced' (n + 1)+        handleOther n = do+          t <- anyTok+          (t:) <$> braced' n++bracketed :: PandocMonad m => Monoid a => LP m a -> LP m a+bracketed parser = try $ do+  symbol '['+  mconcat <$> manyTill parser (symbol ']')++dimenarg :: PandocMonad m => LP m Text+dimenarg = try $ do+  ch  <- option False $ True <$ symbol '='+  Tok _ _ s <- satisfyTok isWordTok+  guard $ T.take 2 (T.reverse s) `elem`+           ["pt","pc","in","bp","cm","mm","dd","cc","sp"]+  let num = T.take (T.length s - 2) s+  guard $ T.length num > 0+  guard $ T.all isDigit num+  return $ T.pack ['=' | ch] <> s++-- inline elements:++word :: PandocMonad m => LP m Inlines+word = (str . T.unpack . untoken) <$> satisfyTok isWordTok++regularSymbol :: PandocMonad m => LP m Inlines+regularSymbol = (str . T.unpack . untoken) <$> satisfyTok isRegularSymbol+  where isRegularSymbol (Tok _ Symbol t) = not $ T.any isSpecial t+        isRegularSymbol _                = False+        isSpecial c = c `Set.member` specialChars++specialChars :: Set.Set Char+specialChars = Set.fromList "#$%&~_^\\{}"++isWordTok :: Tok -> Bool+isWordTok (Tok _ Word _) = True+isWordTok _              = False++inlineGroup :: PandocMonad m => LP m Inlines+inlineGroup = do+  ils <- grouped inline+  if isNull ils+     then return mempty+     else return $ spanWith nullAttr ils+          -- we need the span so we can detitlecase bibtex entries;+          -- we need to know when something is {C}apitalized++doLHSverb :: PandocMonad m => LP m Inlines+doLHSverb =+  (codeWith ("",["haskell"],[]) . T.unpack . untokenize)+    <$> manyTill (satisfyTok (not . isNewlineTok)) (symbol '|')++mkImage :: PandocMonad m => [(String, String)] -> String -> LP m Inlines+mkImage options src = do+   let replaceTextwidth (k,v) =+         case numUnit v of+              Just (num, "\\textwidth") -> (k, showFl (num * 100) ++ "%")+              _                         -> (k, v)+   let kvs = map replaceTextwidth+             $ filter (\(k,_) -> k `elem` ["width", "height"]) options+   let attr = ("",[], kvs)+   let alt = str "image"+   case takeExtension src of+        "" -> do+              defaultExt <- getOption readerDefaultImageExtension+              return $ imageWith attr (addExtension src defaultExt) "" alt+        _  -> return $ imageWith attr src "" alt++doxspace :: PandocMonad m => LP m Inlines+doxspace =+  (space <$ lookAhead (satisfyTok startsWithLetter)) <|> return mempty+  where startsWithLetter (Tok _ Word t) =+          case T.uncons t of+               Just (c, _) | isLetter c -> True+               _           -> False+        startsWithLetter _ = False+++-- converts e.g. \SI{1}[\$]{} to "$ 1" or \SI{1}{\euro} to "1 €"+dosiunitx :: PandocMonad m => LP m Inlines+dosiunitx = do+  skipopts+  value <- tok+  valueprefix <- option "" $ bracketed tok+  unit <- tok+  let emptyOr160 "" = ""+      emptyOr160 _  = "\160"+  return . mconcat $ [valueprefix,+                      emptyOr160 valueprefix,+                      value,+                      emptyOr160 unit,+                      unit]++lit :: String -> LP m Inlines+lit = pure . str++removeDoubleQuotes :: Text -> Text+removeDoubleQuotes t =+  Data.Maybe.fromMaybe t $ T.stripPrefix "\"" t >>= T.stripSuffix "\""++doubleQuote :: PandocMonad m => LP m Inlines+doubleQuote =+       quoted' doubleQuoted (try $ count 2 $ symbol '`')+                     (void $ try $ count 2 $ symbol '\'')+   <|> quoted' doubleQuoted ((:[]) <$> symbol '“') (void $ symbol '”')+   -- the following is used by babel for localized quotes:+   <|> quoted' doubleQuoted (try $ sequence [symbol '"', symbol '`'])+                            (void $ try $ sequence [symbol '"', symbol '\''])++singleQuote :: PandocMonad m => LP m Inlines+singleQuote =+       quoted' singleQuoted ((:[]) <$> symbol '`')+                     (try $ symbol '\'' >>+                           notFollowedBy (satisfyTok startsWithLetter))+   <|> quoted' singleQuoted ((:[]) <$> symbol '‘')+                            (try $ symbol '’' >>+                                  notFollowedBy (satisfyTok startsWithLetter))+  where startsWithLetter (Tok _ Word t) =+          case T.uncons t of+               Just (c, _) | isLetter c -> True+               _           -> False+        startsWithLetter _ = False++quoted' :: PandocMonad m+        => (Inlines -> Inlines)+        -> LP m [Tok]+        -> LP m ()+        -> LP m Inlines+quoted' f starter ender = do+  startchs <- (T.unpack . untokenize) <$> starter+  smart <- extensionEnabled Ext_smart <$> getOption readerExtensions+  if smart+     then do+       ils <- many (notFollowedBy ender >> inline)+       (ender >> return (f (mconcat ils))) <|>+            (<> mconcat ils) <$>+                    lit (case startchs of+                              "``" -> "“"+                              "`"  -> "‘"+                              cs   -> cs)+     else lit startchs++enquote :: PandocMonad m => LP m Inlines+enquote = do+  skipopts+  quoteContext <- sQuoteContext <$> getState+  if quoteContext == InDoubleQuote+     then singleQuoted <$> withQuoteContext InSingleQuote tok+     else doubleQuoted <$> withQuoteContext InDoubleQuote tok++doAcronym :: PandocMonad m => String -> LP m Inlines+doAcronym form = do+  acro <- braced+  return . mconcat $ [spanWith ("",[],[("acronym-label", toksToString acro),+    ("acronym-form", "singular+" ++ form)])+    $ str $ toksToString acro]++doAcronymPlural :: PandocMonad m => String -> LP m Inlines+doAcronymPlural form = do+  acro <- braced+  plural <- lit "s"+  return . mconcat $ [spanWith ("",[],[("acronym-label", toksToString acro),+    ("acronym-form", "plural+" ++ form)]) $+   mconcat [str $ toksToString acro, plural]]++doverb :: PandocMonad m => LP m Inlines+doverb = do+  Tok _ Symbol t <- anySymbol+  marker <- case T.uncons t of+              Just (c, ts) | T.null ts -> return c+              _            -> mzero+  withVerbatimMode $+    (code . T.unpack . untokenize) <$>+      manyTill (verbTok marker) (symbol marker)++verbTok :: PandocMonad m => Char -> LP m Tok+verbTok stopchar = do+  t@(Tok pos toktype txt) <- satisfyTok (not . isNewlineTok)+  case T.findIndex (== stopchar) txt of+       Nothing -> return t+       Just i  -> do+         let (t1, t2) = T.splitAt i txt+         inp <- getInput+         setInput $ Tok (incSourceColumn pos i) Symbol (T.singleton stopchar)+                  : totoks (incSourceColumn pos (i + 1)) (T.drop 1 t2) ++ inp+         return $ Tok pos toktype t1++dolstinline :: PandocMonad m => LP m Inlines+dolstinline = do+  options <- option [] keyvals+  let classes = maybeToList $ lookup "language" options >>= fromListingsLanguage+  Tok _ Symbol t <- anySymbol+  marker <- case T.uncons t of+              Just (c, ts) | T.null ts -> return c+              _            -> mzero+  let stopchar = if marker == '{' then '}' else marker+  withVerbatimMode $+    (codeWith ("",classes,[]) . T.unpack . untokenize) <$>+      manyTill (verbTok stopchar) (symbol stopchar)++keyval :: PandocMonad m => LP m (String, String)+keyval = try $ do+  Tok _ Word key <- satisfyTok isWordTok+  let isSpecSym (Tok _ Symbol t) = t /= "]" && t /= ","+      isSpecSym _                = False+  optional sp+  val <- option [] $ do+           symbol '='+           optional sp+           braced <|> many1 (satisfyTok isWordTok <|> satisfyTok isSpecSym+                               <|> anyControlSeq)+  optional sp+  optional (symbol ',')+  optional sp+  return (T.unpack key, T.unpack . untokenize $ val)++keyvals :: PandocMonad m => LP m [(String, String)]+keyvals = try $ symbol '[' >> manyTill keyval (symbol ']')++accent :: PandocMonad m => Char -> (Char -> String) -> LP m Inlines+accent c f = try $ do+  ils <- tok+  case toList ils of+       (Str (x:xs) : ys) -> return $ fromList (Str (f x ++ xs) : ys)+       [Space]           -> return $ str [c]+       []                -> return $ str [c]+       _                 -> return ils++grave :: Char -> String+grave 'A' = "À"+grave 'E' = "È"+grave 'I' = "Ì"+grave 'O' = "Ò"+grave 'U' = "Ù"+grave 'a' = "à"+grave 'e' = "è"+grave 'i' = "ì"+grave 'o' = "ò"+grave 'u' = "ù"+grave c   = [c]++acute :: Char -> String+acute 'A' = "Á"+acute 'E' = "É"+acute 'I' = "Í"+acute 'O' = "Ó"+acute 'U' = "Ú"+acute 'Y' = "Ý"+acute 'a' = "á"+acute 'e' = "é"+acute 'i' = "í"+acute 'o' = "ó"+acute 'u' = "ú"+acute 'y' = "ý"+acute 'C' = "Ć"+acute 'c' = "ć"+acute 'L' = "Ĺ"+acute 'l' = "ĺ"+acute 'N' = "Ń"+acute 'n' = "ń"+acute 'R' = "Ŕ"+acute 'r' = "ŕ"+acute 'S' = "Ś"+acute 's' = "ś"+acute 'Z' = "Ź"+acute 'z' = "ź"+acute c   = [c]++circ :: Char -> String+circ 'A' = "Â"+circ 'E' = "Ê"+circ 'I' = "Î"+circ 'O' = "Ô"+circ 'U' = "Û"+circ 'a' = "â"+circ 'e' = "ê"+circ 'i' = "î"+circ 'o' = "ô"+circ 'u' = "û"+circ 'C' = "Ĉ"+circ 'c' = "ĉ"+circ 'G' = "Ĝ"+circ 'g' = "ĝ"+circ 'H' = "Ĥ"+circ 'h' = "ĥ"+circ 'J' = "Ĵ"+circ 'j' = "ĵ"+circ 'S' = "Ŝ"+circ 's' = "ŝ"+circ 'W' = "Ŵ"+circ 'w' = "ŵ"+circ 'Y' = "Ŷ"+circ 'y' = "ŷ"+circ c   = [c]++tilde :: Char -> String+tilde 'A' = "Ã"+tilde 'a' = "ã"+tilde 'O' = "Õ"+tilde 'o' = "õ"+tilde 'I' = "Ĩ"+tilde 'i' = "ĩ"+tilde 'U' = "Ũ"+tilde 'u' = "ũ"+tilde 'N' = "Ñ"+tilde 'n' = "ñ"+tilde c   = [c]++umlaut :: Char -> String+umlaut 'A' = "Ä"+umlaut 'E' = "Ë"+umlaut 'I' = "Ï"+umlaut 'O' = "Ö"+umlaut 'U' = "Ü"+umlaut 'a' = "ä"+umlaut 'e' = "ë"+umlaut 'i' = "ï"+umlaut 'o' = "ö"+umlaut 'u' = "ü"+umlaut c   = [c]++hungarumlaut :: Char -> String+hungarumlaut 'A' = "A̋"+hungarumlaut 'E' = "E̋"+hungarumlaut 'I' = "I̋"+hungarumlaut 'O' = "Ő"+hungarumlaut 'U' = "Ű"+hungarumlaut 'Y' = "ӳ"+hungarumlaut 'a' = "a̋"+hungarumlaut 'e' = "e̋"+hungarumlaut 'i' = "i̋"+hungarumlaut 'o' = "ő"+hungarumlaut 'u' = "ű"+hungarumlaut 'y' = "ӳ"+hungarumlaut c   = [c]++dot :: Char -> String+dot 'C' = "Ċ"+dot 'c' = "ċ"+dot 'E' = "Ė"+dot 'e' = "ė"+dot 'G' = "Ġ"+dot 'g' = "ġ"+dot 'I' = "İ"+dot 'Z' = "Ż"+dot 'z' = "ż"+dot c   = [c]++macron :: Char -> String+macron 'A' = "Ā"+macron 'E' = "Ē"+macron 'I' = "Ī"+macron 'O' = "Ō"+macron 'U' = "Ū"+macron 'a' = "ā"+macron 'e' = "ē"+macron 'i' = "ī"+macron 'o' = "ō"+macron 'u' = "ū"+macron c   = [c]++cedilla :: Char -> String+cedilla 'c' = "ç"+cedilla 'C' = "Ç"+cedilla 's' = "ş"+cedilla 'S' = "Ş"+cedilla 't' = "ţ"+cedilla 'T' = "Ţ"+cedilla 'e' = "ȩ"+cedilla 'E' = "Ȩ"+cedilla 'h' = "ḩ"+cedilla 'H' = "Ḩ"+cedilla 'o' = "o̧"+cedilla 'O' = "O̧"+cedilla c   = [c]++hacek :: Char -> String+hacek 'A' = "Ǎ"+hacek 'a' = "ǎ"+hacek 'C' = "Č"+hacek 'c' = "č"+hacek 'D' = "Ď"+hacek 'd' = "ď"+hacek 'E' = "Ě"+hacek 'e' = "ě"+hacek 'G' = "Ǧ"+hacek 'g' = "ǧ"+hacek 'H' = "Ȟ"+hacek 'h' = "ȟ"+hacek 'I' = "Ǐ"+hacek 'i' = "ǐ"+hacek 'j' = "ǰ"+hacek 'K' = "Ǩ"+hacek 'k' = "ǩ"+hacek 'L' = "Ľ"+hacek 'l' = "ľ"+hacek 'N' = "Ň"+hacek 'n' = "ň"+hacek 'O' = "Ǒ"+hacek 'o' = "ǒ"+hacek 'R' = "Ř"+hacek 'r' = "ř"+hacek 'S' = "Š"+hacek 's' = "š"+hacek 'T' = "Ť"+hacek 't' = "ť"+hacek 'U' = "Ǔ"+hacek 'u' = "ǔ"+hacek 'Z' = "Ž"+hacek 'z' = "ž"+hacek c   = [c]++ogonek :: Char -> String+ogonek 'a' = "ą"+ogonek 'e' = "ę"+ogonek 'o' = "ǫ"+ogonek 'i' = "į"+ogonek 'u' = "ų"+ogonek 'A' = "Ą"+ogonek 'E' = "Ę"+ogonek 'I' = "Į"+ogonek 'O' = "Ǫ"+ogonek 'U' = "Ų"+ogonek c   = [c]++breve :: Char -> String+breve 'A' = "Ă"+breve 'a' = "ă"+breve 'E' = "Ĕ"+breve 'e' = "ĕ"+breve 'G' = "Ğ"+breve 'g' = "ğ"+breve 'I' = "Ĭ"+breve 'i' = "ĭ"+breve 'O' = "Ŏ"+breve 'o' = "ŏ"+breve 'U' = "Ŭ"+breve 'u' = "ŭ"+breve c   = [c]++toksToString :: [Tok] -> String+toksToString = T.unpack . untokenize++mathDisplay :: String -> Inlines+mathDisplay = displayMath . trim++mathInline :: String -> Inlines+mathInline = math . trim++dollarsMath :: PandocMonad m => LP m Inlines+dollarsMath = do+  symbol '$'+  display <- option False (True <$ symbol '$')+  contents <- trim . toksToString <$>+               many (notFollowedBy (symbol '$') >> anyTok)+  if display+     then+       mathDisplay contents <$ try (symbol '$' >> symbol '$')+   <|> (guard (null contents) >> return (mathInline ""))+     else mathInline contents <$ symbol '$'++-- citations++addPrefix :: [Inline] -> [Citation] -> [Citation]+addPrefix p (k:ks) = k {citationPrefix = p ++ citationPrefix k} : ks+addPrefix _ _      = []++addSuffix :: [Inline] -> [Citation] -> [Citation]+addSuffix s ks@(_:_) =+  let k = last ks+  in  init ks ++ [k {citationSuffix = citationSuffix k ++ s}]+addSuffix _ _ = []++simpleCiteArgs :: PandocMonad m => LP m [Citation]+simpleCiteArgs = try $ do+  first  <- optionMaybe $ toList <$> opt+  second <- optionMaybe $ toList <$> opt+  keys <- try $ bgroup *> manyTill citationLabel egroup+  let (pre, suf) = case (first  , second ) of+        (Just s , Nothing) -> (mempty, s )+        (Just s , Just t ) -> (s , t )+        _                  -> (mempty, mempty)+      conv k = Citation { citationId      = k+                        , citationPrefix  = []+                        , citationSuffix  = []+                        , citationMode    = NormalCitation+                        , citationHash    = 0+                        , citationNoteNum = 0+                        }+  return $ addPrefix pre $ addSuffix suf $ map conv keys++citationLabel :: PandocMonad m => LP m String+citationLabel  = do+  optional sp+  toksToString <$>+    (many1 (satisfyTok isWordTok <|> symbolIn bibtexKeyChar)+          <* optional sp+          <* optional (symbol ',')+          <* optional sp)+  where bibtexKeyChar = ".:;?!`'()/*@_+=-[]" :: [Char]++cites :: PandocMonad m => CitationMode -> Bool -> LP m [Citation]+cites mode multi = try $ do+  cits <- if multi+             then many1 simpleCiteArgs+             else count 1 simpleCiteArgs+  let cs = concat cits+  return $ case mode of+        AuthorInText -> case cs of+                             (c:rest) -> c {citationMode = mode} : rest+                             []       -> []+        _            -> map (\a -> a {citationMode = mode}) cs++citation :: PandocMonad m => String -> CitationMode -> Bool -> LP m Inlines+citation name mode multi = do+  (c,raw) <- withRaw $ cites mode multi+  return $ cite c (rawInline "latex" $ "\\" ++ name ++ toksToString raw)++handleCitationPart :: Inlines -> [Citation]+handleCitationPart ils =+  let isCite Cite{} = True+      isCite _      = False+      (pref, rest) = break isCite (toList ils)+  in case rest of+          (Cite cs _:suff) -> addPrefix pref $ addSuffix suff cs+          _                -> []++complexNatbibCitation :: PandocMonad m => CitationMode -> LP m Inlines+complexNatbibCitation mode = try $ do+  (cs, raw) <-+    withRaw $ concat <$> do+      bgroup+      items <- mconcat <$>+                many1 (notFollowedBy (symbol ';') >> inline)+                  `sepBy1` (symbol ';')+      egroup+      return $ map handleCitationPart items+  case cs of+       []       -> mzero+       (c:cits) -> return $ cite (c{ citationMode = mode }:cits)+                      (rawInline "latex" $ "\\citetext" ++ toksToString raw)++inNote :: Inlines -> Inlines+inNote ils =+  note $ para $ ils <> str "."++inlineCommand' :: PandocMonad m => LP m Inlines+inlineCommand' = try $ do+  Tok _ (CtrlSeq name) cmd <- anyControlSeq+  guard $ name /= "begin" && name /= "end"+  star <- option "" ("*" <$ symbol '*' <* optional sp)+  let name' = name <> star+  let names = ordNub [name', name] -- check non-starred as fallback+  let raw = do+       guard $ isInlineCommand name || not (isBlockCommand name)+       rawcommand <- getRawCommand name (cmd <> star)+       (guardEnabled Ext_raw_tex >> return (rawInline "latex" rawcommand))+         <|> ignore rawcommand+  lookupListDefault raw names inlineCommands++tok :: PandocMonad m => LP m Inlines+tok = grouped inline <|> inlineCommand' <|> singleChar'+  where singleChar' = do+          Tok _ _ t <- singleChar+          return (str (T.unpack t))++singleChar :: PandocMonad m => LP m Tok+singleChar = try $ do+  Tok pos toktype t <- satisfyTok (tokTypeIn [Word, Symbol])+  guard $ not $ toktype == Symbol &&+                T.any (`Set.member` specialChars) t+  if T.length t > 1+     then do+       let (t1, t2) = (T.take 1 t, T.drop 1 t)+       inp <- getInput+       setInput $ Tok (incSourceColumn pos 1) toktype t2 : inp+       return $ Tok pos toktype t1+     else return $ Tok pos toktype t++opt :: PandocMonad m => LP m Inlines+opt = bracketed inline++rawopt :: PandocMonad m => LP m Text+rawopt = do+  inner <- untokenize <$> bracketedToks+  optional sp+  return $ "[" <> inner <> "]"++skipopts :: PandocMonad m => LP m ()+skipopts = skipMany rawopt++-- opts in angle brackets are used in beamer+rawangle :: PandocMonad m => LP m ()+rawangle = try $ do+  symbol '<'+  () <$ manyTill anyTok (symbol '>')++skipangles :: PandocMonad m => LP m ()+skipangles = skipMany rawangle++ignore :: (Monoid a, PandocMonad m) => String -> ParserT s u m a+ignore raw = do+  pos <- getPosition+  report $ SkippedContent raw pos+  return mempty++withRaw :: PandocMonad m => LP m a -> LP m (a, [Tok])+withRaw parser = do+  inp <- getInput+  result <- parser+  nxt <- option (Tok (initialPos "source") Word "") (lookAhead anyTok)+  let raw = takeWhile (/= nxt) inp+  return (result, raw)++inBrackets :: Inlines -> Inlines+inBrackets x = str "[" <> x <> str "]"++unescapeURL :: String -> String+unescapeURL ('\\':x:xs) | isEscapable x = x:unescapeURL xs+  where isEscapable c = c `elem` ("#$%&~_^\\{}" :: String)+unescapeURL (x:xs) = x:unescapeURL xs+unescapeURL [] = ""++mathEnvWith :: PandocMonad m+            => (Inlines -> a) -> Maybe Text -> Text -> LP m a+mathEnvWith f innerEnv name = f . mathDisplay . inner <$> mathEnv name+   where inner x = case innerEnv of+                        Nothing -> x+                        Just y  -> "\\begin{" ++ T.unpack y ++ "}\n" ++ x +++                                   "\\end{" ++ T.unpack y ++ "}"++mathEnv :: PandocMonad m => Text -> LP m String+mathEnv name = do+  skipopts+  optional blankline+  res <- manyTill anyTok (end_ name)+  return $ stripTrailingNewlines $ T.unpack $ untokenize res++inlineEnvironment :: PandocMonad m => LP m Inlines+inlineEnvironment = try $ do+  controlSeq "begin"+  name <- untokenize <$> braced+  M.findWithDefault mzero name inlineEnvironments++inlineEnvironments :: PandocMonad m => M.Map Text (LP m Inlines)+inlineEnvironments = M.fromList [+    ("displaymath", mathEnvWith id Nothing "displaymath")+  , ("math", math <$> mathEnv "math")+  , ("equation", mathEnvWith id Nothing "equation")+  , ("equation*", mathEnvWith id Nothing "equation*")+  , ("gather", mathEnvWith id (Just "gathered") "gather")+  , ("gather*", mathEnvWith id (Just "gathered") "gather*")+  , ("multline", mathEnvWith id (Just "gathered") "multline")+  , ("multline*", mathEnvWith id (Just "gathered") "multline*")+  , ("eqnarray", mathEnvWith id (Just "aligned") "eqnarray")+  , ("eqnarray*", mathEnvWith id (Just "aligned") "eqnarray*")+  , ("align", mathEnvWith id (Just "aligned") "align")+  , ("align*", mathEnvWith id (Just "aligned") "align*")+  , ("alignat", mathEnvWith id (Just "aligned") "alignat")+  , ("alignat*", mathEnvWith id (Just "aligned") "alignat*")+  ]++inlineCommands :: PandocMonad m => M.Map Text (LP m Inlines)+inlineCommands = M.union inlineLanguageCommands $ M.fromList $+  [ ("emph", extractSpaces emph <$> tok)+  , ("textit", extractSpaces emph <$> tok)+  , ("textsl", extractSpaces emph <$> tok)+  , ("textsc", extractSpaces smallcaps <$> tok)+  , ("textsf", extractSpaces (spanWith ("",["sans-serif"],[])) <$> tok)+  , ("textmd", extractSpaces (spanWith ("",["medium"],[])) <$> tok)+  , ("textrm", extractSpaces (spanWith ("",["roman"],[])) <$> tok)+  , ("textup", extractSpaces (spanWith ("",["upright"],[])) <$> tok)+  , ("texttt", ttfamily)+  , ("sout", extractSpaces strikeout <$> tok)+  , ("lq", return (str "‘"))+  , ("rq", return (str "’"))+  , ("textquoteleft", return (str "‘"))+  , ("textquoteright", return (str "’"))+  , ("textquotedblleft", return (str "“"))+  , ("textquotedblright", return (str "”"))+  , ("textsuperscript", extractSpaces superscript <$> tok)+  , ("textsubscript", extractSpaces subscript <$> tok)+  , ("textbackslash", lit "\\")+  , ("backslash", lit "\\")+  , ("slash", lit "/")+  , ("textbf", extractSpaces strong <$> tok)+  , ("textnormal", extractSpaces (spanWith ("",["nodecor"],[])) <$> tok)+  , ("ldots", lit "…")+  , ("vdots", lit "\8942")+  , ("dots", lit "…")+  , ("mdots", lit "…")+  , ("sim", lit "~")+  , ("sep", lit ",")+  , ("label", rawInlineOr "label" dolabel)+  , ("ref", rawInlineOr "ref" $ doref "ref")+  , ("cref", rawInlineOr "cref" $ doref "ref")       -- from cleveref.sty+  , ("vref", rawInlineOr "vref" $ doref "ref+page")  -- from varioref.sty+  , ("eqref", rawInlineOr "eqref" $ doref "eqref")   -- from amsmath.sty+  , ("lettrine", optional opt >> extractSpaces (spanWith ("",["lettrine"],[])) <$> tok)+  , ("(", mathInline . toksToString <$> manyTill anyTok (controlSeq ")"))+  , ("[", mathDisplay . toksToString <$> manyTill anyTok (controlSeq "]"))+  , ("ensuremath", mathInline . toksToString <$> braced)+  , ("texorpdfstring", (\_ x -> x) <$> tok <*> tok)+  , ("P", lit "¶")+  , ("S", lit "§")+  , ("$", lit "$")+  , ("%", lit "%")+  , ("&", lit "&")+  , ("#", lit "#")+  , ("_", lit "_")+  , ("{", lit "{")+  , ("}", lit "}")+  -- old TeX commands+  , ("em", extractSpaces emph <$> inlines)+  , ("it", extractSpaces emph <$> inlines)+  , ("sl", extractSpaces emph <$> inlines)+  , ("bf", extractSpaces strong <$> inlines)+  , ("rm", inlines)+  , ("itshape", extractSpaces emph <$> inlines)+  , ("slshape", extractSpaces emph <$> inlines)+  , ("scshape", extractSpaces smallcaps <$> inlines)+  , ("bfseries", extractSpaces strong <$> inlines)+  , ("/", pure mempty) -- italic correction+  , ("aa", lit "å")+  , ("AA", lit "Å")+  , ("ss", lit "ß")+  , ("o", lit "ø")+  , ("O", lit "Ø")+  , ("L", lit "Ł")+  , ("l", lit "ł")+  , ("ae", lit "æ")+  , ("AE", lit "Æ")+  , ("oe", lit "œ")+  , ("OE", lit "Œ")+  , ("pounds", lit "£")+  , ("euro", lit "€")+  , ("copyright", lit "©")+  , ("textasciicircum", lit "^")+  , ("textasciitilde", lit "~")+  , ("H", accent '\779' hungarumlaut)+  , ("`", accent '`' grave)+  , ("'", accent '\'' acute)+  , ("^", accent '^' circ)+  , ("~", accent '~' tilde)+  , ("\"", accent '\776' umlaut)+  , (".", accent '\775' dot)+  , ("=", accent '\772' macron)+  , ("c", accent '\807' cedilla)+  , ("v", accent 'ˇ' hacek)+  , ("u", accent '\774' breve)+  , ("k", accent '\808' ogonek)+  , ("textogonekcentered", accent '\808' ogonek)+  , ("i", lit "i")+  , ("\\", linebreak <$ (do inTableCell <- sInTableCell <$> getState+                            guard $ not inTableCell+                            optional opt+                            spaces))+  , (",", lit "\8198")+  , ("@", pure mempty)+  , (" ", lit "\160")+  , ("ps", pure $ str "PS." <> space)+  , ("TeX", lit "TeX")+  , ("LaTeX", lit "LaTeX")+  , ("bar", lit "|")+  , ("textless", lit "<")+  , ("textgreater", lit ">")+  , ("thanks", note <$> grouped block)+  , ("footnote", note <$> grouped block)+  , ("verb", doverb)+  , ("lstinline", dolstinline)+  , ("Verb", doverb)+  , ("url", ((unescapeURL . T.unpack . untokenize) <$> braced) >>= \url ->+                  pure (link url "" (str url)))+  , ("href", (unescapeURL . toksToString <$>+                 braced <* optional sp) >>= \url ->+                   tok >>= \lab -> pure (link url "" lab))+  , ("includegraphics", do options <- option [] keyvals+                           src <- unescapeURL . T.unpack .+                                    removeDoubleQuotes . untokenize <$> braced+                           mkImage options src)+  , ("enquote", enquote)+  , ("figurename", doTerm Translations.Figure)+  , ("prefacename", doTerm Translations.Preface)+  , ("refname", doTerm Translations.References)+  , ("bibname", doTerm Translations.Bibliography)+  , ("chaptername", doTerm Translations.Chapter)+  , ("partname", doTerm Translations.Part)+  , ("contentsname", doTerm Translations.Contents)+  , ("listfigurename", doTerm Translations.ListOfFigures)+  , ("listtablename", doTerm Translations.ListOfTables)+  , ("indexname", doTerm Translations.Index)+  , ("abstractname", doTerm Translations.Abstract)+  , ("tablename", doTerm Translations.Table)+  , ("enclname", doTerm Translations.Encl)+  , ("ccname", doTerm Translations.Cc)+  , ("headtoname", doTerm Translations.To)+  , ("pagename", doTerm Translations.Page)+  , ("seename", doTerm Translations.See)+  , ("seealsoname", doTerm Translations.SeeAlso)+  , ("proofname", doTerm Translations.Proof)+  , ("glossaryname", doTerm Translations.Glossary)+  , ("lstlistingname", doTerm Translations.Listing)+  , ("cite", citation "cite" NormalCitation False)+  , ("Cite", citation "Cite" NormalCitation False)+  , ("citep", citation "citep" NormalCitation False)+  , ("citep*", citation "citep*" NormalCitation False)+  , ("citeal", citation "citeal" NormalCitation False)+  , ("citealp", citation "citealp" NormalCitation False)+  , ("citealp*", citation "citealp*" NormalCitation False)+  , ("autocite", citation "autocite" NormalCitation False)+  , ("smartcite", citation "smartcite" NormalCitation False)+  , ("footcite", inNote <$> citation "footcite" NormalCitation False)+  , ("parencite", citation "parencite" NormalCitation False)+  , ("supercite", citation "supercite" NormalCitation False)+  , ("footcitetext", inNote <$> citation "footcitetext" NormalCitation False)+  , ("citeyearpar", citation "citeyearpar" SuppressAuthor False)+  , ("citeyear", citation "citeyear" SuppressAuthor False)+  , ("autocite*", citation "autocite*" SuppressAuthor False)+  , ("cite*", citation "cite*" SuppressAuthor False)+  , ("parencite*", citation "parencite*" SuppressAuthor False)+  , ("textcite", citation "textcite" AuthorInText False)+  , ("citet", citation "citet" AuthorInText False)+  , ("citet*", citation "citet*" AuthorInText False)+  , ("citealt", citation "citealt" AuthorInText False)+  , ("citealt*", citation "citealt*" AuthorInText False)+  , ("textcites", citation "textcites" AuthorInText True)+  , ("cites", citation "cites" NormalCitation True)+  , ("autocites", citation "autocites" NormalCitation True)+  , ("footcites", inNote <$> citation "footcites" NormalCitation True)+  , ("parencites", citation "parencites" NormalCitation True)+  , ("supercites", citation "supercites" NormalCitation True)+  , ("footcitetexts", inNote <$> citation "footcitetexts" NormalCitation True)+  , ("Autocite", citation "Autocite" NormalCitation False)+  , ("Smartcite", citation "Smartcite" NormalCitation False)+  , ("Footcite", citation "Footcite" NormalCitation False)+  , ("Parencite", citation "Parencite" NormalCitation False)+  , ("Supercite", citation "Supercite" NormalCitation False)+  , ("Footcitetext", inNote <$> citation "Footcitetext" NormalCitation False)+  , ("Citeyearpar", citation "Citeyearpar" SuppressAuthor False)+  , ("Citeyear", citation "Citeyear" SuppressAuthor False)+  , ("Autocite*", citation "Autocite*" SuppressAuthor False)+  , ("Cite*", citation "Cite*" SuppressAuthor False)+  , ("Parencite*", citation "Parencite*" SuppressAuthor False)+  , ("Textcite", citation "Textcite" AuthorInText False)+  , ("Textcites", citation "Textcites" AuthorInText True)+  , ("Cites", citation "Cites" NormalCitation True)+  , ("Autocites", citation "Autocites" NormalCitation True)+  , ("Footcites", citation "Footcites" NormalCitation True)+  , ("Parencites", citation "Parencites" NormalCitation True)+  , ("Supercites", citation "Supercites" NormalCitation True)+  , ("Footcitetexts", inNote <$> citation "Footcitetexts" NormalCitation True)+  , ("citetext", complexNatbibCitation NormalCitation)+  , ("citeauthor", (try (tok *> optional sp *> controlSeq "citetext") *>+                        complexNatbibCitation AuthorInText)+                   <|> citation "citeauthor" AuthorInText False)+  , ("nocite", mempty <$ (citation "nocite" NormalCitation False >>=+                          addMeta "nocite"))+  , ("hyperlink", hyperlink)+  , ("hypertarget", hypertargetInline)+  -- glossaries package+  , ("gls", doAcronym "short")+  , ("Gls", doAcronym "short")+  , ("glsdesc", doAcronym "long")+  , ("Glsdesc", doAcronym "long")+  , ("GLSdesc", doAcronym "long")+  , ("acrlong", doAcronym "long")+  , ("Acrlong", doAcronym "long")+  , ("acrfull", doAcronym "full")+  , ("Acrfull", doAcronym "full")+  , ("acrshort", doAcronym "abbrv")+  , ("Acrshort", doAcronym "abbrv")+  , ("glspl", doAcronymPlural "short")+  , ("Glspl", doAcronymPlural "short")+  , ("glsdescplural", doAcronymPlural "long")+  , ("Glsdescplural", doAcronymPlural "long")+  , ("GLSdescplural", doAcronymPlural "long")+  -- acronyms package+  , ("ac", doAcronym "short")+  , ("acf", doAcronym "full")+  , ("acs", doAcronym "abbrv")+  , ("acp", doAcronymPlural "short")+  , ("acfp", doAcronymPlural "full")+  , ("acsp", doAcronymPlural "abbrv")+  -- siuntix+  , ("SI", dosiunitx)+  -- hyphenat+  , ("bshyp", lit "\\\173")+  , ("fshyp", lit "/\173")+  , ("dothyp", lit ".\173")+  , ("colonhyp", lit ":\173")+  , ("hyp", lit "-")+  , ("nohyphens", tok)+  , ("textnhtt", ttfamily)+  , ("nhttfamily", ttfamily)+  -- LaTeX colors+  , ("textcolor", coloredInline "color")+  , ("colorbox", coloredInline "background-color")+  -- fontawesome+  , ("faCheck", lit "\10003")+  , ("faClose", lit "\10007")+  -- xspace+  , ("xspace", doxspace)+  -- etoolbox+  , ("ifstrequal", ifstrequal)+  , ("newtoggle", braced >>= newToggle)+  , ("toggletrue", braced >>= setToggle True)+  , ("togglefalse", braced >>= setToggle False)+  , ("iftoggle", try $ ifToggle >> inline)+  -- biblatex misc+  , ("RN", romanNumeralUpper)+  , ("Rn", romanNumeralLower)+  ]++inlineLanguageCommands :: PandocMonad m => M.Map Text (LP m Inlines)+inlineLanguageCommands = M.fromList $ mk <$> M.toList polyglossiaLangToBCP47+  where+    mk (polyglossia, bcp47Func) =+      ("text" <> T.pack polyglossia, inlineLanguage bcp47Func)++inlineLanguage :: PandocMonad m => (String -> Lang) -> LP m Inlines+inlineLanguage bcp47Func = do+  o <- option "" $ (T.unpack . T.filter (\c -> c /= '[' && c /= ']'))+                <$> rawopt+  let lang = renderLang $ bcp47Func o+  extractSpaces (spanWith ("", [], [("lang", lang)])) <$> tok++hyperlink :: PandocMonad m => LP m Inlines+hyperlink = try $ do+  src <- toksToString <$> braced+  lab <- tok+  return $ link ('#':src) "" lab++hypertargetBlock :: PandocMonad m => LP m Blocks+hypertargetBlock = try $ do+  ref <- toksToString <$> braced+  bs <- grouped block+  case toList bs of+       [Header 1 (ident,_,_) _] | ident == ref -> return bs+       _                        -> return $ divWith (ref, [], []) bs++hypertargetInline :: PandocMonad m => LP m Inlines+hypertargetInline = try $ do+  ref <- toksToString <$> braced+  ils <- grouped inline+  return $ spanWith (ref, [], []) ils++romanNumeralUpper :: (PandocMonad m) => LP m Inlines+romanNumeralUpper =+  str . toRomanNumeral <$> romanNumeralArg++romanNumeralLower :: (PandocMonad m) => LP m Inlines+romanNumeralLower =+  str . map toLower . toRomanNumeral <$> romanNumeralArg++romanNumeralArg :: (PandocMonad m) => LP m Int+romanNumeralArg = spaces *> (parser <|> inBraces)+  where+    inBraces = do+      symbol '{'+      spaces+      res <- parser+      spaces+      symbol '}'+      return res+    parser = do+      Tok _ Word s <- satisfyTok isWordTok+      let (digits, rest) = T.span isDigit s+      unless (T.null rest) $+        fail "Non-digits in argument to \\Rn or \\RN"+      safeRead $ T.unpack digits++newToggle :: (Monoid a, PandocMonad m) => [Tok] -> LP m a+newToggle name = do+  updateState $ \st ->+    st{ sToggles = M.insert (toksToString name) False (sToggles st) }+  return mempty++setToggle :: (Monoid a, PandocMonad m) => Bool -> [Tok] -> LP m a+setToggle on name = do+  updateState $ \st ->+    st{ sToggles = M.adjust (const on) (toksToString name) (sToggles st) }+  return mempty++ifToggle :: PandocMonad m => LP m ()+ifToggle = do+  name <- braced+  spaces+  yes <- braced+  spaces+  no <- braced+  toggles <- sToggles <$> getState+  inp <- getInput+  let name' = toksToString name+  case M.lookup name' toggles of+                Just True  -> setInput (yes ++ inp)+                Just False -> setInput (no  ++ inp)+                Nothing    -> do+                  pos <- getPosition+                  report $ UndefinedToggle name' pos+  return ()++doTerm :: PandocMonad m => Translations.Term -> LP m Inlines+doTerm term = str <$> translateTerm term++ifstrequal :: (PandocMonad m, Monoid a) => LP m a+ifstrequal = do+  str1 <- tok+  str2 <- tok+  ifequal <- braced+  ifnotequal <- braced+  if str1 == str2+     then getInput >>= setInput . (ifequal ++)+     else getInput >>= setInput . (ifnotequal ++)+  return mempty++coloredInline :: PandocMonad m => String -> LP m Inlines+coloredInline stylename = do+  skipopts+  color <- braced+  spanWith ("",[],[("style",stylename ++ ": " ++ toksToString color)]) <$> tok++ttfamily :: PandocMonad m => LP m Inlines+ttfamily = (code . stringify . toList) <$> tok++rawInlineOr :: PandocMonad m => Text -> LP m Inlines -> LP m Inlines+rawInlineOr name' fallback = do+  parseRaw <- extensionEnabled Ext_raw_tex <$> getOption readerExtensions+  if parseRaw+     then rawInline "latex" <$> getRawCommand name' ("\\" <> name')+     else fallback++getRawCommand :: PandocMonad m => Text -> Text -> LP m String+getRawCommand name txt = do+  (_, rawargs) <- withRaw $+      case name of+           "write" -> do+             void $ satisfyTok isWordTok -- digits+             void braced+           "titleformat" -> do+             void braced+             skipopts+             void $ count 4 braced+           "def" ->+             void $ manyTill anyTok braced+           _ -> do+             skipangles+             skipopts+             option "" (try (optional sp *> dimenarg))+             void $ many braced+  return $ T.unpack (txt <> untokenize rawargs)++isBlockCommand :: Text -> Bool+isBlockCommand s =+  s `M.member` (blockCommands :: M.Map Text (LP PandocPure Blocks))+  || s `Set.member` treatAsBlock++treatAsBlock :: Set.Set Text+treatAsBlock = Set.fromList+   [ "let", "def", "DeclareRobustCommand"+   , "newcommand", "renewcommand"+   , "newenvironment", "renewenvironment"+   , "providecommand", "provideenvironment"+     -- newcommand, etc. should be parsed by macroDef, but we need this+     -- here so these aren't parsed as inline commands to ignore+   , "special", "pdfannot", "pdfstringdef"+   , "bibliographystyle"+   , "maketitle", "makeindex", "makeglossary"+   , "addcontentsline", "addtocontents", "addtocounter"+      -- \ignore{} is used conventionally in literate haskell for definitions+      -- that are to be processed by the compiler but not printed.+   , "ignore"+   , "hyperdef"+   , "markboth", "markright", "markleft"+   , "hspace", "vspace"+   , "newpage"+   , "clearpage"+   , "pagebreak"+   , "titleformat"+   ]++isInlineCommand :: Text -> Bool+isInlineCommand s =+  s `M.member` (inlineCommands :: M.Map Text (LP PandocPure Inlines))+  || s `Set.member` treatAsInline++treatAsInline :: Set.Set Text+treatAsInline = Set.fromList+  [ "index"+  , "hspace"+  , "vspace"+  , "noindent"+  , "newpage"+  , "clearpage"+  , "pagebreak"+  ]++dolabel :: PandocMonad m => LP m Inlines+dolabel = do+  v <- braced+  let refstr = toksToString v+  return $ spanWith (refstr,[],[("label", refstr)])+    $ inBrackets $ str $ toksToString v++doref :: PandocMonad m => String -> LP m Inlines+doref cls = do+  v <- braced+  let refstr = toksToString v+  return $ linkWith ("",[],[ ("reference-type", cls)+                           , ("reference", refstr)])+                    ('#':refstr)+                    ""+                    (inBrackets $ str refstr)++lookupListDefault :: (Show k, Ord k) => v -> [k] -> M.Map k v -> v+lookupListDefault d = (fromMaybe d .) . lookupList+  where lookupList l m = msum $ map (`M.lookup` m) l++inline :: PandocMonad m => LP m Inlines+inline = (mempty <$ comment)+     <|> (space  <$ whitespace)+     <|> (softbreak <$ endline)+     <|> word+     <|> inlineCommand'+     <|> inlineEnvironment+     <|> inlineGroup+     <|> (symbol '-' *>+           option (str "-") (symbol '-' *>+             option (str "–") (str "—" <$ symbol '-')))+     <|> doubleQuote+     <|> singleQuote+     <|> (str "”" <$ try (symbol '\'' >> symbol '\''))+     <|> (str "”" <$ symbol '”')+     <|> (str "’" <$ symbol '\'')+     <|> (str "’" <$ symbol '’')+     <|> (str "\160" <$ symbol '~')+     <|> dollarsMath+     <|> (guardEnabled Ext_literate_haskell *> symbol '|' *> doLHSverb)+     <|> (str . (:[]) <$> primEscape)+     <|> regularSymbol+     <|> (do res <- symbolIn "#^'`\"[]"+             pos <- getPosition+             let s = T.unpack (untoken res)+             report $ ParsingUnescaped s pos+             return $ str s)++inlines :: PandocMonad m => LP m Inlines+inlines = mconcat <$> many inline++-- block elements:++begin_ :: PandocMonad m => Text -> LP m ()+begin_ t = try (do+  controlSeq "begin"+  spaces+  txt <- untokenize <$> braced+  guard (t == txt)) <?> ("\\begin{" ++ T.unpack t ++ "}")++end_ :: PandocMonad m => Text -> LP m ()+end_ t = try (do+  controlSeq "end"+  spaces+  txt <- untokenize <$> braced+  guard $ t == txt) <?> ("\\end{" ++ T.unpack t ++ "}")++preamble :: PandocMonad m => LP m Blocks+preamble = mempty <$ many preambleBlock+  where preambleBlock =  spaces1+                     <|> void include+                     <|> void macroDef+                     <|> void blockCommand+                     <|> void braced+                     <|> (notFollowedBy (begin_ "document") >> void anyTok)++paragraph :: PandocMonad m => LP m Blocks+paragraph = do+  x <- trimInlines . mconcat <$> many1 inline+  if x == mempty+     then return mempty+     else return $ para x++include :: PandocMonad m => LP m Blocks+include = do+  (Tok _ (CtrlSeq name) _) <-+                    controlSeq "include" <|> controlSeq "input" <|>+                    controlSeq "subfile" <|> controlSeq "usepackage"+  skipMany opt+  fs <- (map (T.unpack . removeDoubleQuotes . T.strip) . T.splitOn "," .+         untokenize) <$> braced+  let fs' = if name == "usepackage"+               then map (maybeAddExtension ".sty") fs+               else map (maybeAddExtension ".tex") fs+  dirs <- (splitBy (==':') . fromMaybe ".") <$> lookupEnv "TEXINPUTS"+  mapM_ (insertIncluded dirs) fs'+  return mempty++insertIncluded :: PandocMonad m+               => [FilePath]+               -> FilePath+               -> LP m ()+insertIncluded dirs f = do+  pos <- getPosition+  containers <- getIncludeFiles <$> getState+  when (f `elem` containers) $+    throwError $ PandocParseError $ "Include file loop at " ++ show pos+  updateState $ addIncludeFile f+  mbcontents <- readFileFromDirs dirs f+  contents <- case mbcontents of+                   Just s -> return s+                   Nothing -> do+                     report $ CouldNotLoadIncludeFile f pos+                     return ""+  getInput >>= setInput . (tokenize f (T.pack contents) ++)+  updateState dropLatestIncludeFile++maybeAddExtension :: String -> FilePath -> FilePath+maybeAddExtension ext fp =+  if null (takeExtension fp)+     then addExtension fp ext+     else fp++addMeta :: PandocMonad m => ToMetaValue a => String -> a -> LP m ()+addMeta field val = updateState $ \st ->+   st{ sMeta = addMetaField field val $ sMeta st }++authors :: PandocMonad m => LP m ()+authors = try $ do+  bgroup+  let oneAuthor = mconcat <$>+       many1 (notFollowedBy' (controlSeq "and") >>+               (inline <|> mempty <$ blockCommand))+               -- skip e.g. \vspace{10pt}+  auths <- sepBy oneAuthor (controlSeq "and")+  egroup+  addMeta "author" (map trimInlines auths)++macroDef :: PandocMonad m => LP m Blocks+macroDef =+  mempty <$ ((commandDef <|> environmentDef) <* doMacros 0)+  where commandDef = do+          (name, macro') <- newcommand <|> letmacro <|> defmacro+          guardDisabled Ext_latex_macros <|>+           updateState (\s -> s{ sMacros = M.insert name macro' (sMacros s) })+        environmentDef = do+          (name, macro1, macro2) <- newenvironment+          guardDisabled Ext_latex_macros <|>+            do updateState $ \s -> s{ sMacros =+                M.insert name macro1 (sMacros s) }+               updateState $ \s -> s{ sMacros =+                M.insert ("end" <> name) macro2 (sMacros s) }+        -- @\newenvironment{envname}[n-args][default]{begin}{end}@+        -- is equivalent to+        -- @\newcommand{\envname}[n-args][default]{begin}@+        -- @\newcommand{\endenvname}@++letmacro :: PandocMonad m => LP m (Text, Macro)+letmacro = do+  controlSeq "let"+  Tok _ (CtrlSeq name) _ <- anyControlSeq+  optional $ symbol '='+  spaces+  contents <- braced <|> ((:[]) <$> (anyControlSeq <|> singleChar))+  return (name, Macro ExpandWhenDefined 0 Nothing contents)++defmacro :: PandocMonad m => LP m (Text, Macro)+defmacro = try $ do+  controlSeq "def"+  Tok _ (CtrlSeq name) _ <- anyControlSeq+  numargs <- option 0 $ argSeq 1+  contents <- withVerbatimMode braced+  return (name, Macro ExpandWhenUsed numargs Nothing contents)++-- Note: we don't yet support fancy things like #1.#2+argSeq :: PandocMonad m => Int -> LP m Int+argSeq n = do+  Tok _ (Arg i) _ <- satisfyTok isArgTok+  guard $ i == n+  argSeq (n+1) <|> return n++isArgTok :: Tok -> Bool+isArgTok (Tok _ (Arg _) _) = True+isArgTok _                 = False++newcommand :: PandocMonad m => LP m (Text, Macro)+newcommand = do+  pos <- getPosition+  Tok _ (CtrlSeq mtype) _ <- controlSeq "newcommand" <|>+                             controlSeq "renewcommand" <|>+                             controlSeq "providecommand" <|>+                             controlSeq "DeclareRobustCommand"+  optional $ symbol '*'+  Tok _ (CtrlSeq name) txt <- withVerbatimMode $ anyControlSeq <|>+    (symbol '{' *> spaces *> anyControlSeq <* spaces <* symbol '}')+  spaces+  numargs <- option 0 $ try bracketedNum+  spaces+  optarg <- option Nothing $ Just <$> try bracketedToks+  spaces+  contents <- withVerbatimMode braced+  -- we use withVerbatimMode, because macros are to be expanded+  -- at point of use, not point of definition+  when (mtype == "newcommand") $ do+    macros <- sMacros <$> getState+    case M.lookup name macros of+         Just _  -> report $ MacroAlreadyDefined (T.unpack txt) pos+         Nothing -> return ()+  return (name, Macro ExpandWhenUsed numargs optarg contents)++newenvironment :: PandocMonad m => LP m (Text, Macro, Macro)+newenvironment = do+  pos <- getPosition+  Tok _ (CtrlSeq mtype) _ <- controlSeq "newenvironment" <|>+                             controlSeq "renewenvironment" <|>+                             controlSeq "provideenvironment"+  optional $ symbol '*'+  spaces+  name <- untokenize <$> braced+  spaces+  numargs <- option 0 $ try bracketedNum+  spaces+  optarg <- option Nothing $ Just <$> try bracketedToks+  spaces+  startcontents <- withVerbatimMode braced+  spaces+  endcontents <- withVerbatimMode braced+  when (mtype == "newenvironment") $ do+    macros <- sMacros <$> getState+    case M.lookup name macros of+         Just _  -> report $ MacroAlreadyDefined (T.unpack name) pos+         Nothing -> return ()+  return (name, Macro ExpandWhenUsed numargs optarg startcontents,+             Macro ExpandWhenUsed 0 Nothing endcontents)++bracketedToks :: PandocMonad m => LP m [Tok]+bracketedToks = do+  symbol '['+  mconcat <$> manyTill (braced <|> (:[]) <$> anyTok) (symbol ']')++bracketedNum :: PandocMonad m => LP m Int+bracketedNum = do+  ds <- untokenize <$> bracketedToks+  case safeRead (T.unpack ds) of+       Just i -> return i+       _      -> return 0++setCaption :: PandocMonad m => LP m Blocks+setCaption = do+  ils <- tok+  mblabel <- option Nothing $+               try $ spaces >> controlSeq "label" >> (Just <$> tok)+  let ils' = case mblabel of+                  Just lab -> ils <> spanWith+                                ("",[],[("label", stringify lab)]) mempty+                  Nothing  -> ils+  updateState $ \st -> st{ sCaption = Just ils' }+  return mempty++looseItem :: PandocMonad m => LP m Blocks+looseItem = do+  inListItem <- sInListItem <$> getState+  guard $ not inListItem+  skipopts+  return mempty++resetCaption :: PandocMonad m => LP m ()+resetCaption = updateState $ \st -> st{ sCaption = Nothing }++section :: PandocMonad m => Bool -> Attr -> Int -> LP m Blocks+section starred (ident, classes, kvs) lvl = do+  skipopts+  contents <- grouped inline+  lab <- option ident $+          try (spaces >> controlSeq "label"+               >> spaces >> toksToString <$> braced)+  let classes' = if starred then "unnumbered" : classes else classes+  unless starred $ do+    hn <- sLastHeaderNum <$> getState+    let num = incrementHeaderNum lvl hn+    updateState $ \st -> st{ sLastHeaderNum = num }+    updateState $ \st -> st{ sLabels = M.insert lab+                            [Str (renderHeaderNum num)]+                            (sLabels st) }+  attr' <- registerHeader (lab, classes', kvs) contents+  return $ headerWith attr' lvl contents++blockCommand :: PandocMonad m => LP m Blocks+blockCommand = try $ do+  Tok _ (CtrlSeq name) txt <- anyControlSeq+  guard $ name /= "begin" && name /= "end"+  star <- option "" ("*" <$ symbol '*' <* optional sp)+  let name' = name <> star+  let names = ordNub [name', name]+  let rawDefiniteBlock = do+        guard $ isBlockCommand name+        rawBlock "latex" <$> getRawCommand name (txt <> star)+  -- heuristic:  if it could be either block or inline, we+  -- treat it if block if we have a sequence of block+  -- commands followed by a newline.  But we stop if we+  -- hit a \startXXX, since this might start a raw ConTeXt+  -- environment (this is important because this parser is+  -- used by the Markdown reader).+  let startCommand = try $ do+        Tok _ (CtrlSeq n) _ <- anyControlSeq+        guard $ "start" `T.isPrefixOf` n+  let rawMaybeBlock = try $ do+        guard $ not $ isInlineCommand name+        curr <- rawBlock "latex" <$> getRawCommand name (txt <> star)+        rest <- many $ notFollowedBy startCommand *> blockCommand+        lookAhead $ blankline <|> startCommand+        return $ curr <> mconcat rest+  let raw = rawDefiniteBlock <|> rawMaybeBlock+  lookupListDefault raw names blockCommands++closing :: PandocMonad m => LP m Blocks+closing = do+  contents <- tok+  st <- getState+  let extractInlines (MetaBlocks [Plain ys]) = ys+      extractInlines (MetaBlocks [Para ys ]) = ys+      extractInlines _                       = []+  let sigs = case lookupMeta "author" (sMeta st) of+                  Just (MetaList xs) ->+                    para $ trimInlines $ fromList $+                      intercalate [LineBreak] $ map extractInlines xs+                  _ -> mempty+  return $ para (trimInlines contents) <> sigs++blockCommands :: PandocMonad m => M.Map Text (LP m Blocks)+blockCommands = M.fromList $+   [ ("par", mempty <$ skipopts)+   , ("parbox",  braced >> grouped blocks)+   , ("title", mempty <$ (skipopts *>+                             (grouped inline >>= addMeta "title")+                         <|> (grouped block >>= addMeta "title")))+   , ("subtitle", mempty <$ (skipopts *> tok >>= addMeta "subtitle"))+   , ("author", mempty <$ (skipopts *> authors))+   -- -- in letter class, temp. store address & sig as title, author+   , ("address", mempty <$ (skipopts *> tok >>= addMeta "address"))+   , ("signature", mempty <$ (skipopts *> authors))+   , ("date", mempty <$ (skipopts *> tok >>= addMeta "date"))+   -- Koma-script metadata commands+   , ("dedication", mempty <$ (skipopts *> tok >>= addMeta "dedication"))+   -- sectioning+   , ("part", section False nullAttr (-1))+   , ("part*", section True nullAttr (-1))+   , ("chapter", section False nullAttr 0)+   , ("chapter*", section True ("",["unnumbered"],[]) 0)+   , ("section", section False nullAttr 1)+   , ("section*", section True ("",["unnumbered"],[]) 1)+   , ("subsection", section False nullAttr 2)+   , ("subsection*", section True ("",["unnumbered"],[]) 2)+   , ("subsubsection", section False nullAttr 3)+   , ("subsubsection*", section True ("",["unnumbered"],[]) 3)+   , ("paragraph", section False nullAttr 4)+   , ("paragraph*", section True ("",["unnumbered"],[]) 4)+   , ("subparagraph", section False nullAttr 5)+   , ("subparagraph*", section True ("",["unnumbered"],[]) 5)+   -- beamer slides+   , ("frametitle", section False nullAttr 3)+   , ("framesubtitle", section False nullAttr 4)+   -- letters+   , ("opening", (para . trimInlines) <$> (skipopts *> tok))+   , ("closing", skipopts *> closing)+   -- memoir+   , ("plainbreak", braced >> pure horizontalRule)+   , ("plainbreak*", braced >> pure horizontalRule)+   , ("fancybreak", braced >> pure horizontalRule)+   , ("fancybreak*", braced >> pure horizontalRule)+   , ("plainfancybreak", braced >> braced >> braced >> pure horizontalRule)+   , ("plainfancybreak*", braced >> braced >> braced >> pure horizontalRule)+   , ("pfbreak", pure horizontalRule)+   , ("pfbreak*", pure horizontalRule)+   --+   , ("hrule", pure horizontalRule)+   , ("strut", pure mempty)+   , ("rule", skipopts *> tok *> tok *> pure horizontalRule)+   , ("item", looseItem)+   , ("documentclass", skipopts *> braced *> preamble)+   , ("centerline", (para . trimInlines) <$> (skipopts *> tok))+   , ("caption", skipopts *> setCaption)+   , ("bibliography", mempty <$ (skipopts *> braced >>=+         addMeta "bibliography" . splitBibs . toksToString))+   , ("addbibresource", mempty <$ (skipopts *> braced >>=+         addMeta "bibliography" . splitBibs . toksToString))+   -- includes+   , ("lstinputlisting", inputListing)+   , ("graphicspath", graphicsPath)+   -- polyglossia+   , ("setdefaultlanguage", setDefaultLanguage)+   , ("setmainlanguage", setDefaultLanguage)+   -- hyperlink+   , ("hypertarget", hypertargetBlock)+   -- LaTeX colors+   , ("textcolor", coloredBlock "color")+   , ("colorbox", coloredBlock "background-color")+   ]+++environments :: PandocMonad m => M.Map Text (LP m Blocks)+environments = M.fromList+   [ ("document", env "document" blocks)+   , ("abstract", mempty <$ (env "abstract" blocks >>= addMeta "abstract"))+   , ("letter", env "letter" letterContents)+   , ("minipage", env "minipage" $+          skipopts *> spaces *> optional braced *> spaces *> blocks)+   , ("figure", env "figure" $ skipopts *> figure)+   , ("subfigure", env "subfigure" $ skipopts *> tok *> figure)+   , ("center", env "center" blocks)+   , ("longtable",  env "longtable" $+          resetCaption *> simpTable "longtable" False >>= addTableCaption)+   , ("table",  env "table" $+          resetCaption *> skipopts *> blocks >>= addTableCaption)+   , ("tabular*", env "tabular" $ simpTable "tabular*" True)+   , ("tabularx", env "tabularx" $ simpTable "tabularx" True)+   , ("tabular", env "tabular"  $ simpTable "tabular" False)+   , ("quote", blockQuote <$> env "quote" blocks)+   , ("quotation", blockQuote <$> env "quotation" blocks)+   , ("verse", blockQuote <$> env "verse" blocks)+   , ("itemize", bulletList <$> listenv "itemize" (many item))+   , ("description", definitionList <$> listenv "description" (many descItem))+   , ("enumerate", orderedList')+   , ("alltt", alltt <$> env "alltt" blocks)+   , ("code", guardEnabled Ext_literate_haskell *>+       (codeBlockWith ("",["sourceCode","literate","haskell"],[]) <$>+         verbEnv "code"))+   , ("comment", mempty <$ verbEnv "comment")+   , ("verbatim", codeBlock <$> verbEnv "verbatim")+   , ("Verbatim", fancyverbEnv "Verbatim")+   , ("BVerbatim", fancyverbEnv "BVerbatim")+   , ("lstlisting", do attr <- parseListingsOptions <$> option [] keyvals+                       codeBlockWith attr <$> verbEnv "lstlisting")+   , ("minted", minted)+   , ("obeylines", obeylines)+   , ("displaymath", mathEnvWith para Nothing "displaymath")+   , ("equation", mathEnvWith para Nothing "equation")+   , ("equation*", mathEnvWith para Nothing "equation*")+   , ("gather", mathEnvWith para (Just "gathered") "gather")+   , ("gather*", mathEnvWith para (Just "gathered") "gather*")+   , ("multline", mathEnvWith para (Just "gathered") "multline")+   , ("multline*", mathEnvWith para (Just "gathered") "multline*")+   , ("eqnarray", mathEnvWith para (Just "aligned") "eqnarray")+   , ("eqnarray*", mathEnvWith para (Just "aligned") "eqnarray*")+   , ("align", mathEnvWith para (Just "aligned") "align")+   , ("align*", mathEnvWith para (Just "aligned") "align*")+   , ("alignat", mathEnvWith para (Just "aligned") "alignat")+   , ("alignat*", mathEnvWith para (Just "aligned") "alignat*")+   , ("tikzpicture", rawVerbEnv "tikzpicture")+   -- etoolbox+   , ("ifstrequal", ifstrequal)+   , ("newtoggle", braced >>= newToggle)+   , ("toggletrue", braced >>= setToggle True)+   , ("togglefalse", braced >>= setToggle False)+   , ("iftoggle", try $ ifToggle >> block)+   ]++environment :: PandocMonad m => LP m Blocks+environment = do+  controlSeq "begin"+  name <- untokenize <$> braced+  M.findWithDefault mzero name environments+    <|> rawEnv name++env :: PandocMonad m => Text -> LP m a -> LP m a+env name p = p <* end_ name++rawEnv :: PandocMonad m => Text -> LP m Blocks+rawEnv name = do+  exts <- getOption readerExtensions+  let parseRaw = extensionEnabled Ext_raw_tex exts+  rawOptions <- mconcat <$> many rawopt+  let beginCommand = "\\begin{" <> name <> "}" <> rawOptions+  pos1 <- getPosition+  (bs, raw) <- withRaw $ env name blocks+  if parseRaw+     then return $ rawBlock "latex"+                 $ T.unpack $ beginCommand <> untokenize raw+     else do+       report $ SkippedContent (T.unpack beginCommand) pos1+       pos2 <- getPosition+       report $ SkippedContent ("\\end{" ++ T.unpack name ++ "}") pos2+       return bs++rawVerbEnv :: PandocMonad m => Text -> LP m Blocks+rawVerbEnv name = do+  pos <- getPosition+  (_, raw) <- withRaw $ verbEnv name+  let raw' = "\\begin{tikzpicture}" ++ toksToString raw+  exts <- getOption readerExtensions+  let parseRaw = extensionEnabled Ext_raw_tex exts+  if parseRaw+     then return $ rawBlock "latex" raw'+     else do+       report $ SkippedContent raw' pos+       return mempty++verbEnv :: PandocMonad m => Text -> LP m String+verbEnv name = withVerbatimMode $ do+  skipopts+  optional blankline+  res <- manyTill anyTok (end_ name)+  return $ stripTrailingNewlines $ toksToString res++fancyverbEnv :: PandocMonad m => Text -> LP m Blocks+fancyverbEnv name = do+  options <- option [] keyvals+  let kvs = [ (if k == "firstnumber"+                  then "startFrom"+                  else k, v) | (k,v) <- options ]+  let classes = [ "numberLines" |+                  lookup "numbers" options == Just "left" ]+  let attr = ("",classes,kvs)+  codeBlockWith attr <$> verbEnv name++obeylines :: PandocMonad m => LP m Blocks+obeylines =+  para . fromList . removeLeadingTrailingBreaks .+   walk softBreakToHard . toList <$> env "obeylines" inlines+  where softBreakToHard SoftBreak = LineBreak+        softBreakToHard x         = x+        removeLeadingTrailingBreaks = reverse . dropWhile isLineBreak .+                                      reverse . dropWhile isLineBreak+        isLineBreak LineBreak = True+        isLineBreak _         = False++minted :: PandocMonad m => LP m Blocks+minted = do+  options <- option [] keyvals+  lang <- toksToString <$> braced+  let kvs = [ (if k == "firstnumber"+                  then "startFrom"+                  else k, v) | (k,v) <- options ]+  let classes = [ lang | not (null lang) ] +++                [ "numberLines" |+                  lookup "linenos" options == Just "true" ]+  let attr = ("",classes,kvs)+  codeBlockWith attr <$> verbEnv "minted"++letterContents :: PandocMonad m => LP m Blocks+letterContents = do+  bs <- blocks+  st <- getState+  -- add signature (author) and address (title)+  let addr = case lookupMeta "address" (sMeta st) of+                  Just (MetaBlocks [Plain xs]) ->+                     para $ trimInlines $ fromList xs+                  _ -> mempty+  return $ addr <> bs -- sig added by \closing++figure :: PandocMonad m => LP m Blocks+figure = try $ do+  resetCaption+  blocks >>= addImageCaption++addImageCaption :: PandocMonad m => Blocks -> LP m Blocks+addImageCaption = walkM go+  where go (Image attr alt (src,tit))+            | not ("fig:" `isPrefixOf` tit) = do+          mbcapt <- sCaption <$> getState+          return $ case mbcapt of+               Just ils -> Image attr (toList ils) (src, "fig:" ++ tit)+               Nothing  -> Image attr alt (src,tit)+        go x = return x++coloredBlock :: PandocMonad m => String -> LP m Blocks+coloredBlock stylename = try $ do+  skipopts+  color <- braced+  notFollowedBy (grouped inline)+  let constructor = divWith ("",[],[("style",stylename ++ ": " ++ toksToString color)])+  constructor <$> grouped block++graphicsPath :: PandocMonad m => LP m Blocks+graphicsPath = do+  ps <- map toksToString <$> (bgroup *> manyTill braced egroup)+  getResourcePath >>= setResourcePath . (++ ps)+  return mempty++splitBibs :: String -> [Inlines]+splitBibs = map (str . flip replaceExtension "bib" . trim) . splitBy (==',')++alltt :: Blocks -> Blocks+alltt = walk strToCode+  where strToCode (Str s)   = Code nullAttr s+        strToCode Space     = RawInline (Format "latex") "\\ "+        strToCode SoftBreak = LineBreak+        strToCode x         = x++parseListingsOptions :: [(String, String)] -> Attr+parseListingsOptions options =+  let kvs = [ (if k == "firstnumber"+                  then "startFrom"+                  else k, v) | (k,v) <- options ]+      classes = [ "numberLines" |+                  lookup "numbers" options == Just "left" ]+             ++ maybeToList (lookup "language" options+                     >>= fromListingsLanguage)+  in  (fromMaybe "" (lookup "label" options), classes, kvs)++inputListing :: PandocMonad m => LP m Blocks+inputListing = do+  pos <- getPosition+  options <- option [] keyvals+  f <- filter (/='"') . toksToString <$> braced+  dirs <- (splitBy (==':') . fromMaybe ".") <$> lookupEnv "TEXINPUTS"+  mbCode <- readFileFromDirs dirs f+  codeLines <- case mbCode of+                      Just s -> return $ lines s+                      Nothing -> do+                        report $ CouldNotLoadIncludeFile f pos+                        return []+  let (ident,classes,kvs) = parseListingsOptions options+  let language = case lookup "language" options >>= fromListingsLanguage of+                      Just l -> [l]+                      Nothing -> take 1 $ languagesByExtension (takeExtension f)+  let firstline = fromMaybe 1 $ lookup "firstline" options >>= safeRead+  let lastline = fromMaybe (length codeLines) $+                       lookup "lastline" options >>= safeRead+  let codeContents = intercalate "\n" $ take (1 + lastline - firstline) $+                       drop (firstline - 1) codeLines+  return $ codeBlockWith (ident,ordNub (classes ++ language),kvs) codeContents++-- lists++item :: PandocMonad m => LP m Blocks+item = void blocks *> controlSeq "item" *> skipopts *> blocks++descItem :: PandocMonad m => LP m (Inlines, [Blocks])+descItem = do+  blocks -- skip blocks before item+  controlSeq "item"+  optional sp+  ils <- opt+  bs <- blocks+  return (ils, [bs])++listenv :: PandocMonad m => Text -> LP m a -> LP m a+listenv name p = try $ do+  oldInListItem <- sInListItem `fmap` getState+  updateState $ \st -> st{ sInListItem = True }+  res <- env name p+  updateState $ \st -> st{ sInListItem = oldInListItem }+  return res++orderedList' :: PandocMonad m => LP m Blocks+orderedList' = try $ do+  spaces+  let markerSpec = do+        symbol '['+        ts <- toksToString <$> manyTill anyTok (symbol ']')+        case runParser anyOrderedListMarker def "option" ts of+             Right r -> return r+             Left _  -> do+               pos <- getPosition+               report $ SkippedContent ("[" ++ ts ++ "]") pos+               return (1, DefaultStyle, DefaultDelim)+  (_, style, delim) <- option (1, DefaultStyle, DefaultDelim) markerSpec+  spaces+  optional $ try $ controlSeq "setlength"+                   *> grouped (count 1 $ controlSeq "itemindent")+                   *> braced+  spaces+  start <- option 1 $ try $ do pos <- getPosition+                               controlSeq "setcounter"+                               ctr <- toksToString <$> braced+                               guard $ "enum" `isPrefixOf` ctr+                               guard $ all (`elem` ['i','v']) (drop 4 ctr)+                               optional sp+                               num <- toksToString <$> braced+                               case safeRead num of+                                    Just i -> return (i + 1 :: Int)+                                    Nothing -> do+                                      report $ SkippedContent+                                        ("\\setcounter{" ++ ctr +++                                         "}{" ++ num ++ "}") pos+                                      return 1+  bs <- listenv "enumerate" (many item)+  return $ orderedListWith (start, style, delim) bs++-- tables++hline :: PandocMonad m => LP m ()+hline = try $ do+  spaces+  controlSeq "hline" <|>+    -- booktabs rules:+    controlSeq "toprule" <|>+    controlSeq "bottomrule" <|>+    controlSeq "midrule" <|>+    controlSeq "endhead" <|>+    controlSeq "endfirsthead"+  spaces+  optional opt+  return ()++lbreak :: PandocMonad m => LP m Tok+lbreak = (controlSeq "\\" <|> controlSeq "tabularnewline") <* spaces++amp :: PandocMonad m => LP m Tok+amp = symbol '&'++-- Split a Word into individual Symbols (for parseAligns)+splitWordTok :: PandocMonad m => LP m ()+splitWordTok = do+  inp <- getInput+  case inp of+       (Tok spos Word t : rest) ->+         setInput $ map (Tok spos Symbol . T.singleton) (T.unpack t) ++ rest+       _ -> return ()++parseAligns :: PandocMonad m => LP m [(Alignment, Double, ([Tok], [Tok]))]+parseAligns = try $ do+  let maybeBar = skipMany $+        sp <|> () <$ symbol '|' <|> () <$ (symbol '@' >> braced)+  let cAlign = AlignCenter <$ symbol 'c'+  let lAlign = AlignLeft <$ symbol 'l'+  let rAlign = AlignRight <$ symbol 'r'+  let parAlign = AlignLeft <$ symbol 'p'+  -- aligns from tabularx+  let xAlign = AlignLeft <$ symbol 'X'+  let mAlign = AlignLeft <$ symbol 'm'+  let bAlign = AlignLeft <$ symbol 'b'+  let alignChar = splitWordTok *> (  cAlign <|> lAlign <|> rAlign <|> parAlign+                                 <|> xAlign <|> mAlign <|> bAlign )+  let alignPrefix = symbol '>' >> braced+  let alignSuffix = symbol '<' >> braced+  let colWidth = try $ do+        symbol '{'+        ds <- trim . toksToString <$> manyTill anyTok (controlSeq "linewidth")+        spaces+        symbol '}'+        case safeRead ds of+              Just w  -> return w+              Nothing -> return 0.0+  let alignSpec = try $ do+        spaces+        pref <- option [] alignPrefix+        spaces+        al <- alignChar+        width <- colWidth <|> option 0.0 (do s <- toksToString <$> braced+                                             pos <- getPosition+                                             report $ SkippedContent s pos+                                             return 0.0)+        spaces+        suff <- option [] alignSuffix+        return (al, width, (pref, suff))+  bgroup+  spaces+  maybeBar+  aligns' <- many (alignSpec <* maybeBar)+  spaces+  egroup+  spaces+  return aligns'++parseTableRow :: PandocMonad m+              => Text   -- ^ table environment name+              -> [([Tok], [Tok])] -- ^ pref/suffixes+              -> LP m [Blocks]+parseTableRow envname prefsufs = do+  notFollowedBy (spaces *> end_ envname)+  let cols = length prefsufs+  -- add prefixes and suffixes in token stream:+  let celltoks (pref, suff) = do+        prefpos <- getPosition+        contents <- many (notFollowedBy+                         (() <$ amp <|> () <$ lbreak <|> end_ envname)+                         >> anyTok)+        suffpos <- getPosition+        option [] (count 1 amp)+        return $ map (setpos prefpos) pref ++ contents ++ map (setpos suffpos) suff+  rawcells <- mapM celltoks prefsufs+  oldInput <- getInput+  cells <- mapM (\ts -> setInput ts >> parseTableCell) rawcells+  setInput oldInput+  spaces+  let numcells = length cells+  guard $ numcells <= cols && numcells >= 1+  guard $ cells /= [mempty]+  -- note:  a & b in a three-column table leaves an empty 3rd cell:+  return $ cells ++ replicate (cols - numcells) mempty++parseTableCell :: PandocMonad m => LP m Blocks+parseTableCell = do+  let plainify bs = case toList bs of+                         [Para ils] -> plain (fromList ils)+                         _          -> bs+  updateState $ \st -> st{ sInTableCell = True }+  cells <- plainify <$> blocks+  updateState $ \st -> st{ sInTableCell = False }+  return cells++simpTable :: PandocMonad m => Text -> Bool -> LP m Blocks+simpTable envname hasWidthParameter = try $ do+  when hasWidthParameter $ () <$ (spaces >> tok)+  skipopts+  colspecs <- parseAligns+  let (aligns, widths, prefsufs) = unzip3 colspecs+  let cols = length colspecs+  optional $ controlSeq "caption" *> skipopts *> setCaption+  optional lbreak+  spaces+  skipMany hline+  spaces+  header' <- option [] $ try (parseTableRow envname prefsufs <*+                                   lbreak <* many1 hline)+  spaces+  rows <- sepEndBy (parseTableRow envname prefsufs)+                    (lbreak <* optional (skipMany hline))+  spaces+  optional $ controlSeq "caption" *> skipopts *> setCaption+  optional lbreak+  spaces+  let header'' = if null header'+                    then replicate cols mempty+                    else header'+  lookAhead $ controlSeq "end" -- make sure we're at end+  return $ table mempty (zip aligns widths) header'' rows++addTableCaption :: PandocMonad m => Blocks -> LP m Blocks+addTableCaption = walkM go+  where go (Table c als ws hs rs) = do+          mbcapt <- sCaption <$> getState+          return $ case mbcapt of+               Just ils -> Table (toList ils) als ws hs rs+               Nothing  -> Table c als ws hs rs+        go x = return x+++block :: PandocMonad m => LP m Blocks+block = (mempty <$ spaces1)+    <|> environment+    <|> include+    <|> macroDef+    <|> blockCommand+    <|> paragraph+    <|> grouped block++blocks :: PandocMonad m => LP m Blocks+blocks = mconcat <$> many block++setDefaultLanguage :: PandocMonad m => LP m Blocks+setDefaultLanguage = do+  o <- option "" $ (T.unpack . T.filter (\c -> c /= '[' && c /= ']'))+                <$> rawopt+  polylang <- toksToString <$> braced+  case M.lookup polylang polyglossiaLangToBCP47 of+       Nothing -> return mempty -- TODO mzero? warning?+       Just langFunc -> do+         let l = langFunc o+         setTranslations l+         updateState $ setMeta "lang" $ str (renderLang l)+         return mempty++polyglossiaLangToBCP47 :: M.Map String (String -> Lang)+polyglossiaLangToBCP47 = M.fromList+  [ ("arabic", \o -> case filter (/=' ') o of+       "locale=algeria"    -> Lang "ar" "" "DZ" []+       "locale=mashriq"    -> Lang "ar" "" "SY" []+       "locale=libya"      -> Lang "ar" "" "LY" []+       "locale=morocco"    -> Lang "ar" "" "MA" []+       "locale=mauritania" -> Lang "ar" "" "MR" []+       "locale=tunisia"    -> Lang "ar" "" "TN" []+       _                   -> Lang "ar" "" "" [])+  , ("german", \o -> case filter (/=' ') o of+       "spelling=old" -> Lang "de" "" "DE" ["1901"]+       "variant=austrian,spelling=old"+                       -> Lang "de" "" "AT" ["1901"]+       "variant=austrian" -> Lang "de" "" "AT" []+       "variant=swiss,spelling=old"+                       -> Lang "de" "" "CH" ["1901"]+       "variant=swiss" -> Lang "de" "" "CH" []+       _ -> Lang "de" "" "" [])+  , ("lsorbian", \_ -> Lang "dsb" "" "" [])+  , ("greek", \o -> case filter (/=' ') o of+       "variant=poly"    -> Lang "el" "" "polyton" []+       "variant=ancient" -> Lang "grc" "" "" []+       _                 -> Lang "el" "" "" [])+  , ("english", \o -> case filter (/=' ') o of+       "variant=australian" -> Lang "en" "" "AU" []+       "variant=canadian"   -> Lang "en" "" "CA" []+       "variant=british"    -> Lang "en" "" "GB" []+       "variant=newzealand" -> Lang "en" "" "NZ" []+       "variant=american"   -> Lang "en" "" "US" []+       _                    -> Lang "en" "" "" [])+  , ("usorbian", \_ -> Lang "hsb" "" "" [])+  , ("latin", \o -> case filter (/=' ') o of+       "variant=classic" -> Lang "la" "" "" ["x-classic"]+       _                 -> Lang "la" "" "" [])+  , ("slovenian", \_ -> Lang "sl" "" "" [])+  , ("serbianc", \_ -> Lang "sr" "cyrl" "" [])+  , ("pinyin", \_ -> Lang "zh" "Latn" "" ["pinyin"])+  , ("afrikaans", \_ -> Lang "af" "" "" [])+  , ("amharic", \_ -> Lang "am" "" "" [])+  , ("assamese", \_ -> Lang "as" "" "" [])+  , ("asturian", \_ -> Lang "ast" "" "" [])+  , ("bulgarian", \_ -> Lang "bg" "" "" [])+  , ("bengali", \_ -> Lang "bn" "" "" [])+  , ("tibetan", \_ -> Lang "bo" "" "" [])+  , ("breton", \_ -> Lang "br" "" "" [])+  , ("catalan", \_ -> Lang "ca" "" "" [])+  , ("welsh", \_ -> Lang "cy" "" "" [])+  , ("czech", \_ -> Lang "cs" "" "" [])+  , ("coptic", \_ -> Lang "cop" "" "" [])+  , ("danish", \_ -> Lang "da" "" "" [])+  , ("divehi", \_ -> Lang "dv" "" "" [])+  , ("esperanto", \_ -> Lang "eo" "" "" [])+  , ("spanish", \_ -> Lang "es" "" "" [])+  , ("estonian", \_ -> Lang "et" "" "" [])+  , ("basque", \_ -> Lang "eu" "" "" [])+  , ("farsi", \_ -> Lang "fa" "" "" [])+  , ("finnish", \_ -> Lang "fi" "" "" [])+  , ("french", \_ -> Lang "fr" "" "" [])+  , ("friulan", \_ -> Lang "fur" "" "" [])+  , ("irish", \_ -> Lang "ga" "" "" [])+  , ("scottish", \_ -> Lang "gd" "" "" [])+  , ("ethiopic", \_ -> Lang "gez" "" "" [])+  , ("galician", \_ -> Lang "gl" "" "" [])+  , ("hebrew", \_ -> Lang "he" "" "" [])+  , ("hindi", \_ -> Lang "hi" "" "" [])+  , ("croatian", \_ -> Lang "hr" "" "" [])+  , ("magyar", \_ -> Lang "hu" "" "" [])+  , ("armenian", \_ -> Lang "hy" "" "" [])+  , ("interlingua", \_ -> Lang "ia" "" "" [])+  , ("indonesian", \_ -> Lang "id" "" "" [])+  , ("icelandic", \_ -> Lang "is" "" "" [])+  , ("italian", \_ -> Lang "it" "" "" [])+  , ("japanese", \_ -> Lang "jp" "" "" [])+  , ("khmer", \_ -> Lang "km" "" "" [])+  , ("kurmanji", \_ -> Lang "kmr" "" "" [])+  , ("kannada", \_ -> Lang "kn" "" "" [])+  , ("korean", \_ -> Lang "ko" "" "" [])+  , ("lao", \_ -> Lang "lo" "" "" [])+  , ("lithuanian", \_ -> Lang "lt" "" "" [])+  , ("latvian", \_ -> Lang "lv" "" "" [])+  , ("malayalam", \_ -> Lang "ml" "" "" [])+  , ("mongolian", \_ -> Lang "mn" "" "" [])+  , ("marathi", \_ -> Lang "mr" "" "" [])+  , ("dutch", \_ -> Lang "nl" "" "" [])+  , ("nynorsk", \_ -> Lang "nn" "" "" [])+  , ("norsk", \_ -> Lang "no" "" "" [])+  , ("nko", \_ -> Lang "nqo" "" "" [])+  , ("occitan", \_ -> Lang "oc" "" "" [])+  , ("panjabi", \_ -> Lang "pa" "" "" [])+  , ("polish", \_ -> Lang "pl" "" "" [])+  , ("piedmontese", \_ -> Lang "pms" "" "" [])+  , ("portuguese", \_ -> Lang "pt" "" "" [])+  , ("romansh", \_ -> Lang "rm" "" "" [])+  , ("romanian", \_ -> Lang "ro" "" "" [])+  , ("russian", \_ -> Lang "ru" "" "" [])+  , ("sanskrit", \_ -> Lang "sa" "" "" [])+  , ("samin", \_ -> Lang "se" "" "" [])+  , ("slovak", \_ -> Lang "sk" "" "" [])+  , ("albanian", \_ -> Lang "sq" "" "" [])+  , ("serbian", \_ -> Lang "sr" "" "" [])+  , ("swedish", \_ -> Lang "sv" "" "" [])+  , ("syriac", \_ -> Lang "syr" "" "" [])+  , ("tamil", \_ -> Lang "ta" "" "" [])+  , ("telugu", \_ -> Lang "te" "" "" [])+  , ("thai", \_ -> Lang "th" "" "" [])+  , ("turkmen", \_ -> Lang "tk" "" "" [])+  , ("turkish", \_ -> Lang "tr" "" "" [])+  , ("ukrainian", \_ -> Lang "uk" "" "" [])+  , ("urdu", \_ -> Lang "ur" "" "" [])+  , ("vietnamese", \_ -> Lang "vi" "" "" [])+  ]
+ src/Text/Pandoc/Readers/LaTeX/Types.hs view
@@ -0,0 +1,51 @@+{-+Copyright (C) 2017 John MacFarlane <jgm@berkeley.edu>++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation; either version 2 of the License, or+(at your option) any later version.++This program is distributed in the hope that it will be useful,+but WITHOUT ANY WARRANTY; without even the implied warranty of+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+GNU General Public License for more details.++You should have received a copy of the GNU General Public License+along with this program; if not, write to the Free Software+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+-}++{- |+   Module      : Text.Pandoc.Readers.LaTeX.Types+   Copyright   : Copyright (C) 2017 John MacFarlane+   License     : GNU GPL, version 2 or above++   Maintainer  : John MacFarlane <jgm@berkeley.edu>+   Stability   : alpha+   Portability : portable++Types for LaTeX tokens and macros.+-}+module Text.Pandoc.Readers.LaTeX.Types ( Tok(..)+                                       , TokType(..)+                                       , Macro(..)+                                       , ExpansionPoint(..)+                                       , SourcePos+                                       )+where+import Data.Text (Text)+import Text.Parsec.Pos (SourcePos)++data TokType = CtrlSeq Text | Spaces | Newline | Symbol | Word | Comment |+               Esc1    | Esc2   | Arg Int+     deriving (Eq, Ord, Show)++data Tok = Tok SourcePos TokType Text+     deriving (Eq, Ord, Show)++data ExpansionPoint = ExpandWhenDefined | ExpandWhenUsed+     deriving (Eq, Ord, Show)++data Macro = Macro ExpansionPoint Int (Maybe [Tok]) [Tok]+     deriving Show
src/Text/Pandoc/Readers/Markdown.hs view
@@ -1,2097 +1,2117 @@-{-# LANGUAGE RelaxedPolyRec #-} -- needed for inlinesBetween on GHC < 7-{-# LANGUAGE ScopedTypeVariables #-}-{--Copyright (C) 2006-2015 John MacFarlane <jgm@berkeley.edu>--This program is free software; you can redistribute it and/or modify-it under the terms of the GNU General Public License as published by-the Free Software Foundation; either version 2 of the License, or-(at your option) any later version.--This program is distributed in the hope that it will be useful,-but WITHOUT ANY WARRANTY; without even the implied warranty of-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the-GNU General Public License for more details.--You should have received a copy of the GNU General Public License-along with this program; if not, write to the Free Software-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA--}--{- |-   Module      : Text.Pandoc.Readers.Markdown-   Copyright   : Copyright (C) 2006-2015 John MacFarlane-   License     : GNU GPL, version 2 or above--   Maintainer  : John MacFarlane <jgm@berkeley.edu>-   Stability   : alpha-   Portability : portable--Conversion of markdown-formatted plain text to 'Pandoc' document.--}-module Text.Pandoc.Readers.Markdown ( readMarkdown,-                                      readMarkdownWithWarnings ) where--import Data.List ( transpose, sortBy, findIndex, intercalate )-import qualified Data.Map as M-import Data.Scientific (coefficient, base10Exponent)-import Data.Ord ( comparing )-import Data.Char ( isSpace, isAlphaNum, toLower, isPunctuation )-import Data.Maybe-import Text.Pandoc.Definition-import Text.Pandoc.Emoji (emojis)-import Text.Pandoc.Generic (bottomUp)-import qualified Data.Text as T-import Data.Text (Text)-import qualified Data.Yaml as Yaml-import Data.Yaml (ParseException(..), YamlException(..), YamlMark(..))-import qualified Data.HashMap.Strict as H-import qualified Text.Pandoc.Builder as B-import qualified Text.Pandoc.UTF8 as UTF8-import qualified Data.Vector as V-import Text.Pandoc.Builder (Inlines, Blocks, trimInlines)-import Text.Pandoc.Options-import Text.Pandoc.Shared-import Text.Pandoc.Pretty (charWidth)-import Text.Pandoc.XML (fromEntities)-import Text.Pandoc.Parsing hiding (tableWith)-import Text.Pandoc.Readers.LaTeX ( rawLaTeXInline, rawLaTeXBlock )-import Text.Pandoc.Readers.HTML ( htmlTag, htmlInBalanced, isInlineTag, isBlockTag,-                                  isTextTag, isCommentTag )-import Control.Monad-import System.FilePath (takeExtension, addExtension)-import Text.HTML.TagSoup-import qualified Data.Set as Set-import Text.Printf (printf)-import Debug.Trace (trace)-import Data.Monoid ((<>))-import Text.Pandoc.Error--type MarkdownParser = Parser [Char] ParserState---- | Read markdown from an input string and return a Pandoc document.-readMarkdown :: ReaderOptions -- ^ Reader options-             -> String        -- ^ String to parse (assuming @'\n'@ line endings)-             -> Either PandocError Pandoc-readMarkdown opts s =-  (readWith parseMarkdown) def{ stateOptions = opts } (s ++ "\n\n")---- | Read markdown from an input string and return a pair of a Pandoc document--- and a list of warnings.-readMarkdownWithWarnings :: ReaderOptions -- ^ Reader options-                         -> String        -- ^ String to parse (assuming @'\n'@ line endings)-                         -> Either PandocError (Pandoc, [String])-readMarkdownWithWarnings opts s =-    (readWithWarnings parseMarkdown) def{ stateOptions = opts } (s ++ "\n\n")--trimInlinesF :: F Inlines -> F Inlines-trimInlinesF = liftM trimInlines------- Constants and data structure definitions-----isBulletListMarker :: Char -> Bool-isBulletListMarker '*' = True-isBulletListMarker '+' = True-isBulletListMarker '-' = True-isBulletListMarker _   = False--isHruleChar :: Char -> Bool-isHruleChar '*' = True-isHruleChar '-' = True-isHruleChar '_' = True-isHruleChar _   = False--setextHChars :: String-setextHChars = "=-"--isBlank :: Char -> Bool-isBlank ' '  = True-isBlank '\t' = True-isBlank '\n' = True-isBlank _    = False------- auxiliary functions------- | Succeeds when we're in list context.-inList :: MarkdownParser ()-inList = do-  ctx <- stateParserContext <$> getState-  guard (ctx == ListItemState)--spnl :: Parser [Char] st ()-spnl = try $ do-  skipSpaces-  optional newline-  skipSpaces-  notFollowedBy (char '\n')--indentSpaces :: MarkdownParser String-indentSpaces = try $ do-  tabStop <- getOption readerTabStop-  count tabStop (char ' ') <|>-    string "\t" <?> "indentation"--nonindentSpaces :: MarkdownParser String-nonindentSpaces = do-  tabStop <- getOption readerTabStop-  sps <- many (char ' ')-  if length sps < tabStop-     then return sps-     else unexpected "indented line"---- returns number of spaces parsed-skipNonindentSpaces :: MarkdownParser Int-skipNonindentSpaces = do-  tabStop <- getOption readerTabStop-  atMostSpaces (tabStop - 1) <* notFollowedBy (char ' ')--atMostSpaces :: Int -> MarkdownParser Int-atMostSpaces n-  | n > 0     = (char ' ' >> (+1) <$> atMostSpaces (n-1)) <|> return 0-  | otherwise = return 0--litChar :: MarkdownParser Char-litChar = escapedChar'-       <|> characterReference-       <|> noneOf "\n"-       <|> try (newline >> notFollowedBy blankline >> return ' ')---- | Parse a sequence of inline elements between square brackets,--- including inlines between balanced pairs of square brackets.-inlinesInBalancedBrackets :: MarkdownParser (F Inlines)-inlinesInBalancedBrackets = do-  char '['-  (_, raw) <- withRaw $ charsInBalancedBrackets 1-  guard $ not $ null raw-  parseFromString (trimInlinesF . mconcat <$> many inline) (init raw)--charsInBalancedBrackets :: Int -> MarkdownParser ()-charsInBalancedBrackets 0 = return ()-charsInBalancedBrackets openBrackets =-      (char '[' >> charsInBalancedBrackets (openBrackets + 1))-  <|> (char ']' >> charsInBalancedBrackets (openBrackets - 1))-  <|> ((  (() <$ code)-     <|> (() <$ (escapedChar'))-     <|> (newline >> notFollowedBy blankline)-     <|> skipMany1 (noneOf "[]`\n\\")-     <|> (() <$ count 1 (oneOf "`\\"))-      ) >> charsInBalancedBrackets openBrackets)------- document structure-----rawTitleBlockLine :: MarkdownParser String-rawTitleBlockLine = do-  char '%'-  skipSpaces-  first <- anyLine-  rest <- many $ try $ do spaceChar-                          notFollowedBy blankline-                          skipSpaces-                          anyLine-  return $ trim $ unlines (first:rest)--titleLine :: MarkdownParser (F Inlines)-titleLine = try $ do-  raw <- rawTitleBlockLine-  res <- parseFromString (many inline) raw-  return $ trimInlinesF $ mconcat res--authorsLine :: MarkdownParser (F [Inlines])-authorsLine = try $ do-  raw <- rawTitleBlockLine-  let sep = (char ';' <* spaces) <|> newline-  let pAuthors = sepEndBy-            (trimInlinesF . mconcat <$> many-                 (try $ notFollowedBy sep >> inline))-            sep-  sequence <$> parseFromString pAuthors raw--dateLine :: MarkdownParser (F Inlines)-dateLine = try $ do-  raw <- rawTitleBlockLine-  res <- parseFromString (many inline) raw-  return $ trimInlinesF $ mconcat res--titleBlock :: MarkdownParser ()-titleBlock = pandocTitleBlock <|> mmdTitleBlock--pandocTitleBlock :: MarkdownParser ()-pandocTitleBlock = try $ do-  guardEnabled Ext_pandoc_title_block-  lookAhead (char '%')-  title <- option mempty titleLine-  author <- option (return []) authorsLine-  date <- option mempty dateLine-  optional blanklines-  let meta' = do title' <- title-                 author' <- author-                 date' <- date-                 return $-                     (if B.isNull title' then id else B.setMeta "title" title')-                   . (if null author' then id else B.setMeta "author" author')-                   . (if B.isNull date' then id else B.setMeta "date" date')-                   $ nullMeta-  updateState $ \st -> st{ stateMeta' = stateMeta' st <> meta' }--yamlMetaBlock :: MarkdownParser (F Blocks)-yamlMetaBlock = try $ do-  guardEnabled Ext_yaml_metadata_block-  pos <- getPosition-  string "---"-  blankline-  notFollowedBy blankline  -- if --- is followed by a blank it's an HRULE-  rawYamlLines <- manyTill anyLine stopLine-  -- by including --- and ..., we allow yaml blocks with just comments:-  let rawYaml = unlines ("---" : (rawYamlLines ++ ["..."]))-  optional blanklines-  opts <- stateOptions <$> getState-  meta' <- case Yaml.decodeEither' $ UTF8.fromString rawYaml of-                Right (Yaml.Object hashmap) -> return $ return $-                         H.foldrWithKey (\k v m ->-                              if ignorable k-                                 then m-                                 else case yamlToMeta opts v of-                                        Left _  -> m-                                        Right v' -> B.setMeta (T.unpack k) v' m)-                           nullMeta hashmap-                Right Yaml.Null -> return $ return nullMeta-                Right _ -> do-                            addWarning (Just pos) "YAML header is not an object"-                            return $ return nullMeta-                Left err' -> do-                         case err' of-                            InvalidYaml (Just YamlParseException{-                                        yamlProblem = problem-                                      , yamlContext = _ctxt-                                      , yamlProblemMark = Yaml.YamlMark {-                                            yamlLine = yline-                                          , yamlColumn = ycol-                                      }}) ->-                                 addWarning (Just $ setSourceLine-                                    (setSourceColumn pos-                                       (sourceColumn pos + ycol))-                                    (sourceLine pos + 1 + yline))-                                    $ "Could not parse YAML header: " ++-                                        problem-                            _ -> addWarning (Just pos)-                                    $ "Could not parse YAML header: " ++-                                        show err'-                         return $ return nullMeta-  updateState $ \st -> st{ stateMeta' = stateMeta' st <> meta' }-  return mempty---- ignore fields ending with _-ignorable :: Text -> Bool-ignorable t = (T.pack "_") `T.isSuffixOf` t--toMetaValue :: ReaderOptions -> Text -> Either PandocError MetaValue-toMetaValue opts x = toMeta <$> readMarkdown opts' (T.unpack x)-  where-    toMeta p =-      case p of-        Pandoc _ [Plain xs]  -> MetaInlines xs-        Pandoc _ [Para xs]-         | endsWithNewline x -> MetaBlocks [Para xs]-         | otherwise         -> MetaInlines xs-        Pandoc _ bs           -> MetaBlocks bs-    endsWithNewline t = T.pack "\n" `T.isSuffixOf` t-    opts' = opts{readerExtensions=readerExtensions opts `Set.difference` meta_exts}-    meta_exts = Set.fromList [ Ext_pandoc_title_block-                             , Ext_mmd_title_block-                             , Ext_yaml_metadata_block-                             ]--yamlToMeta :: ReaderOptions -> Yaml.Value -> Either PandocError MetaValue-yamlToMeta opts (Yaml.String t) = toMetaValue opts t-yamlToMeta _    (Yaml.Number n)-  -- avoid decimal points for numbers that don't need them:-  | base10Exponent n >= 0     = return $ MetaString $ show-                                $ coefficient n * (10 ^ base10Exponent n)-  | otherwise                 = return $ MetaString $ show n-yamlToMeta _    (Yaml.Bool b) = return $ MetaBool b-yamlToMeta opts (Yaml.Array xs) = B.toMetaValue <$> mapM (yamlToMeta opts)-                                                  (V.toList xs)-yamlToMeta opts (Yaml.Object o) = MetaMap <$> H.foldrWithKey (\k v m ->-                                if ignorable k-                                   then m-                                   else (do-                                    v' <- yamlToMeta opts v-                                    m' <- m-                                    return (M.insert (T.unpack k) v' m')))-                                (return M.empty) o-yamlToMeta _ _ = return $ MetaString ""--stopLine :: MarkdownParser ()-stopLine = try $ (string "---" <|> string "...") >> blankline >> return ()--mmdTitleBlock :: MarkdownParser ()-mmdTitleBlock = try $ do-  guardEnabled Ext_mmd_title_block-  firstPair <- kvPair False-  restPairs <- many (kvPair True)-  let kvPairs = firstPair : restPairs-  blanklines-  updateState $ \st -> st{ stateMeta' = stateMeta' st <>-                             return (Meta $ M.fromList kvPairs) }--kvPair :: Bool -> MarkdownParser (String, MetaValue)-kvPair allowEmpty = try $ do-  key <- many1Till (alphaNum <|> oneOf "_- ") (char ':')-  val <- trim <$> manyTill anyChar-          (try $ newline >> lookAhead (blankline <|> nonspaceChar))-  guard $ allowEmpty || not (null val)-  let key' = concat $ words $ map toLower key-  let val' = MetaBlocks $ B.toList $ B.plain $ B.text $ val-  return (key',val')--parseMarkdown :: MarkdownParser Pandoc-parseMarkdown = do-  -- markdown allows raw HTML-  updateState $ \state -> state { stateOptions =-                let oldOpts = stateOptions state in-                    oldOpts{ readerParseRaw = True } }-  optional titleBlock-  blocks <- parseBlocks-  st <- getState-  let meta = runF (stateMeta' st) st-  let Pandoc _ bs = B.doc $ runF blocks st-  eastAsianLineBreaks <- option False $-                    True <$ guardEnabled Ext_east_asian_line_breaks-  return $ (if eastAsianLineBreaks-               then bottomUp softBreakFilter-               else id) $ Pandoc meta bs--softBreakFilter :: [Inline] -> [Inline]-softBreakFilter (x:SoftBreak:y:zs) =-  case (stringify x, stringify y) of-        (xs@(_:_), (c:_))-          | charWidth (last xs) == 2 && charWidth c == 2 -> x:y:zs-        _ -> x:SoftBreak:y:zs-softBreakFilter xs = xs--referenceKey :: MarkdownParser (F Blocks)-referenceKey = try $ do-  pos <- getPosition-  skipNonindentSpaces-  (_,raw) <- reference-  char ':'-  skipSpaces >> optional newline >> skipSpaces >> notFollowedBy (char '[')-  let sourceURL = liftM unwords $ many $ try $ do-                    skipMany spaceChar-                    notFollowedBy' referenceTitle-                    notFollowedBy' $ guardEnabled Ext_link_attributes >> attributes-                    notFollowedBy' (() <$ reference)-                    many1 $ notFollowedBy space >> litChar-  let betweenAngles = try $ char '<' >> manyTill litChar (char '>')-  src <- try betweenAngles <|> sourceURL-  tit <- option "" referenceTitle-  attr   <- option nullAttr $ try $-              guardEnabled Ext_link_attributes >> skipSpaces >> attributes-  addKvs <- option [] $ guardEnabled Ext_mmd_link_attributes-                          >> many (try $ spnl >> keyValAttr)-  blanklines-  let attr'  = extractIdClass $ foldl (\x f -> f x) attr addKvs-      target = (escapeURI $ trimr src, tit)-  st <- getState-  let oldkeys = stateKeys st-  let key = toKey raw-  case M.lookup key oldkeys of-    Just _  -> addWarning (Just pos) $ "Duplicate link reference `" ++ raw ++ "'"-    Nothing -> return ()-  updateState $ \s -> s { stateKeys = M.insert key (target, attr') oldkeys }-  return $ return mempty--referenceTitle :: MarkdownParser String-referenceTitle = try $ do-  skipSpaces >> optional newline >> skipSpaces-  quotedTitle '"' <|> quotedTitle '\'' <|> charsInBalanced '(' ')' litChar---- A link title in quotes-quotedTitle :: Char -> MarkdownParser String-quotedTitle c = try $ do-  char c-  notFollowedBy spaces-  let pEnder = try $ char c >> notFollowedBy (satisfy isAlphaNum)-  let regChunk = many1 (noneOf ['\\','\n','&',c]) <|> count 1 litChar-  let nestedChunk = (\x -> [c] ++ x ++ [c]) <$> quotedTitle c-  unwords . words . concat <$> manyTill (nestedChunk <|> regChunk) pEnder---- | PHP Markdown Extra style abbreviation key.  Currently--- we just skip them, since Pandoc doesn't have an element for--- an abbreviation.-abbrevKey :: MarkdownParser (F Blocks)-abbrevKey = do-  guardEnabled Ext_abbreviations-  try $ do-    char '*'-    reference-    char ':'-    skipMany (satisfy (/= '\n'))-    blanklines-    return $ return mempty--noteMarker :: MarkdownParser String-noteMarker = string "[^" >> many1Till (satisfy $ not . isBlank) (char ']')--rawLine :: MarkdownParser String-rawLine = try $ do-  notFollowedBy blankline-  notFollowedBy' $ try $ skipNonindentSpaces >> noteMarker-  optional indentSpaces-  anyLine--rawLines :: MarkdownParser String-rawLines = do-  first <- anyLine-  rest <- many rawLine-  return $ unlines (first:rest)--noteBlock :: MarkdownParser (F Blocks)-noteBlock = try $ do-  pos <- getPosition-  skipNonindentSpaces-  ref <- noteMarker-  char ':'-  optional blankline-  optional indentSpaces-  first <- rawLines-  rest <- many $ try $ blanklines >> indentSpaces >> rawLines-  let raw = unlines (first:rest) ++ "\n"-  optional blanklines-  parsed <- parseFromString parseBlocks raw-  let newnote = (ref, parsed)-  oldnotes <- stateNotes' <$> getState-  case lookup ref oldnotes of-    Just _  -> addWarning (Just pos) $ "Duplicate note reference `" ++ ref ++ "'"-    Nothing -> return ()-  updateState $ \s -> s { stateNotes' = newnote : oldnotes }-  return mempty------- parsing blocks-----parseBlocks :: MarkdownParser (F Blocks)-parseBlocks = mconcat <$> manyTill block eof--block :: MarkdownParser (F Blocks)-block = do-  tr <- getOption readerTrace-  pos <- getPosition-  res <- choice [ mempty <$ blanklines-               , codeBlockFenced-               , yamlMetaBlock-               -- note: bulletList needs to be before header because of-               -- the possibility of empty list items: --               , bulletList-               , header-               , lhsCodeBlock-               , divHtml-               , htmlBlock-               , table-               , codeBlockIndented-               , guardEnabled Ext_latex_macros *> (macro >>= return . return)-               , rawTeXBlock-               , lineBlock-               , blockQuote-               , hrule-               , orderedList-               , definitionList-               , noteBlock-               , referenceKey-               , abbrevKey-               , para-               , plain-               ] <?> "block"-  when tr $ do-    st <- getState-    trace (printf "line %d: %s" (sourceLine pos)-           (take 60 $ show $ B.toList $ runF res st)) (return ())-  return res------- header blocks-----header :: MarkdownParser (F Blocks)-header = setextHeader <|> atxHeader <?> "header"--atxChar :: MarkdownParser Char-atxChar = do-  exts <- getOption readerExtensions-  return $ if Set.member Ext_literate_haskell exts-    then '=' else '#'--atxHeader :: MarkdownParser (F Blocks)-atxHeader = try $ do-  level <- atxChar >>= many1 . char >>= return . length-  notFollowedBy $ guardEnabled Ext_fancy_lists >>-                  (char '.' <|> char ')') -- this would be a list-  skipSpaces-  (text, raw) <- withRaw $-          trimInlinesF . mconcat <$> many (notFollowedBy atxClosing >> inline)-  attr <- atxClosing-  attr' <- registerHeader attr (runF text defaultParserState)-  guardDisabled Ext_implicit_header_references-    <|> registerImplicitHeader raw attr'-  return $ B.headerWith attr' level <$> text--atxClosing :: MarkdownParser Attr-atxClosing = try $ do-  attr' <- option nullAttr-             (guardEnabled Ext_mmd_header_identifiers >> mmdHeaderIdentifier)-  skipMany . char =<< atxChar-  skipSpaces-  attr <- option attr'-             (guardEnabled Ext_header_attributes >> attributes)-  blanklines-  return attr--setextHeaderEnd :: MarkdownParser Attr-setextHeaderEnd = try $ do-  attr <- option nullAttr-          $ (guardEnabled Ext_mmd_header_identifiers >> mmdHeaderIdentifier)-           <|> (guardEnabled Ext_header_attributes >> attributes)-  blanklines-  return attr--mmdHeaderIdentifier :: MarkdownParser Attr-mmdHeaderIdentifier = do-  ident <- stripFirstAndLast . snd <$> reference-  skipSpaces-  return (ident,[],[])--setextHeader :: MarkdownParser (F Blocks)-setextHeader = try $ do-  -- This lookahead prevents us from wasting time parsing Inlines-  -- unless necessary -- it gives a significant performance boost.-  lookAhead $ anyLine >> many1 (oneOf setextHChars) >> blankline-  skipSpaces-  (text, raw) <- withRaw $-       trimInlinesF . mconcat <$> many1 (notFollowedBy setextHeaderEnd >> inline)-  attr <- setextHeaderEnd-  underlineChar <- oneOf setextHChars-  many (char underlineChar)-  blanklines-  let level = (fromMaybe 0 $ findIndex (== underlineChar) setextHChars) + 1-  attr' <- registerHeader attr (runF text defaultParserState)-  guardDisabled Ext_implicit_header_references-    <|> registerImplicitHeader raw attr'-  return $ B.headerWith attr' level <$> text--registerImplicitHeader :: String -> Attr -> MarkdownParser ()-registerImplicitHeader raw attr@(ident, _, _) = do-  let key = toKey $ "[" ++ raw ++ "]"-  updateState (\s -> s { stateHeaderKeys =-                         M.insert key (('#':ident,""), attr) (stateHeaderKeys s) })------- hrule block-----hrule :: Parser [Char] st (F Blocks)-hrule = try $ do-  skipSpaces-  start <- satisfy isHruleChar-  count 2 (skipSpaces >> char start)-  skipMany (spaceChar <|> char start)-  newline-  optional blanklines-  return $ return B.horizontalRule------- code blocks-----indentedLine :: MarkdownParser String-indentedLine = indentSpaces >> anyLine >>= return . (++ "\n")--blockDelimiter :: (Char -> Bool)-               -> Maybe Int-               -> Parser [Char] st Int-blockDelimiter f len = try $ do-  c <- lookAhead (satisfy f)-  case len of-      Just l  -> count l (char c) >> many (char c) >> return l-      Nothing -> count 3 (char c) >> many (char c) >>=-                 return . (+ 3) . length--attributes :: MarkdownParser Attr-attributes = try $ do-  char '{'-  spnl-  attrs <- many (attribute <* spnl)-  char '}'-  return $ foldl (\x f -> f x) nullAttr attrs--attribute :: MarkdownParser (Attr -> Attr)-attribute = identifierAttr <|> classAttr <|> keyValAttr <|> specialAttr--identifier :: MarkdownParser String-identifier = do-  first <- letter-  rest <- many $ alphaNum <|> oneOf "-_:."-  return (first:rest)--identifierAttr :: MarkdownParser (Attr -> Attr)-identifierAttr = try $ do-  char '#'-  result <- identifier-  return $ \(_,cs,kvs) -> (result,cs,kvs)--classAttr :: MarkdownParser (Attr -> Attr)-classAttr = try $ do-  char '.'-  result <- identifier-  return $ \(id',cs,kvs) -> (id',cs ++ [result],kvs)--keyValAttr :: MarkdownParser (Attr -> Attr)-keyValAttr = try $ do-  key <- identifier-  char '='-  val <- enclosed (char '"') (char '"') litChar-     <|> enclosed (char '\'') (char '\'') litChar-     <|> many (escapedChar' <|> noneOf " \t\n\r}")-  return $ \(id',cs,kvs) ->-    case key of-         "id"    -> (val,cs,kvs)-         "class" -> (id',cs ++ words val,kvs)-         _       -> (id',cs,kvs ++ [(key,val)])--specialAttr :: MarkdownParser (Attr -> Attr)-specialAttr = do-  char '-'-  return $ \(id',cs,kvs) -> (id',cs ++ ["unnumbered"],kvs)--codeBlockFenced :: MarkdownParser (F Blocks)-codeBlockFenced = try $ do-  c <- try (guardEnabled Ext_fenced_code_blocks >> lookAhead (char '~'))-     <|> (guardEnabled Ext_backtick_code_blocks >> lookAhead (char '`'))-  size <- blockDelimiter (== c) Nothing-  skipMany spaceChar-  attr <- option ([],[],[]) $-            try (guardEnabled Ext_fenced_code_attributes >> attributes)-           <|> ((\x -> ("",[toLanguageId x],[])) <$> many1 nonspaceChar)-  blankline-  contents <- manyTill anyLine (blockDelimiter (== c) (Just size))-  blanklines-  return $ return $ B.codeBlockWith attr $ intercalate "\n" contents---- correctly handle github language identifiers-toLanguageId :: String -> String-toLanguageId = map toLower . go-  where go "c++" = "cpp"-        go "objective-c" = "objectivec"-        go x = x--codeBlockIndented :: MarkdownParser (F Blocks)-codeBlockIndented = do-  contents <- many1 (indentedLine <|>-                     try (do b <- blanklines-                             l <- indentedLine-                             return $ b ++ l))-  optional blanklines-  classes <- getOption readerIndentedCodeClasses-  return $ return $ B.codeBlockWith ("", classes, []) $-           stripTrailingNewlines $ concat contents--lhsCodeBlock :: MarkdownParser (F Blocks)-lhsCodeBlock = do-  guardEnabled Ext_literate_haskell-  (return . B.codeBlockWith ("",["sourceCode","literate","haskell"],[]) <$>-          (lhsCodeBlockBird <|> lhsCodeBlockLaTeX))-    <|> (return . B.codeBlockWith ("",["sourceCode","haskell"],[]) <$>-          lhsCodeBlockInverseBird)--lhsCodeBlockLaTeX :: MarkdownParser String-lhsCodeBlockLaTeX = try $ do-  string "\\begin{code}"-  manyTill spaceChar newline-  contents <- many1Till anyChar (try $ string "\\end{code}")-  blanklines-  return $ stripTrailingNewlines contents--lhsCodeBlockBird :: MarkdownParser String-lhsCodeBlockBird = lhsCodeBlockBirdWith '>'--lhsCodeBlockInverseBird :: MarkdownParser String-lhsCodeBlockInverseBird = lhsCodeBlockBirdWith '<'--lhsCodeBlockBirdWith :: Char -> MarkdownParser String-lhsCodeBlockBirdWith c = try $ do-  pos <- getPosition-  when (sourceColumn pos /= 1) $ fail "Not in first column"-  lns <- many1 $ birdTrackLine c-  -- if (as is normal) there is always a space after >, drop it-  let lns' = if all (\ln -> null ln || take 1 ln == " ") lns-                then map (drop 1) lns-                else lns-  blanklines-  return $ intercalate "\n" lns'--birdTrackLine :: Char -> Parser [Char] st String-birdTrackLine c = try $ do-  char c-  -- allow html tags on left margin:-  when (c == '<') $ notFollowedBy letter-  anyLine------- block quotes-----emailBlockQuoteStart :: MarkdownParser Char-emailBlockQuoteStart = try $ skipNonindentSpaces >> char '>' <* optional (char ' ')--emailBlockQuote :: MarkdownParser [String]-emailBlockQuote = try $ do-  emailBlockQuoteStart-  let emailLine = many $ nonEndline <|> try-                         (endline >> notFollowedBy emailBlockQuoteStart >>-                         return '\n')-  let emailSep = try (newline >> emailBlockQuoteStart)-  first <- emailLine-  rest <- many $ try $ emailSep >> emailLine-  let raw = first:rest-  newline <|> (eof >> return '\n')-  optional blanklines-  return raw--blockQuote :: MarkdownParser (F Blocks)-blockQuote = do-  raw <- emailBlockQuote-  -- parse the extracted block, which may contain various block elements:-  contents <- parseFromString parseBlocks $ (intercalate "\n" raw) ++ "\n\n"-  return $ B.blockQuote <$> contents------- list blocks-----bulletListStart :: MarkdownParser ()-bulletListStart = try $ do-  optional newline -- if preceded by a Plain block in a list context-  startpos <- sourceColumn <$> getPosition-  skipNonindentSpaces-  notFollowedBy' (() <$ hrule)     -- because hrules start out just like lists-  satisfy isBulletListMarker-  endpos <- sourceColumn <$> getPosition-  tabStop <- getOption readerTabStop-  lookAhead (newline <|> spaceChar)-  () <$ atMostSpaces (tabStop - (endpos - startpos))--anyOrderedListStart :: MarkdownParser (Int, ListNumberStyle, ListNumberDelim)-anyOrderedListStart = try $ do-  optional newline -- if preceded by a Plain block in a list context-  startpos <- sourceColumn <$> getPosition-  skipNonindentSpaces-  notFollowedBy $ string "p." >> spaceChar >> digit  -- page number-  res <- do guardDisabled Ext_fancy_lists-            start <- many1 digit >>= safeRead-            char '.'-            return (start, DefaultStyle, DefaultDelim)-     <|> do (num, style, delim) <- anyOrderedListMarker-            -- if it could be an abbreviated first name,-            -- insist on more than one space-            when (delim == Period && (style == UpperAlpha ||-                 (style == UpperRoman &&-                  num `elem` [1, 5, 10, 50, 100, 500, 1000]))) $-               () <$ spaceChar-            return (num, style, delim)-  endpos <- sourceColumn <$> getPosition-  tabStop <- getOption readerTabStop-  lookAhead (newline <|> spaceChar)-  atMostSpaces (tabStop - (endpos - startpos))-  return res--listStart :: MarkdownParser ()-listStart = bulletListStart <|> (anyOrderedListStart >> return ())--listLine :: MarkdownParser String-listLine = try $ do-  notFollowedBy' (do indentSpaces-                     many spaceChar-                     listStart)-  notFollowedByHtmlCloser-  optional (() <$ indentSpaces)-  listLineCommon--listLineCommon :: MarkdownParser String-listLineCommon = concat <$> manyTill-              (  many1 (satisfy $ \c -> c /= '\n' && c /= '<')-             <|> liftM snd (htmlTag isCommentTag)-             <|> count 1 anyChar-              ) newline---- parse raw text for one list item, excluding start marker and continuations-rawListItem :: MarkdownParser a-            -> MarkdownParser String-rawListItem start = try $ do-  start-  first <- listLineCommon-  rest <- many (notFollowedBy listStart >> notFollowedBy blankline >> listLine)-  blanks <- many blankline-  return $ unlines (first:rest) ++ blanks---- continuation of a list item - indented and separated by blankline--- or (in compact lists) endline.--- note: nested lists are parsed as continuations-listContinuation :: MarkdownParser String-listContinuation = try $ do-  lookAhead indentSpaces-  result <- many1 listContinuationLine-  blanks <- many blankline-  return $ concat result ++ blanks--notFollowedByHtmlCloser :: MarkdownParser ()-notFollowedByHtmlCloser = do-  inHtmlBlock <- stateInHtmlBlock <$> getState-  case inHtmlBlock of-        Just t  -> notFollowedBy' $ htmlTag (~== TagClose t)-        Nothing -> return ()--listContinuationLine :: MarkdownParser String-listContinuationLine = try $ do-  notFollowedBy blankline-  notFollowedBy' listStart-  notFollowedByHtmlCloser-  optional indentSpaces-  result <- anyLine-  return $ result ++ "\n"--listItem :: MarkdownParser a-         -> MarkdownParser (F Blocks)-listItem start = try $ do-  first <- rawListItem start-  continuations <- many listContinuation-  -- parsing with ListItemState forces markers at beginning of lines to-  -- count as list item markers, even if not separated by blank space.-  -- see definition of "endline"-  state <- getState-  let oldContext = stateParserContext state-  setState $ state {stateParserContext = ListItemState}-  -- parse the extracted block, which may contain various block elements:-  let raw = concat (first:continuations)-  contents <- parseFromString parseBlocks raw-  updateState (\st -> st {stateParserContext = oldContext})-  return contents--orderedList :: MarkdownParser (F Blocks)-orderedList = try $ do-  (start, style, delim) <- lookAhead anyOrderedListStart-  unless (style `elem` [DefaultStyle, Decimal, Example] &&-          delim `elem` [DefaultDelim, Period]) $-    guardEnabled Ext_fancy_lists-  when (style == Example) $ guardEnabled Ext_example_lists-  items <- fmap sequence $ many1 $ listItem-                 ( try $ do-                     optional newline -- if preceded by Plain block in a list-                     startpos <- sourceColumn <$> getPosition-                     skipNonindentSpaces-                     res <- orderedListMarker style delim-                     endpos <- sourceColumn <$> getPosition-                     tabStop <- getOption readerTabStop-                     lookAhead (newline <|> spaceChar)-                     atMostSpaces (tabStop - (endpos - startpos))-                     return res )-  start' <- option 1 $ guardEnabled Ext_startnum >> return start-  return $ B.orderedListWith (start', style, delim) <$> fmap compactify' items--bulletList :: MarkdownParser (F Blocks)-bulletList = do-  items <- fmap sequence $ many1 $ listItem  bulletListStart-  return $ B.bulletList <$> fmap compactify' items---- definition lists--defListMarker :: MarkdownParser ()-defListMarker = do-  sps <- nonindentSpaces-  char ':' <|> char '~'-  tabStop <- getOption readerTabStop-  let remaining = tabStop - (length sps + 1)-  if remaining > 0-     then try (count remaining (char ' ')) <|> string "\t" <|> many1 spaceChar-     else mzero-  return ()--definitionListItem :: Bool -> MarkdownParser (F (Inlines, [Blocks]))-definitionListItem compact = try $ do-  rawLine' <- anyLine-  raw <- many1 $ defRawBlock compact-  term <- parseFromString (trimInlinesF . mconcat <$> many inline) rawLine'-  contents <- mapM (parseFromString parseBlocks . (++"\n")) raw-  optional blanklines-  return $ liftM2 (,) term (sequence contents)--defRawBlock :: Bool -> MarkdownParser String-defRawBlock compact = try $ do-  hasBlank <- option False $ blankline >> return True-  defListMarker-  firstline <- anyLine-  let dline = try-               ( do notFollowedBy blankline-                    notFollowedByHtmlCloser-                    if compact -- laziness not compatible with compact-                       then () <$ indentSpaces-                       else (() <$ indentSpaces)-                             <|> notFollowedBy defListMarker-                    anyLine )-  rawlines <- many dline-  cont <- liftM concat $ many $ try $ do-            trailing <- option "" blanklines-            ln <- indentSpaces >> notFollowedBy blankline >> anyLine-            lns <- many dline-            return $ trailing ++ unlines (ln:lns)-  return $ trimr (firstline ++ "\n" ++ unlines rawlines ++ cont) ++-            if hasBlank || not (null cont) then "\n\n" else ""--definitionList :: MarkdownParser (F Blocks)-definitionList = try $ do-  lookAhead (anyLine >>-             optional (blankline >> notFollowedBy (table >> return ())) >>-             -- don't capture table caption as def list!-             defListMarker)-  compactDefinitionList <|> normalDefinitionList--compactDefinitionList :: MarkdownParser (F Blocks)-compactDefinitionList = do-  guardEnabled Ext_compact_definition_lists-  items <- fmap sequence $ many1 $ definitionListItem True-  return $ B.definitionList <$> fmap compactify'DL items--normalDefinitionList :: MarkdownParser (F Blocks)-normalDefinitionList = do-  guardEnabled Ext_definition_lists-  items <- fmap sequence $ many1 $ definitionListItem False-  return $ B.definitionList <$> items------- paragraph block-----para :: MarkdownParser (F Blocks)-para = try $ do-  exts <- getOption readerExtensions-  result <- trimInlinesF . mconcat <$> many1 inline-  option (B.plain <$> result)-    $ try $ do-            newline-            (blanklines >> return mempty)-              <|> (guardDisabled Ext_blank_before_blockquote >> () <$ lookAhead blockQuote)-              <|> (guardEnabled Ext_backtick_code_blocks >> () <$ lookAhead codeBlockFenced)-              <|> (guardDisabled Ext_blank_before_header >> () <$ lookAhead header)-              <|> (guardEnabled Ext_lists_without_preceding_blankline >>-                       -- Avoid creating a paragraph in a nested list.-                       notFollowedBy' inList >>-                       () <$ lookAhead listStart)-              <|> do guardEnabled Ext_native_divs-                     inHtmlBlock <- stateInHtmlBlock <$> getState-                     case inHtmlBlock of-                          Just "div" -> () <$-                                       lookAhead (htmlTag (~== TagClose "div"))-                          _          -> mzero-            return $ do-              result' <- result-              case B.toList result' of-                   [Image attr alt (src,tit)]-                     | Ext_implicit_figures `Set.member` exts ->-                        -- the fig: at beginning of title indicates a figure-                        return $ B.para $ B.singleton-                               $ Image attr alt (src,'f':'i':'g':':':tit)-                   _ -> return $ B.para result'--plain :: MarkdownParser (F Blocks)-plain = fmap B.plain . trimInlinesF . mconcat <$> many1 inline------- raw html-----htmlElement :: MarkdownParser String-htmlElement = rawVerbatimBlock-          <|> strictHtmlBlock-          <|> liftM snd (htmlTag isBlockTag)--htmlBlock :: MarkdownParser (F Blocks)-htmlBlock = do-  guardEnabled Ext_raw_html-  try (do-      (TagOpen t attrs) <- lookAhead $ fst <$> htmlTag isBlockTag-      (guard (t `elem` ["pre","style","script"]) >>-          (return . B.rawBlock "html") <$> rawVerbatimBlock)-        <|> (do guardEnabled Ext_markdown_attribute-                oldMarkdownAttribute <- stateMarkdownAttribute <$> getState-                markdownAttribute <--                   case lookup "markdown" attrs of-                        Just "0" -> False <$ updateState (\st -> st{-                                       stateMarkdownAttribute = False })-                        Just _   -> True <$ updateState (\st -> st{-                                       stateMarkdownAttribute = True })-                        Nothing  -> return oldMarkdownAttribute-                res <- if markdownAttribute-                          then rawHtmlBlocks-                          else htmlBlock'-                updateState $ \st -> st{ stateMarkdownAttribute =-                                         oldMarkdownAttribute }-                return res)-        <|> (guardEnabled Ext_markdown_in_html_blocks >> rawHtmlBlocks))-    <|> htmlBlock'--htmlBlock' :: MarkdownParser (F Blocks)-htmlBlock' = try $ do-    first <- htmlElement-    skipMany spaceChar-    optional blanklines-    return $ return $ B.rawBlock "html" first--strictHtmlBlock :: MarkdownParser String-strictHtmlBlock = htmlInBalanced (not . isInlineTag)--rawVerbatimBlock :: MarkdownParser String-rawVerbatimBlock = htmlInBalanced isVerbTag-  where isVerbTag (TagOpen "pre" _)    = True-        isVerbTag (TagOpen "style" _)  = True-        isVerbTag (TagOpen "script" _) = True-        isVerbTag _                    = False--rawTeXBlock :: MarkdownParser (F Blocks)-rawTeXBlock = do-  guardEnabled Ext_raw_tex-  result <- (B.rawBlock "latex" . concat <$>-                  rawLaTeXBlock `sepEndBy1` blankline)-        <|> (B.rawBlock "context" . concat <$>-                  rawConTeXtEnvironment `sepEndBy1` blankline)-  spaces-  return $ return result--rawHtmlBlocks :: MarkdownParser (F Blocks)-rawHtmlBlocks = do-  (TagOpen tagtype _, raw) <- htmlTag isBlockTag-  -- try to find closing tag-  -- we set stateInHtmlBlock so that closing tags that can be either block or-  -- inline will not be parsed as inline tags-  oldInHtmlBlock <- stateInHtmlBlock <$> getState-  updateState $ \st -> st{ stateInHtmlBlock = Just tagtype }-  let closer = htmlTag (\x -> x ~== TagClose tagtype)-  contents <- mconcat <$> many (notFollowedBy' closer >> block)-  result <--    (closer >>= \(_, rawcloser) -> return (-                return (B.rawBlock "html" $ stripMarkdownAttribute raw) <>-                contents <>-                return (B.rawBlock "html" rawcloser)))-      <|> return (return (B.rawBlock "html" raw) <> contents)-  updateState $ \st -> st{ stateInHtmlBlock = oldInHtmlBlock }-  return result---- remove markdown="1" attribute-stripMarkdownAttribute :: String -> String-stripMarkdownAttribute s = renderTags' $ map filterAttrib $ parseTags s-  where filterAttrib (TagOpen t as) = TagOpen t-                                        [(k,v) | (k,v) <- as, k /= "markdown"]-        filterAttrib              x = x------- line block-----lineBlock :: MarkdownParser (F Blocks)-lineBlock = try $ do-  guardEnabled Ext_line_blocks-  lines' <- lineBlockLines >>=-            mapM (parseFromString (trimInlinesF . mconcat <$> many inline))-  return $ B.lineBlock <$> sequence lines'------- Tables------- Parse a dashed line with optional trailing spaces; return its length--- and the length including trailing space.-dashedLine :: Char-           -> Parser [Char] st (Int, Int)-dashedLine ch = do-  dashes <- many1 (char ch)-  sp     <- many spaceChar-  let lengthDashes = length dashes-      lengthSp     = length sp-  return (lengthDashes, lengthDashes + lengthSp)---- Parse a table header with dashed lines of '-' preceded by--- one (or zero) line of text.-simpleTableHeader :: Bool  -- ^ Headerless table-                  -> MarkdownParser (F [Blocks], [Alignment], [Int])-simpleTableHeader headless = try $ do-  rawContent  <- if headless-                    then return ""-                    else anyLine-  initSp      <- nonindentSpaces-  dashes      <- many1 (dashedLine '-')-  newline-  let (lengths, lines') = unzip dashes-  let indices  = scanl (+) (length initSp) lines'-  -- If no header, calculate alignment on basis of first row of text-  rawHeads <- liftM (tail . splitStringByIndices (init indices)) $-              if headless-                 then lookAhead anyLine-                 else return rawContent-  let aligns   = zipWith alignType (map (\a -> [a]) rawHeads) lengths-  let rawHeads' = if headless-                     then replicate (length dashes) ""-                     else rawHeads-  heads <- fmap sequence-           $ mapM (parseFromString (mconcat <$> many plain))-           $ map trim rawHeads'-  return (heads, aligns, indices)---- Returns an alignment type for a table, based on a list of strings--- (the rows of the column header) and a number (the length of the--- dashed line under the rows.-alignType :: [String]-          -> Int-          -> Alignment-alignType [] _ = AlignDefault-alignType strLst len =-  let nonempties = filter (not . null) $ map trimr strLst-      (leftSpace, rightSpace) =-           case sortBy (comparing length) nonempties of-                 (x:_)  -> (head x `elem` " \t", length x < len)-                 []     -> (False, False)-  in  case (leftSpace, rightSpace) of-        (True,  False)   -> AlignRight-        (False, True)    -> AlignLeft-        (True,  True)    -> AlignCenter-        (False, False)   -> AlignDefault---- Parse a table footer - dashed lines followed by blank line.-tableFooter :: MarkdownParser String-tableFooter = try $ skipNonindentSpaces >> many1 (dashedLine '-') >> blanklines---- Parse a table separator - dashed line.-tableSep :: MarkdownParser Char-tableSep = try $ skipNonindentSpaces >> many1 (dashedLine '-') >> char '\n'---- Parse a raw line and split it into chunks by indices.-rawTableLine :: [Int]-             -> MarkdownParser [String]-rawTableLine indices = do-  notFollowedBy' (blanklines <|> tableFooter)-  line <- many1Till anyChar newline-  return $ map trim $ tail $-           splitStringByIndices (init indices) line---- Parse a table line and return a list of lists of blocks (columns).-tableLine :: [Int]-          -> MarkdownParser (F [Blocks])-tableLine indices = rawTableLine indices >>=-  fmap sequence . mapM (parseFromString (mconcat <$> many plain))---- Parse a multiline table row and return a list of blocks (columns).-multilineRow :: [Int]-             -> MarkdownParser (F [Blocks])-multilineRow indices = do-  colLines <- many1 (rawTableLine indices)-  let cols = map unlines $ transpose colLines-  fmap sequence $ mapM (parseFromString (mconcat <$> many plain)) cols---- Parses a table caption:  inlines beginning with 'Table:'--- and followed by blank lines.-tableCaption :: MarkdownParser (F Inlines)-tableCaption = try $ do-  guardEnabled Ext_table_captions-  skipNonindentSpaces-  string ":" <|> string "Table:"-  trimInlinesF . mconcat <$> many1 inline <* blanklines---- Parse a simple table with '---' header and one line per row.-simpleTable :: Bool  -- ^ Headerless table-            -> MarkdownParser ([Alignment], [Double], F [Blocks], F [[Blocks]])-simpleTable headless = do-  (aligns, _widths, heads', lines') <--       tableWith (simpleTableHeader headless) tableLine-              (return ())-              (if headless then tableFooter else tableFooter <|> blanklines)-  -- Simple tables get 0s for relative column widths (i.e., use default)-  return (aligns, replicate (length aligns) 0, heads', lines')---- Parse a multiline table:  starts with row of '-' on top, then header--- (which may be multiline), then the rows,--- which may be multiline, separated by blank lines, and--- ending with a footer (dashed line followed by blank line).-multilineTable :: Bool -- ^ Headerless table-               -> MarkdownParser ([Alignment], [Double], F [Blocks], F [[Blocks]])-multilineTable headless =-  tableWith (multilineTableHeader headless) multilineRow blanklines tableFooter--multilineTableHeader :: Bool -- ^ Headerless table-                     -> MarkdownParser (F [Blocks], [Alignment], [Int])-multilineTableHeader headless = try $ do-  unless headless $-     tableSep >> notFollowedBy blankline-  rawContent  <- if headless-                    then return $ repeat ""-                    else many1 $ notFollowedBy tableSep >> anyLine-  initSp      <- nonindentSpaces-  dashes      <- many1 (dashedLine '-')-  newline-  let (lengths, lines') = unzip dashes-  let indices  = scanl (+) (length initSp) lines'-  rawHeadsList <- if headless-                     then liftM (map (:[]) . tail .-                              splitStringByIndices (init indices)) $ lookAhead anyLine-                     else return $ transpose $ map-                           (tail . splitStringByIndices (init indices))-                           rawContent-  let aligns   = zipWith alignType rawHeadsList lengths-  let rawHeads = if headless-                    then replicate (length dashes) ""-                    else map (unlines . map trim) rawHeadsList-  heads <- fmap sequence $-           mapM (parseFromString (mconcat <$> many plain)) $-             map trim rawHeads-  return (heads, aligns, indices)---- Parse a grid table:  starts with row of '-' on top, then header--- (which may be grid), then the rows,--- which may be grid, separated by blank lines, and--- ending with a footer (dashed line followed by blank line).-gridTable :: Bool -- ^ Headerless table-          -> MarkdownParser ([Alignment], [Double], F [Blocks], F [[Blocks]])-gridTable headless =-  tableWith (gridTableHeader headless) gridTableRow-            (gridTableSep '-') gridTableFooter--gridTableSplitLine :: [Int] -> String -> [String]-gridTableSplitLine indices line = map removeFinalBar $ tail $-  splitStringByIndices (init indices) $ trimr line--gridPart :: Char -> Parser [Char] st ((Int, Int), Alignment)-gridPart ch = do-  leftColon <- option False (True <$ char ':')-  dashes <- many1 (char ch)-  rightColon <- option False (True <$ char ':')-  char '+'-  let lengthDashes = length dashes + (if leftColon then 1 else 0) +-                       (if rightColon then 1 else 0)-  let alignment = case (leftColon, rightColon) of-                       (True, True)   -> AlignCenter-                       (True, False)  -> AlignLeft-                       (False, True)  -> AlignRight-                       (False, False) -> AlignDefault-  return ((lengthDashes, lengthDashes + 1), alignment)--gridDashedLines :: Char -> Parser [Char] st [((Int, Int), Alignment)]-gridDashedLines ch = try $ char '+' >> many1 (gridPart ch) <* blankline--removeFinalBar :: String -> String-removeFinalBar =-  reverse . dropWhile (`elem` " \t") . dropWhile (=='|') . reverse---- | Separator between rows of grid table.-gridTableSep :: Char -> MarkdownParser Char-gridTableSep ch = try $ gridDashedLines ch >> return '\n'---- | Parse header for a grid table.-gridTableHeader :: Bool -- ^ Headerless table-                -> MarkdownParser (F [Blocks], [Alignment], [Int])-gridTableHeader headless = try $ do-  optional blanklines-  dashes <- gridDashedLines '-'-  rawContent  <- if headless-                    then return []-                    else many1 (try (char '|' >> anyLine))-  underDashes <- if headless-                    then return dashes-                    else gridDashedLines '='-  guard $ length dashes == length underDashes-  let lines'   = map (snd . fst) underDashes-  let indices  = scanl (+) 0 lines'-  let aligns   = map snd underDashes-  let rawHeads = if headless-                    then replicate (length underDashes) ""-                    else map (unlines . map trim) $ transpose-                       $ map (gridTableSplitLine indices) rawContent-  heads <- fmap sequence $ mapM (parseFromString parseBlocks . trim) rawHeads-  return (heads, aligns, indices)--gridTableRawLine :: [Int] -> MarkdownParser [String]-gridTableRawLine indices = do-  char '|'-  line <- anyLine-  return (gridTableSplitLine indices line)---- | Parse row of grid table.-gridTableRow :: [Int]-             -> MarkdownParser (F [Blocks])-gridTableRow indices = do-  colLines <- many1 (gridTableRawLine indices)-  let cols = map ((++ "\n") . unlines . removeOneLeadingSpace) $-               transpose colLines-  fmap compactify' <$> fmap sequence (mapM (parseFromString parseBlocks) cols)--removeOneLeadingSpace :: [String] -> [String]-removeOneLeadingSpace xs =-  if all startsWithSpace xs-     then map (drop 1) xs-     else xs-   where startsWithSpace ""     = True-         startsWithSpace (y:_) = y == ' '---- | Parse footer for a grid table.-gridTableFooter :: MarkdownParser [Char]-gridTableFooter = blanklines--pipeBreak :: MarkdownParser ([Alignment], [Int])-pipeBreak = try $ do-  nonindentSpaces-  openPipe <- (True <$ char '|') <|> return False-  first <- pipeTableHeaderPart-  rest <- many $ sepPipe *> pipeTableHeaderPart-  -- surrounding pipes needed for a one-column table:-  guard $ not (null rest && not openPipe)-  optional (char '|')-  blankline-  return $ unzip (first:rest)--pipeTable :: MarkdownParser ([Alignment], [Double], F [Blocks], F [[Blocks]])-pipeTable = try $ do-  nonindentSpaces-  lookAhead nonspaceChar-  (heads,(aligns, seplengths)) <- (,) <$> pipeTableRow <*> pipeBreak-  let heads' = take (length aligns) <$> heads-  lines' <- many pipeTableRow-  let lines'' = map (take (length aligns) <$>) lines'-  let maxlength = maximum $-       map (\x -> length . stringify $ runF x def) (heads' : lines'')-  numColumns <- getOption readerColumns-  let widths = if maxlength > numColumns-                  then map (\len ->-                           fromIntegral (len + 1) / fromIntegral numColumns)-                             seplengths-                  else replicate (length aligns) 0.0-  return $ (aligns, widths, heads', sequence lines'')--sepPipe :: MarkdownParser ()-sepPipe = try $ do-  char '|' <|> char '+'-  notFollowedBy blankline---- parse a row, also returning probable alignments for org-table cells-pipeTableRow :: MarkdownParser (F [Blocks])-pipeTableRow = try $ do-  scanForPipe-  skipMany spaceChar-  openPipe <- (True <$ char '|') <|> return False-  -- split into cells-  let chunk = void (code <|> rawHtmlInline <|> escapedChar <|> rawLaTeXInline')-       <|> void (noneOf "|\n\r")-  let cellContents = ((trim . snd) <$> withRaw (many chunk)) >>=-        parseFromString pipeTableCell-  cells <- cellContents `sepEndBy1` (char '|')-  -- surrounding pipes needed for a one-column table:-  guard $ not (length cells == 1 && not openPipe)-  blankline-  return $ sequence cells--pipeTableCell :: MarkdownParser (F Blocks)-pipeTableCell = do-  result <- many inline-  if null result-     then return mempty-     else return $ B.plain . mconcat <$> sequence result--pipeTableHeaderPart :: Parser [Char] st (Alignment, Int)-pipeTableHeaderPart = try $ do-  skipMany spaceChar-  left <- optionMaybe (char ':')-  pipe <- many1 (char '-')-  right <- optionMaybe (char ':')-  skipMany spaceChar-  let len = length pipe + maybe 0 (const 1) left + maybe 0 (const 1) right-  return $-    ((case (left,right) of-       (Nothing,Nothing) -> AlignDefault-       (Just _,Nothing)  -> AlignLeft-       (Nothing,Just _)  -> AlignRight-       (Just _,Just _)   -> AlignCenter), len)---- Succeed only if current line contains a pipe.-scanForPipe :: Parser [Char] st ()-scanForPipe = do-  inp <- getInput-  case break (\c -> c == '\n' || c == '|') inp of-       (_,'|':_) -> return ()-       _         -> mzero---- | Parse a table using 'headerParser', 'rowParser',--- 'lineParser', and 'footerParser'.  Variant of the version in--- Text.Pandoc.Parsing.-tableWith :: MarkdownParser (F [Blocks], [Alignment], [Int])-          -> ([Int] -> MarkdownParser (F [Blocks]))-          -> MarkdownParser sep-          -> MarkdownParser end-          -> MarkdownParser ([Alignment], [Double], F [Blocks], F [[Blocks]])-tableWith headerParser rowParser lineParser footerParser = try $ do-    (heads, aligns, indices) <- headerParser-    lines' <- fmap sequence $ rowParser indices `sepEndBy1` lineParser-    footerParser-    numColumns <- getOption readerColumns-    let widths = if (indices == [])-                    then replicate (length aligns) 0.0-                    else widthsFromIndices numColumns indices-    return $ (aligns, widths, heads, lines')--table :: MarkdownParser (F Blocks)-table = try $ do-  frontCaption <- option Nothing (Just <$> tableCaption)-  (aligns, widths, heads, lns) <--         try (guardEnabled Ext_pipe_tables >> scanForPipe >> pipeTable) <|>-         try (guardEnabled Ext_multiline_tables >>-                multilineTable False) <|>-         try (guardEnabled Ext_simple_tables >>-                (simpleTable True <|> simpleTable False)) <|>-         try (guardEnabled Ext_multiline_tables >>-                multilineTable True) <|>-         try (guardEnabled Ext_grid_tables >>-                (gridTable False <|> gridTable True)) <?> "table"-  optional blanklines-  caption <- case frontCaption of-                  Nothing  -> option (return mempty) tableCaption-                  Just c   -> return c-  -- renormalize widths if greater than 100%:-  let totalWidth = sum widths-  let widths' = if totalWidth < 1-                   then widths-                   else map (/ totalWidth) widths-  return $ do-    caption' <- caption-    heads' <- heads-    lns' <- lns-    return $ B.table caption' (zip aligns widths') heads' lns'------- inline-----inline :: MarkdownParser (F Inlines)-inline = choice [ whitespace-                , bareURL-                , str-                , endline-                , code-                , strongOrEmph-                , note-                , cite-                , bracketedSpan-                , link-                , image-                , math-                , strikeout-                , subscript-                , superscript-                , inlineNote  -- after superscript because of ^[link](/foo)^-                , autoLink-                , spanHtml-                , rawHtmlInline-                , escapedChar-                , rawLaTeXInline'-                , exampleRef-                , smart-                , return . B.singleton <$> charRef-                , emoji-                , symbol-                , ltSign-                ] <?> "inline"--escapedChar' :: MarkdownParser Char-escapedChar' = try $ do-  char '\\'-  (guardEnabled Ext_all_symbols_escapable >> satisfy (not . isAlphaNum))-     <|> (guardEnabled Ext_angle_brackets_escapable >>-            oneOf "\\`*_{}[]()>#+-.!~\"<>")-     <|> (guardEnabled Ext_escaped_line_breaks >> char '\n')-     <|> oneOf "\\`*_{}[]()>#+-.!~\""--escapedChar :: MarkdownParser (F Inlines)-escapedChar = do-  result <- escapedChar'-  case result of-       ' '   -> return $ return $ B.str "\160" -- "\ " is a nonbreaking space-       '\n'  -> guardEnabled Ext_escaped_line_breaks >>-                return (return B.linebreak)  -- "\[newline]" is a linebreak-       _     -> return $ return $ B.str [result]--ltSign :: MarkdownParser (F Inlines)-ltSign = do-  guardDisabled Ext_raw_html-    <|> (notFollowedByHtmlCloser >> notFollowedBy' (htmlTag isBlockTag))-  char '<'-  return $ return $ B.str "<"--exampleRef :: MarkdownParser (F Inlines)-exampleRef = try $ do-  guardEnabled Ext_example_lists-  char '@'-  lab <- many1 (alphaNum <|> oneOf "-_")-  return $ do-    st <- askF-    return $ case M.lookup lab (stateExamples st) of-                  Just n    -> B.str (show n)-                  Nothing   -> B.str ('@':lab)--symbol :: MarkdownParser (F Inlines)-symbol = do-  result <- noneOf "<\\\n\t "-         <|> try (do lookAhead $ char '\\'-                     notFollowedBy' (() <$ rawTeXBlock)-                     char '\\')-  return $ return $ B.str [result]---- parses inline code, between n `s and n `s-code :: MarkdownParser (F Inlines)-code = try $ do-  starts <- many1 (char '`')-  skipSpaces-  result <- many1Till (many1 (noneOf "`\n") <|> many1 (char '`') <|>-                       (char '\n' >> notFollowedBy' blankline >> return " "))-                      (try (skipSpaces >> count (length starts) (char '`') >>-                      notFollowedBy (char '`')))-  attr <- option ([],[],[]) (try $ guardEnabled Ext_inline_code_attributes-                                   >> attributes)-  return $ return $ B.codeWith attr $ trim $ concat result--math :: MarkdownParser (F Inlines)-math =  (return . B.displayMath <$> (mathDisplay >>= applyMacros'))-     <|> (return . B.math <$> (mathInline >>= applyMacros')) <+?>-               ((getOption readerSmart >>= guard) *> (return <$> apostrophe)-                <* notFollowedBy (space <|> satisfy isPunctuation))---- Parses material enclosed in *s, **s, _s, or __s.--- Designed to avoid backtracking.-enclosure :: Char-          -> MarkdownParser (F Inlines)-enclosure c = do-  -- we can't start an enclosure with _ if after a string and-  -- the intraword_underscores extension is enabled:-  guardDisabled Ext_intraword_underscores-    <|> guard (c == '*')-    <|> (guard =<< notAfterString)-  cs <- many1 (char c)-  (return (B.str cs) <>) <$> whitespace-    <|> do-        case length cs of-             3  -> three c-             2  -> two   c mempty-             1  -> one   c mempty-             _  -> return (return $ B.str cs)--ender :: Char -> Int -> MarkdownParser ()-ender c n = try $ do-  count n (char c)-  guard (c == '*')-    <|> guardDisabled Ext_intraword_underscores-    <|> notFollowedBy alphaNum---- Parse inlines til you hit one c or a sequence of two cs.--- If one c, emit emph and then parse two.--- If two cs, emit strong and then parse one.--- Otherwise, emit ccc then the results.-three :: Char -> MarkdownParser (F Inlines)-three c = do-  contents <- mconcat <$> many (notFollowedBy (ender c 1) >> inline)-  (ender c 3 >> return ((B.strong . B.emph) <$> contents))-    <|> (ender c 2 >> one c (B.strong <$> contents))-    <|> (ender c 1 >> two c (B.emph <$> contents))-    <|> return (return (B.str [c,c,c]) <> contents)---- Parse inlines til you hit two c's, and emit strong.--- If you never do hit two cs, emit ** plus inlines parsed.-two :: Char -> F Inlines -> MarkdownParser (F Inlines)-two c prefix' = do-  contents <- mconcat <$> many (try $ notFollowedBy (ender c 2) >> inline)-  (ender c 2 >> return (B.strong <$> (prefix' <> contents)))-    <|> return (return (B.str [c,c]) <> (prefix' <> contents))---- Parse inlines til you hit a c, and emit emph.--- If you never hit a c, emit * plus inlines parsed.-one :: Char -> F Inlines -> MarkdownParser (F Inlines)-one c prefix' = do-  contents <- mconcat <$> many (  (notFollowedBy (ender c 1) >> inline)-                           <|> try (string [c,c] >>-                                    notFollowedBy (ender c 1) >>-                                    two c mempty) )-  (ender c 1 >> return (B.emph <$> (prefix' <> contents)))-    <|> return (return (B.str [c]) <> (prefix' <> contents))--strongOrEmph :: MarkdownParser (F Inlines)-strongOrEmph =  enclosure '*' <|> enclosure '_'---- | Parses a list of inlines between start and end delimiters.-inlinesBetween :: (Show b)-               => MarkdownParser a-               -> MarkdownParser b-               -> MarkdownParser (F Inlines)-inlinesBetween start end =-  (trimInlinesF . mconcat) <$> try (start >> many1Till inner end)-    where inner      = innerSpace <|> (notFollowedBy' (() <$ whitespace) >> inline)-          innerSpace = try $ whitespace <* notFollowedBy' end--strikeout :: MarkdownParser (F Inlines)-strikeout = fmap B.strikeout <$>- (guardEnabled Ext_strikeout >> inlinesBetween strikeStart strikeEnd)-    where strikeStart = string "~~" >> lookAhead nonspaceChar-                        >> notFollowedBy (char '~')-          strikeEnd   = try $ string "~~"--superscript :: MarkdownParser (F Inlines)-superscript = fmap B.superscript <$> try (do-  guardEnabled Ext_superscript-  char '^'-  mconcat <$> many1Till (notFollowedBy spaceChar >> inline) (char '^'))--subscript :: MarkdownParser (F Inlines)-subscript = fmap B.subscript <$> try (do-  guardEnabled Ext_subscript-  char '~'-  mconcat <$> many1Till (notFollowedBy spaceChar >> inline) (char '~'))--whitespace :: MarkdownParser (F Inlines)-whitespace = spaceChar >> return <$> (lb <|> regsp) <?> "whitespace"-  where lb = spaceChar >> skipMany spaceChar >> option B.space (endline >> return B.linebreak)-        regsp = skipMany spaceChar >> return B.space--nonEndline :: Parser [Char] st Char-nonEndline = satisfy (/='\n')--str :: MarkdownParser (F Inlines)-str = do-  result <- many1 alphaNum-  updateLastStrPos-  let spacesToNbr = map (\c -> if c == ' ' then '\160' else c)-  isSmart <- getOption readerSmart-  if isSmart-     then case likelyAbbrev result of-               []        -> return $ return $ B.str result-               xs        -> choice (map (\x ->-                               try (string x >> oneOf " \n" >>-                                    lookAhead alphaNum >>-                                    return (return $ B.str-                                                  $ result ++ spacesToNbr x ++ "\160"))) xs)-                           <|> (return $ return $ B.str result)-     else return $ return $ B.str result---- | if the string matches the beginning of an abbreviation (before--- the first period, return strings that would finish the abbreviation.-likelyAbbrev :: String -> [String]-likelyAbbrev x =-  let abbrevs = [ "Mr.", "Mrs.", "Ms.", "Capt.", "Dr.", "Prof.",-                  "Gen.", "Gov.", "e.g.", "i.e.", "Sgt.", "St.",-                  "vol.", "vs.", "Sen.", "Rep.", "Pres.", "Hon.",-                  "Rev.", "Ph.D.", "M.D.", "M.A.", "p.", "pp.",-                  "ch.", "sec.", "cf.", "cp."]-      abbrPairs = map (break (=='.')) abbrevs-  in  map snd $ filter (\(y,_) -> y == x) abbrPairs---- an endline character that can be treated as a space, not a structural break-endline :: MarkdownParser (F Inlines)-endline = try $ do-  newline-  notFollowedBy blankline-  -- parse potential list-starts differently if in a list:-  notFollowedBy (inList >> listStart)-  guardDisabled Ext_lists_without_preceding_blankline <|> notFollowedBy listStart-  guardEnabled Ext_blank_before_blockquote <|> notFollowedBy emailBlockQuoteStart-  guardEnabled Ext_blank_before_header <|> (notFollowedBy . char =<< atxChar) -- atx header-  guardDisabled Ext_backtick_code_blocks <|>-     notFollowedBy (() <$ (lookAhead (char '`') >> codeBlockFenced))-  notFollowedByHtmlCloser-  (eof >> return mempty)-    <|> (guardEnabled Ext_hard_line_breaks >> return (return B.linebreak))-    <|> (guardEnabled Ext_ignore_line_breaks >> return mempty)-    <|> (skipMany spaceChar >> return (return B.softbreak))------- links------- a reference label for a link-reference :: MarkdownParser (F Inlines, String)-reference = do notFollowedBy' (string "[^")   -- footnote reference-               withRaw $ trimInlinesF <$> inlinesInBalancedBrackets--parenthesizedChars :: MarkdownParser [Char]-parenthesizedChars = do-  result <- charsInBalanced '(' ')' litChar-  return $ '(' : result ++ ")"---- source for a link, with optional title-source :: MarkdownParser (String, String)-source = do-  char '('-  skipSpaces-  let urlChunk =-            try parenthesizedChars-        <|> (notFollowedBy (oneOf " )") >> (count 1 litChar))-        <|> try (many1 spaceChar <* notFollowedBy (oneOf "\"')"))-  let sourceURL = (unwords . words . concat) <$> many urlChunk-  let betweenAngles = try $-         char '<' >> manyTill litChar (char '>')-  src <- try betweenAngles <|> sourceURL-  tit <- option "" $ try $ spnl >> linkTitle-  skipSpaces-  char ')'-  return (escapeURI $ trimr src, tit)--linkTitle :: MarkdownParser String-linkTitle = quotedTitle '"' <|> quotedTitle '\''--link :: MarkdownParser (F Inlines)-link = try $ do-  st <- getState-  guard $ stateAllowLinks st-  setState $ st{ stateAllowLinks = False }-  (lab,raw) <- reference-  setState $ st{ stateAllowLinks = True }-  regLink B.linkWith lab <|> referenceLink B.linkWith (lab,raw)--bracketedSpan :: MarkdownParser (F Inlines)-bracketedSpan = try $ do-  guardEnabled Ext_bracketed_spans-  (lab,_) <- reference-  attr <- attributes-  let (ident,classes,keyvals) = attr-  case lookup "style" keyvals of-       Just s | null ident && null classes &&-            map toLower (filter (`notElem` " \t;") s) ==-                 "font-variant:small-caps"-         -> return $ B.smallcaps <$> lab-       _ -> return $ B.spanWith attr <$> lab--regLink :: (Attr -> String -> String -> Inlines -> Inlines)-        -> F Inlines -> MarkdownParser (F Inlines)-regLink constructor lab = try $ do-  (src, tit) <- source-  attr <- option nullAttr $-          guardEnabled Ext_link_attributes >> attributes-  return $ constructor attr src tit <$> lab---- a link like [this][ref] or [this][] or [this]-referenceLink :: (Attr -> String -> String -> Inlines -> Inlines)-              -> (F Inlines, String) -> MarkdownParser (F Inlines)-referenceLink constructor (lab, raw) = do-  sp <- (True <$ lookAhead (char ' ')) <|> return False-  (_,raw') <- option (mempty, "") $-      lookAhead (try (guardEnabled Ext_citations >>-                      spnl >> normalCite >> return (mempty, "")))-      <|>-      try (spnl >> reference)-  when (raw' == "") $ guardEnabled Ext_shortcut_reference_links-  let labIsRef = raw' == "" || raw' == "[]"-  let key = toKey $ if labIsRef then raw else raw'-  parsedRaw <- parseFromString (mconcat <$> many inline) raw'-  fallback  <- parseFromString (mconcat <$> many inline) $ dropBrackets raw-  implicitHeaderRefs <- option False $-                         True <$ guardEnabled Ext_implicit_header_references-  let makeFallback = do-       parsedRaw' <- parsedRaw-       fallback' <- fallback-       return $ B.str "[" <> fallback' <> B.str "]" <>-                (if sp && not (null raw) then B.space else mempty) <>-                parsedRaw'-  return $ do-    keys <- asksF stateKeys-    case M.lookup key keys of-       Nothing        ->-         if implicitHeaderRefs-            then do-              headerKeys <- asksF stateHeaderKeys-              case M.lookup key headerKeys of-                   Just ((src, tit), _) -> constructor nullAttr src tit <$> lab-                   Nothing              -> makeFallback-            else makeFallback-       Just ((src,tit), attr) -> constructor attr src tit <$> lab--dropBrackets :: String -> String-dropBrackets = reverse . dropRB . reverse . dropLB-  where dropRB (']':xs) = xs-        dropRB xs = xs-        dropLB ('[':xs) = xs-        dropLB xs = xs--bareURL :: MarkdownParser (F Inlines)-bareURL = try $ do-  guardEnabled Ext_autolink_bare_uris-  getState >>= guard . stateAllowLinks-  (orig, src) <- uri <|> emailAddress-  notFollowedBy $ try $ spaces >> htmlTag (~== TagClose "a")-  return $ return $ B.link src "" (B.str orig)--autoLink :: MarkdownParser (F Inlines)-autoLink = try $ do-  getState >>= guard . stateAllowLinks-  char '<'-  (orig, src) <- uri <|> emailAddress-  -- in rare cases, something may remain after the uri parser-  -- is finished, because the uri parser tries to avoid parsing-  -- final punctuation.  for example:  in `<http://hi---there>`,-  -- the URI parser will stop before the dashes.-  extra <- fromEntities <$> manyTill nonspaceChar (char '>')-  attr  <- option nullAttr $ try $-            guardEnabled Ext_link_attributes >> attributes-  return $ return $ B.linkWith attr (src ++ escapeURI extra) "" (B.str $ orig ++ extra)--image :: MarkdownParser (F Inlines)-image = try $ do-  char '!'-  (lab,raw) <- reference-  defaultExt <- getOption readerDefaultImageExtension-  let constructor attr' src = case takeExtension src of-                          "" -> B.imageWith attr' (addExtension src defaultExt)-                          _  -> B.imageWith attr' src-  regLink constructor lab <|> referenceLink constructor (lab,raw)--note :: MarkdownParser (F Inlines)-note = try $ do-  guardEnabled Ext_footnotes-  ref <- noteMarker-  return $ do-    notes <- asksF stateNotes'-    case lookup ref notes of-        Nothing       -> return $ B.str $ "[^" ++ ref ++ "]"-        Just contents -> do-          st <- askF-          -- process the note in a context that doesn't resolve-          -- notes, to avoid infinite looping with notes inside-          -- notes:-          let contents' = runF contents st{ stateNotes' = [] }-          return $ B.note contents'--inlineNote :: MarkdownParser (F Inlines)-inlineNote = try $ do-  guardEnabled Ext_inline_notes-  char '^'-  contents <- inlinesInBalancedBrackets-  return $ B.note . B.para <$> contents--rawLaTeXInline' :: MarkdownParser (F Inlines)-rawLaTeXInline' = try $ do-  guardEnabled Ext_raw_tex-  lookAhead $ char '\\' >> notFollowedBy' (string "start") -- context env-  RawInline _ s <- rawLaTeXInline-  return $ return $ B.rawInline "tex" s-  -- "tex" because it might be context or latex--rawConTeXtEnvironment :: Parser [Char] st String-rawConTeXtEnvironment = try $ do-  string "\\start"-  completion <- inBrackets (letter <|> digit <|> spaceChar)-               <|> (many1 letter)-  contents <- manyTill (rawConTeXtEnvironment <|> (count 1 anyChar))-                       (try $ string "\\stop" >> string completion)-  return $ "\\start" ++ completion ++ concat contents ++ "\\stop" ++ completion--inBrackets :: (Parser [Char] st Char) -> Parser [Char] st String-inBrackets parser = do-  char '['-  contents <- many parser-  char ']'-  return $ "[" ++ contents ++ "]"--spanHtml :: MarkdownParser (F Inlines)-spanHtml = try $ do-  guardEnabled Ext_native_spans-  (TagOpen _ attrs, _) <- htmlTag (~== TagOpen "span" [])-  contents <- mconcat <$> manyTill inline (htmlTag (~== TagClose "span"))-  let ident = fromMaybe "" $ lookup "id" attrs-  let classes = maybe [] words $ lookup "class" attrs-  let keyvals = [(k,v) | (k,v) <- attrs, k /= "id" && k /= "class"]-  case lookup "style" keyvals of-       Just s | null ident && null classes &&-            map toLower (filter (`notElem` " \t;") s) ==-                 "font-variant:small-caps"-         -> return $ B.smallcaps <$> contents-       _ -> return $ B.spanWith (ident, classes, keyvals) <$> contents--divHtml :: MarkdownParser (F Blocks)-divHtml = try $ do-  guardEnabled Ext_native_divs-  (TagOpen _ attrs, rawtag) <- htmlTag (~== TagOpen "div" [])-  -- we set stateInHtmlBlock so that closing tags that can be either block or-  -- inline will not be parsed as inline tags-  oldInHtmlBlock <- stateInHtmlBlock <$> getState-  updateState $ \st -> st{ stateInHtmlBlock = Just "div" }-  bls <- option "" (blankline >> option "" blanklines)-  contents <- mconcat <$>-              many (notFollowedBy' (htmlTag (~== TagClose "div")) >> block)-  closed <- option False (True <$ htmlTag (~== TagClose "div"))-  if closed-     then do-       updateState $ \st -> st{ stateInHtmlBlock = oldInHtmlBlock }-       let ident = fromMaybe "" $ lookup "id" attrs-       let classes = maybe [] words $ lookup "class" attrs-       let keyvals = [(k,v) | (k,v) <- attrs, k /= "id" && k /= "class"]-       return $ B.divWith (ident, classes, keyvals) <$> contents-     else -- avoid backtracing-       return $ return (B.rawBlock "html" (rawtag <> bls)) <> contents--rawHtmlInline :: MarkdownParser (F Inlines)-rawHtmlInline = do-  guardEnabled Ext_raw_html-  inHtmlBlock <- stateInHtmlBlock <$> getState-  let isCloseBlockTag t = case inHtmlBlock of-                               Just t' -> t ~== TagClose t'-                               Nothing -> False-  mdInHtml <- option False $-                (    guardEnabled Ext_markdown_in_html_blocks-                 <|> guardEnabled Ext_markdown_attribute-                ) >> return True-  (_,result) <- htmlTag $ if mdInHtml-                             then (\x -> isInlineTag x &&-                                         not (isCloseBlockTag x))-                             else not . isTextTag-  return $ return $ B.rawInline "html" result---- Emoji--emojiChars :: [Char]-emojiChars = ['a'..'z'] ++ ['0'..'9'] ++ ['_','+','-']--emoji :: MarkdownParser (F Inlines)-emoji = try $ do-  guardEnabled Ext_emoji-  char ':'-  emojikey <- many1 (oneOf emojiChars)-  char ':'-  case M.lookup emojikey emojis of-       Just s  -> return (return (B.str s))-       Nothing -> mzero---- Citations--cite :: MarkdownParser (F Inlines)-cite = do-  guardEnabled Ext_citations-  citations <- textualCite-            <|> do (cs, raw) <- withRaw normalCite-                   return $ (flip B.cite (B.text raw)) <$> cs-  return citations--textualCite :: MarkdownParser (F Inlines)-textualCite = try $ do-  (_, key) <- citeKey-  let first = Citation{ citationId      = key-                      , citationPrefix  = []-                      , citationSuffix  = []-                      , citationMode    = AuthorInText-                      , citationNoteNum = 0-                      , citationHash    = 0-                      }-  mbrest <- option Nothing $ try $ spnl >> Just <$> withRaw normalCite-  case mbrest of-       Just (rest, raw) ->-         return $ (flip B.cite (B.text $ '@':key ++ " " ++ raw) . (first:))-               <$> rest-       Nothing   ->-         (do-          (cs, raw) <- withRaw $ bareloc first-          let (spaces',raw') = span isSpace raw-              spc | null spaces' = mempty-                  | otherwise    = B.space-          lab <- parseFromString (mconcat <$> many inline) $ dropBrackets raw'-          fallback <- referenceLink B.linkWith (lab,raw')-          return $ do-            fallback' <- fallback-            cs' <- cs-            return $-              case B.toList fallback' of-                Link{}:_ -> B.cite [first] (B.str $ '@':key) <> spc <> fallback'-                _        -> B.cite cs' (B.text $ '@':key ++ " " ++ raw))-         <|> return (do st <- askF-                        return $ case M.lookup key (stateExamples st) of-                                 Just n -> B.str (show n)-                                 _      -> B.cite [first] $ B.str $ '@':key)--bareloc :: Citation -> MarkdownParser (F [Citation])-bareloc c = try $ do-  spnl-  char '['-  notFollowedBy $ char '^'-  suff <- suffix-  rest <- option (return []) $ try $ char ';' >> citeList-  spnl-  char ']'-  notFollowedBy $ oneOf "[("-  return $ do-    suff' <- suff-    rest' <- rest-    return $ c{ citationSuffix = B.toList suff' } : rest'--normalCite :: MarkdownParser (F [Citation])-normalCite = try $ do-  char '['-  spnl-  citations <- citeList-  spnl-  char ']'-  return citations--suffix :: MarkdownParser (F Inlines)-suffix = try $ do-  hasSpace <- option False (notFollowedBy nonspaceChar >> return True)-  spnl-  rest <- trimInlinesF . mconcat <$> many (notFollowedBy (oneOf ";]") >> inline)-  return $ if hasSpace-              then (B.space <>) <$> rest-              else rest--prefix :: MarkdownParser (F Inlines)-prefix = trimInlinesF . mconcat <$>-  manyTill inline (char ']' <|> liftM (const ']') (lookAhead citeKey))--citeList :: MarkdownParser (F [Citation])-citeList = fmap sequence $ sepBy1 citation (try $ char ';' >> spnl)--citation :: MarkdownParser (F Citation)-citation = try $ do-  pref <- prefix-  (suppress_author, key) <- citeKey-  suff <- suffix-  return $ do-    x <- pref-    y <- suff-    return $ Citation{ citationId      = key-                     , citationPrefix  = B.toList x-                     , citationSuffix  = B.toList y-                     , citationMode    = if suppress_author-                                            then SuppressAuthor-                                            else NormalCitation-                     , citationNoteNum = 0-                     , citationHash    = 0-                     }--smart :: MarkdownParser (F Inlines)-smart = do-  getOption readerSmart >>= guard-  doubleQuoted <|> singleQuoted <|>-    choice (map (return <$>) [apostrophe, dash, ellipses])--singleQuoted :: MarkdownParser (F Inlines)-singleQuoted = try $ do-  singleQuoteStart-  withQuoteContext InSingleQuote $-    fmap B.singleQuoted . trimInlinesF . mconcat <$>-      many1Till inline singleQuoteEnd---- doubleQuoted will handle regular double-quoted sections, as well--- as dialogues with an open double-quote without a close double-quote--- in the same paragraph.-doubleQuoted :: MarkdownParser (F Inlines)+{-# LANGUAGE RelaxedPolyRec      #-}+{-# LANGUAGE ScopedTypeVariables #-}++{-+Copyright (C) 2006-2017 John MacFarlane <jgm@berkeley.edu>++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation; either version 2 of the License, or+(at your option) any later version.++This program is distributed in the hope that it will be useful,+but WITHOUT ANY WARRANTY; without even the implied warranty of+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+GNU General Public License for more details.++You should have received a copy of the GNU General Public License+along with this program; if not, write to the Free Software+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+-}++{- |+   Module      : Text.Pandoc.Readers.Markdown+   Copyright   : Copyright (C) 2006-2017 John MacFarlane+   License     : GNU GPL, version 2 or above++   Maintainer  : John MacFarlane <jgm@berkeley.edu>+   Stability   : alpha+   Portability : portable++Conversion of markdown-formatted plain text to 'Pandoc' document.+-}+module Text.Pandoc.Readers.Markdown ( readMarkdown ) where++import Control.Monad+import Control.Monad.Except (throwError)+import Data.Char (isAlphaNum, isPunctuation, isSpace, toLower)+import qualified Data.HashMap.Strict as H+import Data.List (findIndex, intercalate, sortBy, transpose)+import qualified Data.Map as M+import Data.Maybe+import Data.Monoid ((<>))+import Data.Ord (comparing)+import Data.Scientific (base10Exponent, coefficient)+import qualified Data.Set as Set+import Data.Text (Text)+import qualified Data.Text as T+import qualified Data.Vector as V+import Data.Yaml (ParseException (..), YamlException (..), YamlMark (..))+import qualified Data.Yaml as Yaml+import System.FilePath (addExtension, takeExtension)+import Text.HTML.TagSoup+import Text.Pandoc.Builder (Blocks, Inlines)+import qualified Text.Pandoc.Builder as B+import Text.Pandoc.Class (PandocMonad (..), report)+import Text.Pandoc.Definition+import Text.Pandoc.Emoji (emojis)+import Text.Pandoc.Error+import Text.Pandoc.Logging+import Text.Pandoc.Options+import Text.Pandoc.Parsing hiding (tableWith)+import Text.Pandoc.Readers.HTML (htmlInBalanced, htmlTag, isBlockTag,+                                 isCommentTag, isInlineTag, isTextTag)+import Text.Pandoc.Readers.LaTeX (applyMacros, rawLaTeXBlock, rawLaTeXInline)+import Text.Pandoc.Shared+import qualified Text.Pandoc.UTF8 as UTF8+import Text.Pandoc.XML (fromEntities)++type MarkdownParser m = ParserT [Char] ParserState m++-- | Read markdown from an input string and return a Pandoc document.+readMarkdown :: PandocMonad m+             => ReaderOptions -- ^ Reader options+             -> Text      -- ^ String to parse (assuming @'\n'@ line endings)+             -> m Pandoc+readMarkdown opts s = do+  parsed <- readWithM parseMarkdown def{ stateOptions = opts }+               (T.unpack (crFilter s) ++ "\n\n")+  case parsed of+    Right result -> return result+    Left e       -> throwError e++--+-- Constants and data structure definitions+--++isBulletListMarker :: Char -> Bool+isBulletListMarker '*' = True+isBulletListMarker '+' = True+isBulletListMarker '-' = True+isBulletListMarker _   = False++isHruleChar :: Char -> Bool+isHruleChar '*' = True+isHruleChar '-' = True+isHruleChar '_' = True+isHruleChar _   = False++setextHChars :: String+setextHChars = "=-"++isBlank :: Char -> Bool+isBlank ' '  = True+isBlank '\t' = True+isBlank '\n' = True+isBlank _    = False++--+-- auxiliary functions+--++-- | Succeeds when we're in list context.+inList :: PandocMonad m => MarkdownParser m ()+inList = do+  ctx <- stateParserContext <$> getState+  guard (ctx == ListItemState)++spnl :: PandocMonad m => ParserT [Char] st m ()+spnl = try $ do+  skipSpaces+  optional newline+  skipSpaces+  notFollowedBy (char '\n')++indentSpaces :: PandocMonad m => MarkdownParser m String+indentSpaces = try $ do+  tabStop <- getOption readerTabStop+  count tabStop (char ' ') <|>+    string "\t" <?> "indentation"++nonindentSpaces :: PandocMonad m => MarkdownParser m String+nonindentSpaces = do+  n <- skipNonindentSpaces+  return $ replicate n ' '++-- returns number of spaces parsed+skipNonindentSpaces :: PandocMonad m => MarkdownParser m Int+skipNonindentSpaces = do+  tabStop <- getOption readerTabStop+  gobbleAtMostSpaces (tabStop - 1) <* notFollowedBy spaceChar++litChar :: PandocMonad m => MarkdownParser m Char+litChar = escapedChar'+       <|> characterReference+       <|> noneOf "\n"+       <|> try (newline >> notFollowedBy blankline >> return ' ')++-- | Parse a sequence of inline elements between square brackets,+-- including inlines between balanced pairs of square brackets.+inlinesInBalancedBrackets :: PandocMonad m => MarkdownParser m (F Inlines)+inlinesInBalancedBrackets = do+  char '['+  pos <- getPosition+  (_, raw) <- withRaw $ charsInBalancedBrackets 1+  guard $ not $ null raw+  parseFromString' (setPosition pos >>+                   trimInlinesF <$> inlines) (init raw)++charsInBalancedBrackets :: PandocMonad m => Int -> MarkdownParser m ()+charsInBalancedBrackets 0 = return ()+charsInBalancedBrackets openBrackets =+      (char '[' >> charsInBalancedBrackets (openBrackets + 1))+  <|> (char ']' >> charsInBalancedBrackets (openBrackets - 1))+  <|> ((  (() <$ code)+     <|> (() <$ escapedChar')+     <|> (newline >> notFollowedBy blankline)+     <|> skipMany1 (noneOf "[]`\n\\")+     <|> (() <$ count 1 (oneOf "`\\"))+      ) >> charsInBalancedBrackets openBrackets)++--+-- document structure+--++rawTitleBlockLine :: PandocMonad m => MarkdownParser m String+rawTitleBlockLine = do+  char '%'+  skipSpaces+  first <- anyLine+  rest <- many $ try $ do spaceChar+                          notFollowedBy blankline+                          skipSpaces+                          anyLine+  return $ trim $ unlines (first:rest)++titleLine :: PandocMonad m => MarkdownParser m (F Inlines)+titleLine = try $ do+  raw <- rawTitleBlockLine+  res <- parseFromString' inlines raw+  return $ trimInlinesF res++authorsLine :: PandocMonad m => MarkdownParser m (F [Inlines])+authorsLine = try $ do+  raw <- rawTitleBlockLine+  let sep = (char ';' <* spaces) <|> newline+  let pAuthors = sepEndBy+            (trimInlinesF . mconcat <$> many+                 (try $ notFollowedBy sep >> inline))+            sep+  sequence <$> parseFromString' pAuthors raw++dateLine :: PandocMonad m => MarkdownParser m (F Inlines)+dateLine = try $ do+  raw <- rawTitleBlockLine+  res <- parseFromString' inlines raw+  return $ trimInlinesF res++titleBlock :: PandocMonad m => MarkdownParser m ()+titleBlock = pandocTitleBlock <|> mmdTitleBlock++pandocTitleBlock :: PandocMonad m => MarkdownParser m ()+pandocTitleBlock = try $ do+  guardEnabled Ext_pandoc_title_block+  lookAhead (char '%')+  title <- option mempty titleLine+  author <- option (return []) authorsLine+  date <- option mempty dateLine+  optional blanklines+  let meta' = do title' <- title+                 author' <- author+                 date' <- date+                 return $+                     (if B.isNull title' then id else B.setMeta "title" title')+                   . (if null author' then id else B.setMeta "author" author')+                   . (if B.isNull date' then id else B.setMeta "date" date')+                   $ nullMeta+  updateState $ \st -> st{ stateMeta' = stateMeta' st <> meta' }+++yamlMetaBlock :: PandocMonad m => MarkdownParser m (F Blocks)+yamlMetaBlock = try $ do+  guardEnabled Ext_yaml_metadata_block+  pos <- getPosition+  string "---"+  blankline+  notFollowedBy blankline  -- if --- is followed by a blank it's an HRULE+  rawYamlLines <- manyTill anyLine stopLine+  -- by including --- and ..., we allow yaml blocks with just comments:+  let rawYaml = unlines ("---" : (rawYamlLines ++ ["..."]))+  optional blanklines+  case Yaml.decodeEither' $ UTF8.fromString rawYaml of+       Right (Yaml.Object hashmap) -> do+         let alist = H.toList hashmap+         mapM_ (\(k, v) ->+             if ignorable k+                then return ()+                else do+                  v' <- yamlToMeta v+                  let k' = T.unpack k+                  updateState $ \st -> st{ stateMeta' =+                     (do m <- stateMeta' st+                         -- if there's already a value, leave it unchanged+                         case lookupMeta k' m of+                              Just _ -> return m+                              Nothing -> do+                                v'' <- v'+                                return $ B.setMeta (T.unpack k) v'' m)}+           ) alist+       Right Yaml.Null -> return ()+       Right _ -> do+                   logMessage $+                      CouldNotParseYamlMetadata "not an object"+                      pos+                   return ()+       Left err' -> do+                case err' of+                   InvalidYaml (Just YamlParseException{+                               yamlProblem = problem+                             , yamlContext = _ctxt+                             , yamlProblemMark = Yaml.YamlMark {+                                   yamlLine = yline+                                 , yamlColumn = ycol+                             }}) ->+                        logMessage $ CouldNotParseYamlMetadata+                           problem (setSourceLine+                           (setSourceColumn pos+                              (sourceColumn pos + ycol))+                           (sourceLine pos + 1 + yline))+                   _ -> logMessage $ CouldNotParseYamlMetadata+                           (show err') pos+                return ()+  return mempty++-- ignore fields ending with _+ignorable :: Text -> Bool+ignorable t = (T.pack "_") `T.isSuffixOf` t++toMetaValue :: PandocMonad m+            => Text -> MarkdownParser m (F MetaValue)+toMetaValue x =+  parseFromString' parser' (T.unpack x)+  where parser' = (asInlines <$> ((trimInlinesF . mconcat)+                       <$> (guard (not endsWithNewline)+                             *> manyTill inline eof)))+                  <|> (asBlocks <$> parseBlocks)+        asBlocks p = do+          p' <- p+          return $ MetaBlocks (B.toList p')+        asInlines p = do+          p' <- p+          return $ MetaInlines (B.toList p')+        endsWithNewline = T.pack "\n" `T.isSuffixOf` x+        -- Note: a standard quoted or unquoted YAML value will+        -- not end in a newline, but a "block" set off with+        -- `|` or `>` will.++yamlToMeta :: PandocMonad m+           => Yaml.Value -> MarkdownParser m (F MetaValue)+yamlToMeta (Yaml.String t) = toMetaValue t+yamlToMeta (Yaml.Number n)+  -- avoid decimal points for numbers that don't need them:+  | base10Exponent n >= 0     = return $ return $ MetaString $ show+                                $ coefficient n * (10 ^ base10Exponent n)+  | otherwise                 = return $ return $ MetaString $ show n+yamlToMeta (Yaml.Bool b) = return $ return $ MetaBool b+yamlToMeta (Yaml.Array xs) = do+  xs' <- mapM yamlToMeta (V.toList xs)+  return $ do+    xs'' <- sequence xs'+    return $ B.toMetaValue xs''+yamlToMeta (Yaml.Object o) = do+  let alist = H.toList o+  foldM (\m (k,v) ->+           if ignorable k+              then return m+              else do+                v' <- yamlToMeta v+                return $ do+                   MetaMap m' <- m+                   v'' <- v'+                   return (MetaMap $ M.insert (T.unpack k) v'' m'))+        (return $ MetaMap M.empty)+        alist+yamlToMeta _ = return $ return $ MetaString ""++stopLine :: PandocMonad m => MarkdownParser m ()+stopLine = try $ (string "---" <|> string "...") >> blankline >> return ()++mmdTitleBlock :: PandocMonad m => MarkdownParser m ()+mmdTitleBlock = try $ do+  guardEnabled Ext_mmd_title_block+  firstPair <- kvPair False+  restPairs <- many (kvPair True)+  let kvPairs = firstPair : restPairs+  blanklines+  updateState $ \st -> st{ stateMeta' = stateMeta' st <>+                             return (Meta $ M.fromList kvPairs) }++kvPair :: PandocMonad m => Bool -> MarkdownParser m (String, MetaValue)+kvPair allowEmpty = try $ do+  key <- many1Till (alphaNum <|> oneOf "_- ") (char ':')+  val <- trim <$> manyTill anyChar+          (try $ newline >> lookAhead (blankline <|> nonspaceChar))+  guard $ allowEmpty || not (null val)+  let key' = concat $ words $ map toLower key+  let val' = MetaBlocks $ B.toList $ B.plain $B.text val+  return (key',val')++parseMarkdown :: PandocMonad m => MarkdownParser m Pandoc+parseMarkdown = do+  optional titleBlock+  blocks <- parseBlocks+  st <- getState+  -- check for notes with no corresponding note references+  let notesUsed = stateNoteRefs st+  let notesDefined = M.keys (stateNotes' st)+  mapM_ (\n -> unless (n `Set.member` notesUsed) $+                case M.lookup n (stateNotes' st) of+                   Just (pos, _) -> report (NoteDefinedButNotUsed n pos)+                   Nothing -> throwError $+                     PandocShouldNeverHappenError "note not found")+         notesDefined+  let doc = runF (do Pandoc _ bs <- B.doc <$> blocks+                     meta <- stateMeta' st+                     return $ Pandoc meta bs) st+  reportLogMessages+  return doc++referenceKey :: PandocMonad m => MarkdownParser m (F Blocks)+referenceKey = try $ do+  pos <- getPosition+  skipNonindentSpaces+  (_,raw) <- reference+  char ':'+  skipSpaces >> optional newline >> skipSpaces >> notFollowedBy (char '[')+  let sourceURL = fmap unwords $ many $ try $ do+                    skipMany spaceChar+                    notFollowedBy' referenceTitle+                    notFollowedBy' $ guardEnabled Ext_link_attributes >> attributes+                    notFollowedBy' (() <$ reference)+                    many1 $ notFollowedBy space >> litChar+  let betweenAngles = try $ char '<' >> manyTill litChar (char '>')+  src <- try betweenAngles <|> sourceURL+  tit <- option "" referenceTitle+  attr   <- option nullAttr $ try $+              do guardEnabled Ext_link_attributes+                 skipSpaces >> optional newline >> skipSpaces+                 attributes+  addKvs <- option [] $ guardEnabled Ext_mmd_link_attributes+                          >> many (try $ spnl >> keyValAttr)+  blanklines+  let attr'  = extractIdClass $ foldl (\x f -> f x) attr addKvs+      target = (escapeURI $ trimr src, tit)+  st <- getState+  let oldkeys = stateKeys st+  let key = toKey raw+  case M.lookup key oldkeys of+    Just (t,a) | not (t == target && a == attr') ->+      -- We don't warn on two duplicate keys if the targets are also+      -- the same. This can happen naturally with --reference-location=block+      -- or section. See #3701.+      logMessage $ DuplicateLinkReference raw pos+    _ -> return ()+  updateState $ \s -> s { stateKeys = M.insert key (target, attr') oldkeys }+  return $ return mempty++referenceTitle :: PandocMonad m => MarkdownParser m String+referenceTitle = try $ do+  skipSpaces >> optional newline >> skipSpaces+  quotedTitle '"' <|> quotedTitle '\'' <|> charsInBalanced '(' ')' litChar++-- A link title in quotes+quotedTitle :: PandocMonad m => Char -> MarkdownParser m String+quotedTitle c = try $ do+  char c+  notFollowedBy spaces+  let pEnder = try $ char c >> notFollowedBy (satisfy isAlphaNum)+  let regChunk = many1 (noneOf ['\\','\n','&',c]) <|> count 1 litChar+  let nestedChunk = (\x -> [c] ++ x ++ [c]) <$> quotedTitle c+  unwords . words . concat <$> manyTill (nestedChunk <|> regChunk) pEnder++-- | PHP Markdown Extra style abbreviation key.  Currently+-- we just skip them, since Pandoc doesn't have an element for+-- an abbreviation.+abbrevKey :: PandocMonad m => MarkdownParser m (F Blocks)+abbrevKey = do+  guardEnabled Ext_abbreviations+  try $ do+    char '*'+    reference+    char ':'+    skipMany (satisfy (/= '\n'))+    blanklines+    return $ return mempty++noteMarker :: PandocMonad m => MarkdownParser m String+noteMarker = string "[^" >> many1Till (satisfy $ not . isBlank) (char ']')++rawLine :: PandocMonad m => MarkdownParser m String+rawLine = try $ do+  notFollowedBy blankline+  notFollowedBy' $ try $ skipNonindentSpaces >> noteMarker+  optional indentSpaces+  anyLine++rawLines :: PandocMonad m => MarkdownParser m String+rawLines = do+  first <- anyLine+  rest <- many rawLine+  return $ unlines (first:rest)++noteBlock :: PandocMonad m => MarkdownParser m (F Blocks)+noteBlock = try $ do+  pos <- getPosition+  skipNonindentSpaces+  ref <- noteMarker+  char ':'+  optional blankline+  optional indentSpaces+  first <- rawLines+  rest <- many $ try $ blanklines >> indentSpaces >> rawLines+  let raw = unlines (first:rest) ++ "\n"+  optional blanklines+  parsed <- parseFromString' parseBlocks raw+  oldnotes <- stateNotes' <$> getState+  case M.lookup ref oldnotes of+    Just _  -> logMessage $ DuplicateNoteReference ref pos+    Nothing -> return ()+  updateState $ \s -> s { stateNotes' = M.insert ref (pos, parsed) oldnotes }+  return mempty++--+-- parsing blocks+--++parseBlocks :: PandocMonad m => MarkdownParser m (F Blocks)+parseBlocks = mconcat <$> manyTill block eof++block :: PandocMonad m => MarkdownParser m (F Blocks)+block = do+  res <- choice [ mempty <$ blanklines+               , codeBlockFenced+               , yamlMetaBlock+               -- note: bulletList needs to be before header because of+               -- the possibility of empty list items: -+               , bulletList+               , header+               , lhsCodeBlock+               , divHtml+               , divFenced+               , htmlBlock+               , table+               , codeBlockIndented+               , rawTeXBlock+               , lineBlock+               , blockQuote+               , hrule+               , orderedList+               , definitionList+               , noteBlock+               , referenceKey+               , abbrevKey+               , para+               , plain+               ] <?> "block"+  trace (take 60 $ show $ B.toList $ runF res defaultParserState)+  return res++--+-- header blocks+--++header :: PandocMonad m => MarkdownParser m (F Blocks)+header = setextHeader <|> atxHeader <?> "header"++atxChar :: PandocMonad m => MarkdownParser m Char+atxChar = do+  exts <- getOption readerExtensions+  return $ if extensionEnabled Ext_literate_haskell exts+              then '='+              else '#'++atxHeader :: PandocMonad m => MarkdownParser m (F Blocks)+atxHeader = try $ do+  level <- fmap length (atxChar >>= many1 . char)+  notFollowedBy $ guardEnabled Ext_fancy_lists >>+                  (char '.' <|> char ')') -- this would be a list+  guardDisabled Ext_space_in_atx_header <|> notFollowedBy nonspaceChar+  skipSpaces+  (text, raw) <- withRaw $+          trimInlinesF . mconcat <$> many (notFollowedBy atxClosing >> inline)+  attr <- atxClosing+  attr' <- registerHeader attr (runF text defaultParserState)+  guardDisabled Ext_implicit_header_references+    <|> registerImplicitHeader raw attr'+  return $ B.headerWith attr' level <$> text++atxClosing :: PandocMonad m => MarkdownParser m Attr+atxClosing = try $ do+  attr' <- option nullAttr+             (guardEnabled Ext_mmd_header_identifiers >> mmdHeaderIdentifier)+  skipMany . char =<< atxChar+  skipSpaces+  attr <- option attr'+             (guardEnabled Ext_header_attributes >> attributes)+  blanklines+  return attr++setextHeaderEnd :: PandocMonad m => MarkdownParser m Attr+setextHeaderEnd = try $ do+  attr <- option nullAttr+          $ (guardEnabled Ext_mmd_header_identifiers >> mmdHeaderIdentifier)+           <|> (guardEnabled Ext_header_attributes >> attributes)+  blanklines+  return attr++mmdHeaderIdentifier :: PandocMonad m => MarkdownParser m Attr+mmdHeaderIdentifier = do+  (_, raw) <- reference+  let raw' = trim $ stripFirstAndLast raw+  let ident = concat $ words $ map toLower raw'+  let attr = (ident, [], [])+  guardDisabled Ext_implicit_header_references+    <|> registerImplicitHeader raw' attr+  skipSpaces+  return attr++setextHeader :: PandocMonad m => MarkdownParser m (F Blocks)+setextHeader = try $ do+  -- This lookahead prevents us from wasting time parsing Inlines+  -- unless necessary -- it gives a significant performance boost.+  lookAhead $ anyLine >> many1 (oneOf setextHChars) >> blankline+  skipSpaces+  (text, raw) <- withRaw $+       trimInlinesF . mconcat <$> many1 (notFollowedBy setextHeaderEnd >> inline)+  attr <- setextHeaderEnd+  underlineChar <- oneOf setextHChars+  many (char underlineChar)+  blanklines+  let level = fromMaybe 0 (findIndex (== underlineChar) setextHChars) + 1+  attr' <- registerHeader attr (runF text defaultParserState)+  guardDisabled Ext_implicit_header_references+    <|> registerImplicitHeader raw attr'+  return $ B.headerWith attr' level <$> text++registerImplicitHeader :: PandocMonad m => String -> Attr -> MarkdownParser m ()+registerImplicitHeader raw attr@(ident, _, _) = do+  let key = toKey $ "[" ++ raw ++ "]"+  updateState (\s -> s { stateHeaderKeys =+                         M.insert key (('#':ident,""), attr) (stateHeaderKeys s) })++--+-- hrule block+--++hrule :: PandocMonad m => ParserT [Char] st m (F Blocks)+hrule = try $ do+  skipSpaces+  start <- satisfy isHruleChar+  count 2 (skipSpaces >> char start)+  skipMany (spaceChar <|> char start)+  newline+  optional blanklines+  return $ return B.horizontalRule++--+-- code blocks+--++indentedLine :: PandocMonad m => MarkdownParser m String+indentedLine = indentSpaces >> anyLineNewline++blockDelimiter :: PandocMonad m+               => (Char -> Bool)+               -> Maybe Int+               -> ParserT [Char] st m Int+blockDelimiter f len = try $ do+  c <- lookAhead (satisfy f)+  case len of+      Just l  -> count l (char c) >> many (char c) >> return l+      Nothing -> fmap ((+ 3) . length) (count 3 (char c) >> many (char c))++attributes :: PandocMonad m => MarkdownParser m Attr+attributes = try $ do+  char '{'+  spnl+  attrs <- many (attribute <* spnl)+  char '}'+  return $ foldl (\x f -> f x) nullAttr attrs++attribute :: PandocMonad m => MarkdownParser m (Attr -> Attr)+attribute = identifierAttr <|> classAttr <|> keyValAttr <|> specialAttr++identifier :: PandocMonad m => MarkdownParser m String+identifier = do+  first <- letter+  rest <- many $ alphaNum <|> oneOf "-_:."+  return (first:rest)++identifierAttr :: PandocMonad m => MarkdownParser m (Attr -> Attr)+identifierAttr = try $ do+  char '#'+  result <- identifier+  return $ \(_,cs,kvs) -> (result,cs,kvs)++classAttr :: PandocMonad m => MarkdownParser m (Attr -> Attr)+classAttr = try $ do+  char '.'+  result <- identifier+  return $ \(id',cs,kvs) -> (id',cs ++ [result],kvs)++keyValAttr :: PandocMonad m => MarkdownParser m (Attr -> Attr)+keyValAttr = try $ do+  key <- identifier+  char '='+  val <- enclosed (char '"') (char '"') litChar+     <|> enclosed (char '\'') (char '\'') litChar+     <|> many (escapedChar' <|> noneOf " \t\n\r}")+  return $ \(id',cs,kvs) ->+    case key of+         "id"    -> (val,cs,kvs)+         "class" -> (id',cs ++ words val,kvs)+         _       -> (id',cs,kvs ++ [(key,val)])++specialAttr :: PandocMonad m => MarkdownParser m (Attr -> Attr)+specialAttr = do+  char '-'+  return $ \(id',cs,kvs) -> (id',cs ++ ["unnumbered"],kvs)++rawAttribute :: PandocMonad m => MarkdownParser m String+rawAttribute = do+  char '{'+  skipMany spaceChar+  char '='+  format <- many1 $ satisfy (\c -> isAlphaNum c || c `elem` "-_")+  skipMany spaceChar+  char '}'+  return format++codeBlockFenced :: PandocMonad m => MarkdownParser m (F Blocks)+codeBlockFenced = try $ do+  c <- try (guardEnabled Ext_fenced_code_blocks >> lookAhead (char '~'))+     <|> (guardEnabled Ext_backtick_code_blocks >> lookAhead (char '`'))+  size <- blockDelimiter (== c) Nothing+  skipMany spaceChar+  rawattr <-+     (Left <$> try (guardEnabled Ext_raw_attribute >> rawAttribute))+    <|>+     (Right <$> option ("",[],[])+         (try (guardEnabled Ext_fenced_code_attributes >> attributes)+          <|> ((\x -> ("",[toLanguageId x],[])) <$> many1 nonspaceChar)))+  blankline+  contents <- intercalate "\n" <$>+                 manyTill anyLine (blockDelimiter (== c) (Just size))+  blanklines+  return $ return $+    case rawattr of+          Left syn   -> B.rawBlock syn contents+          Right attr -> B.codeBlockWith attr contents++-- correctly handle github language identifiers+toLanguageId :: String -> String+toLanguageId = map toLower . go+  where go "c++"         = "cpp"+        go "objective-c" = "objectivec"+        go x             = x++codeBlockIndented :: PandocMonad m => MarkdownParser m (F Blocks)+codeBlockIndented = do+  contents <- many1 (indentedLine <|>+                     try (do b <- blanklines+                             l <- indentedLine+                             return $ b ++ l))+  optional blanklines+  classes <- getOption readerIndentedCodeClasses+  return $ return $ B.codeBlockWith ("", classes, []) $+           stripTrailingNewlines $ concat contents++lhsCodeBlock :: PandocMonad m => MarkdownParser m (F Blocks)+lhsCodeBlock = do+  guardEnabled Ext_literate_haskell+  (return . B.codeBlockWith ("",["sourceCode","literate","haskell"],[]) <$>+          (lhsCodeBlockBird <|> lhsCodeBlockLaTeX))+    <|> (return . B.codeBlockWith ("",["sourceCode","haskell"],[]) <$>+          lhsCodeBlockInverseBird)++lhsCodeBlockLaTeX :: PandocMonad m => MarkdownParser m String+lhsCodeBlockLaTeX = try $ do+  string "\\begin{code}"+  manyTill spaceChar newline+  contents <- many1Till anyChar (try $ string "\\end{code}")+  blanklines+  return $ stripTrailingNewlines contents++lhsCodeBlockBird :: PandocMonad m => MarkdownParser m String+lhsCodeBlockBird = lhsCodeBlockBirdWith '>'++lhsCodeBlockInverseBird :: PandocMonad m => MarkdownParser m String+lhsCodeBlockInverseBird = lhsCodeBlockBirdWith '<'++lhsCodeBlockBirdWith :: PandocMonad m => Char -> MarkdownParser m String+lhsCodeBlockBirdWith c = try $ do+  pos <- getPosition+  when (sourceColumn pos /= 1) $ fail "Not in first column"+  lns <- many1 $ birdTrackLine c+  -- if (as is normal) there is always a space after >, drop it+  let lns' = if all (\ln -> null ln || take 1 ln == " ") lns+                then map (drop 1) lns+                else lns+  blanklines+  return $ intercalate "\n" lns'++birdTrackLine :: PandocMonad m => Char -> ParserT [Char] st m String+birdTrackLine c = try $ do+  char c+  -- allow html tags on left margin:+  when (c == '<') $ notFollowedBy letter+  anyLine++--+-- block quotes+--++emailBlockQuoteStart :: PandocMonad m => MarkdownParser m Char+emailBlockQuoteStart = try $ skipNonindentSpaces >> char '>' <* optional (char ' ')++emailBlockQuote :: PandocMonad m => MarkdownParser m [String]+emailBlockQuote = try $ do+  emailBlockQuoteStart+  let emailLine = many $ nonEndline <|> try+                         (endline >> notFollowedBy emailBlockQuoteStart >>+                         return '\n')+  let emailSep = try (newline >> emailBlockQuoteStart)+  first <- emailLine+  rest <- many $ try $ emailSep >> emailLine+  let raw = first:rest+  newline <|> (eof >> return '\n')+  optional blanklines+  return raw++blockQuote :: PandocMonad m => MarkdownParser m (F Blocks)+blockQuote = do+  raw <- emailBlockQuote+  -- parse the extracted block, which may contain various block elements:+  contents <- parseFromString' parseBlocks $ intercalate "\n" raw ++ "\n\n"+  return $ B.blockQuote <$> contents++--+-- list blocks+--++bulletListStart :: PandocMonad m => MarkdownParser m ()+bulletListStart = try $ do+  optional newline -- if preceded by a Plain block in a list context+  skipNonindentSpaces+  notFollowedBy' (() <$ hrule)     -- because hrules start out just like lists+  satisfy isBulletListMarker+  gobbleSpaces 1 <|> () <$ lookAhead newline+  try (gobbleAtMostSpaces 3 >> notFollowedBy spaceChar) <|> return ()++orderedListStart :: PandocMonad m+                 => Maybe (ListNumberStyle, ListNumberDelim)+                 -> MarkdownParser m (Int, ListNumberStyle, ListNumberDelim)+orderedListStart mbstydelim = try $ do+  optional newline -- if preceded by a Plain block in a list context+  skipNonindentSpaces+  notFollowedBy $ string "p." >> spaceChar >> digit  -- page number+  (do guardDisabled Ext_fancy_lists+      start <- many1 digit >>= safeRead+      char '.'+      gobbleSpaces 1 <|> () <$ lookAhead newline+      optional $ try (gobbleAtMostSpaces 3 >> notFollowedBy spaceChar)+      return (start, DefaultStyle, DefaultDelim))+   <|>+   (do (num, style, delim) <- maybe+          anyOrderedListMarker+          (\(sty,delim) -> (\start -> (start,sty,delim)) <$>+               orderedListMarker sty delim)+          mbstydelim+       gobbleSpaces 1 <|> () <$ lookAhead newline+       -- if it could be an abbreviated first name,+       -- insist on more than one space+       when (delim == Period && (style == UpperAlpha ||+            (style == UpperRoman &&+             num `elem` [1, 5, 10, 50, 100, 500, 1000]))) $+              () <$ lookAhead (newline <|> spaceChar)+       optional $ try (gobbleAtMostSpaces 3 >> notFollowedBy spaceChar)+       return (num, style, delim))++listStart :: PandocMonad m => MarkdownParser m ()+listStart = bulletListStart <|> (Control.Monad.void (orderedListStart Nothing))++listLine :: PandocMonad m => Int -> MarkdownParser m String+listLine continuationIndent = try $ do+  notFollowedBy' (do gobbleSpaces continuationIndent+                     skipMany spaceChar+                     listStart)+  notFollowedByHtmlCloser+  optional (() <$ gobbleSpaces continuationIndent)+  listLineCommon++listLineCommon :: PandocMonad m => MarkdownParser m String+listLineCommon = concat <$> manyTill+              (  many1 (satisfy $ \c -> c /= '\n' && c /= '<')+             <|> fmap snd (htmlTag isCommentTag)+             <|> count 1 anyChar+              ) newline++-- parse raw text for one list item, excluding start marker and continuations+rawListItem :: PandocMonad m+            => MarkdownParser m a+            -> MarkdownParser m (String, Int)+rawListItem start = try $ do+  pos1 <- getPosition+  start+  pos2 <- getPosition+  continuationIndent <- (4 <$ guardEnabled Ext_four_space_rule)+                    <|> return (sourceColumn pos2 - sourceColumn pos1)+  first <- listLineCommon+  rest <- many (do notFollowedBy listStart+                   notFollowedBy (() <$ codeBlockFenced)+                   notFollowedBy blankline+                   listLine continuationIndent)+  blanks <- many blankline+  let result = unlines (first:rest) ++ blanks+  return (result, continuationIndent)++-- continuation of a list item - indented and separated by blankline+-- or (in compact lists) endline.+-- note: nested lists are parsed as continuations+listContinuation :: PandocMonad m => Int -> MarkdownParser m String+listContinuation continuationIndent = try $ do+  x <- try $ do+         notFollowedBy blankline+         notFollowedByHtmlCloser+         gobbleSpaces continuationIndent+         anyLineNewline+  xs <- many $ try $ do+         notFollowedBy blankline+         notFollowedByHtmlCloser+         gobbleSpaces continuationIndent <|> notFollowedBy' listStart+         anyLineNewline+  blanks <- many blankline+  return $ concat (x:xs) ++ blanks++notFollowedByHtmlCloser :: PandocMonad m => MarkdownParser m ()+notFollowedByHtmlCloser = do+  inHtmlBlock <- stateInHtmlBlock <$> getState+  case inHtmlBlock of+        Just t  -> notFollowedBy' $ htmlTag (~== TagClose t)+        Nothing -> return ()++listItem :: PandocMonad m+         => MarkdownParser m a+         -> MarkdownParser m (F Blocks)+listItem start = try $ do+  (first, continuationIndent) <- rawListItem start+  continuations <- many (listContinuation continuationIndent)+  -- parsing with ListItemState forces markers at beginning of lines to+  -- count as list item markers, even if not separated by blank space.+  -- see definition of "endline"+  state <- getState+  let oldContext = stateParserContext state+  setState $ state {stateParserContext = ListItemState}+  -- parse the extracted block, which may contain various block elements:+  let raw = concat (first:continuations)+  contents <- parseFromString' parseBlocks raw+  updateState (\st -> st {stateParserContext = oldContext})+  return contents++orderedList :: PandocMonad m => MarkdownParser m (F Blocks)+orderedList = try $ do+  (start, style, delim) <- lookAhead (orderedListStart Nothing)+  unless (style `elem` [DefaultStyle, Decimal, Example] &&+          delim `elem` [DefaultDelim, Period]) $+    guardEnabled Ext_fancy_lists+  when (style == Example) $ guardEnabled Ext_example_lists+  items <- fmap sequence $ many1 $ listItem+                 (orderedListStart (Just (style, delim)))+  start' <- (start <$ guardEnabled Ext_startnum) <|> return 1+  return $ B.orderedListWith (start', style, delim) <$> fmap compactify items++bulletList :: PandocMonad m => MarkdownParser m (F Blocks)+bulletList = do+  items <- fmap sequence $ many1 $ listItem  bulletListStart+  return $ B.bulletList <$> fmap compactify items++-- definition lists++defListMarker :: PandocMonad m => MarkdownParser m ()+defListMarker = do+  sps <- nonindentSpaces+  char ':' <|> char '~'+  tabStop <- getOption readerTabStop+  let remaining = tabStop - (length sps + 1)+  if remaining > 0+     then try (count remaining (char ' ')) <|> string "\t" <|> many1 spaceChar+     else mzero+  return ()++definitionListItem :: PandocMonad m => Bool -> MarkdownParser m (F (Inlines, [Blocks]))+definitionListItem compact = try $ do+  rawLine' <- anyLine+  raw <- many1 $ defRawBlock compact+  term <- parseFromString' (trimInlinesF <$> inlines) rawLine'+  contents <- mapM (parseFromString' parseBlocks . (++"\n")) raw+  optional blanklines+  return $ liftM2 (,) term (sequence contents)++defRawBlock :: PandocMonad m => Bool -> MarkdownParser m String+defRawBlock compact = try $ do+  hasBlank <- option False $ blankline >> return True+  defListMarker+  firstline <- anyLineNewline+  let dline = try+               ( do notFollowedBy blankline+                    notFollowedByHtmlCloser+                    if compact -- laziness not compatible with compact+                       then () <$ indentSpaces+                       else (() <$ indentSpaces)+                             <|> notFollowedBy defListMarker+                    anyLine )+  rawlines <- many dline+  cont <- fmap concat $ many $ try $ do+            trailing <- option "" blanklines+            ln <- indentSpaces >> notFollowedBy blankline >> anyLine+            lns <- many dline+            return $ trailing ++ unlines (ln:lns)+  return $ trimr (firstline ++ unlines rawlines ++ cont) +++            if hasBlank || not (null cont) then "\n\n" else ""++definitionList :: PandocMonad m => MarkdownParser m (F Blocks)+definitionList = try $ do+  lookAhead (anyLine >>+             optional (blankline >> notFollowedBy (Control.Monad.void table)) >>+             -- don't capture table caption as def list!+             defListMarker)+  compactDefinitionList <|> normalDefinitionList++compactDefinitionList :: PandocMonad m => MarkdownParser m (F Blocks)+compactDefinitionList = do+  guardEnabled Ext_compact_definition_lists+  items <- fmap sequence $ many1 $ definitionListItem True+  return $ B.definitionList <$> fmap compactifyDL items++normalDefinitionList :: PandocMonad m => MarkdownParser m (F Blocks)+normalDefinitionList = do+  guardEnabled Ext_definition_lists+  items <- fmap sequence $ many1 $ definitionListItem False+  return $ B.definitionList <$> items++--+-- paragraph block+--++para :: PandocMonad m => MarkdownParser m (F Blocks)+para = try $ do+  exts <- getOption readerExtensions+  result <- trimInlinesF <$> inlines1+  option (B.plain <$> result)+    $ try $ do+            newline+            (blanklines >> return mempty)+              <|> (guardDisabled Ext_blank_before_blockquote >> () <$ lookAhead blockQuote)+              <|> (guardEnabled Ext_backtick_code_blocks >> () <$ lookAhead codeBlockFenced)+              <|> (guardDisabled Ext_blank_before_header >> () <$ lookAhead header)+              <|> (guardEnabled Ext_lists_without_preceding_blankline >>+                       -- Avoid creating a paragraph in a nested list.+                       notFollowedBy' inList >>+                       () <$ lookAhead listStart)+              <|> do guardEnabled Ext_native_divs+                     inHtmlBlock <- stateInHtmlBlock <$> getState+                     case inHtmlBlock of+                          Just "div" -> () <$+                                       lookAhead (htmlTag (~== TagClose "div"))+                          _          -> mzero+              <|> do guardEnabled Ext_fenced_divs+                     divLevel <- stateFencedDivLevel <$> getState+                     if divLevel > 0+                        then lookAhead divFenceEnd+                        else mzero+            return $ do+              result' <- result+              case B.toList result' of+                   [Image attr alt (src,tit)]+                     | not (null alt) &&+                       Ext_implicit_figures `extensionEnabled` exts ->+                        -- the fig: at beginning of title indicates a figure+                        return $ B.para $ B.singleton+                               $ Image attr alt (src,'f':'i':'g':':':tit)+                   _ -> return $ B.para result'++plain :: PandocMonad m => MarkdownParser m (F Blocks)+plain = fmap B.plain . trimInlinesF <$> inlines1++--+-- raw html+--++htmlElement :: PandocMonad m => MarkdownParser m String+htmlElement = rawVerbatimBlock+          <|> strictHtmlBlock+          <|> fmap snd (htmlTag isBlockTag)++htmlBlock :: PandocMonad m => MarkdownParser m (F Blocks)+htmlBlock = do+  guardEnabled Ext_raw_html+  try (do+      (TagOpen t attrs) <- lookAhead $ fst <$> htmlTag isBlockTag+      (guard (t `elem` ["pre","style","script"]) >>+          (return . B.rawBlock "html") <$> rawVerbatimBlock)+        <|> (do guardEnabled Ext_markdown_attribute+                oldMarkdownAttribute <- stateMarkdownAttribute <$> getState+                markdownAttribute <-+                   case lookup "markdown" attrs of+                        Just "0" -> False <$ updateState (\st -> st{+                                       stateMarkdownAttribute = False })+                        Just _   -> True <$ updateState (\st -> st{+                                       stateMarkdownAttribute = True })+                        Nothing  -> return oldMarkdownAttribute+                res <- if markdownAttribute+                          then rawHtmlBlocks+                          else htmlBlock'+                updateState $ \st -> st{ stateMarkdownAttribute =+                                         oldMarkdownAttribute }+                return res)+        <|> (guardEnabled Ext_markdown_in_html_blocks >> rawHtmlBlocks))+    <|> htmlBlock'++htmlBlock' :: PandocMonad m => MarkdownParser m (F Blocks)+htmlBlock' = try $ do+    first <- htmlElement+    skipMany spaceChar+    optional blanklines+    return $ if null first+                then mempty+                else return $ B.rawBlock "html" first++strictHtmlBlock :: PandocMonad m => MarkdownParser m String+strictHtmlBlock = htmlInBalanced (not . isInlineTag)++rawVerbatimBlock :: PandocMonad m => MarkdownParser m String+rawVerbatimBlock = htmlInBalanced isVerbTag+  where isVerbTag (TagOpen "pre" _)    = True+        isVerbTag (TagOpen "style" _)  = True+        isVerbTag (TagOpen "script" _) = True+        isVerbTag _                    = False++rawTeXBlock :: PandocMonad m => MarkdownParser m (F Blocks)+rawTeXBlock = do+  guardEnabled Ext_raw_tex+  result <- (B.rawBlock "context" . concat <$>+                  rawConTeXtEnvironment `sepEndBy1` blankline)+        <|> (B.rawBlock "latex" . concat <$>+                  rawLaTeXBlock `sepEndBy1` blankline)++  optional blanklines+  return $ return result++rawHtmlBlocks :: PandocMonad m => MarkdownParser m (F Blocks)+rawHtmlBlocks = do+  (TagOpen tagtype _, raw) <- htmlTag isBlockTag+  -- we don't want '<td>    text' to be a code block:+  skipMany spaceChar+  indentlevel <- (blankline >> length <$> many (char ' ')) <|> return 0+  -- try to find closing tag+  -- we set stateInHtmlBlock so that closing tags that can be either block or+  -- inline will not be parsed as inline tags+  oldInHtmlBlock <- stateInHtmlBlock <$> getState+  updateState $ \st -> st{ stateInHtmlBlock = Just tagtype }+  let closer = htmlTag (\x -> x ~== TagClose tagtype)+  let block' = do notFollowedBy' closer+                  gobbleAtMostSpaces indentlevel+                  block+  contents <- mconcat <$> many block'+  result <-+    (closer >>= \(_, rawcloser) -> return (+                return (B.rawBlock "html" $ stripMarkdownAttribute raw) <>+                contents <>+                return (B.rawBlock "html" rawcloser)))+      <|> return (return (B.rawBlock "html" raw) <> contents)+  updateState $ \st -> st{ stateInHtmlBlock = oldInHtmlBlock }+  return result++-- remove markdown="1" attribute+stripMarkdownAttribute :: String -> String+stripMarkdownAttribute s = renderTags' $ map filterAttrib $ parseTags s+  where filterAttrib (TagOpen t as) = TagOpen t+                                        [(k,v) | (k,v) <- as, k /= "markdown"]+        filterAttrib              x = x++--+-- line block+--++lineBlock :: PandocMonad m => MarkdownParser m (F Blocks)+lineBlock = try $ do+  guardEnabled Ext_line_blocks+  lines' <- lineBlockLines >>=+            mapM (parseFromString' (trimInlinesF <$> inlines))+  return $ B.lineBlock <$> sequence lines'++--+-- Tables+--++-- Parse a dashed line with optional trailing spaces; return its length+-- and the length including trailing space.+dashedLine :: PandocMonad m+           => Char+           -> ParserT [Char] st m (Int, Int)+dashedLine ch = do+  dashes <- many1 (char ch)+  sp     <- many spaceChar+  let lengthDashes = length dashes+      lengthSp     = length sp+  return (lengthDashes, lengthDashes + lengthSp)++-- Parse a table header with dashed lines of '-' preceded by+-- one (or zero) line of text.+simpleTableHeader :: PandocMonad m+                  => Bool  -- ^ Headerless table+                  -> MarkdownParser m (F [Blocks], [Alignment], [Int])+simpleTableHeader headless = try $ do+  rawContent  <- if headless+                    then return ""+                    else anyLine+  initSp      <- nonindentSpaces+  dashes      <- many1 (dashedLine '-')+  newline+  let (lengths, lines') = unzip dashes+  let indices  = scanl (+) (length initSp) lines'+  -- If no header, calculate alignment on basis of first row of text+  rawHeads <- fmap (tail . splitStringByIndices (init indices)) $+              if headless+                 then lookAhead anyLine+                 else return rawContent+  let aligns   = zipWith alignType (map ((: [])) rawHeads) lengths+  let rawHeads' = if headless+                     then replicate (length dashes) ""+                     else rawHeads+  heads <- fmap sequence+           $+            mapM ((parseFromString' (mconcat <$> many plain)).trim) rawHeads'+  return (heads, aligns, indices)++-- Returns an alignment type for a table, based on a list of strings+-- (the rows of the column header) and a number (the length of the+-- dashed line under the rows.+alignType :: [String]+          -> Int+          -> Alignment+alignType [] _ = AlignDefault+alignType strLst len =+  let nonempties = filter (not . null) $ map trimr strLst+      (leftSpace, rightSpace) =+           case sortBy (comparing length) nonempties of+                 (x:_) -> (head x `elem` " \t", length x < len)+                 []    -> (False, False)+  in  case (leftSpace, rightSpace) of+        (True,  False) -> AlignRight+        (False, True)  -> AlignLeft+        (True,  True)  -> AlignCenter+        (False, False) -> AlignDefault++-- Parse a table footer - dashed lines followed by blank line.+tableFooter :: PandocMonad m => MarkdownParser m String+tableFooter = try $ skipNonindentSpaces >> many1 (dashedLine '-') >> blanklines++-- Parse a table separator - dashed line.+tableSep :: PandocMonad m => MarkdownParser m Char+tableSep = try $ skipNonindentSpaces >> many1 (dashedLine '-') >> char '\n'++-- Parse a raw line and split it into chunks by indices.+rawTableLine :: PandocMonad m+             => [Int]+             -> MarkdownParser m [String]+rawTableLine indices = do+  notFollowedBy' (blanklines <|> tableFooter)+  line <- many1Till anyChar newline+  return $ map trim $ tail $+           splitStringByIndices (init indices) line++-- Parse a table line and return a list of lists of blocks (columns).+tableLine :: PandocMonad m+          => [Int]+          -> MarkdownParser m (F [Blocks])+tableLine indices = rawTableLine indices >>=+  fmap sequence . mapM (parseFromString' (mconcat <$> many plain))++-- Parse a multiline table row and return a list of blocks (columns).+multilineRow :: PandocMonad m+             => [Int]+             -> MarkdownParser m (F [Blocks])+multilineRow indices = do+  colLines <- many1 (rawTableLine indices)+  let cols = map unlines $ transpose colLines+  fmap sequence $ mapM (parseFromString' (mconcat <$> many plain)) cols++-- Parses a table caption:  inlines beginning with 'Table:'+-- and followed by blank lines.+tableCaption :: PandocMonad m => MarkdownParser m (F Inlines)+tableCaption = try $ do+  guardEnabled Ext_table_captions+  skipNonindentSpaces+  string ":" <|> string "Table:"+  trimInlinesF <$> inlines1 <* blanklines++-- Parse a simple table with '---' header and one line per row.+simpleTable :: PandocMonad m+            => Bool  -- ^ Headerless table+            -> MarkdownParser m ([Alignment], [Double], F [Blocks], F [[Blocks]])+simpleTable headless = do+  (aligns, _widths, heads', lines') <-+       tableWith (simpleTableHeader headless) tableLine+              (return ())+              (if headless then tableFooter else tableFooter <|> blanklines)+  -- Simple tables get 0s for relative column widths (i.e., use default)+  return (aligns, replicate (length aligns) 0, heads', lines')++-- Parse a multiline table:  starts with row of '-' on top, then header+-- (which may be multiline), then the rows,+-- which may be multiline, separated by blank lines, and+-- ending with a footer (dashed line followed by blank line).+multilineTable :: PandocMonad m+               => Bool -- ^ Headerless table+               -> MarkdownParser m ([Alignment], [Double], F [Blocks], F [[Blocks]])+multilineTable headless =+  tableWith (multilineTableHeader headless) multilineRow blanklines tableFooter++multilineTableHeader :: PandocMonad m+                     => Bool -- ^ Headerless table+                     -> MarkdownParser m (F [Blocks], [Alignment], [Int])+multilineTableHeader headless = try $ do+  unless headless $+     tableSep >> notFollowedBy blankline+  rawContent  <- if headless+                    then return $ repeat ""+                    else many1 $ notFollowedBy tableSep >> anyLine+  initSp      <- nonindentSpaces+  dashes      <- many1 (dashedLine '-')+  newline+  let (lengths, lines') = unzip dashes+  let indices  = scanl (+) (length initSp) lines'+  rawHeadsList <- if headless+                     then fmap (map (:[]) . tail .+                              splitStringByIndices (init indices)) $ lookAhead anyLine+                     else return $ transpose $ map+                           (tail . splitStringByIndices (init indices))+                           rawContent+  let aligns   = zipWith alignType rawHeadsList lengths+  let rawHeads = if headless+                    then replicate (length dashes) ""+                    else map (unlines . map trim) rawHeadsList+  heads <- fmap sequence $+            mapM ((parseFromString' (mconcat <$> many plain)).trim) rawHeads+  return (heads, aligns, indices)++-- Parse a grid table:  starts with row of '-' on top, then header+-- (which may be grid), then the rows,+-- which may be grid, separated by blank lines, and+-- ending with a footer (dashed line followed by blank line).+gridTable :: PandocMonad m => Bool -- ^ Headerless table+          -> MarkdownParser m ([Alignment], [Double], F [Blocks], F [[Blocks]])+gridTable headless = gridTableWith' parseBlocks headless++pipeBreak :: PandocMonad m => MarkdownParser m ([Alignment], [Int])+pipeBreak = try $ do+  nonindentSpaces+  openPipe <- (True <$ char '|') <|> return False+  first <- pipeTableHeaderPart+  rest <- many $ sepPipe *> pipeTableHeaderPart+  -- surrounding pipes needed for a one-column table:+  guard $ not (null rest && not openPipe)+  optional (char '|')+  blankline+  return $ unzip (first:rest)++pipeTable :: PandocMonad m => MarkdownParser m ([Alignment], [Double], F [Blocks], F [[Blocks]])+pipeTable = try $ do+  nonindentSpaces+  lookAhead nonspaceChar+  (heads,(aligns, seplengths)) <- (,) <$> pipeTableRow <*> pipeBreak+  let heads' = take (length aligns) <$> heads+  lines' <- many pipeTableRow+  let lines'' = map (take (length aligns) <$>) lines'+  let maxlength = maximum $+       map (\x -> length . stringify $ runF x def) (heads' : lines'')+  numColumns <- getOption readerColumns+  let widths = if maxlength > numColumns+                  then map (\len ->+                           fromIntegral (len + 1) / fromIntegral numColumns)+                             seplengths+                  else replicate (length aligns) 0.0+  return (aligns, widths, heads', sequence lines'')++sepPipe :: PandocMonad m => MarkdownParser m ()+sepPipe = try $ do+  char '|' <|> char '+'+  notFollowedBy blankline++-- parse a row, also returning probable alignments for org-table cells+pipeTableRow :: PandocMonad m => MarkdownParser m (F [Blocks])+pipeTableRow = try $ do+  scanForPipe+  skipMany spaceChar+  openPipe <- (True <$ char '|') <|> return False+  -- split into cells+  let chunk = void (code <|> math <|> rawHtmlInline <|> escapedChar <|> rawLaTeXInline')+       <|> void (noneOf "|\n\r")+  let cellContents = ((trim . snd) <$> withRaw (many chunk)) >>=+        parseFromString' pipeTableCell+  cells <- cellContents `sepEndBy1` char '|'+  -- surrounding pipes needed for a one-column table:+  guard $ not (length cells == 1 && not openPipe)+  blankline+  return $ sequence cells++pipeTableCell :: PandocMonad m => MarkdownParser m (F Blocks)+pipeTableCell =+  (do result <- inlines1+      return $ B.plain <$> result)+    <|> return mempty++pipeTableHeaderPart :: PandocMonad m => ParserT [Char] st m (Alignment, Int)+pipeTableHeaderPart = try $ do+  skipMany spaceChar+  left <- optionMaybe (char ':')+  pipe <- many1 (char '-')+  right <- optionMaybe (char ':')+  skipMany spaceChar+  let len = length pipe + maybe 0 (const 1) left + maybe 0 (const 1) right+  return+    ((case (left,right) of+       (Nothing,Nothing) -> AlignDefault+       (Just _,Nothing)  -> AlignLeft+       (Nothing,Just _)  -> AlignRight+       (Just _,Just _)   -> AlignCenter), len)++-- Succeed only if current line contains a pipe.+scanForPipe :: PandocMonad m => ParserT [Char] st m ()+scanForPipe = do+  inp <- getInput+  case break (\c -> c == '\n' || c == '|') inp of+       (_,'|':_) -> return ()+       _         -> mzero++-- | Parse a table using 'headerParser', 'rowParser',+-- 'lineParser', and 'footerParser'.  Variant of the version in+-- Text.Pandoc.Parsing.+tableWith :: PandocMonad m+          => MarkdownParser m (F [Blocks], [Alignment], [Int])+          -> ([Int] -> MarkdownParser m (F [Blocks]))+          -> MarkdownParser m sep+          -> MarkdownParser m end+          -> MarkdownParser m ([Alignment], [Double], F [Blocks], F [[Blocks]])+tableWith headerParser rowParser lineParser footerParser = try $ do+    (heads, aligns, indices) <- headerParser+    lines' <- fmap sequence $ rowParser indices `sepEndBy1` lineParser+    footerParser+    numColumns <- getOption readerColumns+    let widths = if indices == []+                    then replicate (length aligns) 0.0+                    else widthsFromIndices numColumns indices+    return (aligns, widths, heads, lines')++table :: PandocMonad m => MarkdownParser m (F Blocks)+table = try $ do+  frontCaption <- option Nothing (Just <$> tableCaption)+  (aligns, widths, heads, lns) <-+         try (guardEnabled Ext_pipe_tables >> scanForPipe >> pipeTable) <|>+         try (guardEnabled Ext_multiline_tables >>+                multilineTable False) <|>+         try (guardEnabled Ext_simple_tables >>+                (simpleTable True <|> simpleTable False)) <|>+         try (guardEnabled Ext_multiline_tables >>+                multilineTable True) <|>+         try (guardEnabled Ext_grid_tables >>+                (gridTable False <|> gridTable True)) <?> "table"+  optional blanklines+  caption <- case frontCaption of+                  Nothing -> option (return mempty) tableCaption+                  Just c  -> return c+  -- renormalize widths if greater than 100%:+  let totalWidth = sum widths+  let widths' = if totalWidth < 1+                   then widths+                   else map (/ totalWidth) widths+  return $ do+    caption' <- caption+    heads' <- heads+    lns' <- lns+    return $ B.table caption' (zip aligns widths') heads' lns'++--+-- inline+--++inlines :: PandocMonad m => MarkdownParser m (F Inlines)+inlines = mconcat <$> many inline++inlines1 :: PandocMonad m => MarkdownParser m (F Inlines)+inlines1 = mconcat <$> many1 inline++inline :: PandocMonad m => MarkdownParser m (F Inlines)+inline = choice [ whitespace+                , bareURL+                , str+                , endline+                , code+                , strongOrEmph+                , note+                , cite+                , bracketedSpan+                , link+                , image+                , math+                , strikeout+                , subscript+                , superscript+                , inlineNote  -- after superscript because of ^[link](/foo)^+                , autoLink+                , spanHtml+                , rawHtmlInline+                , escapedNewline+                , escapedChar+                , rawLaTeXInline'+                , exampleRef+                , smart+                , return . B.singleton <$> charRef+                , emoji+                , symbol+                , ltSign+                ] <?> "inline"++escapedChar' :: PandocMonad m => MarkdownParser m Char+escapedChar' = try $ do+  char '\\'+  (guardEnabled Ext_all_symbols_escapable >> satisfy (not . isAlphaNum))+     <|> (guardEnabled Ext_angle_brackets_escapable >>+            oneOf "\\`*_{}[]()>#+-.!~\"<>")+     <|> oneOf "\\`*_{}[]()>#+-.!~\""++escapedNewline :: PandocMonad m => MarkdownParser m (F Inlines)+escapedNewline = try $ do+  guardEnabled Ext_escaped_line_breaks+  char '\\'+  lookAhead (char '\n') -- don't consume the newline (see #3730)+  return $ return B.linebreak++escapedChar :: PandocMonad m => MarkdownParser m (F Inlines)+escapedChar = do+  result <- escapedChar'+  case result of+       ' ' -> return $ return $ B.str "\160" -- "\ " is a nonbreaking space+       _   -> return $ return $ B.str [result]++ltSign :: PandocMonad m => MarkdownParser m (F Inlines)+ltSign = do+  guardDisabled Ext_raw_html+    <|> (notFollowedByHtmlCloser >> notFollowedBy' (htmlTag isBlockTag))+  char '<'+  return $ return $ B.str "<"++exampleRef :: PandocMonad m => MarkdownParser m (F Inlines)+exampleRef = try $ do+  guardEnabled Ext_example_lists+  char '@'+  lab <- many1 (alphaNum <|> oneOf "-_")+  return $ do+    st <- askF+    return $ case M.lookup lab (stateExamples st) of+                  Just n  -> B.str (show n)+                  Nothing -> B.str ('@':lab)++symbol :: PandocMonad m => MarkdownParser m (F Inlines)+symbol = do+  result <- noneOf "<\\\n\t "+         <|> try (do lookAhead $ char '\\'+                     notFollowedBy' (() <$ rawTeXBlock)+                     char '\\')+  return $ return $ B.str [result]++-- parses inline code, between n `s and n `s+code :: PandocMonad m => MarkdownParser m (F Inlines)+code = try $ do+  starts <- many1 (char '`')+  skipSpaces+  result <- (trim . concat) <$>+            many1Till (many1 (noneOf "`\n") <|> many1 (char '`') <|>+                       (char '\n' >> notFollowedBy' blankline >> return " "))+                      (try (skipSpaces >> count (length starts) (char '`') >>+                      notFollowedBy (char '`')))+  rawattr <-+     (Left <$> try (guardEnabled Ext_raw_attribute >> rawAttribute))+    <|>+     (Right <$> option ("",[],[])+         (try (guardEnabled Ext_inline_code_attributes >> attributes)))+  return $ return $+    case rawattr of+         Left syn   -> B.rawInline syn result+         Right attr -> B.codeWith attr result++math :: PandocMonad m => MarkdownParser m (F Inlines)+math =  (return . B.displayMath <$> (mathDisplay >>= applyMacros))+     <|> (return . B.math <$> (mathInline >>= applyMacros)) <+?>+               (guardEnabled Ext_smart *> (return <$> apostrophe)+                <* notFollowedBy (space <|> satisfy isPunctuation))++-- Parses material enclosed in *s, **s, _s, or __s.+-- Designed to avoid backtracking.+enclosure :: PandocMonad m+          => Char+          -> MarkdownParser m (F Inlines)+enclosure c = do+  -- we can't start an enclosure with _ if after a string and+  -- the intraword_underscores extension is enabled:+  guardDisabled Ext_intraword_underscores+    <|> guard (c == '*')+    <|> (guard =<< notAfterString)+  cs <- many1 (char c)+  (return (B.str cs) <>) <$> whitespace+    <|>+        case length cs of+             3 -> three c+             2 -> two   c mempty+             1 -> one   c mempty+             _ -> return (return $ B.str cs)++ender :: PandocMonad m => Char -> Int -> MarkdownParser m ()+ender c n = try $ do+  count n (char c)+  guard (c == '*')+    <|> guardDisabled Ext_intraword_underscores+    <|> notFollowedBy alphaNum++-- Parse inlines til you hit one c or a sequence of two cs.+-- If one c, emit emph and then parse two.+-- If two cs, emit strong and then parse one.+-- Otherwise, emit ccc then the results.+three :: PandocMonad m => Char -> MarkdownParser m (F Inlines)+three c = do+  contents <- mconcat <$> many (notFollowedBy (ender c 1) >> inline)+  (ender c 3 >> updateLastStrPos >> return ((B.strong . B.emph) <$> contents))+    <|> (ender c 2 >> updateLastStrPos >> one c (B.strong <$> contents))+    <|> (ender c 1 >> updateLastStrPos >> two c (B.emph <$> contents))+    <|> return (return (B.str [c,c,c]) <> contents)++-- Parse inlines til you hit two c's, and emit strong.+-- If you never do hit two cs, emit ** plus inlines parsed.+two :: PandocMonad m => Char -> F Inlines -> MarkdownParser m (F Inlines)+two c prefix' = do+  contents <- mconcat <$> many (try $ notFollowedBy (ender c 2) >> inline)+  (ender c 2 >> updateLastStrPos >>+                return (B.strong <$> (prefix' <> contents)))+    <|> return (return (B.str [c,c]) <> (prefix' <> contents))++-- Parse inlines til you hit a c, and emit emph.+-- If you never hit a c, emit * plus inlines parsed.+one :: PandocMonad m => Char -> F Inlines -> MarkdownParser m (F Inlines)+one c prefix' = do+  contents <- mconcat <$> many (  (notFollowedBy (ender c 1) >> inline)+                           <|> try (string [c,c] >>+                                    notFollowedBy (ender c 1) >>+                                    two c mempty) )+  (ender c 1 >> updateLastStrPos >> return (B.emph <$> (prefix' <> contents)))+    <|> return (return (B.str [c]) <> (prefix' <> contents))++strongOrEmph :: PandocMonad m => MarkdownParser m (F Inlines)+strongOrEmph =  enclosure '*' <|> enclosure '_'++-- | Parses a list of inlines between start and end delimiters.+inlinesBetween :: PandocMonad m+               => (Show b)+               => MarkdownParser m a+               -> MarkdownParser m b+               -> MarkdownParser m (F Inlines)+inlinesBetween start end =+  (trimInlinesF . mconcat) <$> try (start >> many1Till inner end)+    where inner      = innerSpace <|> (notFollowedBy' (() <$ whitespace) >> inline)+          innerSpace = try $ whitespace <* notFollowedBy' end++strikeout :: PandocMonad m => MarkdownParser m (F Inlines)+strikeout = fmap B.strikeout <$>+ (guardEnabled Ext_strikeout >> inlinesBetween strikeStart strikeEnd)+    where strikeStart = string "~~" >> lookAhead nonspaceChar+                        >> notFollowedBy (char '~')+          strikeEnd   = try $ string "~~"++superscript :: PandocMonad m => MarkdownParser m (F Inlines)+superscript = fmap B.superscript <$> try (do+  guardEnabled Ext_superscript+  char '^'+  mconcat <$> many1Till (notFollowedBy spaceChar >> inline) (char '^'))++subscript :: PandocMonad m => MarkdownParser m (F Inlines)+subscript = fmap B.subscript <$> try (do+  guardEnabled Ext_subscript+  char '~'+  mconcat <$> many1Till (notFollowedBy spaceChar >> inline) (char '~'))++whitespace :: PandocMonad m => MarkdownParser m (F Inlines)+whitespace = spaceChar >> return <$> (lb <|> regsp) <?> "whitespace"+  where lb = spaceChar >> skipMany spaceChar >> option B.space (endline >> return B.linebreak)+        regsp = skipMany spaceChar >> return B.space++nonEndline :: PandocMonad m => ParserT [Char] st m Char+nonEndline = satisfy (/='\n')++str :: PandocMonad m => MarkdownParser m (F Inlines)+str = do+  result <- many1 (alphaNum <|> try (char '.' <* notFollowedBy (char '.')))+  updateLastStrPos+  (do guardEnabled Ext_smart+      abbrevs <- getOption readerAbbreviations+      if not (null result) && last result == '.' && result `Set.member` abbrevs+         then try (do ils <- whitespace <|> endline+                      lookAhead alphaNum+                      return $ do+                        ils' <- ils+                        if ils' == B.space+                           then return (B.str result <> B.str "\160")+                           else -- linebreak or softbreak+                                return (ils' <> B.str result <> B.str "\160"))+                <|> return (return (B.str result))+         else return (return (B.str result)))+     <|> return (return (B.str result))++-- an endline character that can be treated as a space, not a structural break+endline :: PandocMonad m => MarkdownParser m (F Inlines)+endline = try $ do+  newline+  notFollowedBy blankline+  -- parse potential list-starts differently if in a list:+  notFollowedBy (inList >> listStart)+  guardDisabled Ext_lists_without_preceding_blankline <|> notFollowedBy listStart+  guardEnabled Ext_blank_before_blockquote <|> notFollowedBy emailBlockQuoteStart+  guardEnabled Ext_blank_before_header <|> (notFollowedBy . char =<< atxChar) -- atx header+  guardDisabled Ext_backtick_code_blocks <|>+     notFollowedBy (() <$ (lookAhead (char '`') >> codeBlockFenced))+  guardDisabled Ext_fenced_divs <|>+    do divLevel <- stateFencedDivLevel <$> getState+       guard (divLevel < 1) <|> notFollowedBy divFenceEnd+  notFollowedByHtmlCloser+  (eof >> return mempty)+    <|> (guardEnabled Ext_hard_line_breaks >> return (return B.linebreak))+    <|> (guardEnabled Ext_ignore_line_breaks >> return mempty)+    <|> (skipMany spaceChar >> return (return B.softbreak))++--+-- links+--++-- a reference label for a link+reference :: PandocMonad m => MarkdownParser m (F Inlines, String)+reference = do+  guardDisabled Ext_footnotes <|> notFollowedBy' (string "[^")+  guardDisabled Ext_citations <|> notFollowedBy' (string "[@")+  withRaw $ trimInlinesF <$> inlinesInBalancedBrackets++parenthesizedChars :: PandocMonad m => MarkdownParser m [Char]+parenthesizedChars = do+  result <- charsInBalanced '(' ')' litChar+  return $ '(' : result ++ ")"++-- source for a link, with optional title+source :: PandocMonad m => MarkdownParser m (String, String)+source = do+  char '('+  skipSpaces+  let urlChunk =+            try parenthesizedChars+        <|> (notFollowedBy (oneOf " )") >> count 1 litChar)+        <|> try (many1 spaceChar <* notFollowedBy (oneOf "\"')"))+  let sourceURL = (unwords . words . concat) <$> many urlChunk+  let betweenAngles = try $+         char '<' >> manyTill litChar (char '>')+  src <- try betweenAngles <|> sourceURL+  tit <- option "" $ try $ spnl >> linkTitle+  skipSpaces+  char ')'+  return (escapeURI $ trimr src, tit)++linkTitle :: PandocMonad m => MarkdownParser m String+linkTitle = quotedTitle '"' <|> quotedTitle '\''++link :: PandocMonad m => MarkdownParser m (F Inlines)+link = try $ do+  st <- getState+  guard $ stateAllowLinks st+  setState $ st{ stateAllowLinks = False }+  (lab,raw) <- reference+  setState $ st{ stateAllowLinks = True }+  regLink B.linkWith lab <|> referenceLink B.linkWith (lab,raw)++bracketedSpan :: PandocMonad m => MarkdownParser m (F Inlines)+bracketedSpan = try $ do+  guardEnabled Ext_bracketed_spans+  (lab,_) <- reference+  attr <- attributes+  return $ if isSmallCaps attr+              then B.smallcaps <$> lab+              else B.spanWith attr <$> lab++-- | We treat a span as SmallCaps if class is "smallcaps" (and+-- no other attributes are set or if style is "font-variant:small-caps"+-- (and no other attributes are set).+isSmallCaps :: Attr -> Bool+isSmallCaps ("",["smallcaps"],[]) = True+isSmallCaps ("",[],kvs) =+  case lookup "style" kvs of+       Just s -> map toLower (filter (`notElem` " \t;") s) ==+                    "font-variant:small-caps"+       Nothing -> False+isSmallCaps _ = False++regLink :: PandocMonad m+        => (Attr -> String -> String -> Inlines -> Inlines)+        -> F Inlines+        -> MarkdownParser m (F Inlines)+regLink constructor lab = try $ do+  (src, tit) <- source+  attr <- option nullAttr $+          guardEnabled Ext_link_attributes >> attributes+  return $ constructor attr src tit <$> lab++-- a link like [this][ref] or [this][] or [this]+referenceLink :: PandocMonad m+              => (Attr -> String -> String -> Inlines -> Inlines)+              -> (F Inlines, String)+              -> MarkdownParser m (F Inlines)+referenceLink constructor (lab, raw) = do+  sp <- (True <$ lookAhead (char ' ')) <|> return False+  (_,raw') <- option (mempty, "") $+      lookAhead (try (do guardEnabled Ext_citations+                         guardDisabled Ext_spaced_reference_links <|> spnl+                         normalCite+                         return (mempty, "")))+      <|>+      try ((guardDisabled Ext_spaced_reference_links <|> spnl) >> reference)+  when (raw' == "") $ guardEnabled Ext_shortcut_reference_links+  let labIsRef = raw' == "" || raw' == "[]"+  let key = toKey $ if labIsRef then raw else raw'+  parsedRaw <- parseFromString' inlines raw'+  fallback  <- parseFromString' inlines $ dropBrackets raw+  implicitHeaderRefs <- option False $+                         True <$ guardEnabled Ext_implicit_header_references+  let makeFallback = do+       parsedRaw' <- parsedRaw+       fallback' <- fallback+       return $ B.str "[" <> fallback' <> B.str "]" <>+                (if sp && not (null raw) then B.space else mempty) <>+                parsedRaw'+  return $ do+    keys <- asksF stateKeys+    case M.lookup key keys of+       Nothing        ->+         if implicitHeaderRefs+            then do+              headerKeys <- asksF stateHeaderKeys+              case M.lookup key headerKeys of+                   Just ((src, tit), _) -> constructor nullAttr src tit <$> lab+                   Nothing              -> makeFallback+            else makeFallback+       Just ((src,tit), attr) -> constructor attr src tit <$> lab++dropBrackets :: String -> String+dropBrackets = reverse . dropRB . reverse . dropLB+  where dropRB (']':xs) = xs+        dropRB xs       = xs+        dropLB ('[':xs) = xs+        dropLB xs       = xs++bareURL :: PandocMonad m => MarkdownParser m (F Inlines)+bareURL = try $ do+  guardEnabled Ext_autolink_bare_uris+  getState >>= guard . stateAllowLinks+  (orig, src) <- uri <|> emailAddress+  notFollowedBy $ try $ spaces >> htmlTag (~== TagClose "a")+  return $ return $ B.link src "" (B.str orig)++autoLink :: PandocMonad m => MarkdownParser m (F Inlines)+autoLink = try $ do+  getState >>= guard . stateAllowLinks+  char '<'+  (orig, src) <- uri <|> emailAddress+  -- in rare cases, something may remain after the uri parser+  -- is finished, because the uri parser tries to avoid parsing+  -- final punctuation.  for example:  in `<http://hi---there>`,+  -- the URI parser will stop before the dashes.+  extra <- fromEntities <$> manyTill nonspaceChar (char '>')+  attr  <- option nullAttr $ try $+            guardEnabled Ext_link_attributes >> attributes+  return $ return $ B.linkWith attr (src ++ escapeURI extra) "" (B.str $ orig ++ extra)++image :: PandocMonad m => MarkdownParser m (F Inlines)+image = try $ do+  char '!'+  (lab,raw) <- reference+  defaultExt <- getOption readerDefaultImageExtension+  let constructor attr' src = case takeExtension src of+                          "" -> B.imageWith attr' (addExtension src defaultExt)+                          _  -> B.imageWith attr' src+  regLink constructor lab <|> referenceLink constructor (lab,raw)++note :: PandocMonad m => MarkdownParser m (F Inlines)+note = try $ do+  guardEnabled Ext_footnotes+  ref <- noteMarker+  updateState $ \st -> st{ stateNoteRefs = Set.insert ref (stateNoteRefs st) }+  return $ do+    notes <- asksF stateNotes'+    case M.lookup ref notes of+        Nothing       -> return $ B.str $ "[^" ++ ref ++ "]"+        Just (_pos, contents) -> do+          st <- askF+          -- process the note in a context that doesn't resolve+          -- notes, to avoid infinite looping with notes inside+          -- notes:+          let contents' = runF contents st{ stateNotes' = M.empty }+          return $ B.note contents'++inlineNote :: PandocMonad m => MarkdownParser m (F Inlines)+inlineNote = try $ do+  guardEnabled Ext_inline_notes+  char '^'+  contents <- inlinesInBalancedBrackets+  return $ B.note . B.para <$> contents++rawLaTeXInline' :: PandocMonad m => MarkdownParser m (F Inlines)+rawLaTeXInline' = try $ do+  guardEnabled Ext_raw_tex+  lookAhead (char '\\')+  notFollowedBy' rawConTeXtEnvironment+  s <- rawLaTeXInline+  return $ return $ B.rawInline "tex" s -- "tex" because it might be context++rawConTeXtEnvironment :: PandocMonad m => ParserT [Char] st m String+rawConTeXtEnvironment = try $ do+  string "\\start"+  completion <- inBrackets (letter <|> digit <|> spaceChar)+               <|> many1 letter+  contents <- manyTill (rawConTeXtEnvironment <|> count 1 anyChar)+                       (try $ string "\\stop" >> string completion)+  return $ "\\start" ++ completion ++ concat contents ++ "\\stop" ++ completion++inBrackets :: PandocMonad m => (ParserT [Char] st m Char) -> ParserT [Char] st m String+inBrackets parser = do+  char '['+  contents <- many parser+  char ']'+  return $ "[" ++ contents ++ "]"++spanHtml :: PandocMonad m => MarkdownParser m (F Inlines)+spanHtml = try $ do+  guardEnabled Ext_native_spans+  (TagOpen _ attrs, _) <- htmlTag (~== TagOpen "span" [])+  contents <- mconcat <$> manyTill inline (htmlTag (~== TagClose "span"))+  let ident = fromMaybe "" $ lookup "id" attrs+  let classes = maybe [] words $ lookup "class" attrs+  let keyvals = [(k,v) | (k,v) <- attrs, k /= "id" && k /= "class"]+  return $ if isSmallCaps (ident, classes, keyvals)+              then B.smallcaps <$> contents+              else B.spanWith (ident, classes, keyvals) <$> contents++divHtml :: PandocMonad m => MarkdownParser m (F Blocks)+divHtml = try $ do+  guardEnabled Ext_native_divs+  (TagOpen _ attrs, rawtag) <- htmlTag (~== TagOpen "div" [])+  -- we set stateInHtmlBlock so that closing tags that can be either block or+  -- inline will not be parsed as inline tags+  oldInHtmlBlock <- stateInHtmlBlock <$> getState+  updateState $ \st -> st{ stateInHtmlBlock = Just "div" }+  bls <- option "" (blankline >> option "" blanklines)+  contents <- mconcat <$>+              many (notFollowedBy' (htmlTag (~== TagClose "div")) >> block)+  closed <- option False (True <$ htmlTag (~== TagClose "div"))+  if closed+     then do+       updateState $ \st -> st{ stateInHtmlBlock = oldInHtmlBlock }+       let ident = fromMaybe "" $ lookup "id" attrs+       let classes = maybe [] words $ lookup "class" attrs+       let keyvals = [(k,v) | (k,v) <- attrs, k /= "id" && k /= "class"]+       return $ B.divWith (ident, classes, keyvals) <$> contents+     else -- avoid backtracing+       return $ return (B.rawBlock "html" (rawtag <> bls)) <> contents++divFenced :: PandocMonad m => MarkdownParser m (F Blocks)+divFenced = try $ do+  guardEnabled Ext_fenced_divs+  nonindentSpaces+  string ":::"+  skipMany (char ':')+  skipMany spaceChar+  attribs <- attributes <|> ((\x -> ("",[x],[])) <$> many1 nonspaceChar)+  skipMany spaceChar+  skipMany (char ':')+  blankline+  updateState $ \st -> st{ stateFencedDivLevel = stateFencedDivLevel st + 1 }+  bs <- mconcat <$> manyTill block divFenceEnd+  updateState $ \st -> st{ stateFencedDivLevel = stateFencedDivLevel st - 1 }+  return $ B.divWith attribs <$> bs++divFenceEnd :: PandocMonad m => MarkdownParser m ()+divFenceEnd = try $ do+  nonindentSpaces+  string ":::"+  skipMany (char ':')+  blanklines+  return ()++rawHtmlInline :: PandocMonad m => MarkdownParser m (F Inlines)+rawHtmlInline = do+  guardEnabled Ext_raw_html+  inHtmlBlock <- stateInHtmlBlock <$> getState+  let isCloseBlockTag t = case inHtmlBlock of+                               Just t' -> t ~== TagClose t'+                               Nothing -> False+  mdInHtml <- option False $+                (    guardEnabled Ext_markdown_in_html_blocks+                 <|> guardEnabled Ext_markdown_attribute+                ) >> return True+  (_,result) <- htmlTag $ if mdInHtml+                             then (\x -> isInlineTag x &&+                                         not (isCloseBlockTag x))+                             else not . isTextTag+  return $ return $ B.rawInline "html" result++-- Emoji++emojiChars :: [Char]+emojiChars = ['a'..'z'] ++ ['0'..'9'] ++ ['_','+','-']++emoji :: PandocMonad m => MarkdownParser m (F Inlines)+emoji = try $ do+  guardEnabled Ext_emoji+  char ':'+  emojikey <- many1 (oneOf emojiChars)+  char ':'+  case M.lookup emojikey emojis of+       Just s  -> return (return (B.str s))+       Nothing -> mzero++-- Citations++cite :: PandocMonad m => MarkdownParser m (F Inlines)+cite = do+  guardEnabled Ext_citations+  textualCite+            <|> do (cs, raw) <- withRaw normalCite+                   return $ (flip B.cite (B.text raw)) <$> cs++textualCite :: PandocMonad m => MarkdownParser m (F Inlines)+textualCite = try $ do+  (suppressAuthor, key) <- citeKey+  let first = Citation{ citationId      = key+                      , citationPrefix  = []+                      , citationSuffix  = []+                      , citationMode    = if suppressAuthor+                                             then SuppressAuthor+                                             else AuthorInText+                      , citationNoteNum = 0+                      , citationHash    = 0+                      }+  mbrest <- option Nothing $ try $ spnl >> Just <$> withRaw normalCite+  case mbrest of+       Just (rest, raw) ->+         return $ (flip B.cite (B.text $ '@':key ++ " " ++ raw) . (first:))+               <$> rest+       Nothing   ->+         (do+          (cs, raw) <- withRaw $ bareloc first+          let (spaces',raw') = span isSpace raw+              spc | null spaces' = mempty+                  | otherwise    = B.space+          lab <- parseFromString' inlines $ dropBrackets raw'+          fallback <- referenceLink B.linkWith (lab,raw')+          return $ do+            fallback' <- fallback+            cs' <- cs+            return $+              case B.toList fallback' of+                Link{}:_ -> B.cite [first] (B.str $ '@':key) <> spc <> fallback'+                _        -> B.cite cs' (B.text $ '@':key ++ " " ++ raw))+         <|> return (do st <- askF+                        return $ case M.lookup key (stateExamples st) of+                                 Just n -> B.str (show n)+                                 _      -> B.cite [first] $ B.str $ '@':key)++bareloc :: PandocMonad m => Citation -> MarkdownParser m (F [Citation])+bareloc c = try $ do+  spnl+  char '['+  notFollowedBy $ char '^'+  suff <- suffix+  rest <- option (return []) $ try $ char ';' >> citeList+  spnl+  char ']'+  notFollowedBy $ oneOf "[("+  return $ do+    suff' <- suff+    rest' <- rest+    return $ c{ citationSuffix = B.toList suff' } : rest'++normalCite :: PandocMonad m => MarkdownParser m (F [Citation])+normalCite = try $ do+  char '['+  spnl+  citations <- citeList+  spnl+  char ']'+  return citations++suffix :: PandocMonad m => MarkdownParser m (F Inlines)+suffix = try $ do+  hasSpace <- option False (notFollowedBy nonspaceChar >> return True)+  spnl+  rest <- trimInlinesF . mconcat <$> many (notFollowedBy (oneOf ";]") >> inline)+  return $ if hasSpace+              then (B.space <>) <$> rest+              else rest++prefix :: PandocMonad m => MarkdownParser m (F Inlines)+prefix = trimInlinesF . mconcat <$>+  manyTill inline (char ']' <|> fmap (const ']') (lookAhead citeKey))++citeList :: PandocMonad m => MarkdownParser m (F [Citation])+citeList = fmap sequence $ sepBy1 citation (try $ char ';' >> spnl)++citation :: PandocMonad m => MarkdownParser m (F Citation)+citation = try $ do+  pref <- prefix+  (suppress_author, key) <- citeKey+  suff <- suffix+  return $ do+    x <- pref+    y <- suff+    return $ Citation{ citationId      = key+                     , citationPrefix  = B.toList x+                     , citationSuffix  = B.toList y+                     , citationMode    = if suppress_author+                                            then SuppressAuthor+                                            else NormalCitation+                     , citationNoteNum = 0+                     , citationHash    = 0+                     }++smart :: PandocMonad m => MarkdownParser m (F Inlines)+smart = do+  guardEnabled Ext_smart+  doubleQuoted <|> singleQuoted <|>+    choice (map (return <$>) [apostrophe, dash, ellipses])++singleQuoted :: PandocMonad m => MarkdownParser m (F Inlines)+singleQuoted = try $ do+  singleQuoteStart+  withQuoteContext InSingleQuote $+    fmap B.singleQuoted . trimInlinesF . mconcat <$>+      many1Till inline singleQuoteEnd++-- doubleQuoted will handle regular double-quoted sections, as well+-- as dialogues with an open double-quote without a close double-quote+-- in the same paragraph.+doubleQuoted :: PandocMonad m => MarkdownParser m (F Inlines) doubleQuoted = try $ do   doubleQuoteStart   contents <- mconcat <$> many (try $ notFollowedBy doubleQuoteEnd >> inline)
src/Text/Pandoc/Readers/MediaWiki.hs view
@@ -1,7 +1,9 @@-{-# LANGUAGE RelaxedPolyRec, FlexibleInstances, TypeSynonymInstances #-}+{-# LANGUAGE FlexibleInstances    #-}+{-# LANGUAGE RelaxedPolyRec       #-}+{-# LANGUAGE TypeSynonymInstances #-} -- RelaxedPolyRec needed for inlinesBetween on GHC < 7 {--  Copyright (C) 2012-2015 John MacFarlane <jgm@berkeley.edu>+  Copyright (C) 2012-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -20,7 +22,7 @@  {- |    Module      : Text.Pandoc.Readers.MediaWiki-   Copyright   : Copyright (C) 2012-2015 John MacFarlane+   Copyright   : Copyright (C) 2012-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -36,43 +38,50 @@ -} module Text.Pandoc.Readers.MediaWiki ( readMediaWiki ) where -import Text.Pandoc.Definition-import qualified Text.Pandoc.Builder as B-import Text.Pandoc.Builder (Inlines, Blocks, trimInlines)-import Data.Monoid ((<>))-import Text.Pandoc.Options-import Text.Pandoc.Readers.HTML ( htmlTag, isBlockTag, isCommentTag )-import Text.Pandoc.XML ( fromEntities )-import Text.Pandoc.Parsing hiding ( nested )-import Text.Pandoc.Walk ( walk )-import Text.Pandoc.Shared ( stripTrailingNewlines, safeRead, stringify, trim ) import Control.Monad-import Data.List (intersperse, intercalate, isPrefixOf )-import Text.HTML.TagSoup-import Data.Sequence (viewl, ViewL(..), (<|))+import Control.Monad.Except (throwError)+import Data.Char (isDigit, isSpace) import qualified Data.Foldable as F+import Data.List (intercalate, intersperse, isPrefixOf) import qualified Data.Map as M-import qualified Data.Set as Set-import Data.Char (isDigit, isSpace) import Data.Maybe (fromMaybe)-import Text.Printf (printf)-import Debug.Trace (trace)--import Text.Pandoc.Error+import Data.Monoid ((<>))+import Data.Sequence (ViewL (..), viewl, (<|))+import qualified Data.Set as Set+import Data.Text (Text, unpack)+import Text.HTML.TagSoup+import Text.Pandoc.Builder (Blocks, Inlines, trimInlines)+import qualified Text.Pandoc.Builder as B+import Text.Pandoc.Class (PandocMonad (..))+import Text.Pandoc.Definition+import Text.Pandoc.Logging+import Text.Pandoc.Options+import Text.Pandoc.Parsing hiding (nested)+import Text.Pandoc.Readers.HTML (htmlTag, isBlockTag, isCommentTag)+import Text.Pandoc.Shared (crFilter, safeRead, stringify, stripTrailingNewlines,+                           trim)+import Text.Pandoc.Walk (walk)+import Text.Pandoc.XML (fromEntities)  -- | Read mediawiki from an input string and return a Pandoc document.-readMediaWiki :: ReaderOptions -- ^ Reader options-              -> String        -- ^ String to parse (assuming @'\n'@ line endings)-              -> Either PandocError Pandoc-readMediaWiki opts s =-  readWith parseMediaWiki MWState{ mwOptions = opts-                                       , mwMaxNestingLevel = 4-                                       , mwNextLinkNumber  = 1-                                       , mwCategoryLinks = []-                                       , mwHeaderMap = M.empty-                                       , mwIdentifierList = Set.empty-                                       }-           (s ++ "\n")+readMediaWiki :: PandocMonad m+              => ReaderOptions -- ^ Reader options+              -> Text          -- ^ String to parse (assuming @'\n'@ line endings)+              -> m Pandoc+readMediaWiki opts s = do+  parsed <- readWithM parseMediaWiki MWState{ mwOptions = opts+                                            , mwMaxNestingLevel = 4+                                            , mwNextLinkNumber  = 1+                                            , mwCategoryLinks = []+                                            , mwHeaderMap = M.empty+                                            , mwIdentifierList = Set.empty+                                            , mwLogMessages = []+                                            , mwInTT = False+                                            }+            (unpack (crFilter s) ++ "\n")+  case parsed of+    Right result -> return result+    Left e       -> throwError e  data MWState = MWState { mwOptions         :: ReaderOptions                        , mwMaxNestingLevel :: Int@@ -80,9 +89,11 @@                        , mwCategoryLinks   :: [Inlines]                        , mwHeaderMap       :: M.Map Inlines String                        , mwIdentifierList  :: Set.Set String+                       , mwLogMessages     :: [LogMessage]+                       , mwInTT            :: Bool                        } -type MWParser = Parser [Char] MWState+type MWParser m = ParserT [Char] MWState m  instance HasReaderOptions MWState where   extractReaderOptions = mwOptions@@ -95,13 +106,17 @@   extractIdentifierList     = mwIdentifierList   updateIdentifierList f st = st{ mwIdentifierList = f $ mwIdentifierList st } +instance HasLogMessages MWState where+  addLogMessage m s = s{ mwLogMessages = m : mwLogMessages s }+  getLogMessages = reverse . mwLogMessages+ -- -- auxiliary functions --  -- This is used to prevent exponential blowups for things like: -- ''a'''a''a'''a''a'''a''a'''a-nested :: MWParser a -> MWParser a+nested :: PandocMonad m => MWParser m a -> MWParser m a nested p = do   nestlevel <- mwMaxNestingLevel `fmap` getState   guard $ nestlevel > 0@@ -116,7 +131,7 @@ spaceChars :: [Char] spaceChars = " \n\t" -sym :: String -> MWParser ()+sym :: PandocMonad m => String -> MWParser m () sym s = () <$ try (string s)  newBlockTags :: [String]@@ -131,16 +146,16 @@  isInlineTag' :: Tag String -> Bool isInlineTag' (TagComment _) = True-isInlineTag' t = not (isBlockTag' t)+isInlineTag' t              = not (isBlockTag' t)  eitherBlockOrInline :: [String] eitherBlockOrInline = ["applet", "button", "del", "iframe", "ins",                                "map", "area", "object"] -htmlComment :: MWParser ()+htmlComment :: PandocMonad m => MWParser m () htmlComment = () <$ htmlTag isCommentTag -inlinesInTags :: String -> MWParser Inlines+inlinesInTags :: PandocMonad m => String -> MWParser m Inlines inlinesInTags tag = try $ do   (_,raw) <- htmlTag (~== TagOpen tag [])   if '/' `elem` raw   -- self-closing tag@@ -148,7 +163,7 @@      else trimInlines . mconcat <$>             manyTill inline (htmlTag (~== TagClose tag)) -blocksInTags :: String -> MWParser Blocks+blocksInTags :: PandocMonad m => String -> MWParser m Blocks blocksInTags tag = try $ do   (_,raw) <- htmlTag (~== TagOpen tag [])   let closer = if tag == "li"@@ -162,7 +177,7 @@      then return mempty      else mconcat <$> manyTill block closer -charsInTags :: String -> MWParser [Char]+charsInTags :: PandocMonad m => String -> MWParser m [Char] charsInTags tag = try $ do   (_,raw) <- htmlTag (~== TagOpen tag [])   if '/' `elem` raw   -- self-closing tag@@ -173,7 +188,7 @@ -- main parser -- -parseMediaWiki :: MWParser Pandoc+parseMediaWiki :: PandocMonad m => MWParser m Pandoc parseMediaWiki = do   bs <- mconcat <$> many block   spaces@@ -182,16 +197,15 @@   let categories = if null categoryLinks                       then mempty                       else B.para $ mconcat $ intersperse B.space categoryLinks+  reportLogMessages   return $ B.doc $ bs <> categories  -- -- block parsers -- -block :: MWParser Blocks+block :: PandocMonad m => MWParser m Blocks block = do-  tr <- getOption readerTrace-  pos <- getPosition   res <- mempty <$ skipMany1 blankline      <|> table      <|> header@@ -204,22 +218,22 @@      <|> blockTag      <|> (B.rawBlock "mediawiki" <$> template)      <|> para-  when tr $-    trace (printf "line %d: %s" (sourceLine pos)-           (take 60 $ show $ B.toList res)) (return ())+  trace (take 60 $ show $ B.toList res)   return res -para :: MWParser Blocks+para :: PandocMonad m => MWParser m Blocks para = do   contents <- trimInlines . mconcat <$> many1 inline   if F.all (==Space) contents      then return mempty      else return $ B.para contents -table :: MWParser Blocks+table :: PandocMonad m => MWParser m Blocks table = do   tableStart-  styles <- option [] parseAttrs <* blankline+  styles <- option [] parseAttrs+  skipMany spaceChar+  optional blanklines   let tableWidth = case lookup "width" styles of                          Just w  -> fromMaybe 1.0 $ parseWidth w                          Nothing -> 1.0@@ -244,10 +258,10 @@                           else (replicate cols mempty, hdr:rows')   return $ B.table caption cellspecs headers rows -parseAttrs :: MWParser [(String,String)]+parseAttrs :: PandocMonad m => MWParser m [(String,String)] parseAttrs = many1 parseAttr -parseAttr :: MWParser (String, String)+parseAttr :: PandocMonad m => MWParser m (String, String) parseAttr = try $ do   skipMany spaceChar   k <- many1 letter@@ -256,27 +270,23 @@        <|> many1 (satisfy $ \c -> not (isSpace c) && c /= '|')   return (k,v) -tableStart :: MWParser ()+tableStart :: PandocMonad m => MWParser m () tableStart = try $ guardColumnOne *> skipSpaces *> sym "{|" -tableEnd :: MWParser ()+tableEnd :: PandocMonad m => MWParser m () tableEnd = try $ guardColumnOne *> skipSpaces *> sym "|}" -rowsep :: MWParser ()+rowsep :: PandocMonad m => MWParser m () rowsep = try $ guardColumnOne *> skipSpaces *> sym "|-" <*-               optional parseAttr <* blanklines+               many (char '-') <* optional parseAttr <* blanklines -cellsep :: MWParser ()-cellsep = try $-             (guardColumnOne *> skipSpaces <*-                 (  (char '|' <* notFollowedBy (oneOf "-}+"))-                <|> (char '!')-                 )-             )-            <|> (() <$ try (string "||"))-            <|> (() <$ try (string "!!"))+cellsep :: PandocMonad m => MWParser m ()+cellsep = try $ do+  skipSpaces+  (char '|' *> notFollowedBy (oneOf "-}+") *> optional (char '|'))+    <|> (char '!' *> optional (char '!')) -tableCaption :: MWParser Inlines+tableCaption :: PandocMonad m => MWParser m Inlines tableCaption = try $ do   guardColumnOne   skipSpaces@@ -284,19 +294,21 @@   optional (try $ parseAttr *> skipSpaces *> char '|' *> skipSpaces)   (trimInlines . mconcat) <$> many (notFollowedBy (cellsep <|> rowsep) *> inline) -tableRow :: MWParser [((Alignment, Double), Blocks)]+tableRow :: PandocMonad m => MWParser m [((Alignment, Double), Blocks)] tableRow = try $ skipMany htmlComment *> many tableCell -tableCell :: MWParser ((Alignment, Double), Blocks)+tableCell :: PandocMonad m => MWParser m ((Alignment, Double), Blocks) tableCell = try $ do   cellsep   skipMany spaceChar   attrs <- option [] $ try $ parseAttrs <* skipSpaces <* char '|' <*                                  notFollowedBy (char '|')   skipMany spaceChar+  pos' <- getPosition   ls <- concat <$> many (notFollowedBy (cellsep <|> rowsep <|> tableEnd) *>                      ((snd <$> withRaw table) <|> count 1 anyChar))-  bs <- parseFromString (mconcat <$> many block) ls+  bs <- parseFromString (do setPosition pos'+                            mconcat <$> many block) ls   let align = case lookup "align" attrs of                     Just "left"   -> AlignLeft                     Just "right"  -> AlignRight@@ -311,9 +323,9 @@ parseWidth s =   case reverse s of        ('%':ds) | all isDigit ds -> safeRead ('0':'.':reverse ds)-       _ -> Nothing+       _        -> Nothing -template :: MWParser String+template :: PandocMonad m => MWParser m String template = try $ do   string "{{"   notFollowedBy (char '{')@@ -322,7 +334,7 @@   contents <- manyTill chunk (try $ string "}}")   return $ "{{" ++ concat contents ++ "}}" -blockTag :: MWParser Blocks+blockTag :: PandocMonad m => MWParser m Blocks blockTag = do   (tag, _) <- lookAhead $ htmlTag isBlockTag'   case tag of@@ -341,7 +353,7 @@ trimCode ('\n':xs) = stripTrailingNewlines xs trimCode xs        = stripTrailingNewlines xs -syntaxhighlight :: String -> [Attribute String] -> MWParser Blocks+syntaxhighlight :: PandocMonad m => String -> [Attribute String] -> MWParser m Blocks syntaxhighlight tag attrs = try $ do   let mblang = lookup "lang" attrs   let mbstart = lookup "start" attrs@@ -351,13 +363,13 @@   contents <- charsInTags tag   return $ B.codeBlockWith ("",classes,kvs) $ trimCode contents -hrule :: MWParser Blocks+hrule :: PandocMonad m => MWParser m Blocks hrule = B.horizontalRule <$ try (string "----" *> many (char '-') *> newline) -guardColumnOne :: MWParser ()+guardColumnOne :: PandocMonad m => MWParser m () guardColumnOne = getPosition >>= \pos -> guard (sourceColumn pos == 1) -preformatted :: MWParser Blocks+preformatted :: PandocMonad m => MWParser m Blocks preformatted = try $ do   guardColumnOne   char ' '@@ -388,7 +400,7 @@           normalizeCode $ (Code a1 (x ++ y)) : zs         normalizeCode (x:xs) = x : normalizeCode xs -header :: MWParser Blocks+header :: PandocMonad m => MWParser m Blocks header = try $ do   guardColumnOne   eqs <- many1 (char '=')@@ -398,13 +410,13 @@   attr <- registerHeader nullAttr contents   return $ B.headerWith attr lev contents -bulletList :: MWParser Blocks+bulletList :: PandocMonad m => MWParser m Blocks bulletList = B.bulletList <$>    (   many1 (listItem '*')    <|> (htmlTag (~== TagOpen "ul" []) *> spaces *> many (listItem '*' <|> li) <*         optional (htmlTag (~== TagClose "ul"))) ) -orderedList :: MWParser Blocks+orderedList :: PandocMonad m => MWParser m Blocks orderedList =        (B.orderedList <$> many1 (listItem '#'))    <|> try@@ -415,10 +427,10 @@            let start = fromMaybe 1 $ safeRead $ fromAttrib "start" tag            return $ B.orderedListWith (start, DefaultStyle, DefaultDelim) items) -definitionList :: MWParser Blocks+definitionList :: PandocMonad m => MWParser m Blocks definitionList = B.definitionList <$> many1 defListItem -defListItem :: MWParser (Inlines, [Blocks])+defListItem :: PandocMonad m => MWParser m (Inlines, [Blocks]) defListItem = try $ do   terms <- mconcat . intersperse B.linebreak <$> many defListTerm   -- we allow dd with no dt, or dt with no dd@@ -429,44 +441,49 @@               else many (listItem ':')   return (terms, defs) -defListTerm  :: MWParser Inlines-defListTerm = char ';' >> skipMany spaceChar >> anyLine >>=-  parseFromString (trimInlines . mconcat <$> many inline)+defListTerm  :: PandocMonad m => MWParser m Inlines+defListTerm = do+  guardColumnOne+  char ';'+  skipMany spaceChar+  pos' <- getPosition+  anyLine >>= parseFromString (do setPosition pos'+                                  trimInlines . mconcat <$> many inline) -listStart :: Char -> MWParser ()+listStart :: PandocMonad m => Char -> MWParser m () listStart c = char c *> notFollowedBy listStartChar -listStartChar :: MWParser Char+listStartChar :: PandocMonad m => MWParser m Char listStartChar = oneOf "*#;:" -anyListStart :: MWParser Char-anyListStart =  char '*'-            <|> char '#'-            <|> char ':'-            <|> char ';'+anyListStart :: PandocMonad m => MWParser m Char+anyListStart = guardColumnOne >> oneOf "*#:;" -li :: MWParser Blocks+li :: PandocMonad m => MWParser m Blocks li = lookAhead (htmlTag (~== TagOpen "li" [])) *>      (firstParaToPlain <$> blocksInTags "li") <* spaces -listItem :: Char -> MWParser Blocks+listItem :: PandocMonad m => Char -> MWParser m Blocks listItem c = try $ do+  guardColumnOne   extras <- many (try $ char c <* lookAhead listStartChar)   if null extras      then listItem' c      else do        skipMany spaceChar+       pos' <- getPosition        first <- concat <$> manyTill listChunk newline        rest <- many                 (try $ string extras *> lookAhead listStartChar *>                        (concat <$> manyTill listChunk newline))-       contents <- parseFromString (many1 $ listItem' c)+       contents <- parseFromString (do setPosition pos'+                                       many1 $ listItem' c)                           (unlines (first : rest))        case c of-           '*'  -> return $ B.bulletList contents-           '#'  -> return $ B.orderedList contents-           ':'  -> return $ B.definitionList [(mempty, contents)]-           _    -> mzero+           '*' -> return $ B.bulletList contents+           '#' -> return $ B.orderedList contents+           ':' -> return $ B.definitionList [(mempty, contents)]+           _   -> mzero  -- The point of this is to handle stuff like -- * {{cite book@@ -475,17 +492,19 @@ -- }} -- * next list item -- which seems to be valid mediawiki.-listChunk :: MWParser String+listChunk :: PandocMonad m => MWParser m String listChunk = template <|> count 1 anyChar -listItem' :: Char -> MWParser Blocks+listItem' :: PandocMonad m => Char -> MWParser m Blocks listItem' c = try $ do   listStart c   skipMany spaceChar+  pos' <- getPosition   first <- concat <$> manyTill listChunk newline   rest <- many (try $ char c *> lookAhead listStartChar *>                    (concat <$> manyTill listChunk newline))-  parseFromString (firstParaToPlain . mconcat <$> many1 block)+  parseFromString (do setPosition pos'+                      firstParaToPlain . mconcat <$> many1 block)       $ unlines $ first : rest  firstParaToPlain :: Blocks -> Blocks@@ -498,7 +517,7 @@ -- inline parsers -- -inline :: MWParser Inlines+inline :: PandocMonad m => MWParser m Inlines inline =  whitespace       <|> url       <|> str@@ -516,10 +535,10 @@       <|> (B.rawInline "mediawiki" <$> template)       <|> special -str :: MWParser Inlines+str :: PandocMonad m => MWParser m Inlines str = B.str <$> many1 (noneOf $ specialChars ++ spaceChars) -math :: MWParser Inlines+math :: PandocMonad m => MWParser m Inlines math = (B.displayMath . trim <$> try (many1 (char ':') >> charsInTags "math"))    <|> (B.math . trim <$> charsInTags "math")    <|> (B.displayMath . trim <$> try (dmStart *> manyTill anyChar dmEnd))@@ -529,13 +548,13 @@        mStart  = string "\\("        mEnd    = try (string "\\)") -variable :: MWParser String+variable :: PandocMonad m => MWParser m String variable = try $ do   string "{{{"   contents <- manyTill anyChar (try $ string "}}}")   return $ "{{{" ++ contents ++ "}}}" -inlineTag :: MWParser Inlines+inlineTag :: PandocMonad m => MWParser m Inlines inlineTag = do   (tag, _) <- lookAhead $ htmlTag isInlineTag'   case tag of@@ -553,22 +572,27 @@        TagOpen "sub" _ -> B.subscript <$> inlinesInTags "sub"        TagOpen "sup" _ -> B.superscript <$> inlinesInTags "sup"        TagOpen "code" _ -> encode <$> inlinesInTags "code"-       TagOpen "tt" _ -> encode <$> inlinesInTags "tt"+       TagOpen "tt" _ -> do+         inTT <- mwInTT <$> getState+         updateState $ \st -> st{ mwInTT = True }+         result <- encode <$> inlinesInTags "tt"+         updateState $ \st -> st{ mwInTT = inTT }+         return result        TagOpen "hask" _ -> B.codeWith ("",["haskell"],[]) <$> charsInTags "hask"        _ -> B.rawInline "html" . snd <$> htmlTag (~== tag) -special :: MWParser Inlines+special :: PandocMonad m => MWParser m Inlines special = B.str <$> count 1 (notFollowedBy' (htmlTag isBlockTag') *>                              oneOf specialChars) -inlineHtml :: MWParser Inlines+inlineHtml :: PandocMonad m => MWParser m Inlines inlineHtml = B.rawInline "html" . snd <$> htmlTag isInlineTag' -whitespace :: MWParser Inlines+whitespace :: PandocMonad m => MWParser m Inlines whitespace = B.space <$ (skipMany1 spaceChar <|> htmlComment)          <|> B.softbreak <$ endline -endline :: MWParser ()+endline :: PandocMonad m => MWParser m () endline = () <$ try (newline <*                      notFollowedBy spaceChar <*                      notFollowedBy newline <*@@ -577,12 +601,12 @@                      notFollowedBy' header <*                      notFollowedBy anyListStart) -imageIdentifiers :: [MWParser ()]+imageIdentifiers :: PandocMonad m => [MWParser m ()] imageIdentifiers = [sym (identifier ++ ":") | identifier <- identifiers]     where identifiers = ["File", "Image", "Archivo", "Datei", "Fichier",                          "Bild"] -image :: MWParser Inlines+image :: PandocMonad m => MWParser m Inlines image = try $ do   sym "[["   choice imageIdentifiers@@ -600,7 +624,7 @@            <|> try (char '|' *> (mconcat <$> manyTill inline (sym "]]")))   return $ B.imageWith attr fname ("fig:" ++ stringify caption) caption -imageOption :: MWParser String+imageOption :: PandocMonad m => MWParser m String imageOption = try $ char '|' *> opt   where     opt = try (oneOfStrings [ "border", "thumbnail", "frameless"@@ -612,14 +636,14 @@       <|> try (oneOfStrings ["link=","alt=","page=","class="] <* many (noneOf "|]"))  collapseUnderscores :: String -> String-collapseUnderscores [] = []+collapseUnderscores []           = [] collapseUnderscores ('_':'_':xs) = collapseUnderscores ('_':xs)-collapseUnderscores (x:xs) = x : collapseUnderscores xs+collapseUnderscores (x:xs)       = x : collapseUnderscores xs  addUnderscores :: String -> String addUnderscores = collapseUnderscores . intercalate "_" . words -internalLink :: MWParser Inlines+internalLink :: PandocMonad m => MWParser m Inlines internalLink = try $ do   sym "[["   pagename <- unwords . words <$> many (noneOf "|]")@@ -637,7 +661,7 @@        return mempty      else return link -externalLink :: MWParser Inlines+externalLink :: PandocMonad m => MWParser m Inlines externalLink = try $ do   char '['   (_, src) <- uri@@ -649,29 +673,33 @@               return $ B.str $ show num   return $ B.link src "" lab -url :: MWParser Inlines+url :: PandocMonad m => MWParser m Inlines url = do   (orig, src) <- uri   return $ B.link src "" (B.str orig)  -- | Parses a list of inlines between start and end delimiters.-inlinesBetween :: (Show b) => MWParser a -> MWParser b -> MWParser Inlines+inlinesBetween :: (PandocMonad m, Show b) => MWParser m a -> MWParser m b -> MWParser m Inlines inlinesBetween start end =   (trimInlines . mconcat) <$> try (start >> many1Till inner end)     where inner      = innerSpace <|> (notFollowedBy' (() <$ whitespace) >> inline)           innerSpace = try $ whitespace <* notFollowedBy' end -emph :: MWParser Inlines+emph :: PandocMonad m => MWParser m Inlines emph = B.emph <$> nested (inlinesBetween start end)     where start = sym "''" >> lookAhead nonspaceChar           end   = try $ notFollowedBy' (() <$ strong) >> sym "''" -strong :: MWParser Inlines+strong :: PandocMonad m => MWParser m Inlines strong = B.strong <$> nested (inlinesBetween start end)     where start = sym "'''" >> lookAhead nonspaceChar           end   = try $ sym "'''" -doubleQuotes :: MWParser Inlines-doubleQuotes = B.doubleQuoted <$> nested (inlinesBetween openDoubleQuote closeDoubleQuote)+doubleQuotes :: PandocMonad m => MWParser m Inlines+doubleQuotes = do+  guardEnabled Ext_smart+  inTT <- mwInTT <$> getState+  guard (not inTT)+  B.doubleQuoted <$> nested (inlinesBetween openDoubleQuote closeDoubleQuote)     where openDoubleQuote = sym "\"" >> lookAhead nonspaceChar           closeDoubleQuote = try $ sym "\""
+ src/Text/Pandoc/Readers/Muse.hs view
@@ -0,0 +1,691 @@+{-# LANGUAGE FlexibleContexts      #-}+{-+  Copyright (C) 2017 Alexander Krotov <ilabdsf@gmail.com>++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation; either version 2 of the License, or+(at your option) any later version.++This program is distributed in the hope that it will be useful,+but WITHOUT ANY WARRANTY; without even the implied warranty of+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+GNU General Public License for more details.++You should have received a copy of the GNU General Public License+along with this program; if not, write to the Free Software+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+-}++{- |+   Module      : Text.Pandoc.Readers.Muse+   Copyright   : Copyright (C) 2017 Alexander Krotov+   License     : GNU GPL, version 2 or above++   Maintainer  : Alexander Krotov <ilabdsf@gmail.com>+   Stability   : alpha+   Portability : portable++Conversion of Muse text to 'Pandoc' document.+-}+{-+TODO:+- Page breaks (five "*")+- Headings with anchors (make it round trip with Muse writer)+- Org tables+- table.el tables+- Images with attributes (floating and width)+- Citations and <biblio>+- <play> environment+-}+module Text.Pandoc.Readers.Muse (readMuse) where++import Control.Monad+import Control.Monad.Except (throwError)+import Data.Char (isLetter)+import Data.List (stripPrefix)+import qualified Data.Map as M+import Data.Maybe (fromMaybe)+import Data.Text (Text, unpack)+import System.FilePath (takeExtension)+import Text.HTML.TagSoup+import Text.Pandoc.Builder (Blocks, Inlines)+import qualified Text.Pandoc.Builder as B+import Text.Pandoc.Class (PandocMonad (..))+import Text.Pandoc.Definition+import Text.Pandoc.Logging+import Text.Pandoc.Options+import Text.Pandoc.Parsing hiding (nested)+import Text.Pandoc.Readers.HTML (htmlTag)+import Text.Pandoc.Shared (crFilter)+import Text.Pandoc.XML (fromEntities)++-- | Read Muse from an input string and return a Pandoc document.+readMuse :: PandocMonad m+         => ReaderOptions+         -> Text+         -> m Pandoc+readMuse opts s = do+  res <- readWithM parseMuse def{ stateOptions = opts } (unpack (crFilter s))+  case res of+       Left e  -> throwError e+       Right d -> return d++type MuseParser = ParserT String ParserState++--+-- main parser+--++parseMuse :: PandocMonad m => MuseParser m Pandoc+parseMuse = do+  many directive+  blocks <- parseBlocks+  st <- getState+  let doc = runF (do Pandoc _ bs <- B.doc <$> blocks+                     meta <- stateMeta' st+                     return $ Pandoc meta bs) st+  reportLogMessages+  return doc++parseBlocks :: PandocMonad m => MuseParser m (F Blocks)+parseBlocks = do+  res <- mconcat <$> many block+  spaces+  eof+  return res++--+-- utility functions+--++eol :: Stream s m Char => ParserT s st m ()+eol = void newline <|> eof++nested :: PandocMonad m => MuseParser m a -> MuseParser m a+nested p = do+  nestlevel <- stateMaxNestingLevel <$>  getState+  guard $ nestlevel > 0+  updateState $ \st -> st{ stateMaxNestingLevel = stateMaxNestingLevel st - 1 }+  res <- p+  updateState $ \st -> st{ stateMaxNestingLevel = nestlevel }+  return res++htmlElement :: PandocMonad m => String -> MuseParser m (Attr, String)+htmlElement tag = try $ do+  (TagOpen _ attr, _) <- htmlTag (~== TagOpen tag [])+  content <- manyTill anyChar endtag+  return (htmlAttrToPandoc attr, content)+  where+    endtag = void $ htmlTag (~== TagClose tag)++htmlAttrToPandoc :: [Attribute String] -> Attr+htmlAttrToPandoc attrs = (ident, classes, keyvals)+  where+    ident   = fromMaybe "" $ lookup "id" attrs+    classes = maybe [] words $ lookup "class" attrs+    keyvals = [(k,v) | (k,v) <- attrs, k /= "id" && k /= "class"]++parseHtmlContentWithAttrs :: PandocMonad m+                          => String -> MuseParser m a -> MuseParser m (Attr, [a])+parseHtmlContentWithAttrs tag parser = do+  (attr, content) <- htmlElement tag+  parsedContent <- parseContent (content ++ "\n")+  return (attr, parsedContent)+  where+    parseContent = parseFromString $ nested $ manyTill parser endOfContent+    endOfContent = try $ skipMany blankline >> skipSpaces >> eof++parseHtmlContent :: PandocMonad m => String -> MuseParser m a -> MuseParser m [a]+parseHtmlContent tag p = fmap snd (parseHtmlContentWithAttrs tag p)++--+-- directive parsers+--++parseDirective :: PandocMonad m => MuseParser m (String, F Inlines)+parseDirective = do+  char '#'+  key <- many letter+  space+  spaces+  raw <- manyTill anyChar eol+  value <- parseFromString (trimInlinesF . mconcat <$> many inline) raw+  return (key, value)++directive :: PandocMonad m => MuseParser m ()+directive = do+  (key, value) <- parseDirective+  updateState $ \st -> st { stateMeta' = B.setMeta key <$> value <*> stateMeta' st }++--+-- block parsers+--++block :: PandocMonad m => MuseParser m (F Blocks)+block = do+  res <- mempty <$ skipMany1 blankline+         <|> blockElements+         <|> para+  skipMany blankline+  trace (take 60 $ show $ B.toList $ runF res defaultParserState)+  return res++blockElements :: PandocMonad m => MuseParser m (F Blocks)+blockElements = choice [ comment+                       , separator+                       , header+                       , example+                       , exampleTag+                       , literal+                       , centerTag+                       , rightTag+                       , quoteTag+                       , divTag+                       , verseTag+                       , lineBlock+                       , bulletList+                       , orderedList+                       , definitionList+                       , table+                       , commentTag+                       , noteBlock+                       ]++comment :: PandocMonad m => MuseParser m (F Blocks)+comment = try $ do+  char ';'+  space+  many $ noneOf "\n"+  eol+  return mempty++separator :: PandocMonad m => MuseParser m (F Blocks)+separator = try $ do+  string "----"+  many $ char '-'+  many spaceChar+  eol+  return $ return B.horizontalRule++header :: PandocMonad m => MuseParser m (F Blocks)+header = try $ do+  st <- stateParserContext <$> getState+  q <- stateQuoteContext <$> getState+  getPosition >>= \pos -> guard (st == NullState && q == NoQuote && sourceColumn pos == 1)+  level <- fmap length $ many1 $ char '*'+  guard $ level <= 5+  spaceChar+  content <- trimInlinesF . mconcat <$> manyTill inline eol+  attr <- registerHeader ("", [], []) (runF content defaultParserState)+  return $ B.headerWith attr level <$> content++example :: PandocMonad m => MuseParser m (F Blocks)+example = try $ do+  string "{{{"+  optionMaybe blankline+  contents <- manyTill anyChar $ try (optionMaybe blankline >> string "}}}")+  return $ return $ B.codeBlock contents++exampleTag :: PandocMonad m => MuseParser m (F Blocks)+exampleTag = do+  (attr, contents) <- htmlElement "example"+  return $ return $ B.codeBlockWith attr $ chop contents+  where lchop s = case s of+                    '\n':ss -> ss+                    _       -> s+        rchop = reverse . lchop . reverse+        -- Trim up to one newline from the beginning and the end,+        -- in case opening and/or closing tags are on separate lines.+        chop = lchop . rchop++literal :: PandocMonad m => MuseParser m (F Blocks)+literal = (return . rawBlock) <$> htmlElement "literal"+  where+    format (_, _, kvs)        = fromMaybe "html" $ lookup "format" kvs+    rawBlock (attrs, content) = B.rawBlock (format attrs) content++blockTag :: PandocMonad m+          => (Blocks -> Blocks)+          -> String+          -> MuseParser m (F Blocks)+blockTag f s = do+  res <- parseHtmlContent s block+  return $ f <$> mconcat res++-- <center> tag is ignored+centerTag :: PandocMonad m => MuseParser m (F Blocks)+centerTag = blockTag id "center"++-- <right> tag is ignored+rightTag :: PandocMonad m => MuseParser m (F Blocks)+rightTag = blockTag id "right"++quoteTag :: PandocMonad m => MuseParser m (F Blocks)+quoteTag = withQuoteContext InDoubleQuote $ blockTag B.blockQuote "quote"++-- <div> tag is supported by Emacs Muse, but not Amusewiki 2.025+divTag :: PandocMonad m => MuseParser m (F Blocks)+divTag = do+  (attrs, content) <- parseHtmlContentWithAttrs "div" block+  return $ B.divWith attrs <$> mconcat content++verseLine :: PandocMonad m => MuseParser m String+verseLine = do+  line <- anyLine <|> many1Till anyChar eof+  let (white, rest) = span (== ' ') line+  return $ replicate (length white) '\160' ++ rest++verseLines :: PandocMonad m => MuseParser m (F Blocks)+verseLines = do+  optionMaybe blankline -- Skip blankline after opening tag on separate line+  lns <- many verseLine+  lns' <- mapM (parseFromString' (trimInlinesF . mconcat <$> many inline)) lns+  return $ B.lineBlock <$> sequence lns'++verseTag :: PandocMonad m => MuseParser m (F Blocks)+verseTag = do+  (_, content) <- htmlElement "verse"+  parseFromString verseLines content++commentTag :: PandocMonad m => MuseParser m (F Blocks)+commentTag = parseHtmlContent "comment" anyChar >> return mempty++-- Indented paragraph is either center, right or quote+para :: PandocMonad m => MuseParser m (F Blocks)+para = do+ indent <- length <$> many spaceChar+ let f = if indent >= 2 && indent < 6 then B.blockQuote else id+ fmap (f . B.para) . trimInlinesF . mconcat <$> many1Till inline endOfParaElement+ where+   endOfParaElement = lookAhead $ endOfInput <|> endOfPara <|> newBlockElement+   endOfInput       = try $ skipMany blankline >> skipSpaces >> eof+   endOfPara        = try $ blankline >> skipMany1 blankline+   newBlockElement  = try $ blankline >> void blockElements++noteMarker :: PandocMonad m => MuseParser m String+noteMarker = try $ do+  char '['+  many1Till digit $ char ']'++noteBlock :: PandocMonad m => MuseParser m (F Blocks)+noteBlock = try $ do+  pos <- getPosition+  ref <- noteMarker <* skipSpaces+  content <- mconcat <$> blocksTillNote+  oldnotes <- stateNotes' <$> getState+  case M.lookup ref oldnotes of+    Just _  -> logMessage $ DuplicateNoteReference ref pos+    Nothing -> return ()+  updateState $ \s -> s{ stateNotes' = M.insert ref (pos, content) oldnotes }+  return mempty+  where+    blocksTillNote =+      many1Till block (eof <|> () <$ lookAhead noteMarker)++--+-- Verse markup+--++lineVerseLine :: PandocMonad m => MuseParser m String+lineVerseLine = try $ do+  char '>'+  white <- many1 (char ' ' >> pure '\160')+  rest <- anyLine+  return $ tail white ++ rest++blanklineVerseLine :: PandocMonad m => MuseParser m Char+blanklineVerseLine = try $ char '>' >> blankline++lineBlock :: PandocMonad m => MuseParser m (F Blocks)+lineBlock = try $ do+  lns <- many1 (pure <$> blanklineVerseLine <|> lineVerseLine)+  lns' <- mapM (parseFromString' (trimInlinesF . mconcat <$> many inline)) lns+  return $ B.lineBlock <$> sequence lns'++--+-- lists+--++listLine :: PandocMonad m => Int -> MuseParser m String+listLine markerLength = try $ do+  indentWith markerLength+  anyLineNewline++withListContext :: PandocMonad m => MuseParser m a -> MuseParser m a+withListContext p = do+  state <- getState+  let oldContext = stateParserContext state+  setState $ state { stateParserContext = ListItemState }+  parsed <- p+  updateState (\st -> st {stateParserContext = oldContext})+  return parsed++listContinuation :: PandocMonad m => Int -> MuseParser m String+listContinuation markerLength = try $ do+  result <- many1 $ listLine markerLength+  blank <- option "" ("\n" <$ blankline)+  return $ concat result ++ blank++listStart :: PandocMonad m => MuseParser m Int -> MuseParser m Int+listStart marker = try $ do+  preWhitespace <- length <$> many spaceChar+  st <- stateParserContext <$> getState+  getPosition >>= \pos -> guard (st == ListItemState || sourceColumn pos /= 1)+  markerLength <- marker+  postWhitespace <- length <$> many1 spaceChar+  return $ preWhitespace + markerLength + postWhitespace++listItem :: PandocMonad m => MuseParser m Int -> MuseParser m (F Blocks)+listItem start = try $ do+  markerLength <- start+  firstLine <- anyLineNewline+  restLines <- many $ listLine markerLength+  blank <- option "" ("\n" <$ blankline)+  let first = firstLine ++ concat restLines ++ blank+  rest <- many $ listContinuation markerLength+  parseFromString (withListContext parseBlocks) $ concat (first:rest) ++ "\n"++bulletListItems :: PandocMonad m => MuseParser m (F [Blocks])+bulletListItems = sequence <$> many1 (listItem bulletListStart)++bulletListStart :: PandocMonad m => MuseParser m Int+bulletListStart = listStart (char '-' >> return 1)++bulletList :: PandocMonad m => MuseParser m (F Blocks)+bulletList = do+  listItems <- bulletListItems+  return $ B.bulletList <$> listItems++orderedListStart :: PandocMonad m+                 => ListNumberStyle+                 -> ListNumberDelim+                 -> MuseParser m Int+orderedListStart style delim = listStart (snd <$> withHorizDisplacement (orderedListMarker style delim))++orderedList :: PandocMonad m => MuseParser m (F Blocks)+orderedList = try $ do+  p@(_, style, delim) <- lookAhead (many spaceChar *> anyOrderedListMarker <* spaceChar)+  guard $ style `elem` [Decimal, LowerAlpha, UpperAlpha, LowerRoman, UpperRoman]+  guard $ delim == Period+  items <- sequence <$> many1 (listItem $ orderedListStart style delim)+  return $ B.orderedListWith p <$> items++definitionListItem :: PandocMonad m => MuseParser m (F (Inlines, [Blocks]))+definitionListItem = try $ do+  term <- termParser+  many1 spaceChar+  string "::"+  firstLine <- anyLineNewline+  restLines <- manyTill anyLineNewline endOfListItemElement+  let lns = firstLine : restLines+  lineContent <- parseFromString (withListContext parseBlocks) $ concat lns ++ "\n"+  pure $ do lineContent' <- lineContent+            pure (B.text term, [lineContent'])+  where+    termParser = many1 spaceChar >> -- Initial space as required by Amusewiki, but not Emacs Muse+                 many1Till anyChar (lookAhead (void (try (spaceChar >> string "::")) <|> void newline))+    endOfInput = try $ skipMany blankline >> skipSpaces >> eof+    twoBlankLines = try $ blankline >> skipMany1 blankline+    newDefinitionListItem = try $ void termParser+    endOfListItemElement = lookAhead $ endOfInput <|> newDefinitionListItem <|> twoBlankLines++definitionListItems :: PandocMonad m => MuseParser m (F [(Inlines, [Blocks])])+definitionListItems = sequence <$> many1 definitionListItem++definitionList :: PandocMonad m => MuseParser m (F Blocks)+definitionList = do+  listItems <- definitionListItems+  return $ B.definitionList <$> listItems++--+-- tables+--++data MuseTable = MuseTable+  { museTableCaption :: Inlines+  , museTableHeaders :: [[Blocks]]+  , museTableRows    :: [[Blocks]]+  , museTableFooters :: [[Blocks]]+  }++data MuseTableElement = MuseHeaderRow (F [Blocks])+                      | MuseBodyRow   (F [Blocks])+                      | MuseFooterRow (F [Blocks])+                      | MuseCaption (F Inlines)++museToPandocTable :: MuseTable -> Blocks+museToPandocTable (MuseTable caption headers body footers) =+  B.table caption attrs headRow rows+  where ncol = maximum (0 : map length (headers ++ body ++ footers))+        attrs = replicate ncol (AlignDefault, 0.0)+        headRow = if null headers then [] else head headers+        rows = (if null headers then [] else tail headers) ++ body ++ footers++museAppendElement :: MuseTable+                  -> MuseTableElement+                  -> F MuseTable+museAppendElement tbl element =+  case element of+    MuseHeaderRow row -> do+      row' <- row+      return tbl{ museTableHeaders = museTableHeaders tbl ++ [row'] }+    MuseBodyRow row -> do+      row' <- row+      return tbl{ museTableRows = museTableRows tbl ++ [row'] }+    MuseFooterRow row-> do+      row' <- row+      return tbl{ museTableFooters = museTableFooters tbl ++ [row'] }+    MuseCaption inlines -> do+      inlines' <- inlines+      return tbl{ museTableCaption = inlines' }++tableCell :: PandocMonad m => MuseParser m (F Blocks)+tableCell = try $ fmap B.plain . trimInlinesF . mconcat <$> manyTill inline (lookAhead cellEnd)+  where cellEnd = try $ void (many1 spaceChar >> char '|') <|> eol++tableElements :: PandocMonad m => MuseParser m [MuseTableElement]+tableElements = tableParseElement `sepEndBy1` eol++elementsToTable :: [MuseTableElement] -> F MuseTable+elementsToTable = foldM museAppendElement emptyTable+  where emptyTable = MuseTable mempty mempty mempty mempty++table :: PandocMonad m => MuseParser m (F Blocks)+table = try $ do+  rows <- tableElements+  let tbl = elementsToTable rows+  let pandocTbl = museToPandocTable <$> tbl :: F Blocks+  return pandocTbl++tableParseElement :: PandocMonad m => MuseParser m MuseTableElement+tableParseElement = tableParseHeader+                <|> tableParseBody+                <|> tableParseFooter+                <|> tableParseCaption++tableParseRow :: PandocMonad m => Int -> MuseParser m (F [Blocks])+tableParseRow n = try $ do+  fields <- tableCell `sepBy2` fieldSep+  return $ sequence fields+    where p `sepBy2` sep = (:) <$> p <*> many1 (sep >> p)+          fieldSep = many1 spaceChar >> count n (char '|') >> (void (many1 spaceChar) <|> void (lookAhead newline))++tableParseHeader :: PandocMonad m => MuseParser m MuseTableElement+tableParseHeader = MuseHeaderRow <$> tableParseRow 2++tableParseBody :: PandocMonad m => MuseParser m MuseTableElement+tableParseBody = MuseBodyRow <$> tableParseRow 1++tableParseFooter :: PandocMonad m => MuseParser m MuseTableElement+tableParseFooter = MuseFooterRow <$> tableParseRow 3++tableParseCaption :: PandocMonad m => MuseParser m MuseTableElement+tableParseCaption = try $ do+  many spaceChar+  string "|+"+  contents <- trimInlinesF . mconcat <$> many1Till inline (lookAhead $ string "+|")+  string "+|"+  return $ MuseCaption contents++--+-- inline parsers+--++inline :: PandocMonad m => MuseParser m (F Inlines)+inline = choice [ br+                , anchor+                , footnote+                , strong+                , strongTag+                , emph+                , emphTag+                , superscriptTag+                , subscriptTag+                , strikeoutTag+                , verbatimTag+                , link+                , code+                , codeTag+                , whitespace+                , str+                , symbol+                ] <?> "inline"++anchor :: PandocMonad m => MuseParser m (F Inlines)+anchor = try $ do+  getPosition >>= \pos -> guard (sourceColumn pos == 1)+  char '#'+  first <- letter+  rest <- many (letter <|> digit)+  skipMany spaceChar <|> void newline+  let anchorId = first:rest+  return $ return $ B.spanWith (anchorId, [], []) mempty++footnote :: PandocMonad m => MuseParser m (F Inlines)+footnote = try $ do+  ref <- noteMarker+  return $ do+    notes <- asksF stateNotes'+    case M.lookup ref notes of+      Nothing -> return $ B.str $ "[" ++ ref ++ "]"+      Just (_pos, contents) -> do+        st <- askF+        let contents' = runF contents st { stateNotes' = M.empty }+        return $ B.note contents'++whitespace :: PandocMonad m => MuseParser m (F Inlines)+whitespace = fmap return (lb <|> regsp)+  where lb = try $ skipMany spaceChar >> linebreak >> return B.space+        regsp = try $ skipMany1 spaceChar >> return B.space++br :: PandocMonad m => MuseParser m (F Inlines)+br = try $ do+  string "<br>"+  return $ return B.linebreak++linebreak :: PandocMonad m => MuseParser m (F Inlines)+linebreak = newline >> notFollowedBy newline >> (lastNewline <|> innerNewline)+  where lastNewline  = do+                         eof+                         return $ return mempty+        innerNewline = return $ return B.space++emphasisBetween :: (PandocMonad m, Show a) => MuseParser m a -> MuseParser m (F Inlines)+emphasisBetween c = try $ enclosedInlines c c++enclosedInlines :: (PandocMonad m, Show a, Show b)+                => MuseParser m a+                -> MuseParser m b+                -> MuseParser m (F Inlines)+enclosedInlines start end = try $+  trimInlinesF . mconcat <$> (enclosed start end inline <* notFollowedBy (satisfy isLetter))++inlineTag :: PandocMonad m+          => (Inlines -> Inlines)+          -> String+          -> MuseParser m (F Inlines)+inlineTag f s = try $ do+  res <- parseHtmlContent s inline+  return $ f <$> mconcat res++strongTag :: PandocMonad m => MuseParser m (F Inlines)+strongTag = inlineTag B.strong "strong"++strong :: PandocMonad m => MuseParser m (F Inlines)+strong = fmap B.strong <$> emphasisBetween (string "**")++emph :: PandocMonad m => MuseParser m (F Inlines)+emph = fmap B.emph <$> emphasisBetween (char '*')++emphTag :: PandocMonad m => MuseParser m (F Inlines)+emphTag = inlineTag B.emph "em"++superscriptTag :: PandocMonad m => MuseParser m (F Inlines)+superscriptTag = inlineTag B.superscript "sup"++subscriptTag :: PandocMonad m => MuseParser m (F Inlines)+subscriptTag = inlineTag B.subscript "sub"++strikeoutTag :: PandocMonad m => MuseParser m (F Inlines)+strikeoutTag = inlineTag B.strikeout "del"++verbatimTag :: PandocMonad m => MuseParser m (F Inlines)+verbatimTag = do+  content <- parseHtmlContent "verbatim" anyChar+  return $ return $ B.text $ fromEntities content++code :: PandocMonad m => MuseParser m (F Inlines)+code = try $ do+  pos <- getPosition+  sp <- if sourceColumn pos == 1+          then pure mempty+          else skipMany1 spaceChar >> pure B.space+  char '='+  contents <- many1Till (noneOf "\n\r" <|> (newline <* notFollowedBy newline)) $ char '='+  guard $ not $ null contents+  guard $ head contents `notElem` " \t\n"+  guard $ last contents `notElem` " \t\n"+  notFollowedBy $ satisfy isLetter+  return $ return (sp B.<> B.code contents)++codeTag :: PandocMonad m => MuseParser m (F Inlines)+codeTag = do+  (attrs, content) <- parseHtmlContentWithAttrs "code" anyChar+  return $ return $ B.codeWith attrs $ fromEntities content++str :: PandocMonad m => MuseParser m (F Inlines)+str = fmap (return . B.str) (many1 alphaNum <|> count 1 characterReference)++symbol :: PandocMonad m => MuseParser m (F Inlines)+symbol = (return . B.str) <$> count 1 nonspaceChar++link :: PandocMonad m => MuseParser m (F Inlines)+link = try $ do+  st <- getState+  guard $ stateAllowLinks st+  setState $ st{ stateAllowLinks = False }+  (url, title, content) <- linkText+  setState $ st{ stateAllowLinks = True }+  return $ case stripPrefix "URL:" url of+             Nothing -> if isImageUrl url+                          then B.image url title <$> fromMaybe (return mempty) content+                          else B.link url title <$> fromMaybe (return $ B.str url) content+             Just url' -> B.link url' title <$> fromMaybe (return $ B.str url') content+    where -- Taken from muse-image-regexp defined in Emacs Muse file lisp/muse-regexps.el+          imageExtensions = [".eps", ".gif", ".jpg", ".jpeg", ".pbm", ".png", ".tiff", ".xbm", ".xpm"]+          isImageUrl = (`elem` imageExtensions) . takeExtension++linkContent :: PandocMonad m => MuseParser m (F Inlines)+linkContent = do+  char '['+  res <- many1Till anyChar $ char ']'+  parseFromString (mconcat <$> many1 inline) res++linkText :: PandocMonad m => MuseParser m (String, String, Maybe (F Inlines))+linkText = do+  string "[["+  url <- many1Till anyChar $ char ']'+  content <- optionMaybe linkContent+  char ']'+  return (url, "", content)
src/Text/Pandoc/Readers/Native.hs view
@@ -1,5 +1,5 @@ {--Copyright (C) 2011-2015 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2011-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -18,7 +18,7 @@  {- |    Module      : Text.Pandoc.Readers.Native-   Copyright   : Copyright (C) 2011-2015 John MacFarlane+   Copyright   : Copyright (C) 2011-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -31,8 +31,12 @@ module Text.Pandoc.Readers.Native ( readNative ) where  import Text.Pandoc.Definition+import Text.Pandoc.Options (ReaderOptions) import Text.Pandoc.Shared (safeRead) +import Control.Monad.Except (throwError)+import Data.Text (Text, unpack)+import Text.Pandoc.Class import Text.Pandoc.Error  -- | Read native formatted text and return a Pandoc document.@@ -45,19 +49,23 @@ -- -- > Pandoc nullMeta [Plain [Str "hi"]] ---readNative :: String      -- ^ String to parse (assuming @'\n'@ line endings)-           -> Either PandocError Pandoc-readNative s = maybe (Pandoc nullMeta <$> readBlocks s) Right (safeRead s)--readBlocks :: String -> Either PandocError [Block]-readBlocks s = maybe ((:[]) <$> readBlock s) Right (safeRead s)+readNative :: PandocMonad m+           => ReaderOptions+           -> Text       -- ^ String to parse (assuming @'\n'@ line endings)+           -> m Pandoc+readNative _ s =+  case maybe (Pandoc nullMeta <$> readBlocks s) Right (safeRead (unpack s)) of+    Right doc -> return doc+    Left _    -> throwError $ PandocParseError "couldn't read native" -readBlock :: String -> Either PandocError Block-readBlock s = maybe (Plain <$> readInlines s) Right (safeRead s)+readBlocks :: Text -> Either PandocError [Block]+readBlocks s = maybe ((:[]) <$> readBlock s) Right (safeRead (unpack s)) -readInlines :: String -> Either PandocError [Inline]-readInlines s = maybe ((:[]) <$> readInline s) Right (safeRead s)+readBlock :: Text -> Either PandocError Block+readBlock s = maybe (Plain <$> readInlines s) Right (safeRead (unpack s)) -readInline :: String -> Either PandocError Inline-readInline s = maybe (Left . ParseFailure $ "Could not read: " ++ s) Right (safeRead s)+readInlines :: Text -> Either PandocError [Inline]+readInlines s = maybe ((:[]) <$> readInline s) Right (safeRead (unpack s)) +readInline :: Text -> Either PandocError Inline+readInline s = maybe (Left . PandocParseError $ "Could not read: " ++ unpack s) Right (safeRead (unpack s))
src/Text/Pandoc/Readers/OPML.hs view
@@ -1,20 +1,21 @@ {-# LANGUAGE FlexibleContexts #-} module Text.Pandoc.Readers.OPML ( readOPML ) where+import Control.Monad.State.Strict import Data.Char (toUpper)-import Text.Pandoc.Options-import Text.Pandoc.Definition+import Data.Default+import Data.Generics+import Data.Maybe (fromMaybe)+import Data.Text (Text, pack, unpack)+import Text.HTML.TagSoup.Entity (lookupEntity) import Text.Pandoc.Builder+import Text.Pandoc.Class (PandocMonad)+import Text.Pandoc.Options import Text.Pandoc.Readers.HTML (readHtml) import Text.Pandoc.Readers.Markdown (readMarkdown)+import Text.Pandoc.Shared (crFilter) import Text.XML.Light-import Text.HTML.TagSoup.Entity (lookupEntity)-import Data.Generics-import Control.Monad.State-import Data.Default-import Control.Monad.Except-import Text.Pandoc.Error -type OPML = ExceptT PandocError (State OPMLState)+type OPML m = StateT OPMLState m  data OPMLState = OPMLState{                         opmlSectionLevel :: Int@@ -30,12 +31,16 @@                  , opmlDocDate = mempty                   } -readOPML :: ReaderOptions -> String -> Either PandocError Pandoc-readOPML _ inp  = setTitle (opmlDocTitle st')-                   . setAuthors (opmlDocAuthors st')-                   . setDate (opmlDocDate st')-                   . doc . mconcat <$> bs-  where (bs, st') = flip runState def . runExceptT $ (mapM parseBlock $ normalizeTree $ parseXML inp)+readOPML :: PandocMonad m => ReaderOptions -> Text -> m Pandoc+readOPML _ inp  = do+  (bs, st') <- runStateT+                 (mapM parseBlock $ normalizeTree $+                    parseXML (unpack (crFilter inp))) def+  return $+    setTitle (opmlDocTitle st') $+    setAuthors (opmlDocAuthors st') $+    setDate (opmlDocDate st') $+    doc $ mconcat bs  -- normalize input, consolidating adjacent Text and CRef elements normalizeTree :: [Content] -> [Content]@@ -53,30 +58,29 @@         go xs = xs  convertEntity :: String -> String-convertEntity e = maybe (map toUpper e) id (lookupEntity e)+convertEntity e = Data.Maybe.fromMaybe (map toUpper e) (lookupEntity e)  -- convenience function to get an attribute value, defaulting to "" attrValue :: String -> Element -> String attrValue attr elt =-  case lookupAttrBy (\x -> qName x == attr) (elAttribs elt) of-    Just z  -> z-    Nothing -> ""+  fromMaybe "" (lookupAttrBy (\x -> qName x == attr) (elAttribs elt)) -exceptT :: Either PandocError a -> OPML a-exceptT = either throwError return+-- exceptT :: PandocMonad m => Either PandocError a -> OPML m a+-- exceptT = either throwError return -asHtml :: String -> OPML Inlines-asHtml s = (\(Pandoc _ bs) -> case bs of+asHtml :: PandocMonad m => String -> OPML m Inlines+asHtml s =+  (\(Pandoc _ bs) -> case bs of                                 [Plain ils] -> fromList ils-                                _ -> mempty) <$> exceptT (readHtml def s)+                                _           -> mempty) <$> lift (readHtml def (pack s)) -asMarkdown :: String -> OPML Blocks-asMarkdown s = (\(Pandoc _ bs) -> fromList bs) <$> exceptT (readMarkdown def s)+asMarkdown :: PandocMonad m => String -> OPML m Blocks+asMarkdown s = (\(Pandoc _ bs) -> fromList bs) <$> lift (readMarkdown def (pack s)) -getBlocks :: Element -> OPML Blocks-getBlocks e =  mconcat <$> (mapM parseBlock $ elContent e)+getBlocks :: PandocMonad m => Element -> OPML m Blocks+getBlocks e =  mconcat <$> mapM parseBlock (elContent e) -parseBlock :: Content -> OPML Blocks+parseBlock :: PandocMonad m => Content -> OPML m Blocks parseBlock (Elem e) =   case qName (elName e) of         "ownerName"    -> mempty <$ modify (\st ->
src/Text/Pandoc/Readers/Odt.hs view
@@ -32,31 +32,45 @@  module Text.Pandoc.Readers.Odt ( readOdt ) where -import           Codec.Archive.Zip-import qualified Text.XML.Light                        as XML+import Codec.Archive.Zip+import qualified Text.XML.Light as XML -import qualified Data.ByteString.Lazy                  as B+import qualified Data.ByteString.Lazy as B -import           System.FilePath+import System.FilePath -import           Text.Pandoc.Definition-import           Text.Pandoc.Error-import           Text.Pandoc.Options-import           Text.Pandoc.MediaBag-import qualified Text.Pandoc.UTF8                      as UTF8+import Control.Monad.Except (throwError) -import           Text.Pandoc.Readers.Odt.ContentReader-import           Text.Pandoc.Readers.Odt.StyleReader+import Text.Pandoc.Class (PandocMonad)+import qualified Text.Pandoc.Class as P+import Text.Pandoc.Definition+import Text.Pandoc.Error+import Text.Pandoc.MediaBag+import Text.Pandoc.Options+import qualified Text.Pandoc.UTF8 as UTF8 -import           Text.Pandoc.Readers.Odt.Generic.XMLConverter-import           Text.Pandoc.Readers.Odt.Generic.Fallible-import           Text.Pandoc.Shared (filteredFilesFromArchive)+import Text.Pandoc.Readers.Odt.ContentReader+import Text.Pandoc.Readers.Odt.StyleReader ----readOdt :: ReaderOptions+import Text.Pandoc.Readers.Odt.Generic.Fallible+import Text.Pandoc.Readers.Odt.Generic.XMLConverter+import Text.Pandoc.Shared (filteredFilesFromArchive)++readOdt :: PandocMonad m+        => ReaderOptions         -> B.ByteString-        -> Either PandocError (Pandoc, MediaBag)-readOdt _ bytes = bytesToOdt bytes-- of+        -> m Pandoc+readOdt opts bytes = case readOdt' opts bytes of+  Right (doc, mb) -> do+    P.setMediaBag mb+    return doc+  Left e -> throwError e++--+readOdt' :: ReaderOptions+         -> B.ByteString+         -> Either PandocError (Pandoc, MediaBag)+readOdt' _ bytes = bytesToOdt bytes-- of --                    Right (pandoc, mediaBag) -> Right (pandoc , mediaBag) --                    Left  err                -> Left err @@ -64,7 +78,7 @@ bytesToOdt :: B.ByteString -> Either PandocError (Pandoc, MediaBag) bytesToOdt bytes = case toArchiveOrFail bytes of   Right archive -> archiveToOdt archive-  Left _        -> Left $ ParseFailure "Couldn't parse odt file."+  Left _        -> Left $ PandocParseError "Couldn't parse odt file."  -- archiveToOdt :: Archive -> Either PandocError (Pandoc, MediaBag)@@ -85,7 +99,7 @@    | otherwise     -- Not very detailed, but I don't think more information would be helpful-  = Left $ ParseFailure "Couldn't parse odt file."+  = Left $ PandocParseError "Couldn't parse odt file."     where       filePathIsOdtMedia :: FilePath -> Bool       filePathIsOdtMedia fp =
src/Text/Pandoc/Readers/Odt/Arrows/State.hs view
@@ -1,6 +1,6 @@-{-# LANGUAGE Arrows            #-}-{-# LANGUAGE TupleSections     #-}+ {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TupleSections     #-} {- Copyright (C) 2015 Martin Linnemann <theCodingMarlin@googlemail.com> @@ -38,17 +38,17 @@  module Text.Pandoc.Readers.Odt.Arrows.State where -import Prelude hiding ( foldr, foldl )+import Prelude hiding (foldl, foldr) -import qualified Control.Category                     as Cat-import           Control.Arrow-import           Control.Monad+import Control.Arrow+import qualified Control.Category as Cat+import Control.Monad -import           Data.Foldable-import           Data.Monoid+import Data.Foldable+import Data.Monoid -import           Text.Pandoc.Readers.Odt.Arrows.Utils-import           Text.Pandoc.Readers.Odt.Generic.Fallible+import Text.Pandoc.Readers.Odt.Arrows.Utils+import Text.Pandoc.Readers.Odt.Generic.Fallible   newtype ArrowState state a b = ArrowState@@ -59,10 +59,6 @@ withState            = ArrowState . uncurry  -- | Constructor-withState'          :: ((state, a) -> (state, b)) -> ArrowState state a b-withState'           = ArrowState---- | Constructor modifyState         :: (state      ->  state    ) -> ArrowState state a a modifyState          = ArrowState . first @@ -79,10 +75,6 @@ extractFromState   f = ArrowState $ \(state,_) -> (state, f state)  -- | Constructor-withUnchangedState  :: (state -> a ->         b ) -> ArrowState state a b-withUnchangedState f = ArrowState $ \(state,a) -> (state, f state a)---- | Constructor tryModifyState      :: (state ->  Either f state)                     -> ArrowState state a (Either f a) tryModifyState     f = ArrowState $ \(state,a)@@ -107,44 +99,10 @@                                  Left  l -> (s, Left l)                                  Right r -> second Right $ runArrowState a (s,r) -instance ArrowLoop (ArrowState state) where-  loop   a          = ArrowState $ \(s, x)-                            -> let (s', (x', _d)) = runArrowState a (s, (x, _d))-                               in  (s', x')- instance ArrowApply (ArrowState state) where    app             = ArrowState $ \(s, (f,b)) -> runArrowState f (s,b) ---- | Embedding of a state arrow in a state arrow with a different state type.-switchState :: (s -> s') -> (s' -> s) -> ArrowState s' x y -> ArrowState s x y-switchState there back a = ArrowState $     first there-                                        >>> runArrowState a-                                        >>> first back---- | Lift a state arrow to modify the state of an arrow--- with a different state type.-liftToState :: (s -> s') -> ArrowState s' s s -> ArrowState s x x-liftToState unlift a = modifyState $     unlift &&& id-                                     >>> runArrowState a-                                     >>> snd- -- | Switches the type of the state temporarily.--- Drops the intermediate result state, behaving like the identity arrow,--- save for side effects in the state.-withSubState :: ArrowState s x s2 -> ArrowState s2 s s -> ArrowState s x x-withSubState unlift a = keepingTheValue (withSubState unlift a) >>^ fst---- | Switches the type of the state temporarily.--- Returns the resulting sub-state.-withSubState' :: ArrowState s x s' -> ArrowState s' s s -> ArrowState s x s'-withSubState' unlift a = ArrowState $     runArrowState unlift-                                      >>> switch-                                      >>> runArrowState a-                                      >>> switch-  where switch (x,y) = (y,x)---- | Switches the type of the state temporarily. -- Drops the intermediate result state, behaving like a fallible -- identity arrow, save for side effects in the state. withSubStateF  :: ArrowState s  x (Either f s')@@ -175,49 +133,13 @@ foldS a = ArrowState $ \(s,f) -> foldr a' (s,mempty) f   where a' x (s',m) = second (m <>)  $ runArrowState a (s',x) --- | Fold a state arrow through something 'Foldable'. Collect the results--- in a 'Monoid'.--- Intermediate form of a fold between one with "only" a 'Monoid'--- and one with any function.-foldSL :: (Foldable f, Monoid m) => ArrowState s x m -> ArrowState s (f x) m-foldSL a = ArrowState $ \(s,f) -> foldl a' (s,mempty) f-  where a' (s',m) x = second (m <>)  $ runArrowState a (s',x)---- | Fold a fallible state arrow through something 'Foldable'. Collect the--- results in a 'Monoid'.--- Intermediate form of a fold between one with "only" a 'Monoid'--- and one with any function.--- If the iteration fails, the state will be reset to the initial one.-foldS' :: (Foldable f, Monoid m)-       => ArrowState s    x  (Either e m)-       -> ArrowState s (f x) (Either e m)-foldS' a = ArrowState $ \(s,f) -> foldr (a' s) (s,Right mempty) f-  where a' s x (s',Right m) = case runArrowState a (s',x) of-                                (s'',Right m') -> (s'', Right (m <> m'))-                                (_  ,Left  e ) -> (s  , Left  e)-        a' _ _   e          = e---- | Fold a fallible state arrow through something 'Foldable'. Collect the--- results in a 'Monoid'.--- Intermediate form of a fold between one with "only" a 'Monoid'--- and one with any function.--- If the iteration fails, the state will be reset to the initial one.-foldSL' :: (Foldable f, Monoid m)-        => ArrowState s    x  (Either e m)-        -> ArrowState s (f x) (Either e m)-foldSL' a = ArrowState $ \(s,f) -> foldl (a' s) (s,Right mempty) f-  where a' s (s',Right m) x = case runArrowState a (s',x) of-                                (s'',Right m') -> (s'', Right (m <> m'))-                                (_  ,Left  e ) -> (s  , Left  e)-        a' _    e         _ = e- -- | Fold a state arrow through something 'Foldable'. Collect the results in a -- 'MonadPlus'. iterateS :: (Foldable f, MonadPlus m)          => ArrowState s    x     y          -> ArrowState s (f x) (m y) iterateS a = ArrowState $ \(s,f) -> foldr a' (s,mzero) f-  where a' x (s',m) = second ((mplus m).return) $ runArrowState a (s',x)+  where a' x (s',m) = second (mplus m.return) $ runArrowState a (s',x)  -- | Fold a state arrow through something 'Foldable'. Collect the results in a -- 'MonadPlus'.@@ -225,7 +147,7 @@           => ArrowState s    x     y           -> ArrowState s (f x) (m y) iterateSL a = ArrowState $ \(s,f) -> foldl a' (s,mzero) f-  where a' (s',m) x = second ((mplus m).return) $ runArrowState a (s',x)+  where a' (s',m) x = second (mplus m.return) $ runArrowState a (s',x)   -- | Fold a fallible state arrow through something 'Foldable'.@@ -239,15 +161,3 @@                                 (s'',Right m') -> (s'',Right $ mplus m $ return m')                                 (_  ,Left  e ) -> (s  ,Left  e )         a' _ _   e          = e---- | Fold a fallible state arrow through something 'Foldable'.--- Collect the results in a 'MonadPlus'.--- If the iteration fails, the state will be reset to the initial one.-iterateSL' :: (Foldable f, MonadPlus m)-           => ArrowState s    x  (Either e    y )-           -> ArrowState s (f x) (Either e (m y))-iterateSL' a = ArrowState $ \(s,f) -> foldl (a' s) (s,Right mzero) f-  where a' s (s',Right m) x = case runArrowState a (s',x) of-                                (s'',Right m') -> (s'',Right $ mplus m $ return m')-                                (_  ,Left  e ) -> (s  ,Left  e )-        a' _     e        _ = e
src/Text/Pandoc/Readers/Odt/Arrows/Utils.hs view
@@ -39,14 +39,11 @@ -- We export everything module Text.Pandoc.Readers.Odt.Arrows.Utils where -import           Control.Arrow-import           Control.Monad                         ( join, MonadPlus(..) )--import qualified Data.Foldable                    as F-import           Data.Monoid+import Control.Arrow+import Control.Monad (join) -import           Text.Pandoc.Readers.Odt.Generic.Fallible-import           Text.Pandoc.Readers.Odt.Generic.Utils+import Text.Pandoc.Readers.Odt.Generic.Fallible+import Text.Pandoc.Readers.Odt.Generic.Utils  and2 :: (Arrow a) => a b c -> a b c' -> a b (c,c') and2 = (&&&)@@ -63,12 +60,6 @@ and6 :: (Arrow a)      => a b c0->a b c1->a b c2->a b c3->a b c4->a b c5      -> a b (c0,c1,c2,c3,c4,c5      )-and7 :: (Arrow a)-     => a b c0->a b c1->a b c2->a b c3->a b c4->a b c5->a b c6-     -> a b (c0,c1,c2,c3,c4,c5,c6   )-and8 :: (Arrow a)-     => a b c0->a b c1->a b c2->a b c3->a b c4->a b c5->a b c6->a b c7-     -> a b (c0,c1,c2,c3,c4,c5,c6,c7)  and3 a b c           = (and2 a b          ) &&& c                        >>^ \((z,y          ) , x) -> (z,y,x          )@@ -78,10 +69,6 @@                        >>^ \((z,y,x,w      ) , v) -> (z,y,x,w,v      ) and6 a b c d e f     = (and5 a b c d e    ) &&& f                        >>^ \((z,y,x,w,v    ) , u) -> (z,y,x,w,v,u    )-and7 a b c d e f g   = (and6 a b c d e f  ) &&& g-                       >>^ \((z,y,x,w,v,u  ) , t) -> (z,y,x,w,v,u,t  )-and8 a b c d e f g h = (and7 a b c d e f g) &&& h-                       >>^ \((z,y,x,w,v,u,t) , s) -> (z,y,x,w,v,u,t,s)  liftA2 :: (Arrow a) => (x -> y -> z) -> a b x -> a b y -> a b z liftA2 f a b = a &&& b >>^ uncurry f@@ -98,19 +85,11 @@ liftA6 :: (Arrow a) => (z->y->x->w->v->u       -> r)                     -> a b z->a b y->a b x->a b w->a b v->a b u                     -> a b r-liftA7 :: (Arrow a) => (z->y->x->w->v->u->t    -> r)-                    -> a b z->a b y->a b x->a b w->a b v->a b u->a b t-                    -> a b r-liftA8 :: (Arrow a) => (z->y->x->w->v->u->t->s -> r)-                    -> a b z->a b y->a b x->a b w->a b v->a b u->a b t->a b s-                    -> a b r  liftA3 fun a b c           = and3 a b c           >>^ uncurry3 fun liftA4 fun a b c d         = and4 a b c d         >>^ uncurry4 fun liftA5 fun a b c d e       = and5 a b c d e       >>^ uncurry5 fun liftA6 fun a b c d e f     = and6 a b c d e f     >>^ uncurry6 fun-liftA7 fun a b c d e f g   = and7 a b c d e f g   >>^ uncurry7 fun-liftA8 fun a b c d e f g h = and8 a b c d e f g h >>^ uncurry8 fun  liftA :: (Arrow a) => (y -> z) -> a b y -> a b z liftA  fun a = a >>^ fun@@ -124,28 +103,12 @@ duplicate :: (Arrow a) => a b (b,b) duplicate = arr $ join (,) --- | Lifts the combination of two values into an arrow.-joinOn :: (Arrow a) => (x -> y -> z) -> a (x,y) z-joinOn = arr.uncurry- -- | Applies a function to the uncurried result-pair of an arrow-application. -- (The %-symbol was chosen to evoke an association with pairs.) (>>%) :: (Arrow a) => a x (b,c) -> (b -> c -> d) -> a x d a >>% f = a >>^ uncurry f --- | '(>>%)' with its arguments flipped-(%<<) :: (Arrow a) => (b -> c -> d) -> a x (b,c) -> a x d-(%<<) = flip (>>%)---- | Precomposition with an uncurried function-(%>>) :: (Arrow a) => (b -> c -> d) -> a d r -> a (b,c) r-f %>> a = uncurry f ^>> a---- | Precomposition with an uncurried function (right to left variant)-(<<%) :: (Arrow a) => a d r -> (b -> c -> d) -> a (b,c) r-(<<%) = flip (%>>)--infixr 2 >>%, %<<, %>>, <<%+infixr 2 >>%   -- | Duplicate a value and apply an arrow to the second instance.@@ -156,56 +119,6 @@ keepingTheValue :: (Arrow a) => a b c -> a b (b,c) keepingTheValue a = returnA &&& a --- | Duplicate a value and apply an arrow to the first instance.--- Aequivalent to--- > \a -> duplicate >>> first a--- or--- > \a -> a &&& returnA-keepingTheValue' :: (Arrow a) => a b c -> a b (c,b)-keepingTheValue' a = a &&& returnA---- | 'bind' from the "Maybe"-Monad lifted into an 'ArrowChoice'.--- Actually, it's the more complex '(>=>)', because 'bind' alone does not--- combine as nicely in arrow form.--- The current implementation is not the most efficient one, because it can--- not return directly if a 'Nothing' is encountered. That in turn follows--- from the type system, as 'Nothing' has an "invisible" type parameter that--- can not be dropped early.------ Also, there probably is a way to generalize this to other monads--- or applicatives, but I'm leaving that as an exercise to the reader.--- I have a feeling there is a new Arrow-typeclass to be found that is less--- restrictive than 'ArrowApply'. If it is already out there,--- I have not seen it yet. ('ArrowPlus' for example is not general enough.)-(>>>=) :: (ArrowChoice a) => a x (Maybe b) -> a b (Maybe c) -> a x (Maybe c)-a1 >>>= a2 = a1 >>> maybeToChoice >>> right a2 >>> choiceToMaybe >>^ join--infixr 2 >>>=---- | 'mplus' Lifted into an arrow. No 'ArrowPlus' required.--- (But still different from a true bind)-(>++<) :: (Arrow a, MonadPlus m) => a x (m b) -> a x (m b) -> a x (m b)-(>++<) = liftA2 mplus---- | Left-compose with a pure function-leftLift :: (ArrowChoice a) => (l -> l') -> a (Either l r) (Either l' r)-leftLift = left.arr---- | Right-compose with a pure function-rightLift :: (ArrowChoice a) => (r -> r') -> a (Either l r) (Either l r')-rightLift = right.arr---( ^+++  ) :: (ArrowChoice a) => (b -> c) ->  a b' c'   -> a (Either b b') (Either c c')-(  +++^ ) :: (ArrowChoice a) =>  a b c   -> (b' -> c') -> a (Either b b') (Either c c')-( ^+++^ ) :: (ArrowChoice a) => (b -> c) -> (b' -> c') -> a (Either b b') (Either c c')--l ^+++  r  = leftLift l >>> right r-l  +++^ r  = left     l >>> rightLift r-l ^+++^ r  = leftLift l >>> rightLift r--infixr 2 ^+++, +++^, ^+++^- ( ^|||  ) :: (ArrowChoice a) => (b -> d) ->  a c d   -> a (Either b c) d (  |||^ ) :: (ArrowChoice a) =>  a b d   -> (c -> d) -> a (Either b c) d ( ^|||^ ) :: (ArrowChoice a) => (b -> d) -> (c -> d) -> a (Either b c) d@@ -218,34 +131,13 @@  ( ^&&&  ) :: (Arrow a) => (b -> c) ->  a b c'   -> a b (c,c') (  &&&^ ) :: (Arrow a) =>  a b c   -> (b -> c') -> a b (c,c')-( ^&&&^ ) :: (Arrow a) => (b -> c) -> (b -> c') -> a b (c,c')  l ^&&&  r = arr l &&&     r l  &&&^ r =     l &&& arr r-l ^&&&^ r = arr l &&& arr r -infixr 3 ^&&&, &&&^, ^&&&^+infixr 3 ^&&&, &&&^ -( ^***  ) :: (Arrow a) => (b -> c) ->  a b' c'   -> a (b,b') (c,c')-(  ***^ ) :: (Arrow a) =>  a b c   -> (b' -> c') -> a (b,b') (c,c')-( ^***^ ) :: (Arrow a) => (b -> c) -> (b' -> c') -> a (b,b') (c,c') -l ^***  r = arr l ***     r-l  ***^ r =     l *** arr r-l ^***^ r = arr l *** arr r--infixr 3 ^***, ***^, ^***^---- | A version of------ >>> \p -> arr (\x -> if p x the  Right x else Left x)------ but with p being an arrow-choose :: (ArrowChoice a) => a b Bool -> a b (Either b b)-choose checkValue = keepingTheValue checkValue >>^ select-  where select (x,True  ) = Right x-        select (x,False ) = Left  x- -- | Converts @Right a@ into @Just a@ and @Left _@ into @Nothing@. choiceToMaybe :: (ArrowChoice a) => a (Either l r) (Maybe r) choiceToMaybe = arr eitherToMaybe@@ -258,130 +150,15 @@ returnV :: (Arrow a) => c -> a x c returnV = arr.const --- | 'returnA' dropping everything-returnA_ :: (Arrow a) => a _b ()-returnA_  = returnV ()---- | Wrapper for an arrow that can be evaluated im parallel. All--- Arrows can be evaluated in parallel, as long as they return a--- monoid.-newtype ParallelArrow a b c = CoEval { evalParallelArrow :: a b c }-  deriving (Eq, Ord, Show)--instance (Arrow a, Monoid m) => Monoid (ParallelArrow a b m) where-  mempty = CoEval $ returnV mempty-  (CoEval a) `mappend` (CoEval ~b) = CoEval $ a &&& b >>% mappend---- | Evaluates a collection of arrows in a parallel fashion.------ This is in essence a fold of '(&&&)' over the collection,--- so the actual execution order and parallelity depends on the--- implementation of '(&&&)' in the arrow in question.--- The default implementation of '(&&&)' for example keeps the--- order as given in the collection.------ This function can be seen as a generalization of--- 'Control.Applicative.sequenceA' to arrows or as an alternative to--- a fold with 'Control.Applicative.WrappedArrow', which--- substitutes the monoid with function application.----coEval :: (Arrow a, F.Foldable f, Monoid m) => f (a b m) -> a b m-coEval = evalParallelArrow . (F.foldMap CoEval)- -- | Defines Left as failure, Right as success type FallibleArrow a input failure success = a input (Either failure success) -type ReFallibleArrow a failure success success'-     = FallibleArrow a (Either failure success) failure success'---- | Wrapper for fallible arrows. Fallible arrows are all arrows that return--- an Either value where left is a faliure and right is a success value.-newtype AlternativeArrow a input failure success-  = TryArrow { evalAlternativeArrow :: FallibleArrow a input failure success }---instance (ArrowChoice a, Monoid failure)-         => Monoid (AlternativeArrow a input failure success) where-  mempty = TryArrow $ returnV $ Left mempty-  (TryArrow a) `mappend` (TryArrow b)-         = TryArrow $ a &&& b-                      >>^ \(a',~b')-                          -> ( (\a'' -> left (mappend a'') b') ||| Right )-                               a'---- | Evaluates a collection of fallible arrows, trying each one in succession.--- Left values are interpreted as failures, right values as successes. ----- The evaluation is stopped once an arrow succeeds.--- Up to that point, all failures are collected in the failure-monoid.--- Note that '()' is a monoid, and thus can serve as a failure-collector if--- you are uninterested in the exact failures.------ This is in essence a fold of '(&&&)' over the collection, enhanced with a--- little bit of repackaging, so the actual execution order depends on the--- implementation of '(&&&)' in the arrow in question.--- The default implementation of '(&&&)' for example keeps the--- order as given in the collection.----tryArrows         :: (ArrowChoice a, F.Foldable f, Monoid failure)-                  => f (FallibleArrow a b failure success)-                  ->    FallibleArrow a b failure success-tryArrows         = evalAlternativeArrow . (F.foldMap TryArrow)-----liftSuccess       :: (ArrowChoice a)-                  => (success -> success')-                  -> ReFallibleArrow a failure success success'-liftSuccess       = rightLift---- liftAsSuccess     :: (ArrowChoice a)                   => a x success                   -> FallibleArrow a x failure success liftAsSuccess a   = a >>^ Right ----asFallibleArrow   :: (ArrowChoice a)-                  => a x success-                  -> FallibleArrow a x failure success-asFallibleArrow a = a >>^ Right---- | Raises an error into a 'ReFallibleArrow' if the arrow is already in--- "error mode"-liftError         :: (ArrowChoice a, Monoid failure)-                  => failure-                  -> ReFallibleArrow a failure success success-liftError e       = leftLift (e <>)---- | Raises an error into a 'FallibleArrow', droping both the arrow input--- and any previously stored error value.-_raiseA           :: (ArrowChoice a)-                  => failure-                  -> FallibleArrow a x failure success-_raiseA e         = returnV (Left e)---- | Raises an empty error into a 'FallibleArrow', droping both the arrow input--- and any previously stored error value.-_raiseAEmpty      :: (ArrowChoice a, Monoid failure)-                  => FallibleArrow a x failure success-_raiseAEmpty      = _raiseA mempty---- | Raises an error into a 'ReFallibleArrow', possibly appending the new error--- to an existing one-raiseA            :: (ArrowChoice a, Monoid failure)-                  => failure-                  -> ReFallibleArrow a failure success success-raiseA e          = arr $ Left.(either (<> e) (const e))---- | Raises an empty error into a 'ReFallibleArrow'. If there already is an--- error, nothing changes.--- (Note that this function is only aequivalent to @raiseA mempty@ iff the--- failure monoid follows the monoid laws.)-raiseAEmpty       :: (ArrowChoice a, Monoid failure)-                  => ReFallibleArrow a failure success success-raiseAEmpty       = arr (fromRight (const mempty) >>> Left)-- -- | Execute the second arrow if the first succeeds (>>?) :: (ArrowChoice a)             => FallibleArrow a x       failure success@@ -410,20 +187,6 @@             -> FallibleArrow a x       failure success' a ^>>? b = a ^>> Left ^||| b --- | Execute the lifted second arrow if the lifted first arrow succeeds-(^>>?^) :: (ArrowChoice a)-            => (x            -> Either failure success)-            -> (success                     -> success')-            -> FallibleArrow a x       failure success'-a ^>>?^ f = arr $ a >>> right f---- | Execute the lifted second arrow if the lifted first arrow succeeds-(^>>?^?) :: (ArrowChoice a)-            => (x            -> Either failure success)-            -> (success      -> Either failure success')-            -> FallibleArrow a x       failure success'-a ^>>?^? f = a ^>> Left ^|||^ f- -- | Execute the second, non-fallible arrow if the first arrow succeeds (>>?!) :: (ArrowChoice a)             => FallibleArrow a x       failure success@@ -453,33 +216,9 @@ a >>?%? f = a >>?^? (uncurry f)  infixr 1  >>?,  >>?^,  >>?^?-infixr 1 ^>>?, ^>>?^, ^>>?^?, >>?!+infixr 1 ^>>?, >>?! infixr 1 >>?%, ^>>?%, >>?%? --- | Keep values that are Right, replace Left values by a constant.-ifFailedUse :: (ArrowChoice a) => v -> a (Either f v) v-ifFailedUse v = arr $ either (const v) id---- | '(&&)' lifted into an arrow-(<&&>) :: (Arrow a) => a x Bool -> a x Bool -> a x Bool-(<&&>) = liftA2 (&&)---- | '(||)' lifted into an arrow-(<||>) :: (Arrow a) => a x Bool -> a x Bool -> a x Bool-(<||>) = liftA2 (||)---- | An equivalent of '(&&)' in a fallible arrow-(>&&<) :: (ArrowChoice a, Monoid f) => FallibleArrow a x f s-                                    -> FallibleArrow a x f s'-                                    -> FallibleArrow a x f (s,s')-(>&&<) = liftA2 chooseMin---- | An equivalent of '(||)' in some forms of fallible arrows-(>||<) :: (ArrowChoice a, Monoid f, Monoid s) => FallibleArrow a x f s-                                              -> FallibleArrow a x f s-                                              -> FallibleArrow a x f s-(>||<) = liftA2 chooseMax- -- | An arrow version of a short-circuit (<|>) ifFailedDo :: (ArrowChoice a)            => FallibleArrow a x f y@@ -489,7 +228,4 @@   where repackage (x , Left  _) = Left  x         repackage (_ , Right y) = Right y -infixr 4 <&&>, <||>, >&&<, >||< infixr 1 `ifFailedDo`--
src/Text/Pandoc/Readers/Odt/Base.hs view
@@ -1,5 +1,5 @@-{-# LANGUAGE PatternGuards #-} + {- Copyright (C) 2015 Martin Linnemann <theCodingMarlin@googlemail.com> @@ -32,12 +32,11 @@  module Text.Pandoc.Readers.Odt.Base where -import           Text.Pandoc.Readers.Odt.Generic.XMLConverter-import           Text.Pandoc.Readers.Odt.Namespaces+import Text.Pandoc.Readers.Odt.Generic.XMLConverter+import Text.Pandoc.Readers.Odt.Namespaces  type OdtConverterState s = XMLConverterState Namespace s  type XMLReader     s a b = FallibleXMLConverter Namespace s a b  type XMLReaderSafe s a b =         XMLConverter Namespace s a b-
src/Text/Pandoc/Readers/Odt/ContentReader.hs view
@@ -1,8 +1,8 @@ {-# LANGUAGE Arrows          #-}-{-# LANGUAGE TupleSections   #-} {-# LANGUAGE PatternGuards   #-}-{-# LANGUAGE ViewPatterns    #-} {-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TupleSections   #-}+{-# LANGUAGE ViewPatterns    #-}  {- Copyright (C) 2015 Martin Linnemann <theCodingMarlin@googlemail.com>@@ -39,29 +39,28 @@ , read_body ) where -import           Control.Arrow-import           Control.Applicative    hiding ( liftA, liftA2, liftA3 )+import Control.Applicative hiding (liftA, liftA2, liftA3)+import Control.Arrow -import qualified Data.ByteString.Lazy   as B-import qualified Data.Map               as M-import           Data.List                     ( find, intercalate )-import           Data.Maybe+import qualified Data.ByteString.Lazy as B+import Data.List (find, intercalate)+import qualified Data.Map as M+import Data.Maybe -import qualified Text.XML.Light         as XML+import qualified Text.XML.Light as XML -import           Text.Pandoc.Definition-import           Text.Pandoc.Builder-import           Text.Pandoc.MediaBag (insertMedia, MediaBag)-import           Text.Pandoc.Shared+import Text.Pandoc.Builder+import Text.Pandoc.MediaBag (MediaBag, insertMedia)+import Text.Pandoc.Shared -import           Text.Pandoc.Readers.Odt.Base-import           Text.Pandoc.Readers.Odt.Namespaces-import           Text.Pandoc.Readers.Odt.StyleReader+import Text.Pandoc.Readers.Odt.Base+import Text.Pandoc.Readers.Odt.Namespaces+import Text.Pandoc.Readers.Odt.StyleReader -import           Text.Pandoc.Readers.Odt.Arrows.Utils-import           Text.Pandoc.Readers.Odt.Generic.XMLConverter-import           Text.Pandoc.Readers.Odt.Generic.Fallible-import           Text.Pandoc.Readers.Odt.Generic.Utils+import Text.Pandoc.Readers.Odt.Arrows.Utils+import Text.Pandoc.Readers.Odt.Generic.Fallible+import Text.Pandoc.Readers.Odt.Generic.Utils+import Text.Pandoc.Readers.Odt.Generic.XMLConverter  import qualified Data.Set as Set @@ -94,8 +93,6 @@                  , envMedia         :: Media                    -- | Hold binary resources used in the document                  , odtMediaBag      :: MediaBag---               , sequences---               , trackedChangeIDs                  }   deriving ( Show ) @@ -344,9 +341,9 @@               Just oldVPos -> getVPosModifier' (oldVPos, verticalPosition textProps)      getVPosModifier' (oldVPos , newVPos   ) | oldVPos == newVPos = ignore-    getVPosModifier' ( _      , VPosSub   )                      = subscript-    getVPosModifier' ( _      , VPosSuper )                      = superscript-    getVPosModifier' ( _      ,  _        )                      = ignore+    getVPosModifier' ( _      , VPosSub   ) = subscript+    getVPosModifier' ( _      , VPosSuper ) = superscript+    getVPosModifier' ( _      ,  _        ) = ignore      hasEmphChanged :: PropertyTriple -> Bool     hasEmphChanged = swing any [ hasChanged  isEmphasised@@ -663,7 +660,7 @@ -- read_list_item   :: ElementMatcher [Blocks] read_list_item    = matchingElement NsText "list-item"-                    $ liftA (compactify'.(:[]))+                    $ liftA (compactify.(:[]))                       ( matchChildContent' [ read_paragraph                                            , read_header                                            , read_list@@ -749,7 +746,7 @@ -- read_table_cell   :: ElementMatcher [Blocks] read_table_cell    = matchingElement NsTable "table-cell"-                     $ liftA (compactify'.(:[]))+                     $ liftA (compactify.(:[]))                      $ matchChildContent' [ read_paragraph                                           ] @@ -898,9 +895,6 @@ ---------------------- -- Entry point --------------------------read_plain_content :: OdtReaderSafe _x Inlines---read_plain_content = strContent >>^ text  read_text :: OdtReaderSafe _x Pandoc read_text = matchChildContent' [ read_header
src/Text/Pandoc/Readers/Odt/Generic/Fallible.hs view
@@ -1,5 +1,5 @@-{-# LANGUAGE GeneralizedNewtypeDeriving #-} + {- Copyright (C) 2015 Martin Linnemann <theCodingMarlin@googlemail.com> @@ -39,11 +39,7 @@ -- We export everything module Text.Pandoc.Readers.Odt.Generic.Fallible where -import           Control.Applicative-import           Control.Monad--import qualified Data.Foldable       as F-import           Data.Monoid ((<>))+import Data.Monoid ((<>))  -- | Default for now. Will probably become a class at some point. type Failure = ()@@ -51,16 +47,6 @@ type Fallible a = Either Failure a  --- | False -> Left (), True -> Right ()-boolToEither :: Bool -> Fallible ()-boolToEither False = Left  ()-boolToEither True  = Right ()---- | False -> Left (), True -> Right ()-boolToChoice :: Bool -> Fallible ()-boolToChoice False = Left  ()-boolToChoice True  = Right ()- -- maybeToEither :: Maybe a -> Fallible a maybeToEither (Just a) = Right a@@ -71,21 +57,11 @@ eitherToMaybe (Left  _) = Nothing eitherToMaybe (Right a) = Just a --- | > untagEither === either id id-untagEither :: Either a a -> a-untagEither (Left  a) = a-untagEither (Right a) = a- -- | > fromLeft f === either f id fromLeft :: (a -> b) -> Either a b -> b fromLeft f (Left  a) = f a fromLeft _ (Right b) = b --- | > fromRight f === either id f-fromRight :: (a -> b) -> Either b a -> b-fromRight _ (Left  b) = b-fromRight f (Right a) = f a- -- | > recover a === fromLeft (const a) === either (const a) id recover :: a -> Either _f a -> a recover a (Left  _) = a@@ -110,24 +86,6 @@ collapseEither (Right (Left  f)) = Left f collapseEither (Right (Right x)) = Right x --- | If either of the values represents an error, the result is a--- (possibly combined) error. If both values represent a success,--- both are returned.-chooseMin :: (Monoid a) => Either a b -> Either a b' -> Either a (b,b')-chooseMin = chooseMinWith (,)---- | If either of the values represents an error, the result is a--- (possibly combined) error. If both values represent a success,--- a combination is returned.-chooseMinWith :: (Monoid a) => (b -> b' -> c)-                            -> Either a b-                            -> Either a b'-                            -> Either a c-chooseMinWith (><) (Right a) (Right b) = Right $ a >< b-chooseMinWith  _   (Left  a) (Left  b) = Left  $ a <> b-chooseMinWith  _   (Left  a)     _     = Left  a-chooseMinWith  _       _     (Left  b) = Left  b- -- | If either of the values represents a  non-error, the result is a -- (possibly combined) non-error. If both values represent an error, an error -- is returned.@@ -152,109 +110,17 @@ class ChoiceVector v where   spreadChoice :: v (Either f a) -> Either f (v a) --- Let's do a few examples first--instance ChoiceVector Maybe where-  spreadChoice (Just (Left  f))  = Left  f-  spreadChoice (Just (Right x))  = Right (Just x)-  spreadChoice Nothing           = Right Nothing--instance ChoiceVector (Either l) where-  spreadChoice (Right (Left  f)) = Left  f-  spreadChoice (Right (Right x)) = Right (Right x)-  spreadChoice (Left   x       ) = Right (Left x)- instance ChoiceVector ((,) a) where   spreadChoice (_, Left  f) = Left  f   spreadChoice (x, Right y) = Right (x,y)   -- Wasn't there a newtype somewhere with the elements flipped? ------ More instances later, first some discussion.------ I'll have to freshen up on type system details to see how (or if) to do--- something like------ > instance (ChoiceVector a, ChoiceVector b) => ChoiceVector (a b) where--- >   :------ But maybe it would be even better to use something like------ > class ChoiceVector v v' f | v -> v' f where--- >   spreadChoice :: v -> Either f v'------ That way, more places in @v@ could spread the cheer, e.g.:------ As before:--- --                       ( a , Either f b)    (a , b)  f--- > instance ChoiceVector ((,) a (Either f b)) ((,) a b) f where--- >   spreadChoice (_, Left  f) = Left f--- >   spreadChoice (a, Right b) = Right (a,b)------ But also:--- --                       ( Either f a , b)    (a , b)  f--- > instance ChoiceVector ((,) (Either f a) b) ((,) a b) f where--- >   spreadChoice (Right a,b) = Right (a,b)--- >   spreadChoice (Left  f,_) = Left f------ And maybe even:--- --                        ( Either f a , Either f b)     (a , b)  f--- > instance ChoiceVector ((,) (Either f a) (Either f b)) ((,) a b) f where--- >   spreadChoice (Right a , Right b) = Right (a,b)--- >   spreadChoice (Left  f , _      ) = Left f--- >   spreadChoice ( _      , Left  f) = Left f------ Of course that would lead to a lot of overlapping instances...--- But I can't think of a different way. A selector function might help,--- but not even a "Data.Traversable" is powerful enough for that.--- But maybe someone has already solved all this with a lens library.------ Well, it's an interesting academic question. But for practical purposes,--- I have more than enough right now.--instance ChoiceVector ((,,) a b) where-  spreadChoice (_,_, Left  f) = Left  f-  spreadChoice (a,b, Right x) = Right (a,b,x)--instance ChoiceVector ((,,,) a b c) where-  spreadChoice (_,_,_, Left  f) = Left  f-  spreadChoice (a,b,c, Right x) = Right (a,b,c,x)--instance ChoiceVector ((,,,,) a b c d) where-  spreadChoice (_,_,_,_, Left  f) = Left  f-  spreadChoice (a,b,c,d, Right x) = Right (a,b,c,d,x)--instance ChoiceVector (Const a) where-  spreadChoice (Const c) = Right (Const c) -- need to repackage because of implicit types---- | Fails on the first error-instance ChoiceVector [] where-  spreadChoice = sequence -- using the monad instance of Either.-  -- Could be generalized to "Data.Traversable" - but why play-  -- with UndecidableInstances unless this is really needed.- -- | Wrapper for a list. While the normal list instance of 'ChoiceVector' -- fails whenever it can, this type will never fail. newtype SuccessList a = SuccessList { collectNonFailing :: [a] }   deriving ( Eq, Ord, Show )  instance ChoiceVector SuccessList  where-  spreadChoice = Right . SuccessList . (foldr unTagRight []) . collectNonFailing+  spreadChoice = Right . SuccessList . foldr unTagRight [] . collectNonFailing     where unTagRight (Right x) = (x:)           unTagRight _         = id---- | Like 'catMaybes', but for 'Either'.-collectRights :: [Either _l r] -> [r]-collectRights = collectNonFailing . untag . spreadChoice . SuccessList-  where untag = fromLeft (error "Unexpected Left")---- | A version of 'collectRights' generalized to other containers. The--- container must be both "reducible" and "buildable". Most general containers--- should fullfill these requirements, but there is no single typeclass--- (that I know of) for that.--- Therefore, they are split between 'Foldable' and 'MonadPlus'.--- (Note that 'Data.Traversable.Traversable' alone would not be enough, either.)-collectRightsF :: (F.Foldable c, MonadPlus c) => c (Either _l r) ->  c r-collectRightsF = F.foldr unTagRight mzero-  where unTagRight (Right x) = mplus $ return x-        unTagRight _         = id
src/Text/Pandoc/Readers/Odt/Generic/Utils.hs view
@@ -1,6 +1,6 @@++ {-# LANGUAGE TypeOperators #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE PatternGuards #-} {-# LANGUAGE ViewPatterns  #-}  {-@@ -38,8 +38,6 @@ , uncurry4 , uncurry5 , uncurry6-, uncurry7-, uncurry8 , swap , reverseComposition , bool@@ -53,12 +51,12 @@ , composition ) where -import           Control.Category        ( Category, (>>>), (<<<) )-import qualified Control.Category as Cat ( id )-import           Control.Monad           ( msum )+import Control.Category (Category, (<<<), (>>>))+import qualified Control.Category as Cat (id)+import Control.Monad (msum) -import qualified Data.Foldable    as F   ( Foldable, foldr )-import           Data.Maybe+import qualified Data.Foldable as F (Foldable, foldr)+import Data.Maybe   -- | Aequivalent to@@ -148,15 +146,11 @@ uncurry4 :: (a->b->c->d             -> z) -> (a,b,c,d        ) -> z uncurry5 :: (a->b->c->d->e          -> z) -> (a,b,c,d,e      ) -> z uncurry6 :: (a->b->c->d->e->f       -> z) -> (a,b,c,d,e,f    ) -> z-uncurry7 :: (a->b->c->d->e->f->g    -> z) -> (a,b,c,d,e,f,g  ) -> z-uncurry8 :: (a->b->c->d->e->f->g->h -> z) -> (a,b,c,d,e,f,g,h) -> z  uncurry3 fun (a,b,c          ) = fun a b c uncurry4 fun (a,b,c,d        ) = fun a b c d uncurry5 fun (a,b,c,d,e      ) = fun a b c d e uncurry6 fun (a,b,c,d,e,f    ) = fun a b c d e f-uncurry7 fun (a,b,c,d,e,f,g  ) = fun a b c d e f g-uncurry8 fun (a,b,c,d,e,f,g,h) = fun a b c d e f g h  swap :: (a,b) -> (b,a) swap (a,b) = (b,a)@@ -168,4 +162,3 @@ findBy _               []   = Nothing findBy f ((f -> Just x):_ ) = Just x findBy f (            _:xs) = findBy f xs-
src/Text/Pandoc/Readers/Odt/Generic/XMLConverter.hs view
@@ -41,50 +41,17 @@ , XMLConverterState , XMLConverter , FallibleXMLConverter-, swapPosition-, runConverter-, runConverter'' , runConverter'-, runConverterF'-, runConverterF-, getCurrentElement , getExtraState , setExtraState , modifyExtraState-, convertingExtraState , producingExtraState-, lookupNSiri-, lookupNSprefix-, readNSattributes-, elemName-, elemNameIs-, strContent-, elContent-, currentElem-, currentElemIs-, expectElement-, elChildren-, findChildren-, filterChildren-, filterChildrenName , findChild'-, findChild-, filterChild'-, filterChild-, filterChildName'-, filterChildName-, isSet , isSet' , isSetWithDefault-, hasAttrValueOf'-, failIfNotAttrValueOf-, isThatTheAttrValue-, searchAttrIn-, searchAttrWith , searchAttr , lookupAttr , lookupAttr'-, lookupAttrWithDefault , lookupDefaultingAttr , findAttr' , findAttr@@ -93,25 +60,9 @@ , readAttr' , readAttrWithDefault , getAttr--- , (>/<)--- , (?>/<) , executeIn-, collectEvery , withEveryL-, withEvery , tryAll-, tryAll'-, IdXMLConverter-, MaybeEConverter-, ElementMatchConverter-, MaybeCConverter-, ContentMatchConverter-, makeMatcherE-, makeMatcherC-, prepareMatchersE-, prepareMatchersC-, matchChildren-, matchContent'' , matchContent' , matchContent ) where@@ -120,8 +71,8 @@ import           Control.Monad               ( MonadPlus ) import           Control.Arrow +import           Data.Either ( rights ) import qualified Data.Map             as M-import qualified Data.Foldable        as F import           Data.Default import           Data.Maybe @@ -210,17 +161,6 @@  -- | Replace the current position by another, modifying the extra state -- in the process-swapPosition        :: (extraState -> extraState')-                    -> [XML.Element]-                    -> XMLConverterState nsID extraState-                    -> XMLConverterState nsID extraState'-swapPosition f stack state-                     = state { parentElements = stack-                             , moreState      = f (moreState state)-                             }---- | Replace the current position by another, modifying the extra state--- in the process swapStack'          :: XMLConverterState nsID extraState                     -> [XML.Element]                     -> ( XMLConverterState nsID extraState , [XML.Element] )@@ -264,14 +204,6 @@                  -> output runConverter converter state input = snd $ runArrowState converter (state,input) ----runConverter''    :: (NameSpaceID nsID)-                 => XMLConverter nsID extraState (Fallible ()) output-                 -> extraState-                 -> XML.Element-                 -> output-runConverter'' converter extraState element = runConverter (readNSattributes >>> converter) (createStartState element extraState) ()- runConverter' :: (NameSpaceID nsID)               => FallibleXMLConverter nsID extraState () success               -> extraState@@ -280,20 +212,6 @@ runConverter' converter extraState element = runConverter (readNSattributes >>? converter) (createStartState element extraState) ()  ---runConverterF' :: FallibleXMLConverter nsID extraState x y-              -> XMLConverterState nsID extraState-              -> Fallible x -> Fallible y-runConverterF' a s e = runConverter (returnV e >>? a) s e-----runConverterF :: (NameSpaceID nsID)-              => FallibleXMLConverter nsID extraState XML.Element x-              -> extraState-              -> Fallible XML.Element -> Fallible x-runConverterF a s = either failWith-                           (\e -> runConverter a (createStartState e s) e)---- getCurrentElement :: XMLConverter nsID extraState x XML.Element getCurrentElement  = extractFromState currentElement @@ -430,57 +348,15 @@ --------------------------------------------------------------------------------  ---strContent               :: XMLConverter nsID extraState x String-strContent               =     getCurrentElement-                           >>^ XML.strContent---- elContent               :: XMLConverter nsID extraState x [XML.Content] elContent               =     getCurrentElement                            >>^ XML.elContent  ----------------------------------------------------------------------------------- Current element--------------------------------------------------------------------------------------currentElem              :: XMLConverter nsID extraState x (XML.QName)-currentElem              =     getCurrentElement-                           >>^ XML.elName--currentElemIs            :: (NameSpaceID nsID)-                         => nsID -> ElementName-                         -> XMLConverter nsID extraState x Bool-currentElemIs nsID name  =     getCurrentElement-                           >>> elemNameIs nsID name----{--currentElemIs'' nsID name = ( (getCurrentElement >>^ XML.elName >>>-                                (XML.qName >>^ (&&).(== name) )-                                  ^&&&^-                                (XML.qIRI  >>^ (==) )-                              ) >>% (.)-                            ) &&& lookupNSiri nsID >>% ($)--}-----expectElement            :: (NameSpaceID nsID)-                         => nsID -> ElementName-                         -> FallibleXMLConverter nsID extraState x ()-expectElement nsID name  =     currentElemIs nsID name-                           >>^ boolToChoice---------------------------------------------------------------------------------- -- Chilren --------------------------------------------------------------------------------  ---elChildren               :: XMLConverter nsID extraState x [XML.Element]-elChildren               =     getCurrentElement-                           >>^ XML.elChildren- -- findChildren             :: (NameSpaceID nsID)                          => nsID -> ElementName@@ -490,18 +366,6 @@                            >>% XML.findChildren  ---filterChildren           :: (XML.Element -> Bool)-                         -> XMLConverter nsID extraState x [XML.Element]-filterChildren p         =     getCurrentElement-                           >>^ XML.filterChildren p-----filterChildrenName       :: (XML.QName   -> Bool)-                         -> XMLConverter nsID extraState x [XML.Element]-filterChildrenName p     =     getCurrentElement-                           >>^ XML.filterChildrenName p---- findChild'              :: (NameSpaceID nsID)                         => nsID                         -> ElementName@@ -517,45 +381,12 @@ findChild nsID name    =     findChild' nsID name                          >>> maybeToChoice ----filterChild'            :: (XML.Element -> Bool)-                        -> XMLConverter nsID extraState x (Maybe XML.Element)-filterChild' p          =     getCurrentElement-                          >>^ XML.filterChild p ----filterChild            :: (XML.Element -> Bool)-                       -> FallibleXMLConverter nsID extraState x XML.Element-filterChild p          =     filterChild' p-                         >>> maybeToChoice-----filterChildName'        :: (XML.QName   -> Bool)-                        -> XMLConverter nsID extraState x (Maybe XML.Element)-filterChildName' p      =     getCurrentElement-                          >>^ XML.filterChildName p-----filterChildName        :: (XML.QName   -> Bool)-                       -> FallibleXMLConverter nsID extraState x XML.Element-filterChildName p      =     filterChildName' p-                         >>> maybeToChoice-- -------------------------------------------------------------------------------- -- Attributes --------------------------------------------------------------------------------  ---isSet                    :: (NameSpaceID nsID)-                         => nsID -> AttributeName-                         -> (Either Failure Bool)-                         -> FallibleXMLConverter nsID extraState x Bool-isSet nsID attrName deflt-                         =      findAttr' nsID attrName-                            >>^ maybe deflt stringToBool---- isSet'                   :: (NameSpaceID nsID)                          => nsID -> AttributeName                          -> XMLConverter nsID extraState x (Maybe Bool)@@ -570,34 +401,6 @@                          =     isSet' nsID attrName                            >>^ fromMaybe def' ----hasAttrValueOf'          :: (NameSpaceID nsID)-                         => nsID -> AttributeName-                         -> AttributeValue-                         -> XMLConverter nsID extraState x Bool-hasAttrValueOf' nsID attrName attrValue-                         =     findAttr nsID attrName-                           >>> ( const False ^|||^ (==attrValue))-----failIfNotAttrValueOf     :: (NameSpaceID nsID)-                         => nsID -> AttributeName-                         -> AttributeValue-                         -> FallibleXMLConverter nsID extraState x ()-failIfNotAttrValueOf nsID attrName attrValue-                         =     hasAttrValueOf' nsID attrName attrValue-                           >>^ boolToChoice---- | Is the value that is currently transported in the arrow the value of--- the specified attribute?-isThatTheAttrValue       :: (NameSpaceID nsID)-                         => nsID -> AttributeName-                         -> FallibleXMLConverter nsID extraState AttributeValue Bool-isThatTheAttrValue nsID attrName-                         =     keepingTheValue-                                 (findAttr nsID attrName)-                           >>% right.(==)- -- | Lookup value in a dictionary, fail if no attribute found or value -- not in dictionary searchAttrIn             :: (NameSpaceID nsID)@@ -608,18 +411,6 @@                          =       findAttr nsID attrName                            >>?^? maybeToChoice.(`lookup` dict ) ---- | Lookup value in a dictionary. Fail if no attribute found. If value not in--- dictionary, return default value-searchAttrWith           :: (NameSpaceID nsID)-                         => nsID -> AttributeName-                         -> a-                         -> [(AttributeValue,a)]-                         -> FallibleXMLConverter nsID extraState x a-searchAttrWith nsID attrName defV dict-                         =      findAttr nsID attrName-                           >>?^ (fromMaybe defV).(`lookup` dict )- -- | Lookup value in a dictionary. If attribute or value not found, -- return default value searchAttr               :: (NameSpaceID nsID)@@ -789,16 +580,6 @@                                    (findChildren nsID name)                              >>% distributeValue --- | Applies a converter to every child element of a specific type.--- Collects results in a 'Monoid'.--- Fails completely if any conversion fails.-collectEvery           :: (NameSpaceID nsID, Monoid m)-                       => nsID -> ElementName-                       -> FallibleXMLConverter nsID extraState a m-                       -> FallibleXMLConverter nsID extraState a m-collectEvery nsID name a   =     prepareIteration nsID name-                             >>> foldS' (switchingTheStack a)- -- withEveryL             :: (NameSpaceID nsID)                        => nsID -> ElementName@@ -824,17 +605,7 @@                        ->         XMLConverter nsID extraState b [a] tryAll nsID name a         =     prepareIteration nsID name                              >>> iterateS (switchingTheStack a)-                             >>^ collectRights---- | Applies a converter to every child element of a specific type.--- Collects all successful results.-tryAll'                 :: (NameSpaceID nsID, F.Foldable c, MonadPlus c)-                        => nsID -> ElementName-                        -> FallibleXMLConverter nsID extraState b   a-                        ->         XMLConverter nsID extraState b (c a)-tryAll' nsID name a         =     prepareIteration nsID name-                              >>> iterateS (switchingTheStack a)-                              >>^ collectRightsF+                             >>^ rights  -------------------------------------------------------------------------------- -- Matching children@@ -843,15 +614,6 @@ type IdXMLConverter nsID moreState x    = XMLConverter   nsID moreState x x -type MaybeEConverter nsID moreState x-   = Maybe (IdXMLConverter nsID moreState (x, XML.Element))---- Chainable converter that helps deciding which converter to actually use.-type ElementMatchConverter nsID extraState x-   = IdXMLConverter  nsID-                     extraState-                     (MaybeEConverter nsID extraState x, XML.Element)- type MaybeCConverter nsID moreState x    = Maybe (IdXMLConverter nsID moreState (x, XML.Content)) @@ -862,26 +624,6 @@                      (MaybeCConverter nsID extraState x, XML.Content)  -- Helper function: The @c@ is actually a converter that is to be selected by--- matching XML elements to the first two parameters.--- The fold used to match elements however is very simple, so to use it,--- this function wraps the converter in another converter that unifies--- the accumulator. Think of a lot of converters with the resulting type--- chained together. The accumulator not only transports the element--- unchanged to the next matcher, it also does the actual selecting by--- combining the intermediate results with '(<|>)'.-makeMatcherE           :: (NameSpaceID nsID)-                       => nsID -> ElementName-                       -> FallibleXMLConverter  nsID extraState a a-                       -> ElementMatchConverter nsID extraState a-makeMatcherE nsID name c = (     second (-                                              elemNameIs nsID name-                                          >>^ bool Nothing (Just tryC)-                                        )-                             >>% (<|>)-                           ) &&&^ snd-  where tryC = (fst ^&&& executeThere c >>% recover) &&&^ snd---- Helper function: The @c@ is actually a converter that is to be selected by -- matching XML content to the first two parameters. -- The fold used to match elements however is very simple, so to use it, -- this function wraps the converter in another converter that unifies@@ -914,13 +656,6 @@                                      _           -> failEmpty  -- Creates and chains a bunch of matchers-prepareMatchersE       :: (NameSpaceID nsID)-                       => [(nsID, ElementName, FallibleXMLConverter nsID extraState x x)]-                       -> ElementMatchConverter nsID extraState x---prepareMatchersE       = foldSs . (map $ uncurry3  makeMatcherE)-prepareMatchersE       = reverseComposition . (map $ uncurry3  makeMatcherE)---- Creates and chains a bunch of matchers prepareMatchersC      :: (NameSpaceID nsID)                        => [(nsID, ElementName, FallibleXMLConverter nsID extraState x x)]                        -> ContentMatchConverter nsID extraState x@@ -928,52 +663,6 @@ prepareMatchersC      = reverseComposition . (map $ uncurry3  makeMatcherC)  -- | Takes a list of element-data - converter groups and--- * Finds all children of the current element--- * Matches each group to each child in order (at most one group per child)--- * Filters non-matched children--- * Chains all found converters in child-order--- * Applies the chain to the input element-matchChildren          :: (NameSpaceID nsID)-                       => [(nsID, ElementName, FallibleXMLConverter nsID extraState a a)]-                       -> XMLConverter nsID extraState a a-matchChildren lookups  = let matcher = prepareMatchersE lookups-                         in  keepingTheValue (-                                   elChildren-                               >>> map (Nothing,)-                               ^>> iterateSL matcher-                               >>^ catMaybes.map (\(m,e) -> fmap (swallowElem e) m)-                              -- >>> foldSs-                               >>> reverseComposition-                             )-                         >>> swap-                         ^>> app-  where-        -- let the converter swallow the element and drop the element-        -- in the return value-        swallowElem element converter = (,element) ^>> converter >>^ fst-----matchContent''         :: (NameSpaceID nsID)-                       => [(nsID, ElementName, FallibleXMLConverter nsID extraState a a)]-                       -> XMLConverter nsID extraState a a-matchContent'' lookups  = let matcher = prepareMatchersC lookups-                          in  keepingTheValue (-                                   elContent-                               >>> map (Nothing,)-                               ^>> iterateSL matcher-                               >>^ catMaybes.map (\(m,c) -> fmap (swallowContent c) m)-                              -- >>> foldSs-                               >>> reverseComposition-                             )-                         >>> swap-                         ^>> app-  where-        -- let the converter swallow the content and drop the content-        -- in the return value-        swallowContent content converter = (,content) ^>> converter >>^ fst----- | Takes a list of element-data - converter groups and -- * Finds all content of the current element -- * Matches each group to each piece of content in order --   (at most one group per piece of content)@@ -1017,14 +706,6 @@ -------------------------------------------------------------------------------- -- Internals ----------------------------------------------------------------------------------stringToBool :: (Monoid failure) => String -> Either failure Bool-stringToBool val  -- stringToBool' val >>> maybeToChoice-                 | val `elem` trueValues  = succeedWith True-                 | val `elem` falseValues = succeedWith False-                 | otherwise              = failEmpty-  where trueValues  = ["true" ,"on" ,"1"]-        falseValues = ["false","off","0"]  stringToBool' :: String -> Maybe Bool stringToBool' val | val `elem` trueValues  = Just True
src/Text/Pandoc/Readers/Odt/Namespaces.hs view
@@ -31,11 +31,11 @@ module Text.Pandoc.Readers.Odt.Namespaces ( Namespace (..)                                           ) where -import           Data.List       ( isPrefixOf )-import           Data.Maybe      ( fromMaybe, listToMaybe )-import qualified Data.Map   as M ( empty, insert )+import Data.List (isPrefixOf)+import qualified Data.Map as M (empty, insert)+import Data.Maybe (fromMaybe, listToMaybe) -import           Text.Pandoc.Readers.Odt.Generic.Namespaces+import Text.Pandoc.Readers.Odt.Generic.Namespaces   instance NameSpaceID Namespace where
src/Text/Pandoc/Readers/Odt/StyleReader.hs view
@@ -1,9 +1,8 @@-{-# LANGUAGE TupleSections   #-}-{-# LANGUAGE PatternGuards   #-}-{-# LANGUAGE ViewPatterns    #-}-{-# LANGUAGE RecordWildCards #-} {-# LANGUAGE Arrows          #-} +{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TupleSections   #-}+ {- Copyright (C) 2015 Martin Linnemann <theCodingMarlin@googlemail.com> @@ -50,49 +49,36 @@ , ListLevelType        (..) , LengthOrPercent      (..) , lookupStyle-, getTextProperty-, getTextProperty'-, getParaProperty-, getListStyle , getListLevelStyle , getStyleFamily-, lookupDefaultStyle , lookupDefaultStyle' , lookupListStyleByName-, getPropertyChain-, textPropertyChain-, stylePropertyChain-, stylePropertyChain'-, getStylePropertyChain , extendedStylePropertyChain-, extendedStylePropertyChain'-, liftStyles , readStylesAt ) where -import           Control.Arrow-import           Control.Applicative hiding ( liftA, liftA2, liftA3 )+import Control.Applicative hiding (liftA, liftA2, liftA3)+import Control.Arrow -import qualified Data.Foldable                                as F-import qualified Data.Map                                     as M-import qualified Data.Set                                     as S-import           Data.Char                                           ( isDigit )-import           Data.Default-import           Data.List                                           ( unfoldr )-import           Data.Maybe+import Data.Char (isDigit)+import Data.Default+import qualified Data.Foldable as F+import Data.List (unfoldr)+import qualified Data.Map as M+import Data.Maybe+import qualified Data.Set as S -import qualified Text.XML.Light                               as XML+import qualified Text.XML.Light as XML -import           Text.Pandoc.Readers.Odt.Arrows.State-import           Text.Pandoc.Readers.Odt.Arrows.Utils+import Text.Pandoc.Readers.Odt.Arrows.Utils -import           Text.Pandoc.Readers.Odt.Generic.Utils-import qualified Text.Pandoc.Readers.Odt.Generic.SetMap       as SM-import           Text.Pandoc.Readers.Odt.Generic.Fallible-import           Text.Pandoc.Readers.Odt.Generic.XMLConverter+import Text.Pandoc.Readers.Odt.Generic.Fallible+import qualified Text.Pandoc.Readers.Odt.Generic.SetMap as SM+import Text.Pandoc.Readers.Odt.Generic.Utils+import Text.Pandoc.Readers.Odt.Generic.XMLConverter -import           Text.Pandoc.Readers.Odt.Namespaces-import           Text.Pandoc.Readers.Odt.Base+import Text.Pandoc.Readers.Odt.Base+import Text.Pandoc.Readers.Odt.Namespaces   readStylesAt :: XML.Element -> Fallible Styles@@ -230,15 +216,15 @@                 ]  -- | A named style-data Style            = Style  { styleFamily      :: Maybe StyleFamily-                               , styleParentName  :: Maybe StyleName-                               , listStyle        :: Maybe StyleName-                               , styleProperties  :: StyleProperties+data Style            = Style  { styleFamily     :: Maybe StyleFamily+                               , styleParentName :: Maybe StyleName+                               , listStyle       :: Maybe StyleName+                               , styleProperties :: StyleProperties                                }   deriving ( Eq, Show ) -data StyleProperties  = SProps { textProperties      :: Maybe TextProperties-                               , paraProperties      :: Maybe ParaProperties+data StyleProperties  = SProps { textProperties :: Maybe TextProperties+                               , paraProperties :: Maybe ParaProperties --                             , tableColProperties  :: Maybe TColProperties --                             , tableRowProperties  :: Maybe TRowProperties --                             , tableCellProperties :: Maybe TCellProperties@@ -624,20 +610,11 @@ lookupStyle name Styles{..} = M.lookup name stylesByName  ---lookupDefaultStyle    :: StyleFamily -> Styles -> StyleProperties-lookupDefaultStyle family Styles{..} = fromMaybe def-                                       (M.lookup family defaultStyleMap)---- lookupDefaultStyle'   :: Styles -> StyleFamily -> StyleProperties lookupDefaultStyle' Styles{..} family = fromMaybe def                                         (M.lookup family defaultStyleMap)  ---getListStyle          :: Style       -> Styles -> Maybe ListStyle-getListStyle Style{..} styles = listStyle >>= (`lookupListStyleByName` styles)---- lookupListStyleByName :: StyleName   -> Styles -> Maybe ListStyle lookupListStyleByName name Styles{..} = M.lookup name listStylesByName @@ -681,64 +658,3 @@                                                   ++ (maybeToList (fmap (lookupDefaultStyle' styles) (getStyleFamily style styles))) extendedStylePropertyChain (style:trace) styles =    (stylePropertyChain style styles)                                                   ++ (extendedStylePropertyChain trace styles)--- Optimizable with Data.Sequence-----extendedStylePropertyChain' :: [Style] -> Styles -> Maybe [StyleProperties]-extendedStylePropertyChain' [] _ = Nothing-extendedStylePropertyChain' [style]       styles = Just (-                                                             (stylePropertyChain style styles)-                                                          ++ (maybeToList (fmap (lookupDefaultStyle' styles) (getStyleFamily style styles)))-                                                        )-extendedStylePropertyChain' (style:trace) styles = fmap ((stylePropertyChain style styles) ++)-                                                        (extendedStylePropertyChain' trace styles)-----stylePropertyChain'   :: Styles      -> Style  -> [StyleProperties]-stylePropertyChain' = flip stylePropertyChain-----getStylePropertyChain :: StyleName   -> Styles -> [StyleProperties]-getStylePropertyChain name styles = maybe []-                                          (`stylePropertyChain` styles)-                                          (lookupStyle name styles)-----getPropertyChain :: (StyleProperties -> Maybe a) -> Style -> Styles ->     [a]-getPropertyChain extract style styles = catMaybes-                                      $ map extract-                                      $ stylePropertyChain style styles-----textPropertyChain     :: Style       -> Styles -> [TextProperties]-textPropertyChain = getPropertyChain textProperties-----paraPropertyChain     :: Style       -> Styles -> [ParaProperties]-paraPropertyChain = getPropertyChain paraProperties-----getTextProperty   :: (TextProperties ->       a) -> Style -> Styles -> Maybe a-getTextProperty extract style styles  = fmap extract-                                      $ listToMaybe-                                      $ textPropertyChain style styles-----getTextProperty'  :: (TextProperties -> Maybe a) -> Style -> Styles -> Maybe a-getTextProperty' extract style styles = F.asum-                                      $ map extract-                                      $ textPropertyChain style styles-----getParaProperty   :: (ParaProperties ->       a) -> Style -> Styles -> Maybe a-getParaProperty extract style styles  = fmap extract-                                      $ listToMaybe-                                      $ paraPropertyChain style styles---- | Lifts the reader into another readers' state.-liftStyles :: (OdtConverterState s      -> OdtConverterState Styles)-           -> (OdtConverterState Styles -> OdtConverterState s     )-           -> XMLReader s x x-liftStyles extract inject = switchState extract inject-                          $ convertingExtraState M.empty readAllStyles-
src/Text/Pandoc/Readers/Org.hs view
@@ -1,5 +1,5 @@ {--Copyright (C) 2014-2016 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>+Copyright (C) 2014-2017 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -18,7 +18,7 @@  {- |    Module      : Text.Pandoc.Readers.Org-   Copyright   : Copyright (C) 2014-2016 Albert Krewinkel+   Copyright   : Copyright (C) 2014-2017 Albert Krewinkel    License     : GNU GPL, version 2 or above     Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>@@ -27,29 +27,42 @@ -} module Text.Pandoc.Readers.Org ( readOrg ) where -import           Text.Pandoc.Readers.Org.Blocks ( blockList, meta )-import           Text.Pandoc.Readers.Org.Parsing ( OrgParser, readWithM )-import           Text.Pandoc.Readers.Org.ParserState ( optionsToParserState )+import Text.Pandoc.Readers.Org.Blocks (blockList, meta)+import Text.Pandoc.Readers.Org.ParserState (optionsToParserState)+import Text.Pandoc.Readers.Org.Parsing (OrgParser, readWithM) -import           Text.Pandoc.Definition-import           Text.Pandoc.Error-import           Text.Pandoc.Options+import Text.Pandoc.Class (PandocMonad)+import Text.Pandoc.Definition+import Text.Pandoc.Error+import Text.Pandoc.Options+import Text.Pandoc.Parsing (reportLogMessages)+import Text.Pandoc.Shared (crFilter) -import           Control.Monad.Reader ( runReader )+import Control.Monad.Except (throwError)+import Control.Monad.Reader (runReaderT) +import Data.Text (Text)+import qualified Data.Text as T  -- | Parse org-mode string and return a Pandoc document.-readOrg :: ReaderOptions -- ^ Reader options-        -> String        -- ^ String to parse (assuming @'\n'@ line endings)-        -> Either PandocError Pandoc-readOrg opts s = flip runReader def $-                 readWithM parseOrg (optionsToParserState opts) (s ++ "\n\n")+readOrg :: PandocMonad m+        => ReaderOptions -- ^ Reader options+        -> Text          -- ^ String to parse (assuming @'\n'@ line endings)+        -> m Pandoc+readOrg opts s = do+  parsed <- flip runReaderT def $+            readWithM parseOrg (optionsToParserState opts)+            (T.unpack (crFilter s) ++ "\n\n")+  case parsed of+    Right result -> return result+    Left  _      -> throwError $ PandocParseError "problem parsing org"  -- -- Parser ---parseOrg :: OrgParser Pandoc+parseOrg :: PandocMonad m => OrgParser m Pandoc parseOrg = do   blocks' <- blockList   meta'   <- meta+  reportLogMessages   return $ Pandoc meta' blocks'
src/Text/Pandoc/Readers/Org/BlockStarts.hs view
@@ -1,5 +1,5 @@ {--Copyright (C) 2014-2016 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>+Copyright (C) 2014-2017 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -17,8 +17,8 @@ -}  {- |-   Module      : Text.Pandoc.Readers.Org.Options-   Copyright   : Copyright (C) 2014-2016 Albert Krewinkel+   Module      : Text.Pandoc.Readers.Org.BlockStarts+   Copyright   : Copyright (C) 2014-2017 Albert Krewinkel    License     : GNU GPL, version 2 or above     Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>@@ -40,11 +40,11 @@   , endOfBlock   ) where -import Control.Monad ( void )+import Control.Monad (void) import Text.Pandoc.Readers.Org.Parsing  -- | Horizontal Line (five -- dashes or more)-hline :: OrgParser ()+hline :: Monad m => OrgParser m () hline = try $ do   skipSpaces   string "-----"@@ -54,58 +54,62 @@   return ()  -- | Read the start of a header line, return the header level-headerStart :: OrgParser Int+headerStart :: Monad m => OrgParser m Int headerStart = try $   (length <$> many1 (char '*')) <* many1 (char ' ') <* updateLastPreCharPos -tableStart :: OrgParser Char+tableStart :: Monad m => OrgParser m Char tableStart = try $ skipSpaces *> char '|' -latexEnvStart :: OrgParser String-latexEnvStart = try $ do+gridTableStart :: Monad m => OrgParser m ()+gridTableStart = try $ skipSpaces <* char '+' <* char '-'+++latexEnvStart :: Monad m => OrgParser m String+latexEnvStart = try $   skipSpaces *> string "\\begin{"              *> latexEnvName              <* string "}"              <* blankline  where-   latexEnvName :: OrgParser String+   latexEnvName :: Monad m => OrgParser m String    latexEnvName = try $ mappend <$> many1 alphaNum <*> option "" (string "*")   -- | Parses bullet list marker.-bulletListStart :: OrgParser ()+bulletListStart :: Monad m => OrgParser m () bulletListStart = try $   choice   [ () <$ skipSpaces  <* oneOf "+-" <* skipSpaces1   , () <$ skipSpaces1 <* char '*'   <* skipSpaces1   ] -genericListStart :: OrgParser String-                 -> OrgParser Int+genericListStart :: Monad m+                 => OrgParser m String+                 -> OrgParser m Int genericListStart listMarker = try $   (+) <$> (length <$> many spaceChar)       <*> (length <$> listMarker <* many1 spaceChar) -orderedListStart :: OrgParser Int+orderedListStart :: Monad m => OrgParser m Int orderedListStart = genericListStart orderedListMarker   -- Ordered list markers allowed in org-mode   where orderedListMarker = mappend <$> many1 digit <*> (pure <$> oneOf ".)") -drawerStart :: OrgParser String-drawerStart = try $-  skipSpaces *> drawerName <* skipSpaces <* newline+drawerStart :: Monad m => OrgParser m String+drawerStart = try $ skipSpaces *> drawerName <* skipSpaces <* newline  where drawerName = char ':' *> manyTill nonspaceChar (char ':') -metaLineStart :: OrgParser ()+metaLineStart :: Monad m => OrgParser m () metaLineStart = try $ skipSpaces <* string "#+" -commentLineStart :: OrgParser ()+commentLineStart :: Monad m => OrgParser m () commentLineStart = try $ skipSpaces <* string "# " -exampleLineStart :: OrgParser ()+exampleLineStart :: Monad m => OrgParser m () exampleLineStart = () <$ try (skipSpaces *> string ": ") -noteMarker :: OrgParser String+noteMarker :: Monad m => OrgParser m String noteMarker = try $ do   char '['   choice [ many1Till digit (char ']')@@ -114,17 +118,18 @@          ]  -- | Succeeds if the parser is at the end of a block.-endOfBlock :: OrgParser ()-endOfBlock = lookAhead . try $ do-    void blankline <|> anyBlockStart+endOfBlock :: Monad m => OrgParser m ()+endOfBlock = lookAhead . try $+  void blankline <|> anyBlockStart  where    -- Succeeds if there is a new block starting at this position.-   anyBlockStart :: OrgParser ()+   anyBlockStart :: Monad m => OrgParser m ()    anyBlockStart = try . choice $      [ exampleLineStart      , hline      , metaLineStart      , commentLineStart+     , gridTableStart      , void noteMarker      , void tableStart      , void drawerStart@@ -133,4 +138,3 @@      , void bulletListStart      , void orderedListStart      ]-
src/Text/Pandoc/Readers/Org/Blocks.hs view
@@ -1,6 +1,3 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE ViewPatterns #-} {- Copyright (C) 2014-2017 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de> @@ -18,9 +15,10 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA -}-+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RecordWildCards  #-} {- |-   Module      : Text.Pandoc.Readers.Org.Options+   Module      : Text.Pandoc.Readers.Org.Blocks    Copyright   : Copyright (C) 2014-2017 Albert Krewinkel    License     : GNU GPL, version 2 or above @@ -33,247 +31,59 @@   , meta   ) where -import           Text.Pandoc.Readers.Org.BlockStarts-import           Text.Pandoc.Readers.Org.Inlines-import           Text.Pandoc.Readers.Org.Meta ( metaExport, metaKey, metaLine )-import           Text.Pandoc.Readers.Org.ParserState-import           Text.Pandoc.Readers.Org.Parsing-import           Text.Pandoc.Readers.Org.Shared-                   ( cleanLinkString, isImageFilename, rundocBlockClass-                   , toRundocAttrib, translateLang )+import Text.Pandoc.Readers.Org.BlockStarts+import Text.Pandoc.Readers.Org.DocumentTree (documentTree, headlineToBlocks)+import Text.Pandoc.Readers.Org.Inlines+import Text.Pandoc.Readers.Org.Meta (metaExport, metaKey, metaLine)+import Text.Pandoc.Readers.Org.ParserState+import Text.Pandoc.Readers.Org.Parsing+import Text.Pandoc.Readers.Org.Shared (cleanLinkString, isImageFilename,+                                       originalLang, translateLang) +import Text.Pandoc.Builder (Blocks, Inlines) import qualified Text.Pandoc.Builder as B-import           Text.Pandoc.Builder ( Inlines, Blocks )-import           Text.Pandoc.Definition-import           Text.Pandoc.Options-import           Text.Pandoc.Shared ( compactify', compactify'DL, safeRead )--import           Control.Monad ( foldM, guard, mzero, void )-import           Data.Char ( isSpace, toLower, toUpper)-import           Data.Default ( Default )-import           Data.List ( foldl', isPrefixOf )-import           Data.Maybe ( fromMaybe, isNothing )-import           Data.Monoid ((<>))------- Org headers----newtype Tag = Tag { fromTag :: String }-  deriving (Show, Eq)---- | Create a tag containing the given string.-toTag :: String -> Tag-toTag = Tag---- | The key (also called name or type) of a property.-newtype PropertyKey = PropertyKey { fromKey :: String }-  deriving (Show, Eq, Ord)---- | Create a property key containing the given string.  Org mode keys are--- case insensitive and are hence converted to lower case.-toPropertyKey :: String -> PropertyKey-toPropertyKey = PropertyKey . map toLower---- | The value assigned to a property.-newtype PropertyValue = PropertyValue { fromValue :: String }---- | Create a property value containing the given string.-toPropertyValue :: String -> PropertyValue-toPropertyValue = PropertyValue---- | Check whether the property value is non-nil (i.e. truish).-isNonNil :: PropertyValue -> Bool-isNonNil p = map toLower (fromValue p) `notElem` ["()", "{}", "nil"]---- | Key/value pairs from a PROPERTIES drawer-type Properties = [(PropertyKey, PropertyValue)]---- | Org mode headline (i.e. a document subtree).-data Headline = Headline-  { headlineLevel      :: Int-  , headlineTodoMarker :: Maybe TodoMarker-  , headlineText       :: Inlines-  , headlineTags       :: [Tag]-  , headlineProperties :: Properties-  , headlineContents   :: Blocks-  , headlineChildren   :: [Headline]-  }------- Parsing headlines and subtrees------- | Read an Org mode headline and its contents (i.e. a document subtree).--- @lvl@ gives the minimum acceptable level of the tree.-headline :: Int -> OrgParser (F Headline)-headline lvl = try $ do-  level <- headerStart-  guard (lvl <= level)-  todoKw <- optionMaybe todoKeyword-  title <- trimInlinesF . mconcat <$> manyTill inline endOfTitle-  tags  <- option [] headerTags-  newline-  properties <- option mempty propertiesDrawer-  contents   <- blocks-  children   <- many (headline (level + 1))-  return $ do-    title'    <- title-    contents' <- contents-    children' <- sequence children-    return $ Headline-      { headlineLevel = level-      , headlineTodoMarker = todoKw-      , headlineText = title'-      , headlineTags = tags-      , headlineProperties = properties-      , headlineContents = contents'-      , headlineChildren = children'-      }- where-   endOfTitle :: OrgParser ()-   endOfTitle = void . lookAhead $ optional headerTags *> newline--   headerTags :: OrgParser [Tag]-   headerTags = try $-     let tag = many1 (alphaNum <|> oneOf "@%#_") <* char ':'-     in map toTag <$> (skipSpaces *> char ':' *> many1 tag <* skipSpaces)---- | Convert an Org mode headline (i.e. a document tree) into pandoc's Blocks-headlineToBlocks :: Headline -> OrgParser Blocks-headlineToBlocks hdln@(Headline {..}) = do-  maxHeadlineLevels <- getExportSetting exportHeadlineLevels-  case () of-    _ | any isNoExportTag headlineTags     -> return mempty-    _ | any isArchiveTag  headlineTags     -> archivedHeadlineToBlocks hdln-    _ | isCommentTitle headlineText        -> return mempty-    _ | headlineLevel >= maxHeadlineLevels -> headlineToHeaderWithList hdln-    _ | otherwise                          -> headlineToHeaderWithContents hdln--isNoExportTag :: Tag -> Bool-isNoExportTag = (== toTag "noexport")--isArchiveTag :: Tag -> Bool-isArchiveTag = (== toTag "ARCHIVE")---- | Check if the title starts with COMMENT.--- FIXME: This accesses builder internals not intended for use in situations--- like these.  Replace once keyword parsing is supported.-isCommentTitle :: Inlines -> Bool-isCommentTitle (B.toList -> (Str "COMMENT":_)) = True-isCommentTitle _                               = False--archivedHeadlineToBlocks :: Headline -> OrgParser Blocks-archivedHeadlineToBlocks hdln = do-  archivedTreesOption <- getExportSetting exportArchivedTrees-  case archivedTreesOption of-    ArchivedTreesNoExport     -> return mempty-    ArchivedTreesExport       -> headlineToHeaderWithContents hdln-    ArchivedTreesHeadlineOnly -> headlineToHeader hdln--headlineToHeaderWithList :: Headline -> OrgParser Blocks-headlineToHeaderWithList hdln@(Headline {..}) = do-  maxHeadlineLevels <- getExportSetting exportHeadlineLevels-  header        <- headlineToHeader hdln-  listElements  <- sequence (map headlineToBlocks headlineChildren)-  let listBlock  = if null listElements-                   then mempty-                   else B.orderedList listElements-  let headerText = if maxHeadlineLevels == headlineLevel-                   then header-                   else flattenHeader header-  return $ headerText <> headlineContents <> listBlock- where-   flattenHeader :: Blocks -> Blocks-   flattenHeader blks =-     case B.toList blks of-       (Header _ _ inlns:_) -> B.para (B.fromList inlns)-       _                    -> mempty--headlineToHeaderWithContents :: Headline -> OrgParser Blocks-headlineToHeaderWithContents hdln@(Headline {..}) = do-  header         <- headlineToHeader hdln-  childrenBlocks <- mconcat <$> sequence (map headlineToBlocks headlineChildren)-  return $ header <> headlineContents <> childrenBlocks--headlineToHeader :: Headline -> OrgParser Blocks-headlineToHeader (Headline {..}) = do-  exportTodoKeyword <- getExportSetting exportWithTodoKeywords-  let todoText    = if exportTodoKeyword-                    then case headlineTodoMarker of-                      Just kw -> todoKeywordToInlines kw <> B.space-                      Nothing -> mempty-                    else mempty-  let text        = tagTitle (todoText <> headlineText) headlineTags-  let propAttr    = propertiesToAttr headlineProperties-  attr           <- registerHeader propAttr headlineText-  return $ B.headerWith attr headlineLevel text--todoKeyword :: OrgParser TodoMarker-todoKeyword = try $ do-  taskStates <- activeTodoMarkers <$> getState-  let kwParser tdm = try $ (tdm <$ string (todoMarkerName tdm) <* spaceChar)-  choice (map kwParser taskStates)--todoKeywordToInlines :: TodoMarker -> Inlines-todoKeywordToInlines tdm =-  let todoText  = todoMarkerName tdm-      todoState = map toLower . show $ todoMarkerState tdm-      classes = [todoState, todoText]-  in B.spanWith (mempty, classes, mempty) (B.str todoText)--propertiesToAttr :: Properties -> Attr-propertiesToAttr properties =-  let-    toStringPair prop = (fromKey (fst prop), fromValue (snd prop))-    customIdKey = toPropertyKey "custom_id"-    classKey    = toPropertyKey "class"-    unnumberedKey = toPropertyKey "unnumbered"-    specialProperties = [customIdKey, classKey, unnumberedKey]-    id'  = fromMaybe mempty . fmap fromValue . lookup customIdKey $ properties-    cls  = fromMaybe mempty . fmap fromValue . lookup classKey    $ properties-    kvs' = map toStringPair . filter ((`notElem` specialProperties) . fst)-           $ properties-    isUnnumbered =-      fromMaybe False . fmap isNonNil . lookup unnumberedKey $ properties-  in-    (id', words cls ++ (if isUnnumbered then ["unnumbered"] else []), kvs')--tagTitle :: Inlines -> [Tag] -> Inlines-tagTitle title tags = title <> (mconcat $ map tagToInline tags)--tagToInline :: Tag -> Inlines-tagToInline t = B.spanWith ("", ["tag"], [("data-tag-name", fromTag t)]) mempty+import Text.Pandoc.Class (PandocMonad)+import Text.Pandoc.Definition+import Text.Pandoc.Options+import Text.Pandoc.Shared (compactify, compactifyDL, safeRead) +import Control.Monad (foldM, guard, mzero, void)+import Data.Char (isSpace, toLower, toUpper)+import Data.Default (Default)+import Data.List (foldl', isPrefixOf)+import Data.Maybe (fromMaybe, isJust, isNothing)+import Data.Monoid ((<>))  -- -- parsing blocks --  -- | Get a list of blocks.-blockList :: OrgParser [Block]+blockList :: PandocMonad m => OrgParser m [Block] blockList = do-  initialBlocks  <- blocks-  headlines      <- sequence <$> manyTill (headline 1) eof+  headlines      <- documentTree blocks inline   st             <- getState-  headlineBlocks <- fmap mconcat . sequence . map headlineToBlocks $ runF headlines st-  return . B.toList $ (runF initialBlocks st) <> headlineBlocks+  headlineBlocks <- headlineToBlocks $ runF headlines st+  -- ignore first headline, it's the document's title+  return . drop 1 . B.toList $ headlineBlocks --- | Get the meta information safed in the state.-meta :: OrgParser Meta+-- | Get the meta information saved in the state.+meta :: Monad m => OrgParser m Meta meta = do   meta' <- metaExport   runF meta' <$> getState -blocks :: OrgParser (F Blocks)+blocks :: PandocMonad m => OrgParser m (F Blocks) blocks = mconcat <$> manyTill block (void (lookAhead headerStart) <|> eof) -block :: OrgParser (F Blocks)+block :: PandocMonad m => OrgParser m (F Blocks) block = choice [ mempty <$ blanklines                , table                , orgBlock                , figure                , example                , genericDrawer+               , include                , specialLine                , horizontalRule                , list@@ -283,6 +93,11 @@                ] <?> "block"  +-- | Parse a horizontal rule into a block element+horizontalRule :: Monad m => OrgParser m (F Blocks)+horizontalRule = return B.horizontalRule <$ try hline++ -- -- Block Attributes --@@ -297,7 +112,7 @@  -- | Convert BlockAttributes into pandoc Attr attrFromBlockAttributes :: BlockAttributes -> Attr-attrFromBlockAttributes (BlockAttributes{..}) =+attrFromBlockAttributes BlockAttributes{..} =   let     ident   = fromMaybe mempty $ lookup "id" blockAttrKeyValues     classes = case lookup "class" blockAttrKeyValues of@@ -306,18 +121,18 @@     kv      = filter ((`notElem` ["id", "class"]) . fst) blockAttrKeyValues   in (ident, classes, kv) -stringyMetaAttribute :: (String -> Bool) -> OrgParser (String, String)-stringyMetaAttribute attrCheck = try $ do+stringyMetaAttribute :: Monad m => OrgParser m (String, String)+stringyMetaAttribute = try $ do   metaLineStart   attrName <- map toUpper <$> many1Till nonspaceChar (char ':')-  guard $ attrCheck attrName   skipSpaces-  attrValue <- anyLine+  attrValue <- anyLine <|> ("" <$ newline)   return (attrName, attrValue) -blockAttributes :: OrgParser BlockAttributes+blockAttributes :: PandocMonad m => OrgParser m BlockAttributes blockAttributes = try $ do-  kv <- many (stringyMetaAttribute attrCheck)+  kv <- many stringyMetaAttribute+  guard $ all (attrCheck . fst) kv   let caption = foldl' (appendValues "CAPTION") Nothing kv   let kvAttrs = foldl' (appendValues "ATTR_HTML") Nothing kv   let name    = lookup "NAME" kv@@ -326,7 +141,7 @@                    Nothing -> return Nothing                    Just s  -> Just <$> parseFromString inlines (s ++ "\n")   kvAttrs' <- parseFromString keyValues . (++ "\n") $ fromMaybe mempty kvAttrs-  return $ BlockAttributes+  return BlockAttributes            { blockAttrName = name            , blockAttrLabel = label            , blockAttrCaption = caption'@@ -334,13 +149,7 @@            }  where    attrCheck :: String -> Bool-   attrCheck attr =-     case attr of-       "NAME"      -> True-       "LABEL"     -> True-       "CAPTION"   -> True-       "ATTR_HTML" -> True-       _           -> False+   attrCheck x = x `elem` ["NAME", "LABEL", "CAPTION", "ATTR_HTML", "RESULTS"]     appendValues :: String -> Maybe String -> (String, String) -> Maybe String    appendValues attrName accValue (key, value) =@@ -350,17 +159,18 @@             Just acc -> Just $ acc ++ ' ':value             Nothing  -> Just value -keyValues :: OrgParser [(String, String)]+-- | Parse key-value pairs for HTML attributes+keyValues :: Monad m => OrgParser m [(String, String)] keyValues = try $   manyTill ((,) <$> key <*> value) newline  where-   key :: OrgParser String+   key :: Monad m => OrgParser m String    key = try $ skipSpaces *> char ':' *> many1 nonspaceChar -   value :: OrgParser String+   value :: Monad m => OrgParser m String    value = skipSpaces *> manyTill anyChar endOfValue -   endOfValue :: OrgParser ()+   endOfValue :: Monad m => OrgParser m ()    endOfValue =      lookAhead $ (() <$ try (many1 spaceChar <* key))               <|> () <$ newline@@ -371,12 +181,12 @@ --  -- | Read an org-mode block delimited by #+BEGIN_TYPE and #+END_TYPE.-orgBlock :: OrgParser (F Blocks)+orgBlock :: PandocMonad m => OrgParser m (F Blocks) orgBlock = try $ do   blockAttrs <- blockAttributes   blkType <- blockHeaderStart   ($ blkType) $-    case (map toLower blkType) of+    case map toLower blkType of       "export"  -> exportBlock       "comment" -> rawBlockLines (const mempty)       "html"    -> rawBlockLines (return . B.rawBlock (lowercase blkType))@@ -390,25 +200,25 @@                    let (ident, classes, kv) = attrFromBlockAttributes blockAttrs                    in fmap $ B.divWith (ident, classes ++ [blkType], kv)  where-   blockHeaderStart :: OrgParser String+   blockHeaderStart :: Monad m => OrgParser m String    blockHeaderStart = try $ skipSpaces *> stringAnyCase "#+begin_" *> orgArgWord     lowercase :: String -> String    lowercase = map toLower -rawBlockLines :: (String   -> F Blocks) -> String -> OrgParser (F Blocks)-rawBlockLines f blockType = (ignHeaders *> (f <$> rawBlockContent blockType))+rawBlockLines :: Monad m => (String   -> F Blocks) -> String -> OrgParser m (F Blocks)+rawBlockLines f blockType = ignHeaders *> (f <$> rawBlockContent blockType) -parseBlockLines :: (F Blocks -> F Blocks) -> String -> OrgParser (F Blocks)-parseBlockLines f blockType = (ignHeaders *> (f <$> parsedBlockContent))+parseBlockLines :: PandocMonad m => (F Blocks -> F Blocks) -> String -> OrgParser m (F Blocks)+parseBlockLines f blockType = ignHeaders *> (f <$> parsedBlockContent)  where-   parsedBlockContent :: OrgParser (F Blocks)+   parsedBlockContent :: PandocMonad m => OrgParser m (F Blocks)    parsedBlockContent = try $ do      raw <- rawBlockContent blockType      parseFromString blocks (raw ++ "\n")  -- | Read the raw string content of a block-rawBlockContent :: String -> OrgParser String+rawBlockContent :: Monad m => String -> OrgParser m String rawBlockContent blockType = try $ do   blkLines <- manyTill rawLine blockEnder   tabLen <- getOption readerTabStop@@ -418,18 +228,17 @@     . map (tabsToSpaces tabLen . commaEscaped)     $ blkLines  where-   rawLine :: OrgParser String+   rawLine :: Monad m => OrgParser m String    rawLine = try $ ("" <$ blankline) <|> anyLine -   blockEnder :: OrgParser ()+   blockEnder :: Monad m => OrgParser m ()    blockEnder = try $ skipSpaces <* stringAnyCase ("#+end_" <> blockType)     stripIndent :: [String] -> [String]    stripIndent strs = map (drop (shortestIndent strs)) strs     shortestIndent :: [String] -> Int-   shortestIndent = foldr min maxBound-                    . map (length . takeWhile isSpace)+   shortestIndent = foldr (min . length . takeWhile isSpace) maxBound                     . filter (not . null)     tabsToSpaces :: Int -> String -> String@@ -437,7 +246,7 @@    tabsToSpaces tabLen cs'@(c:cs) =        case c of          ' '  -> ' ':tabsToSpaces tabLen cs-         '\t' -> (take tabLen $ repeat ' ') ++ tabsToSpaces tabLen cs+         '\t' -> replicate tabLen ' ' ++ tabsToSpaces tabLen cs          _    -> cs'     commaEscaped :: String -> String@@ -448,18 +257,18 @@    commaEscaped cs                   = cs  -- | Read but ignore all remaining block headers.-ignHeaders :: OrgParser ()+ignHeaders :: Monad m => OrgParser m () ignHeaders = (() <$ newline) <|> (() <$ anyLine)  -- | Read a block containing code intended for export in specific backends -- only.-exportBlock :: String -> OrgParser (F Blocks)+exportBlock :: Monad m => String -> OrgParser m (F Blocks) exportBlock blockType = try $ do   exportType <- skipSpaces *> orgArgWord <* ignHeaders   contents   <- rawBlockContent blockType   returnF (B.rawBlock (map toLower exportType) contents) -verseBlock :: String -> OrgParser (F Blocks)+verseBlock :: PandocMonad m => String -> OrgParser m (F Blocks) verseBlock blockType = try $ do   ignHeaders   content <- rawBlockContent blockType@@ -468,7 +277,7 @@  where    -- replace initial spaces with nonbreaking spaces to preserve    -- indentation, parse the rest as normal inline-   parseVerseLine :: String -> OrgParser (F Inlines)+   parseVerseLine :: PandocMonad m => String -> OrgParser m (F Inlines)    parseVerseLine cs = do      let (initialSpaces, indentedLine) = span isSpace cs      let nbspIndent = if null initialSpaces@@ -480,23 +289,20 @@ -- | Read a code block and the associated results block if present.  Which of -- boths blocks is included in the output is determined using the "exports" -- argument in the block header.-codeBlock :: BlockAttributes -> String -> OrgParser (F Blocks)+codeBlock :: PandocMonad m => BlockAttributes -> String -> OrgParser m (F Blocks) codeBlock blockAttrs blockType = do   skipSpaces   (classes, kv)     <- codeHeaderArgs <|> (mempty <$ ignHeaders)   content           <- rawBlockContent blockType-  resultsContent    <- trailingResultsBlock+  resultsContent    <- option mempty babelResultsBlock   let id'            = fromMaybe mempty $ blockAttrName blockAttrs-  let includeCode    = exportsCode kv-  let includeResults = exportsResults kv   let codeBlck       = B.codeBlockWith ( id', classes, kv ) content   let labelledBlck   = maybe (pure codeBlck)                              (labelDiv codeBlck)                              (blockAttrCaption blockAttrs)-  let resultBlck     = fromMaybe mempty resultsContent   return $-    (if includeCode    then labelledBlck else mempty) <>-    (if includeResults then resultBlck   else mempty)+    (if exportsCode kv    then labelledBlck   else mempty) <>+    (if exportsResults kv then resultsContent else mempty)  where    labelDiv :: Blocks -> F Inlines -> F Blocks    labelDiv blk value =@@ -505,60 +311,97 @@    labelledBlock :: F Inlines -> F Blocks    labelledBlock = fmap (B.plain . B.spanWith ("", ["label"], [])) -exportsCode :: [(String, String)] -> Bool-exportsCode attrs = not (("rundoc-exports", "none") `elem` attrs-                         || ("rundoc-exports", "results") `elem` attrs)+   exportsCode :: [(String, String)] -> Bool+   exportsCode = maybe True (`elem` ["code", "both"]) . lookup "exports" -exportsResults :: [(String, String)] -> Bool-exportsResults attrs = ("rundoc-exports", "results") `elem` attrs-                       || ("rundoc-exports", "both") `elem` attrs+   exportsResults :: [(String, String)] -> Bool+   exportsResults = maybe False (`elem` ["results", "both"]) . lookup "exports" -trailingResultsBlock :: OrgParser (Maybe (F Blocks))-trailingResultsBlock = optionMaybe . try $ do+-- | Parse the result of an evaluated babel code block.+babelResultsBlock :: PandocMonad m => OrgParser m (F Blocks)+babelResultsBlock = try $ do   blanklines-  stringAnyCase "#+RESULTS:"-  blankline+  resultsMarker <|>+    (lookAhead . void . try $+      manyTill (metaLineStart *> anyLineNewline) resultsMarker)   block+ where+  resultsMarker = try . void $ stringAnyCase "#+RESULTS:" *> blankline  -- | Parse code block arguments--- TODO: We currently don't handle switches.-codeHeaderArgs :: OrgParser ([String], [(String, String)])+codeHeaderArgs :: Monad m => OrgParser m ([String], [(String, String)]) codeHeaderArgs = try $ do   language   <- skipSpaces *> orgArgWord-  _          <- skipSpaces *> (try $ switch `sepBy` (many1 spaceChar))+  (switchClasses, switchKv) <- switchesAsAttributes   parameters <- manyTill blockOption newline-  let pandocLang = translateLang language-  return $-    if hasRundocParameters parameters-    then ( [ pandocLang, rundocBlockClass ]-         , map toRundocAttrib (("language", language) : parameters)+  return ( translateLang language : switchClasses+         , originalLang language <> switchKv <> parameters          )-    else ([ pandocLang ], parameters)++switchesAsAttributes :: Monad m => OrgParser m ([String], [(String, String)])+switchesAsAttributes = try $ do+  switches <- skipSpaces *> try (switch `sepBy` many1 spaceChar)+  return $ foldr addToAttr ([], []) switches  where-   hasRundocParameters = not . null+  addToAttr :: (Char, Maybe String, SwitchPolarity)+            -> ([String], [(String, String)])+            -> ([String], [(String, String)])+  addToAttr ('n', lineNum, pol) (cls, kv) =+    let kv' = case lineNum of+                Just num -> ("startFrom", num):kv+                Nothing  -> kv+        cls' = case pol of+                 SwitchPlus  -> "continuedSourceBlock":cls+                 SwitchMinus -> cls+    in ("numberLines":cls', kv')+  addToAttr _ x = x -switch :: OrgParser (Char, Maybe String)-switch = try $ simpleSwitch <|> lineNumbersSwitch+-- | Whether a switch flag is specified with @+@ or @-@.+data SwitchPolarity = SwitchPlus | SwitchMinus+  deriving (Show, Eq)++-- | Parses a switch's polarity.+switchPolarity :: Monad m => OrgParser m SwitchPolarity+switchPolarity = (SwitchMinus <$ char '-') <|> (SwitchPlus <$ char '+')++-- | Parses a source block switch option.+switch :: Monad m => OrgParser m (Char, Maybe String, SwitchPolarity)+switch = try $ lineNumberSwitch <|> labelSwitch <|> simpleSwitch  where-   simpleSwitch = (\c -> (c, Nothing)) <$> (oneOf "-+" *> letter)-   lineNumbersSwitch = (\ls -> ('l', Just ls)) <$>-                       (string "-l \"" *> many1Till nonspaceChar (char '"'))+   simpleSwitch = (\pol c -> (c, Nothing, pol)) <$> switchPolarity <*> letter+   labelSwitch = genericSwitch 'l' $+     char '"' *> many1Till nonspaceChar (char '"') -blockOption :: OrgParser (String, String)+-- | Generic source block switch-option parser.+genericSwitch :: Monad m+              => Char+              -> OrgParser m String+              -> OrgParser m (Char, Maybe String, SwitchPolarity)+genericSwitch c p = try $ do+  polarity <- switchPolarity <* char c <* skipSpaces+  arg <- optionMaybe p+  return (c, arg, polarity)++-- | Reads a line number switch option. The line number switch can be used with+-- example and source blocks.+lineNumberSwitch :: Monad m => OrgParser m (Char, Maybe String, SwitchPolarity)+lineNumberSwitch = genericSwitch 'n' (many digit)++blockOption :: Monad m => OrgParser m (String, String) blockOption = try $ do   argKey <- orgArgKey   paramValue <- option "yes" orgParamValue   return (argKey, paramValue) -orgParamValue :: OrgParser String+orgParamValue :: Monad m => OrgParser m String orgParamValue = try $   skipSpaces-    *> notFollowedBy (char ':' )-    *> many1 nonspaceChar+    *> notFollowedBy orgArgKey+    *> noneOf "\n\r" `many1Till` endOfValue     <* skipSpaces--horizontalRule :: OrgParser (F Blocks)-horizontalRule = return B.horizontalRule <$ try hline+ where+  endOfValue = lookAhead $  try (skipSpaces <* oneOf "\n\r")+                        <|> try (skipSpaces1 <* orgArgKey)   --@@ -568,7 +411,7 @@ -- | A generic drawer which has no special meaning for org-mode. -- Whether or not this drawer is included in the output depends on the drawers -- export setting.-genericDrawer :: OrgParser (F Blocks)+genericDrawer :: PandocMonad m => OrgParser m (F Blocks) genericDrawer = try $ do   name    <- map toUpper <$> drawerStart   content <- manyTill drawerLine (try drawerEnd)@@ -576,52 +419,33 @@   -- Include drawer if it is explicitly included in or not explicitly excluded   -- from the list of drawers that should be exported.  PROPERTIES drawers are   -- never exported.-  case (exportDrawers . orgStateExportSettings $ state) of+  case exportDrawers . orgStateExportSettings $ state of     _           | name == "PROPERTIES" -> return mempty     Left  names | name `elem`    names -> return mempty     Right names | name `notElem` names -> return mempty-    _                                  -> drawerDiv name <$> parseLines content+    _           -> drawerDiv name <$> parseLines content  where-  parseLines :: [String] -> OrgParser (F Blocks)+  parseLines :: PandocMonad m => [String] -> OrgParser m (F Blocks)   parseLines = parseFromString blocks . (++ "\n") . unlines    drawerDiv :: String -> F Blocks -> F Blocks   drawerDiv drawerName = fmap $ B.divWith (mempty, [drawerName, "drawer"], mempty) -drawerLine :: OrgParser String+drawerLine :: Monad m => OrgParser m String drawerLine = anyLine -drawerEnd :: OrgParser String+drawerEnd :: Monad m => OrgParser m String drawerEnd = try $   skipSpaces *> stringAnyCase ":END:" <* skipSpaces <* newline --- | Read a :PROPERTIES: drawer and return the key/value pairs contained--- within.-propertiesDrawer :: OrgParser Properties-propertiesDrawer = try $ do-  drawerType <- drawerStart-  guard $ map toUpper drawerType == "PROPERTIES"-  manyTill property (try drawerEnd)- where-   property :: OrgParser (PropertyKey, PropertyValue)-   property = try $ (,) <$> key <*> value -   key :: OrgParser PropertyKey-   key = fmap toPropertyKey . try $-         skipSpaces *> char ':' *> many1Till nonspaceChar (char ':')--   value :: OrgParser PropertyValue-   value = fmap toPropertyValue . try $-           skipSpaces *> manyTill anyChar (try $ skipSpaces *> newline)-- -- -- Figures --  -- | Figures or an image paragraph (i.e. an image on a line by itself). Only -- images with a caption attribute are interpreted as figures.-figure :: OrgParser (F Blocks)+figure :: PandocMonad m => OrgParser m (F Blocks) figure = try $ do   figAttrs <- blockAttributes   src <- skipSpaces *> selfTarget <* skipSpaces <* endOfParagraph@@ -629,10 +453,10 @@     Nothing     -> mzero     Just imgSrc -> do       guard (isImageFilename imgSrc)-      let isFigure = not . isNothing $ blockAttrCaption figAttrs+      let isFigure = isJust $ blockAttrCaption figAttrs       return $ imageBlock isFigure figAttrs imgSrc  where-   selfTarget :: OrgParser String+   selfTarget :: PandocMonad m => OrgParser m String    selfTarget = try $ char '[' *> linkTarget <* char ']'     imageBlock :: Bool -> BlockAttributes -> String -> F Blocks@@ -654,7 +478,7 @@      else "fig:" ++ cs  -- | Succeeds if looking at the end of the current paragraph-endOfParagraph :: OrgParser ()+endOfParagraph :: Monad m => OrgParser m () endOfParagraph = try $ skipSpaces *> newline *> endOfBlock  @@ -663,11 +487,10 @@ --  -- | Example code marked up by a leading colon.-example :: OrgParser (F Blocks)-example = try $ do-  return . return . exampleCode =<< unlines <$> many1 exampleLine+example :: Monad m => OrgParser m (F Blocks)+example = try $ returnF . exampleCode =<< unlines <$> many1 exampleLine  where-   exampleLine :: OrgParser String+   exampleLine :: Monad m => OrgParser m String    exampleLine = try $ exampleLineStart *> anyLine  exampleCode :: String -> Blocks@@ -678,10 +501,38 @@ -- Comments, Options and Metadata -- -specialLine :: OrgParser (F Blocks)+specialLine :: PandocMonad m => OrgParser m (F Blocks) specialLine = fmap return . try $ rawExportLine <|> metaLine <|> commentLine -rawExportLine :: OrgParser Blocks+-- | Include the content of a file.+include :: PandocMonad m => OrgParser m (F Blocks)+include = try $ do+  metaLineStart <* stringAnyCase "include:" <* skipSpaces+  filename <- includeTarget+  blockType <- optionMaybe $ skipSpaces *> many1 alphaNum+  blocksParser <- case blockType of+                    Just "example" ->+                      return $ pure . B.codeBlock <$> parseRaw+                    Just "export" -> do+                      format <- skipSpaces *> many (noneOf "\n\r\t ")+                      return $ pure . B.rawBlock format <$> parseRaw+                    Just "src" -> do+                      language <- skipSpaces *> many (noneOf "\n\r\t ")+                      let attr = (mempty, [language], mempty)+                      return $ pure . B.codeBlockWith attr <$> parseRaw+                    _ -> return $ pure . B.fromList <$> blockList+  anyLine+  insertIncludedFileF blocksParser ["."] filename+ where+  includeTarget :: PandocMonad m => OrgParser m FilePath+  includeTarget = do+    char '"'+    manyTill (noneOf "\n\r\t") (char '"')++  parseRaw :: PandocMonad m => OrgParser m String+  parseRaw = many anyChar++rawExportLine :: PandocMonad m => OrgParser m Blocks rawExportLine = try $ do   metaLineStart   key <- metaKey@@ -689,7 +540,7 @@     then B.rawBlock key <$> anyLine     else mzero -commentLine :: OrgParser Blocks+commentLine :: Monad m => OrgParser m Blocks commentLine = commentLineStart *> anyLine *> pure mempty  @@ -714,12 +565,21 @@ -- should be generated using a builder function. data OrgTable = OrgTable   { orgTableColumnProperties :: [ColumnProperty]-  , orgTableHeader     :: [Blocks]-  , orgTableRows       :: [[Blocks]]+  , orgTableHeader           :: [Blocks]+  , orgTableRows             :: [[Blocks]]   } -table :: OrgParser (F Blocks)-table = try $ do+table :: PandocMonad m => OrgParser m (F Blocks)+table = gridTableWith blocks True <|> orgTable++-- | A normal org table+orgTable :: PandocMonad m => OrgParser m (F Blocks)+orgTable = try $ do+  -- don't allow a table on the first line of a list item; org requires that+  -- tables start at first non-space character on the line+  let isFirstInListItem st = orgStateParserContext st == ListItemState &&+                             isNothing (orgStateLastPreCharPos st)+  guard =<< not . isFirstInListItem <$> getState   blockAttrs <- blockAttributes   lookAhead tableStart   do@@ -731,7 +591,7 @@                  -> Inlines                  -> Blocks orgToPandocTable (OrgTable colProps heads lns) caption =-  let totalWidth = if any (not . isNothing) (map columnRelWidth colProps)+  let totalWidth = if any isJust (map columnRelWidth colProps)                    then Just . sum $ map (fromMaybe 1 . columnRelWidth) colProps                    else Nothing   in B.table caption (map (convertColProp totalWidth) colProps) heads lns@@ -741,22 +601,22 @@      let        align' = fromMaybe AlignDefault $ columnAlignment colProp        width' = fromMaybe 0 $ (\w t -> (fromIntegral w / fromIntegral t))-                              <$> (columnRelWidth colProp)+                              <$> columnRelWidth colProp                               <*> totalWidth      in (align', width') -tableRows :: OrgParser [OrgTableRow]+tableRows :: PandocMonad m => OrgParser m [OrgTableRow] tableRows = try $ many (tableAlignRow <|> tableHline <|> tableContentRow) -tableContentRow :: OrgParser OrgTableRow+tableContentRow :: PandocMonad m => OrgParser m OrgTableRow tableContentRow = try $   OrgContentRow . sequence <$> (tableStart *> many1Till tableContentCell newline) -tableContentCell :: OrgParser (F Blocks)+tableContentCell :: PandocMonad m => OrgParser m (F Blocks) tableContentCell = try $   fmap B.plain . trimInlinesF . mconcat <$> manyTill inline endOfCell -tableAlignRow :: OrgParser OrgTableRow+tableAlignRow :: Monad m => OrgParser m OrgTableRow tableAlignRow = try $ do   tableStart   colProps <- many1Till columnPropertyCell newline@@ -764,10 +624,10 @@   guard $ any (/= def) colProps   return $ OrgAlignRow colProps -columnPropertyCell :: OrgParser ColumnProperty+columnPropertyCell :: Monad m => OrgParser m ColumnProperty columnPropertyCell = emptyCell <|> propCell <?> "alignment info"  where-   emptyCell = ColumnProperty Nothing Nothing <$ (try $ skipSpaces *> endOfCell)+   emptyCell = ColumnProperty Nothing Nothing <$ try (skipSpaces *> endOfCell)    propCell = try $ ColumnProperty                  <$> (skipSpaces                       *> char '<'@@ -776,18 +636,18 @@                       <* char '>'                       <* emptyCell) -tableAlignFromChar :: OrgParser Alignment+tableAlignFromChar :: Monad m => OrgParser m Alignment tableAlignFromChar = try $   choice [ char 'l' *> return AlignLeft          , char 'c' *> return AlignCenter          , char 'r' *> return AlignRight          ] -tableHline :: OrgParser OrgTableRow+tableHline :: Monad m => OrgParser m OrgTableRow tableHline = try $   OrgHlineRow <$ (tableStart *> char '-' *> anyLine) -endOfCell :: OrgParser Char+endOfCell :: Monad m => OrgParser m Char endOfCell = try $ char '|' <|> lookAhead newline  rowsToTable :: [OrgTableRow]@@ -813,45 +673,45 @@ rowToContent :: OrgTable              -> OrgTableRow              -> F OrgTable-rowToContent orgTable row =+rowToContent tbl row =   case row of     OrgHlineRow       -> return singleRowPromotedToHeader     OrgAlignRow props -> return . setProperties $ props     OrgContentRow cs  -> appendToBody cs  where    singleRowPromotedToHeader :: OrgTable-   singleRowPromotedToHeader = case orgTable of-     OrgTable{ orgTableHeader = [], orgTableRows = b:[] } ->-            orgTable{ orgTableHeader = b , orgTableRows = [] }-     _   -> orgTable+   singleRowPromotedToHeader = case tbl of+     OrgTable{ orgTableHeader = [], orgTableRows = [b] } ->+            tbl{ orgTableHeader = b , orgTableRows = [] }+     _   -> tbl     setProperties :: [ColumnProperty] -> OrgTable-   setProperties ps = orgTable{ orgTableColumnProperties = ps }+   setProperties ps = tbl{ orgTableColumnProperties = ps }     appendToBody :: F [Blocks] -> F OrgTable    appendToBody frow = do      newRow <- frow-     let oldRows = orgTableRows orgTable+     let oldRows = orgTableRows tbl      -- NOTE: This is an inefficient O(n) operation.  This should be changed      -- if performance ever becomes a problem.-     return orgTable{ orgTableRows = oldRows ++ [newRow] }+     return tbl{ orgTableRows = oldRows ++ [newRow] }   -- -- LaTeX fragments ---latexFragment :: OrgParser (F Blocks)+latexFragment :: Monad m => OrgParser m (F Blocks) latexFragment = try $ do   envName <- latexEnvStart   content <- mconcat <$> manyTill anyLineNewline (latexEnd envName)-  return . return $ B.rawBlock "latex" (content `inLatexEnv` envName)+  returnF $ B.rawBlock "latex" (content `inLatexEnv` envName)  where    c `inLatexEnv` e = mconcat [ "\\begin{", e, "}\n"                               , c                               , "\\end{", e, "}\n"                               ] -latexEnd :: String -> OrgParser ()+latexEnd :: Monad m => String -> OrgParser m () latexEnd envName = try $   () <$ skipSpaces      <* string ("\\end{" ++ envName ++ "}")@@ -861,22 +721,23 @@ -- -- Footnote defintions ---noteBlock :: OrgParser (F Blocks)+noteBlock :: PandocMonad m => OrgParser m (F Blocks) noteBlock = try $ do-  ref <- noteMarker <* skipSpaces-  content <- mconcat <$> blocksTillHeaderOrNote+  ref <- noteMarker <* skipSpaces <* updateLastPreCharPos+  content <- mconcat <$> many1Till block endOfFootnote   addToNotesTable (ref, content)   return mempty  where-   blocksTillHeaderOrNote =-     many1Till block (eof <|> () <$ lookAhead noteMarker-                          <|> () <$ lookAhead headerStart)+   endOfFootnote =  eof+                <|> () <$ lookAhead noteMarker+                <|> () <$ lookAhead headerStart+                <|> () <$ lookAhead (try $ blankline *> blankline)  -- Paragraphs or Plain text-paraOrPlain :: OrgParser (F Blocks)+paraOrPlain :: PandocMonad m => OrgParser m (F Blocks) paraOrPlain = try $ do   -- Make sure we are not looking at a headline-  notFollowedBy' (char '*' *> (oneOf " *"))+  notFollowedBy' (char '*' *> oneOf " *")   ils <- inlines   nl <- option False (newline *> return True)   -- Read block as paragraph, except if we are in a list context and the block@@ -885,31 +746,31 @@   try (guard nl        *> notFollowedBy (inList *> (() <$ orderedListStart <|> bulletListStart))        *> return (B.para <$> ils))-    <|>  (return (B.plain <$> ils))+    <|>  return (B.plain <$> ils)   -- -- list blocks -- -list :: OrgParser (F Blocks)+list :: PandocMonad m => OrgParser m (F Blocks) list = choice [ definitionList, bulletList, orderedList ] <?> "list" -definitionList :: OrgParser (F Blocks)+definitionList :: PandocMonad m => OrgParser m (F Blocks) definitionList = try $ do n <- lookAhead (bulletListStart' Nothing)-                          fmap B.definitionList . fmap compactify'DL . sequence+                          fmap (B.definitionList . compactifyDL) . sequence                             <$> many1 (definitionListItem $ bulletListStart' (Just n)) -bulletList :: OrgParser (F Blocks)+bulletList :: PandocMonad m => OrgParser m (F Blocks) bulletList = try $ do n <- lookAhead (bulletListStart' Nothing)-                      fmap B.bulletList . fmap compactify' . sequence+                      fmap (B.bulletList . compactify) . sequence                         <$> many1 (listItem (bulletListStart' $ Just n)) -orderedList :: OrgParser (F Blocks)-orderedList = fmap B.orderedList . fmap compactify' . sequence+orderedList :: PandocMonad m => OrgParser m (F Blocks)+orderedList = fmap (B.orderedList . compactify) . sequence               <$> many1 (listItem orderedListStart) -bulletListStart' :: Maybe Int -> OrgParser Int+bulletListStart' :: Monad m => Maybe Int -> OrgParser m Int -- returns length of bulletList prefix, inclusive of marker bulletListStart' Nothing  = do ind <- length <$> many spaceChar                                oneOf (bullets $ ind == 0)@@ -925,8 +786,9 @@ bullets :: Bool -> String bullets unindented = if unindented then "+-" else "*+-" -definitionListItem :: OrgParser Int-                   -> OrgParser (F (Inlines, [Blocks]))+definitionListItem :: PandocMonad m+                   => OrgParser m Int+                   -> OrgParser m (F (Inlines, [Blocks])) definitionListItem parseMarkerGetLength = try $ do   markerLength <- parseMarkerGetLength   term <- manyTill (noneOf "\n\r") (try definitionMarker)@@ -942,8 +804,9 @@   -- parse raw text for one list item, excluding start marker and continuations-listItem :: OrgParser Int-         -> OrgParser (F Blocks)+listItem :: PandocMonad m+         => OrgParser m Int+         -> OrgParser m (F Blocks) listItem start = try . withContext ListItemState $ do   markerLength <- try start   firstLine <- anyLineNewline@@ -953,24 +816,11 @@  -- continuation of a list item - indented and separated by blankline or endline. -- Note: nested lists are parsed as continuations.-listContinuation :: Int-                 -> OrgParser String+listContinuation :: Monad m => Int+                 -> OrgParser m String listContinuation markerLength = try $   notFollowedBy' blankline   *> (mappend <$> (concat <$> many1 listLine)               <*> many blankline)  where    listLine = try $ indentWith markerLength *> anyLineNewline--   -- indent by specified number of spaces (or equiv. tabs)-   indentWith :: Int -> OrgParser String-   indentWith num = do-     tabStop <- getOption readerTabStop-     if num < tabStop-       then count num (char ' ')-       else choice [ try (count num (char ' '))-                   , try (char '\t' >> count (num - tabStop) (char ' ')) ]---- | Parse any line, include the final newline in the output.-anyLineNewline :: OrgParser String-anyLineNewline = (++ "\n") <$> anyLine
+ src/Text/Pandoc/Readers/Org/DocumentTree.hs view
@@ -0,0 +1,304 @@+{-+Copyright (C) 2014-2017 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation; either version 2 of the License, or+(at your option) any later version.++This program is distributed in the hope that it will be useful,+but WITHOUT ANY WARRANTY; without even the implied warranty of+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+GNU General Public License for more details.++You should have received a copy of the GNU General Public License+along with this program; if not, write to the Free Software+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RecordWildCards  #-}+{-# LANGUAGE ViewPatterns     #-}+{- |+   Module      : Text.Pandoc.Readers.Org.DocumentTree+   Copyright   : Copyright (C) 2014-2017 Albert Krewinkel+   License     : GNU GPL, version 2 or above++   Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>++Parsers for org-mode headlines and document subtrees+-}+module Text.Pandoc.Readers.Org.DocumentTree+  ( documentTree+  , headlineToBlocks+  ) where++import Control.Arrow ((***))+import Control.Monad (guard, void)+import Data.Char (toLower, toUpper)+import Data.List (intersperse)+import Data.Monoid ((<>))+import Text.Pandoc.Builder (Blocks, Inlines)+import Text.Pandoc.Class (PandocMonad)+import Text.Pandoc.Definition+import Text.Pandoc.Readers.Org.BlockStarts+import Text.Pandoc.Readers.Org.ParserState+import Text.Pandoc.Readers.Org.Parsing++import qualified Data.Map as Map+import qualified Text.Pandoc.Builder as B++--+-- Org headers+--++-- | Parse input as org document tree.+documentTree :: PandocMonad m+             => OrgParser m (F Blocks)+             -> OrgParser m (F Inlines)+             -> OrgParser m (F Headline)+documentTree blocks inline = do+  initialBlocks <- blocks+  headlines <- sequence <$> manyTill (headline blocks inline 1) eof+  title <- fmap (getTitle . unMeta) . orgStateMeta <$> getState+  return $ do+    headlines' <- headlines+    initialBlocks' <- initialBlocks+    title' <- title+    return Headline+      { headlineLevel = 0+      , headlineTodoMarker = Nothing+      , headlineText = B.fromList title'+      , headlineTags = mempty+      , headlineProperties = mempty+      , headlineContents = initialBlocks'+      , headlineChildren = headlines'+      }+ where+  getTitle :: Map.Map String MetaValue -> [Inline]+  getTitle metamap =+    case Map.lookup "title" metamap of+      Just (MetaInlines inlns) -> inlns+      _                        -> []++newtype Tag = Tag { fromTag :: String }+  deriving (Show, Eq)++-- | Create a tag containing the given string.+toTag :: String -> Tag+toTag = Tag++-- | The key (also called name or type) of a property.+newtype PropertyKey = PropertyKey { fromKey :: String }+  deriving (Show, Eq, Ord)++-- | Create a property key containing the given string.  Org mode keys are+-- case insensitive and are hence converted to lower case.+toPropertyKey :: String -> PropertyKey+toPropertyKey = PropertyKey . map toLower++-- | The value assigned to a property.+newtype PropertyValue = PropertyValue { fromValue :: String }++-- | Create a property value containing the given string.+toPropertyValue :: String -> PropertyValue+toPropertyValue = PropertyValue++-- | Check whether the property value is non-nil (i.e. truish).+isNonNil :: PropertyValue -> Bool+isNonNil p = map toLower (fromValue p) `notElem` ["()", "{}", "nil"]++-- | Key/value pairs from a PROPERTIES drawer+type Properties = [(PropertyKey, PropertyValue)]++-- | Org mode headline (i.e. a document subtree).+data Headline = Headline+  { headlineLevel      :: Int+  , headlineTodoMarker :: Maybe TodoMarker+  , headlineText       :: Inlines+  , headlineTags       :: [Tag]+  , headlineProperties :: Properties+  , headlineContents   :: Blocks+  , headlineChildren   :: [Headline]+  }++-- | Read an Org mode headline and its contents (i.e. a document subtree).+-- @lvl@ gives the minimum acceptable level of the tree.+headline :: PandocMonad m+         => OrgParser m (F Blocks)+         -> OrgParser m (F Inlines)+         -> Int+         -> OrgParser m (F Headline)+headline blocks inline lvl = try $ do+  level <- headerStart+  guard (lvl <= level)+  todoKw <- optionMaybe todoKeyword+  title <- trimInlinesF . mconcat <$> manyTill inline endOfTitle+  tags  <- option [] headerTags+  newline+  properties <- option mempty propertiesDrawer+  contents   <- blocks+  children   <- many (headline blocks inline (level + 1))+  return $ do+    title'    <- title+    contents' <- contents+    children' <- sequence children+    return Headline+      { headlineLevel = level+      , headlineTodoMarker = todoKw+      , headlineText = title'+      , headlineTags = tags+      , headlineProperties = properties+      , headlineContents = contents'+      , headlineChildren = children'+      }+ where+   endOfTitle :: Monad m => OrgParser m ()+   endOfTitle = void . lookAhead $ optional headerTags *> newline++   headerTags :: Monad m => OrgParser m [Tag]+   headerTags = try $+     let tag = many1 (alphaNum <|> oneOf "@%#_") <* char ':'+     in map toTag <$> (skipSpaces *> char ':' *> many1 tag <* skipSpaces)++-- | Convert an Org mode headline (i.e. a document tree) into pandoc's Blocks+headlineToBlocks :: Monad m => Headline -> OrgParser m Blocks+headlineToBlocks hdln@Headline {..} = do+  maxHeadlineLevels <- getExportSetting exportHeadlineLevels+  case () of+    _ | any isNoExportTag headlineTags     -> return mempty+    _ | any isArchiveTag  headlineTags     -> archivedHeadlineToBlocks hdln+    _ | isCommentTitle headlineText        -> return mempty+    _ | headlineLevel >= maxHeadlineLevels -> headlineToHeaderWithList hdln+    _ | otherwise                          -> headlineToHeaderWithContents hdln++isNoExportTag :: Tag -> Bool+isNoExportTag = (== toTag "noexport")++isArchiveTag :: Tag -> Bool+isArchiveTag = (== toTag "ARCHIVE")++-- | Check if the title starts with COMMENT.+-- FIXME: This accesses builder internals not intended for use in situations+-- like these.  Replace once keyword parsing is supported.+isCommentTitle :: Inlines -> Bool+isCommentTitle (B.toList -> (Str "COMMENT":_)) = True+isCommentTitle _                               = False++archivedHeadlineToBlocks :: Monad m => Headline -> OrgParser m Blocks+archivedHeadlineToBlocks hdln = do+  archivedTreesOption <- getExportSetting exportArchivedTrees+  case archivedTreesOption of+    ArchivedTreesNoExport     -> return mempty+    ArchivedTreesExport       -> headlineToHeaderWithContents hdln+    ArchivedTreesHeadlineOnly -> headlineToHeader hdln++headlineToHeaderWithList :: Monad m => Headline -> OrgParser m Blocks+headlineToHeaderWithList hdln@Headline {..} = do+  maxHeadlineLevels <- getExportSetting exportHeadlineLevels+  header        <- headlineToHeader hdln+  listElements  <- mapM headlineToBlocks headlineChildren+  let listBlock  = if null listElements+                   then mempty+                   else B.orderedList listElements+  let headerText = if maxHeadlineLevels == headlineLevel+                   then header+                   else flattenHeader header+  return $ headerText <> headlineContents <> listBlock+ where+   flattenHeader :: Blocks -> Blocks+   flattenHeader blks =+     case B.toList blks of+       (Header _ _ inlns:_) -> B.para (B.fromList inlns)+       _                    -> mempty++headlineToHeaderWithContents :: Monad m => Headline -> OrgParser m Blocks+headlineToHeaderWithContents hdln@Headline {..} = do+  header         <- headlineToHeader hdln+  childrenBlocks <- mconcat <$> mapM headlineToBlocks headlineChildren+  return $ header <> headlineContents <> childrenBlocks++headlineToHeader :: Monad m => Headline -> OrgParser m Blocks+headlineToHeader Headline {..} = do+  exportTodoKeyword <- getExportSetting exportWithTodoKeywords+  exportTags        <- getExportSetting exportWithTags+  let todoText    = if exportTodoKeyword+                    then case headlineTodoMarker of+                      Just kw -> todoKeywordToInlines kw <> B.space+                      Nothing -> mempty+                    else mempty+  let text        = todoText <> headlineText <>+                    if exportTags+                    then tagsToInlines headlineTags+                    else mempty+  let propAttr    = propertiesToAttr headlineProperties+  attr           <- registerHeader propAttr headlineText+  return $ B.headerWith attr headlineLevel text++todoKeyword :: Monad m => OrgParser m TodoMarker+todoKeyword = try $ do+  taskStates <- activeTodoMarkers <$> getState+  let kwParser tdm = try (tdm <$ string (todoMarkerName tdm) <* spaceChar)+  choice (map kwParser taskStates)++todoKeywordToInlines :: TodoMarker -> Inlines+todoKeywordToInlines tdm =+  let todoText  = todoMarkerName tdm+      todoState = map toLower . show $ todoMarkerState tdm+      classes = [todoState, todoText]+  in B.spanWith (mempty, classes, mempty) (B.str todoText)++propertiesToAttr :: Properties -> Attr+propertiesToAttr properties =+  let+    toStringPair = fromKey *** fromValue+    customIdKey = toPropertyKey "custom_id"+    classKey    = toPropertyKey "class"+    unnumberedKey = toPropertyKey "unnumbered"+    specialProperties = [customIdKey, classKey, unnumberedKey]+    id'  = maybe mempty fromValue . lookup customIdKey $ properties+    cls  = maybe mempty fromValue . lookup classKey    $ properties+    kvs' = map toStringPair . filter ((`notElem` specialProperties) . fst)+           $ properties+    isUnnumbered =+      maybe False isNonNil . lookup unnumberedKey $ properties+  in+    (id', words cls ++ ["unnumbered" | isUnnumbered], kvs')++tagsToInlines :: [Tag] -> Inlines+tagsToInlines [] = mempty+tagsToInlines tags =+  (B.space <>) . mconcat . intersperse (B.str "\160") . map tagToInline $ tags+ where+  tagToInline :: Tag -> Inlines+  tagToInline t = tagSpan t . B.smallcaps . B.str $ fromTag t++-- | Wrap the given inline in a span, marking it as a tag.+tagSpan :: Tag -> Inlines -> Inlines+tagSpan t = B.spanWith ("", ["tag"], [("tag-name", fromTag t)])++++++-- | Read a :PROPERTIES: drawer and return the key/value pairs contained+-- within.+propertiesDrawer :: Monad m => OrgParser m Properties+propertiesDrawer = try $ do+  drawerType <- drawerStart+  guard $ map toUpper drawerType == "PROPERTIES"+  manyTill property (try endOfDrawer)+ where+   property :: Monad m => OrgParser m (PropertyKey, PropertyValue)+   property = try $ (,) <$> key <*> value++   key :: Monad m => OrgParser m PropertyKey+   key = fmap toPropertyKey . try $+         skipSpaces *> char ':' *> many1Till nonspaceChar (char ':')++   value :: Monad m => OrgParser m PropertyValue+   value = fmap toPropertyValue . try $+           skipSpaces *> manyTill anyChar (try $ skipSpaces *> newline)++   endOfDrawer :: Monad m => OrgParser m String+   endOfDrawer = try $+     skipSpaces *> stringAnyCase ":END:" <* skipSpaces <* newline
src/Text/Pandoc/Readers/Org/ExportSettings.hs view
@@ -1,5 +1,5 @@ {--Copyright (C) 2014-2016 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>+Copyright (C) 2014-2017 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -17,8 +17,8 @@ -}  {- |-   Module      : Text.Pandoc.Readers.Org.Options-   Copyright   : Copyright (C) 2016 Albert Krewinkel+   Module      : Text.Pandoc.Readers.Org.ExportSettings+   Copyright   : © 2016–2017 Albert Krewinkel    License     : GNU GPL, version 2 or above     Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>@@ -29,22 +29,22 @@   ( exportSettings   ) where -import           Text.Pandoc.Readers.Org.ParserState-import           Text.Pandoc.Readers.Org.Parsing+import Text.Pandoc.Readers.Org.ParserState+import Text.Pandoc.Readers.Org.Parsing -import           Control.Monad ( mzero, void )-import           Data.Char ( toLower )-import           Data.Maybe ( listToMaybe )+import Control.Monad (mzero, void)+import Data.Char (toLower)+import Data.Maybe (listToMaybe)  -- | Read and handle space separated org-mode export settings.-exportSettings :: OrgParser ()+exportSettings :: Monad m => OrgParser m () exportSettings = void $ sepBy spaces exportSetting  -- | Setter function for export settings. type ExportSettingSetter a = a -> ExportSettings -> ExportSettings  -- | Read and process a single org-mode export option.-exportSetting :: OrgParser ()+exportSetting :: Monad m => OrgParser m () exportSetting = choice   [ booleanSetting "^" (\val es -> es { exportSubSuperscripts = val })   , booleanSetting "'" (\val es -> es { exportSmartQuotes = val })@@ -52,7 +52,7 @@   , booleanSetting "-" (\val es -> es { exportSpecialStrings = val })   , ignoredSetting ":"   , ignoredSetting "<"-  , ignoredSetting "\\n"+  , booleanSetting "\\n" (\val es -> es { exportPreserveBreaks = val })   , archivedTreeSetting "arch" (\val es -> es { exportArchivedTrees = val })   , booleanSetting "author" (\val es -> es { exportWithAuthor = val })   , ignoredSetting "c"@@ -71,7 +71,7 @@   , ignoredSetting "pri"   , ignoredSetting "prop"   , ignoredSetting "stat"-  , ignoredSetting "tags"+  , booleanSetting "tags" (\val es -> es { exportWithTags = val })   , ignoredSetting "tasks"   , ignoredSetting "tex"   , ignoredSetting "timestamp"@@ -81,10 +81,11 @@   , ignoredSetting "|"   ] <?> "export setting" -genericExportSetting :: OrgParser a+genericExportSetting :: Monad m+                     => OrgParser m a                      -> String                      -> ExportSettingSetter a-                     -> OrgParser ()+                     -> OrgParser m () genericExportSetting optionParser settingIdentifier setter = try $ do   _     <- string settingIdentifier *> char ':'   value <- optionParser@@ -94,11 +95,11 @@      st { orgStateExportSettings = setter val . orgStateExportSettings $ st }  -- | A boolean option, either nil (False) or non-nil (True).-booleanSetting :: String ->  ExportSettingSetter Bool -> OrgParser ()+booleanSetting :: Monad m => String ->  ExportSettingSetter Bool -> OrgParser m () booleanSetting = genericExportSetting elispBoolean  -- | An integer-valued option.-integerSetting :: String -> ExportSettingSetter Int -> OrgParser ()+integerSetting :: Monad m => String -> ExportSettingSetter Int -> OrgParser m () integerSetting = genericExportSetting parseInt  where    parseInt = try $@@ -106,9 +107,10 @@  -- | Either the string "headline" or an elisp boolean and treated as an -- @ArchivedTreesOption@.-archivedTreeSetting :: String+archivedTreeSetting :: Monad m+                    => String                     -> ExportSettingSetter ArchivedTreesOption-                    -> OrgParser ()+                    -> OrgParser m () archivedTreeSetting =   genericExportSetting $ archivedTreesHeadlineSetting <|> archivedTreesBoolean  where@@ -125,9 +127,10 @@        else ArchivedTreesNoExport  -- | A list or a complement list (i.e. a list starting with `not`).-complementableListSetting :: String+complementableListSetting :: Monad m+                          => String                           -> ExportSettingSetter (Either [String] [String])-                          -> OrgParser ()+                          -> OrgParser m () complementableListSetting = genericExportSetting $ choice   [ Left  <$> complementStringList   , Right <$> stringList@@ -135,31 +138,31 @@   ]  where    -- Read a plain list of strings.-   stringList :: OrgParser [String]+   stringList :: Monad m => OrgParser m [String]    stringList = try $      char '('        *> sepBy elispString spaces        <* char ')'     -- Read an emacs lisp list specifying a complement set.-   complementStringList :: OrgParser [String]+   complementStringList :: Monad m => OrgParser m [String]    complementStringList = try $      string "(not "        *> sepBy elispString spaces        <* char ')' -   elispString :: OrgParser String+   elispString :: Monad m => OrgParser m String    elispString = try $      char '"'        *> manyTill alphaNum (char '"')  -- | Read but ignore the export setting.-ignoredSetting :: String -> OrgParser ()+ignoredSetting :: Monad m => String -> OrgParser m () ignoredSetting s = try (() <$ string s <* char ':' <* many1 nonspaceChar)  -- | Read an elisp boolean.  Only NIL is treated as false, non-NIL values are -- interpreted as true.-elispBoolean :: OrgParser Bool+elispBoolean :: Monad m => OrgParser m Bool elispBoolean = try $ do   value <- many1 nonspaceChar   return $ case map toLower value of
src/Text/Pandoc/Readers/Org/Inlines.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE OverloadedStrings #-} {--Copyright (C) 2014-2016 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>+Copyright (C) 2014-2017 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -18,8 +18,8 @@ -}  {- |-   Module      : Text.Pandoc.Readers.Org.Options-   Copyright   : Copyright (C) 2014-2016 Albert Krewinkel+   Module      : Text.Pandoc.Readers.Org.Inlines+   Copyright   : Copyright (C) 2014-2017 Albert Krewinkel    License     : GNU GPL, version 2 or above     Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>@@ -33,73 +33,75 @@   , linkTarget   ) where -import           Text.Pandoc.Readers.Org.BlockStarts ( endOfBlock, noteMarker )-import           Text.Pandoc.Readers.Org.ParserState-import           Text.Pandoc.Readers.Org.Parsing-import           Text.Pandoc.Readers.Org.Shared-                   ( cleanLinkString, isImageFilename, rundocBlockClass-                   , toRundocAttrib, translateLang )+import Text.Pandoc.Readers.Org.BlockStarts (endOfBlock, noteMarker)+import Text.Pandoc.Readers.Org.ParserState+import Text.Pandoc.Readers.Org.Parsing+import Text.Pandoc.Readers.Org.Shared (cleanLinkString, isImageFilename,+                                       originalLang, translateLang) +import Text.Pandoc.Builder (Inlines) import qualified Text.Pandoc.Builder as B-import           Text.Pandoc.Builder ( Inlines )-import           Text.Pandoc.Definition-import           Text.Pandoc.Options-import           Text.Pandoc.Readers.LaTeX ( inlineCommand, rawLaTeXInline )-import           Text.TeXMath ( readTeX, writePandoc, DisplayType(..) )+import Text.Pandoc.Class (PandocMonad)+import Text.Pandoc.Definition+import Text.Pandoc.Options+import Text.Pandoc.Readers.LaTeX (inlineCommand, rawLaTeXInline)+import Text.Pandoc.Shared (underlineSpan)+import Text.TeXMath (DisplayType (..), readTeX, writePandoc) import qualified Text.TeXMath.Readers.MathML.EntityMap as MathMLEntityMap -import           Prelude hiding (sequence)-import           Control.Monad ( guard, mplus, mzero, when, void )-import           Data.Char ( isAlphaNum, isSpace )-import           Data.List ( intersperse )-import           Data.Maybe ( fromMaybe )+import Control.Monad (guard, mplus, mzero, unless, void, when)+import Control.Monad.Trans (lift)+import Data.Char (isAlphaNum, isSpace)+import Data.List (intersperse) import qualified Data.Map as M-import           Data.Monoid ( (<>) )-import           Data.Traversable (sequence)+import Data.Maybe (fromMaybe)+import Data.Monoid ((<>))+import Data.Traversable (sequence)+import Prelude hiding (sequence)  -- -- Functions acting on the parser state ---recordAnchorId :: String -> OrgParser ()+recordAnchorId :: PandocMonad m => String -> OrgParser m () recordAnchorId i = updateState $ \s ->-  s{ orgStateAnchorIds = i : (orgStateAnchorIds s) }+  s{ orgStateAnchorIds = i : orgStateAnchorIds s } -pushToInlineCharStack :: Char -> OrgParser ()+pushToInlineCharStack :: PandocMonad m => Char -> OrgParser m () pushToInlineCharStack c = updateState $ \s ->   s{ orgStateEmphasisCharStack = c:orgStateEmphasisCharStack s } -popInlineCharStack :: OrgParser ()+popInlineCharStack :: PandocMonad m => OrgParser m () popInlineCharStack = updateState $ \s ->   s{ orgStateEmphasisCharStack = drop 1 . orgStateEmphasisCharStack $ s } -surroundingEmphasisChar :: OrgParser [Char]+surroundingEmphasisChar :: PandocMonad m => OrgParser m [Char] surroundingEmphasisChar =   take 1 . drop 1 . orgStateEmphasisCharStack <$> getState -startEmphasisNewlinesCounting :: Int -> OrgParser ()+startEmphasisNewlinesCounting :: PandocMonad m => Int -> OrgParser m () startEmphasisNewlinesCounting maxNewlines = updateState $ \s ->   s{ orgStateEmphasisNewlines = Just maxNewlines } -decEmphasisNewlinesCount :: OrgParser ()+decEmphasisNewlinesCount :: PandocMonad m => OrgParser m () decEmphasisNewlinesCount = updateState $ \s ->   s{ orgStateEmphasisNewlines = (\n -> n - 1) <$> orgStateEmphasisNewlines s } -newlinesCountWithinLimits :: OrgParser Bool+newlinesCountWithinLimits :: PandocMonad m => OrgParser m Bool newlinesCountWithinLimits = do   st <- getState   return $ ((< 0) <$> orgStateEmphasisNewlines st) /= Just True -resetEmphasisNewlines :: OrgParser ()+resetEmphasisNewlines :: PandocMonad m => OrgParser m () resetEmphasisNewlines = updateState $ \s ->   s{ orgStateEmphasisNewlines = Nothing } -addToNotesTable :: OrgNoteRecord -> OrgParser ()+addToNotesTable :: PandocMonad m => OrgNoteRecord -> OrgParser m () addToNotesTable note = do   oldnotes <- orgStateNotes' <$> getState   updateState $ \s -> s{ orgStateNotes' = note:oldnotes }  -- | Parse a single Org-mode inline element-inline :: OrgParser (F Inlines)+inline :: PandocMonad m => OrgParser m (F Inlines) inline =   choice [ whitespace          , linebreak@@ -119,13 +121,14 @@          , superscript          , inlineLaTeX          , exportSnippet+         , macro          , smart          , symbol          ] <* (guard =<< newlinesCountWithinLimits)   <?> "inline"  -- | Read the rest of the input as inlines.-inlines :: OrgParser (F Inlines)+inlines :: PandocMonad m => OrgParser m (F Inlines) inlines = trimInlinesF . mconcat <$> many1 inline  -- treat these as potentially non-text when parsing inline:@@ -133,30 +136,31 @@ specialChars = "\"$'()*+-,./:;<=>@[\\]^_{|}~"  -whitespace :: OrgParser (F Inlines)+whitespace :: PandocMonad m => OrgParser m (F Inlines) whitespace = pure B.space <$ skipMany1 spaceChar                           <* updateLastPreCharPos                           <* updateLastForbiddenCharPos              <?> "whitespace" -linebreak :: OrgParser (F Inlines)+linebreak :: PandocMonad m => OrgParser m (F Inlines) linebreak = try $ pure B.linebreak <$ string "\\\\" <* skipSpaces <* newline -str :: OrgParser (F Inlines)+str :: PandocMonad m => OrgParser m (F Inlines) str = return . B.str <$> many1 (noneOf $ specialChars ++ "\n\r ")       <* updateLastStrPos  -- | An endline character that can be treated as a space, not a structural -- break.  This should reflect the values of the Emacs variable -- @org-element-pagaraph-separate@.-endline :: OrgParser (F Inlines)+endline :: PandocMonad m => OrgParser m (F Inlines) endline = try $ do   newline   notFollowedBy' endOfBlock   decEmphasisNewlinesCount   guard =<< newlinesCountWithinLimits   updateLastPreCharPos-  return . return $ B.softbreak+  useHardBreaks <- exportPreserveBreaks . orgStateExportSettings <$> getState+  returnF (if useHardBreaks then B.linebreak else B.softbreak)   --@@ -174,7 +178,7 @@ -- contributors.  All this should be consolidated once an official Org-mode -- citation syntax has emerged. -cite :: OrgParser (F Inlines)+cite :: PandocMonad m => OrgParser m (F Inlines) cite = try $ berkeleyCite <|> do   guardEnabled Ext_citations   (cs, raw) <- withRaw $ choice@@ -182,43 +186,44 @@                , orgRefCite                , berkeleyTextualCite                ]-  return $ (flip B.cite (B.text raw)) <$> cs+  return $ flip B.cite (B.text raw) <$> cs  -- | A citation in Pandoc Org-mode style (@[prefix \@citekey suffix]@).-pandocOrgCite :: OrgParser (F [Citation])+pandocOrgCite :: PandocMonad m => OrgParser m (F [Citation]) pandocOrgCite = try $   char '[' *> skipSpaces *> citeList <* skipSpaces <* char ']' -orgRefCite :: OrgParser (F [Citation])+orgRefCite :: PandocMonad m => OrgParser m (F [Citation]) orgRefCite = try $ choice   [ normalOrgRefCite   , fmap (:[]) <$> linkLikeOrgRefCite   ] -normalOrgRefCite :: OrgParser (F [Citation])+normalOrgRefCite :: PandocMonad m => OrgParser m (F [Citation]) normalOrgRefCite = try $ do   mode <- orgRefCiteMode-  -- org-ref style citation key, parsed into a citation of the given mode-  let orgRefCiteItem :: OrgParser (F Citation)-      orgRefCiteItem = try $ do-        key <- orgRefCiteKey-        returnF $ Citation-          { citationId      = key-          , citationPrefix  = mempty-          , citationSuffix  = mempty-          , citationMode    = mode-          , citationNoteNum = 0-          , citationHash    = 0-          }-  firstCitation <- orgRefCiteItem-  moreCitations <- many (try $ char ',' *> orgRefCiteItem)+  firstCitation <- orgRefCiteList mode+  moreCitations <- many (try $ char ',' *> orgRefCiteList mode)   return . sequence $ firstCitation : moreCitations-    where+ where+  -- | A list of org-ref style citation keys, parsed as citation of the given+  -- citation mode.+  orgRefCiteList :: PandocMonad m => CitationMode -> OrgParser m (F Citation)+  orgRefCiteList citeMode = try $ do+    key <- orgRefCiteKey+    returnF Citation+     { citationId      = key+     , citationPrefix  = mempty+     , citationSuffix  = mempty+     , citationMode    = citeMode+     , citationNoteNum = 0+     , citationHash    = 0+     }  -- | Read an Berkeley-style Org-mode citation.  Berkeley citation style was -- develop and adjusted to Org-mode style by John MacFarlane and Richard -- Lawrence, respectively, both philosophers at UC Berkeley.-berkeleyCite :: OrgParser (F Inlines)+berkeleyCite :: PandocMonad m => OrgParser m (F Inlines) berkeleyCite = try $ do   bcl <- berkeleyCitationList   return $ do@@ -229,11 +234,11 @@     return $       if parens       then toCite-           . maybe id (\p -> alterFirst (prependPrefix p)) prefix-           . maybe id (\s -> alterLast  (appendSuffix  s)) suffix+           . maybe id (alterFirst . prependPrefix) prefix+           . maybe id (alterLast . appendSuffix) suffix            $ citationList       else maybe mempty (<> " ") prefix-             <> (toListOfCites $ map toInTextMode citationList)+             <> toListOfCites (map toInTextMode citationList)              <> maybe mempty (", " <>) suffix  where    toCite :: [Citation] -> Inlines@@ -247,7 +252,7 @@     alterFirst, alterLast :: (a -> a) -> [a] -> [a]    alterFirst _ []     = []-   alterFirst f (c:cs) = (f c):cs+   alterFirst f (c:cs) = f c : cs    alterLast  f = reverse . alterFirst f . reverse     prependPrefix, appendSuffix :: Inlines -> Citation -> Citation@@ -255,12 +260,12 @@    appendSuffix  suf c = c { citationSuffix = citationSuffix c <> B.toList suf }  data BerkeleyCitationList = BerkeleyCitationList-  { berkeleyCiteParens :: Bool+  { berkeleyCiteParens       :: Bool   , berkeleyCiteCommonPrefix :: Maybe Inlines   , berkeleyCiteCommonSuffix :: Maybe Inlines-  , berkeleyCiteCitations :: [Citation]+  , berkeleyCiteCitations    :: [Citation]   }-berkeleyCitationList :: OrgParser (F BerkeleyCitationList)+berkeleyCitationList :: PandocMonad m => OrgParser m (F BerkeleyCitationList) berkeleyCitationList = try $ do   char '['   parens <- choice [ False <$ berkeleyBareTag, True <$ berkeleyParensTag ]@@ -268,29 +273,29 @@   skipSpaces   commonPrefix <- optionMaybe (try $ citationListPart <* char ';')   citations    <- citeList-  commonSuffix <- optionMaybe (try $ citationListPart)+  commonSuffix <- optionMaybe (try citationListPart)   char ']'   return (BerkeleyCitationList parens     <$> sequence commonPrefix     <*> sequence commonSuffix     <*> citations)  where-   citationListPart :: OrgParser (F Inlines)+   citationListPart :: PandocMonad m => OrgParser m (F Inlines)    citationListPart = fmap (trimInlinesF . mconcat) . try . many1 $ do      notFollowedBy' citeKey      notFollowedBy (oneOf ";]")      inline -berkeleyBareTag :: OrgParser ()+berkeleyBareTag :: PandocMonad m => OrgParser m () berkeleyBareTag = try $ void berkeleyBareTag' -berkeleyParensTag :: OrgParser ()+berkeleyParensTag :: PandocMonad m => OrgParser m () berkeleyParensTag = try . void $ enclosedByPair '(' ')' berkeleyBareTag' -berkeleyBareTag' :: OrgParser ()+berkeleyBareTag' :: PandocMonad m => OrgParser m () berkeleyBareTag' = try $ void (string "cite") -berkeleyTextualCite :: OrgParser (F [Citation])+berkeleyTextualCite :: PandocMonad m => OrgParser m (F [Citation]) berkeleyTextualCite = try $ do   (suppressAuthor, key) <- citeKey   returnF . return $ Citation@@ -305,14 +310,14 @@ -- The following is what a Berkeley-style bracketed textual citation parser -- would look like.  However, as these citations are a subset of Pandoc's Org -- citation style, this isn't used.--- berkeleyBracketedTextualCite :: OrgParser (F [Citation])+-- berkeleyBracketedTextualCite :: PandocMonad m => OrgParser m (F [Citation]) -- berkeleyBracketedTextualCite = try . (fmap head) $ --   enclosedByPair '[' ']' berkeleyTextualCite  -- | Read a link-like org-ref style citation.  The citation includes pre and -- post text.  However, multiple citations are not possible due to limitations -- in the syntax.-linkLikeOrgRefCite :: OrgParser (F Citation)+linkLikeOrgRefCite :: PandocMonad m => OrgParser m (F Citation) linkLikeOrgRefCite = try $ do   _    <- string "[["   mode <- orgRefCiteMode@@ -335,13 +340,20 @@  -- | Read a citation key.  The characters allowed in citation keys are taken -- from the `org-ref-cite-re` variable in `org-ref.el`.-orgRefCiteKey :: OrgParser String-orgRefCiteKey = try . many1 . satisfy $ \c ->-                  isAlphaNum c || c `elem` ("-_:\\./"::String)+orgRefCiteKey :: PandocMonad m => OrgParser m String+orgRefCiteKey =+  let citeKeySpecialChars = "-_:\\./," :: String+      isCiteKeySpecialChar c = c `elem` citeKeySpecialChars+      isCiteKeyChar c = isAlphaNum c || isCiteKeySpecialChar c+      endOfCitation = try $ do+        many $ satisfy isCiteKeySpecialChar+        satisfy $ not . isCiteKeyChar+  in try $ satisfy isCiteKeyChar `many1Till` lookAhead endOfCitation + -- | Supported citation types.  Only a small subset of org-ref types is -- supported for now.  TODO: rewrite this, use LaTeX reader as template.-orgRefCiteMode :: OrgParser CitationMode+orgRefCiteMode :: PandocMonad m => OrgParser m CitationMode orgRefCiteMode =   choice $ map (\(s, mode) -> mode <$ try (string s <* char ':'))     [ ("cite", AuthorInText)@@ -352,10 +364,10 @@     , ("citeyear", SuppressAuthor)     ] -citeList :: OrgParser (F [Citation])+citeList :: PandocMonad m => OrgParser m (F [Citation]) citeList = sequence <$> sepEndBy1 citation (try $ char ';' *> skipSpaces) -citation :: OrgParser (F Citation)+citation :: PandocMonad m => OrgParser m (F Citation) citation = try $ do   pref <- prefix   (suppress_author, key) <- citeKey@@ -363,15 +375,16 @@   return $ do     x <- pref     y <- suff-    return $ Citation{ citationId      = key-                     , citationPrefix  = B.toList x-                     , citationSuffix  = B.toList y-                     , citationMode    = if suppress_author-                                            then SuppressAuthor-                                            else NormalCitation-                     , citationNoteNum = 0-                     , citationHash    = 0-                     }+    return Citation+      { citationId      = key+      , citationPrefix  = B.toList x+      , citationSuffix  = B.toList y+      , citationMode    = if suppress_author+                          then SuppressAuthor+                          else NormalCitation+      , citationNoteNum = 0+      , citationHash    = 0+      }  where    prefix = trimInlinesF . mconcat <$>             manyTill inline (char ']' <|> (']' <$ lookAhead citeKey))@@ -384,39 +397,39 @@               then (B.space <>) <$> rest               else rest -footnote :: OrgParser (F Inlines)+footnote :: PandocMonad m => OrgParser m (F Inlines) footnote = try $ inlineNote <|> referencedNote -inlineNote :: OrgParser (F Inlines)+inlineNote :: PandocMonad m => OrgParser m (F Inlines) inlineNote = try $ do   string "[fn:"   ref <- many alphaNum   char ':'   note <- fmap B.para . trimInlinesF . mconcat <$> many1Till inline (char ']')-  when (not $ null ref) $+  unless (null ref) $        addToNotesTable ("fn:" ++ ref, note)   return $ B.note <$> note -referencedNote :: OrgParser (F Inlines)+referencedNote :: PandocMonad m => OrgParser m (F Inlines) referencedNote = try $ do   ref <- noteMarker   return $ do     notes <- asksF orgStateNotes'     case lookup ref notes of-      Nothing   -> return $ B.str $ "[" ++ ref ++ "]"+      Nothing   -> return . B.str $ "[" ++ ref ++ "]"       Just contents  -> do         st <- askF         let contents' = runF contents st{ orgStateNotes' = [] }         return $ B.note contents' -linkOrImage :: OrgParser (F Inlines)+linkOrImage :: PandocMonad m => OrgParser m (F Inlines) linkOrImage = explicitOrImageLink               <|> selflinkOrImage               <|> angleLink               <|> plainLink               <?> "link or image" -explicitOrImageLink :: OrgParser (F Inlines)+explicitOrImageLink :: PandocMonad m => OrgParser m (F Inlines) explicitOrImageLink = try $ do   char '['   srcF   <- applyCustomLinkFormat =<< possiblyEmptyLinkTarget@@ -427,34 +440,34 @@     src <- srcF     case cleanLinkString title of       Just imgSrc | isImageFilename imgSrc ->-        pure $ B.link src "" $ B.image imgSrc mempty mempty+        pure . B.link src "" $ B.image imgSrc mempty mempty       _ ->         linkToInlinesF src =<< title' -selflinkOrImage :: OrgParser (F Inlines)+selflinkOrImage :: PandocMonad m => OrgParser m (F Inlines) selflinkOrImage = try $ do   src <- char '[' *> linkTarget <* char ']'   return $ linkToInlinesF src (B.str src) -plainLink :: OrgParser (F Inlines)+plainLink :: PandocMonad m => OrgParser m (F Inlines) plainLink = try $ do   (orig, src) <- uri   returnF $ B.link src "" (B.str orig) -angleLink :: OrgParser (F Inlines)+angleLink :: PandocMonad m => OrgParser m (F Inlines) angleLink = try $ do   char '<'   link <- plainLink   char '>'   return link -linkTarget :: OrgParser String+linkTarget :: PandocMonad m => OrgParser m String linkTarget = enclosedByPair '[' ']' (noneOf "\n\r[]") -possiblyEmptyLinkTarget :: OrgParser String+possiblyEmptyLinkTarget :: PandocMonad m => OrgParser m String possiblyEmptyLinkTarget = try linkTarget <|> ("" <$ string "[]") -applyCustomLinkFormat :: String -> OrgParser (F String)+applyCustomLinkFormat :: String -> OrgParser m (F String) applyCustomLinkFormat link = do   let (linkType, rest) = break (== ':') link   return $ do@@ -487,7 +500,7 @@ -- @anchor-id@ contains spaces, we are more restrictive in what is accepted as -- an anchor. -anchor :: OrgParser (F Inlines)+anchor :: PandocMonad m => OrgParser m (F Inlines) anchor =  try $ do   anchorId <- parseAnchor   recordAnchorId anchorId@@ -509,23 +522,23 @@            | otherwise       = '-'  -- | Parses an inline code block and marks it as an babel block.-inlineCodeBlock :: OrgParser (F Inlines)+inlineCodeBlock :: PandocMonad m => OrgParser m (F Inlines) inlineCodeBlock = try $ do   string "src_"   lang <- many1 orgArgWordChar   opts <- option [] $ enclosedByPair '[' ']' inlineBlockOption   inlineCode <- enclosedByPair '{' '}' (noneOf "\n\r")-  let attrClasses = [translateLang lang, rundocBlockClass]-  let attrKeyVal  = map toRundocAttrib (("language", lang) : opts)+  let attrClasses = [translateLang lang]+  let attrKeyVal  = originalLang lang <> opts   returnF $ B.codeWith ("", attrClasses, attrKeyVal) inlineCode  where-   inlineBlockOption :: OrgParser (String, String)+   inlineBlockOption :: PandocMonad m => OrgParser m (String, String)    inlineBlockOption = try $ do      argKey <- orgArgKey      paramValue <- option "yes" orgInlineParamValue      return (argKey, paramValue) -   orgInlineParamValue :: OrgParser String+   orgInlineParamValue :: PandocMonad m => OrgParser m String    orgInlineParamValue = try $      skipSpaces        *> notFollowedBy (char ':')@@ -533,7 +546,7 @@        <* skipSpaces  -emphasizedText :: OrgParser (F Inlines)+emphasizedText :: PandocMonad m => OrgParser m (F Inlines) emphasizedText = do   state <- getState   guard . exportEmphasizedText . orgStateExportSettings $ state@@ -544,60 +557,62 @@     , underline     ] -enclosedByPair :: Char          -- ^ opening char+enclosedByPair :: PandocMonad m+               => Char          -- ^ opening char                -> Char          -- ^ closing char-               -> OrgParser a   -- ^ parser-               -> OrgParser [a]+               -> OrgParser m a   -- ^ parser+               -> OrgParser m [a] enclosedByPair s e p = char s *> many1Till p (char e) -emph      :: OrgParser (F Inlines)+emph      :: PandocMonad m => OrgParser m (F Inlines) emph      = fmap B.emph         <$> emphasisBetween '/' -strong    :: OrgParser (F Inlines)+strong    :: PandocMonad m => OrgParser m (F Inlines) strong    = fmap B.strong       <$> emphasisBetween '*' -strikeout :: OrgParser (F Inlines)+strikeout :: PandocMonad m => OrgParser m (F Inlines) strikeout = fmap B.strikeout    <$> emphasisBetween '+' --- There is no underline, so we use strong instead.-underline :: OrgParser (F Inlines)-underline = fmap B.strong       <$> emphasisBetween '_'+underline :: PandocMonad m => OrgParser m (F Inlines)+underline = fmap underlineSpan  <$> emphasisBetween '_' -verbatim  :: OrgParser (F Inlines)+verbatim  :: PandocMonad m => OrgParser m (F Inlines) verbatim  = return . B.code     <$> verbatimBetween '=' -code      :: OrgParser (F Inlines)+code      :: PandocMonad m => OrgParser m (F Inlines) code      = return . B.code     <$> verbatimBetween '~' -subscript   :: OrgParser (F Inlines)+subscript   :: PandocMonad m => OrgParser m (F Inlines) subscript   = fmap B.subscript   <$> try (char '_' *> subOrSuperExpr) -superscript :: OrgParser (F Inlines)+superscript :: PandocMonad m => OrgParser m (F Inlines) superscript = fmap B.superscript <$> try (char '^' *> subOrSuperExpr) -math      :: OrgParser (F Inlines)+math      :: PandocMonad m => OrgParser m (F Inlines) math      = return . B.math      <$> choice [ math1CharBetween '$'                                             , mathStringBetween '$'                                             , rawMathBetween "\\(" "\\)"                                             ] -displayMath :: OrgParser (F Inlines)+displayMath :: PandocMonad m => OrgParser m (F Inlines) displayMath = return . B.displayMath <$> choice [ rawMathBetween "\\[" "\\]"                                                 , rawMathBetween "$$"  "$$"                                                 ] -updatePositions :: Char-                -> OrgParser Char+updatePositions :: PandocMonad m+                => Char+                -> OrgParser m Char updatePositions c = do   when (c `elem` emphasisPreChars) updateLastPreCharPos   when (c `elem` emphasisForbiddenBorderChars) updateLastForbiddenCharPos   return c -symbol :: OrgParser (F Inlines)+symbol :: PandocMonad m => OrgParser m (F Inlines) symbol = return . B.str . (: "") <$> (oneOf specialChars >>= updatePositions) -emphasisBetween :: Char-                -> OrgParser (F Inlines)+emphasisBetween :: PandocMonad m+                => Char+                -> OrgParser m (F Inlines) emphasisBetween c = try $ do   startEmphasisNewlinesCounting emphasisAllowedNewlines   res <- enclosedInlines (emphasisStart c) (emphasisEnd c)@@ -606,8 +621,9 @@        resetEmphasisNewlines   return res -verbatimBetween :: Char-                -> OrgParser String+verbatimBetween :: PandocMonad m+                => Char+                -> OrgParser m String verbatimBetween c = try $   emphasisStart c *>   many1TillNOrLessNewlines 1 verbatimChar (emphasisEnd c)@@ -615,8 +631,9 @@    verbatimChar = noneOf "\n\r" >>= updatePositions  -- | Parses a raw string delimited by @c@ using Org's math rules-mathStringBetween :: Char-                  -> OrgParser String+mathStringBetween :: PandocMonad m+                  => Char+                  -> OrgParser m String mathStringBetween c = try $ do   mathStart c   body <- many1TillNOrLessNewlines mathAllowedNewlines@@ -626,8 +643,9 @@   return $ body ++ [final]  -- | Parse a single character between @c@ using math rules-math1CharBetween :: Char-                -> OrgParser String+math1CharBetween :: PandocMonad m+                 => Char+                -> OrgParser m String math1CharBetween c = try $ do   char c   res <- noneOf $ c:mathForbiddenBorderChars@@ -635,13 +653,14 @@   eof <|> () <$ lookAhead (oneOf mathPostChars)   return [res] -rawMathBetween :: String+rawMathBetween :: PandocMonad m+               => String                -> String-               -> OrgParser String+               -> OrgParser m String rawMathBetween s e = try $ string s *> manyTill anyChar (try $ string e)  -- | Parses the start (opening character) of emphasis-emphasisStart :: Char -> OrgParser Char+emphasisStart :: PandocMonad m => Char -> OrgParser m Char emphasisStart c = try $ do   guard =<< afterEmphasisPreChar   guard =<< notAfterString@@ -654,7 +673,7 @@   return c  -- | Parses the closing character of emphasis-emphasisEnd :: Char -> OrgParser Char+emphasisEnd :: PandocMonad m => Char -> OrgParser m Char emphasisEnd c = try $ do   guard =<< notAfterForbiddenBorderChar   char c@@ -665,11 +684,11 @@  where acceptablePostChars =            surroundingEmphasisChar >>= \x -> oneOf (x ++ emphasisPostChars) -mathStart :: Char -> OrgParser Char+mathStart :: PandocMonad m => Char -> OrgParser m Char mathStart c = try $   char c <* notFollowedBy' (oneOf (c:mathForbiddenBorderChars)) -mathEnd :: Char -> OrgParser Char+mathEnd :: PandocMonad m => Char -> OrgParser m Char mathEnd c = try $ do   res <- noneOf (c:mathForbiddenBorderChars)   char c@@ -677,15 +696,15 @@   return res  -enclosedInlines :: OrgParser a-                -> OrgParser b-                -> OrgParser (F Inlines)+enclosedInlines :: (PandocMonad m, Show b) => OrgParser m a+                -> OrgParser m b+                -> OrgParser m (F Inlines) enclosedInlines start end = try $   trimInlinesF . mconcat <$> enclosed start end inline -enclosedRaw :: OrgParser a-            -> OrgParser b-            -> OrgParser String+enclosedRaw :: (PandocMonad m, Show b) => OrgParser m a+            -> OrgParser m b+            -> OrgParser m String enclosedRaw start end = try $   start *> (onSingleLine <|> spanningTwoLines)  where onSingleLine = try $ many1Till (noneOf "\n\r") end@@ -694,10 +713,10 @@  -- | Like many1Till, but parses at most @n+1@ lines.  @p@ must not consume --   newlines.-many1TillNOrLessNewlines :: Int-                         -> OrgParser Char-                         -> OrgParser a-                         -> OrgParser String+many1TillNOrLessNewlines :: PandocMonad m => Int+                         -> OrgParser m Char+                         -> OrgParser m a+                         -> OrgParser m String many1TillNOrLessNewlines n p end = try $   nMoreLines (Just n) mempty >>= oneOrMore  where@@ -717,15 +736,15 @@  -- | Chars allowed to occur before emphasis (spaces and newlines are ok, too) emphasisPreChars :: [Char]-emphasisPreChars = "\t \"'({"+emphasisPreChars = "-\t ('\"{"  -- | Chars allowed at after emphasis emphasisPostChars :: [Char]-emphasisPostChars = "\t\n !\"'),-.:;?\\}"+emphasisPostChars = "-\t\n .,:!?;'\")}["  -- | Chars not allowed at the (inner) border of emphasis emphasisForbiddenBorderChars :: [Char]-emphasisForbiddenBorderChars = "\t\n\r \"',"+emphasisForbiddenBorderChars = "\t\n\r "  -- | The maximum number of newlines within emphasisAllowedNewlines :: Int@@ -746,29 +765,29 @@ mathAllowedNewlines = 2  -- | Whether we are right behind a char allowed before emphasis-afterEmphasisPreChar :: OrgParser Bool+afterEmphasisPreChar :: PandocMonad m => OrgParser m Bool afterEmphasisPreChar = do   pos <- getPosition   lastPrePos <- orgStateLastPreCharPos <$> getState   return . fromMaybe True $ (== pos) <$> lastPrePos  -- | Whether the parser is right after a forbidden border char-notAfterForbiddenBorderChar :: OrgParser Bool+notAfterForbiddenBorderChar :: PandocMonad m => OrgParser m Bool notAfterForbiddenBorderChar = do   pos <- getPosition   lastFBCPos <- orgStateLastForbiddenCharPos <$> getState   return $ lastFBCPos /= Just pos  -- | Read a sub- or superscript expression-subOrSuperExpr :: OrgParser (F Inlines)+subOrSuperExpr :: PandocMonad m => OrgParser m (F Inlines) subOrSuperExpr = try $-  choice [ id                   <$> charsInBalanced '{' '}' (noneOf "\n\r")+  choice [ charsInBalanced '{' '}' (noneOf "\n\r")          , enclosing ('(', ')') <$> charsInBalanced '(' ')' (noneOf "\n\r")          , simpleSubOrSuperString          ] >>= parseFromString (mconcat <$> many inline)  where enclosing (left, right) s = left : s ++ [right] -simpleSubOrSuperString :: OrgParser String+simpleSubOrSuperString :: PandocMonad m => OrgParser m String simpleSubOrSuperString = try $ do   state <- getState   guard . exportSubSuperscripts . orgStateExportSettings $ state@@ -777,17 +796,18 @@                    <*> many1 alphaNum          ] -inlineLaTeX :: OrgParser (F Inlines)+inlineLaTeX :: PandocMonad m => OrgParser m (F Inlines) inlineLaTeX = try $ do   cmd <- inlineLaTeXCommand+  ils <- (lift . lift) $ parseAsInlineLaTeX cmd   maybe mzero returnF $-     parseAsMath cmd `mplus` parseAsMathMLSym cmd `mplus` parseAsInlineLaTeX cmd+     parseAsMath cmd `mplus` parseAsMathMLSym cmd `mplus` ils  where    parseAsMath :: String -> Maybe Inlines    parseAsMath cs = B.fromList <$> texMathToPandoc cs -   parseAsInlineLaTeX :: String -> Maybe Inlines-   parseAsInlineLaTeX cs = maybeRight $ runParser inlineCommand state "" cs+   parseAsInlineLaTeX :: PandocMonad m => String -> m (Maybe Inlines)+   parseAsInlineLaTeX cs = maybeRight <$> runParserT inlineCommand state "" cs     parseAsMathMLSym :: String -> Maybe Inlines    parseAsMathMLSym cs = B.str <$> MathMLEntityMap.getUnicode (clean cs)@@ -795,19 +815,22 @@     where clean = dropWhileEnd (`elem` ("{}" :: String)) . drop 1     state :: ParserState-   state = def{ stateOptions = def{ readerParseRaw = True }}+   state = def{ stateOptions = def{ readerExtensions =+                    enableExtension Ext_raw_tex (readerExtensions def) } }     texMathToPandoc :: String -> Maybe [Inline]-   texMathToPandoc cs = (maybeRight $ readTeX cs) >>= writePandoc DisplayInline+   texMathToPandoc cs = maybeRight (readTeX cs) >>= writePandoc DisplayInline  maybeRight :: Either a b -> Maybe b maybeRight = either (const Nothing) Just -inlineLaTeXCommand :: OrgParser String+inlineLaTeXCommand :: PandocMonad m => OrgParser m String inlineLaTeXCommand = try $ do   rest <- getInput-  case runParser rawLaTeXInline def "source" rest of-    Right (RawInline _ cs) -> do+  st <- getState+  parsed <- (lift . lift) $ runParserT rawLaTeXInline st "source" rest+  case parsed of+    Right cs -> do       -- drop any trailing whitespace, those are not be part of the command as       -- far as org mode is concerned.       let cmdNoSpc = dropWhileEnd isSpace cs@@ -820,33 +843,56 @@ dropWhileEnd :: (a -> Bool) -> [a] -> [a] dropWhileEnd p = foldr (\x xs -> if p x && null xs then [] else x : xs) [] -exportSnippet :: OrgParser (F Inlines)+exportSnippet :: PandocMonad m => OrgParser m (F Inlines) exportSnippet = try $ do   string "@@"   format <- many1Till (alphaNum <|> char '-') (char ':')   snippet <- manyTill anyChar (try $ string "@@")   returnF $ B.rawInline format snippet -smart :: OrgParser (F Inlines)-smart = do-  getOption readerSmart >>= guard-  doubleQuoted <|> singleQuoted <|>-    choice (map (return <$>) [orgApostrophe, orgDash, orgEllipses])+macro :: PandocMonad m => OrgParser m (F Inlines)+macro = try $ do+  recursionDepth <- orgStateMacroDepth <$> getState+  guard $ recursionDepth < 15+  string "{{{"+  name <- many alphaNum+  args <- ([] <$ string "}}}")+          <|> char '(' *> argument `sepBy` char ',' <* eoa+  expander <- lookupMacro name <$> getState+  case expander of+    Nothing -> mzero+    Just fn -> do+      updateState $ \s -> s { orgStateMacroDepth = recursionDepth + 1 }+      res <- parseFromString (mconcat <$> many inline) $ fn args+      updateState $ \s -> s { orgStateMacroDepth = recursionDepth }+      return res+ where+  argument = many $ notFollowedBy eoa *> noneOf ","+  eoa = string ")}}}"++smart :: PandocMonad m => OrgParser m (F Inlines)+smart = choice [doubleQuoted, singleQuoted, orgApostrophe, orgDash, orgEllipses]   where     orgDash = do-      guard =<< getExportSetting exportSpecialStrings-      dash <* updatePositions '-'+      guardOrSmartEnabled =<< getExportSetting exportSpecialStrings+      pure <$> dash <* updatePositions '-'     orgEllipses = do-      guard =<< getExportSetting exportSpecialStrings-      ellipses <* updatePositions '.'-    orgApostrophe =-          (char '\'' <|> char '\8217') <* updateLastPreCharPos-                                       <* updateLastForbiddenCharPos-                                       *> return (B.str "\x2019")+      guardOrSmartEnabled =<< getExportSetting exportSpecialStrings+      pure <$> ellipses <* updatePositions '.'+    orgApostrophe = do+      guardEnabled Ext_smart+      (char '\'' <|> char '\8217') <* updateLastPreCharPos+                                   <* updateLastForbiddenCharPos+      returnF (B.str "\x2019") -singleQuoted :: OrgParser (F Inlines)+guardOrSmartEnabled :: PandocMonad m => Bool -> OrgParser m ()+guardOrSmartEnabled b = do+  smartExtension <- extensionEnabled Ext_smart <$> getOption readerExtensions+  guard (b || smartExtension)++singleQuoted :: PandocMonad m => OrgParser m (F Inlines) singleQuoted = try $ do-  guard =<< getExportSetting exportSmartQuotes+  guardOrSmartEnabled =<< getExportSetting exportSmartQuotes   singleQuoteStart   updatePositions '\''   withQuoteContext InSingleQuote $@@ -856,12 +902,15 @@ -- doubleQuoted will handle regular double-quoted sections, as well -- as dialogues with an open double-quote without a close double-quote -- in the same paragraph.-doubleQuoted :: OrgParser (F Inlines)+doubleQuoted :: PandocMonad m => OrgParser m (F Inlines) doubleQuoted = try $ do-  guard =<< getExportSetting exportSmartQuotes+  guardOrSmartEnabled =<< getExportSetting exportSmartQuotes   doubleQuoteStart   updatePositions '"'   contents <- mconcat <$> many (try $ notFollowedBy doubleQuoteEnd >> inline)-  (withQuoteContext InDoubleQuote $ (doubleQuoteEnd <* updateLastForbiddenCharPos) >> return-       (fmap B.doubleQuoted . trimInlinesF $ contents))-   <|> (return $ return (B.str "\8220") <> contents)+  let doubleQuotedContent = withQuoteContext InDoubleQuote $ do+        doubleQuoteEnd+        updateLastForbiddenCharPos+        return . fmap B.doubleQuoted . trimInlinesF $ contents+  let leftQuoteAndContent = return $ pure (B.str "\8220") <> contents+  doubleQuotedContent <|> leftQuoteAndContent
src/Text/Pandoc/Readers/Org/Meta.hs view
@@ -1,5 +1,5 @@ {-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TupleSections    #-} {- Copyright (C) 2014-2017 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de> @@ -33,25 +33,25 @@   , metaLine   ) where -import           Text.Pandoc.Readers.Org.BlockStarts-import           Text.Pandoc.Readers.Org.ExportSettings ( exportSettings )-import           Text.Pandoc.Readers.Org.Inlines-import           Text.Pandoc.Readers.Org.ParserState-import           Text.Pandoc.Readers.Org.Parsing+import Text.Pandoc.Readers.Org.BlockStarts+import Text.Pandoc.Readers.Org.ExportSettings (exportSettings)+import Text.Pandoc.Readers.Org.Inlines+import Text.Pandoc.Readers.Org.ParserState+import Text.Pandoc.Readers.Org.Parsing +import Text.Pandoc.Builder (Blocks, Inlines) import qualified Text.Pandoc.Builder as B-import           Text.Pandoc.Builder ( Blocks, Inlines )-import           Text.Pandoc.Definition+import Text.Pandoc.Class (PandocMonad)+import Text.Pandoc.Definition -import           Control.Monad ( mzero, void )-import           Data.Char ( toLower )-import           Data.List ( intersperse )+import Control.Monad (mzero, void, when)+import Data.Char (toLower)+import Data.List (intersperse) import qualified Data.Map as M-import           Data.Monoid ( (<>) )-import           Network.HTTP ( urlEncode )+import Network.HTTP (urlEncode)  -- | Returns the current meta, respecting export options.-metaExport :: OrgParser (F Meta)+metaExport :: Monad m => OrgParser m (F Meta) metaExport = do   st <- getState   let settings = orgStateExportSettings st@@ -68,29 +68,32 @@ -- | Parse and handle a single line containing meta information -- The order, in which blocks are tried, makes sure that we're not looking at -- the beginning of a block, so we don't need to check for it-metaLine :: OrgParser Blocks+metaLine :: PandocMonad m => OrgParser m Blocks metaLine = mempty <$ metaLineStart <* (optionLine <|> declarationLine) -declarationLine :: OrgParser ()+declarationLine :: PandocMonad m => OrgParser m () declarationLine = try $ do   key   <- map toLower <$> metaKey   (key', value) <- metaValue key-  updateState $ \st ->-    let meta' = B.setMeta key' <$> value <*> pure nullMeta-    in st { orgStateMeta = meta' <> orgStateMeta st }+  let addMetaValue st =+        st { orgStateMeta = B.setMeta key' <$> value <*> orgStateMeta st }+  when (key' /= "results") $ updateState addMetaValue -metaKey :: OrgParser String+metaKey :: Monad m => OrgParser m String metaKey = map toLower <$> many1 (noneOf ": \n\r")                       <*  char ':'                       <*  skipSpaces -metaValue :: String -> OrgParser (String, (F MetaValue))+metaValue :: PandocMonad m => String -> OrgParser m (String, F MetaValue) metaValue key =   let inclKey = "header-includes"   in case key of     "author"          -> (key,) <$> metaInlinesCommaSeparated+    "keywords"        -> (key,) <$> metaInlinesCommaSeparated     "title"           -> (key,) <$> metaInlines+    "subtitle"        -> (key,) <$> metaInlines     "date"            -> (key,) <$> metaInlines+    "nocite"          -> (key,) <$> accumulatingList key metaInlines     "header-includes" -> (key,) <$> accumulatingList key metaInlines     "latex_header"    -> (inclKey,) <$>                          accumulatingList inclKey (metaExportSnippet "latex")@@ -103,32 +106,32 @@                          accumulatingList inclKey (metaExportSnippet "html")     _                 -> (key,) <$> metaString -metaInlines :: OrgParser (F MetaValue)+metaInlines :: PandocMonad m => OrgParser m (F MetaValue) metaInlines = fmap (MetaInlines . B.toList) <$> inlinesTillNewline -metaInlinesCommaSeparated :: OrgParser (F MetaValue)+metaInlinesCommaSeparated :: PandocMonad m => OrgParser m (F MetaValue) metaInlinesCommaSeparated = do-  authStrs <- (many1 (noneOf ",\n")) `sepBy1` (char ',')+  itemStrs <- many1 (noneOf ",\n") `sepBy1` char ','   newline-  authors <- mapM (parseFromString inlinesTillNewline . (++ "\n")) authStrs+  items <- mapM (parseFromString inlinesTillNewline . (++ "\n")) itemStrs   let toMetaInlines = MetaInlines . B.toList-  return $ MetaList . map toMetaInlines <$> sequence authors+  return $ MetaList . map toMetaInlines <$> sequence items -metaString :: OrgParser (F MetaValue)+metaString :: Monad m => OrgParser m (F MetaValue) metaString = metaModifiedString id -metaModifiedString :: (String -> String) -> OrgParser (F MetaValue)+metaModifiedString :: Monad m => (String -> String) -> OrgParser m (F MetaValue) metaModifiedString f = return . MetaString . f <$> anyLine  -- | Read an format specific meta definition-metaExportSnippet :: String -> OrgParser (F MetaValue)+metaExportSnippet :: Monad m => String -> OrgParser m (F MetaValue) metaExportSnippet format =   return . MetaInlines . B.toList . B.rawInline format <$> anyLine  -- | Accumulate the result of the @parser@ in a list under @key@.-accumulatingList :: String-                 -> OrgParser (F MetaValue)-                 -> OrgParser (F MetaValue)+accumulatingList :: Monad m => String+                 -> OrgParser m (F MetaValue)+                 -> OrgParser m (F MetaValue) accumulatingList key p = do   value <- p   meta' <- orgStateMeta <$> getState@@ -141,7 +144,7 @@ -- -- export options ---optionLine :: OrgParser ()+optionLine :: Monad m => OrgParser m () optionLine = try $ do   key <- metaKey   case key of@@ -150,16 +153,17 @@     "todo"     -> todoSequence >>= updateState . registerTodoSequence     "seq_todo" -> todoSequence >>= updateState . registerTodoSequence     "typ_todo" -> todoSequence >>= updateState . registerTodoSequence-    _         -> mzero+    "macro"    -> macroDefinition >>= updateState . registerMacro+    _          -> mzero -addLinkFormat :: String+addLinkFormat :: Monad m => String               -> (String -> String)-              -> OrgParser ()+              -> OrgParser m () addLinkFormat key formatter = updateState $ \s ->   let fs = orgStateLinkFormatters s   in s{ orgStateLinkFormatters = M.insert key formatter fs } -parseLinkFormat :: OrgParser ((String, String -> String))+parseLinkFormat :: Monad m => OrgParser m (String, String -> String) parseLinkFormat = try $ do   linkType <- (:) <$> letter <*> many (alphaNum <|> oneOf "-_") <* skipSpaces   linkSubst <- parseFormat@@ -167,9 +171,8 @@  -- | An ad-hoc, single-argument-only implementation of a printf-style format -- parser.-parseFormat :: OrgParser (String -> String)-parseFormat = try $ do-  replacePlain <|> replaceUrl <|> justAppend+parseFormat :: Monad m => OrgParser m (String -> String)+parseFormat = try $ replacePlain <|> replaceUrl <|> justAppend  where    -- inefficient, but who cares    replacePlain = try $ (\x -> concat . flip intersperse x)@@ -181,13 +184,15 @@    rest            = manyTill anyChar         (eof <|> () <$ oneOf "\n\r")    tillSpecifier c = manyTill (noneOf "\n\r") (try $ string ('%':c:"")) -inlinesTillNewline :: OrgParser (F Inlines)-inlinesTillNewline = trimInlinesF . mconcat <$> manyTill inline newline+inlinesTillNewline :: PandocMonad m => OrgParser m (F Inlines)+inlinesTillNewline = do+  updateLastPreCharPos+  trimInlinesF . mconcat <$> manyTill inline newline  -- -- ToDo Sequences and Keywords ---todoSequence :: OrgParser TodoSequence+todoSequence :: Monad m => OrgParser m TodoSequence todoSequence = try $ do   todoKws <- todoKeywords   doneKws <- optionMaybe $ todoDoneSep *> todoKeywords@@ -201,13 +206,13 @@                     (x:xs) -> return $ keywordsToSequence (reverse xs) [x]   where-   todoKeywords :: OrgParser [String]+   todoKeywords :: Monad m => OrgParser m [String]    todoKeywords = try $      let keyword = many1 nonspaceChar <* skipSpaces          endOfKeywords = todoDoneSep <|> void newline      in manyTill keyword (lookAhead endOfKeywords) -   todoDoneSep :: OrgParser ()+   todoDoneSep :: Monad m => OrgParser m ()    todoDoneSep = void . try $ skipSpaces *> char '|' <* skipSpaces1     keywordsToSequence :: [String] -> [String] -> TodoSequence@@ -215,3 +220,27 @@      let todoMarkers = map (TodoMarker Todo) todo          doneMarkers = map (TodoMarker Done) done      in todoMarkers ++ doneMarkers++macroDefinition :: Monad m => OrgParser m (String, [String] -> String)+macroDefinition = try $ do+  macroName <- many1 nonspaceChar <* skipSpaces+  firstPart <- expansionPart+  (elemOrder, parts) <- unzip <$> many ((,) <$> placeholder <*> expansionPart)+  let expander = mconcat . alternate (firstPart:parts) . reorder elemOrder+  return (macroName, expander)+ where+  placeholder :: Monad m => OrgParser m Int+  placeholder = try . fmap read $ char '$' *> many1 digit++  expansionPart :: Monad m => OrgParser m String+  expansionPart = try $ many (notFollowedBy placeholder *> noneOf "\n\r")++  alternate :: [a] -> [a] -> [a]+  alternate []     ys     = ys+  alternate xs     []     = xs+  alternate (x:xs) (y:ys) = x : y : alternate xs ys++  reorder :: [Int] -> [String] -> [String]+  reorder perm xs =+    let element n = take 1 $ drop (n - 1) xs+    in concatMap element perm
src/Text/Pandoc/Readers/Org/ParserState.hs view
@@ -1,8 +1,7 @@-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE FlexibleInstances     #-} {-# LANGUAGE MultiParamTypeClasses #-} {--Copyright (C) 2014-2016 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>+Copyright (C) 2014-2017 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -20,8 +19,8 @@ -}  {- |-   Module      : Text.Pandoc.Readers.Org.Options-   Copyright   : Copyright (C) 2014-2016 Albert Krewinkel+   Module      : Text.Pandoc.Readers.Org.ParserState+   Copyright   : Copyright (C) 2014-2017 Albert Krewinkel    License     : GNU GPL, version 2 or above     Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>@@ -34,12 +33,16 @@   , OrgNoteRecord   , HasReaderOptions (..)   , HasQuoteContext (..)+  , HasMacros (..)   , TodoMarker (..)   , TodoSequence   , TodoState (..)   , activeTodoMarkers   , registerTodoSequence-  , F(..)+  , MacroExpander+  , lookupMacro+  , registerMacro+  , F   , askF   , asksF   , trimInlinesF@@ -50,25 +53,29 @@   , optionsToParserState   ) where -import           Control.Monad (liftM, liftM2)-import           Control.Monad.Reader (Reader, runReader, ask, asks, local)+import Control.Monad.Reader (ReaderT, asks, local) -import           Data.Default (Default(..))+import Data.Default (Default (..)) import qualified Data.Map as M import qualified Data.Set as Set+import Data.Text (Text) -import           Text.Pandoc.Builder ( Inlines, Blocks, trimInlines )-import           Text.Pandoc.Definition ( Meta(..), nullMeta )-import           Text.Pandoc.Options ( ReaderOptions(..) )-import           Text.Pandoc.Parsing ( HasHeaderMap(..)-                                     , HasIdentifierList(..)-                                     , HasLastStrPosition(..)-                                     , HasQuoteContext(..)-                                     , HasReaderOptions(..)-                                     , ParserContext(..)-                                     , QuoteContext(..)-                                     , SourcePos )+import Text.Pandoc.Builder (Blocks, Inlines)+import Text.Pandoc.Definition (Meta (..), nullMeta)+import Text.Pandoc.Logging+import Text.Pandoc.Options (ReaderOptions (..))+import Text.Pandoc.Parsing (Future, HasHeaderMap (..), HasIdentifierList (..),+                            HasIncludeFiles (..), HasLastStrPosition (..),+                            HasLogMessages (..), HasMacros (..),+                            HasQuoteContext (..), HasReaderOptions (..),+                            ParserContext (..), QuoteContext (..), SourcePos,+                            askF, asksF, returnF, runF, trimInlinesF)+import Text.Pandoc.Readers.LaTeX.Types (Macro) +-- | This is used to delay evaluation until all relevant information has been+-- parsed and made available in the parser state.+type F = Future OrgParserState+ -- | An inline note / footnote containing the note key and its (inline) value. type OrgNoteRecord = (String, F Blocks) -- | Table of footnotes@@ -76,6 +83,8 @@ -- | Map of functions for link transformations.  The map key is refers to the -- link-type, the corresponding function transforms the given link string. type OrgLinkFormatters = M.Map String (String -> String)+-- | Macro expander function+type MacroExpander = [String] -> String  -- | The states in which a todo item can be data TodoState = Todo | Done@@ -99,15 +108,20 @@   , orgStateExportSettings       :: ExportSettings   , orgStateHeaderMap            :: M.Map Inlines String   , orgStateIdentifiers          :: Set.Set String+  , orgStateIncludeFiles         :: [String]   , orgStateLastForbiddenCharPos :: Maybe SourcePos   , orgStateLastPreCharPos       :: Maybe SourcePos   , orgStateLastStrPos           :: Maybe SourcePos   , orgStateLinkFormatters       :: OrgLinkFormatters+  , orgStateMacros               :: M.Map String MacroExpander+  , orgStateMacroDepth           :: Int   , orgStateMeta                 :: F Meta   , orgStateNotes'               :: OrgNoteTable   , orgStateOptions              :: ReaderOptions   , orgStateParserContext        :: ParserContext   , orgStateTodoSequences        :: [TodoSequence]+  , orgLogMessages               :: [LogMessage]+  , orgMacros                    :: M.Map Text Macro   }  data OrgParserLocal = OrgParserLocal { orgLocalQuoteContext :: QuoteContext }@@ -122,7 +136,7 @@   getLastStrPos = orgStateLastStrPos   setLastStrPos pos st = st{ orgStateLastStrPos = Just pos } -instance HasQuoteContext st (Reader OrgParserLocal) where+instance Monad m => HasQuoteContext st (ReaderT OrgParserLocal m) where   getQuoteContext = asks orgLocalQuoteContext   withQuoteContext q = local (\s -> s{orgLocalQuoteContext = q}) @@ -134,6 +148,20 @@   extractHeaderMap = orgStateHeaderMap   updateHeaderMap  f s = s{ orgStateHeaderMap = f (orgStateHeaderMap s) } +instance HasLogMessages OrgParserState where+  addLogMessage msg st = st{ orgLogMessages = msg : orgLogMessages st }+  getLogMessages st = reverse $ orgLogMessages st++instance HasMacros OrgParserState where+  extractMacros st = orgMacros st+  updateMacros f st = st{ orgMacros = f (orgMacros st) }++instance HasIncludeFiles OrgParserState where+  getIncludeFiles = orgStateIncludeFiles+  addIncludeFile f st = st { orgStateIncludeFiles = f : orgStateIncludeFiles st }+  dropLatestIncludeFile st =+    st { orgStateIncludeFiles = drop 1 $ orgStateIncludeFiles st }+ instance Default OrgParserState where   def = defaultOrgParserState @@ -145,15 +173,20 @@   , orgStateExportSettings = def   , orgStateHeaderMap = M.empty   , orgStateIdentifiers = Set.empty+  , orgStateIncludeFiles = []   , orgStateLastForbiddenCharPos = Nothing   , orgStateLastPreCharPos = Nothing   , orgStateLastStrPos = Nothing   , orgStateLinkFormatters = M.empty+  , orgStateMacros = M.empty+  , orgStateMacroDepth = 0   , orgStateMeta = return nullMeta   , orgStateNotes' = []   , orgStateOptions = def   , orgStateParserContext = NullState   , orgStateTodoSequences = []+  , orgLogMessages = []+  , orgMacros = M.empty   }  optionsToParserState :: ReaderOptions -> OrgParserState@@ -177,7 +210,16 @@ activeTodoMarkers :: OrgParserState -> TodoSequence activeTodoMarkers = concat . activeTodoSequences +lookupMacro :: String -> OrgParserState -> Maybe MacroExpander+lookupMacro macroName = M.lookup macroName . orgStateMacros +registerMacro :: (String, MacroExpander) -> OrgParserState -> OrgParserState+registerMacro (name, expander) st =+  let curMacros = orgStateMacros st+  in st{ orgStateMacros = M.insert name expander curMacros }+++ -- -- Export Settings --@@ -191,20 +233,22 @@ -- | Export settings <http://orgmode.org/manual/Export-settings.html> -- These settings can be changed via OPTIONS statements. data ExportSettings = ExportSettings-  { exportArchivedTrees   :: ArchivedTreesOption -- ^ How to treat archived trees-  , exportDrawers         :: Either [String] [String]+  { exportArchivedTrees    :: ArchivedTreesOption -- ^ How to treat archived trees+  , exportDrawers          :: Either [String] [String]   -- ^ Specify drawer names which should be exported.  @Left@ names are   -- explicitly excluded from the resulting output while @Right@ means that   -- only the listed drawer names should be included.-  , exportEmphasizedText  :: Bool -- ^ Parse emphasized text-  , exportHeadlineLevels  :: Int+  , exportEmphasizedText   :: Bool -- ^ Parse emphasized text+  , exportHeadlineLevels   :: Int   -- ^ Maximum depth of headlines, deeper headlines are convert to list-  , exportSmartQuotes     :: Bool -- ^ Parse quotes smartly-  , exportSpecialStrings  :: Bool -- ^ Parse ellipses and dashes smartly-  , exportSubSuperscripts :: Bool -- ^ TeX-like syntax for sub- and superscripts-  , exportWithAuthor      :: Bool -- ^ Include author in final meta-data-  , exportWithCreator     :: Bool -- ^ Include creator in final meta-data-  , exportWithEmail       :: Bool -- ^ Include email in final meta-data+  , exportPreserveBreaks   :: Bool -- ^ Whether to preserve linebreaks+  , exportSmartQuotes      :: Bool -- ^ Parse quotes smartly+  , exportSpecialStrings   :: Bool -- ^ Parse ellipses and dashes smartly+  , exportSubSuperscripts  :: Bool -- ^ TeX-like syntax for sub- and superscripts+  , exportWithAuthor       :: Bool -- ^ Include author in final meta-data+  , exportWithCreator      :: Bool -- ^ Include creator in final meta-data+  , exportWithEmail        :: Bool -- ^ Include email in final meta-data+  , exportWithTags         :: Bool -- ^ Keep tags as part of headlines   , exportWithTodoKeywords :: Bool -- ^ Keep TODO keywords in headers   } @@ -217,43 +261,13 @@   , exportDrawers = Left ["LOGBOOK"]   , exportEmphasizedText = True   , exportHeadlineLevels = 3-  , exportSmartQuotes = True+  , exportPreserveBreaks = False+  , exportSmartQuotes = False   , exportSpecialStrings = True   , exportSubSuperscripts = True   , exportWithAuthor = True   , exportWithCreator = True   , exportWithEmail = True+  , exportWithTags = True   , exportWithTodoKeywords = True   }-------- Parser state reader------- | Reader monad wrapping the parser state.  This is used to delay evaluation--- until all relevant information has been parsed and made available in the--- parser state.  See also the newtype of the same name in--- Text.Pandoc.Parsing.-newtype F a = F { unF :: Reader OrgParserState a-                } deriving (Functor, Applicative, Monad)--instance Monoid a => Monoid (F a) where-  mempty = return mempty-  mappend = liftM2 mappend-  mconcat = fmap mconcat . sequence--runF :: F a -> OrgParserState -> a-runF = runReader . unF--askF :: F OrgParserState-askF = F ask--asksF :: (OrgParserState -> a) -> F a-asksF f = F $ asks f--trimInlinesF :: F Inlines -> F Inlines-trimInlinesF = liftM trimInlines--returnF :: Monad m => a -> m (F a)-returnF = return . return
src/Text/Pandoc/Readers/Org/Parsing.hs view
@@ -1,5 +1,5 @@ {--Copyright (C) 2014-2016 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>+Copyright (C) 2014-2017 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -17,8 +17,8 @@ -}  {- |-   Module      : Text.Pandoc.Readers.Org.Options-   Copyright   : Copyright (C) 2014-2016 Albert Krewinkel+   Module      : Text.Pandoc.Readers.Org.Parsing+   Copyright   : Copyright (C) 2014-2017 Albert Krewinkel    License     : GNU GPL, version 2 or above     Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>@@ -31,6 +31,8 @@ module Text.Pandoc.Readers.Org.Parsing   ( OrgParser   , anyLine+  , anyLineNewline+  , indentWith   , blanklines   , newline   , parseFromString@@ -70,8 +72,11 @@   , dash   , ellipses   , citeKey+  , gridTableWith+  , insertIncludedFileF   -- * Re-exports from Text.Pandoc.Parsec   , runParser+  , runParserT   , getInput   , char   , letter@@ -107,24 +112,24 @@   , getPosition   ) where -import           Text.Pandoc.Readers.Org.ParserState+import Text.Pandoc.Readers.Org.ParserState +import Text.Pandoc.Parsing hiding (F, anyLine, blanklines, newline,+                            parseFromString) import qualified Text.Pandoc.Parsing as P-import           Text.Pandoc.Parsing hiding ( anyLine, blanklines, newline-                                            , parseFromString ) -import           Control.Monad ( guard )-import           Control.Monad.Reader ( Reader )+import Control.Monad (guard)+import Control.Monad.Reader (ReaderT)  -- | The parser used to read org files.-type OrgParser = ParserT [Char] OrgParserState (Reader OrgParserLocal)+type OrgParser m = ParserT [Char] OrgParserState (ReaderT OrgParserLocal m)  -- -- Adaptions and specializations of parsing utilities --  -- | Parse any line of text-anyLine :: OrgParser String+anyLine :: Monad m => OrgParser m String anyLine =   P.anyLine     <* updateLastPreCharPos@@ -132,7 +137,7 @@  -- The version Text.Pandoc.Parsing cannot be used, as we need additional parts -- of the state saved and restored.-parseFromString :: OrgParser a -> String -> OrgParser a+parseFromString :: Monad m => OrgParser m a -> String -> OrgParser m a parseFromString parser str' = do   oldLastPreCharPos <- orgStateLastPreCharPos <$> getState   updateState $ \s -> s{ orgStateLastPreCharPos = Nothing }@@ -141,33 +146,34 @@   return result  -- | Skip one or more tab or space characters.-skipSpaces1 :: OrgParser ()+skipSpaces1 :: Monad m => OrgParser m () skipSpaces1 = skipMany1 spaceChar  -- | Like @Text.Parsec.Char.newline@, but causes additional state changes.-newline :: OrgParser Char+newline :: Monad m => OrgParser m Char newline =   P.newline        <* updateLastPreCharPos        <* updateLastForbiddenCharPos  -- | Like @Text.Parsec.Char.blanklines@, but causes additional state changes.-blanklines :: OrgParser [Char]+blanklines :: Monad m => OrgParser m [Char] blanklines =   P.blanklines        <* updateLastPreCharPos        <* updateLastForbiddenCharPos  -- | Succeeds when we're in list context.-inList :: OrgParser ()+inList :: Monad m => OrgParser m () inList = do   ctx <- orgStateParserContext <$> getState   guard (ctx == ListItemState)  -- | Parse in different context-withContext :: ParserContext -- ^ New parser context-            -> OrgParser a   -- ^ Parser to run in that context-            -> OrgParser a+withContext :: Monad m+            => ParserContext -- ^ New parser context+            -> OrgParser m a   -- ^ Parser to run in that context+            -> OrgParser m a withContext context parser = do   oldContext <- orgStateParserContext <$> getState   updateState $ \s -> s{ orgStateParserContext = context }@@ -180,19 +186,19 @@ --  -- | Get an export setting.-getExportSetting :: (ExportSettings -> a) -> OrgParser a+getExportSetting :: Monad m =>  (ExportSettings -> a) -> OrgParser m a getExportSetting s = s . orgStateExportSettings <$> getState  -- | Set the current position as the last position at which a forbidden char -- was found (i.e. a character which is not allowed at the inner border of -- markup).-updateLastForbiddenCharPos :: OrgParser ()+updateLastForbiddenCharPos :: Monad m => OrgParser m () updateLastForbiddenCharPos = getPosition >>= \p ->   updateState $ \s -> s{ orgStateLastForbiddenCharPos = Just p}  -- | Set the current parser position as the position at which a character was -- seen which allows inline markup to follow.-updateLastPreCharPos :: OrgParser ()+updateLastPreCharPos :: Monad m => OrgParser m () updateLastPreCharPos = getPosition >>= \p ->   updateState $ \s -> s{ orgStateLastPreCharPos = Just p} @@ -201,15 +207,15 @@ --  -- | Read the key of a plist style key-value list.-orgArgKey :: OrgParser String+orgArgKey :: Monad m => OrgParser m String orgArgKey = try $   skipSpaces *> char ':'              *> many1 orgArgWordChar  -- | Read the value of a plist style key-value list.-orgArgWord :: OrgParser String+orgArgWord :: Monad m => OrgParser m String orgArgWord = many1 orgArgWordChar  -- | Chars treated as part of a word in plists.-orgArgWordChar :: OrgParser Char+orgArgWordChar :: Monad m => OrgParser m Char orgArgWordChar = alphaNum <|> oneOf "-_"
src/Text/Pandoc/Readers/Org/Shared.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE OverloadedStrings #-} {--Copyright (C) 2014-2016 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>+Copyright (C) 2014-2017 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -18,8 +18,8 @@ -}  {- |-   Module      : Text.Pandoc.Readers.Org.Options-   Copyright   : Copyright (C) 2014-2016 Albert Krewinkel+   Module      : Text.Pandoc.Readers.Org.Shared+   Copyright   : Copyright (C) 2014-2017 Albert Krewinkel    License     : GNU GPL, version 2 or above     Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>@@ -29,14 +29,12 @@ module Text.Pandoc.Readers.Org.Shared   ( cleanLinkString   , isImageFilename-  , rundocBlockClass-  , toRundocAttrib+  , originalLang   , translateLang   ) where -import           Control.Arrow ( first )-import           Data.Char ( isAlphaNum )-import           Data.List ( isPrefixOf, isSuffixOf )+import Data.Char (isAlphaNum)+import Data.List (isPrefixOf, isSuffixOf)   -- | Check whether the given string looks like the path to of URL of an image.@@ -58,8 +56,8 @@     '.':'/':_              -> Just s                 -- relative path     '.':'.':'/':_          -> Just s                 -- relative path     -- Relative path or URL (file schema)-    'f':'i':'l':'e':':':s' -> Just $ if ("//" `isPrefixOf` s') then s else s'-    _ | isUrl s            -> Just s                 -- URL+    'f':'i':'l':'e':':':s' -> Just $ if "//" `isPrefixOf` s' then s else s'+    _                      | isUrl s            -> Just s                 -- URL     _                      -> Nothing  where    isUrl :: String -> Bool@@ -68,17 +66,17 @@      in all (\c -> isAlphaNum c || c `elem` (".-"::String)) scheme           && not (null path) --- | Prefix used for Rundoc classes and arguments.-rundocPrefix :: String-rundocPrefix = "rundoc-"---- | The class-name used to mark rundoc blocks.-rundocBlockClass :: String-rundocBlockClass = rundocPrefix ++ "block"+-- | Creates an key-value pair marking the original language name specified for+-- a piece of source code. --- | Prefix the name of a attribute, marking it as a code execution parameter.-toRundocAttrib :: (String, String) -> (String, String)-toRundocAttrib = first (rundocPrefix ++)+-- | Creates an key-value attributes marking the original language name+-- specified for a piece of source code.+originalLang :: String -> [(String, String)]+originalLang lang =+  let transLang = translateLang lang+  in if transLang == lang+     then []+     else [("org-language", lang)]  -- | Translate from Org-mode's programming language identifiers to those used -- by Pandoc.  This is useful to allow for proper syntax highlighting in
src/Text/Pandoc/Readers/RST.hs view
@@ -1,7 +1,8 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleContexts    #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE ScopedTypeVariables #-} {--Copyright (C) 2006-2015 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2006-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -20,7 +21,7 @@  {- |    Module      : Text.Pandoc.Readers.RST-   Copyright   : Copyright (C) 2006-2015 John MacFarlane+   Copyright   : Copyright (C) 2006-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -29,38 +30,50 @@  Conversion from reStructuredText to 'Pandoc' document. -}-module Text.Pandoc.Readers.RST (-                                readRST,-                                readRSTWithWarnings-                               ) where-import Text.Pandoc.Definition-import Text.Pandoc.Builder (setMeta, fromList)-import Text.Pandoc.Shared-import Text.Pandoc.Parsing-import Text.Pandoc.Options-import Control.Monad ( when, liftM, guard, mzero )-import Data.List ( findIndex, intercalate,-                   transpose, sort, deleteFirstsBy, isSuffixOf , nub, union)-import Data.Maybe (fromMaybe)+module Text.Pandoc.Readers.RST ( readRST ) where+import Control.Arrow (second)+import Control.Monad (forM_, guard, liftM, mplus, mzero, when)+import Control.Monad.Except (throwError)+import Control.Monad.Identity (Identity (..))+import Data.Char (isHexDigit, isSpace, toLower, toUpper)+import Data.List (deleteFirstsBy, elemIndex, intercalate, isInfixOf, isSuffixOf,+                  nub, sort, transpose, union) import qualified Data.Map as M-import Text.Printf ( printf )-import Text.Pandoc.Builder (Inlines, Blocks, trimInlines)-import qualified Text.Pandoc.Builder as B-import Data.Sequence (viewr, ViewR(..))-import Data.Char (toLower, isHexDigit, isSpace)+import Data.Maybe (fromMaybe, isJust) import Data.Monoid ((<>))+import Data.Sequence (ViewR (..), viewr)+import Data.Text (Text)+import qualified Data.Text as T+import Text.Pandoc.Builder (Blocks, Inlines, fromList, setMeta, trimInlines)+import qualified Text.Pandoc.Builder as B+import Text.Pandoc.Class (PandocMonad, fetchItem, readFileFromDirs)+import Text.Pandoc.CSV (CSVOptions (..), defaultCSVOptions, parseCSV)+import Text.Pandoc.Definition import Text.Pandoc.Error+import Text.Pandoc.ImageSize (lengthToDim, scaleDimension)+import Text.Pandoc.Logging+import Text.Pandoc.Options+import Text.Pandoc.Parsing+import Text.Pandoc.Shared+import qualified Text.Pandoc.UTF8 as UTF8+import Text.Printf (printf) --- | Parse reStructuredText string and return Pandoc document.-readRST :: ReaderOptions -- ^ Reader options-        -> String        -- ^ String to parse (assuming @'\n'@ line endings)-        -> Either PandocError Pandoc-readRST opts s = (readWith parseRST) def{ stateOptions = opts } (s ++ "\n\n")+-- TODO:+-- [ ] .. parsed-literal -readRSTWithWarnings :: ReaderOptions -> String -> Either PandocError (Pandoc, [String])-readRSTWithWarnings opts s = (readWithWarnings parseRST) def{ stateOptions = opts } (s ++ "\n\n")+-- | Parse reStructuredText string and return Pandoc document.+readRST :: PandocMonad m+        => ReaderOptions -- ^ Reader options+        -> Text          -- ^ String to parse (assuming @'\n'@ line endings)+        -> m Pandoc+readRST opts s = do+  parsed <- readWithM parseRST def{ stateOptions = opts }+               (T.unpack (crFilter s) ++ "\n\n")+  case parsed of+    Right result -> return result+    Left e       -> throwError e -type RSTParser = Parser [Char] ParserState+type RSTParser m = ParserT [Char] ParserState m  -- -- Constants and data structure definitions@@ -87,9 +100,9 @@ -- | Promote all headers in a list of blocks.  (Part of -- title transformation for RST.) promoteHeaders :: Int -> [Block] -> [Block]-promoteHeaders num ((Header level attr text):rest) =-    (Header (level - num) attr text):(promoteHeaders num rest)-promoteHeaders num (other:rest) = other:(promoteHeaders num rest)+promoteHeaders num (Header level attr text:rest) =+    Header (level - num) attr text:promoteHeaders num rest+promoteHeaders num (other:rest) = other:promoteHeaders num rest promoteHeaders _   [] = []  -- | If list of blocks starts with a header (or a header and subheader)@@ -101,11 +114,11 @@ titleTransform (bs, meta) =   let (bs', meta') =        case bs of-          ((Header 1 _ head1):(Header 2 _ head2):rest)+          (Header 1 _ head1:Header 2 _ head2:rest)            | not (any (isHeader 1) rest || any (isHeader 2) rest) -> -- tit/sub             (promoteHeaders 2 rest, setMeta "title" (fromList head1) $               setMeta "subtitle" (fromList head2) meta)-          ((Header 1 _ head1):rest)+          (Header 1 _ head1:rest)            | not (any (isHeader 1) rest) -> -- title only             (promoteHeaders 1 rest,                 setMeta "title" (fromList head1) meta)@@ -121,8 +134,10 @@        adjustAuthors (Meta metamap) = Meta $ M.adjust splitAuthors "author"                                            $ M.adjust toPlain "date"                                            $ M.adjust toPlain "title"-                                           $ M.mapKeys (\k -> if k == "authors" then "author" else k)-                                           $ metamap+                                           $ M.mapKeys (\k ->+                                                 if k == "authors"+                                                    then "author"+                                                    else k) metamap        toPlain (MetaBlocks [Para xs]) = MetaInlines xs        toPlain x                      = x        splitAuthors (MetaBlocks [Para xs])@@ -131,6 +146,12 @@        splitAuthors x                 = x        splitAuthors'                  = map normalizeSpaces .                                          splitOnSemi . concatMap factorSemi+       normalizeSpaces                = reverse . dropWhile isSp . reverse .+                                         dropWhile isSp+       isSp Space     = True+       isSp SoftBreak = True+       isSp LineBreak = True+       isSp _         = False        splitOnSemi                    = splitBy (==Str ";")        factorSemi (Str [])            = []        factorSemi (Str s)             = case break (==';') s of@@ -141,41 +162,61 @@                                                 factorSemi (Str ys)        factorSemi x                   = [x] -parseRST :: RSTParser Pandoc+parseRST :: PandocMonad m => RSTParser m Pandoc parseRST = do   optional blanklines -- skip blank lines at beginning of file   startPos <- getPosition   -- go through once just to get list of reference keys and notes   -- docMinusKeys is the raw document with blanks where the keys were...   docMinusKeys <- concat <$>-                  manyTill (referenceKey <|> noteBlock <|> lineClump) eof+                  manyTill (referenceKey <|> anchorDef <|>+                            noteBlock <|> citationBlock <|>+                            headerBlock <|> lineClump) eof   setInput docMinusKeys   setPosition startPos   st' <- getState   let reversedNotes = stateNotes st'-  updateState $ \s -> s { stateNotes = reverse reversedNotes }+  updateState $ \s -> s { stateNotes = reverse reversedNotes+                        , stateHeaders = mempty+                        , stateIdentifiers = mempty }   -- now parse it for real...   blocks <- B.toList <$> parseBlocks+  citations <- (sort . M.toList . stateCitations) <$> getState+  citationItems <- mapM parseCitation citations+  let refBlock = if null citationItems+                    then []+                    else [Div ("citations",[],[]) $+                            B.toList $ B.definitionList citationItems]   standalone <- getOption readerStandalone   state <- getState   let meta = stateMeta state   let (blocks', meta') = if standalone                             then titleTransform (blocks, meta)                             else (blocks, meta)-  return $ Pandoc meta' blocks'+  reportLogMessages+  return $ Pandoc meta' (blocks' ++ refBlock) +parseCitation :: PandocMonad m+              => (String, String) -> RSTParser m (Inlines, [Blocks])+parseCitation (ref, raw) = do+  contents <- parseFromString' parseBlocks raw+  return (B.spanWith (ref, ["citation-label"], []) (B.str ref),+           [contents])++ -- -- parsing blocks -- -parseBlocks :: RSTParser Blocks+parseBlocks :: PandocMonad m => RSTParser m Blocks parseBlocks = mconcat <$> manyTill block eof -block :: RSTParser Blocks+block :: PandocMonad m => RSTParser m Blocks block = choice [ codeBlock                , blockQuote                , fieldList                , directive+               , anchor                , comment                , header                , hrule@@ -191,7 +232,7 @@ -- field list -- -rawFieldListItem :: Int -> RSTParser (String, String)+rawFieldListItem :: Monad m => Int -> RSTParser m (String, String) rawFieldListItem minIndent = try $ do   indent <- length <$> many (char ' ')   guard $ indent >= minIndent@@ -204,15 +245,15 @@   let raw = (if null first then "" else (first ++ "\n")) ++ rest ++ "\n"   return (name, raw) -fieldListItem :: Int -> RSTParser (Inlines, [Blocks])+fieldListItem :: PandocMonad m => Int -> RSTParser m (Inlines, [Blocks]) fieldListItem minIndent = try $ do   (name, raw) <- rawFieldListItem minIndent   term <- parseInlineFromString name-  contents <- parseFromString parseBlocks raw+  contents <- parseFromString' parseBlocks raw   optional blanklines   return (term, [contents]) -fieldList :: RSTParser Blocks+fieldList :: PandocMonad m => RSTParser m Blocks fieldList = try $ do   indent <- length <$> lookAhead (many spaceChar)   items <- many1 $ fieldListItem indent@@ -224,43 +265,62 @@ -- line block -- -lineBlock :: RSTParser Blocks+lineBlock :: PandocMonad m => RSTParser m Blocks lineBlock = try $ do   lines' <- lineBlockLines   lines'' <- mapM parseInlineFromString lines'   return $ B.lineBlock lines'' +lineBlockDirective :: PandocMonad m => String -> RSTParser m Blocks+lineBlockDirective body = do+  lines' <- mapM parseInlineFromString $ lines $ stripTrailingNewlines body+  return $ B.lineBlock lines'+ -- -- paragraph block --  -- note: paragraph can end in a :: starting a code block-para :: RSTParser Blocks+para :: PandocMonad m => RSTParser m Blocks para = try $ do   result <- trimInlines . mconcat <$> many1 inline   option (B.plain result) $ try $ do     newline     blanklines     case viewr (B.unMany result) of-         ys :> (Str xs) | "::" `isSuffixOf` xs -> do+         ys :> Str xs | "::" `isSuffixOf` xs -> do               raw <- option mempty codeBlockBody               return $ B.para (B.Many ys <> B.str (take (length xs - 1) xs))                          <> raw          _ -> return (B.para result) -plain :: RSTParser Blocks+plain :: PandocMonad m => RSTParser m Blocks plain = B.plain . trimInlines . mconcat <$> many1 inline  -- -- header blocks -- -header :: RSTParser Blocks+header :: PandocMonad m => RSTParser m Blocks header = doubleHeader <|> singleHeader <?> "header"  -- a header with lines on top and bottom-doubleHeader :: RSTParser Blocks-doubleHeader = try $ do+doubleHeader :: PandocMonad m => RSTParser m Blocks+doubleHeader = do+  (txt, c) <- doubleHeader'+  -- check to see if we've had this kind of header before.+  -- if so, get appropriate level.  if not, add to list.+  state <- getState+  let headerTable = stateHeaderTable state+  let (headerTable',level) = case elemIndex (DoubleHeader c) headerTable of+        Just ind -> (headerTable, ind + 1)+        Nothing  -> (headerTable ++ [DoubleHeader c], length headerTable + 1)+  setState (state { stateHeaderTable = headerTable' })+  attr <- registerHeader nullAttr txt+  return $ B.headerWith attr level txt++doubleHeader' :: PandocMonad m => RSTParser m (Inlines, Char)+doubleHeader' = try $ do   c <- oneOf underlineChars   rest <- many (char c)  -- the top line   let lenTop = length (c:rest)@@ -268,48 +328,45 @@   newline   txt <- trimInlines . mconcat <$> many1 (notFollowedBy blankline >> inline)   pos <- getPosition-  let len = (sourceColumn pos) - 1-  if (len > lenTop) then fail "title longer than border" else return ()+  let len = sourceColumn pos - 1+  when (len > lenTop) $ fail "title longer than border"   blankline              -- spaces and newline   count lenTop (char c)  -- the bottom line   blanklines-  -- check to see if we've had this kind of header before.-  -- if so, get appropriate level.  if not, add to list.+  return (txt, c)++-- a header with line on the bottom only+singleHeader :: PandocMonad m => RSTParser m Blocks+singleHeader = do+  (txt, c) <- singleHeader'   state <- getState   let headerTable = stateHeaderTable state-  let (headerTable',level) = case findIndex (== DoubleHeader c) headerTable of+  let (headerTable',level) = case elemIndex (SingleHeader c) headerTable of         Just ind -> (headerTable, ind + 1)-        Nothing -> (headerTable ++ [DoubleHeader c], (length headerTable) + 1)+        Nothing  -> (headerTable ++ [SingleHeader c], length headerTable + 1)   setState (state { stateHeaderTable = headerTable' })   attr <- registerHeader nullAttr txt   return $ B.headerWith attr level txt --- a header with line on the bottom only-singleHeader :: RSTParser Blocks-singleHeader = try $ do+singleHeader' :: PandocMonad m => RSTParser m (Inlines, Char)+singleHeader' = try $ do   notFollowedBy' whitespace-  txt <- trimInlines . mconcat <$> many1 (do {notFollowedBy blankline; inline})+  lookAhead $ anyLine >> oneOf underlineChars+  txt <- trimInlines . mconcat <$> many1 (do {notFollowedBy newline; inline})   pos <- getPosition-  let len = (sourceColumn pos) - 1+  let len = sourceColumn pos - 1   blankline   c <- oneOf underlineChars   count (len - 1) (char c)   many (char c)   blanklines-  state <- getState-  let headerTable = stateHeaderTable state-  let (headerTable',level) = case findIndex (== SingleHeader c) headerTable of-        Just ind -> (headerTable, ind + 1)-        Nothing -> (headerTable ++ [SingleHeader c], (length headerTable) + 1)-  setState (state { stateHeaderTable = headerTable' })-  attr <- registerHeader nullAttr txt-  return $ B.headerWith attr level txt+  return (txt, c)  -- -- hrule block -- -hrule :: Parser [Char] st Blocks+hrule :: Monad m => ParserT [Char] st m Blocks hrule = try $ do   chr <- oneOf underlineChars   count 3 (char chr)@@ -323,14 +380,14 @@ --  -- read a line indented by a given string-indentedLine :: String -> Parser [Char] st [Char]+indentedLine :: Monad m => String -> ParserT [Char] st m [Char] indentedLine indents = try $ do   string indents   anyLine  -- one or more indented lines, possibly separated by blank lines. -- any amount of indentation will work.-indentedBlock :: Parser [Char] st [Char]+indentedBlock :: Monad m => ParserT [Char] st m [Char] indentedBlock = try $ do   indents <- lookAhead $ many1 spaceChar   lns <- many1 $ try $ do b <- option "" blanklines@@ -339,24 +396,24 @@   optional blanklines   return $ unlines lns -quotedBlock :: Parser [Char] st [Char]+quotedBlock :: Monad m => ParserT [Char] st m [Char] quotedBlock = try $ do     quote <- lookAhead $ oneOf "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"     lns <- many1 $ lookAhead (char quote) >> anyLine     optional blanklines     return $ unlines lns -codeBlockStart :: Parser [Char] st Char+codeBlockStart :: Monad m => ParserT [Char] st m Char codeBlockStart = string "::" >> blankline >> blankline -codeBlock :: Parser [Char] st Blocks+codeBlock :: Monad m => ParserT [Char] st m Blocks codeBlock = try $ codeBlockStart >> codeBlockBody -codeBlockBody :: Parser [Char] st Blocks+codeBlockBody :: Monad m => ParserT [Char] st m Blocks codeBlockBody = try $ B.codeBlock . stripTrailingNewlines <$>                 (indentedBlock <|> quotedBlock) -lhsCodeBlock :: RSTParser Blocks+lhsCodeBlock :: Monad m => RSTParser m Blocks lhsCodeBlock = try $ do   getPosition >>= guard . (==1) . sourceColumn   guardEnabled Ext_literate_haskell@@ -366,14 +423,14 @@   return $ B.codeBlockWith ("", ["sourceCode", "literate", "haskell"], [])          $ intercalate "\n" lns -latexCodeBlock :: Parser [Char] st [[Char]]+latexCodeBlock :: Monad m => ParserT [Char] st m [[Char]] latexCodeBlock = try $ do   try (latexBlockLine "\\begin{code}")   many1Till anyLine (try $ latexBlockLine "\\end{code}")  where   latexBlockLine s = skipMany spaceChar >> string s >> blankline -birdCodeBlock :: Parser [Char] st [[Char]]+birdCodeBlock :: Monad m => ParserT [Char] st m [[Char]] birdCodeBlock = filterSpace <$> many1 birdTrackLine   where filterSpace lns =             -- if (as is normal) there is always a space after >, drop it@@ -381,42 +438,112 @@                then map (drop 1) lns                else lns -birdTrackLine :: Parser [Char] st [Char]+birdTrackLine :: Monad m => ParserT [Char] st m [Char] birdTrackLine = char '>' >> anyLine  -- -- block quotes -- -blockQuote :: RSTParser Blocks+blockQuote :: PandocMonad m => RSTParser m Blocks blockQuote = do   raw <- indentedBlock   -- parse the extracted block, which may contain various block elements:-  contents <- parseFromString parseBlocks $ raw ++ "\n\n"+  contents <- parseFromString' parseBlocks $ raw ++ "\n\n"   return $ B.blockQuote contents +{-+Unsupported options for include:+tab-width+encoding+-}++includeDirective :: PandocMonad m+                 => String -> [(String, String)] -> String+                 -> RSTParser m Blocks+includeDirective top fields body = do+  let f = trim top+  guard $ not (null f)+  guard $ null (trim body)+  -- options+  let (startLine :: Maybe Int) = lookup "start-line" fields >>= safeRead+  let (endLine :: Maybe Int) = lookup "end-line" fields >>= safeRead+  oldPos <- getPosition+  oldInput <- getInput+  containers <- stateContainers <$> getState+  when (f `elem` containers) $+    throwError $ PandocParseError $ "Include file loop at " ++ show oldPos+  updateState $ \s -> s{ stateContainers = f : stateContainers s }+  mbContents <- readFileFromDirs ["."] f+  contentLines <- case mbContents of+                       Just s -> return $ lines s+                       Nothing -> do+                         logMessage $ CouldNotLoadIncludeFile f oldPos+                         return []+  let numLines = length contentLines+  let startLine' = case startLine of+                        Nothing            -> 1+                        Just x | x >= 0    -> x+                               | otherwise -> numLines + x -- negative from end+  let endLine' = case endLine of+                        Nothing            -> numLines + 1+                        Just x | x >= 0    -> x+                               | otherwise -> numLines + x -- negative from end+  let contentLines' =   drop (startLine' - 1)+                      $ take (endLine' - 1) contentLines+  let contentLines'' = (case trim <$> lookup "end-before" fields of+                             Just patt -> takeWhile (not . (patt `isInfixOf`))+                             Nothing   -> id) .+                       (case trim <$> lookup "start-after" fields of+                             Just patt -> drop 1 .+                                            dropWhile (not . (patt `isInfixOf`))+                             Nothing   -> id) $ contentLines'+  let contents' = unlines contentLines'' ++ "\n"+  case lookup "code" fields of+       Just lang -> do+         let numberLines = lookup "number-lines" fields+         let classes = trimr lang : ["numberLines" | isJust numberLines] +++                          maybe [] words (lookup "class" fields)+         let kvs = maybe [] (\n -> [("startFrom", trimr n)]) numberLines+         let ident = maybe "" trimr $ lookup "name" fields+         let attribs = (ident, classes, kvs)+         return $ B.codeBlockWith attribs contents'+       Nothing   -> case lookup "literal" fields of+                         Just _  -> return $ B.rawBlock "rst" contents'+                         Nothing -> do+                           setPosition $ newPos f 1 1+                           setInput contents'+                           bs <- optional blanklines >>+                                  (mconcat <$> many block)+                           setInput oldInput+                           setPosition oldPos+                           updateState $ \s -> s{ stateContainers =+                                         tail $ stateContainers s }+                           return bs++ -- -- list blocks -- -list :: RSTParser Blocks+list :: PandocMonad m => RSTParser m Blocks list = choice [ bulletList, orderedList, definitionList ] <?> "list" -definitionListItem :: RSTParser (Inlines, [Blocks])+definitionListItem :: PandocMonad m => RSTParser m (Inlines, [Blocks]) definitionListItem = try $ do   -- avoid capturing a directive or comment   notFollowedBy (try $ char '.' >> char '.')   term <- trimInlines . mconcat <$> many1Till inline endline   raw <- indentedBlock   -- parse the extracted block, which may contain various block elements:-  contents <- parseFromString parseBlocks $ raw ++ "\n"+  contents <- parseFromString' parseBlocks $ raw ++ "\n"   return (term, [contents]) -definitionList :: RSTParser Blocks+definitionList :: PandocMonad m => RSTParser m Blocks definitionList = B.definitionList <$> many1 definitionListItem  -- parses bullet list start and returns its length (inc. following whitespace)-bulletListStart :: Parser [Char] st Int+bulletListStart :: Monad m => ParserT [Char] st m Int bulletListStart = try $ do   notFollowedBy' hrule  -- because hrules start out just like lists   marker <- oneOf bulletListMarkers@@ -424,56 +551,46 @@   return $ length (marker:white)  -- parses ordered list start and returns its length (inc following whitespace)-orderedListStart :: ListNumberStyle+orderedListStart :: Monad m => ListNumberStyle                  -> ListNumberDelim-                 -> RSTParser Int+                 -> RSTParser m Int orderedListStart style delim = try $ do   (_, markerLen) <- withHorizDisplacement (orderedListMarker style delim)   white <- many1 spaceChar   return $ markerLen + length white  -- parse a line of a list item-listLine :: Int -> RSTParser [Char]+listLine :: Monad m => Int -> RSTParser m [Char] listLine markerLength = try $ do   notFollowedBy blankline   indentWith markerLength-  line <- anyLine-  return $ line ++ "\n"---- indent by specified number of spaces (or equiv. tabs)-indentWith :: Int -> RSTParser [Char]-indentWith num = do-  tabStop <- getOption readerTabStop-  if (num < tabStop)-     then count num  (char ' ')-     else choice [ try (count num (char ' ')),-                   (try (char '\t' >> count (num - tabStop) (char ' '))) ]+  anyLineNewline  -- parse raw text for one list item, excluding start marker and continuations-rawListItem :: RSTParser Int-            -> RSTParser (Int, [Char])+rawListItem :: Monad m => RSTParser m Int+            -> RSTParser m (Int, [Char]) rawListItem start = try $ do   markerLength <- start-  firstLine <- anyLine+  firstLine <- anyLineNewline   restLines <- many (listLine markerLength)-  return (markerLength, (firstLine ++ "\n" ++ (concat restLines)))+  return (markerLength, firstLine ++ concat restLines)  -- continuation of a list item - indented and separated by blankline or -- (in compact lists) endline. -- Note: nested lists are parsed as continuations.-listContinuation :: Int -> RSTParser [Char]+listContinuation :: Monad m => Int -> RSTParser m [Char] listContinuation markerLength = try $ do   blanks <- many1 blankline   result <- many1 (listLine markerLength)   return $ blanks ++ concat result -listItem :: RSTParser Int-         -> RSTParser Blocks+listItem :: PandocMonad m+         => RSTParser m Int+         -> RSTParser m Blocks listItem start = try $ do   (markerLength, first) <- rawListItem start   rest <- many (listContinuation markerLength)-  blanks <- choice [ try (many blankline <* lookAhead start),-                     many1 blankline ]  -- whole list must end with blank.+  skipMany1 blankline <|> () <$ lookAhead start   -- parsing with ListItemState forces markers at beginning of lines to   -- count as list item markers, even if not separated by blank space.   -- see definition of "endline"@@ -481,52 +598,52 @@   let oldContext = stateParserContext state   setState $ state {stateParserContext = ListItemState}   -- parse the extracted block, which may itself contain block elements-  parsed <- parseFromString parseBlocks $ concat (first:rest) ++ blanks+  parsed <- parseFromString' parseBlocks $ concat (first:rest) ++ "\n"   updateState (\st -> st {stateParserContext = oldContext})   return $ case B.toList parsed of-                [Para xs] -> B.singleton $ Plain xs-                [Para xs, BulletList ys] -> B.fromList [Plain xs, BulletList ys]-                [Para xs, OrderedList s ys] -> B.fromList [Plain xs, OrderedList s ys]-                [Para xs, DefinitionList ys] -> B.fromList [Plain xs, DefinitionList ys]+                [Para xs] ->+                   B.singleton $ Plain xs+                [Para xs, BulletList ys] ->+                   B.fromList [Plain xs, BulletList ys]+                [Para xs, OrderedList s ys] ->+                   B.fromList [Plain xs, OrderedList s ys]+                [Para xs, DefinitionList ys] ->+                   B.fromList [Plain xs, DefinitionList ys]                 _         -> parsed -orderedList :: RSTParser Blocks+orderedList :: PandocMonad m => RSTParser m Blocks orderedList = try $ do   (start, style, delim) <- lookAhead (anyOrderedListMarker <* spaceChar)   items <- many1 (listItem (orderedListStart style delim))-  let items' = compactify' items+  let items' = compactify items   return $ B.orderedListWith (start, style, delim) items' -bulletList :: RSTParser Blocks-bulletList = B.bulletList . compactify' <$> many1 (listItem bulletListStart)+bulletList :: PandocMonad m => RSTParser m Blocks+bulletList = B.bulletList . compactify <$> many1 (listItem bulletListStart)  -- -- directive (e.g. comment, container, compound-paragraph) -- -comment :: RSTParser Blocks+comment :: Monad m => RSTParser m Blocks comment = try $ do   string ".."   skipMany1 spaceChar <|> (() <$ lookAhead newline)-  notFollowedBy' directiveLabel+  -- notFollowedBy' directiveLabel -- comment comes after directive so unnec.   manyTill anyChar blanklines   optional indentedBlock   return mempty -directiveLabel :: RSTParser String+directiveLabel :: Monad m => RSTParser m String directiveLabel = map toLower   <$> many1Till (letter <|> char '-') (try $ string "::") -directive :: RSTParser Blocks+directive :: PandocMonad m => RSTParser m Blocks directive = try $ do   string ".."   directive' --- TODO: line-block, parsed-literal, table, csv-table, list-table--- date--- include--- title-directive' :: RSTParser Blocks+directive' :: PandocMonad m => RSTParser m Blocks directive' = do   skipMany1 spaceChar   label <- directiveLabel@@ -541,43 +658,69 @@   body <- option "" $ try $ blanklines >> indentedBlock   optional blanklines   let body' = body ++ "\n\n"-      imgAttr cl = ("", classes, getAtt "width" ++ getAtt "height")+      imgAttr cl = ("", classes, widthAttr ++ heightAttr)         where-          classes = words $ maybe "" trim $ lookup cl fields-          getAtt k = case lookup k fields of-                       Just v  -> [(k, filter (not . isSpace) v)]-                       Nothing -> []+          classes = words $ maybe "" trim (lookup cl fields) +++                      maybe "" (\x -> "align-" ++ trim x)+                        (lookup "align" fields)+          scale = case trim <$> lookup "scale" fields of+                       Just v  -> case reverse v of+                                       '%':vv ->+                                         case safeRead (reverse vv) of+                                              Just (percent :: Double)+                                                      -> percent / 100.0+                                              Nothing -> 1.0+                                       _ ->+                                         case safeRead v of+                                              Just (s :: Double) -> s+                                              Nothing            -> 1.0+                       Nothing -> 1.0+          widthAttr = maybe [] (\x -> [("width",+                                        show $ scaleDimension scale x)])+                        $ lookup "width" fields >>=+                          (lengthToDim . filter (not . isSpace))+          heightAttr = maybe [] (\x -> [("height",+                                         show $ scaleDimension scale x)])+                        $ lookup "height" fields >>=+                          (lengthToDim . filter (not . isSpace))   case label of+        "include" -> includeDirective top fields body'+        "table" -> tableDirective top fields body'+        "list-table" -> listTableDirective top fields body'+        "csv-table" -> csvTableDirective top fields body'+        "line-block" -> lineBlockDirective body'         "raw" -> return $ B.rawBlock (trim top) (stripTrailingNewlines body)-        "role" -> addNewRole top $ map (\(k,v) -> (k, trim v)) fields-        "container" -> parseFromString parseBlocks body'+        "role" -> addNewRole top $ map (second trim) fields+        "container" -> parseFromString' parseBlocks body'         "replace" -> B.para <$>  -- consumed by substKey                    parseInlineFromString (trim top)         "unicode" -> B.para <$>  -- consumed by substKey                    parseInlineFromString (trim $ unicodeTransform top)-        "compound" -> parseFromString parseBlocks body'-        "pull-quote" -> B.blockQuote <$> parseFromString parseBlocks body'-        "epigraph" -> B.blockQuote <$> parseFromString parseBlocks body'-        "highlights" -> B.blockQuote <$> parseFromString parseBlocks body'+        "compound" -> parseFromString' parseBlocks body'+        "pull-quote" -> B.blockQuote <$> parseFromString' parseBlocks body'+        "epigraph" -> B.blockQuote <$> parseFromString' parseBlocks body'+        "highlights" -> B.blockQuote <$> parseFromString' parseBlocks body'         "rubric" -> B.para . B.strong <$> parseInlineFromString top         _ | label `elem` ["attention","caution","danger","error","hint",-                          "important","note","tip","warning"] ->-           do bod <- parseFromString parseBlocks $ top ++ "\n\n" ++ body'-              return $ B.divWith ("",["admonition", label],[]) bod-        "admonition" ->-           do bod <- parseFromString parseBlocks $ top ++ "\n\n" ++ body'-              return $ B.divWith ("",["admonition"],[]) bod+                          "important","note","tip","warning","admonition"] ->+           do bod <- parseFromString' parseBlocks $ top ++ "\n\n" ++ body'+              let lab = case label of+                             "admonition" -> mempty+                             (l:ls) -> B.divWith ("",["admonition-title"],[])+                                          (B.para (B.str (toUpper l : ls)))+                             [] -> mempty+              return $ B.divWith ("",[label],[]) (lab <> bod)         "sidebar" ->            do let subtit = maybe "" trim $ lookup "subtitle" fields               tit <- B.para . B.strong <$> parseInlineFromString                           (trim top ++ if null subtit                                           then ""                                           else (":  " ++ subtit))-              bod <- parseFromString parseBlocks body'+              bod <- parseFromString' parseBlocks body'               return $ B.divWith ("",["sidebar"],[]) $ tit <> bod         "topic" ->            do tit <- B.para . B.strong <$> parseInlineFromString top-              bod <- parseFromString parseBlocks body'+              bod <- parseFromString' parseBlocks body'               return $ B.divWith ("",["topic"],[]) $ tit <> bod         "default-role" -> mempty <$ updateState (\s ->                               s { stateRstDefaultRole =@@ -588,14 +731,15 @@           codeblock (words $ fromMaybe [] $ lookup "class" fields)                     (lookup "number-lines" fields) (trim top) body         "aafig" -> do-          let attribs = ("", ["aafig"], map (\(k,v) -> (k, trimr v)) fields)+          let attribs = ("", ["aafig"], map (second trimr) fields)           return $ B.codeBlockWith attribs $ stripTrailingNewlines body         "math" -> return $ B.para $ mconcat $ map B.displayMath                          $ toChunks $ top ++ "\n\n" ++ body         "figure" -> do-           (caption, legend) <- parseFromString extractCaption body'+           (caption, legend) <- parseFromString' extractCaption body'            let src = escapeURI $ trim top-           return $ B.para (B.imageWith (imgAttr "figclass") src "fig:" caption) <> legend+           return $ B.para (B.imageWith (imgAttr "figclass") src "fig:"+                       caption) <> legend         "image" -> do            let src = escapeURI $ trim top            let alt = B.str $ maybe "image" trim $ lookup "alt" fields@@ -606,28 +750,150 @@                                      $ B.imageWith attr src "" alt                           Nothing -> B.imageWith attr src "" alt         "class" -> do-            let attrs = ("", (splitBy isSpace $ trim top), map (\(k,v) -> (k, trimr v)) fields)+            let attrs = ("", splitBy isSpace $ trim top,+                              map (second trimr) fields)             --  directive content or the first immediately following element             children <- case body of                 "" -> block-                _ -> parseFromString parseBlocks  body'+                _  -> parseFromString' parseBlocks  body'             return $ B.divWith attrs children         other     -> do             pos <- getPosition-            addWarning (Just pos) $ "ignoring unknown directive: " ++ other-            return mempty+            logMessage $ SkippedContent (".. " ++ other) pos+            bod <- parseFromString' parseBlocks $ top ++ "\n\n" ++ body'+            return $ B.divWith ("",[other],[]) bod +tableDirective :: PandocMonad m+               => String -> [(String, String)] -> String -> RSTParser m Blocks+tableDirective top fields body = do+  bs <- parseFromString' parseBlocks body+  case B.toList bs of+       [Table _ aligns' widths' header' rows'] -> do+         title <- parseFromString' (trimInlines . mconcat <$> many inline) top+         columns <- getOption readerColumns+         let numOfCols = length header'+         let normWidths ws =+                map (/ max 1.0 (fromIntegral (columns - numOfCols))) ws+         let widths = case trim <$> lookup "widths" fields of+                           Just "auto" -> replicate numOfCols 0.0+                           Just "grid" -> widths'+                           Just specs -> normWidths+                               $ map (fromMaybe (0 :: Double) . safeRead)+                               $ splitBy (`elem` (" ," :: String)) specs+                           Nothing -> widths'+         -- align is not applicable since we can't represent whole table align+         return $ B.singleton $ Table (B.toList title)+                                  aligns' widths header' rows'+       _ -> return mempty+++-- TODO: :stub-columns:.+-- Only the first row becomes the header even if header-rows: > 1,+-- since Pandoc doesn't support a table with multiple header rows.+-- We don't need to parse :align: as it represents the whole table align.+listTableDirective :: PandocMonad m+                   => String -> [(String, String)] -> String+                   -> RSTParser m Blocks+listTableDirective top fields body = do+  bs <- parseFromString' parseBlocks body+  title <- parseFromString' (trimInlines . mconcat <$> many inline) top+  let rows = takeRows $ B.toList bs+      headerRowsNum = fromMaybe (0 :: Int) $+         lookup "header-rows" fields >>= safeRead+      (headerRow,bodyRows,numOfCols) = case rows of+        x:xs -> if headerRowsNum > 0+                   then (x, xs, length x)+                   else ([], rows, length x)+        _ -> ([],[],0)+      widths = case trim <$> lookup "widths" fields of+        Just "auto" -> replicate numOfCols 0+        Just specs -> normWidths $ map (fromMaybe (0 :: Double) . safeRead) $+                           splitBy (`elem` (" ," :: String)) specs+        _ -> replicate numOfCols 0+  return $ B.table title+             (zip (replicate numOfCols AlignDefault) widths)+             headerRow+             bodyRows+    where takeRows [BulletList rows] = map takeCells rows+          takeRows _                 = []+          takeCells [BulletList cells] = map B.fromList cells+          takeCells _                  = []+          normWidths ws = map (/ max 1 (sum ws)) ws++csvTableDirective :: PandocMonad m+                   => String -> [(String, String)] -> String+                   -> RSTParser m Blocks+csvTableDirective top fields rawcsv = do+  let explicitHeader = trim <$> lookup "header" fields+  let opts = defaultCSVOptions{+                csvDelim = case trim <$> lookup "delim" fields of+                                Just "tab"   -> '\t'+                                Just "space" -> ' '+                                Just [c]     -> c+                                _            -> ','+              , csvQuote = case trim <$> lookup "quote" fields of+                                Just [c] -> c+                                _        -> '"'+              , csvEscape = case trim <$> lookup "escape" fields of+                                Just [c] -> Just c+                                _        -> Nothing+              , csvKeepSpace = case trim <$> lookup "keepspace" fields of+                                       Just "true" -> True+                                       _           -> False+              }+  let headerRowsNum = fromMaybe (case explicitHeader of+                                       Just _  -> 1 :: Int+                                       Nothing -> 0 :: Int) $+           lookup "header-rows" fields >>= safeRead+  rawcsv' <- case trim <$>+                    lookup "file" fields `mplus` lookup "url" fields of+                  Just u  -> do+                    (bs, _) <- fetchItem u+                    return $ UTF8.toString bs+                  Nothing -> return rawcsv+  let res = parseCSV opts (T.pack $ case explicitHeader of+                                         Just h  -> h ++ "\n" ++ rawcsv'+                                         Nothing -> rawcsv')+  case res of+       Left e  ->+         throwError $ PandocParsecError "csv table" e+       Right rawrows -> do+         let parseCell = parseFromString' (plain <|> return mempty) . T.unpack+         let parseRow = mapM parseCell+         rows <- mapM parseRow rawrows+         let (headerRow,bodyRows,numOfCols) =+              case rows of+                   x:xs -> if headerRowsNum > 0+                          then (x, xs, length x)+                          else ([], rows, length x)+                   _ -> ([],[],0)+         title <- parseFromString' (trimInlines . mconcat <$> many inline) top+         let normWidths ws = map (/ max 1 (sum ws)) ws+         let widths =+               case trim <$> lookup "widths" fields of+                 Just "auto" -> replicate numOfCols 0+                 Just specs -> normWidths+                               $ map (fromMaybe (0 :: Double) . safeRead)+                               $ splitBy (`elem` (" ," :: String)) specs+                 _ -> replicate numOfCols 0+         return $ B.table title+                  (zip (replicate numOfCols AlignDefault) widths)+                  headerRow+                  bodyRows+ -- TODO: --  - Only supports :format: fields with a single format for :raw: roles, --    change Text.Pandoc.Definition.Format to fix-addNewRole :: String -> [(String, String)] -> RSTParser Blocks+addNewRole :: PandocMonad m+           => String -> [(String, String)] -> RSTParser m Blocks addNewRole roleString fields = do-    (role, parentRole) <- parseFromString inheritedRole roleString+    pos <- getPosition+    (role, parentRole) <- parseFromString' inheritedRole roleString     customRoles <- stateRstCustomRoles <$> getState     let getBaseRole (r, f, a) roles =             case M.lookup r roles of                  Just (r', f', a') -> getBaseRole (r', f', a') roles-                 Nothing -> (r, f, a)+                 Nothing           -> (r, f, a)         (baseRole, baseFmt, baseAttr) =                getBaseRole (parentRole, Nothing, nullAttr) customRoles         fmt = if parentRole == "raw" then lookup "format" fields else baseFmt@@ -641,34 +907,32 @@                in (ident, nub . (role :) . annotate $ classes, keyValues)      -- warn about syntax we ignore-    flip mapM_ fields $ \(key, _) -> case key of-        "language" -> when (baseRole /= "code") $ addWarning Nothing $-            "ignoring :language: field because the parent of role :" ++-            role ++ ": is :" ++ baseRole ++ ": not :code:"-        "format" -> when (baseRole /= "raw") $ addWarning Nothing $-            "ignoring :format: field because the parent of role :" ++-            role ++ ": is :" ++ baseRole ++ ": not :raw:"-        _ -> addWarning Nothing $ "ignoring unknown field :" ++ key ++-             ": in definition of role :" ++ role ++ ": in"+    forM_ fields $ \(key, _) -> case key of+                 "language" -> when (baseRole /= "code") $ logMessage $+                     SkippedContent ":language: [because parent of role is not :code:]"+                        pos+                 "format" -> when (baseRole /= "raw") $ logMessage $+                     SkippedContent ":format: [because parent of role is not :raw:]" pos+                 _ -> logMessage $ SkippedContent (":" ++ key ++ ":") pos     when (parentRole == "raw" && countKeys "format" > 1) $-        addWarning Nothing $-        "ignoring :format: fields after the first in the definition of role :"-        ++ role ++": in"+        logMessage $ SkippedContent+                  ":format: [after first in definition of role]"+                  pos     when (parentRole == "code" && countKeys "language" > 1) $-        addWarning Nothing $-        "ignoring :language: fields after the first in the definition of role :"-        ++ role ++": in"+        logMessage $ SkippedContent+          ":language: [after first in definition of role]" pos      updateState $ \s -> s {         stateRstCustomRoles =           M.insert role (baseRole, fmt, attr) customRoles     } -    return $ B.singleton Null+    return mempty   where     countKeys k = length . filter (== k) . map fst $ fields     inheritedRole =-        (,) <$> roleName <*> ((char '(' *> roleName <* char ')') <|> pure "span")+        (,) <$> roleName <*> ((char '(' *> roleName <* char ')')+                            <|> pure "span")   -- Can contain character codes as decimal numbers or@@ -700,7 +964,7 @@   where (ds,rest) = span isHexDigit s         mbc = safeRead ('\'':'\\':'x':ds ++ "'") -extractCaption :: RSTParser (Inlines, Blocks)+extractCaption :: PandocMonad m => RSTParser m (Inlines, Blocks) extractCaption = do   capt <- trimInlines . mconcat <$> many inline   legend <- optional blanklines >> (mconcat <$> many block)@@ -712,12 +976,12 @@            . map (trim . unlines)            . splitBy (all (`elem` (" \t" :: String))) . lines -codeblock :: [String] -> Maybe String -> String -> String -> RSTParser Blocks+codeblock :: [String] -> Maybe String -> String -> String -> RSTParser m Blocks codeblock classes numberLines lang body =   return $ B.codeBlockWith attribs $ stripTrailingNewlines body     where attribs = ("", classes', kvs)           classes' = "sourceCode" : lang-                    : maybe [] (\_ -> ["numberLines"]) numberLines+                    : maybe [] (const ["numberLines"]) numberLines                     ++ classes           kvs     = case numberLines of                           Just "" -> []@@ -728,30 +992,52 @@ --- note block --- -noteBlock :: RSTParser [Char]+noteBlock :: Monad m => RSTParser m [Char] noteBlock = try $ do+  (ref, raw, replacement) <- noteBlock' noteMarker+  updateState $ \s -> s { stateNotes = (ref, raw) : stateNotes s }+  -- return blanks so line count isn't affected+  return replacement++citationBlock :: Monad m => RSTParser m [Char]+citationBlock = try $ do+  (ref, raw, replacement) <- noteBlock' citationMarker+  updateState $ \s ->+     s { stateCitations = M.insert ref raw (stateCitations s),+         stateKeys = M.insert (toKey ref) (('#':ref,""), ("",["citation"],[]))+                               (stateKeys s) }+  -- return blanks so line count isn't affected+  return replacement++noteBlock' :: Monad m+           => RSTParser m String -> RSTParser m (String, String, String)+noteBlock' marker = try $ do   startPos <- getPosition   string ".."   spaceChar >> skipMany spaceChar-  ref <- noteMarker+  ref <- marker   first <- (spaceChar >> skipMany spaceChar >> anyLine)         <|> (newline >> return "")   blanks <- option "" blanklines   rest <- option "" indentedBlock   endPos <- getPosition   let raw = first ++ "\n" ++ blanks ++ rest ++ "\n"-  let newnote = (ref, raw)-  st <- getState-  let oldnotes = stateNotes st-  updateState $ \s -> s { stateNotes = newnote : oldnotes }-  -- return blanks so line count isn't affected-  return $ replicate (sourceLine endPos - sourceLine startPos) '\n'+  let replacement =replicate (sourceLine endPos - sourceLine startPos) '\n'+  return (ref, raw, replacement) -noteMarker :: RSTParser [Char]+citationMarker :: Monad m => RSTParser m [Char]+citationMarker = do+  char '['+  res <- simpleReferenceName'+  char ']'+  return res++noteMarker :: Monad m => RSTParser m [Char] noteMarker = do   char '['   res <- many1 digit-      <|> (try $ char '#' >> liftM ('#':) simpleReferenceName')+      <|>+                  try (char '#' >> liftM ('#':) simpleReferenceName')       <|> count 1 (oneOf "#*")   char ']'   return res@@ -760,39 +1046,36 @@ -- reference key -- -quotedReferenceName :: RSTParser Inlines+quotedReferenceName :: PandocMonad m => RSTParser m Inlines quotedReferenceName = try $ do   char '`' >> notFollowedBy (char '`') -- `` means inline code!-  label' <- trimInlines . mconcat <$> many1Till inline (char '`')-  return label'+  trimInlines . mconcat <$> many1Till inline (char '`') -unquotedReferenceName :: RSTParser Inlines-unquotedReferenceName = try $ do-  label' <- trimInlines . mconcat <$> many1Till inline (lookAhead $ char ':')-  return label'+unquotedReferenceName :: PandocMonad m => RSTParser m Inlines+unquotedReferenceName = try $ do -- `` means inline code!+  trimInlines . mconcat <$> many1Till inline (lookAhead $ char ':')  -- Simple reference names are single words consisting of alphanumerics -- plus isolated (no two adjacent) internal hyphens, underscores, -- periods, colons and plus signs; no whitespace or other characters -- are allowed.-simpleReferenceName' :: Parser [Char] st String+simpleReferenceName' :: Monad m => ParserT [Char] st m String simpleReferenceName' = do   x <- alphaNum   xs <- many $  alphaNum-            <|> (try $ oneOf "-_:+." <* lookAhead alphaNum)+            <|>+                  try (oneOf "-_:+." <* lookAhead alphaNum)   return (x:xs) -simpleReferenceName :: Parser [Char] st Inlines-simpleReferenceName = do-  raw <- simpleReferenceName'-  return $ B.str raw+simpleReferenceName :: Monad m => ParserT [Char] st m Inlines+simpleReferenceName = B.str <$> simpleReferenceName' -referenceName :: RSTParser Inlines+referenceName :: PandocMonad m => RSTParser m Inlines referenceName = quotedReferenceName <|>-                (try $ simpleReferenceName <* lookAhead (char ':')) <|>+                try (simpleReferenceName <* lookAhead (char ':')) <|>                 unquotedReferenceName -referenceKey :: RSTParser [Char]+referenceKey :: PandocMonad m => RSTParser m [Char] referenceKey = do   startPos <- getPosition   choice [substKey, anonymousKey, regularKey]@@ -801,16 +1084,16 @@   -- return enough blanks to replace key   return $ replicate (sourceLine endPos - sourceLine startPos) '\n' -targetURI :: Parser [Char] st [Char]+targetURI :: Monad m => ParserT [Char] st m [Char] targetURI = do   skipSpaces   optional newline   contents <- many1 (try (many spaceChar >> newline >>                           many1 spaceChar >> noneOf " \t\n") <|> noneOf "\n")   blanklines-  return $ escapeURI $ trim $ contents+  return $ escapeURI $ trim contents -substKey :: RSTParser ()+substKey :: PandocMonad m => RSTParser m () substKey = try $ do   string ".."   skipMany1 spaceChar@@ -826,32 +1109,76 @@              [Para ils] -> return $ B.fromList ils              _          -> mzero   let key = toKey $ stripFirstAndLast ref-  updateState $ \s -> s{ stateSubstitutions = M.insert key il $ stateSubstitutions s }+  updateState $ \s -> s{ stateSubstitutions =+                          M.insert key il $ stateSubstitutions s } -anonymousKey :: RSTParser ()+anonymousKey :: Monad m => RSTParser m () anonymousKey = try $ do   oneOfStrings [".. __:", "__"]   src <- targetURI   pos <- getPosition   let key = toKey $ "_" ++ printf "%09d" (sourceLine pos)-  --TODO: parse width, height, class and name attributes-  updateState $ \s -> s { stateKeys = M.insert key ((src,""), nullAttr) $ stateKeys s }+  updateState $ \s -> s { stateKeys = M.insert key ((src,""), nullAttr) $+                          stateKeys s }  stripTicks :: String -> String stripTicks = reverse . stripTick . reverse . stripTick   where stripTick ('`':xs) = xs-        stripTick xs = xs+        stripTick xs       = xs -regularKey :: RSTParser ()+referenceNames :: PandocMonad m => RSTParser m [String]+referenceNames = do+  let rn = try $ do+             string ".. _"+             (_, ref) <- withRaw referenceName+             char ':'+             return ref+  first <- rn+  rest  <- many (try (blanklines *> rn))+  return (first:rest)++regularKey :: PandocMonad m => RSTParser m () regularKey = try $ do-  string ".. _"-  (_,ref) <- withRaw referenceName-  char ':'+  -- we allow several references to the same URL, e.g.+  -- .. _hello:+  -- .. _goodbye: url.com+  refs <- referenceNames   src <- targetURI-  let key = toKey $ stripTicks ref-  --TODO: parse width, height, class and name attributes-  updateState $ \s -> s { stateKeys = M.insert key ((src,""), nullAttr) $ stateKeys s }+  guard $ not (null src)+  let keys = map (toKey . stripTicks) refs+  forM_ keys $ \key ->+    updateState $ \s -> s { stateKeys = M.insert key ((src,""), nullAttr) $+                            stateKeys s } +anchorDef :: PandocMonad m => RSTParser m [Char]+anchorDef = try $ do+  (refs, raw) <- withRaw (try (referenceNames <* blanklines))+  let keys = map stripTicks refs+  forM_ keys $ \rawkey ->+    updateState $ \s -> s { stateKeys =+       M.insert (toKey rawkey) (('#':rawkey,""), nullAttr) $ stateKeys s }+  -- keep this for 2nd round of parsing, where we'll add the divs (anchor)+  return raw++anchor :: PandocMonad m => RSTParser m Blocks+anchor = try $ do+  refs <- referenceNames+  blanklines+  b <- block+  -- put identifier on next block:+  let addDiv ref = B.divWith (ref, [], [])+  return $ foldr addDiv b refs++headerBlock :: PandocMonad m => RSTParser m [Char]+headerBlock = do+  ((txt, _), raw) <- withRaw (doubleHeader' <|> singleHeader')+  (ident,_,_) <- registerHeader nullAttr txt+  let key = toKey (stringify txt)+  updateState $ \s -> s { stateKeys = M.insert key (('#':ident,""), nullAttr)+                          $ stateKeys s }+  return raw++ -- -- tables --@@ -869,45 +1196,53 @@ -- Grid tables TODO: --  - column spans -dashedLine :: Char -> Parser [Char] st (Int, Int)+dashedLine :: Monad m => Char -> ParserT [Char] st m (Int, Int) dashedLine ch = do   dashes <- many1 (char ch)   sp     <- many (char ' ')   return (length dashes, length $ dashes ++ sp) -simpleDashedLines :: Char -> Parser [Char] st [(Int,Int)]+simpleDashedLines :: Monad m => Char -> ParserT [Char] st m [(Int,Int)] simpleDashedLines ch = try $ many1 (dashedLine ch)  -- Parse a table row separator-simpleTableSep :: Char -> RSTParser Char+simpleTableSep :: Monad m => Char -> RSTParser m Char simpleTableSep ch = try $ simpleDashedLines ch >> newline  -- Parse a table footer-simpleTableFooter :: RSTParser [Char]+simpleTableFooter :: Monad m => RSTParser m [Char] simpleTableFooter = try $ simpleTableSep '=' >> blanklines  -- Parse a raw line and split it into chunks by indices.-simpleTableRawLine :: [Int] -> RSTParser [String]-simpleTableRawLine indices = do-  line <- many1Till anyChar newline-  return (simpleTableSplitLine indices line)+simpleTableRawLine :: Monad m => [Int] -> RSTParser m [String]+simpleTableRawLine indices = simpleTableSplitLine indices <$> anyLine +simpleTableRawLineWithEmptyCell :: Monad m => [Int] -> RSTParser m [String]+simpleTableRawLineWithEmptyCell indices = try $ do+  cs <- simpleTableRawLine indices+  let isEmptyCell = all (\c -> c == ' ' || c == '\t')+  guard $ any isEmptyCell cs+  return cs+ -- Parse a table row and return a list of blocks (columns).-simpleTableRow :: [Int] -> RSTParser [[Block]]+simpleTableRow :: PandocMonad m => [Int] -> RSTParser m [Blocks] simpleTableRow indices = do   notFollowedBy' simpleTableFooter   firstLine <- simpleTableRawLine indices-  colLines  <- return [] -- TODO-  let cols = map unlines . transpose $ firstLine : colLines-  mapM (parseFromString (B.toList . mconcat <$> many plain)) cols+  conLines  <- many $ simpleTableRawLineWithEmptyCell indices+  let cols = map unlines . transpose $ firstLine : conLines +++                                 [replicate (length indices) ""+                                   | not (null conLines)]+  mapM (parseFromString' parseBlocks) cols  simpleTableSplitLine :: [Int] -> String -> [String] simpleTableSplitLine indices line =-  map trim+  map trimr   $ tail $ splitByIndices (init indices) line -simpleTableHeader :: Bool  -- ^ Headerless table-                  -> RSTParser ([[Block]], [Alignment], [Int])+simpleTableHeader :: PandocMonad m+                  => Bool  -- ^ Headerless table+                  -> RSTParser m ([Blocks], [Alignment], [Int]) simpleTableHeader headless = try $ do   optional blanklines   rawContent  <- if headless@@ -921,26 +1256,37 @@   let rawHeads = if headless                     then replicate (length dashes) ""                     else simpleTableSplitLine indices rawContent-  heads <- mapM (parseFromString (B.toList . mconcat <$> many plain)) $-             map trim rawHeads+  heads <- mapM ( (parseFromString' (mconcat <$> many plain)) . trim) rawHeads   return (heads, aligns, indices)  -- Parse a simple table.-simpleTable :: Bool  -- ^ Headerless table-            -> RSTParser Blocks+simpleTable :: PandocMonad m+            => Bool  -- ^ Headerless table+            -> RSTParser m Blocks simpleTable headless = do-  Table c a _w h l <- tableWith (simpleTableHeader headless) simpleTableRow sep simpleTableFooter+  let wrapIdFst (a, b, c) = (Identity a, b, c)+      wrapId = fmap Identity+  tbl <- runIdentity <$> tableWith+           (wrapIdFst <$> simpleTableHeader headless)+           (wrapId <$> simpleTableRow)+           sep simpleTableFooter   -- Simple tables get 0s for relative column widths (i.e., use default)-  return $ B.singleton $ Table c a (replicate (length a) 0) h l+  case B.toList tbl of+       [Table c a _w h l]  -> return $ B.singleton $+                                 Table c a (replicate (length a) 0) h l+       _ ->+         throwError $ PandocShouldNeverHappenError+            "tableWith returned something unexpected"  where   sep = return () -- optional (simpleTableSep '-') -gridTable :: Bool -- ^ Headerless table-          -> RSTParser Blocks-gridTable headerless = B.singleton-  <$> gridTableWith (B.toList <$> parseBlocks) headerless+gridTable :: PandocMonad m+          => Bool -- ^ Headerless table+          -> RSTParser m Blocks+gridTable headerless = runIdentity <$>+  gridTableWith (Identity <$> parseBlocks) headerless -table :: RSTParser Blocks+table :: PandocMonad m => RSTParser m Blocks table = gridTable False <|> simpleTable False <|>         gridTable True  <|> simpleTable True <?> "table" @@ -948,7 +1294,7 @@ -- inline -- -inline :: RSTParser Inlines+inline :: PandocMonad m => RSTParser m Inlines inline = choice [ note          -- can start with whitespace, so try before ws                 , whitespace                 , link@@ -964,29 +1310,30 @@                 , escapedChar                 , symbol ] <?> "inline" -parseInlineFromString :: String -> RSTParser Inlines-parseInlineFromString = parseFromString (trimInlines . mconcat <$> many inline)+parseInlineFromString :: PandocMonad m => String -> RSTParser m Inlines+parseInlineFromString = parseFromString' (trimInlines . mconcat <$> many inline) -hyphens :: RSTParser Inlines+hyphens :: Monad m => RSTParser m Inlines hyphens = do   result <- many1 (char '-')   optional endline   -- don't want to treat endline after hyphen or dash as a space   return $ B.str result -escapedChar :: Parser [Char] st Inlines+escapedChar :: Monad m => ParserT [Char] st m Inlines escapedChar = do c <- escaped anyChar-                 return $ if c == ' '  -- '\ ' is null in RST+                 return $ if c == ' ' || c == '\n' || c == '\r'+                             -- '\ ' is null in RST                              then mempty                              else B.str [c] -symbol :: RSTParser Inlines+symbol :: Monad m => RSTParser m Inlines symbol = do   result <- oneOf specialChars   return $ B.str [result]  -- parses inline code, between codeStart and codeEnd-code :: RSTParser Inlines+code :: Monad m => RSTParser m Inlines code = try $ do   string "``"   result <- manyTill anyChar (try (string "``"))@@ -994,7 +1341,7 @@          $ trim $ unwords $ lines result  -- succeeds only if we're not right after a str (ie. in middle of word)-atStart :: RSTParser a -> RSTParser a+atStart :: Monad m => RSTParser m a -> RSTParser m a atStart p = do   pos <- getPosition   st <- getState@@ -1002,11 +1349,11 @@   guard $ stateLastStrPos st /= Just pos   p -emph :: RSTParser Inlines+emph :: PandocMonad m => RSTParser m Inlines emph = B.emph . trimInlines . mconcat <$>          enclosed (atStart $ char '*') (char '*') inline -strong :: RSTParser Inlines+strong :: PandocMonad m => RSTParser m Inlines strong = B.strong . trimInlines . mconcat <$>           enclosed (atStart $ string "**") (try $ string "**") inline @@ -1018,12 +1365,13 @@ --  - Classes are silently discarded in addNewRole --  - Lacks sensible implementation for title-reference (which is the default) --  - Allows direct use of the :raw: role, rST only allows inherited use.-interpretedRole :: RSTParser Inlines+interpretedRole :: PandocMonad m => RSTParser m Inlines interpretedRole = try $ do   (role, contents) <- roleBefore <|> roleAfter   renderRole contents Nothing role nullAttr -renderRole :: String -> Maybe String -> String -> Attr -> RSTParser Inlines+renderRole :: PandocMonad m+           => String -> Maybe String -> String -> Attr -> RSTParser m Inlines renderRole contents fmt role attr = case role of     "sup"  -> return $ B.superscript $ B.str contents     "superscript" -> return $ B.superscript $ B.str contents@@ -1048,10 +1396,8 @@         case M.lookup custom customRoles of             Just (newRole, newFmt, newAttr) ->                 renderRole contents newFmt newRole newAttr-            Nothing -> do-                pos <- getPosition-                addWarning (Just pos) $ "ignoring unknown role :" ++ custom ++ ": in"-                return $ B.str contents -- Undefined role+            Nothing -> -- undefined role+                return $ B.spanWith ("",[],[("role",role)]) (B.str contents)  where    titleRef ref = return $ B.str ref -- FIXME: Not a sensible behaviour    rfcLink rfcNo = B.link rfcUrl ("RFC " ++ rfcNo) $ B.str ("RFC " ++ rfcNo)@@ -1063,31 +1409,31 @@ addClass :: String -> Attr -> Attr addClass c (ident, classes, keyValues) = (ident, union classes [c], keyValues) -roleName :: RSTParser String+roleName :: PandocMonad m => RSTParser m String roleName = many1 (letter <|> char '-') -roleMarker :: RSTParser String+roleMarker :: PandocMonad m => RSTParser m String roleMarker = char ':' *> roleName <* char ':' -roleBefore :: RSTParser (String,String)+roleBefore :: PandocMonad m => RSTParser m (String,String) roleBefore = try $ do   role <- roleMarker   contents <- unmarkedInterpretedText   return (role,contents) -roleAfter :: RSTParser (String,String)+roleAfter :: PandocMonad m => RSTParser m (String,String) roleAfter = try $ do   contents <- unmarkedInterpretedText   role <- roleMarker <|> (stateRstDefaultRole <$> getState)   return (role,contents) -unmarkedInterpretedText :: RSTParser [Char]+unmarkedInterpretedText :: PandocMonad m => RSTParser m [Char] unmarkedInterpretedText = enclosed (atStart $ char '`') (char '`') anyChar -whitespace :: RSTParser Inlines+whitespace :: PandocMonad m => RSTParser m Inlines whitespace = B.space <$ skipMany1 spaceChar <?> "whitespace" -str :: RSTParser Inlines+str :: Monad m => RSTParser m Inlines str = do   let strChar = noneOf ("\t\n " ++ specialChars)   result <- many1 strChar@@ -1095,26 +1441,24 @@   return $ B.str result  -- an endline character that can be treated as a space, not a structural break-endline :: RSTParser Inlines+endline :: Monad m => RSTParser m Inlines endline = try $ do   newline   notFollowedBy blankline   -- parse potential list-starts at beginning of line differently in a list:   st <- getState-  if (stateParserContext st) == ListItemState-     then notFollowedBy (anyOrderedListMarker >> spaceChar) >>+  when ((stateParserContext st) == ListItemState) $ notFollowedBy (anyOrderedListMarker >> spaceChar) >>           notFollowedBy' bulletListStart-     else return ()   return B.softbreak  -- -- links -- -link :: RSTParser Inlines+link :: PandocMonad m => RSTParser m Inlines link = choice [explicitLink, referenceLink, autoLink]  <?> "link" -explicitLink :: RSTParser Inlines+explicitLink :: PandocMonad m => RSTParser m Inlines explicitLink = try $ do   char '`'   notFollowedBy (char '`') -- `` marks start of inline code@@ -1128,61 +1472,75 @@                    then B.str src                    else label'   -- `link <google_>` is a reference link to _google!-  (src',tit,attr) <- case reverse src of-                          '_':xs -> do-                            keyTable <- stateKeys <$> getState-                            let key = toKey $ reverse xs-                            case M.lookup key keyTable of-                                 Nothing -> do-                                   pos <- getPosition-                                   addWarning (Just pos) $-                                     "Could not find reference for " ++-                                       show key-                                   return ("","",nullAttr)-                                 Just ((s,t),a) -> return (s,t,a)-                          _ -> return (src, "", nullAttr)+  ((src',tit),attr) <- case reverse src of+                          '_':xs -> lookupKey [] (toKey (reverse xs))+                          _      -> return ((src, ""), nullAttr)   return $ B.linkWith attr (escapeURI src') tit label'' -referenceLink :: RSTParser Inlines+citationName :: PandocMonad m => RSTParser m Inlines+citationName = do+  raw <- citationMarker+  return $ B.str $ "[" ++ raw ++ "]"++referenceLink :: PandocMonad m => RSTParser m Inlines referenceLink = try $ do-  (label',ref) <- withRaw (quotedReferenceName <|> simpleReferenceName) <*+  (label',ref) <- withRaw (quotedReferenceName+                          <|> simpleReferenceName+                          <|> citationName) <*                    char '_'-  state <- getState-  let keyTable = stateKeys state   let isAnonKey (Key ('_':_)) = True       isAnonKey _             = False+  state <- getState+  let keyTable = stateKeys state   key <- option (toKey $ stripTicks ref) $                 do char '_'                    let anonKeys = sort $ filter isAnonKey $ M.keys keyTable-                   if null anonKeys-                      then mzero-                      else return (head anonKeys)-  ((src,tit), attr) <- case M.lookup key keyTable of-                         Nothing  -> do-                           pos <- getPosition-                           addWarning (Just pos) $-                             "Could not find reference for " ++-                               show key-                           return (("",""),nullAttr)-                         Just val -> return val+                   case anonKeys of+                        []    -> mzero+                        (k:_) -> return k+  ((src,tit), attr) <- lookupKey [] key   -- if anonymous link, remove key so it won't be used again-  when (isAnonKey key) $ updateState $ \s -> s{ stateKeys = M.delete key keyTable }+  when (isAnonKey key) $ updateState $ \s ->+                          s{ stateKeys = M.delete key keyTable }   return $ B.linkWith attr src tit label' -autoURI :: RSTParser Inlines+-- We keep a list of oldkeys so we can detect lookup loops.+lookupKey :: PandocMonad m+          => [Key] -> Key -> RSTParser m ((String, String), Attr)+lookupKey oldkeys key = do+  pos <- getPosition+  state <- getState+  let keyTable = stateKeys state+  case M.lookup key keyTable of+       Nothing  -> do+         let Key key' = key+         logMessage $ ReferenceNotFound key' pos+         return (("",""),nullAttr)+       -- check for keys of the form link_, which need to be resolved:+       Just ((u@(_:_),""),_) | last u == '_' -> do+         let rawkey = init u+         let newkey = toKey rawkey+         if newkey `elem` oldkeys+            then do+              logMessage $ CircularReference rawkey pos+              return (("",""),nullAttr)+            else lookupKey (key:oldkeys) newkey+       Just val -> return val++autoURI :: Monad m => RSTParser m Inlines autoURI = do   (orig, src) <- uri   return $ B.link src "" $ B.str orig -autoEmail :: RSTParser Inlines+autoEmail :: Monad m => RSTParser m Inlines autoEmail = do   (orig, src) <- emailAddress   return $ B.link src "" $ B.str orig -autoLink :: RSTParser Inlines+autoLink :: PandocMonad m => RSTParser m Inlines autoLink = autoURI <|> autoEmail -subst :: RSTParser Inlines+subst :: PandocMonad m => RSTParser m Inlines subst = try $ do   (_,ref) <- withRaw $ enclosed (char '|') (char '|') inline   state <- getState@@ -1191,12 +1549,11 @@   case M.lookup key substTable of        Nothing     -> do          pos <- getPosition-         addWarning (Just pos) $-           "Could not find reference for " ++ show key+         logMessage $ ReferenceNotFound (show key) pos          return mempty        Just target -> return target -note :: RSTParser Inlines+note :: PandocMonad m => RSTParser m Inlines note = try $ do   optional whitespace   ref <- noteMarker@@ -1206,8 +1563,7 @@   case lookup ref notes of     Nothing   -> do       pos <- getPosition-      addWarning (Just pos) $-        "Could not find note for " ++ show ref+      logMessage $ ReferenceNotFound ref pos       return mempty     Just raw  -> do       -- We temporarily empty the note list while parsing the note,@@ -1215,7 +1571,7 @@       -- Note references inside other notes are allowed in reST, but       -- not yet in this implementation.       updateState $ \st -> st{ stateNotes = [] }-      contents <- parseFromString parseBlocks raw+      contents <- parseFromString' parseBlocks raw       let newnotes = if (ref == "*" || ref == "#") -- auto-numbered                         -- delete the note so the next auto-numbered note                         -- doesn't get the same contents:@@ -1224,20 +1580,20 @@       updateState $ \st -> st{ stateNotes = newnotes }       return $ B.note contents -smart :: RSTParser Inlines+smart :: PandocMonad m => RSTParser m Inlines smart = do-  getOption readerSmart >>= guard+  guardEnabled Ext_smart   doubleQuoted <|> singleQuoted <|>     choice [apostrophe, dash, ellipses] -singleQuoted :: RSTParser Inlines+singleQuoted :: PandocMonad m => RSTParser m Inlines singleQuoted = try $ do   singleQuoteStart   withQuoteContext InSingleQuote $     B.singleQuoted . trimInlines . mconcat <$>       many1Till inline singleQuoteEnd -doubleQuoted :: RSTParser Inlines+doubleQuoted :: PandocMonad m => RSTParser m Inlines doubleQuoted = try $ do   doubleQuoteStart   withQuoteContext InDoubleQuote $
src/Text/Pandoc/Readers/TWiki.hs view
@@ -1,4 +1,7 @@-{-# LANGUAGE RelaxedPolyRec, FlexibleInstances, TypeSynonymInstances, FlexibleContexts #-}+{-# LANGUAGE FlexibleContexts     #-}+{-# LANGUAGE FlexibleInstances    #-}+{-# LANGUAGE RelaxedPolyRec       #-}+{-# LANGUAGE TypeSynonymInstances #-} -- RelaxedPolyRec needed for inlinesBetween on GHC < 7 {-   Copyright (C) 2014 Alexander Sulfrian <alexander.sulfrian@fu-berlin.de>@@ -30,54 +33,50 @@ Conversion of twiki text to 'Pandoc' document. -} module Text.Pandoc.Readers.TWiki ( readTWiki-                                 , readTWikiWithWarnings                                  ) where -import Text.Pandoc.Definition+import Control.Monad+import Control.Monad.Except (throwError)+import Data.Char (isAlphaNum)+import qualified Data.Foldable as F+import Data.Maybe (fromMaybe)+import Data.Text (Text)+import qualified Data.Text as T+import Text.HTML.TagSoup import qualified Text.Pandoc.Builder as B+import Text.Pandoc.Class (PandocMonad (..))+import Text.Pandoc.Definition import Text.Pandoc.Options-import Text.Pandoc.Parsing hiding (enclosed, macro, nested)+import Text.Pandoc.Parsing hiding (enclosed, nested) import Text.Pandoc.Readers.HTML (htmlTag, isCommentTag)-import Control.Monad-import Text.Printf (printf)-import Debug.Trace (trace)+import Text.Pandoc.Shared (crFilter) import Text.Pandoc.XML (fromEntities)-import Data.Maybe (fromMaybe)-import Text.HTML.TagSoup-import Data.Char (isAlphaNum)-import qualified Data.Foldable as F-import Text.Pandoc.Error  -- | Read twiki from an input string and return a Pandoc document.-readTWiki :: ReaderOptions -- ^ Reader options-          -> String        -- ^ String to parse (assuming @'\n'@ line endings)-          -> Either PandocError Pandoc-readTWiki opts s =-  (readWith parseTWiki) def{ stateOptions = opts } (s ++ "\n\n")--readTWikiWithWarnings :: ReaderOptions -- ^ Reader options-                      -> String        -- ^ String to parse (assuming @'\n'@ line endings)-                      -> Either PandocError (Pandoc, [String])-readTWikiWithWarnings opts s =-  (readWith parseTWikiWithWarnings) def{ stateOptions = opts } (s ++ "\n\n")- where parseTWikiWithWarnings = do-         doc <- parseTWiki-         warnings <- stateWarnings <$> getState-         return (doc, warnings)+readTWiki :: PandocMonad m+          => ReaderOptions+          -> Text+          -> m Pandoc+readTWiki opts s = do+  res <- readWithM parseTWiki def{ stateOptions = opts }+             (T.unpack (crFilter s) ++ "\n\n")+  case res of+       Left e  -> throwError e+       Right d -> return d -type TWParser = Parser [Char] ParserState+type TWParser = ParserT [Char] ParserState  -- -- utility functions -- -tryMsg :: String -> TWParser a -> TWParser a+tryMsg :: String -> TWParser m a -> TWParser m a tryMsg msg p = try p <?> msg -skip :: TWParser a -> TWParser ()+skip :: TWParser m a -> TWParser m () skip parser = parser >> return () -nested :: TWParser a -> TWParser a+nested :: PandocMonad m => TWParser m a -> TWParser m a nested p = do   nestlevel <- stateMaxNestingLevel <$>  getState   guard $ nestlevel > 0@@ -86,7 +85,7 @@   updateState $ \st -> st{ stateMaxNestingLevel = nestlevel }   return res -htmlElement :: String -> TWParser (Attr, String)+htmlElement :: PandocMonad m => String -> TWParser m (Attr, String) htmlElement tag = tryMsg tag $ do   (TagOpen _ attr, _) <- htmlTag (~== TagOpen tag [])   content <- manyTill anyChar (endtag <|> endofinput)@@ -103,23 +102,24 @@     classes = maybe [] words $ lookup "class" attrs     keyvals = [(k,v) | (k,v) <- attrs, k /= "id" && k /= "class"] -parseHtmlContentWithAttrs :: String -> TWParser a -> TWParser (Attr, [a])+parseHtmlContentWithAttrs :: PandocMonad m+                          => String -> TWParser m a -> TWParser m (Attr, [a]) parseHtmlContentWithAttrs tag parser = do   (attr, content) <- htmlElement tag   parsedContent <- try $ parseContent content   return (attr, parsedContent)   where-    parseContent = parseFromString $ nested $ manyTill parser endOfContent+    parseContent = parseFromString' $ nested $ manyTill parser endOfContent     endOfContent = try $ skipMany blankline >> skipSpaces >> eof -parseHtmlContent :: String -> TWParser a -> TWParser [a]+parseHtmlContent :: PandocMonad m => String -> TWParser m a -> TWParser m [a] parseHtmlContent tag p = parseHtmlContentWithAttrs tag p >>= return . snd  -- -- main parser -- -parseTWiki :: TWParser Pandoc+parseTWiki :: PandocMonad m => TWParser m Pandoc parseTWiki = do   bs <- mconcat <$> many block   spaces@@ -131,20 +131,16 @@ -- block parsers -- -block :: TWParser B.Blocks+block :: PandocMonad m => TWParser m B.Blocks block = do-  tr <- getOption readerTrace-  pos <- getPosition   res <- mempty <$ skipMany1 blankline          <|> blockElements          <|> para   skipMany blankline-  when tr $-    trace (printf "line %d: %s" (sourceLine pos)-           (take 60 $ show $ B.toList res)) (return ())+  trace (take 60 $ show $ B.toList res)   return res -blockElements :: TWParser B.Blocks+blockElements :: PandocMonad m => TWParser m B.Blocks blockElements = choice [ separator                        , header                        , verbatim@@ -155,10 +151,10 @@                        , noautolink                        ] -separator :: TWParser B.Blocks+separator :: PandocMonad m => TWParser m B.Blocks separator = tryMsg "separator" $ string "---" >> newline >> return B.horizontalRule -header :: TWParser B.Blocks+header :: PandocMonad m => TWParser m B.Blocks header = tryMsg "header" $ do   string "---"   level <- many1 (char '+') >>= return . length@@ -167,45 +163,47 @@   skipSpaces   content <- B.trimInlines . mconcat <$> manyTill inline newline   attr <- registerHeader ("", classes, []) content-  return $ B.headerWith attr level $ content+  return $ B.headerWith attr level content -verbatim :: TWParser B.Blocks+verbatim :: PandocMonad m => TWParser m B.Blocks verbatim = (htmlElement "verbatim" <|> htmlElement "pre")            >>= return . (uncurry B.codeBlockWith) -literal :: TWParser B.Blocks+literal :: PandocMonad m => TWParser m B.Blocks literal = htmlElement "literal" >>= return . rawBlock   where     format (_, _, kvs)        = fromMaybe "html" $ lookup "format" kvs     rawBlock (attrs, content) = B.rawBlock (format attrs) content -list :: String -> TWParser B.Blocks+list :: PandocMonad m => String -> TWParser m B.Blocks list prefix = choice [ bulletList prefix                      , orderedList prefix                      , definitionList prefix] -definitionList :: String -> TWParser B.Blocks+definitionList :: PandocMonad m => String -> TWParser m B.Blocks definitionList prefix = tryMsg "definitionList" $ do   indent <- lookAhead $ string prefix *> (many1 $ string "   ") <* string "$ "   elements <- many $ parseDefinitionListItem (prefix ++ concat indent)   return $ B.definitionList elements   where-    parseDefinitionListItem :: String -> TWParser (B.Inlines, [B.Blocks])+    parseDefinitionListItem :: PandocMonad m+                            => String -> TWParser m (B.Inlines, [B.Blocks])     parseDefinitionListItem indent = do       string (indent ++ "$ ") >> skipSpaces       term <- many1Till inline $ string ": "       line <- listItemLine indent $ string "$ "       return $ (mconcat term, [line]) -bulletList :: String -> TWParser B.Blocks+bulletList :: PandocMonad m => String -> TWParser m B.Blocks bulletList prefix = tryMsg "bulletList" $                     parseList prefix (char '*') (char ' ') -orderedList :: String -> TWParser B.Blocks+orderedList :: PandocMonad m => String -> TWParser m B.Blocks orderedList prefix = tryMsg "orderedList" $                      parseList prefix (oneOf "1iIaA") (string ". ") -parseList :: String -> TWParser Char -> TWParser a -> TWParser B.Blocks+parseList :: PandocMonad m+          => String -> TWParser m Char -> TWParser m a -> TWParser m B.Blocks parseList prefix marker delim = do   (indent, style) <- lookAhead $ string prefix *> listStyle <* delim   blocks <- many $ parseListItem (prefix ++ indent) (char style <* delim)@@ -222,10 +220,12 @@       style <- marker       return (concat indent, style) -parseListItem :: Show a => String -> TWParser a -> TWParser B.Blocks+parseListItem :: (PandocMonad m, Show a)+              => String -> TWParser m a -> TWParser m B.Blocks parseListItem prefix marker = string prefix >> marker >> listItemLine prefix marker -listItemLine :: Show a => String -> TWParser a -> TWParser B.Blocks+listItemLine :: (PandocMonad m, Show a)+             => String -> TWParser m a -> TWParser m B.Blocks listItemLine prefix marker = lineContent >>= parseContent >>= return . mconcat   where     lineContent = do@@ -235,14 +235,14 @@     filterSpaces = reverse . dropWhile (== ' ') . reverse     listContinuation = notFollowedBy (string prefix >> marker) >>                        string "   " >> lineContent-    parseContent = parseFromString $ many1 $ nestedList <|> parseInline+    parseContent = parseFromString' $ many1 $ nestedList <|> parseInline     parseInline = many1Till inline (lastNewline <|> newlineBeforeNestedList) >>=                   return . B.plain . mconcat     nestedList = list prefix     lastNewline = try $ char '\n' <* eof     newlineBeforeNestedList = try $ char '\n' <* lookAhead nestedList -table :: TWParser B.Blocks+table :: PandocMonad m => TWParser m B.Blocks table = try $ do   tableHead <- optionMaybe $ many1Till tableParseHeader newline >>= return . unzip   rows <- many1 tableParseRow@@ -254,7 +254,7 @@     columns rows    = replicate (columCount rows) mempty     columCount rows = length $ head rows -tableParseHeader :: TWParser ((Alignment, Double), B.Blocks)+tableParseHeader :: PandocMonad m => TWParser m ((Alignment, Double), B.Blocks) tableParseHeader = try $ do   char '|'   leftSpaces <- many spaceChar >>= return . length@@ -270,27 +270,27 @@       | left > right = (AlignRight, 0)       | otherwise = (AlignLeft, 0) -tableParseRow :: TWParser [B.Blocks]+tableParseRow :: PandocMonad m => TWParser m [B.Blocks] tableParseRow = many1Till tableParseColumn newline -tableParseColumn :: TWParser B.Blocks+tableParseColumn :: PandocMonad m => TWParser m B.Blocks tableParseColumn = char '|' *> skipSpaces *>                    tableColumnContent (skipSpaces >> char '|')                    <* skipSpaces <* optional tableEndOfRow -tableEndOfRow :: TWParser Char+tableEndOfRow :: PandocMonad m => TWParser m Char tableEndOfRow = lookAhead (try $ char '|' >> char '\n') >> char '|' -tableColumnContent :: TWParser a -> TWParser B.Blocks+tableColumnContent :: PandocMonad m => TWParser m a -> TWParser m B.Blocks tableColumnContent end = manyTill content (lookAhead $ try end) >>= return . B.plain . mconcat   where     content = continuation <|> inline     continuation = try $ char '\\' >> newline >> return mempty -blockQuote :: TWParser B.Blocks+blockQuote :: PandocMonad m => TWParser m B.Blocks blockQuote = parseHtmlContent "blockquote" block >>= return . B.blockQuote . mconcat -noautolink :: TWParser B.Blocks+noautolink :: PandocMonad m => TWParser m B.Blocks noautolink = do   (_, content) <- htmlElement "noautolink"   st <- getState@@ -299,9 +299,9 @@   setState $ st{ stateAllowLinks = True }   return $ mconcat blocks   where-    parseContent      = parseFromString $ many $ block+    parseContent      = parseFromString' $ many $ block -para :: TWParser B.Blocks+para :: PandocMonad m => TWParser m B.Blocks para = many1Till inline endOfParaElement >>= return . result . mconcat  where    endOfParaElement = lookAhead $ endOfInput <|> endOfPara <|> newBlockElement@@ -317,7 +317,7 @@ -- inline parsers -- -inline :: TWParser B.Inlines+inline :: PandocMonad m => TWParser m B.Inlines inline = choice [ whitespace                 , br                 , macro@@ -338,36 +338,39 @@                 , symbol                 ] <?> "inline" -whitespace :: TWParser B.Inlines+whitespace :: PandocMonad m => TWParser m B.Inlines whitespace = (lb <|> regsp) >>= return   where lb = try $ skipMany spaceChar >> linebreak >> return B.space         regsp = try $ skipMany1 spaceChar >> return B.space -br :: TWParser B.Inlines+br :: PandocMonad m => TWParser m B.Inlines br = try $ string "%BR%" >> return B.linebreak -linebreak :: TWParser B.Inlines+linebreak :: PandocMonad m => TWParser m B.Inlines linebreak = newline >> notFollowedBy newline >> (lastNewline <|> innerNewline)   where lastNewline  = eof >> return mempty         innerNewline = return B.space -between :: (Monoid c) => TWParser a -> TWParser b -> (TWParser b -> TWParser c) -> TWParser c+between :: (Monoid c, PandocMonad m, Show b)+        => TWParser m a -> TWParser m b -> (TWParser m b -> TWParser m c)+        -> TWParser m c between start end p =   mconcat <$> try (start >> notFollowedBy whitespace >> many1Till (p end) end) -enclosed :: (Monoid b) => TWParser a -> (TWParser a -> TWParser b) -> TWParser b+enclosed :: (Monoid b, PandocMonad m, Show a)+         => TWParser m a -> (TWParser m a -> TWParser m b) -> TWParser m b enclosed sep p = between sep (try $ sep <* endMarker) p   where     endMarker   = lookAhead $ skip endSpace <|> skip (oneOf ".,!?:)|") <|> eof     endSpace    = (spaceChar <|> newline) >> return B.space -macro :: TWParser B.Inlines+macro :: PandocMonad m => TWParser m B.Inlines macro = macroWithParameters <|> withoutParameters   where     withoutParameters = enclosed (char '%') (\_ -> macroName) >>= return . emptySpan     emptySpan name = buildSpan name [] mempty -macroWithParameters :: TWParser B.Inlines+macroWithParameters :: PandocMonad m => TWParser m B.Inlines macroWithParameters = try $ do   char '%'   name <- macroName@@ -382,22 +385,22 @@     additionalClasses = maybe [] words $ lookup "class" kvs     kvsWithoutClasses = [(k,v) | (k,v) <- kvs, k /= "class"] -macroName :: TWParser String+macroName :: PandocMonad m => TWParser m String macroName = do   first <- letter   rest <- many $ alphaNum <|> char '_'   return (first:rest) -attributes :: TWParser (String, [(String, String)])+attributes :: PandocMonad m => TWParser m (String, [(String, String)]) attributes = char '{' *> spnl *> many (attribute <* spnl) <* char '}' >>=              return . foldr (either mkContent mkKvs) ([], [])   where     spnl                      = skipMany (spaceChar <|> newline)-    mkContent c  ([], kvs)    = (c, kvs)-    mkContent c  (rest, kvs)  = (c ++ " " ++ rest, kvs)+    mkContent c  ([], kvs)   = (c, kvs)+    mkContent c  (rest, kvs) = (c ++ " " ++ rest, kvs)     mkKvs     kv (cont, rest) = (cont, (kv : rest)) -attribute :: TWParser (Either String (String, String))+attribute :: PandocMonad m => TWParser m (Either String (String, String)) attribute = withKey <|> withoutKey   where     withKey = try $ do@@ -411,49 +414,51 @@       | allowSpaces == True = many1 $ noneOf "}"       | otherwise           = many1 $ noneOf " }" -nestedInlines :: Show a => TWParser a -> TWParser B.Inlines+nestedInlines :: (Show a, PandocMonad m)+              => TWParser m a -> TWParser m B.Inlines nestedInlines end = innerSpace <|> nestedInline   where     innerSpace   = try $ whitespace <* (notFollowedBy end)     nestedInline = notFollowedBy whitespace >> nested inline -strong :: TWParser B.Inlines+strong :: PandocMonad m => TWParser m B.Inlines strong = try $ enclosed (char '*') nestedInlines >>= return . B.strong -strongHtml :: TWParser B.Inlines+strongHtml :: PandocMonad m => TWParser m B.Inlines strongHtml = (parseHtmlContent "strong" inline <|> parseHtmlContent "b" inline)              >>= return . B.strong . mconcat -strongAndEmph :: TWParser B.Inlines+strongAndEmph :: PandocMonad m => TWParser m B.Inlines strongAndEmph = try $ enclosed (string "__") nestedInlines >>= return . B.emph . B.strong -emph :: TWParser B.Inlines+emph :: PandocMonad m => TWParser m B.Inlines emph = try $ enclosed (char '_') nestedInlines >>= return . B.emph -emphHtml :: TWParser B.Inlines+emphHtml :: PandocMonad m => TWParser m B.Inlines emphHtml = (parseHtmlContent "em" inline <|> parseHtmlContent "i" inline)            >>= return . B.emph . mconcat -nestedString :: Show a => TWParser a -> TWParser String+nestedString :: (Show a, PandocMonad m)+             => TWParser m a -> TWParser m String nestedString end = innerSpace <|> (count 1 nonspaceChar)   where     innerSpace = try $ many1 spaceChar <* notFollowedBy end -boldCode :: TWParser B.Inlines+boldCode :: PandocMonad m => TWParser m B.Inlines boldCode = try $ enclosed (string "==") nestedString >>= return . B.strong . B.code . fromEntities -htmlComment :: TWParser B.Inlines+htmlComment :: PandocMonad m => TWParser m B.Inlines htmlComment = htmlTag isCommentTag >> return mempty -code :: TWParser B.Inlines+code :: PandocMonad m => TWParser m B.Inlines code = try $ enclosed (char '=') nestedString >>= return . B.code . fromEntities -codeHtml :: TWParser B.Inlines+codeHtml :: PandocMonad m => TWParser m B.Inlines codeHtml = do   (attrs, content) <- parseHtmlContentWithAttrs "code" anyChar   return $ B.codeWith attrs $ fromEntities content -autoLink :: TWParser B.Inlines+autoLink :: PandocMonad m => TWParser m B.Inlines autoLink = try $ do   state <- getState   guard $ stateAllowLinks state@@ -467,36 +472,36 @@       | c == '/' = True       | otherwise = isAlphaNum c -str :: TWParser B.Inlines+str :: PandocMonad m => TWParser m B.Inlines str = (many1 alphaNum <|> count 1 characterReference) >>= return . B.str -nop :: TWParser B.Inlines+nop :: PandocMonad m => TWParser m B.Inlines nop = try $ (skip exclamation <|> skip nopTag) >> followContent   where     exclamation   = char '!'     nopTag        = stringAnyCase "<nop>"     followContent = many1 nonspaceChar >>= return . B.str . fromEntities -symbol :: TWParser B.Inlines+symbol :: PandocMonad m => TWParser m B.Inlines symbol = count 1 nonspaceChar >>= return . B.str -smart :: TWParser B.Inlines+smart :: PandocMonad m => TWParser m B.Inlines smart = do-  getOption readerSmart >>= guard+  guardEnabled Ext_smart   doubleQuoted <|> singleQuoted <|>     choice [ apostrophe            , dash            , ellipses            ] -singleQuoted :: TWParser B.Inlines+singleQuoted :: PandocMonad m => TWParser m B.Inlines singleQuoted = try $ do   singleQuoteStart   withQuoteContext InSingleQuote $     many1Till inline singleQuoteEnd >>=     (return . B.singleQuoted . B.trimInlines . mconcat) -doubleQuoted :: TWParser B.Inlines+doubleQuoted :: PandocMonad m => TWParser m B.Inlines doubleQuoted = try $ do   doubleQuoteStart   contents <- mconcat <$> many (try $ notFollowedBy doubleQuoteEnd >> inline)@@ -504,7 +509,7 @@    return (B.doubleQuoted $ B.trimInlines contents))    <|> (return $ (B.str "\8220") B.<> contents) -link :: TWParser B.Inlines+link :: PandocMonad m => TWParser m B.Inlines link = try $ do   st <- getState   guard $ stateAllowLinks st@@ -513,13 +518,13 @@   setState $ st{ stateAllowLinks = True }   return $ B.link url title content -linkText :: TWParser (String, String, B.Inlines)+linkText :: PandocMonad m => TWParser m (String, String, B.Inlines) linkText = do   string "[["   url <- many1Till anyChar (char ']')-  content <- option [B.str url] linkContent+  content <- option (B.str url) (mconcat <$> linkContent)   char ']'-  return (url, "", mconcat content)+  return (url, "", content)   where     linkContent      = (char '[') >> many1Till anyChar (char ']') >>= parseLinkContent-    parseLinkContent = parseFromString $ many1 inline+    parseLinkContent = parseFromString' $ many1 inline
− src/Text/Pandoc/Readers/TeXMath.hs
@@ -1,48 +0,0 @@-{--Copyright (C) 2007-2015 John MacFarlane <jgm@berkeley.edu>--This program is free software; you can redistribute it and/or modify-it under the terms of the GNU General Public License as published by-the Free Software Foundation; either version 2 of the License, or-(at your option) any later version.--This program is distributed in the hope that it will be useful,-but WITHOUT ANY WARRANTY; without even the implied warranty of-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the-GNU General Public License for more details.--You should have received a copy of the GNU General Public License-along with this program; if not, write to the Free Software-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA--}--{- |-   Module      : Text.Pandoc.Readers.TeXMath-   Copyright   : Copyright (C) 2007-2015 John MacFarlane-   License     : GNU GPL, version 2 or above--   Maintainer  : John MacFarlane <jgm@berkeley.edu>-   Stability   : alpha-   Portability : portable--Conversion of TeX math to a list of 'Pandoc' inline elements.--}-module Text.Pandoc.Readers.TeXMath ( texMathToInlines ) where--import Text.Pandoc.Definition-import Text.TeXMath---- | Converts a raw TeX math formula to a list of 'Pandoc' inlines.--- Defaults to raw formula between @$@ or @$$@ characters if entire formula--- can't be converted.-texMathToInlines :: MathType-             -> String    -- ^ String to parse (assumes @'\n'@ line endings)-             -> [Inline]-texMathToInlines mt inp =-  case writePandoc dt `fmap` readTeX inp of-       Right (Just ils)  -> ils-       _                 -> [Str (delim ++ inp ++ delim)]-    where (dt, delim) = case mt of-                             DisplayMath -> (DisplayBlock, "$$")-                             InlineMath  -> (DisplayInline, "$")-
src/Text/Pandoc/Readers/Textile.hs view
@@ -1,6 +1,6 @@ {--Copyright (C) 2010-2015 Paul Rivier <paul*rivier#demotera*com> | tr '*#' '.@'-                        and John MacFarlane+Copyright (C) 2010-2012 Paul Rivier <paul*rivier#demotera*com> | tr '*#' '.@'+              2010-2017 John MacFarlane  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -19,7 +19,8 @@  {- |    Module      : Text.Pandoc.Readers.Textile-   Copyright   : Copyright (C) 2010-2015 Paul Rivier and John MacFarlane+   Copyright   : Copyright (C) 2010-2012 Paul Rivier+                               2010-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : Paul Rivier <paul*rivier#demotera*com>@@ -51,44 +52,42 @@   module Text.Pandoc.Readers.Textile ( readTextile) where+import Control.Monad (guard, liftM)+import Control.Monad.Except (throwError)+import Data.Char (digitToInt, isUpper)+import Data.List (intercalate, intersperse, transpose)+import Data.Monoid ((<>))+import Data.Text (Text)+import qualified Data.Text as T+import Text.HTML.TagSoup (Tag (..), fromAttrib)+import Text.HTML.TagSoup.Match+import Text.Pandoc.Builder (Blocks, Inlines, trimInlines)+import qualified Text.Pandoc.Builder as B+import Text.Pandoc.Class (PandocMonad (..)) import Text.Pandoc.CSS import Text.Pandoc.Definition-import Text.Pandoc.Builder (Inlines, Blocks, trimInlines)-import qualified Text.Pandoc.Builder as B import Text.Pandoc.Options import Text.Pandoc.Parsing-import Text.Pandoc.Readers.HTML ( htmlTag, isBlockTag, isInlineTag )-import Text.Pandoc.Shared (trim)-import Text.Pandoc.Readers.LaTeX ( rawLaTeXInline, rawLaTeXBlock )-import Text.HTML.TagSoup (fromAttrib, Tag(..))-import Text.HTML.TagSoup.Match-import Data.List ( intercalate, transpose, intersperse )-import Data.Char ( digitToInt, isUpper )-import Control.Monad ( guard, liftM, when )-import Data.Monoid ((<>))-import Text.Printf-import Debug.Trace (trace)-import Text.Pandoc.Error+import Text.Pandoc.Readers.HTML (htmlTag, isBlockTag, isInlineTag)+import Text.Pandoc.Readers.LaTeX (rawLaTeXBlock, rawLaTeXInline)+import Text.Pandoc.Shared (crFilter, trim, underlineSpan)  -- | Parse a Textile text and return a Pandoc document.-readTextile :: ReaderOptions -- ^ Reader options-            -> String       -- ^ String to parse (assuming @'\n'@ line endings)-            -> Either PandocError Pandoc-readTextile opts s =-  (readWith parseTextile) def{ stateOptions = opts } (s ++ "\n\n")+readTextile :: PandocMonad m+            => ReaderOptions -- ^ Reader options+            -> Text          -- ^ String to parse (assuming @'\n'@ line endings)+            -> m Pandoc+readTextile opts s = do+  parsed <- readWithM parseTextile def{ stateOptions = opts }+                (T.unpack (crFilter s) ++ "\n\n")+  case parsed of+     Right result -> return result+     Left e       -> throwError e   -- | Generate a Pandoc ADT from a textile document-parseTextile :: Parser [Char] ParserState Pandoc+parseTextile :: PandocMonad m => ParserT [Char] ParserState m Pandoc parseTextile = do-  -- textile allows raw HTML and does smart punctuation by default,-  -- but we do not enable smart punctuation unless it is explicitly-  -- asked for, for better conversion to other light markup formats-  oldOpts <- stateOptions `fmap` getState-  updateState $ \state -> state{ stateOptions =-                                   oldOpts{ readerParseRaw = True-                                          , readerOldDashes = True-                                          } }   many blankline   startPos <- getPosition   -- go through once just to get list of reference keys and notes@@ -103,15 +102,15 @@   blocks <- parseBlocks   return $ Pandoc nullMeta (B.toList blocks) -- FIXME -noteMarker :: Parser [Char] ParserState [Char]+noteMarker :: PandocMonad m => ParserT [Char] ParserState m [Char] noteMarker = skipMany spaceChar >> string "fn" >> manyTill digit (char '.') -noteBlock :: Parser [Char] ParserState [Char]+noteBlock :: PandocMonad m => ParserT [Char] ParserState m [Char] noteBlock = try $ do   startPos <- getPosition   ref <- noteMarker   optional blankline-  contents <- liftM unlines $ many1Till anyLine (blanklines <|> noteBlock)+  contents <- fmap unlines $ many1Till anyLine (blanklines <|> noteBlock)   endPos <- getPosition   let newnote = (ref, contents ++ "\n")   st <- getState@@ -121,11 +120,11 @@   return $ replicate (sourceLine endPos - sourceLine startPos) '\n'  -- | Parse document blocks-parseBlocks :: Parser [Char] ParserState Blocks+parseBlocks :: PandocMonad m => ParserT [Char] ParserState m Blocks parseBlocks = mconcat <$> manyTill block eof  -- | Block parsers list tried in definition order-blockParsers :: [Parser [Char] ParserState Blocks]+blockParsers :: PandocMonad m => [ParserT [Char] ParserState m Blocks] blockParsers = [ codeBlock                , header                , blockQuote@@ -140,26 +139,22 @@                ]  -- | Any block in the order of definition of blockParsers-block :: Parser [Char] ParserState Blocks+block :: PandocMonad m => ParserT [Char] ParserState m Blocks block = do   res <- choice blockParsers <?> "block"-  pos <- getPosition-  tr <- getOption readerTrace-  when tr $-    trace (printf "line %d: %s" (sourceLine pos)-           (take 60 $ show $ B.toList res)) (return ())+  trace (take 60 $ show $ B.toList res)   return res -commentBlock :: Parser [Char] ParserState Blocks+commentBlock :: PandocMonad m => ParserT [Char] ParserState m Blocks commentBlock = try $ do   string "###."   manyTill anyLine blanklines   return mempty -codeBlock :: Parser [Char] ParserState Blocks+codeBlock :: PandocMonad m => ParserT [Char] ParserState m Blocks codeBlock = codeBlockBc <|> codeBlockPre -codeBlockBc :: Parser [Char] ParserState Blocks+codeBlockBc :: PandocMonad m => ParserT [Char] ParserState m Blocks codeBlockBc = try $ do   string "bc."   extended <- option False (True <$ char '.')@@ -179,11 +174,10 @@ trimTrailingNewlines = reverse . dropWhile (=='\n') . reverse  -- | Code Blocks in Textile are between <pre> and </pre>-codeBlockPre :: Parser [Char] ParserState Blocks+codeBlockPre :: PandocMonad m => ParserT [Char] ParserState m Blocks codeBlockPre = try $ do   (t@(TagOpen _ attrs),_) <- htmlTag (tagOpen (=="pre") (const True))   result' <- manyTill anyChar (htmlTag (tagClose (=="pre")))-  optional blanklines   -- drop leading newline if any   let result'' = case result' of                       '\n':xs -> xs@@ -198,7 +192,7 @@   return $ B.codeBlockWith (ident,classes,kvs) result'''  -- | Header of the form "hN. content" with N in 1..6-header :: Parser [Char] ParserState Blocks+header :: PandocMonad m => ParserT [Char] ParserState m Blocks header = try $ do   char 'h'   level <- digitToInt <$> oneOf "123456"@@ -210,14 +204,14 @@   return $ B.headerWith attr' level name  -- | Blockquote of the form "bq. content"-blockQuote :: Parser [Char] ParserState Blocks+blockQuote :: PandocMonad m => ParserT [Char] ParserState m Blocks blockQuote = try $ do   string "bq" >> attributes >> char '.' >> whitespace   B.blockQuote <$> para  -- Horizontal rule -hrule :: Parser [Char] st Blocks+hrule :: PandocMonad m => ParserT [Char] st m Blocks hrule = try $ do   skipSpaces   start <- oneOf "-*"@@ -232,66 +226,67 @@ -- | Can be a bullet list or an ordered list. This implementation is -- strict in the nesting, sublist must start at exactly "parent depth -- plus one"-anyList :: Parser [Char] ParserState Blocks+anyList :: PandocMonad m => ParserT [Char] ParserState m Blocks anyList = try $ anyListAtDepth 1 <* blanklines  -- | This allow one type of list to be nested into an other type, -- provided correct nesting-anyListAtDepth :: Int -> Parser [Char] ParserState Blocks+anyListAtDepth :: PandocMonad m => Int -> ParserT [Char] ParserState m Blocks anyListAtDepth depth = choice [ bulletListAtDepth depth,                                 orderedListAtDepth depth,                                 definitionList ]  -- | Bullet List of given depth, depth being the number of leading '*'-bulletListAtDepth :: Int -> Parser [Char] ParserState Blocks+bulletListAtDepth :: PandocMonad m => Int -> ParserT [Char] ParserState m Blocks bulletListAtDepth depth = try $ B.bulletList  <$> many1 (bulletListItemAtDepth depth)  -- | Bullet List Item of given depth, depth being the number of -- leading '*'-bulletListItemAtDepth :: Int -> Parser [Char] ParserState Blocks+bulletListItemAtDepth :: PandocMonad m => Int -> ParserT [Char] ParserState m Blocks bulletListItemAtDepth = genericListItemAtDepth '*'  -- | Ordered List of given depth, depth being the number of -- leading '#'-orderedListAtDepth :: Int -> Parser [Char] ParserState Blocks+orderedListAtDepth :: PandocMonad m => Int -> ParserT [Char] ParserState m Blocks orderedListAtDepth depth = try $ do   items <- many1 (orderedListItemAtDepth depth)   return $ B.orderedList items  -- | Ordered List Item of given depth, depth being the number of -- leading '#'-orderedListItemAtDepth :: Int -> Parser [Char] ParserState Blocks+orderedListItemAtDepth :: PandocMonad m => Int -> ParserT [Char] ParserState m Blocks orderedListItemAtDepth = genericListItemAtDepth '#'  -- | Common implementation of list items-genericListItemAtDepth :: Char -> Int -> Parser [Char] ParserState Blocks+genericListItemAtDepth :: PandocMonad m => Char -> Int -> ParserT [Char] ParserState m Blocks genericListItemAtDepth c depth = try $ do   count depth (char c) >> attributes >> whitespace-  p <- mconcat <$> many listInline+  contents <- mconcat <$> many ((B.plain . mconcat <$> many1 inline) <|>+                                try (newline >> codeBlockPre))   newline   sublist <- option mempty (anyListAtDepth (depth + 1))-  return $ (B.plain p) <> sublist+  return $ contents <> sublist  -- | A definition list is a set of consecutive definition items-definitionList :: Parser [Char] ParserState Blocks+definitionList :: PandocMonad m => ParserT [Char] ParserState m Blocks definitionList = try $ B.definitionList <$> many1 definitionListItem  -- | List start character.-listStart :: Parser [Char] ParserState ()+listStart :: PandocMonad m => ParserT [Char] ParserState m () listStart = genericListStart '*'         <|> () <$ genericListStart '#'         <|> () <$ definitionListStart -genericListStart :: Char -> Parser [Char] st ()+genericListStart :: PandocMonad m => Char -> ParserT [Char] st m () genericListStart c = () <$ try (many1 (char c) >> whitespace) -basicDLStart :: Parser [Char] ParserState ()+basicDLStart :: PandocMonad m => ParserT [Char] ParserState m () basicDLStart = do   char '-'   whitespace   notFollowedBy newline -definitionListStart :: Parser [Char] ParserState Inlines+definitionListStart :: PandocMonad m => ParserT [Char] ParserState m Inlines definitionListStart = try $ do   basicDLStart   trimInlines . mconcat <$>@@ -300,34 +295,30 @@     <|> try (lookAhead (() <$ string ":="))      ) -listInline :: Parser [Char] ParserState Inlines-listInline = try (notFollowedBy newline >> inline)-         <|> try (endline <* notFollowedBy listStart)- -- | A definition list item in textile begins with '- ', followed by -- the term defined, then spaces and ":=". The definition follows, on -- the same single line, or spaned on multiple line, after a line -- break.-definitionListItem :: Parser [Char] ParserState (Inlines, [Blocks])+definitionListItem :: PandocMonad m => ParserT [Char] ParserState m (Inlines, [Blocks]) definitionListItem = try $ do   term <- (mconcat . intersperse B.linebreak) <$> many1 definitionListStart   def' <- string ":=" *> optional whitespace *> (multilineDef <|> inlineDef)   return (term, def')-  where inlineDef :: Parser [Char] ParserState [Blocks]+  where inlineDef :: PandocMonad m => ParserT [Char] ParserState m [Blocks]         inlineDef = liftM (\d -> [B.plain d])-                    $ optional whitespace >> (trimInlines . mconcat <$> many listInline) <* newline-        multilineDef :: Parser [Char] ParserState [Blocks]+                    $ optional whitespace >> (trimInlines . mconcat <$> many inline) <* newline+        multilineDef :: PandocMonad m => ParserT [Char] ParserState m [Blocks]         multilineDef = try $ do           optional whitespace >> newline           s <- many1Till anyChar (try (string "=:" >> newline))           -- this ++ "\n\n" does not look very good-          ds <- parseFromString parseBlocks (s ++ "\n\n")+          ds <- parseFromString' parseBlocks (s ++ "\n\n")           return [ds]  -- raw content  -- | A raw Html Block, optionally followed by blanklines-rawHtmlBlock :: Parser [Char] ParserState Blocks+rawHtmlBlock :: PandocMonad m => ParserT [Char] ParserState m Blocks rawHtmlBlock = try $ do   skipMany spaceChar   (_,b) <- htmlTag isBlockTag@@ -335,14 +326,14 @@   return $ B.rawBlock "html" b  -- | Raw block of LaTeX content-rawLaTeXBlock' :: Parser [Char] ParserState Blocks+rawLaTeXBlock' :: PandocMonad m => ParserT [Char] ParserState m Blocks rawLaTeXBlock' = do   guardEnabled Ext_raw_tex   B.rawBlock "latex" <$> (rawLaTeXBlock <* spaces)   -- | In textile, paragraphs are separated by blank lines.-para :: Parser [Char] ParserState Blocks+para :: PandocMonad m => ParserT [Char] ParserState m Blocks para = B.para . trimInlines . mconcat <$> many1 inline  -- Tables@@ -353,7 +344,7 @@ toAlignment '=' = AlignCenter toAlignment _   = AlignDefault -cellAttributes :: Parser [Char] ParserState (Bool, Alignment)+cellAttributes :: PandocMonad m => ParserT [Char] ParserState m (Bool, Alignment) cellAttributes = try $ do   isHeader <- option False (True <$ char '_')   -- we just ignore colspan and rowspan markers:@@ -366,18 +357,18 @@   return (isHeader, alignment)  -- | A table cell spans until a pipe |-tableCell :: Parser [Char] ParserState ((Bool, Alignment), Blocks)+tableCell :: PandocMonad m => ParserT [Char] ParserState m ((Bool, Alignment), Blocks) tableCell = try $ do   char '|'   (isHeader, alignment) <- option (False, AlignDefault) $ cellAttributes   notFollowedBy blankline   raw <- trim <$>          many (noneOf "|\n" <|> try (char '\n' <* notFollowedBy blankline))-  content <- mconcat <$> parseFromString (many inline) raw+  content <- mconcat <$> parseFromString' (many inline) raw   return ((isHeader, alignment), B.plain content)  -- | A table row is made of many table cells-tableRow :: Parser [Char] ParserState [((Bool, Alignment), Blocks)]+tableRow :: PandocMonad m => ParserT [Char] ParserState m [((Bool, Alignment), Blocks)] tableRow = try $ do   -- skip optional row attributes   optional $ try $ do@@ -387,7 +378,7 @@   many1 tableCell <* char '|' <* blankline  -- | A table with an optional header.-table :: Parser [Char] ParserState Blocks+table :: PandocMonad m => ParserT [Char] ParserState m Blocks table = try $ do   -- ignore table attributes   caption <- option mempty $ try $ do@@ -395,7 +386,7 @@     _ <- attributes     char '.'     rawcapt <- trim <$> anyLine-    parseFromString (mconcat <$> many inline) rawcapt+    parseFromString' (mconcat <$> many inline) rawcapt   rawrows <- many1 $ (skipMany ignorableRow) >> tableRow   skipMany ignorableRow   blanklines@@ -411,7 +402,7 @@     (map (map snd) rows)  -- | Ignore markers for cols, thead, tfoot.-ignorableRow :: Parser [Char] ParserState ()+ignorableRow :: PandocMonad m => ParserT [Char] ParserState m () ignorableRow = try $ do   char '|'   oneOf ":^-~"@@ -420,7 +411,7 @@   _ <- anyLine   return () -explicitBlockStart :: String -> Parser [Char] ParserState ()+explicitBlockStart :: PandocMonad m => String -> ParserT [Char] ParserState m () explicitBlockStart name = try $ do   string name   attributes@@ -430,9 +421,10 @@  -- | Blocks like 'p' and 'table' do not need explicit block tag. -- However, they can be used to set HTML/CSS attributes when needed.-maybeExplicitBlock :: String  -- ^ block tag name-                    -> Parser [Char] ParserState Blocks -- ^ implicit block-                    -> Parser [Char] ParserState Blocks+maybeExplicitBlock :: PandocMonad m+                   => String  -- ^ block tag name+                   -> ParserT [Char] ParserState m Blocks -- ^ implicit block+                   -> ParserT [Char] ParserState m Blocks maybeExplicitBlock name blk = try $ do   optional $ explicitBlockStart name   blk@@ -445,12 +437,12 @@   -- | Any inline element-inline :: Parser [Char] ParserState Inlines+inline :: PandocMonad m => ParserT [Char] ParserState m Inlines inline = do     choice inlineParsers <?> "inline"  -- | Inline parsers tried in order-inlineParsers :: [Parser [Char] ParserState Inlines]+inlineParsers :: PandocMonad m => [ParserT [Char] ParserState m Inlines] inlineParsers = [ str                 , whitespace                 , endline@@ -470,13 +462,13 @@                 ]  -- | Inline markups-inlineMarkup :: Parser [Char] ParserState Inlines+inlineMarkup :: PandocMonad m => ParserT [Char] ParserState m Inlines inlineMarkup = choice [ simpleInline (string "??") (B.cite [])                       , simpleInline (string "**") B.strong                       , simpleInline (string "__") B.emph                       , simpleInline (char '*') B.strong                       , simpleInline (char '_') B.emph-                      , simpleInline (char '+') B.emph  -- approximates underline+                      , simpleInline (char '+') underlineSpan                       , simpleInline (char '-' <* notFollowedBy (char '-')) B.strikeout                       , simpleInline (char '^') B.superscript                       , simpleInline (char '~') B.subscript@@ -484,35 +476,35 @@                       ]  -- | Trademark, registered, copyright-mark :: Parser [Char] st Inlines+mark :: PandocMonad m => ParserT [Char] st m Inlines mark = try $ char '(' >> (try tm <|> try reg <|> copy) -reg :: Parser [Char] st Inlines+reg :: PandocMonad m => ParserT [Char] st m Inlines reg = do   oneOf "Rr"   char ')'   return $ B.str "\174" -tm :: Parser [Char] st Inlines+tm :: PandocMonad m => ParserT [Char] st m Inlines tm = do   oneOf "Tt"   oneOf "Mm"   char ')'   return $ B.str "\8482" -copy :: Parser [Char] st Inlines+copy :: PandocMonad m => ParserT [Char] st m Inlines copy = do   oneOf "Cc"   char ')'   return $ B.str "\169" -note :: Parser [Char] ParserState Inlines+note :: PandocMonad m => ParserT [Char] ParserState m Inlines note = try $ do   ref <- (char '[' *> many1 digit <* char ']')   notes <- stateNotes <$> getState   case lookup ref notes of-    Nothing   -> fail "note not found"-    Just raw  -> B.note <$> parseFromString parseBlocks raw+    Nothing  -> fail "note not found"+    Just raw -> B.note <$> parseFromString' parseBlocks raw  -- | Special chars markupChars :: [Char]@@ -530,13 +522,13 @@ wordBoundaries = markupChars ++ stringBreakers  -- | Parse a hyphened sequence of words-hyphenedWords :: Parser [Char] ParserState String+hyphenedWords :: PandocMonad m => ParserT [Char] ParserState m String hyphenedWords = do   x <- wordChunk   xs <-  many (try $ char '-' >> wordChunk)   return $ intercalate "-" (x:xs) -wordChunk :: Parser [Char] ParserState String+wordChunk :: PandocMonad m => ParserT [Char] ParserState m String wordChunk = try $ do   hd <- noneOf wordBoundaries   tl <- many ( (noneOf wordBoundaries) <|>@@ -545,7 +537,7 @@   return $ hd:tl  -- | Any string-str :: Parser [Char] ParserState Inlines+str :: PandocMonad m => ParserT [Char] ParserState m Inlines str = do   baseStr <- hyphenedWords   -- RedCloth compliance : if parsed word is uppercase and immediatly@@ -558,11 +550,11 @@   return $ B.str fullStr  -- | Some number of space chars-whitespace :: Parser [Char] st Inlines+whitespace :: PandocMonad m => ParserT [Char] st m Inlines whitespace = many1 spaceChar >> return B.space <?> "whitespace"  -- | In Textile, an isolated endline character is a line break-endline :: Parser [Char] ParserState Inlines+endline :: PandocMonad m => ParserT [Char] ParserState m Inlines endline = try $ do   newline   notFollowedBy blankline@@ -570,18 +562,18 @@   notFollowedBy rawHtmlBlock   return B.linebreak -rawHtmlInline :: Parser [Char] ParserState Inlines+rawHtmlInline :: PandocMonad m => ParserT [Char] ParserState m Inlines rawHtmlInline = B.rawInline "html" . snd <$> htmlTag isInlineTag  -- | Raw LaTeX Inline-rawLaTeXInline' :: Parser [Char] ParserState Inlines+rawLaTeXInline' :: PandocMonad m => ParserT [Char] ParserState m Inlines rawLaTeXInline' = try $ do   guardEnabled Ext_raw_tex-  B.singleton <$> rawLaTeXInline+  B.rawInline "latex" <$> rawLaTeXInline  -- | Textile standard link syntax is "label":target. But we -- can also have ["label":target].-link :: Parser [Char] ParserState Inlines+link :: PandocMonad m => ParserT [Char] ParserState m Inlines link = try $ do   bracketed <- (True <$ char '[') <|> return False   char '"' *> notFollowedBy (oneOf " \t\n\r")@@ -591,8 +583,9 @@   char ':'   let stop = if bracketed                 then char ']'-                else lookAhead $ space <|>-                       try (oneOf "!.,;:" *> (space <|> newline))+                else lookAhead $ space <|> eof' <|>+                       try (oneOf "!.,;:" *>+                              (space <|> newline <|> eof'))   url <- many1Till nonspaceChar stop   let name' = if B.toList name == [Str "$"] then B.str url else name   return $ if attr == nullAttr@@ -600,7 +593,7 @@               else B.spanWith attr $ B.link url "" name'  -- | image embedding-image :: Parser [Char] ParserState Inlines+image :: PandocMonad m => ParserT [Char] ParserState m Inlines image = try $ do   char '!' >> notFollowedBy space   (ident, cls, kvs) <- attributes@@ -612,50 +605,50 @@   char '!'   return $ B.imageWith attr src alt (B.str alt) -escapedInline :: Parser [Char] ParserState Inlines+escapedInline :: PandocMonad m => ParserT [Char] ParserState m Inlines escapedInline = escapedEqs <|> escapedTag -escapedEqs :: Parser [Char] ParserState Inlines+escapedEqs :: PandocMonad m => ParserT [Char] ParserState m Inlines escapedEqs = B.str <$>   (try $ string "==" *> manyTill anyChar' (try $ string "=="))  -- | literal text escaped btw <notextile> tags-escapedTag :: Parser [Char] ParserState Inlines+escapedTag :: PandocMonad m => ParserT [Char] ParserState m Inlines escapedTag = B.str <$>   (try $ string "<notextile>" *>          manyTill anyChar' (try $ string "</notextile>"))  -- | Any special symbol defined in wordBoundaries-symbol :: Parser [Char] ParserState Inlines+symbol :: PandocMonad m => ParserT [Char] ParserState m Inlines symbol = B.str . singleton <$> (notFollowedBy newline *>                                 notFollowedBy rawHtmlBlock *>                                 oneOf wordBoundaries)  -- | Inline code-code :: Parser [Char] ParserState Inlines+code :: PandocMonad m => ParserT [Char] ParserState m Inlines code = code1 <|> code2  -- any character except a newline before a blank line-anyChar' :: Parser [Char] ParserState Char+anyChar' :: PandocMonad m => ParserT [Char] ParserState m Char anyChar' =   satisfy (/='\n') <|> (try $ char '\n' <* notFollowedBy blankline) -code1 :: Parser [Char] ParserState Inlines+code1 :: PandocMonad m => ParserT [Char] ParserState m Inlines code1 = B.code <$> surrounded (char '@') anyChar' -code2 :: Parser [Char] ParserState Inlines+code2 :: PandocMonad m => ParserT [Char] ParserState m Inlines code2 = do   htmlTag (tagOpen (=="tt") null)   B.code <$> manyTill anyChar' (try $ htmlTag $ tagClose (=="tt"))  -- | Html / CSS attributes-attributes :: Parser [Char] ParserState Attr+attributes :: PandocMonad m => ParserT [Char] ParserState m Attr attributes = (foldl (flip ($)) ("",[],[])) <$>   try (do special <- option id specialAttribute           attrs <- many attribute           return (special : attrs)) -specialAttribute :: Parser [Char] ParserState (Attr -> Attr)+specialAttribute :: PandocMonad m => ParserT [Char] ParserState m (Attr -> Attr) specialAttribute = do   alignStr <- ("center" <$ char '=') <|>     ("justify" <$ try (string "<>")) <|>@@ -664,11 +657,11 @@   notFollowedBy spaceChar   return $ addStyle ("text-align:" ++ alignStr) -attribute :: Parser [Char] ParserState (Attr -> Attr)+attribute :: PandocMonad m => ParserT [Char] ParserState m (Attr -> Attr) attribute = try $   (classIdAttr <|> styleAttr <|> langAttr) <* notFollowedBy spaceChar -classIdAttr :: Parser [Char] ParserState (Attr -> Attr)+classIdAttr :: PandocMonad m => ParserT [Char] ParserState m (Attr -> Attr) classIdAttr = try $ do -- (class class #id)   char '('   ws <- words `fmap` manyTill anyChar' (char ')')@@ -679,7 +672,7 @@        classes'                -> return $ \(_,_,keyvals) ->                                              ("",classes',keyvals) -styleAttr :: Parser [Char] ParserState (Attr -> Attr)+styleAttr :: PandocMonad m => ParserT [Char] ParserState m (Attr -> Attr) styleAttr = do   style <- try $ enclosed (char '{') (char '}') anyChar'   return $ addStyle style@@ -690,21 +683,23 @@   where keyvals' = ("style", style') : [(k,v) | (k,v) <- keyvals, k /= "style"]         style' = style ++ ";" ++ concat [v | ("style",v) <- keyvals] -langAttr :: Parser [Char] ParserState (Attr -> Attr)+langAttr :: PandocMonad m => ParserT [Char] ParserState m (Attr -> Attr) langAttr = do   lang <- try $ enclosed (char '[') (char ']') alphaNum   return $ \(id',classes,keyvals) -> (id',classes,("lang",lang):keyvals)  -- | Parses material surrounded by a parser.-surrounded :: Parser [Char] st t   -- ^ surrounding parser-            -> Parser [Char] st a    -- ^ content parser (to be used repeatedly)-            -> Parser [Char] st [a]+surrounded :: (PandocMonad m, Show t)+           => ParserT [Char] st m t   -- ^ surrounding parser+           -> ParserT [Char] st m a   -- ^ content parser (to be used repeatedly)+           -> ParserT [Char] st m [a] surrounded border =   enclosed (border *> notFollowedBy (oneOf " \t\n\r")) (try border) -simpleInline :: Parser [Char] ParserState t           -- ^ surrounding parser-             -> (Inlines -> Inlines)       -- ^ Inline constructor-             -> Parser [Char] ParserState Inlines   -- ^ content parser (to be used repeatedly)+simpleInline :: PandocMonad m+             => ParserT [Char] ParserState m t        -- ^ surrounding parser+             -> (Inlines -> Inlines)                  -- ^ Inline constructor+             -> ParserT [Char] ParserState m Inlines  -- ^ content parser (to be used repeatedly) simpleInline border construct = try $ do   notAfterString   border *> notFollowedBy (oneOf " \t\n\r")@@ -718,7 +713,7 @@            then body            else B.spanWith attr body -groupedInlineMarkup :: Parser [Char] ParserState Inlines+groupedInlineMarkup :: PandocMonad m => ParserT [Char] ParserState m Inlines groupedInlineMarkup = try $ do     char '['     sp1 <- option mempty $ B.space <$ whitespace@@ -731,3 +726,5 @@ singleton :: a -> [a] singleton x = [x] +eof' :: Monad m => ParserT [Char] s m Char+eof' = '\n' <$ eof
+ src/Text/Pandoc/Readers/TikiWiki.hs view
@@ -0,0 +1,656 @@+{-# LANGUAGE FlexibleContexts     #-}+{-# LANGUAGE FlexibleInstances    #-}+{-# LANGUAGE OverloadedStrings    #-}+{-# LANGUAGE RelaxedPolyRec       #-}+{-# LANGUAGE TypeSynonymInstances #-}++{- |+   Module      : Text.Pandoc.Readers.TikiWiki+   Copyright   : Copyright (C) 2017 Robin Lee Powell+   License     : GPLv2++   Maintainer  : Robin Lee Powell <robinleepowell@gmail.com>+   Stability   : alpha+   Portability : portable++Conversion of TikiWiki text to 'Pandoc' document.+-}++module Text.Pandoc.Readers.TikiWiki ( readTikiWiki+                                    ) where++import Control.Monad+import Control.Monad.Except (throwError)+import qualified Data.Foldable as F+import Data.Maybe (fromMaybe)+import Data.Text (Text)+import qualified Data.Text as T+import qualified Text.Pandoc.Builder as B+import Text.Pandoc.Class (CommonState (..), PandocMonad (..))+import Text.Pandoc.Definition+import Text.Pandoc.Logging (Verbosity (..))+import Text.Pandoc.Options+import Text.Pandoc.Parsing hiding (enclosed, nested)+import Text.Pandoc.Shared (crFilter)+import Text.Pandoc.XML (fromEntities)+import Text.Printf (printf)++-- | Read TikiWiki from an input string and return a Pandoc document.+readTikiWiki :: PandocMonad m+          => ReaderOptions+          -> Text+          -> m Pandoc+readTikiWiki opts s = do+  res <- readWithM parseTikiWiki def{ stateOptions = opts }+             (T.unpack (crFilter s) ++ "\n\n")+  case res of+       Left e  -> throwError e+       Right d -> return d++type TikiWikiParser = ParserT [Char] ParserState++--+-- utility functions+--++tryMsg :: PandocMonad m => String -> TikiWikiParser m a -> TikiWikiParser m a+tryMsg msg p = try p <?> msg++skip :: PandocMonad m => TikiWikiParser m a -> TikiWikiParser m ()+skip parser = Control.Monad.void parser++nested :: PandocMonad m => TikiWikiParser m a -> TikiWikiParser m a+nested p = do+  nestlevel <- stateMaxNestingLevel <$>  getState+  guard $ nestlevel > 0+  updateState $ \st -> st{ stateMaxNestingLevel = stateMaxNestingLevel st - 1 }+  res <- p+  updateState $ \st -> st{ stateMaxNestingLevel = nestlevel }+  return res++--+-- main parser+--++parseTikiWiki :: PandocMonad m => TikiWikiParser m Pandoc+parseTikiWiki = do+  bs <- mconcat <$> many block+  spaces+  eof+  return $ B.doc bs++block :: PandocMonad m => TikiWikiParser m B.Blocks+block = do+  verbosity <- getsCommonState stVerbosity+  pos <- getPosition+  res <- mempty <$ skipMany1 blankline+         <|> blockElements+         <|> para+  skipMany blankline+  when (verbosity >= INFO) $+    trace (printf "line %d: %s" (sourceLine pos) (take 60 $ show $ B.toList res))+  return res++blockElements :: PandocMonad m => TikiWikiParser m B.Blocks+blockElements = choice [ table+                       , hr+                       , header+                       , mixedList+                       , definitionList+                       , codeMacro+                       ]++-- top+-- ----+-- bottom+--+-- ----+--+hr :: PandocMonad m => TikiWikiParser m B.Blocks+hr = try $ do+  string "----"+  many (char '-')+  newline+  return B.horizontalRule++-- ! header+--+-- !! header level two+--+-- !!! header level 3+--+header :: PandocMonad m => TikiWikiParser m B.Blocks+header = tryMsg "header" $ do+  level <- fmap length (many1 (char '!'))+  guard $ level <= 6+  skipSpaces+  content <- B.trimInlines . mconcat <$> manyTill inline newline+  attr <- registerHeader nullAttr content+  return $B.headerWith attr level content++tableRow :: PandocMonad m => TikiWikiParser m [B.Blocks]+tableRow = try $ do+--  row <- sepBy1 (many1Till inline $ oneOf "\n|") (try $ string "|" <* notFollowedBy (oneOf "|\n"))+--  return $ map (B.plain . mconcat) row+  row <- sepBy1 (many1 (noneOf "\n|") >>= parseColumn) (try $ string "|" <* notFollowedBy (oneOf "|\n"))+  return $ map B.plain row+  where+    parseColumn x = do+      parsed <- parseFromString (many1 inline) x+      return $ mconcat parsed++++-- Tables:+--+-- ||foo||+--+-- ||row1-column1|row1-column2||row2-column1|row2-column2||+--+-- ||row1-column1|row1-column2+-- row2-column1|row2-column2||+--+-- ||row1-column1|row1-column2+-- row2-column1|row2-column2||row3-column1|row3-column2||+--+-- || Orange | Apple     | more+--  Bread  | Pie       | more+--  Butter | Ice cream | and more ||+--+table :: PandocMonad m => TikiWikiParser m B.Blocks+table = try $ do+  string "||"+  rows <- sepBy1 tableRow (try $ string "\n" <|> (string "||" <* notFollowedBy (string "\n")))+  string "||"+  newline+  -- return $ B.simpleTable (headers rows) $ trace ("rows: " ++ (show rows)) rows+  return $B.simpleTable (headers rows) rows+  where+    -- The headers are as many empty srings as the number of columns+    -- in the first row+    headers rows = map (B.plain . B.str) $replicate (length $ rows !! 0) ""++para :: PandocMonad m => TikiWikiParser m B.Blocks+para =  fmap (result . mconcat) ( many1Till inline endOfParaElement)+ where+   endOfParaElement = lookAhead $ endOfInput <|> endOfPara <|> newBlockElement+   endOfInput       = try $ skipMany blankline >> skipSpaces >> eof+   endOfPara        = try $ blankline >> skipMany1 blankline+   newBlockElement  = try $ blankline >> skip blockElements+   result content   = if F.all (==Space) content+                      then mempty+                      else B.para $ B.trimInlines content++-- ;item 1: definition 1+-- ;item 2: definition 2-1+-- + definition 2-2+-- ;item ''3'': definition ''3''+--+definitionList :: PandocMonad m => TikiWikiParser m B.Blocks+definitionList = tryMsg "definitionList" $ do+  elements <-many1 parseDefinitionListItem+  return $ B.definitionList elements+  where+    parseDefinitionListItem :: PandocMonad m => TikiWikiParser m (B.Inlines, [B.Blocks])+    parseDefinitionListItem = do+      skipSpaces >> char ';' <* skipSpaces+      term <- many1Till inline $ char ':' <* skipSpaces+      line <- listItemLine 1+      return (mconcat term, [B.plain line])++data ListType = None | Numbered | Bullet deriving (Ord, Eq, Show)++data ListNesting = LN { lntype :: ListType, lnnest :: Int } deriving (Ord, Eq, Show)++-- The first argument is a stack (most recent == head) of our list+-- nesting status; the list type and the nesting level; if we're in+-- a number list in a bullet list it'd be+-- [LN Numbered 2, LN Bullet 1]+--+-- Mixed list example:+--+-- # one+-- # two+-- ** two point one+-- ** two point two+-- # three+-- # four+--+mixedList :: PandocMonad m => TikiWikiParser m B.Blocks+mixedList = try $ do+  items <- try $ many1 listItem+  return $ mconcat $ fixListNesting $ spanFoldUpList (LN None 0) items++-- See the "Handling Lists" section of DESIGN-CODE for why this+-- function exists.  It's to post-process the lists and do some+-- mappends.+--+-- We need to walk the tree two items at a time, so we can see what+-- we're going to join *to* before we get there.+--+-- Because of that, it seemed easier to do it by hand than to try to+-- figre out a fold or something.+fixListNesting :: [B.Blocks] -> [B.Blocks]+fixListNesting [] = []+fixListNesting [first] = [recurseOnList first]+-- fixListNesting nestall | trace ("\n\nfixListNesting: " ++ (show nestall)) False = undefined+-- fixListNesting nestall@(first:second:rest) =+fixListNesting (first:second:rest) =+  let secondBlock = head $ B.toList second in+    case secondBlock of+      BulletList _ -> fixListNesting $ (mappend (recurseOnList first) (recurseOnList second)) : rest+      OrderedList _ _ -> fixListNesting $ (mappend (recurseOnList first) (recurseOnList second)) : rest+      _ -> recurseOnList first : fixListNesting (second:rest)++-- This function walks the Block structure for fixListNesting,+-- because it's a bit complicated, what with converting to and from+-- lists and so on.+recurseOnList :: B.Blocks -> B.Blocks+-- recurseOnList item | trace ("rOL: " ++ (show $ length $ B.toList item) ++ ", " ++ (show $ B.toList item)) False = undefined+recurseOnList items+  | length (B.toList items) == 1 =+    let itemBlock = head $ B.toList items in+      case itemBlock of+        BulletList listItems -> B.bulletList $ fixListNesting $ map B.fromList listItems+        OrderedList _ listItems -> B.orderedList $ fixListNesting $ map B.fromList listItems+        _ -> items++  -- The otherwise works because we constructed the blocks, and we+  -- know for a fact that no mappends have been run on them; each+  -- Blocks consists of exactly one Block.+  --+  -- Anything that's not like that has already been processed by+  -- fixListNesting; don't bother to process it again.+  | otherwise = items+++-- Turn the list if list items into a tree by breaking off the first+-- item, splitting the remainder of the list into items that are in+-- the tree of the first item and those that aren't, wrapping the+-- tree of the first item in its list time, and recursing on both+-- sections.+spanFoldUpList :: ListNesting -> [(ListNesting, B.Blocks)] -> [B.Blocks]+spanFoldUpList _ [] = []+spanFoldUpList ln [first] =+  listWrap ln (fst first) [snd first]+spanFoldUpList ln (first:rest) =+  let (span1, span2) = span (splitListNesting (fst first)) rest+      newTree1 = listWrap ln (fst first) $ snd first : spanFoldUpList (fst first) span1+      newTree2 = spanFoldUpList ln span2+  in+    newTree1 ++ newTree2++-- Decide if the second item should be in the tree of the first+-- item, which is true if the second item is at a deeper nesting+-- level and of the same type.+splitListNesting :: ListNesting -> (ListNesting, B.Blocks) -> Bool+splitListNesting ln1 (ln2, _)+  | (lnnest ln1) < (lnnest ln2) =+  True+  | ln1 == ln2 =+  True+  | otherwise =+  False++-- If we've moved to a deeper nesting level, wrap the new level in+-- the appropriate type of list.+listWrap :: ListNesting -> ListNesting -> [B.Blocks] -> [B.Blocks]+listWrap upperLN curLN retTree =+  if upperLN == curLN then+    retTree+  else+    case lntype curLN of+      None     -> []+      Bullet   -> [B.bulletList retTree]+      Numbered -> [B.orderedList retTree]++listItem :: PandocMonad m => TikiWikiParser m (ListNesting, B.Blocks)+listItem = choice [+    bulletItem+  , numberedItem+  ]+++-- * Start each line+-- * with an asterisk (*).+-- ** More asterisks gives deeper+-- *** and deeper levels.+--+bulletItem :: PandocMonad m => TikiWikiParser m (ListNesting, B.Blocks)+bulletItem = try $ do+  prefix <- many1 $ char '*'+  many1 $ char ' '+  content <- listItemLine (length prefix)+  return (LN Bullet (length prefix), B.plain content)++-- # Start each line+-- # with a number (1.).+-- ## More number signs gives deeper+-- ### and deeper+--+numberedItem :: PandocMonad m => TikiWikiParser m (ListNesting, B.Blocks)+numberedItem = try $ do+  prefix <- many1 $ char '#'+  many1 $ char ' '+  content <- listItemLine (length prefix)+  return (LN Numbered (length prefix), B.plain content)++listItemLine :: PandocMonad m => Int -> TikiWikiParser m B.Inlines+listItemLine nest = lineContent >>= parseContent+  where+    lineContent = do+      content <- anyLine+      continuation <- optionMaybe listContinuation+      return $ filterSpaces content ++ "\n" ++ maybe "" id continuation+    filterSpaces = reverse . dropWhile (== ' ') . reverse+    listContinuation = string (replicate nest '+') >> lineContent+    parseContent x = do+      parsed <- parseFromString (many1 inline) x+      return $ mconcat parsed++-- Turn the CODE macro attributes into Pandoc code block attributes.+mungeAttrs :: [(String, String)] -> (String, [String], [(String, String)])+mungeAttrs rawAttrs = ("", classes, rawAttrs)+  where+    -- "colors" is TikiWiki CODE macro for "name of language to do+    -- highlighting for"; turn the value into a class+    color = fromMaybe "" $ lookup "colors" rawAttrs+    -- ln = 1 means line numbering.  It's also the default.  So we+    -- emit numberLines as a class unless ln = 0+    lnRaw = fromMaybe "1" $ lookup "ln" rawAttrs+    ln = if lnRaw == "0" then+            ""+         else+            "numberLines"+    classes = filter (/= "") [color, ln]++codeMacro :: PandocMonad m => TikiWikiParser m B.Blocks+codeMacro = try $ do+  string "{CODE("+  rawAttrs <- macroAttrs+  string ")}"+  body <- manyTill anyChar (try (string "{CODE}"))+  newline+  if not (null rawAttrs)+    then+      return $ B.codeBlockWith (mungeAttrs rawAttrs) body+    else+      return $ B.codeBlock body+++--+-- inline parsers+--++inline :: PandocMonad m => TikiWikiParser m B.Inlines+inline = choice [ whitespace+                , noparse+                , strong+                , emph+                , nbsp+                , image+                , htmlComment+                , strikeout+                , code+                , wikiLink+                , notExternalLink+                , externalLink+                , superTag+                , superMacro+                , subTag+                , subMacro+                , escapedChar+                , colored+                , centered+                , underlined+                , boxed+                , breakChars+                , str+                , symbol+                ] <?> "inline"++whitespace :: PandocMonad m => TikiWikiParser m B.Inlines+whitespace = (lb <|> regsp)+  where lb = try $ skipMany spaceChar >> linebreak >> return B.space+        regsp = try $ skipMany1 spaceChar >> return B.space++-- UNSUPPORTED, as there doesn't seem to be any facility in calibre+-- for this+nbsp :: PandocMonad m => TikiWikiParser m B.Inlines+nbsp = try $ do+  string "~hs~"+  return $ B.str " NOT SUPPORTED BEGIN: ~hs~ (non-breaking space) :END "++-- UNSUPPORTED, as the desired behaviour (that the data be+-- *retained* and stored as a comment) doesn't exist in calibre, and+-- silently throwing data out seemed bad.+htmlComment :: PandocMonad m => TikiWikiParser m B.Inlines+htmlComment = try $ do+  string "~hc~"+  inner <- many1 $ noneOf "~"+  string "~/hc~"+  return $ B.str $ " NOT SUPPORTED: ~hc~ (html comment opener) BEGIN: " ++ inner ++ " ~/hc~ :END "++linebreak :: PandocMonad m => TikiWikiParser m B.Inlines+linebreak = newline >> notFollowedBy newline >> (lastNewline <|> innerNewline)+  where lastNewline  = eof >> return mempty+        innerNewline = return B.space++between :: (Monoid c, PandocMonad m, Show b) => TikiWikiParser m a -> TikiWikiParser m b -> (TikiWikiParser m b -> TikiWikiParser m c) -> TikiWikiParser m c+between start end p =+  mconcat <$> try (start >> notFollowedBy whitespace >> many1Till (p end) end)++enclosed :: (Monoid b, PandocMonad m, Show a) => TikiWikiParser m a -> (TikiWikiParser m a -> TikiWikiParser m b) -> TikiWikiParser m b+enclosed sep p = between sep (try $ sep <* endMarker) p+  where+    endMarker   = lookAhead $ skip endSpace <|> skip (oneOf ".,!?:)|'_") <|> eof+    endSpace    = (spaceChar <|> newline) >> return B.space+++nestedInlines :: (Show a, PandocMonad m) => TikiWikiParser m a -> TikiWikiParser m B.Inlines+nestedInlines end = innerSpace <|> nestedInline+  where+    innerSpace   = try $ whitespace <* notFollowedBy end+    nestedInline = notFollowedBy whitespace >> nested inline++-- {img attId="39" imalign="right" link="http://info.tikiwiki.org" alt="Panama Hat"}+--+-- {img attId="37", thumb="mouseover", styleimage="border", desc="150"}+--+-- {img src="img/wiki_up/393px-Pears.jpg" thumb="y" imalign="center" stylebox="border" button="y" desc="Pretty pears" max="200" rel="box"}+--+image :: PandocMonad m => TikiWikiParser m B.Inlines+image = try $ do+  string "{img "+  rawAttrs <- sepEndBy1 imageAttr spaces+  string "}"+  let src = fromMaybe "" $ lookup "src" rawAttrs+  let title = fromMaybe src $ lookup "desc" rawAttrs+  let alt = fromMaybe title $ lookup "alt" rawAttrs+  let classes = map fst $ filter (\(_,b) -> b == "" || b == "y") rawAttrs+  if not (null src)+    then+      return $ B.imageWith ("", classes, rawAttrs) src title (B.str alt)+    else+      return $ B.str $ " NOT SUPPORTED: image without src attribute BEGIN: {img " ++ printAttrs rawAttrs ++ "} :END "+  where+    printAttrs attrs = unwords $ map (\(a, b) -> a ++ "=\"" ++ b ++ "\"") attrs++imageAttr :: PandocMonad m => TikiWikiParser m (String, String)+imageAttr = try $ do+  key <- many1 (noneOf "=} \t\n")+  char '='+  optional $ char '"'+  value <- many1 (noneOf "}\"\n")+  optional $ char '"'+  optional $ char ','+  return (key, value)+++-- __strong__+strong :: PandocMonad m => TikiWikiParser m B.Inlines+strong = try $ fmap B.strong (enclosed (string "__") nestedInlines)++-- ''emph''+emph :: PandocMonad m => TikiWikiParser m B.Inlines+emph = try $ fmap B.emph (enclosed (string "''") nestedInlines)++-- ~246~+escapedChar :: PandocMonad m => TikiWikiParser m B.Inlines+escapedChar = try $ do+  string "~"+  inner <- many1 $ oneOf "0123456789"+  string "~"+  return $B.str [(toEnum ((read inner) :: Int)) :: Char]++-- UNSUPPORTED, as there doesn't seem to be any facility in calibre+-- for this+centered :: PandocMonad m => TikiWikiParser m B.Inlines+centered = try $ do+  string "::"+  inner <- many1 $ noneOf ":\n"+  string "::"+  return $ B.str $ " NOT SUPPORTED: :: (centered) BEGIN: ::" ++ inner ++ ":: :END "++-- UNSUPPORTED, as there doesn't seem to be any facility in calibre+-- for this+colored :: PandocMonad m => TikiWikiParser m B.Inlines+colored = try $ do+  string "~~"+  inner <- many1 $ noneOf "~\n"+  string "~~"+  return $ B.str $ " NOT SUPPORTED: ~~ (colored) BEGIN: ~~" ++ inner ++ "~~ :END "++-- UNSUPPORTED, as there doesn't seem to be any facility in calibre+-- for this+underlined :: PandocMonad m => TikiWikiParser m B.Inlines+underlined = try $ do+  string "==="+  inner <- many1 $ noneOf "=\n"+  string "==="+  return $ B.str $ " NOT SUPPORTED: ==== (underlined) BEGIN: ===" ++ inner ++ "=== :END "++-- UNSUPPORTED, as there doesn't seem to be any facility in calibre+-- for this+boxed :: PandocMonad m => TikiWikiParser m B.Inlines+boxed = try $ do+  string "^"+  inner <- many1 $ noneOf "^\n"+  string "^"+  return $ B.str $ " NOT SUPPORTED: ^ (boxed) BEGIN: ^" ++ inner ++ "^ :END "++-- --text--+strikeout :: PandocMonad m => TikiWikiParser m B.Inlines+strikeout = try $ fmap B.strikeout (enclosed (string "--") nestedInlines)++nestedString :: (Show a, PandocMonad m) => TikiWikiParser m a -> TikiWikiParser m String+nestedString end = innerSpace <|> count 1 nonspaceChar+  where+    innerSpace = try $ many1 spaceChar <* notFollowedBy end++breakChars :: PandocMonad m => TikiWikiParser m B.Inlines+breakChars = try $ string "%%%" >> return B.linebreak++-- superscript: foo{TAG(tag=>sup)}super{TAG}foo / bar{SUP()}super2{SUP}bar+superTag :: PandocMonad m => TikiWikiParser m B.Inlines+superTag = try $  fmap (B.superscript . B.text . fromEntities) ( between (string "{TAG(tag=>sup)}") (string "{TAG}") nestedString)++superMacro :: PandocMonad m => TikiWikiParser m B.Inlines+superMacro = try $ do+  string "{SUP("+  manyTill anyChar (string ")}")+  body <- manyTill anyChar (string "{SUP}")+  return $ B.superscript $ B.text body++-- subscript: baz{TAG(tag=>sub)}sub{TAG}qux / qux{SUB()}sub2{SUB}qux+subTag :: PandocMonad m => TikiWikiParser m B.Inlines+subTag = try $  fmap (B.subscript . B.text . fromEntities) ( between (string "{TAG(tag=>sub)}") (string "{TAG}") nestedString)++subMacro :: PandocMonad m => TikiWikiParser m B.Inlines+subMacro = try $ do+  string "{SUB("+  manyTill anyChar (string ")}")+  body <- manyTill anyChar (string "{SUB}")+  return $ B.subscript $ B.text body++-- -+text+-+code :: PandocMonad m => TikiWikiParser m B.Inlines+code = try $  fmap (B.code . fromEntities) ( between (string "-+") (string "+-") nestedString)++macroAttr :: PandocMonad m => TikiWikiParser m (String, String)+macroAttr = try $ do+  key <- many1 (noneOf "=)")+  char '='+  optional $ char '"'+  value <- many1 (noneOf " )\"")+  optional $ char '"'+  return (key, value)++macroAttrs :: PandocMonad m => TikiWikiParser m [(String, String)]+macroAttrs = try $ do+  sepEndBy macroAttr spaces++-- ~np~ __not bold__ ~/np~+noparse :: PandocMonad m => TikiWikiParser m B.Inlines+noparse = try $ do+  string "~np~"+  body <- manyTill anyChar (string "~/np~")+  return $ B.str body++str :: PandocMonad m => TikiWikiParser m B.Inlines+str = fmap B.str (many1 alphaNum <|> count 1 characterReference)++symbol :: PandocMonad m => TikiWikiParser m B.Inlines+symbol = fmap B.str (count 1 nonspaceChar)++-- [[not a link]+notExternalLink :: PandocMonad m => TikiWikiParser m B.Inlines+notExternalLink = try $ do+  start <- string "[["+  body <- many (noneOf "\n[]")+  end <- string "]"+  return $ B.text (start ++ body ++ end)++-- [http://www.somesite.org url|Some Site title]+-- ((internal link))+--+-- The ((...)) wiki links and [...] external links are handled+-- exactly the same; this abstracts that out+makeLink :: PandocMonad m => String -> String -> String -> TikiWikiParser m B.Inlines+makeLink start middle end = try $ do+  st <- getState+  guard $ stateAllowLinks st+  setState $ st{ stateAllowLinks = False }+  (url, title, anchor) <- wikiLinkText start middle end+  parsedTitle <- parseFromString (many1 inline) title+  setState $ st{ stateAllowLinks = True }+  return $ B.link (url++anchor) "" $mconcat parsedTitle++wikiLinkText :: PandocMonad m => String -> String -> String -> TikiWikiParser m (String, String, String)+wikiLinkText start middle end = do+  string start+  url <- many1 (noneOf $ middle ++ "\n")+  seg1 <- option url linkContent+  seg2 <- option "" linkContent+  string end+  if seg2 /= ""+    then+      return (url, seg2, seg1)+    else+      return (url, seg1, "")+  where+    linkContent      = do+      char '|'+      mystr <- many (noneOf middle)+      return mystr++externalLink :: PandocMonad m => TikiWikiParser m B.Inlines+externalLink = makeLink "[" "]|" "]"++-- NB: this wiki linking is unlikely to work for anyone besides me+-- (rlpowell); it happens to work for me because my Hakyll code has+-- post-processing that treats pandoc .md titles as valid link+-- targets, so something like+-- [see also this other post](My Other Page) is perfectly valid.+wikiLink :: PandocMonad m => TikiWikiParser m B.Inlines+wikiLink = makeLink "((" ")|" "))"
src/Text/Pandoc/Readers/Txt2Tags.hs view
@@ -29,39 +29,39 @@ module Text.Pandoc.Readers.Txt2Tags ( readTxt2Tags                                     , getT2TMeta                                     , T2TMeta (..)-                                    , readTxt2TagsNoMacros)+                                    )                                     where -import qualified Text.Pandoc.Builder as B-import Text.Pandoc.Builder ( Inlines, Blocks, trimInlines )-import Data.Monoid ((<>))-import Text.Pandoc.Definition-import Text.Pandoc.Options-import Text.Pandoc.Shared (escapeURI,compactify', compactify'DL)-import Text.Pandoc.Parsing hiding (space, spaces, uri, macro)+import Control.Monad (guard, void, when)+import Control.Monad.Except (catchError, throwError)+import Control.Monad.Reader (Reader, asks, runReader) import Data.Char (toLower)-import Data.List (transpose, intersperse, intercalate)-import Data.Maybe (fromMaybe)---import Network.URI (isURI) -- Not sure whether to use this function-import Control.Monad (void, guard, when) import Data.Default-import Control.Monad.Reader (Reader, runReader, asks)-import Text.Pandoc.Error--import Data.Time.LocalTime (getZonedTime)-import System.Directory(getModificationTime)+import Data.List (intercalate, intersperse, transpose)+import Data.Maybe (fromMaybe)+import Data.Monoid ((<>))+import Data.Text (Text)+import qualified Data.Text as T import Data.Time.Format (formatTime)+import Text.Pandoc.Builder (Blocks, Inlines, trimInlines)+import qualified Text.Pandoc.Builder as B+import Text.Pandoc.Class (PandocMonad)+import qualified Text.Pandoc.Class as P import Text.Pandoc.Compat.Time (defaultTimeLocale)-import System.IO.Error (catchIOError)+import Text.Pandoc.Definition+import Text.Pandoc.Options+import Text.Pandoc.Parsing hiding (space, spaces, uri)+import Text.Pandoc.Shared (compactify, compactifyDL, crFilter, escapeURI,+                           underlineSpan)  type T2T = ParserT String ParserState (Reader T2TMeta)  -- | An object for the T2T macros meta information -- the contents of each field is simply substituted verbatim into the file data  T2TMeta = T2TMeta {-                 date :: String -- ^ Current date-               , mtime :: String -- ^ Last modification time of infile-               , infile :: FilePath -- ^ Input file+                 date    :: String -- ^ Current date+               , mtime   :: String -- ^ Last modification time of infile+               , infile  :: FilePath -- ^ Input file                , outfile :: FilePath -- ^ Output file                } deriving Show @@ -69,26 +69,38 @@     def = T2TMeta "" "" "" ""  -- | Get the meta information required by Txt2Tags macros-getT2TMeta :: [FilePath] -> FilePath -> IO T2TMeta-getT2TMeta inps out = do-    curDate <- formatTime defaultTimeLocale "%F" <$> getZonedTime+getT2TMeta :: PandocMonad m => m T2TMeta+getT2TMeta = do+    inps <- P.getInputFiles+    outp <- fromMaybe "" <$> P.getOutputFile+    curDate <- formatTime defaultTimeLocale "%F" <$> P.getZonedTime     let getModTime = fmap (formatTime defaultTimeLocale "%T") .-                       getModificationTime+                       P.getModificationTime     curMtime <- case inps of-                  [] -> formatTime defaultTimeLocale "%T" <$> getZonedTime-                  _ -> catchIOError+                  [] -> formatTime defaultTimeLocale "%T" <$> P.getZonedTime+                  _ -> catchError                         (maximum <$> mapM getModTime inps)                         (const (return ""))-    return $ T2TMeta curDate curMtime (intercalate ", " inps) out+    return $ T2TMeta curDate curMtime (intercalate ", " inps) outp  -- | Read Txt2Tags from an input string returning a Pandoc document-readTxt2Tags :: T2TMeta -> ReaderOptions -> String -> Either PandocError Pandoc-readTxt2Tags t opts s = flip runReader t $ readWithM parseT2T (def {stateOptions = opts}) (s ++ "\n\n")+readTxt2Tags :: PandocMonad m+             => ReaderOptions+             -> Text+             -> m Pandoc+readTxt2Tags opts s = do+  meta <- getT2TMeta+  let parsed = flip runReader meta $+        readWithM parseT2T (def {stateOptions = opts}) $+        T.unpack (crFilter s) ++ "\n\n"+  case parsed of+    Right result -> return $ result+    Left e       -> throwError e  -- | Read Txt2Tags (ignoring all macros) from an input string returning -- a Pandoc document-readTxt2TagsNoMacros :: ReaderOptions -> String -> Either PandocError Pandoc-readTxt2TagsNoMacros = readTxt2Tags def+-- readTxt2TagsNoMacros :: PandocMonad m => ReaderOptions -> String -> m Pandoc+-- readTxt2TagsNoMacros = readTxt2Tags  parseT2T :: T2T Pandoc parseT2T = do@@ -198,7 +210,7 @@ quote = try $ do   lookAhead tab   rawQuote <-  many1 (tab *> optional spaces *> anyLine)-  contents <- parseFromString parseBlocks (intercalate "\n" rawQuote ++ "\n\n")+  contents <- parseFromString' parseBlocks (intercalate "\n" rawQuote ++ "\n\n")   return $ B.blockQuote contents  commentLine :: T2T Inlines@@ -210,16 +222,16 @@ list = choice [bulletList, orderedList, definitionList]  bulletList :: T2T Blocks-bulletList = B.bulletList . compactify'+bulletList = B.bulletList . compactify              <$> many1 (listItem bulletListStart parseBlocks)  orderedList :: T2T Blocks-orderedList = B.orderedList . compactify'+orderedList = B.orderedList . compactify               <$> many1 (listItem orderedListStart parseBlocks)  definitionList :: T2T Blocks definitionList = try $ do-  B.definitionList . compactify'DL <$>+  B.definitionList . compactifyDL <$>     many1 (listItem definitionListStart definitionListEnd)  definitionListEnd :: T2T (Inlines, [Blocks])@@ -250,7 +262,7 @@   firstLine <- anyLineNewline   blank <- option "" ("\n" <$ blankline)   rest <- concat <$> many (listContinuation markerLength)-  parseFromString end $ firstLine ++ blank ++ rest+  parseFromString' end $ firstLine ++ blank ++ rest  -- continuation of a list item - indented and separated by blankline or endline. -- Note: nested lists are parsed as continuations.@@ -262,12 +274,6 @@               <*> many blankline)  where listLine = try $ indentWith markerLength *> anyLineNewline -anyLineNewline :: T2T String-anyLineNewline = (++ "\n") <$> anyLine--indentWith :: Int -> T2T String-indentWith n = count n space- -- Table  table :: T2T Blocks@@ -388,7 +394,7 @@ bold = inlineMarkup inline B.strong '*' (B.str)  underline :: T2T Inlines-underline = inlineMarkup inline B.emph '_' (B.str)+underline = inlineMarkup inline underlineSpan '_' (B.str)  strike :: T2T Inlines strike = inlineMarkup inline B.strikeout '-' (B.str)@@ -431,10 +437,14 @@     Just middle -> do       lastChar <- anyChar       end <- many1 (char c)-      let parser inp = parseFromString (mconcat <$> many p) inp-      let start' = special (drop 2 start)+      let parser inp = parseFromString' (mconcat <$> many p) inp+      let start' = case drop 2 start of+                          "" -> mempty+                          xs -> special xs       body' <- parser (middle ++ [lastChar])-      let end' = special (drop 2 end)+      let end' = case drop 2 end of+                          "" -> mempty+                          xs -> special xs       return $ f (start' <> body' <> end')     Nothing -> do -- Either bad or case such as *****       guard (l >= 5)
+ src/Text/Pandoc/Readers/Vimwiki.hs view
@@ -0,0 +1,675 @@+{-+  Copyright (C) 2017 Yuchen Pei <me@ypei.me>++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation; either version 2 of the License, or+(at your option) any later version.++This program is distributed in the hope that it will be useful,+but WITHOUT ANY WARRANTY; without even the implied warranty of+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+GNU General Public License for more details.++You should have received a copy of the GNU General Public License+along with this program; if not, write to the Free Software+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+-}++{- |+   Module      : Text.Pandoc.Readers.Vimwiki+   Copyright   : Copyright (C) 2017 Yuchen Pei+   License     : GNU GPL, version 2 or above++   Maintainer  : Yuchen Pei <me@ypei.me>+   Stability   : alpha+   Portability : portable++Conversion of vimwiki text to 'Pandoc' document.+-}+{--+[X]: implemented+[O]: not implemented+* block parsers:+    * [X] header+    * [X] hrule+    * [X] comment+    * [X] blockquote+    * [X] preformatted -- using codeblock+    * [X] displaymath+    * [X] bulletlist / orderedlist+        * [X] todo lists -- using span.+    * [X] table+        * [X] centered table -- using div+        * [O] colspan and rowspan -- see issue #1024+    * [X] paragraph+    * [X] definition list+* inline parsers:+    * [X] bareURL+    * [X] strong+    * [X] emph+    * [X] strikeout+    * [X] code+    * [X] link+    * [X] image+    * [X] inline math+    * [X] tag+    * [X] sub- and super-scripts+* misc:+    * [X] `TODO:` mark+    * [X] metadata placeholders: %title and %date+    * [O] control placeholders: %template and %nohtml -- ignored+--}++module Text.Pandoc.Readers.Vimwiki ( readVimwiki+                                 ) where+import Control.Monad (guard)+import Control.Monad.Except (throwError)+import Data.Default+import Data.List (isInfixOf, isPrefixOf)+import Data.Maybe+import Data.Monoid ((<>))+import Data.Text (Text, unpack)+import Text.Pandoc.Builder (Blocks, Inlines, fromList, toList, trimInlines)+import qualified Text.Pandoc.Builder as B (blockQuote, bulletList, code,+                                           codeBlockWith, definitionList,+                                           displayMath, divWith, emph,+                                           headerWith, horizontalRule, image,+                                           imageWith, link, math, orderedList,+                                           para, plain, setMeta, simpleTable,+                                           softbreak, space, spanWith, str,+                                           strikeout, strong, subscript,+                                           superscript)+import Text.Pandoc.Class (PandocMonad (..))+import Text.Pandoc.Definition (Attr, Block (BulletList, OrderedList),+                               Inline (Space), ListNumberDelim (..),+                               ListNumberStyle (..), Meta, Pandoc (..),+                               nullMeta)+import Text.Pandoc.Options (ReaderOptions)+import Text.Pandoc.Parsing (F, ParserState, ParserT, blanklines, emailAddress,+                            many1Till, orderedListMarker, readWithM,+                            registerHeader, runF, spaceChar, stateMeta',+                            stateOptions, uri)+import Text.Pandoc.Shared (crFilter, splitBy, stringify, stripFirstAndLast)+import Text.Parsec.Char (alphaNum, anyChar, char, newline, noneOf, oneOf, space,+                         spaces, string)+import Text.Parsec.Combinator (between, choice, count, eof, lookAhead, many1,+                               manyTill, notFollowedBy, option, skipMany1)+import Text.Parsec.Prim (getState, many, try, updateState, (<|>))++readVimwiki :: PandocMonad m => ReaderOptions -> Text -> m Pandoc+readVimwiki opts s = do+  res <- readWithM parseVimwiki def{ stateOptions = opts }+            (unpack (crFilter s))+  case res of+       Left e       -> throwError e+       Right result -> return result++type VwParser = ParserT [Char] ParserState+++-- constants++specialChars :: [Char]+specialChars = "=*-#[]_~{}`$|:%^,"++spaceChars :: [Char]+spaceChars = " \t\n"++-- main parser++parseVimwiki :: PandocMonad m => VwParser m Pandoc+parseVimwiki = do+  bs <- mconcat <$> many block+  spaces+  eof+  st <- getState+  let meta = runF (stateMeta' st) st+  return $ Pandoc meta (toList bs)++-- block parser++block :: PandocMonad m => VwParser m Blocks+block = do+  res <- choice [ mempty <$ blanklines+                , header+                , hrule+                , mempty <$ comment+                , mixedList+                , preformatted+                , displayMath+                , table+                , mempty <$ placeholder+                , blockQuote+                , definitionList+                , para+                ]+  trace (take 60 $ show $ toList res)+  return res++blockML :: PandocMonad m => VwParser m Blocks+blockML = choice [preformatted, displayMath, table]++header :: PandocMonad m => VwParser m Blocks+header = try $ do+  sp <- many spaceChar+  eqs <- many1 (char '=')+  spaceChar+  let lev = length eqs+  guard $ lev <= 6+  contents <- trimInlines . mconcat <$> manyTill inline (try $ spaceChar+    >> string eqs >> many spaceChar >> newline)+  attr <- registerHeader (makeId contents,+    if sp == "" then [] else ["justcenter"], []) contents+  return $ B.headerWith attr lev contents++para :: PandocMonad m => VwParser m Blocks+para = try $ do+  contents <- trimInlines . mconcat <$> many1 inline+  if all (==Space) (toList contents)+     then return mempty+     else return $ B.para contents++hrule :: PandocMonad m => VwParser m Blocks+hrule = try $ B.horizontalRule <$ (string "----" >> many (char '-') >> newline)++comment :: PandocMonad m => VwParser m ()+comment = try $ do+  many spaceChar >> string "%%" >> many (noneOf "\n")+  return ()++blockQuote :: PandocMonad m => VwParser m Blocks+blockQuote = try $ do+  string "    "+  contents <- trimInlines . mconcat <$> many1 inlineBQ+  if all (==Space) (toList contents)+     then return mempty+     else return $ B.blockQuote $ B.plain contents++definitionList :: PandocMonad m => VwParser m Blocks+definitionList = try $+  B.definitionList <$> many1 (dlItemWithDT <|> dlItemWithoutDT)++dlItemWithDT :: PandocMonad m => VwParser m (Inlines, [Blocks])+dlItemWithDT = do+  dt <- definitionTerm+  dds <- many definitionDef+  return (dt, dds)++dlItemWithoutDT :: PandocMonad m => VwParser m (Inlines, [Blocks])+dlItemWithoutDT = do+  dds <- many1 definitionDef+  return (mempty, dds)++definitionDef :: PandocMonad m => VwParser m Blocks+definitionDef = try $+  notFollowedBy definitionTerm >> many spaceChar+    >> (definitionDef1 <|> definitionDef2)++definitionDef1 :: PandocMonad m => VwParser m Blocks+definitionDef1 = try $ mempty <$ defMarkerE++definitionDef2 :: PandocMonad m => VwParser m Blocks+definitionDef2 = try $ B.plain <$>+  (defMarkerM >> (trimInlines . mconcat <$> many inline') <* newline)+++definitionTerm :: PandocMonad m => VwParser m Inlines+definitionTerm = try $ do+  x <- definitionTerm1 <|> definitionTerm2+  guard (stringify x /= "")+  return x++definitionTerm1 :: PandocMonad m => VwParser m Inlines+definitionTerm1 = try $+  trimInlines . mconcat <$> manyTill inline' (try defMarkerE)++definitionTerm2 :: PandocMonad m => VwParser m Inlines+definitionTerm2 = try $ trimInlines . mconcat <$> manyTill inline'+  (try $lookAhead (defMarkerM >> notFollowedBy hasDefMarkerM))++defMarkerM :: PandocMonad m => VwParser m Char+defMarkerM = string "::" >> spaceChar++defMarkerE :: PandocMonad m => VwParser m Char+defMarkerE = string "::" >> newline++hasDefMarkerM :: PandocMonad m => VwParser m String+hasDefMarkerM = manyTill (noneOf "\n") (try defMarkerM)++preformatted :: PandocMonad m => VwParser m Blocks+preformatted = try $ do+  many spaceChar >> string "{{{"+  attrText <- many (noneOf "\n")+  lookAhead newline+  contents <- manyTill anyChar (try (char '\n' >> many spaceChar >> string "}}}"+    >> many spaceChar >> newline))+  if not (contents == "") && (head contents == '\n')+     then return $ B.codeBlockWith (makeAttr attrText) (tail contents)+     else return $ B.codeBlockWith (makeAttr attrText) contents++makeAttr :: String -> Attr+makeAttr s =+  let xs = splitBy (`elem` " \t") s in+    ("", [], mapMaybe nameValue xs)++nameValue :: String -> Maybe (String, String)+nameValue s =+  let t = splitBy (== '=') s in+    if length t /= 2+      then Nothing+      else let (a, b) = (head t, last t) in+             if (length b < 2) || ((head b, last b) /= ('"', '"'))+               then Nothing+               else Just (a, stripFirstAndLast b)+++displayMath :: PandocMonad m => VwParser m Blocks+displayMath = try $ do+  many spaceChar >> string "{{$"+  mathTag <- option "" mathTagParser+  many space+  contents <- manyTill anyChar (try (char '\n' >> many spaceChar >> string "}}$"+    >> many spaceChar >> newline))+  let contentsWithTags+        | mathTag == "" = contents+        | otherwise     = "\\begin{" ++ mathTag ++ "}\n" ++ contents+                          ++ "\n\\end{" ++ mathTag ++ "}"+  return $ B.para $ B.displayMath contentsWithTags+++mathTagLaTeX :: String -> String+mathTagLaTeX s = case s of+   "equation"  -> ""+   "equation*" -> ""+   "gather"    -> "gathered"+   "gather*"   -> "gathered"+   "multline"  -> "gathered"+   "multline*" -> "gathered"+   "eqnarray"  -> "aligned"+   "eqnarray*" -> "aligned"+   "align"     -> "aligned"+   "align*"    -> "aligned"+   "alignat"   -> "aligned"+   "alignat*"  -> "aligned"+   _           -> s+++mixedList :: PandocMonad m => VwParser m Blocks+mixedList = try $ do+  (bl, _) <- mixedList' (-1)+  return $ head bl++mixedList' :: PandocMonad m => Int -> VwParser m ([Blocks], Int)+mixedList' prevInd = do+  (curInd, builder) <- option (-1, "na") (lookAhead listStart)+  if curInd < prevInd+     then return ([], curInd)+     else do+          listStart+          curLine <- listItemContent+          let listBuilder =+                if builder == "ul" then B.bulletList else B.orderedList+          (subList, lowInd) <- (mixedList' curInd)+          if lowInd >= curInd+             then do+                  (sameIndList, endInd) <- (mixedList' lowInd)+                  let curList = combineList curLine subList ++ sameIndList+                  if curInd > prevInd+                     then return ([listBuilder curList], endInd)+                     else return (curList, endInd)+             else do+                  let (curList, endInd) = (combineList curLine subList,+                                           lowInd)+                  if curInd > prevInd+                     then return ([listBuilder curList], endInd)+                     else return (curList, endInd)++plainInlineML' :: PandocMonad m => Inlines -> VwParser m Blocks+plainInlineML' w = do+  xs <- many inlineML+  newline+  return $ B.plain $ trimInlines $ mconcat $ w:xs++plainInlineML :: PandocMonad m => VwParser m Blocks+plainInlineML = notFollowedBy listStart >> spaceChar >> plainInlineML' mempty+++listItemContent :: PandocMonad m => VwParser m Blocks+listItemContent = try $ do+  w <- option mempty listTodoMarker+  x <- plainInlineML' w+  y <- many blocksThenInline+  z <- many blockML+  return $ mconcat $ x:y ++ z++blocksThenInline :: PandocMonad m => VwParser m Blocks+blocksThenInline = try $ do+  y <- many1 blockML+  x <- plainInlineML+  return $ mconcat $ y ++ [x]++listTodoMarker :: PandocMonad m => VwParser m Inlines+listTodoMarker = try $ do+  x <- between (many spaceChar >> char '[') (char ']' >> spaceChar)+    (oneOf " .oOX")+  return $ makeListMarkerSpan x++makeListMarkerSpan :: Char -> Inlines+makeListMarkerSpan x =+  let cl = case x of+            ' ' -> "done0"+            '.' -> "done1"+            'o' -> "done2"+            'O' -> "done3"+            'X' -> "done4"+            _   -> ""+    in+      B.spanWith ("", [cl], []) mempty++combineList :: Blocks -> [Blocks] -> [Blocks]+combineList x [y] = case toList y of+                            [BulletList z] -> [fromList $ toList x+                                              ++ [BulletList z]]+                            [OrderedList attr z] -> [fromList $ toList x+                                                    ++ [OrderedList attr z]]+                            _ -> x:[y]+combineList x xs = x:xs++listStart :: PandocMonad m => VwParser m (Int, String)+listStart = try $ do+  s <- many spaceChar+  listType <- bulletListMarkers <|> orderedListMarkers+  spaceChar+  return (length s, listType)++bulletListMarkers :: PandocMonad m => VwParser m String+bulletListMarkers = "ul" <$ (char '*' <|> char '-')++orderedListMarkers :: PandocMonad m => VwParser m String+orderedListMarkers =+  ("ol" <$choice ((orderedListMarker Decimal Period):(($OneParen)+    <$> orderedListMarker+    <$> [Decimal, LowerRoman, UpperRoman, LowerAlpha, UpperAlpha])))+    <|> ("ol" <$ char '#')++--many need trimInlines+table :: PandocMonad m => VwParser m Blocks+table = try $ do+  indent <- lookAhead (many spaceChar)+  (th, trs) <- table1 <|> table2+  let tab = B.simpleTable th trs+  if indent == ""+    then return tab+    else return $ B.divWith ("", ["center"], []) tab++-- table with header+table1 :: PandocMonad m => VwParser m ([Blocks], [[Blocks]])+table1 = try $ do+  th <- tableRow+  many1 tableHeaderSeparator+  trs <- many tableRow+  return (th, trs)++-- headerless table+table2 :: PandocMonad m => VwParser m ([Blocks], [[Blocks]])+table2 = try $ do+  trs <- many1 tableRow+  return (replicate (length $ head trs) mempty, trs)++tableHeaderSeparator :: PandocMonad m => VwParser m ()+tableHeaderSeparator = try $ do+  many spaceChar >> char '|' >> many1 (many1 (char '-') >> char '|')+    >> many spaceChar >> newline+  return ()++tableRow :: PandocMonad m => VwParser m [Blocks]+tableRow = try $ do+  many spaceChar >> char '|'+  s <- lookAhead $ manyTill anyChar (try (char '|' >> many spaceChar+    >> newline))+  guard $ not $ "||" `isInfixOf` ("|" ++ s ++ "|")+  tr <- many tableCell+  many spaceChar >> char '\n'+  return tr++tableCell :: PandocMonad m => VwParser m Blocks+tableCell = try $+  B.plain . trimInlines . mconcat <$> (manyTill inline' (char '|'))++placeholder :: PandocMonad m => VwParser m ()+placeholder = try $+  choice (ph <$> ["title", "date"]) <|> noHtmlPh <|> templatePh++ph :: PandocMonad m => String -> VwParser m ()+ph s = try $ do+  many spaceChar >>string ('%':s) >> spaceChar+  contents <- trimInlines . mconcat <$> (manyTill inline (lookAhead newline))+    --use lookAhead because of placeholder in the whitespace parser+  let meta' = return $ B.setMeta s contents nullMeta :: F Meta+  updateState $ \st -> st { stateMeta' = stateMeta' st <> meta' }++noHtmlPh :: PandocMonad m => VwParser m ()+noHtmlPh = try $+  () <$ (many spaceChar >> string "%nohtml" >> many spaceChar+    >> lookAhead newline)++templatePh :: PandocMonad m => VwParser m ()+templatePh = try $+  () <$ (many spaceChar >> string "%template" >>many (noneOf "\n")+    >> lookAhead newline)++-- inline parser++inline :: PandocMonad m => VwParser m Inlines+inline = choice $ whitespace endlineP:inlineList++inlineList :: PandocMonad m => [VwParser m Inlines]+inlineList = [  bareURL+             ,  todoMark+             ,  str+             ,  strong+             ,  emph+             ,  strikeout+             ,  code+             ,  link+             ,  image+             ,  inlineMath+             ,  tag+             ,  superscript+             ,  subscript+             ,  special+             ]++-- inline parser without softbreaks or comment breaks+inline' :: PandocMonad m => VwParser m Inlines+inline' = choice $ whitespace':inlineList++-- inline parser for blockquotes+inlineBQ :: PandocMonad m => VwParser m Inlines+inlineBQ = choice $ whitespace endlineBQ:inlineList++-- inline parser for mixedlists+inlineML :: PandocMonad m => VwParser m Inlines+inlineML = choice $ whitespace endlineML:inlineList++str :: PandocMonad m => VwParser m Inlines+str = B.str <$>many1 (noneOf $ spaceChars ++ specialChars)++whitespace :: PandocMonad m => VwParser m () -> VwParser m Inlines+whitespace endline = B.space <$ (skipMany1 spaceChar <|>+                                 try (newline >> (comment <|> placeholder)))+         <|> B.softbreak <$ endline++whitespace' :: PandocMonad m => VwParser m Inlines+whitespace' = B.space <$ skipMany1 spaceChar++special :: PandocMonad m => VwParser m Inlines+special = B.str <$> count 1 (oneOf specialChars)++bareURL :: PandocMonad m => VwParser m Inlines+bareURL = try $ do+  (orig, src) <- uri <|> emailAddress+  return $ B.link src "" (B.str orig)++strong :: PandocMonad m => VwParser m Inlines+strong = try $ do+  s <- lookAhead $ between (char '*') (char '*') (many1 $ noneOf "*")+  guard $ not ((head s) `elem` spaceChars)+             &&not ((last s) `elem` spaceChars)+  char '*'+  contents <- mconcat <$>manyTill inline' (char '*'+    >> notFollowedBy alphaNum)+  return $ B.spanWith ((makeId contents), [], []) mempty+    <> B.strong contents++makeId :: Inlines -> String+makeId i = concat (stringify <$> toList i)++emph :: PandocMonad m => VwParser m Inlines+emph = try $ do+  s <- lookAhead $ between (char '_') (char '_') (many1 $ noneOf "_")+  guard $ not ((head s) `elem` spaceChars)+          &&not ((last s) `elem` spaceChars)+  char '_'+  contents <- mconcat <$>manyTill inline' (char '_'+    >> notFollowedBy alphaNum)+  return $ B.emph contents++strikeout :: PandocMonad m => VwParser m Inlines+strikeout = try $ do+  string "~~"+  contents <- mconcat <$>many1Till inline' (string $ "~~")+  return $ B.strikeout contents++code :: PandocMonad m => VwParser m Inlines+code = try $ do+  char '`'+  contents <- many1Till (noneOf "\n") (char '`')+  return $ B.code contents++superscript :: PandocMonad m => VwParser m Inlines+superscript = try $+  B.superscript . mconcat <$> (char '^' >> many1Till inline' (char '^'))++subscript :: PandocMonad m => VwParser m Inlines+subscript = try $+  B.subscript . mconcat <$> (string ",,"+    >> many1Till inline' (try $ string ",,"))++link :: PandocMonad m => VwParser m Inlines+link = try $ do+  string "[["+  contents <- lookAhead $ manyTill anyChar (string "]]")+  case '|' `elem` contents of+                  False -> do+                    manyTill anyChar (string "]]")+-- not using try here because [[hell]o]] is not rendered as a link in vimwiki+                    return $ B.link (procLink contents) "" (B.str contents)+                  True  -> do+                    url <- manyTill anyChar $ char '|'+                    lab <- mconcat <$> (manyTill inline $ string "]]")+                    return $ B.link (procLink url) "" lab++image :: PandocMonad m => VwParser m Inlines+image = try $ do+  string "{{"+  contentText <- lookAhead $ manyTill (noneOf "\n") (try $ string "}}")+  images $ length $ filter (== '|') contentText++images :: PandocMonad m => Int -> VwParser m Inlines+images k+  | k == 0 = do+           imgurl <- manyTill anyChar (try $ string "}}")+           return $ B.image (procImgurl imgurl) "" (B.str "")+  | k == 1 = do+           imgurl <- manyTill anyChar (char '|')+           alt <- mconcat <$> (manyTill inline (try $ string "}}"))+           return $ B.image (procImgurl imgurl) "" alt+  | k == 2 = do+           imgurl <- manyTill anyChar (char '|')+           alt <- mconcat <$>manyTill inline (char '|')+           attrText <- manyTill anyChar (try $ string "}}")+           return $ B.imageWith (makeAttr attrText) (procImgurl imgurl) "" alt+  | otherwise = do+           imgurl <- manyTill anyChar (char '|')+           alt <- mconcat <$>manyTill inline (char '|')+           attrText <- manyTill anyChar (char '|')+           manyTill anyChar (try $ string "}}")+           return $ B.imageWith (makeAttr attrText) (procImgurl imgurl) "" alt++procLink' :: String -> String+procLink' s+  | (take 6 s) == "local:" = "file" ++ drop 5 s+  | (take 6 s) == "diary:" = "diary/" ++ drop 6 s ++ ".html"+  | or ((`isPrefixOf` s) <$> [ "http:", "https:", "ftp:", "file:", "mailto:",+                              "news:", "telnet:" ])+                             = s+  | s == ""                  = ""+  | last s == '/'          = s+  | otherwise                = s ++ ".html"++procLink :: String -> String+procLink s = procLink' x ++ y+  where (x, y) = break (=='#') s++procImgurl :: String -> String+procImgurl s = if (take 6 s) == "local:" then "file" ++ drop 5 s else s++inlineMath :: PandocMonad m => VwParser m Inlines+inlineMath = try $ do+  char '$'+  contents <- many1Till (noneOf "\n") (char '$')+  return $ B.math contents++tag :: PandocMonad m => VwParser m Inlines+tag = try $ do+  char ':'+  s <- manyTill (noneOf spaceChars) (try (char ':' >> lookAhead space))+  guard $ not $ "::" `isInfixOf` (":" ++ s ++ ":")+  let ss = splitBy (==':') s+  return $ mconcat $ makeTagSpan' (head ss):(makeTagSpan <$> tail ss)++todoMark :: PandocMonad m => VwParser m Inlines+todoMark = try $ do+  string "TODO:"+  return $ B.spanWith ("", ["todo"], []) (B.str "TODO:")++-- helper functions and parsers+endlineP :: PandocMonad m => VwParser m ()+endlineP = () <$ try (newline <* nFBTTBSB <* notFollowedBy blockQuote)++endlineBQ :: PandocMonad m => VwParser m ()+endlineBQ = () <$ try (newline <* nFBTTBSB <* string "    ")++endlineML :: PandocMonad m => VwParser m ()+endlineML = () <$ try (newline <* nFBTTBSB <* many1 spaceChar)++--- nFBTTBSB is short for notFollowedByThingsThatBreakSoftBreaks+nFBTTBSB :: PandocMonad m => VwParser m ()+nFBTTBSB =+    notFollowedBy newline <*+    notFollowedBy hrule <*+    notFollowedBy tableRow <*+    notFollowedBy header <*+    notFollowedBy listStart <*+    notFollowedBy preformatted <*+    notFollowedBy displayMath <*+    notFollowedBy hasDefMarker++hasDefMarker :: PandocMonad m => VwParser m ()+hasDefMarker = () <$ manyTill (noneOf "\n") (string "::" >> oneOf spaceChars)++makeTagSpan' :: String -> Inlines+makeTagSpan' s = B.spanWith ('-' : s, [], []) (B.str "") <>+                  B.spanWith (s, ["tag"], []) (B.str s)++makeTagSpan :: String -> Inlines+makeTagSpan s = B.space <> makeTagSpan' s++mathTagParser :: PandocMonad m => VwParser m String+mathTagParser = do+  s <- try $ lookAhead (char '%' >> manyTill (noneOf spaceChars)+    (try $ char '%' >> many (noneOf $ '%':spaceChars) >> space))+  char '%' >> string s >> char '%'+  return $ mathTagLaTeX s
src/Text/Pandoc/SelfContained.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE OverloadedStrings #-} {--Copyright (C) 2011-2016 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2011-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -19,7 +19,7 @@  {- |    Module      : Text.Pandoc.SelfContained-   Copyright   : Copyright (C) 2011-2016 John MacFarlane+   Copyright   : Copyright (C) 2011-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -30,32 +30,36 @@ offline, by incorporating linked images, CSS, and scripts into the HTML using data URIs. -}-module Text.Pandoc.SelfContained ( makeSelfContained ) where-import Text.HTML.TagSoup-import Network.URI (isURI, escapeURIString, URI(..), parseURI)+module Text.Pandoc.SelfContained ( makeDataURI, makeSelfContained ) where+import Codec.Compression.GZip as Gzip+import Control.Applicative ((<|>))+import Control.Monad.Except (throwError)+import Control.Monad.Trans (lift)+import Data.ByteString (ByteString) import Data.ByteString.Base64 import qualified Data.ByteString.Char8 as B-import Data.ByteString (ByteString)-import System.FilePath (takeExtension, takeDirectory, (</>))-import Data.Char (toLower, isAscii, isAlphaNum)-import Codec.Compression.GZip as Gzip import qualified Data.ByteString.Lazy as L-import Text.Pandoc.Shared (renderTags', err, fetchItem', warn, trim)-import Text.Pandoc.MediaBag (MediaBag)+import Data.Char (isAlphaNum, isAscii, toLower)+import Data.List (isPrefixOf)+import Data.Monoid ((<>))+import Network.URI (escapeURIString)+import System.FilePath (takeDirectory, takeExtension, (</>))+import Text.HTML.TagSoup+import Text.Pandoc.Class (PandocMonad (..), fetchItem, getInputFiles, report,+                          setInputFiles)+import Text.Pandoc.Error+import Text.Pandoc.Logging import Text.Pandoc.MIME (MimeType)+import Text.Pandoc.Shared (isURI, renderTags', trim) import Text.Pandoc.UTF8 (toString)-import Text.Pandoc.Options (WriterOptions(..))-import Data.List (isPrefixOf)-import Control.Applicative ((<|>))-import Text.Parsec (runParserT, ParsecT)+import Text.Parsec (ParsecT, runParserT) import qualified Text.Parsec as P-import Control.Monad.Trans (lift)  isOk :: Char -> Bool isOk c = isAscii c && isAlphaNum c -makeDataURI :: String -> ByteString -> String-makeDataURI mime raw =+makeDataURI :: (MimeType, ByteString) -> String+makeDataURI (mime, raw) =   if textual      then "data:" ++ mime' ++ "," ++ escapeURIString isOk (toString raw)      else "data:" ++ mime' ++ ";base64," ++ toString (encode raw)@@ -64,64 +68,142 @@                    then mime ++ ";charset=utf-8"                    else mime  -- mime type already has charset -convertTag :: MediaBag -> Maybe String -> Tag String -> IO (Tag String)-convertTag media sourceURL t@(TagOpen tagname as)+convertTags :: PandocMonad m => [Tag String] -> m [Tag String]+convertTags [] = return []+convertTags (t@TagOpen{}:ts)+  | fromAttrib "data-external" t == "1" = (t:) <$> convertTags ts+convertTags (t@(TagOpen tagname as):ts)   | tagname `elem`-     ["img", "embed", "video", "input", "audio", "source", "track"] = do+     ["img", "embed", "video", "input", "audio", "source", "track",+      "section"] = do        as' <- mapM processAttribute as-       return $ TagOpen tagname as'+       rest <- convertTags ts+       return $ TagOpen tagname as' : rest   where processAttribute (x,y) =-           if x == "src" || x == "href" || x == "poster"+           if x `elem` ["src", "data-src", "href", "poster", "data-background-image"]               then do-                enc <- getDataURI media sourceURL (fromAttrib "type" t) y+                enc <- getDataURI (fromAttrib "type" t) y                 return (x, enc)               else return (x,y)-convertTag media sourceURL t@(TagOpen "script" as) =+convertTags (t@(TagOpen "script" as):TagClose "script":ts) =   case fromAttrib "src" t of-       []     -> return t+       []  -> (t:) <$> convertTags ts        src    -> do-           enc <- getDataURI media sourceURL (fromAttrib "type" t) src-           return $ TagOpen "script" (("src",enc) : [(x,y) | (x,y) <- as, x /= "src"])-convertTag media sourceURL t@(TagOpen "link" as) =+           let typeAttr = fromAttrib "type" t+           res <- getData typeAttr src+           rest <- convertTags ts+           case res of+                Left dataUri -> return $ TagOpen "script"+                     (("src",dataUri) : [(x,y) | (x,y) <- as, x /= "src"]) :+                     TagClose "script" : rest+                Right (mime, bs)+                  | ("text/javascript" `isPrefixOf` mime ||+                     "application/javascript" `isPrefixOf` mime ||+                     "application/x-javascript" `isPrefixOf` mime) &&+                     not ("</script" `B.isInfixOf` bs) ->+                     return $+                       TagOpen "script" [("type", typeAttr)|not (null typeAttr)]+                       : TagText (toString bs)+                       : TagClose "script"+                       : rest+                  | otherwise ->+                       return  $ TagOpen "script"+                         (("src",makeDataURI (mime, bs)) :+                          [(x,y) | (x,y) <- as, x /= "src"]) :+                        TagClose "script" : rest+convertTags (t@(TagOpen "link" as):ts) =   case fromAttrib "href" t of-       []  -> return t+       []  -> (t:) <$> convertTags ts        src -> do-           enc <- getDataURI media sourceURL (fromAttrib "type" t) src-           return $ TagOpen "link" (("href",enc) : [(x,y) | (x,y) <- as, x /= "href"])-convertTag _ _ t = return t+           res <- getData (fromAttrib "type" t) src+           case res of+                Left dataUri -> do+                  rest <- convertTags ts+                  return $ TagOpen "link"+                     (("href",dataUri) : [(x,y) | (x,y) <- as, x /= "href"]) :+                     rest+                Right (mime, bs)+                  | "text/css" `isPrefixOf` mime+                    && not ("</" `B.isInfixOf` bs) -> do+                      rest <- convertTags $+                                 dropWhile (==TagClose "link") ts+                      return $+                       TagOpen "style" [("type", mime)]+                       : TagText (toString bs)+                       : TagClose "style"+                       : rest+                  | otherwise -> do+                      rest <- convertTags ts+                      return $ TagOpen "link"+                       (("href",makeDataURI (mime, bs)) :+                         [(x,y) | (x,y) <- as, x /= "href"]) : rest+convertTags (t:ts) = (t:) <$> convertTags ts -cssURLs :: MediaBag -> Maybe String -> FilePath -> ByteString-        -> IO ByteString-cssURLs media sourceURL d orig = do-  res <- runParserT (parseCSSUrls media sourceURL d) () "css" orig+cssURLs :: PandocMonad m+        => FilePath -> ByteString -> m ByteString+cssURLs d orig = do+  res <- runParserT (parseCSSUrls d) () "css" orig   case res of-       Left e    -> warn ("Could not parse CSS: " ++ show e) >> return orig+       Left e    -> do+         report $ CouldNotParseCSS (show e)+         return orig        Right bs  -> return bs -parseCSSUrls :: MediaBag -> Maybe String -> FilePath-             -> ParsecT ByteString () IO ByteString-parseCSSUrls media sourceURL d = B.concat <$> P.many-    (pCSSWhite <|> pCSSComment <|> pCSSUrl media sourceURL d <|> pCSSOther)+parseCSSUrls :: PandocMonad m+             => FilePath -> ParsecT ByteString () m ByteString+parseCSSUrls d = B.concat <$> P.many+  (pCSSWhite <|> pCSSComment <|> pCSSImport d <|> pCSSUrl d <|> pCSSOther) +pCSSImport :: PandocMonad m+           => FilePath -> ParsecT ByteString () m ByteString+pCSSImport d = P.try $ do+  P.string "@import"+  P.spaces+  res <- (pQuoted <|> pUrl) >>= handleCSSUrl d+  P.spaces+  P.char ';'+  P.spaces+  case res of+       Left b       -> return $ B.pack "@import " <> b+       Right (_, b) -> return b+ -- Note: some whitespace in CSS is significant, so we can't collapse it!-pCSSWhite :: ParsecT ByteString () IO ByteString+pCSSWhite :: PandocMonad m => ParsecT ByteString () m ByteString pCSSWhite = B.singleton <$> P.space <* P.spaces -pCSSComment :: ParsecT ByteString () IO ByteString+pCSSComment :: PandocMonad m => ParsecT ByteString () m ByteString pCSSComment = P.try $ do   P.string "/*"   P.manyTill P.anyChar (P.try (P.string "*/"))   return B.empty -pCSSOther :: ParsecT ByteString () IO ByteString-pCSSOther = do+pCSSOther :: PandocMonad m => ParsecT ByteString () m ByteString+pCSSOther =   (B.pack <$> P.many1 (P.noneOf "u/ \n\r\t")) <|>-    (B.singleton <$> P.char 'u') <|>-    (B.singleton <$> P.char '/')+  (B.singleton <$> P.char 'u') <|>+  (B.singleton <$> P.char '/') -pCSSUrl :: MediaBag -> Maybe String -> FilePath-        -> ParsecT ByteString () IO ByteString-pCSSUrl media sourceURL d = P.try $ do+pCSSUrl :: PandocMonad m+        => FilePath -> ParsecT ByteString () m ByteString+pCSSUrl d = P.try $ do+  res <- pUrl >>= handleCSSUrl d+  case res of+       Left b -> return b+       Right (mt,b) -> do+         let enc = makeDataURI (mt, b)+         return (B.pack $ "url(" ++ enc ++ ")")++pQuoted :: PandocMonad m+        => ParsecT ByteString () m (String, ByteString)+pQuoted = P.try $ do+  quote <- P.oneOf "\"'"+  url <- P.manyTill P.anyChar (P.char quote)+  let fallback = B.pack ([quote] ++ trim url ++ [quote])+  return (url, fallback)++pUrl :: PandocMonad m+     => ParsecT ByteString () m (String, ByteString)+pUrl = P.try $ do   P.string "url("   P.spaces   quote <- P.option Nothing (Just <$> P.oneOf "\"'")@@ -130,49 +212,66 @@   P.char ')'   let fallback = B.pack ("url(" ++ maybe "" (:[]) quote ++ trim url ++                             maybe "" (:[]) quote ++ ")")-  case trim url of-      '#':_ -> return fallback-      'd':'a':'t':'a':':':_ -> return fallback+  return (url, fallback)++handleCSSUrl :: PandocMonad m+             => FilePath -> (String, ByteString)+             -> ParsecT ByteString () m+                  (Either ByteString (MimeType, ByteString))+handleCSSUrl d (url, fallback) =+  case escapeURIString (/='|') (trim url) of+      '#':_ -> return $ Left fallback+      'd':'a':'t':'a':':':_ -> return $ Left fallback       u ->  do let url' = if isURI u then u else d </> u-               enc <- lift $ getDataURI media sourceURL "" url'-               return (B.pack $ "url(" ++ enc ++ ")")+               res <- lift $ getData "" url'+               case res of+                    Left uri -> return $ Left (B.pack $ "url(" ++ uri ++ ")")+                    Right (mt, raw) -> do+                      -- note that the downloaded CSS may+                      -- itself contain url(...).+                      b <- if "text/css" `isPrefixOf` mt+                              then cssURLs d raw+                              else return raw+                      return $ Right (mt, b) +getDataURI :: PandocMonad m => MimeType -> String -> m String+getDataURI mimetype src = do+  res <- getData mimetype src+  case res of+       Left uri -> return uri+       Right x  -> return $ makeDataURI x -getDataURI :: MediaBag -> Maybe String -> MimeType -> String-       -> IO String-getDataURI _ _ _ src@('d':'a':'t':'a':':':_) = return src  -- already data: uri-getDataURI media sourceURL mimetype src = do+getData :: PandocMonad m+        => MimeType -> String+        -> m (Either String (MimeType, ByteString))+getData _ src@('d':'a':'t':'a':':':_) = return $ Left src-- already data: uri+getData mimetype src = do   let ext = map toLower $ takeExtension src-  fetchResult <- fetchItem' media sourceURL src-  (raw, respMime) <- case fetchResult of-                          Left msg -> err 67 $ "Could not fetch " ++ src ++-                                               "\n" ++ show msg-                          Right x  -> return x+  (raw, respMime) <- fetchItem src   let raw' = if ext == ".gz"-                then B.concat $ L.toChunks $ Gzip.decompress $ L.fromChunks-                      $ [raw]+                then B.concat $ L.toChunks $ Gzip.decompress $ L.fromChunks [raw]                 else raw-  let mime = case (mimetype, respMime) of-                  ("",Nothing) -> error+  mime <- case (mimetype, respMime) of+                  ("",Nothing) -> throwError $ PandocSomeError                          $ "Could not determine mime type for `" ++ src ++ "'"-                  (x, Nothing) -> x-                  (_, Just x ) -> x-  let cssSourceURL = case parseURI src of-                          Just u-                            | uriScheme u `elem` ["http:","https:"] ->-                                Just $ show u{ uriPath = "",-                                               uriQuery = "",-                                               uriFragment = "" }-                          _ -> Nothing-  result <- if mime == "text/css"-               then cssURLs media cssSourceURL (takeDirectory src) raw'+                  (x, Nothing) -> return x+                  (_, Just x ) -> return x+  result <- if "text/css" `isPrefixOf` mime+               then do+                 oldInputs <- getInputFiles+                 setInputFiles [src]+                 res <- cssURLs (takeDirectory src) raw'+                 setInputFiles oldInputs+                 return res                else return raw'-  return $ makeDataURI mime result+  return $ Right (mime, result) ++ -- | Convert HTML into self-contained HTML, incorporating images, -- scripts, and CSS using data: URIs.-makeSelfContained :: WriterOptions -> String -> IO String-makeSelfContained opts inp = do+makeSelfContained :: PandocMonad m => String -> m String+makeSelfContained inp = do   let tags = parseTags inp-  out' <- mapM (convertTag (writerMediaBag opts) (writerSourceURL opts)) tags+  out' <- convertTags tags   return $ renderTags' out'
src/Text/Pandoc/Shared.hs view
@@ -1,8 +1,12 @@-{-# LANGUAGE DeriveDataTypeable, CPP, MultiParamTypeClasses,-    FlexibleContexts, ScopedTypeVariables, PatternGuards,-    ViewPatterns #-}+{-# LANGUAGE CPP                   #-}+{-# LANGUAGE DeriveDataTypeable    #-}+{-# LANGUAGE FlexibleContexts      #-}+{-# LANGUAGE MultiParamTypeClasses #-}++{-# LANGUAGE ScopedTypeVariables   #-}+{-# LANGUAGE ViewPatterns          #-} {--Copyright (C) 2006-2016 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2006-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -21,7 +25,7 @@  {- |    Module      : Text.Pandoc.Shared-   Copyright   : Copyright (C) 2006-2016 John MacFarlane+   Copyright   : Copyright (C) 2006-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -49,21 +53,18 @@                      toRomanNumeral,                      escapeURI,                      tabFilter,+                     crFilter,                      -- * Date/time                      normalizeDate,                      -- * Pandoc block and inline list processing                      orderedListMarkers,-                     normalizeSpaces,                      extractSpaces,-                     normalize,-                     normalizeInlines,-                     normalizeBlocks,                      removeFormatting,+                     deNote,                      stringify,                      capitalize,                      compactify,-                     compactify',-                     compactify'DL,+                     compactifyDL,                      linesToPara,                      Element (..),                      hierarchicalize,@@ -74,24 +75,19 @@                      isTightList,                      addMetaField,                      makeMeta,+                     eastAsianLineBreakFilter,+                     underlineSpan,                      -- * TagSoup HTML handling                      renderTags',                      -- * File handling                      inDirectory,-                     getDefaultReferenceDocx,-                     getDefaultReferenceODT,-                     readDataFile,-                     readDataFileUTF8,-                     fetchItem,-                     fetchItem',-                     openURL,                      collapseFilePath,                      filteredFilesFromArchive,+                     -- * URI handling+                     schemes,+                     isURI,                      -- * Error handling-                     err,-                     warn,                      mapLeft,-                     hush,                      -- * for squashing blocks                      blocksToInlines,                      -- * Safe read@@ -102,74 +98,37 @@                      pandocVersion                     ) where -import Text.Pandoc.Definition-import Text.Pandoc.Walk-import Text.Pandoc.MediaBag (MediaBag, lookupMedia)-import Text.Pandoc.Builder (Inlines, Blocks, ToMetaValue(..))-import qualified Text.Pandoc.Builder as B-import qualified Text.Pandoc.UTF8 as UTF8-import System.Environment (getProgName)-import System.Exit (exitWith, ExitCode(..))-import Data.Char ( toLower, isLower, isUpper, isAlpha,-                   isLetter, isDigit, isSpace )-import Data.List ( find, stripPrefix, intercalate )-import Data.Maybe (mapMaybe)-import Data.Version ( showVersion )+import Codec.Archive.Zip+import qualified Control.Exception as E+import Control.Monad (MonadPlus (..), msum, unless)+import qualified Control.Monad.State.Strict as S+import qualified Data.ByteString.Lazy as BL+import Data.Char (isAlpha, isDigit, isLetter, isLower, isSpace, isUpper,+                  toLower)+import Data.Data (Data, Typeable)+import Data.List (find, intercalate, stripPrefix) import qualified Data.Map as M-import Network.URI ( escapeURIString, nonStrictRelativeTo,-                     unEscapeString, parseURIReference, isAllowedInURI,-                     parseURI, URI(..) )+import Data.Maybe (mapMaybe)+import Data.Monoid ((<>))+import Data.Sequence (ViewL (..), ViewR (..), viewl, viewr) import qualified Data.Set as Set+import qualified Data.Text as T+import Data.Version (showVersion)+import Network.URI (URI (uriScheme), escapeURIString, parseURI)+import Paths_pandoc (version) import System.Directory-import System.FilePath (splitDirectories, isPathSeparator)+import System.FilePath (isPathSeparator, splitDirectories) import qualified System.FilePath.Posix as Posix-import Text.Pandoc.MIME (MimeType, getMimeType)-import System.FilePath ( (</>), takeExtension, dropExtension)-import Data.Generics (Typeable, Data)-import qualified Control.Monad.State as S-import Control.Monad.Trans (MonadIO (..))-import qualified Control.Exception as E-import Control.Monad (msum, unless, MonadPlus(..))-import Text.Pandoc.Pretty (charWidth)-import Text.Pandoc.Compat.Time-import Data.Time.Clock.POSIX-import System.IO (stderr) import System.IO.Temp-import Text.HTML.TagSoup (renderTagsOptions, RenderOptions(..), Tag(..),-         renderOptions)-import Data.Monoid ((<>))-import qualified Data.ByteString as BS-import qualified Data.ByteString.Char8 as B8-import Data.ByteString.Base64 (decodeLenient)-import Data.Sequence (ViewR(..), ViewL(..), viewl, viewr)-import qualified Data.Text as T (toUpper, pack, unpack)-import Data.ByteString.Lazy (toChunks, fromChunks)-import qualified Data.ByteString.Lazy as BL-import Paths_pandoc (version)--import Codec.Archive.Zip--#ifdef EMBED_DATA_FILES-import Text.Pandoc.Data (dataFiles)-#else-import Paths_pandoc (getDataFileName)-#endif-#ifdef HTTP_CLIENT-import Network.HTTP.Client (httpLbs, responseBody, responseHeaders,-                            Request(port,host))-import Network.HTTP.Client (parseRequest)-import Network.HTTP.Client (newManager)-import Network.HTTP.Client.Internal (addProxy)-import Network.HTTP.Client.TLS (tlsManagerSettings)-import System.Environment (getEnv)-import Network.HTTP.Types.Header ( hContentType)-import Network (withSocketsDo)-#else-import Network.URI (parseURI)-import Network.HTTP (findHeader, rspBody,-                     RequestMethod(..), HeaderName(..), mkRequest)-import Network.Browser (browse, setAllowRedirects, setOutHandler, request)-#endif+import Text.HTML.TagSoup (RenderOptions (..), Tag (..), renderOptions,+                          renderTagsOptions)+import Text.Pandoc.Builder (Blocks, Inlines, ToMetaValue (..))+import qualified Text.Pandoc.Builder as B+import Text.Pandoc.Compat.Time+import Text.Pandoc.Definition+import Text.Pandoc.Generic (bottomUp)+import Text.Pandoc.Pretty (charWidth)+import Text.Pandoc.Walk  -- | Version number of pandoc library. pandocVersion :: String@@ -185,11 +144,11 @@ splitBy isSep lst =   let (first, rest) = break isSep lst       rest'         = dropWhile isSep rest-  in  first:(splitBy isSep rest')+  in  first:splitBy isSep rest'  splitByIndices :: [Int] -> [a] -> [[a]] splitByIndices [] lst = [lst]-splitByIndices (x:xs) lst = first:(splitByIndices (map (\y -> y - x)  xs) rest)+splitByIndices (x:xs) lst = first:splitByIndices (map (\y -> y - x)  xs) rest   where (first, rest) = splitAt x lst  -- | Split string into chunks divided at specified indices.@@ -197,7 +156,7 @@ splitStringByIndices [] lst = [lst] splitStringByIndices (x:xs) lst =   let (first, rest) = splitAt' x lst in-  first : (splitStringByIndices (map (\y -> y - x) xs) rest)+  first : splitStringByIndices (map (\y -> y - x) xs) rest  splitAt' :: Int -> [Char] -> ([Char],[Char]) splitAt' _ []          = ([],[])@@ -236,9 +195,9 @@ escapeStringUsing :: [(Char, String)] -> String -> String escapeStringUsing _ [] = "" escapeStringUsing escapeTable (x:xs) =-  case (lookup x escapeTable) of-       Just str  -> str ++ rest-       Nothing   -> x:rest+  case lookup x escapeTable of+       Just str -> str ++ rest+       Nothing  -> x:rest   where rest = escapeStringUsing escapeTable xs  -- | Strip trailing newlines from string.@@ -260,35 +219,33 @@ -- | Strip leading and trailing characters from string stripFirstAndLast :: String -> String stripFirstAndLast str =-  drop 1 $ take ((length str) - 1) str+  drop 1 $ take (length str - 1) str  -- | Change CamelCase word to hyphenated lowercase (e.g., camel-case). camelCaseToHyphenated :: String -> String camelCaseToHyphenated [] = "" camelCaseToHyphenated (a:b:rest) | isLower a && isUpper b =-  a:'-':(toLower b):(camelCaseToHyphenated rest)-camelCaseToHyphenated (a:rest) = (toLower a):(camelCaseToHyphenated rest)+  a:'-':toLower b:camelCaseToHyphenated rest+camelCaseToHyphenated (a:rest) = toLower a:camelCaseToHyphenated rest  -- | Convert number < 4000 to uppercase roman numeral. toRomanNumeral :: Int -> String-toRomanNumeral x =-  if x >= 4000 || x < 0-     then "?"-     else case x of-              _ | x >= 1000 -> "M" ++ toRomanNumeral (x - 1000)-              _ | x >= 900  -> "CM" ++ toRomanNumeral (x - 900)-              _ | x >= 500  -> "D" ++ toRomanNumeral (x - 500)-              _ | x >= 400  -> "CD" ++ toRomanNumeral (x - 400)-              _ | x >= 100  -> "C" ++ toRomanNumeral (x - 100)-              _ | x >= 90   -> "XC" ++ toRomanNumeral (x - 90)-              _ | x >= 50   -> "L"  ++ toRomanNumeral (x - 50)-              _ | x >= 40   -> "XL" ++ toRomanNumeral (x - 40)-              _ | x >= 10   -> "X" ++ toRomanNumeral (x - 10)-              _ | x == 9    -> "IX"-              _ | x >= 5    -> "V" ++ toRomanNumeral (x - 5)-              _ | x == 4    -> "IV"-              _ | x >= 1    -> "I" ++ toRomanNumeral (x - 1)-              _             -> ""+toRomanNumeral x+  | x >= 4000 || x < 0 = "?"+  | x >= 1000 = "M" ++ toRomanNumeral (x - 1000)+  | x >= 900  = "CM" ++ toRomanNumeral (x - 900)+  | x >= 500  = "D" ++ toRomanNumeral (x - 500)+  | x >= 400  = "CD" ++ toRomanNumeral (x - 400)+  | x >= 100  = "C" ++ toRomanNumeral (x - 100)+  | x >= 90   = "XC" ++ toRomanNumeral (x - 90)+  | x >= 50   = "L"  ++ toRomanNumeral (x - 50)+  | x >= 40   = "XL" ++ toRomanNumeral (x - 40)+  | x >= 10   = "X" ++ toRomanNumeral (x - 10)+  | x == 9    = "IX"+  | x >= 5    = "V" ++ toRomanNumeral (x - 5)+  | x == 4    = "IV"+  | x >= 1    = "I" ++ toRomanNumeral (x - 1)+  | otherwise = ""  -- | Escape whitespace and some punctuation characters in URI. escapeURI :: String -> String@@ -296,27 +253,24 @@   where needsEscaping c = isSpace c || c `elem`                            ['<','>','|','"','{','}','[',']','^', '`'] ---- | Convert tabs to spaces and filter out DOS line endings.--- Tabs will be preserved if tab stop is set to 0.+-- | Convert tabs to spaces. Tabs will be preserved if tab stop is set to 0. tabFilter :: Int       -- ^ Tab stop-          -> String    -- ^ Input-          -> String-tabFilter tabStop =-  let go _ [] = ""-      go _ ('\n':xs) = '\n' : go tabStop xs-      go _ ('\r':'\n':xs) = '\n' : go tabStop xs-      go _ ('\r':xs) = '\n' : go tabStop xs-      go spsToNextStop ('\t':xs) =-        if tabStop == 0-           then '\t' : go tabStop xs-           else replicate spsToNextStop ' ' ++ go tabStop xs-      go 1 (x:xs) =-        x : go tabStop xs-      go spsToNextStop (x:xs) =-        x : go (spsToNextStop - 1) xs-  in  go tabStop+          -> T.Text    -- ^ Input+          -> T.Text+tabFilter 0 = id+tabFilter tabStop = T.unlines . map go . T.lines+  where go s =+         let (s1, s2) = T.break (== '\t') s+         in  if T.null s2+                then s1+                else s1 <> T.replicate+                       (tabStop - (T.length s1 `mod` tabStop)) (T.pack " ")+                       <> go (T.drop 1 s2) +-- | Strip out DOS line endings.+crFilter :: T.Text -> T.Text+crFilter = T.filter (/= '\r')+ -- -- Date/time --@@ -329,7 +283,7 @@   (msum $ map (\fs -> parsetimeWith fs s >>= rejectBadYear) formats :: Maybe Day)   where rejectBadYear day = case toGregorian day of           (y, _, _) | y >= 1601 && y <= 9999 -> Just day-          _ -> Nothing+          _         -> Nothing         parsetimeWith = #if MIN_VERSION_time(1,5,0)              parseTimeM True defaultTimeLocale@@ -366,23 +320,6 @@                             TwoParens    -> "(" ++ str ++ ")"   in  map inDelim nums --- | Normalize a list of inline elements: remove leading and trailing--- @Space@ elements, collapse double @Space@s into singles, and--- remove empty Str elements.-normalizeSpaces :: [Inline] -> [Inline]-normalizeSpaces = cleanup . dropWhile isSpaceOrEmpty- where  cleanup []              = []-        cleanup (Space:rest)    = case dropWhile isSpaceOrEmpty rest of-                                        []     -> []-                                        (x:xs) -> Space : x : cleanup xs-        cleanup ((Str ""):rest) = cleanup rest-        cleanup (x:rest)        = x : cleanup rest--isSpaceOrEmpty :: Inline -> Bool-isSpaceOrEmpty Space = True-isSpaceOrEmpty (Str "") = True-isSpaceOrEmpty _ = False- -- | Extract the leading and trailing spaces from inside an inline element -- and place them outside the element.  SoftBreaks count as Spaces for -- these purposes.@@ -399,183 +336,43 @@                     _                -> mempty in   (left <> f (B.trimInlines . B.Many $ contents) <> right) --- | Normalize @Pandoc@ document, consolidating doubled 'Space's,--- combining adjacent 'Str's and 'Emph's, remove 'Null's and--- empty elements, etc.-normalize :: Pandoc -> Pandoc-normalize (Pandoc (Meta meta) blocks) =-  Pandoc (Meta $ M.map go meta) (normalizeBlocks blocks)-  where go (MetaInlines xs) = MetaInlines $ normalizeInlines xs-        go (MetaBlocks xs)  = MetaBlocks  $ normalizeBlocks xs-        go (MetaList ms)    = MetaList $ map go ms-        go (MetaMap m)      = MetaMap $ M.map go m-        go x                = x--normalizeBlocks :: [Block] -> [Block]-normalizeBlocks (Null : xs) = normalizeBlocks xs-normalizeBlocks (Div attr bs : xs) =-  Div attr (normalizeBlocks bs) : normalizeBlocks xs-normalizeBlocks (BlockQuote bs : xs) =-  case normalizeBlocks bs of-       []    -> normalizeBlocks xs-       bs'   -> BlockQuote bs' : normalizeBlocks xs-normalizeBlocks (BulletList [] : xs) = normalizeBlocks xs-normalizeBlocks (BulletList items : xs) =-  BulletList (map normalizeBlocks items) : normalizeBlocks xs-normalizeBlocks (OrderedList _ [] : xs) = normalizeBlocks xs-normalizeBlocks (OrderedList attr items : xs) =-  OrderedList attr (map normalizeBlocks items) : normalizeBlocks xs-normalizeBlocks (DefinitionList [] : xs) = normalizeBlocks xs-normalizeBlocks (DefinitionList items : xs) =-  DefinitionList (map go items) : normalizeBlocks xs-  where go (ils, bs) = (normalizeInlines ils, map normalizeBlocks bs)-normalizeBlocks (RawBlock _ "" : xs) = normalizeBlocks xs-normalizeBlocks (RawBlock f x : xs) =-   case normalizeBlocks xs of-        (RawBlock f' x' : rest) | f' == f ->-          RawBlock f (x ++ ('\n':x')) : rest-        rest -> RawBlock f x : rest-normalizeBlocks (Para ils : xs) =-  case normalizeInlines ils of-       []   -> normalizeBlocks xs-       ils' -> Para ils' : normalizeBlocks xs-normalizeBlocks (Plain ils : xs) =-  case normalizeInlines ils of-       []   -> normalizeBlocks xs-       ils' -> Plain ils' : normalizeBlocks xs-normalizeBlocks (Header lev attr ils : xs) =-  Header lev attr (normalizeInlines ils) : normalizeBlocks xs-normalizeBlocks (Table capt aligns widths hdrs rows : xs) =-  Table (normalizeInlines capt) aligns widths-    (map normalizeBlocks hdrs) (map (map normalizeBlocks) rows)-  : normalizeBlocks xs-normalizeBlocks (x:xs) = x : normalizeBlocks xs-normalizeBlocks [] = []--normalizeInlines :: [Inline] -> [Inline]-normalizeInlines (Str x : ys) =-  case concat (x : map fromStr strs) of-        ""     -> rest-        n      -> Str n : rest-   where-     (strs, rest)  = span isStr $ normalizeInlines ys-     isStr (Str _) = True-     isStr _       = False-     fromStr (Str z) = z-     fromStr _       = error "normalizeInlines - fromStr - not a Str"-normalizeInlines (Space : SoftBreak : ys) =-  SoftBreak : normalizeInlines ys-normalizeInlines (Space : ys) =-  if null rest-     then []-     else Space : rest-   where isSp Space = True-         isSp _     = False-         rest       = dropWhile isSp $ normalizeInlines ys-normalizeInlines (Emph xs : zs) =-  case normalizeInlines zs of-       (Emph ys : rest) -> normalizeInlines $-         Emph (normalizeInlines $ xs ++ ys) : rest-       rest -> case normalizeInlines xs of-                    []  -> rest-                    xs' -> Emph xs' : rest-normalizeInlines (Strong xs : zs) =-  case normalizeInlines zs of-       (Strong ys : rest) -> normalizeInlines $-         Strong (normalizeInlines $ xs ++ ys) : rest-       rest -> case normalizeInlines xs of-                    []  -> rest-                    xs' -> Strong xs' : rest-normalizeInlines (Subscript xs : zs) =-  case normalizeInlines zs of-       (Subscript ys : rest) -> normalizeInlines $-         Subscript (normalizeInlines $ xs ++ ys) : rest-       rest -> case normalizeInlines xs of-                    []  -> rest-                    xs' -> Subscript xs' : rest-normalizeInlines (Superscript xs : zs) =-  case normalizeInlines zs of-       (Superscript ys : rest) -> normalizeInlines $-         Superscript (normalizeInlines $ xs ++ ys) : rest-       rest -> case normalizeInlines xs of-                    []  -> rest-                    xs' -> Superscript xs' : rest-normalizeInlines (SmallCaps xs : zs) =-  case normalizeInlines zs of-       (SmallCaps ys : rest) -> normalizeInlines $-         SmallCaps (normalizeInlines $ xs ++ ys) : rest-       rest -> case normalizeInlines xs of-                    []  -> rest-                    xs' -> SmallCaps xs' : rest-normalizeInlines (Strikeout xs : zs) =-  case normalizeInlines zs of-       (Strikeout ys : rest) -> normalizeInlines $-         Strikeout (normalizeInlines $ xs ++ ys) : rest-       rest -> case normalizeInlines xs of-                    []  -> rest-                    xs' -> Strikeout xs' : rest-normalizeInlines (RawInline _ [] : ys) = normalizeInlines ys-normalizeInlines (RawInline f xs : zs) =-  case normalizeInlines zs of-       (RawInline f' ys : rest) | f == f' -> normalizeInlines $-         RawInline f (xs ++ ys) : rest-       rest -> RawInline f xs : rest-normalizeInlines (Code _ "" : ys) = normalizeInlines ys-normalizeInlines (Code attr xs : zs) =-  case normalizeInlines zs of-       (Code attr' ys : rest) | attr == attr' -> normalizeInlines $-         Code attr (xs ++ ys) : rest-       rest -> Code attr xs : rest--- allow empty spans, they may carry identifiers etc.--- normalizeInlines (Span _ [] : ys) = normalizeInlines ys-normalizeInlines (Span attr xs : zs) =-  case normalizeInlines zs of-       (Span attr' ys : rest) | attr == attr' -> normalizeInlines $-         Span attr (normalizeInlines $ xs ++ ys) : rest-       rest -> Span attr (normalizeInlines xs) : rest-normalizeInlines (Note bs : ys) = Note (normalizeBlocks bs) :-  normalizeInlines ys-normalizeInlines (Quoted qt ils : ys) =-  Quoted qt (normalizeInlines ils) : normalizeInlines ys-normalizeInlines (Link attr ils t : ys) =-  Link attr (normalizeInlines ils) t : normalizeInlines ys-normalizeInlines (Image attr ils t : ys) =-  Image attr (normalizeInlines ils) t : normalizeInlines ys-normalizeInlines (Cite cs ils : ys) =-  Cite cs (normalizeInlines ils) : normalizeInlines ys-normalizeInlines (x : xs) = x : normalizeInlines xs-normalizeInlines [] = []- -- | Extract inlines, removing formatting. removeFormatting :: Walkable Inline a => a -> [Inline]-removeFormatting = query go . walk deNote+removeFormatting = query go . walk (deNote . deQuote)   where go :: Inline -> [Inline]-        go (Str xs)     = [Str xs]-        go Space        = [Space]-        go SoftBreak    = [SoftBreak]-        go (Code _ x)   = [Str x]-        go (Math _ x)   = [Str x]-        go LineBreak    = [Space]-        go _            = []-        deNote (Note _) = Str ""-        deNote x        = x+        go (Str xs)   = [Str xs]+        go Space      = [Space]+        go SoftBreak  = [SoftBreak]+        go (Code _ x) = [Str x]+        go (Math _ x) = [Str x]+        go LineBreak  = [Space]+        go _          = [] +deNote :: Inline -> Inline+deNote (Note _) = Str ""+deNote x        = x++deQuote :: Inline -> Inline+deQuote (Quoted SingleQuote xs) =+  Span ("",[],[]) (Str "\8216" : xs ++ [Str "\8217"])+deQuote (Quoted DoubleQuote xs) =+  Span ("",[],[]) (Str "\8220" : xs ++ [Str "\8221"])+deQuote x = x+ -- | Convert pandoc structure to a string with formatting removed. -- Footnotes are skipped (since we don't want their contents in link -- labels). stringify :: Walkable Inline a => a -> String-stringify = query go . walk deNote+stringify = query go . walk (deNote . deQuote)   where go :: Inline -> [Char]-        go Space = " "-        go SoftBreak = " "-        go (Str x) = x-        go (Code _ x) = x-        go (Math _ x) = x+        go Space                                       = " "+        go SoftBreak                                   = " "+        go (Str x)                                     = x+        go (Code _ x)                                  = x+        go (Math _ x)                                  = x         go (RawInline (Format "html") ('<':'b':'r':_)) = " " -- see #2105-        go LineBreak = " "-        go _ = ""-        deNote (Note _) = Str ""-        deNote x = x+        go LineBreak                                   = " "+        go _                                           = ""  -- | Bring all regular text in a pandoc structure to uppercase. --@@ -589,28 +386,12 @@         go x       = x  -- | Change final list item from @Para@ to @Plain@ if the list contains--- no other @Para@ blocks.-compactify :: [[Block]]  -- ^ List of list items (each a list of blocks)-           -> [[Block]]-compactify [] = []-compactify items =-  case (init items, last items) of-       (_,[])          -> items-       (others, final) ->-            case last final of-                 Para a -> case (filter isPara $ concat items) of-                                -- if this is only Para, change to Plain-                                [_] -> others ++ [init final ++ [Plain a]]-                                _   -> items-                 _      -> items---- | Change final list item from @Para@ to @Plain@ if the list contains -- no other @Para@ blocks.  Like compactify, but operates on @Blocks@ rather -- than @[Block]@.-compactify' :: [Blocks]  -- ^ List of list items (each a list of blocks)+compactify :: [Blocks]  -- ^ List of list items (each a list of blocks)            -> [Blocks]-compactify' [] = []-compactify' items =+compactify [] = []+compactify items =   let (others, final) = (init items, last items)   in  case reverse (B.toList final) of            (Para a:xs) -> case [Para x | Para x <- concatMap B.toList items] of@@ -619,9 +400,9 @@                             _   -> items            _      -> items --- | Like @compactify'@, but acts on items of definition lists.-compactify'DL :: [(Inlines, [Blocks])] -> [(Inlines, [Blocks])]-compactify'DL items =+-- | Like @compactify@, but acts on items of definition lists.+compactifyDL :: [(Inlines, [Blocks])] -> [(Inlines, [Blocks])]+compactifyDL items =   let defs = concatMap snd items   in  case reverse (concatMap B.toList defs) of            (Para x:xs)@@ -663,7 +444,7 @@     ils' <- walkM f ils     elts' <- walkM f elts     return $ Sec lev nums attr ils' elts'-  query f (Blk x) = query f x+  query f (Blk x)              = query f x   query f (Sec _ _ _ ils elts) = query f ils <> query f elts  instance Walkable Block Element where@@ -674,7 +455,7 @@     ils' <- walkM f ils     elts' <- walkM f elts     return $ Sec lev nums attr ils' elts'-  query f (Blk x) = query f x+  query f (Blk x)              = query f x   query f (Sec _ _ _ ils elts) = query f ils <> query f elts  @@ -687,8 +468,8 @@     map (nbspToSp . toLower) .     filter (\c -> isLetter c || isDigit c || c `elem` "_-. ") .     stringify- where nbspToSp '\160'     =  ' '-       nbspToSp x          =  x+ where nbspToSp '\160' =  ' '+       nbspToSp x      =  x  -- | Convert list of Pandoc blocks into (hierarchical) list of Elements hierarchicalize :: [Block] -> [Element]@@ -696,7 +477,7 @@  hierarchicalizeWithIds :: [Block] -> S.State [Int] [Element] hierarchicalizeWithIds [] = return []-hierarchicalizeWithIds ((Header level attr@(_,classes,_) title'):xs) = do+hierarchicalizeWithIds (Header level attr@(_,classes,_) title':xs) = do   lastnum <- S.get   let lastnum' = take level lastnum   let newnum = case length lastnum' of@@ -709,26 +490,26 @@   sectionContents' <- hierarchicalizeWithIds sectionContents   rest' <- hierarchicalizeWithIds rest   return $ Sec level newnum attr title' sectionContents' : rest'-hierarchicalizeWithIds ((Div ("",["references"],[])-                         (Header level (ident,classes,kvs) title' : xs)):ys) =-  hierarchicalizeWithIds ((Header level (ident,("references":classes),kvs)-                           title') : (xs ++ ys))+hierarchicalizeWithIds (Div ("",["references"],[])+                         (Header level (ident,classes,kvs) title' : xs):ys) =+  hierarchicalizeWithIds (Header level (ident,("references":classes),kvs)+                           title' : (xs ++ ys)) hierarchicalizeWithIds (x:rest) = do   rest' <- hierarchicalizeWithIds rest-  return $ (Blk x) : rest'+  return $ Blk x : rest'  headerLtEq :: Int -> Block -> Bool-headerLtEq level (Header l _ _) = l <= level-headerLtEq level (Div ("",["references"],[]) (Header l _ _ : _))  = l <= level-headerLtEq _ _ = False+headerLtEq level (Header l _ _)                                  = l <= level+headerLtEq level (Div ("",["references"],[]) (Header l _ _ : _)) = l <= level+headerLtEq _ _                                                   = False  -- | Generate a unique identifier from a list of inlines. -- Second argument is a list of already used identifiers. uniqueIdent :: [Inline] -> Set.Set String -> String uniqueIdent title' usedIdents   =  let baseIdent = case inlineListToIdentifier title' of-                        ""   -> "section"-                        x    -> x+                        "" -> "section"+                        x  -> x          numIdent n = baseIdent ++ "-" ++ show n      in  if baseIdent `Set.member` usedIdents            then case find (\x -> not $ numIdent x `Set.member` usedIdents) ([1..60000] :: [Int]) of@@ -738,8 +519,8 @@  -- | True if block is a Header block. isHeaderBlock :: Block -> Bool-isHeaderBlock (Header _ _ _) = True-isHeaderBlock _ = False+isHeaderBlock (Header{}) = True+isHeaderBlock _          = False  -- | Shift header levels up or down. headerShift :: Int -> Pandoc -> Pandoc@@ -765,8 +546,8 @@   Meta $ M.insertWith combine key (toMetaValue val) meta   where combine newval (MetaList xs) = MetaList (xs ++ tolist newval)         combine newval x             = MetaList [x, newval]-        tolist (MetaList ys)         = ys-        tolist y                     = [y]+        tolist (MetaList ys) = ys+        tolist y             = [y]  -- | Create 'Meta' from old-style title, authors, date.  This is -- provided to ease the transition from the old API.@@ -774,9 +555,25 @@ makeMeta title authors date =       addMetaField "title" (B.fromList title)     $ addMetaField "author" (map B.fromList authors)-    $ addMetaField "date" (B.fromList date)-    $ nullMeta+    $ addMetaField "date" (B.fromList date) nullMeta +-- | Remove soft breaks between East Asian characters.+eastAsianLineBreakFilter :: Pandoc -> Pandoc+eastAsianLineBreakFilter = bottomUp go+  where go (x:SoftBreak:y:zs) =+         case (stringify x, stringify y) of+               (xs@(_:_), c:_)+                 | charWidth (last xs) == 2 && charWidth c == 2 -> x:y:zs+               _ -> x:SoftBreak:y:zs+        go xs = xs++-- | Builder for underline.+-- This probably belongs in Builder.hs in pandoc-types.+-- Will be replaced once Underline is an element.+underlineSpan :: Inlines -> Inlines+underlineSpan = B.spanWith ("", ["underline"], [])++ -- -- TagSoup HTML handling --@@ -800,226 +597,14 @@                              setCurrentDirectory                              (const $ setCurrentDirectory path >> action) -getDefaultReferenceDocx :: Maybe FilePath -> IO Archive-getDefaultReferenceDocx datadir = do-  let paths = ["[Content_Types].xml",-               "_rels/.rels",-               "docProps/app.xml",-               "docProps/core.xml",-               "word/document.xml",-               "word/fontTable.xml",-               "word/footnotes.xml",-               "word/numbering.xml",-               "word/settings.xml",-               "word/webSettings.xml",-               "word/styles.xml",-               "word/_rels/document.xml.rels",-               "word/_rels/footnotes.xml.rels",-               "word/theme/theme1.xml"]-  let toLazy = fromChunks . (:[])-  let pathToEntry path = do epochtime <- (floor . utcTimeToPOSIXSeconds) <$>-                                          getCurrentTime-                            contents <- toLazy <$> readDataFile datadir-                                                       ("docx/" ++ path)-                            return $ toEntry path epochtime contents-  mbArchive <- case datadir of-                    Nothing   -> return Nothing-                    Just d    -> do-                       exists <- doesFileExist (d </> "reference.docx")-                       if exists-                          then return (Just (d </> "reference.docx"))-                          else return Nothing-  case mbArchive of-     Just arch -> toArchive <$> BL.readFile arch-     Nothing   -> foldr addEntryToArchive emptyArchive <$>-                     mapM pathToEntry paths--getDefaultReferenceODT :: Maybe FilePath -> IO Archive-getDefaultReferenceODT datadir = do-  let paths = ["mimetype",-               "manifest.rdf",-               "styles.xml",-               "content.xml",-               "meta.xml",-               "settings.xml",-               "Configurations2/accelerator/current.xml",-               "Thumbnails/thumbnail.png",-               "META-INF/manifest.xml"]-  let pathToEntry path = do epochtime <- floor `fmap` getPOSIXTime-                            contents <- (fromChunks . (:[])) `fmap`-                                          readDataFile datadir ("odt/" ++ path)-                            return $ toEntry path epochtime contents-  mbArchive <- case datadir of-                    Nothing   -> return Nothing-                    Just d    -> do-                       exists <- doesFileExist (d </> "reference.odt")-                       if exists-                          then return (Just (d </> "reference.odt"))-                          else return Nothing-  case mbArchive of-     Just arch -> toArchive <$> BL.readFile arch-     Nothing   -> foldr addEntryToArchive emptyArchive <$>-                     mapM pathToEntry paths---readDefaultDataFile :: FilePath -> IO BS.ByteString-readDefaultDataFile "reference.docx" =-  (BS.concat . toChunks . fromArchive) <$> getDefaultReferenceDocx Nothing-readDefaultDataFile "reference.odt" =-  (BS.concat . toChunks . fromArchive) <$> getDefaultReferenceODT Nothing-readDefaultDataFile fname =-#ifdef EMBED_DATA_FILES-  case lookup (makeCanonical fname) dataFiles of-    Nothing       -> err 97 $ "Could not find data file " ++ fname-    Just contents -> return contents-  where makeCanonical = Posix.joinPath . transformPathParts . splitDirectories-        transformPathParts = reverse . foldl go []-        go as     "."  = as-        go (_:as) ".." = as-        go as     x    = x : as-#else-  getDataFileName fname' >>= checkExistence >>= BS.readFile-    where fname' = if fname == "MANUAL.txt" then fname else "data" </> fname--checkExistence :: FilePath -> IO FilePath-checkExistence fn = do-  exists <- doesFileExist fn-  if exists-     then return fn-     else err 97 ("Could not find data file " ++ fn)-#endif---- | Read file from specified user data directory or, if not found there, from--- Cabal data directory.-readDataFile :: Maybe FilePath -> FilePath -> IO BS.ByteString-readDataFile Nothing fname = readDefaultDataFile fname-readDataFile (Just userDir) fname = do-  exists <- doesFileExist (userDir </> fname)-  if exists-     then BS.readFile (userDir </> fname)-     else readDefaultDataFile fname---- | Same as 'readDataFile' but returns a String instead of a ByteString.-readDataFileUTF8 :: Maybe FilePath -> FilePath -> IO String-readDataFileUTF8 userDir fname =-  UTF8.toString `fmap` readDataFile userDir fname---- | Specialized version of parseURIReference that disallows--- single-letter schemes.  Reason:  these are usually windows absolute--- paths.-parseURIReference' :: String -> Maybe URI-parseURIReference' s =-  case parseURIReference s of-       Just u-         | length (uriScheme u) > 2  -> Just u-         | null (uriScheme u)        -> Just u  -- protocol-relative-       _                             -> Nothing---- | Fetch an image or other item from the local filesystem or the net.--- Returns raw content and maybe mime type.-fetchItem :: Maybe String -> String-          -> IO (Either E.SomeException (BS.ByteString, Maybe MimeType))-fetchItem sourceURL s =-  case (sourceURL >>= parseURIReference' . ensureEscaped, ensureEscaped s) of-       (Just u, s') -> -- try fetching from relative path at source-          case parseURIReference' s' of-               Just u' -> openURL $ show $ u' `nonStrictRelativeTo` u-               Nothing -> openURL s' -- will throw error-       (Nothing, s'@('/':'/':_)) ->  -- protocol-relative URI-          case parseURIReference' s' of-               Just u' -> openURL $ show $ u' `nonStrictRelativeTo` httpcolon-               Nothing -> openURL s' -- will throw error-       (Nothing, s') ->-          case parseURI s' of  -- requires absolute URI-               -- We don't want to treat C:/ as a scheme:-               Just u' | length (uriScheme u') > 2 -> openURL (show u')-               Just u' | uriScheme u' == "file:" ->-                    E.try $ readLocalFile $ dropWhile (=='/') (uriPath u')-               _ -> E.try $ readLocalFile fp -- get from local file system-  where readLocalFile f = do-          cont <- BS.readFile f-          return (cont, mime)-        httpcolon = URI{ uriScheme = "http:",-                         uriAuthority = Nothing,-                         uriPath = "",-                         uriQuery = "",-                         uriFragment = "" }-        dropFragmentAndQuery = takeWhile (\c -> c /= '?' && c /= '#')-        fp = unEscapeString $ dropFragmentAndQuery s-        mime = case takeExtension fp of-                    ".gz" -> getMimeType $ dropExtension fp-                    ".svgz" -> getMimeType $ dropExtension fp ++ ".svg"-                    x     -> getMimeType x-        ensureEscaped = escapeURIString isAllowedInURI . map convertSlash-        convertSlash '\\' = '/'-        convertSlash x    = x---- | Like 'fetchItem', but also looks for items in a 'MediaBag'.-fetchItem' :: MediaBag -> Maybe String -> String-           -> IO (Either E.SomeException (BS.ByteString, Maybe MimeType))-fetchItem' media sourceURL s = do-  case lookupMedia s media of-       Nothing -> fetchItem sourceURL s-       Just (mime, bs) -> return $ Right (BS.concat $ toChunks bs, Just mime)---- | Read from a URL and return raw data and maybe mime type.-openURL :: String -> IO (Either E.SomeException (BS.ByteString, Maybe MimeType))-openURL u-  | Just u'' <- stripPrefix "data:" u =-    let mime     = takeWhile (/=',') u''-        contents = B8.pack $ unEscapeString $ drop 1 $ dropWhile (/=',') u''-    in  return $ Right (decodeLenient contents, Just mime)-#ifdef HTTP_CLIENT-  | otherwise = withSocketsDo $ E.try $ do-     let parseReq = parseRequest-     (proxy :: Either E.SomeException String) <- E.try $ getEnv "http_proxy"-     req <- parseReq u-     req' <- case proxy of-                     Left _   -> return req-                     Right pr -> (parseReq pr >>= \r ->-                                  return $ addProxy (host r) (port r) req)-                                  `mplus` return req-     resp <- newManager tlsManagerSettings >>= httpLbs req'-     return (BS.concat $ toChunks $ responseBody resp,-             UTF8.toString `fmap` lookup hContentType (responseHeaders resp))-#else-  | otherwise = E.try $ getBodyAndMimeType `fmap` browse-              (do liftIO $ UTF8.hPutStrLn stderr $ "Fetching " ++ u ++ "..."-                  setOutHandler $ const (return ())-                  setAllowRedirects True-                  request (getRequest' u'))-  where getBodyAndMimeType (_, r) = (rspBody r, findHeader HdrContentType r)-        getRequest' uriString = case parseURI uriString of-                                   Nothing -> error ("Not a valid URL: " ++-                                                        uriString)-                                   Just v  -> mkRequest GET v-        u' = escapeURIString (/= '|') u  -- pipes are rejected by Network.URI-#endif- -- -- Error reporting -- -err :: Int -> String -> IO a-err exitCode msg = do-  name <- getProgName-  UTF8.hPutStrLn stderr $ name ++ ": " ++ msg-  exitWith $ ExitFailure exitCode-  return undefined--warn :: MonadIO m => String -> m ()-warn msg = liftIO $ do-  name <- getProgName-  UTF8.hPutStrLn stderr $ "[" ++ name ++ " warning] " ++ msg- mapLeft :: (a -> b) -> Either a c -> Either b c-mapLeft f (Left x) = Left (f x)+mapLeft f (Left x)  = Left (f x) mapLeft _ (Right x) = Right x -hush :: Either a b -> Maybe b-hush (Left _) = Nothing-hush (Right x) = Just x- -- | Remove intermediate "." and ".." directories from a path. -- -- > collapseFilePath "./foo" == "foo"@@ -1034,14 +619,14 @@   where     go rs "." = rs     go r@(p:rs) ".." = case p of-                            ".." -> ("..":r)-                            (checkPathSeperator -> Just True) -> ("..":r)-                            _ -> rs+                            ".."                              -> "..":r+                            (checkPathSeperator -> Just True) -> "..":r+                            _                                 -> rs     go _ (checkPathSeperator -> Just True) = [[Posix.pathSeparator]]     go rs x = x:rs-    isSingleton [] = Nothing+    isSingleton []  = Nothing     isSingleton [x] = Just x-    isSingleton _ = Nothing+    isSingleton _   = Nothing     checkPathSeperator = fmap isPathSeparator . isSingleton  --@@ -1054,6 +639,71 @@     fileAndBinary :: Archive -> FilePath -> Maybe (FilePath, BL.ByteString)     fileAndBinary a fp = findEntryByPath fp a >>= \e -> Just (fp, fromEntry e) ++--+-- IANA URIs+--++-- | Schemes from http://www.iana.org/assignments/uri-schemes.html plus+-- the unofficial schemes doi, javascript, isbn, pmid.+schemes :: Set.Set String+schemes = Set.fromList+  -- Official IANA schemes+  [ "aaa", "aaas", "about", "acap", "acct", "acr", "adiumxtra", "afp", "afs"+  , "aim", "appdata", "apt", "attachment", "aw", "barion", "beshare", "bitcoin"+  , "blob", "bolo", "browserext", "callto", "cap", "chrome", "chrome-extension"+  , "cid", "coap", "coaps", "com-eventbrite-attendee", "content", "crid", "cvs"+  , "data", "dav", "dict", "dis", "dlna-playcontainer", "dlna-playsingle"+  , "dns", "dntp", "dtn", "dvb", "ed2k", "example", "facetime", "fax", "feed"+  , "feedready", "file", "filesystem", "finger", "fish", "ftp", "geo", "gg"+  , "git", "gizmoproject", "go", "gopher", "graph", "gtalk", "h323", "ham"+  , "hcp", "http", "https", "hxxp", "hxxps", "hydrazone", "iax", "icap", "icon"+  , "im", "imap", "info", "iotdisco", "ipn", "ipp", "ipps", "irc", "irc6"+  , "ircs", "iris", "iris.beep", "iris.lwz", "iris.xpc", "iris.xpcs"+  , "isostore", "itms", "jabber", "jar", "jms", "keyparc", "lastfm", "ldap"+  , "ldaps", "lvlt", "magnet", "mailserver", "mailto", "maps", "market"+  , "message", "mid", "mms", "modem", "mongodb", "moz", "ms-access"+  , "ms-browser-extension", "ms-drive-to", "ms-enrollment", "ms-excel"+  , "ms-gamebarservices", "ms-getoffice", "ms-help", "ms-infopath"+  , "ms-media-stream-id", "ms-officeapp", "ms-project", "ms-powerpoint"+  , "ms-publisher", "ms-search-repair", "ms-secondary-screen-controller"+  , "ms-secondary-screen-setup", "ms-settings", "ms-settings-airplanemode"+  , "ms-settings-bluetooth", "ms-settings-camera", "ms-settings-cellular"+  , "ms-settings-cloudstorage", "ms-settings-connectabledevices"+  , "ms-settings-displays-topology", "ms-settings-emailandaccounts"+  , "ms-settings-language", "ms-settings-location", "ms-settings-lock"+  , "ms-settings-nfctransactions", "ms-settings-notifications"+  , "ms-settings-power", "ms-settings-privacy", "ms-settings-proximity"+  , "ms-settings-screenrotation", "ms-settings-wifi", "ms-settings-workplace"+  , "ms-spd", "ms-sttoverlay", "ms-transit-to", "ms-virtualtouchpad"+  , "ms-visio", "ms-walk-to", "ms-whiteboard", "ms-whiteboard-cmd", "ms-word"+  , "msnim", "msrp", "msrps", "mtqp", "mumble", "mupdate", "mvn", "news", "nfs"+  , "ni", "nih", "nntp", "notes", "ocf", "oid", "onenote", "onenote-cmd"+  , "opaquelocktoken", "pack", "palm", "paparazzi", "pkcs11", "platform", "pop"+  , "pres", "prospero", "proxy", "pwid", "psyc", "qb", "query", "redis"+  , "rediss", "reload", "res", "resource", "rmi", "rsync", "rtmfp", "rtmp"+  , "rtsp", "rtsps", "rtspu", "secondlife", "service", "session", "sftp", "sgn"+  , "shttp", "sieve", "sip", "sips", "skype", "smb", "sms", "smtp", "snews"+  , "snmp", "soap.beep", "soap.beeps", "soldat", "spotify", "ssh", "steam"+  , "stun", "stuns", "submit", "svn", "tag", "teamspeak", "tel", "teliaeid"+  , "telnet", "tftp", "things", "thismessage", "tip", "tn3270", "tool", "turn"+  , "turns", "tv", "udp", "unreal", "urn", "ut2004", "v-event", "vemmi"+  , "ventrilo", "videotex", "vnc", "view-source", "wais", "webcal", "wpid"+  , "ws", "wss", "wtai", "wyciwyg", "xcon", "xcon-userid", "xfire"+  , "xmlrpc.beep", "xmlrpc.beeps", "xmpp", "xri", "ymsgr", "z39.50", "z39.50r"+  , "z39.50s"+  -- Inofficial schemes+  , "doi", "isbn", "javascript", "pmid"+  ]++-- | Check if the string is a valid URL with a IANA or frequently used but+-- unofficial scheme (see @schemes@).+isURI :: String -> Bool+isURI = maybe False hasKnownScheme . parseURI+  where+    hasKnownScheme = (`Set.member` schemes) . map toLower .+                     filter (/= ':') . uriScheme+ --- --- Squash blocks into inlines ---@@ -1074,9 +724,9 @@   where     f (ils, blkslst) = ils ++       [Str ":", Space] ++-      (concatMap blocksToInlines blkslst)+      concatMap blocksToInlines blkslst blockToInlines (Header _ _  ils) = ils-blockToInlines (HorizontalRule) = []+blockToInlines HorizontalRule = [] blockToInlines (Table _ _ _ headers rows) =   intercalate [LineBreak] $ map (concatMap blocksToInlines) tbl   where
src/Text/Pandoc/Slides.hs view
@@ -1,5 +1,5 @@ {--Copyright (C) 2012-2016 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2012-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -18,7 +18,7 @@  {- |    Module      : Text.Pandoc.Slides-   Copyright   : Copyright (C) 2012-2016 John MacFarlane+   Copyright   : Copyright (C) 2012-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -40,9 +40,9 @@                  | otherwise               = go least (x:xs)         go least (_ : xs) = go least xs         go least [] = least-        nonHOrHR (Header{}) = False-        nonHOrHR (HorizontalRule) = False-        nonHOrHR _ = True+        nonHOrHR Header{}       = False+        nonHOrHR HorizontalRule = False+        nonHOrHR _              = True  -- | Prepare a block list to be passed to hierarchicalize. prepSlides :: Int -> [Block] -> [Block]
src/Text/Pandoc/Templates.hs view
@@ -1,7 +1,9 @@-{-# LANGUAGE TypeSynonymInstances, FlexibleInstances,-    OverloadedStrings, GeneralizedNewtypeDeriving #-}+{-# LANGUAGE FlexibleInstances    #-}++{-# LANGUAGE OverloadedStrings    #-}+{-# LANGUAGE TypeSynonymInstances #-} {--Copyright (C) 2009-2016 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2009-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -20,7 +22,7 @@  {- |    Module      : Text.Pandoc.Templates-   Copyright   : Copyright (C) 2009-2016 John MacFarlane+   Copyright   : Copyright (C) 2009-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -31,44 +33,51 @@  -} -module Text.Pandoc.Templates ( renderTemplate+module Text.Pandoc.Templates ( module Text.DocTemplates                              , renderTemplate'-                             , TemplateTarget-                             , varListToJSON-                             , compileTemplate-                             , Template-                             , getDefaultTemplate ) where+                             , getDefaultTemplate+                             ) where -import Text.DocTemplates (Template, TemplateTarget, compileTemplate,-                          renderTemplate, applyTemplate,-                          varListToJSON)-import Data.Aeson (ToJSON(..))+import Control.Monad.Except (throwError)+import Data.Aeson (ToJSON (..)) import qualified Data.Text as T-import System.FilePath ((</>), (<.>))-import qualified Control.Exception.Extensible as E (try, IOException)-import Text.Pandoc.Shared (readDataFileUTF8)+import System.FilePath ((<.>), (</>))+import Text.DocTemplates (Template, TemplateTarget, applyTemplate,+                          compileTemplate, renderTemplate, varListToJSON)+import Text.Pandoc.Class (PandocMonad, readDataFile)+import Text.Pandoc.Error+import qualified Text.Pandoc.UTF8 as UTF8  -- | Get default template for the specified writer.-getDefaultTemplate :: (Maybe FilePath) -- ^ User data directory to search first-                   -> String           -- ^ Name of writer-                   -> IO (Either E.IOException String)-getDefaultTemplate user writer = do+getDefaultTemplate :: PandocMonad m+                   => String           -- ^ Name of writer+                   -> m String+getDefaultTemplate writer = do   let format = takeWhile (`notElem` ("+-" :: String)) writer  -- strip off extensions   case format of-       "native" -> return $ Right ""-       "json"   -> return $ Right ""-       "docx"   -> return $ Right ""-       "fb2"    -> return $ Right ""-       "odt"    -> getDefaultTemplate user "opendocument"-       "markdown_strict"   -> getDefaultTemplate user "markdown"-       "multimarkdown"     -> getDefaultTemplate user "markdown"-       "markdown_github"   -> getDefaultTemplate user "markdown"-       "markdown_mmd"      -> getDefaultTemplate user "markdown"-       "markdown_phpextra" -> getDefaultTemplate user "markdown"+       "native"  -> return ""+       "json"    -> return ""+       "docx"    -> return ""+       "fb2"     -> return ""+       "odt"     -> getDefaultTemplate "opendocument"+       "html"    -> getDefaultTemplate "html5"+       "docbook" -> getDefaultTemplate "docbook5"+       "epub"    -> getDefaultTemplate "epub3"+       "beamer"  -> getDefaultTemplate "latex"+       "markdown_strict"   -> getDefaultTemplate "markdown"+       "multimarkdown"     -> getDefaultTemplate "markdown"+       "markdown_github"   -> getDefaultTemplate "markdown"+       "markdown_mmd"      -> getDefaultTemplate "markdown"+       "markdown_phpextra" -> getDefaultTemplate "markdown"+       "gfm"               -> getDefaultTemplate "commonmark"        _        -> let fname = "templates" </> "default" <.> format-                   in  E.try $ readDataFileUTF8 user fname---- | Like 'applyTemplate', but raising an error if compilation fails.-renderTemplate' :: (ToJSON a, TemplateTarget b) => String -> a -> b-renderTemplate' template = either error id . applyTemplate (T.pack template)+                   in  UTF8.toString <$> readDataFile fname +-- | Like 'applyTemplate', but runs in PandocMonad and+-- raises an error if compilation fails.+renderTemplate' :: (PandocMonad m, ToJSON a, TemplateTarget b)+                => String -> a -> m b+renderTemplate' template context =+  case applyTemplate (T.pack template) context of+       Left e  -> throwError (PandocTemplateError e)+       Right r -> return r
+ src/Text/Pandoc/Translations.hs view
@@ -0,0 +1,112 @@+{-# LANGUAGE DeriveGeneric              #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-+Copyright (C) 2017 John MacFarlane <jgm@berkeley.edu>++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation; either version 2 of the License, or+(at your option) any later version.++This program is distributed in the hope that it will be useful,+but WITHOUT ANY WARRANTY; without even the implied warranty of+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+GNU General Public License for more details.++You should have received a copy of the GNU General Public License+along with this program; if not, write to the Free Software+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+-}++{- |+   Module      : Text.Pandoc.Translations+   Copyright   : Copyright (C) 2017 John MacFarlane+   License     : GNU GPL, version 2 or above++   Maintainer  : John MacFarlane <jgm@berkeley.edu>+   Stability   : alpha+   Portability : portable++Data types for localization.++Translations are stored in @data/translations/langname.trans@,+where langname can be the full BCP47 language specifier, or+just the language part.  File format is:++> # A comment, ignored+> Figure: Figura+> Index: Indeksi++-}+module Text.Pandoc.Translations (+                           Term(..)+                         , Translations+                         , lookupTerm+                         , readTranslations+                         )+where+import Data.Aeson.Types (typeMismatch)+import qualified Data.HashMap.Strict as HM+import qualified Data.Map as M+import Data.Text as T+import Data.Yaml as Yaml+import GHC.Generics (Generic)+import Text.Pandoc.Shared (safeRead)+import qualified Text.Pandoc.UTF8 as UTF8++data Term =+    Preface+  | References+  | Abstract+  | Bibliography+  | Chapter+  | Appendix+  | Contents+  | ListOfFigures+  | ListOfTables+  | Index+  | Figure+  | Table+  | Part+  | Page+  | See+  | SeeAlso+  | Encl+  | Cc+  | To+  | Proof+  | Glossary+  | Listing+  deriving (Show, Eq, Ord, Generic, Enum, Read)++newtype Translations = Translations (M.Map Term String)+        deriving (Show, Generic, Monoid)++instance FromJSON Term where+  parseJSON (String t) = case safeRead (T.unpack t) of+                               Just t' -> pure t'+                               Nothing -> fail $ "Invalid Term name " +++                                                 show t+  parseJSON invalid = typeMismatch "Term" invalid++instance FromJSON Translations where+  parseJSON (Object hm) = do+    xs <- mapM addItem (HM.toList hm)+    return $ Translations (M.fromList xs)+    where addItem (k,v) =+            case safeRead (T.unpack k) of+                 Nothing -> fail $ "Invalid Term name " ++ show k+                 Just t  ->+                   case v of+                        (String s) -> return (t, T.unpack $ T.strip s)+                        inv        -> typeMismatch "String" inv+  parseJSON invalid = typeMismatch "Translations" invalid++lookupTerm :: Term -> Translations -> Maybe String+lookupTerm t (Translations tm) = M.lookup t tm++readTranslations :: String -> Either String Translations+readTranslations s =+  case Yaml.decodeEither' $ UTF8.fromString s of+       Left err' -> Left $ prettyPrintParseException err'+       Right t   -> Right t
src/Text/Pandoc/UTF8.hs view
@@ -1,5 +1,6 @@+{-# LANGUAGE OverloadedStrings #-} {--Copyright (C) 2010-2016 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2010-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -18,7 +19,7 @@  {- |    Module      : Text.Pandoc.UTF8-   Copyright   : Copyright (C) 2010-2016 John MacFarlane+   Copyright   : Copyright (C) 2010-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -28,16 +29,25 @@ UTF-8 aware string IO functions that will work with GHC 6.10, 6.12, or 7. -} module Text.Pandoc.UTF8 ( readFile-                        , writeFile                         , getContents+                        , writeFileWith+                        , writeFile+                        , putStrWith                         , putStr+                        , putStrLnWith                         , putStrLn+                        , hPutStrWith                         , hPutStr+                        , hPutStrLnWith                         , hPutStrLn                         , hGetContents                         , toString+                        , toText                         , fromString+                        , fromText                         , toStringLazy+                        , fromTextLazy+                        , toTextLazy                         , fromStringLazy                         , encodePath                         , decodeArg@@ -45,39 +55,59 @@  where -import System.IO hiding (readFile, writeFile, getContents,-                          putStr, putStrLn, hPutStr, hPutStrLn, hGetContents)-import Prelude hiding (readFile, writeFile, getContents, putStr, putStrLn)-import qualified System.IO as IO import qualified Data.ByteString.Char8 as B-import qualified Data.ByteString.Lazy as BL-import qualified Data.Text.Encoding as T+import qualified Data.ByteString.Lazy.Char8 as BL import qualified Data.Text as T+import qualified Data.Text.Encoding as T import qualified Data.Text.Lazy as TL import qualified Data.Text.Lazy.Encoding as TL+import Prelude hiding (getContents, putStr, putStrLn, readFile, writeFile)+import System.IO hiding (getContents, hGetContents, hPutStr, hPutStrLn, putStr,+                  putStrLn, readFile, writeFile)+import qualified System.IO as IO  readFile :: FilePath -> IO String readFile f = do   h <- openFile (encodePath f) ReadMode   hGetContents h -writeFile :: FilePath -> String -> IO ()-writeFile f s = withFile (encodePath f) WriteMode $ \h -> hPutStr h s- getContents :: IO String getContents = hGetContents stdin +writeFileWith :: Newline -> FilePath -> String -> IO ()+writeFileWith eol f s =+  withFile (encodePath f) WriteMode $ \h -> hPutStrWith eol h s++writeFile :: FilePath -> String -> IO ()+writeFile = writeFileWith nativeNewline++putStrWith :: Newline -> String -> IO ()+putStrWith eol s = hPutStrWith eol stdout s+ putStr :: String -> IO ()-putStr s = hPutStr stdout s+putStr = putStrWith nativeNewline +putStrLnWith :: Newline -> String -> IO ()+putStrLnWith eol s = hPutStrLnWith eol stdout s+ putStrLn :: String -> IO ()-putStrLn s = hPutStrLn stdout s+putStrLn = putStrLnWith nativeNewline +hPutStrWith :: Newline -> Handle -> String -> IO ()+hPutStrWith eol h s =+  hSetNewlineMode h (NewlineMode eol eol) >>+  hSetEncoding h utf8 >> IO.hPutStr h s+ hPutStr :: Handle -> String -> IO ()-hPutStr h s = hSetEncoding h utf8 >> IO.hPutStr h s+hPutStr = hPutStrWith nativeNewline +hPutStrLnWith :: Newline -> Handle -> String -> IO ()+hPutStrLnWith eol h s =+  hSetNewlineMode h (NewlineMode eol eol) >>+  hSetEncoding h utf8 >> IO.hPutStrLn h s+ hPutStrLn :: Handle -> String -> IO ()-hPutStrLn h s = hSetEncoding h utf8 >> IO.hPutStrLn h s+hPutStrLn = hPutStrLnWith nativeNewline  hGetContents :: Handle -> IO String hGetContents = fmap toString . B.hGetContents@@ -85,34 +115,47 @@ --                   >> hSetNewlineMode h universalNewlineMode --                   >> IO.hGetContents h --- | Drop BOM (byte order marker) if present at beginning of string.--- Note that Data.Text converts the BOM to code point FEFF, zero-width--- no-break space, so if the string begins with this  we strip it off.-dropBOM :: String -> String-dropBOM ('\xFEFF':xs) = xs-dropBOM xs = xs--filterCRs :: String -> String-filterCRs ('\r':'\n':xs) = '\n': filterCRs xs-filterCRs ('\r':xs) = '\n' : filterCRs xs-filterCRs (x:xs) = x : filterCRs xs-filterCRs []     = []+-- | Convert UTF8-encoded ByteString to Text, also+-- removing '\r' characters.+toText :: B.ByteString -> T.Text+toText = T.decodeUtf8 . filterCRs . dropBOM+  where dropBOM bs =+         if "\xEF\xBB\xBF" `B.isPrefixOf` bs+            then B.drop 3 bs+            else bs+        filterCRs = B.filter (/='\r')  -- | Convert UTF8-encoded ByteString to String, also -- removing '\r' characters. toString :: B.ByteString -> String-toString = filterCRs . dropBOM . T.unpack . T.decodeUtf8+toString = T.unpack . toText -fromString :: String -> B.ByteString-fromString = T.encodeUtf8 . T.pack+-- | Convert UTF8-encoded ByteString to Text, also+-- removing '\r' characters.+toTextLazy :: BL.ByteString -> TL.Text+toTextLazy = TL.decodeUtf8 . filterCRs . dropBOM+  where dropBOM bs =+         if "\xEF\xBB\xBF" `BL.isPrefixOf` bs+            then BL.drop 3 bs+            else bs+        filterCRs = BL.filter (/='\r')  -- | Convert UTF8-encoded ByteString to String, also -- removing '\r' characters. toStringLazy :: BL.ByteString -> String-toStringLazy = filterCRs . dropBOM . TL.unpack . TL.decodeUtf8+toStringLazy = TL.unpack . toTextLazy +fromText :: T.Text -> B.ByteString+fromText = T.encodeUtf8++fromTextLazy :: TL.Text -> BL.ByteString+fromTextLazy = TL.encodeUtf8++fromString :: String -> B.ByteString+fromString = fromText . T.pack+ fromStringLazy :: String -> BL.ByteString-fromStringLazy = TL.encodeUtf8 . TL.pack+fromStringLazy = fromTextLazy . TL.pack  encodePath :: FilePath -> FilePath encodePath = id
src/Text/Pandoc/UUID.hs view
@@ -1,5 +1,5 @@ {--Copyright (C) 2010-2016 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2010-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -18,7 +18,7 @@  {- |    Module      : Text.Pandoc.UUID-   Copyright   : Copyright (C) 2010-2016 John MacFarlane+   Copyright   : Copyright (C) 2010-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -29,13 +29,12 @@ in RFC4122. See http://tools.ietf.org/html/rfc4122 -} -module Text.Pandoc.UUID ( UUID, getRandomUUID ) where+module Text.Pandoc.UUID ( UUID(..), getRandomUUID, getUUID ) where -import Text.Printf ( printf )-import System.Random ( randomIO )+import Data.Bits (clearBit, setBit) import Data.Word-import Data.Bits ( setBit, clearBit )-import Control.Monad ( liftM )+import System.Random (RandomGen, getStdGen, randoms)+import Text.Printf (printf)  data UUID = UUID Word8 Word8 Word8 Word8 Word8 Word8 Word8 Word8                  Word8 Word8 Word8 Word8 Word8 Word8 Word8 Word8@@ -64,14 +63,15 @@    printf "%02x" o ++    printf "%02x" p -getRandomUUID :: IO UUID-getRandomUUID = do-  let getRN :: a -> IO Word8-      getRN _ = liftM fromIntegral (randomIO :: IO Int)-  [a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p] <- mapM getRN ([1..16] :: [Int])+getUUID :: RandomGen g => g -> UUID+getUUID gen =+  let [a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p] = take 16 $ randoms gen :: [Word8]   -- set variant-  let i' = i `setBit` 7 `clearBit` 6+      i' = i `setBit` 7 `clearBit` 6   -- set version (0100 for random)-  let g' = g `clearBit` 7 `setBit` 6 `clearBit` 5 `clearBit` 4-  return $ UUID a b c d e f g' h i' j k l m n o p+      g' = g `clearBit` 7 `setBit` 6 `clearBit` 5 `clearBit` 4+  in+    UUID a b c d e f g' h i' j k l m n o p +getRandomUUID :: IO UUID+getRandomUUID = getUUID <$> getStdGen
+ src/Text/Pandoc/Writers.hs view
@@ -0,0 +1,192 @@+{-+Copyright (C) 2006-2017 John MacFarlane <jgm@berkeley.edu>++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation; either version 2 of the License, or+(at your option) any later version.++This program is distributed in the hope that it will be useful,+but WITHOUT ANY WARRANTY; without even the implied warranty of+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+GNU General Public License for more details.++You should have received a copy of the GNU General Public License+along with this program; if not, write to the Free Software+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+-}+{-# LANGUAGE FlexibleInstances   #-}+{-# LANGUAGE GADTs               #-}+{-# LANGUAGE ScopedTypeVariables #-}++{- |+   Module      : Text.Pandoc+   Copyright   : Copyright (C) 2006-2017 John MacFarlane+   License     : GNU GPL, version 2 or above++   Maintainer  : John MacFarlane <jgm@berkeley.edu>+   Stability   : alpha+   Portability : portable++This helper module exports all writers functions.+-}+module Text.Pandoc.Writers+  (+    -- * Writers: converting /from/ Pandoc format+      Writer(..)+    , writers+    , writeAsciiDoc+    , writeBeamer+    , writeCommonMark+    , writeConTeXt+    , writeCustom+    , writeDZSlides+    , writeDocbook4+    , writeDocbook5+    , writeDocx+    , writeDokuWiki+    , writeEPUB2+    , writeEPUB3+    , writeFB2+    , writeHaddock+    , writeHtml4+    , writeHtml4String+    , writeHtml5+    , writeHtml5String+    , writeICML+    , writeJATS+    , writeJSON+    , writeLaTeX+    , writeMan+    , writeMarkdown+    , writeMediaWiki+    , writeMs+    , writeMuse+    , writeNative+    , writeODT+    , writeOPML+    , writeOpenDocument+    , writeOrg+    , writePlain+    , writeRST+    , writeRTF+    , writeRevealJs+    , writeS5+    , writeSlideous+    , writeSlidy+    , writeTEI+    , writeTexinfo+    , writeTextile+    , writeZimWiki+    , getWriter+    ) where++import Data.Aeson+import qualified Data.ByteString.Lazy as BL+import Data.List (intercalate)+import Data.Text (Text)+import Text.Pandoc.Class+import Text.Pandoc.Definition+import Text.Pandoc.Options+import qualified Text.Pandoc.UTF8 as UTF8+import Text.Pandoc.Writers.AsciiDoc+import Text.Pandoc.Writers.CommonMark+import Text.Pandoc.Writers.ConTeXt+import Text.Pandoc.Writers.Custom+import Text.Pandoc.Writers.Docbook+import Text.Pandoc.Writers.Docx+import Text.Pandoc.Writers.DokuWiki+import Text.Pandoc.Writers.EPUB+import Text.Pandoc.Writers.FB2+import Text.Pandoc.Writers.Haddock+import Text.Pandoc.Writers.HTML+import Text.Pandoc.Writers.ICML+import Text.Pandoc.Writers.JATS+import Text.Pandoc.Writers.LaTeX+import Text.Pandoc.Writers.Man+import Text.Pandoc.Writers.Markdown+import Text.Pandoc.Writers.MediaWiki+import Text.Pandoc.Writers.Ms+import Text.Pandoc.Writers.Muse+import Text.Pandoc.Writers.Native+import Text.Pandoc.Writers.ODT+import Text.Pandoc.Writers.OpenDocument+import Text.Pandoc.Writers.OPML+import Text.Pandoc.Writers.Org+import Text.Pandoc.Writers.RST+import Text.Pandoc.Writers.RTF+import Text.Pandoc.Writers.TEI+import Text.Pandoc.Writers.Texinfo+import Text.Pandoc.Writers.Textile+import Text.Pandoc.Writers.ZimWiki+import Text.Parsec.Error++data Writer m = TextWriter (WriterOptions -> Pandoc -> m Text)+              | ByteStringWriter (WriterOptions -> Pandoc -> m BL.ByteString)++-- | Association list of formats and writers.+writers :: PandocMonad m => [ ( String, Writer m) ]+writers = [+   ("native"       , TextWriter writeNative)+  ,("json"         , TextWriter $ \o d -> return $ writeJSON o d)+  ,("docx"         , ByteStringWriter writeDocx)+  ,("odt"          , ByteStringWriter writeODT)+  ,("epub"         , ByteStringWriter writeEPUB3)+  ,("epub2"        , ByteStringWriter writeEPUB2)+  ,("epub3"        , ByteStringWriter writeEPUB3)+  ,("fb2"          , TextWriter writeFB2)+  ,("html"         , TextWriter writeHtml5String)+  ,("html4"        , TextWriter writeHtml4String)+  ,("html5"        , TextWriter writeHtml5String)+  ,("icml"         , TextWriter writeICML)+  ,("s5"           , TextWriter writeS5)+  ,("slidy"        , TextWriter writeSlidy)+  ,("slideous"     , TextWriter writeSlideous)+  ,("dzslides"     , TextWriter writeDZSlides)+  ,("revealjs"     , TextWriter writeRevealJs)+  ,("docbook"      , TextWriter writeDocbook5)+  ,("docbook4"     , TextWriter writeDocbook4)+  ,("docbook5"     , TextWriter writeDocbook5)+  ,("jats"         , TextWriter writeJATS)+  ,("opml"         , TextWriter writeOPML)+  ,("opendocument" , TextWriter writeOpenDocument)+  ,("latex"        , TextWriter writeLaTeX)+  ,("beamer"       , TextWriter writeBeamer)+  ,("context"      , TextWriter writeConTeXt)+  ,("texinfo"      , TextWriter writeTexinfo)+  ,("man"          , TextWriter writeMan)+  ,("ms"           , TextWriter writeMs)+  ,("markdown"     , TextWriter writeMarkdown)+  ,("markdown_strict" , TextWriter writeMarkdown)+  ,("markdown_phpextra" , TextWriter writeMarkdown)+  ,("markdown_github" , TextWriter writeMarkdown)+  ,("markdown_mmd" , TextWriter writeMarkdown)+  ,("plain"        , TextWriter writePlain)+  ,("rst"          , TextWriter writeRST)+  ,("mediawiki"    , TextWriter writeMediaWiki)+  ,("dokuwiki"     , TextWriter writeDokuWiki)+  ,("zimwiki"      , TextWriter writeZimWiki)+  ,("textile"      , TextWriter writeTextile)+  ,("rtf"          , TextWriter writeRTF)+  ,("org"          , TextWriter writeOrg)+  ,("asciidoc"     , TextWriter writeAsciiDoc)+  ,("haddock"      , TextWriter writeHaddock)+  ,("commonmark"   , TextWriter writeCommonMark)+  ,("gfm"          , TextWriter writeCommonMark)+  ,("tei"          , TextWriter writeTEI)+  ,("muse"         , TextWriter writeMuse)+  ]++-- | Retrieve writer, extensions based on formatSpec (format+extensions).+getWriter :: PandocMonad m => String -> Either String (Writer m, Extensions)+getWriter s+  = case parseFormatSpec s of+         Left e  -> Left $ intercalate "\n" [m | Message m <- errorMessages e]+         Right (writerName, setExts) ->+             case lookup writerName writers of+                     Nothing -> Left $ "Unknown writer: " ++ writerName+                     Just r -> Right (r, setExts $+                                  getDefaultExtensions writerName)++writeJSON :: WriterOptions -> Pandoc -> Text+writeJSON _ = UTF8.toText . BL.toStrict . encode
src/Text/Pandoc/Writers/AsciiDoc.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE OverloadedStrings #-} {--Copyright (C) 2006-2015 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2006-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -19,7 +19,7 @@  {- |    Module      : Text.Pandoc.Writers.AsciiDoc-   Copyright   : Copyright (C) 2006-2015 John MacFarlane+   Copyright   : Copyright (C) 2006-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -37,49 +37,56 @@ AsciiDoc:  <http://www.methods.co.nz/asciidoc/> -} module Text.Pandoc.Writers.AsciiDoc (writeAsciiDoc) where+import Control.Monad.State.Strict+import Data.Aeson (Result (..), Value (String), fromJSON, toJSON)+import Data.Char (isPunctuation, isSpace)+import Data.List (intercalate, intersperse, stripPrefix)+import qualified Data.Map as M+import Data.Maybe (fromMaybe, isJust)+import Data.Text (Text)+import qualified Data.Text as T+import Text.Pandoc.Class (PandocMonad, report) import Text.Pandoc.Definition-import Text.Pandoc.Templates (renderTemplate')-import Text.Pandoc.Shared-import Text.Pandoc.Writers.Shared+import Text.Pandoc.ImageSize+import Text.Pandoc.Logging import Text.Pandoc.Options import Text.Pandoc.Parsing hiding (blankline, space)-import Data.Maybe (fromMaybe)-import Data.List ( stripPrefix, intersperse, intercalate ) import Text.Pandoc.Pretty-import Text.Pandoc.ImageSize-import Control.Monad.State-import qualified Data.Map as M-import Data.Aeson (Value(String), fromJSON, toJSON, Result(..))-import qualified Data.Text as T-import Data.Char (isSpace, isPunctuation)+import Text.Pandoc.Shared+import Text.Pandoc.Templates (renderTemplate')+import Text.Pandoc.Writers.Shared -data WriterState = WriterState { defListMarker :: String+data WriterState = WriterState { defListMarker    :: String                                , orderedListLevel :: Int                                , bulletListLevel  :: Int                                , intraword        :: Bool                                }  -- | Convert Pandoc to AsciiDoc.-writeAsciiDoc :: WriterOptions -> Pandoc -> String+writeAsciiDoc :: PandocMonad m => WriterOptions -> Pandoc -> m Text writeAsciiDoc opts document =-  evalState (pandocToAsciiDoc opts document) WriterState{+  evalStateT (pandocToAsciiDoc opts document) WriterState{       defListMarker = "::"     , orderedListLevel = 1     , bulletListLevel = 1     , intraword = False     } +type ADW = StateT WriterState+ -- | Return asciidoc representation of document.-pandocToAsciiDoc :: WriterOptions -> Pandoc -> State WriterState String+pandocToAsciiDoc :: PandocMonad m => WriterOptions -> Pandoc -> ADW m Text pandocToAsciiDoc opts (Pandoc meta blocks) = do   let titleblock = not $ null (docTitle meta) && null (docAuthors meta) &&                          null (docDate meta)   let colwidth = if writerWrapText opts == WrapAuto                     then Just $ writerColumns opts                     else Nothing+  let render' :: Doc -> Text+      render' = render colwidth   metadata <- metaToJSON opts-              (fmap (render colwidth) . blockListToAsciiDoc opts)-              (fmap (render colwidth) . inlineListToAsciiDoc opts)+              (fmap render' . blockListToAsciiDoc opts)+              (fmap render' . inlineListToAsciiDoc opts)               meta   let addTitleLine (String t) = String $          t <> "\n" <> T.replicate (T.length t) "="@@ -93,12 +100,11 @@   let context  = defField "body" main                $ defField "toc"                   (writerTableOfContents opts &&-                   writerTemplate opts /= Nothing)-               $ defField "titleblock" titleblock-               $ metadata'+                   isJust (writerTemplate opts))+               $defField "titleblock" titleblock metadata'   case writerTemplate opts of        Nothing  -> return main-       Just tpl -> return $ renderTemplate' tpl context+       Just tpl -> renderTemplate' tpl context  -- | Escape special characters for AsciiDoc. escapeString :: String -> String@@ -118,18 +124,19 @@ beginsWithOrderedListMarker :: String -> Bool beginsWithOrderedListMarker str =   case runParser olMarker defaultParserState "para start" (take 10 str) of-         Left  _  -> False-         Right _  -> True+         Left  _ -> False+         Right _ -> True  -- | Convert Pandoc block element to asciidoc.-blockToAsciiDoc :: WriterOptions -- ^ Options+blockToAsciiDoc :: PandocMonad m+                => WriterOptions -- ^ Options                 -> Block         -- ^ Block element-                -> State WriterState Doc+                -> ADW m Doc blockToAsciiDoc _ Null = return empty blockToAsciiDoc opts (Plain inlines) = do   contents <- inlineListToAsciiDoc opts inlines   return $ contents <> blankline-blockToAsciiDoc opts (Para [Image attr alt (src,'f':'i':'g':':':tit)]) = do+blockToAsciiDoc opts (Para [Image attr alt (src,'f':'i':'g':':':tit)]) =   blockToAsciiDoc opts (Para [Image attr alt (src,tit)]) blockToAsciiDoc opts (Para inlines) = do   contents <- inlineListToAsciiDoc opts inlines@@ -145,9 +152,11 @@   let joinWithLinefeeds = nowrap . mconcat . intersperse cr   contents <- joinWithLinefeeds <$> mapM docify lns   return $ "[verse]" $$ text "--" $$ contents $$ text "--" $$ blankline-blockToAsciiDoc _ (RawBlock f s)+blockToAsciiDoc _ b@(RawBlock f s)   | f == "asciidoc" = return $ text s-  | otherwise       = return empty+  | otherwise         = do+      report $ BlockNotRendered b+      return empty blockToAsciiDoc _ HorizontalRule =   return $ blankline <> text "'''''" <> blankline blockToAsciiDoc opts (Header level (ident,_,_) inlines) = do@@ -155,21 +164,21 @@   let len = offset contents   -- ident seem to be empty most of the time and asciidoc will generate them automatically   -- so lets make them not show up when null-  let identifier = if (null ident) then empty else ("[[" <> text ident <> "]]")+  let identifier = if null ident then empty else "[[" <> text ident <> "]]"   let setext = writerSetextHeaders opts-  return $+  return          (if setext             then               identifier $$ contents $$               (case level of-               1  -> text $ replicate len '-'-               2  -> text $ replicate len '~'-               3  -> text $ replicate len '^'-               4  -> text $ replicate len '+'-               _  -> empty) <> blankline+               1 -> text $ replicate len '-'+               2 -> text $ replicate len '~'+               3 -> text $ replicate len '^'+               4 -> text $ replicate len '+'+               _ -> empty) <> blankline             else               identifier $$ text (replicate level '=') <> space <> contents <> blankline)-blockToAsciiDoc _ (CodeBlock (_,classes,_) str) = return $ (flush $+blockToAsciiDoc _ (CodeBlock (_,classes,_) str) = return $ flush (   if null classes      then "...." $$ text str $$ "...."      else attrs $$ "----" $$ text str $$ "----")@@ -194,7 +203,7 @@   let isSimple = all (== 0) widths   let relativePercentWidths = if isSimple                                  then widths-                                 else map (/ (sum widths)) widths+                                 else map (/ sum widths) widths   let widths'' :: [Integer]       widths'' = map (floor . (* 100)) relativePercentWidths   -- ensure that the widths sum to 100@@ -256,21 +265,22 @@   let markers' = map (\m -> if length m < 3                                then m ++ replicate (3 - length m) ' '                                else m) markers-  contents <- mapM (\(item, num) -> orderedListItemToAsciiDoc opts item num) $+  contents <- mapM (uncurry (orderedListItemToAsciiDoc opts)) $               zip markers' items   return $ cat contents <> blankline blockToAsciiDoc opts (DefinitionList items) = do   contents <- mapM (definitionListItemToAsciiDoc opts) items   return $ cat contents <> blankline blockToAsciiDoc opts (Div (ident,_,_) bs) = do-  let identifier = if (null ident) then empty else ("[[" <> text ident <> "]]")+  let identifier = if null ident then empty else ("[[" <> text ident <> "]]")   contents <- blockListToAsciiDoc opts bs   return $ identifier $$ contents  -- | Convert bullet list item (list of blocks) to asciidoc.-bulletListItemToAsciiDoc :: WriterOptions -> [Block] -> State WriterState Doc+bulletListItemToAsciiDoc :: PandocMonad m+                         => WriterOptions -> [Block] -> ADW m Doc bulletListItemToAsciiDoc opts blocks = do-  let addBlock :: Doc -> Block -> State WriterState Doc+  let addBlock :: PandocMonad m => Doc -> Block -> ADW m Doc       addBlock d b | isEmpty d    = chomp `fmap` blockToAsciiDoc opts b       addBlock d b@(BulletList _) = do x <- blockToAsciiDoc opts b                                        return $ d <> cr <> chomp x@@ -278,7 +288,7 @@                                           return $ d <> cr <> chomp x       addBlock d b = do x <- blockToAsciiDoc opts b                         return $ d <> cr <> text "+" <> cr <> chomp x-  lev <- bulletListLevel `fmap` get+  lev <- gets bulletListLevel   modify $ \s -> s{ bulletListLevel = lev + 1 }   contents <- foldM addBlock empty blocks   modify $ \s -> s{ bulletListLevel = lev }@@ -286,37 +296,38 @@   return $ marker <> text " " <> contents <> cr  -- | Convert ordered list item (a list of blocks) to asciidoc.-orderedListItemToAsciiDoc :: WriterOptions -- ^ options+orderedListItemToAsciiDoc :: PandocMonad m+                          => WriterOptions -- ^ options                           -> String        -- ^ list item marker                           -> [Block]       -- ^ list item (list of blocks)-                          -> State WriterState Doc+                          -> ADW m Doc orderedListItemToAsciiDoc opts marker blocks = do-  let addBlock :: Doc -> Block -> State WriterState Doc-      addBlock d b | isEmpty d    = chomp `fmap` blockToAsciiDoc opts b+  let addBlock d b | isEmpty d    = chomp `fmap` blockToAsciiDoc opts b       addBlock d b@(BulletList _) = do x <- blockToAsciiDoc opts b                                        return $ d <> cr <> chomp x       addBlock d b@(OrderedList _ _) = do x <- blockToAsciiDoc opts b                                           return $ d <> cr <> chomp x       addBlock d b = do x <- blockToAsciiDoc opts b                         return $ d <> cr <> text "+" <> cr <> chomp x-  lev <- orderedListLevel `fmap` get+  lev <- gets orderedListLevel   modify $ \s -> s{ orderedListLevel = lev + 1 }   contents <- foldM addBlock empty blocks   modify $ \s -> s{ orderedListLevel = lev }   return $ text marker <> text " " <> contents <> cr  -- | Convert definition list item (label, list of blocks) to asciidoc.-definitionListItemToAsciiDoc :: WriterOptions+definitionListItemToAsciiDoc :: PandocMonad m+                             => WriterOptions                              -> ([Inline],[[Block]])-                             -> State WriterState Doc+                             -> ADW m Doc definitionListItemToAsciiDoc opts (label, defs) = do   labelText <- inlineListToAsciiDoc opts label-  marker <- defListMarker `fmap` get+  marker <- gets defListMarker   if marker == "::"      then modify (\st -> st{ defListMarker = ";;"})      else modify (\st -> st{ defListMarker = "::"})   let divider = cr <> text "+" <> cr-  let defsToAsciiDoc :: [Block] -> State WriterState Doc+  let defsToAsciiDoc :: PandocMonad m => [Block] -> ADW m Doc       defsToAsciiDoc ds = (vcat . intersperse divider . map chomp)            `fmap` mapM (blockToAsciiDoc opts) ds   defs' <- mapM defsToAsciiDoc defs@@ -325,15 +336,16 @@   return $ labelText <> text marker <> cr <> contents <> cr  -- | Convert list of Pandoc block elements to asciidoc.-blockListToAsciiDoc :: WriterOptions -- ^ Options+blockListToAsciiDoc :: PandocMonad m+                    => WriterOptions -- ^ Options                     -> [Block]       -- ^ List of block elements-                    -> State WriterState Doc+                    -> ADW m Doc blockListToAsciiDoc opts blocks = cat `fmap` mapM (blockToAsciiDoc opts) blocks  data SpacyLocation = End | Start  -- | Convert list of Pandoc inline elements to asciidoc.-inlineListToAsciiDoc :: WriterOptions -> [Inline] -> State WriterState Doc+inlineListToAsciiDoc :: PandocMonad m => WriterOptions -> [Inline] -> ADW m Doc inlineListToAsciiDoc opts lst = do   oldIntraword <- gets intraword   setIntraword False@@ -369,14 +381,14 @@        isSpacy Start (Str (c:_)) = isPunctuation c || isSpace c        isSpacy _ _ = False -setIntraword :: Bool -> State WriterState ()+setIntraword :: PandocMonad m => Bool -> ADW m () setIntraword b = modify $ \st -> st{ intraword = b } -withIntraword :: State WriterState a -> State WriterState a+withIntraword :: PandocMonad m => ADW m a -> ADW m a withIntraword p = setIntraword True *> p <* setIntraword False  -- | Convert Pandoc inline element to asciidoc.-inlineToAsciiDoc :: WriterOptions -> Inline -> State WriterState Doc+inlineToAsciiDoc :: PandocMonad m => WriterOptions -> Inline -> ADW m Doc inlineToAsciiDoc opts (Emph lst) = do   contents <- inlineListToAsciiDoc opts lst   isIntraword <- gets intraword@@ -408,16 +420,19 @@   return $ "latexmath:[$" <> text str <> "$]" inlineToAsciiDoc _ (Math DisplayMath str) =   return $ "latexmath:[\\[" <> text str <> "\\]]"-inlineToAsciiDoc _ (RawInline f s)+inlineToAsciiDoc _ il@(RawInline f s)   | f == "asciidoc" = return $ text s+  | otherwise         = do+      report $ InlineNotRendered il+      return empty   | otherwise       = return empty-inlineToAsciiDoc _ (LineBreak) = return $ " +" <> cr+inlineToAsciiDoc _ LineBreak = return $ " +" <> cr inlineToAsciiDoc _ Space = return space inlineToAsciiDoc opts SoftBreak =   case writerWrapText opts of-       WrapAuto -> return space+       WrapAuto     -> return space        WrapPreserve -> return cr-       WrapNone -> return space+       WrapNone     -> return space inlineToAsciiDoc opts (Cite _ lst) = inlineListToAsciiDoc opts lst inlineToAsciiDoc opts (Link _ txt (src, _tit)) = do -- relative:  link:downloads/foo.zip[download foo.zip]@@ -431,7 +446,7 @@   let srcSuffix = fromMaybe src (stripPrefix "mailto:" src)   let useAuto = case txt of                       [Str s] | escapeURI s == srcSuffix -> True-                      _                                  -> False+                      _       -> False   return $ if useAuto               then text srcSuffix               else prefix <> text src <> "[" <> linktext <> "]"@@ -444,7 +459,7 @@   let linktitle = if null tit                      then empty                      else ",title=\"" <> text tit <> "\""-      showDim dir = case (dimension dir attr) of+      showDim dir = case dimension dir attr of                       Just (Percent a) ->                         ["scaledwidth=" <> text (show (Percent a))]                       Just dim         ->@@ -464,6 +479,6 @@ -- asciidoc can't handle blank lines in notes inlineToAsciiDoc _ (Note _) = return "[multiblock footnote omitted]" inlineToAsciiDoc opts (Span (ident,_,_) ils) = do-  let identifier = if (null ident) then empty else ("[[" <> text ident <> "]]")+  let identifier = if null ident then empty else ("[[" <> text ident <> "]]")   contents <- inlineListToAsciiDoc opts ils   return $ identifier <> contents
src/Text/Pandoc/Writers/CommonMark.hs view
@@ -1,5 +1,6 @@+{-# LANGUAGE OverloadedStrings #-} {--Copyright (C) 2015 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2015-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -18,7 +19,7 @@  {- |    Module      : Text.Pandoc.Writers.CommonMark-   Copyright   : Copyright (C) 2015 John MacFarlane+   Copyright   : Copyright (C) 2015-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -31,35 +32,43 @@ -} module Text.Pandoc.Writers.CommonMark (writeCommonMark) where -import Text.Pandoc.Writers.HTML (writeHtmlString)+import CMarkGFM+import Control.Monad.State.Strict (State, get, modify, runState)+import Data.Foldable (foldrM)+import Data.List (transpose)+import Data.Monoid (Any (..), (<>))+import Data.Text (Text)+import qualified Data.Text as T+import Text.Pandoc.Class (PandocMonad) import Text.Pandoc.Definition-import Text.Pandoc.Shared (isTightList, linesToPara)+import Text.Pandoc.Options+import Text.Pandoc.Shared (isTightList, linesToPara, substitute) import Text.Pandoc.Templates (renderTemplate')+import Text.Pandoc.Walk (query, walk, walkM)+import Text.Pandoc.Writers.HTML (writeHtml5String) import Text.Pandoc.Writers.Shared-import Text.Pandoc.Options-import CMark-import qualified Data.Text as T-import Control.Monad.Identity (runIdentity, Identity)-import Control.Monad.State (runState, State, modify, get)-import Text.Pandoc.Walk (walkM)  -- | Convert Pandoc to CommonMark.-writeCommonMark :: WriterOptions -> Pandoc -> String-writeCommonMark opts (Pandoc meta blocks) = rendered-  where main = runIdentity $ blocksToCommonMark opts (blocks' ++ notes')-        (blocks', notes) = runState (walkM processNotes blocks) []-        notes' = if null notes-                    then []-                    else [OrderedList (1, Decimal, Period) $ reverse notes]-        metadata = runIdentity $ metaToJSON opts-                     (blocksToCommonMark opts)-                     (inlinesToCommonMark opts)-                     meta-        context = defField "body" main $ metadata-        rendered = case writerTemplate opts of-                        Nothing  -> main-                        Just tpl -> renderTemplate' tpl context+writeCommonMark :: PandocMonad m => WriterOptions -> Pandoc -> m Text+writeCommonMark opts (Pandoc meta blocks) = do+  let (blocks', notes) = runState (walkM processNotes blocks) []+      notes' = if null notes+               then []+               else [OrderedList (1, Decimal, Period) $ reverse notes]+  main <-  blocksToCommonMark opts (blocks' ++ notes')+  metadata <- metaToJSON opts+              (blocksToCommonMark opts)+              (inlinesToCommonMark opts)+              meta+  let context = defField "body" main metadata+  case writerTemplate opts of+       Nothing  -> return main+       Just tpl -> renderTemplate' tpl context +softBreakToSpace :: Inline -> Inline+softBreakToSpace SoftBreak = Space+softBreakToSpace x         = x+ processNotes :: Inline -> State [[Block]] Inline processNotes (Note bs) = do   modify (bs :)@@ -70,111 +79,210 @@ node :: NodeType -> [Node] -> Node node = Node Nothing -blocksToCommonMark :: WriterOptions -> [Block] -> Identity String-blocksToCommonMark opts bs = return $-  T.unpack $ nodeToCommonmark cmarkOpts colwidth-           $ node DOCUMENT (blocksToNodes bs)-   where cmarkOpts = [optHardBreaks | isEnabled Ext_hard_line_breaks opts]-         colwidth = if writerWrapText opts == WrapAuto-                       then Just $ writerColumns opts-                       else Nothing+blocksToCommonMark :: PandocMonad m => WriterOptions -> [Block] -> m Text+blocksToCommonMark opts bs = do+  let cmarkOpts = [optHardBreaks | isEnabled Ext_hard_line_breaks opts]+      colwidth = if writerWrapText opts == WrapAuto+                 then Just $ writerColumns opts+                 else Nothing+  nodes <- blocksToNodes opts bs+  return $ T.stripEnd $+    nodeToCommonmark cmarkOpts colwidth $+    node DOCUMENT nodes -inlinesToCommonMark :: WriterOptions -> [Inline] -> Identity String+inlinesToCommonMark :: PandocMonad m => WriterOptions -> [Inline] -> m Text inlinesToCommonMark opts ils = return $-  T.unpack $ nodeToCommonmark cmarkOpts colwidth-           $ node PARAGRAPH (inlinesToNodes ils)+  nodeToCommonmark cmarkOpts colwidth $+    node PARAGRAPH (inlinesToNodes opts ils)    where cmarkOpts = [optHardBreaks | isEnabled Ext_hard_line_breaks opts]          colwidth = if writerWrapText opts == WrapAuto                        then Just $ writerColumns opts                        else Nothing -blocksToNodes :: [Block] -> [Node]-blocksToNodes = foldr blockToNodes []+blocksToNodes :: PandocMonad m => WriterOptions -> [Block] -> m [Node]+blocksToNodes opts = foldrM (blockToNodes opts) [] -blockToNodes :: Block -> [Node] -> [Node]-blockToNodes (Plain xs) = (node PARAGRAPH (inlinesToNodes xs) :)-blockToNodes (Para xs) = (node PARAGRAPH (inlinesToNodes xs) :)-blockToNodes (LineBlock lns) = blockToNodes $ linesToPara lns-blockToNodes (CodeBlock (_,classes,_) xs) =-  (node (CODE_BLOCK (T.pack (unwords classes)) (T.pack xs)) [] :)-blockToNodes (RawBlock fmt xs)-  | fmt == Format "html" = (node (HTML_BLOCK (T.pack xs)) [] :)-  | otherwise = (node (CUSTOM_BLOCK (T.pack xs) (T.empty)) [] :)-blockToNodes (BlockQuote bs) =-  (node BLOCK_QUOTE (blocksToNodes bs) :)-blockToNodes (BulletList items) =-  (node (LIST ListAttributes{-               listType = BULLET_LIST,-               listDelim = PERIOD_DELIM,-               listTight = isTightList items,-               listStart = 1 }) (map (node ITEM . blocksToNodes) items) :)-blockToNodes (OrderedList (start, _sty, delim) items) =-  (node (LIST ListAttributes{-               listType = ORDERED_LIST,-               listDelim = case delim of-                                OneParen  -> PAREN_DELIM-                                TwoParens -> PAREN_DELIM-                                _         -> PERIOD_DELIM,-               listTight = isTightList items,-               listStart = start }) (map (node ITEM . blocksToNodes) items) :)-blockToNodes HorizontalRule = (node THEMATIC_BREAK [] :)-blockToNodes (Header lev _ ils) = (node (HEADING lev) (inlinesToNodes ils) :)-blockToNodes (Div _ bs) = (blocksToNodes bs ++)-blockToNodes (DefinitionList items) = blockToNodes (BulletList items')+blockToNodes :: PandocMonad m => WriterOptions -> Block -> [Node] -> m [Node]+blockToNodes opts (Plain xs) ns =+  return (node PARAGRAPH (inlinesToNodes opts xs) : ns)+blockToNodes opts (Para xs) ns =+  return (node PARAGRAPH (inlinesToNodes opts xs) : ns)+blockToNodes opts (LineBlock lns) ns = blockToNodes opts (linesToPara lns) ns+blockToNodes _ (CodeBlock (_,classes,_) xs) ns = return+  (node (CODE_BLOCK (T.pack (unwords classes)) (T.pack xs)) [] : ns)+blockToNodes _ (RawBlock fmt xs) ns+  | fmt == Format "html" = return (node (HTML_BLOCK (T.pack xs)) [] : ns)+  | otherwise = return (node (CUSTOM_BLOCK (T.pack xs) T.empty) [] : ns)+blockToNodes opts (BlockQuote bs) ns = do+  nodes <- blocksToNodes opts bs+  return (node BLOCK_QUOTE nodes : ns)+blockToNodes opts (BulletList items) ns = do+  nodes <- mapM (blocksToNodes opts) items+  return (node (LIST ListAttributes{+                   listType = BULLET_LIST,+                   listDelim = PERIOD_DELIM,+                   listTight = isTightList items,+                   listStart = 1 }) (map (node ITEM) nodes) : ns)+blockToNodes opts (OrderedList (start, _sty, delim) items) ns = do+  nodes <- mapM (blocksToNodes opts) items+  return (node (LIST ListAttributes{+                   listType = ORDERED_LIST,+                   listDelim = case delim of+                                 OneParen  -> PAREN_DELIM+                                 TwoParens -> PAREN_DELIM+                                 _         -> PERIOD_DELIM,+                   listTight = isTightList items,+                   listStart = start }) (map (node ITEM) nodes) : ns)+blockToNodes _ HorizontalRule ns = return (node THEMATIC_BREAK [] : ns)+blockToNodes opts (Header lev _ ils) ns =+  return (node (HEADING lev) (inlinesToNodes opts ils) : ns)+blockToNodes opts (Div _ bs) ns = do+  nodes <- blocksToNodes opts bs+  return (nodes ++ ns)+blockToNodes opts (DefinitionList items) ns =+  blockToNodes opts (BulletList items') ns   where items' = map dlToBullet items-        dlToBullet (term, ((Para xs : ys) : zs))  =+        dlToBullet (term, (Para xs : ys) : zs)  =           Para (term ++ [LineBreak] ++ xs) : ys ++ concat zs-        dlToBullet (term, ((Plain xs : ys) : zs)) =+        dlToBullet (term, (Plain xs : ys) : zs) =           Plain (term ++ [LineBreak] ++ xs) : ys ++ concat zs         dlToBullet (term, xs) =           Para term : concat xs-blockToNodes t@(Table _ _ _ _ _) =-  (node (HTML_BLOCK (T.pack $! writeHtmlString def $! Pandoc nullMeta [t])) [] :)-blockToNodes Null = id+blockToNodes opts t@(Table capt aligns _widths headers rows) ns = do+  let allcells = concat (headers:rows)+  let isLineBreak LineBreak = Any True+      isLineBreak _         = Any False+  let isPlainOrPara [Para _]  = True+      isPlainOrPara [Plain _] = True+      isPlainOrPara []        = True+      isPlainOrPara _         = False+  let isSimple = all isPlainOrPara allcells &&+                 not ( getAny (query isLineBreak allcells) )+  if isEnabled Ext_pipe_tables opts && isSimple+     then do+       -- We construct a table manually as a CUSTOM_BLOCK, for+       -- two reasons:  (1) cmark-gfm currently doesn't support+       -- rendering TABLE nodes; (2) we can align the column sides;+       -- (3) we can render the caption as a regular paragraph.+       let capt' = node PARAGRAPH (inlinesToNodes opts capt)+       -- backslash | in code and raw:+       let fixPipe (Code attr xs) =+             Code attr (substitute "|" "\\|" xs)+           fixPipe (RawInline format xs) =+             RawInline format (substitute "|" "\\|" xs)+           fixPipe x = x+       let toCell [Plain ils] = T.strip+                                $ nodeToCommonmark [] Nothing+                                $ node (CUSTOM_INLINE mempty mempty)+                                $ inlinesToNodes opts+                                $ walk (fixPipe . softBreakToSpace) ils+           toCell [Para  ils] = T.strip+                                $ nodeToCommonmark [] Nothing+                                $ node (CUSTOM_INLINE mempty mempty)+                                $ inlinesToNodes opts+                                $ walk (fixPipe . softBreakToSpace) ils+           toCell []          = ""+           toCell xs          = error $ "toCell encountered " ++ show xs+       let separator = " | "+       let starter = "| "+       let ender   = " |"+       let rawheaders = map toCell headers+       let rawrows = map (map toCell) rows+       let maximum' [] = 0+           maximum' xs = maximum xs+       let colwidths = map (maximum' . map T.length) $+                        transpose (rawheaders:rawrows)+       let toHeaderLine len AlignDefault = T.replicate len "-"+           toHeaderLine len AlignLeft    = ":" <>+                  T.replicate (max (len - 1) 1) "-"+           toHeaderLine len AlignRight   =+                  T.replicate (max (len - 1) 1) "-" <> ":"+           toHeaderLine len AlignCenter  = ":" <>+                  T.replicate (max (len - 2) 1) (T.pack "-") <> ":"+       let rawheaderlines = zipWith toHeaderLine colwidths aligns+       let headerlines = starter <> T.intercalate separator rawheaderlines <>+                          ender+       let padContent (align, w) t' =+             let padding = w - T.length t'+                 halfpadding = padding `div` 2+             in  case align of+                      AlignRight -> T.replicate padding " " <> t'+                      AlignCenter -> T.replicate halfpadding " " <> t' <>+                                     T.replicate (padding - halfpadding) " "+                      _ -> t' <> T.replicate padding " "+       let toRow xs = starter <> T.intercalate separator+                      (zipWith padContent (zip aligns colwidths) xs) <>+                      ender+       let table' = toRow rawheaders <> "\n" <> headerlines <> "\n" <>+                     T.intercalate "\n" (map toRow rawrows)+       return (node (CUSTOM_BLOCK table' mempty) [] :+               if null capt+                  then ns+                  else capt' : ns)+     else do -- fall back to raw HTML+       s <- writeHtml5String def $! Pandoc nullMeta [t]+       return (node (HTML_BLOCK s) [] : ns)+blockToNodes _ Null ns = return ns -inlinesToNodes :: [Inline] -> [Node]-inlinesToNodes  = foldr inlineToNodes []+inlinesToNodes :: WriterOptions -> [Inline] -> [Node]+inlinesToNodes opts  = foldr (inlineToNodes opts) [] -inlineToNodes :: Inline -> [Node] -> [Node]-inlineToNodes (Str s) = (node (TEXT (T.pack s)) [] :)-inlineToNodes Space   = (node (TEXT (T.pack " ")) [] :)-inlineToNodes LineBreak = (node LINEBREAK [] :)-inlineToNodes SoftBreak = (node SOFTBREAK [] :)-inlineToNodes (Emph xs) = (node EMPH (inlinesToNodes xs) :)-inlineToNodes (Strong xs) = (node STRONG (inlinesToNodes xs) :)-inlineToNodes (Strikeout xs) =-  ((node (HTML_INLINE (T.pack "<s>")) [] : inlinesToNodes xs ++-   [node (HTML_INLINE (T.pack "</s>")) []]) ++ )-inlineToNodes (Superscript xs) =-  ((node (HTML_INLINE (T.pack "<sup>")) [] : inlinesToNodes xs +++inlineToNodes :: WriterOptions -> Inline -> [Node] -> [Node]+inlineToNodes opts (Str s) = (node (TEXT (T.pack s')) [] :)+  where s' = if isEnabled Ext_smart opts+                then unsmartify opts s+                else s+inlineToNodes _ Space   = (node (TEXT (T.pack " ")) [] :)+inlineToNodes _ LineBreak = (node LINEBREAK [] :)+inlineToNodes opts SoftBreak+  | isEnabled Ext_hard_line_breaks opts = (node LINEBREAK [] :)+  | writerWrapText opts == WrapNone     = (node (TEXT " ") [] :)+  | otherwise                           = (node SOFTBREAK [] :)+inlineToNodes opts (Emph xs) = (node EMPH (inlinesToNodes opts xs) :)+inlineToNodes opts (Strong xs) = (node STRONG (inlinesToNodes opts xs) :)+inlineToNodes opts (Strikeout xs) =+  if isEnabled Ext_strikeout opts+     then (node STRIKETHROUGH (inlinesToNodes opts xs) :)+     else ((node (HTML_INLINE (T.pack "<s>")) [] : inlinesToNodes opts xs +++           [node (HTML_INLINE (T.pack "</s>")) []]) ++ )+inlineToNodes opts (Superscript xs) =+  ((node (HTML_INLINE (T.pack "<sup>")) [] : inlinesToNodes opts xs ++    [node (HTML_INLINE (T.pack "</sup>")) []]) ++ )-inlineToNodes (Subscript xs) =-  ((node (HTML_INLINE (T.pack "<sub>")) [] : inlinesToNodes xs +++inlineToNodes opts (Subscript xs) =+  ((node (HTML_INLINE (T.pack "<sub>")) [] : inlinesToNodes opts xs ++    [node (HTML_INLINE (T.pack "</sub>")) []]) ++ )-inlineToNodes (SmallCaps xs) =-  ((node (HTML_INLINE (T.pack "<span style=\"font-variant:small-caps;\">")) []-    : inlinesToNodes xs +++inlineToNodes opts (SmallCaps xs) =+  ((node (HTML_INLINE (T.pack "<span class=\"smallcaps\">")) []+    : inlinesToNodes opts xs ++     [node (HTML_INLINE (T.pack "</span>")) []]) ++ )-inlineToNodes (Link _ ils (url,tit)) =-  (node (LINK (T.pack url) (T.pack tit)) (inlinesToNodes ils) :)-inlineToNodes (Image _ ils (url,tit)) =-  (node (IMAGE (T.pack url) (T.pack tit)) (inlinesToNodes ils) :)-inlineToNodes (RawInline fmt xs)+inlineToNodes opts (Link _ ils (url,tit)) =+  (node (LINK (T.pack url) (T.pack tit)) (inlinesToNodes opts ils) :)+-- title beginning with fig: indicates implicit figure+inlineToNodes opts (Image alt ils (url,'f':'i':'g':':':tit)) =+  inlineToNodes opts (Image alt ils (url,tit))+inlineToNodes opts (Image _ ils (url,tit)) =+  (node (IMAGE (T.pack url) (T.pack tit)) (inlinesToNodes opts ils) :)+inlineToNodes _ (RawInline fmt xs)   | fmt == Format "html" = (node (HTML_INLINE (T.pack xs)) [] :)-  | otherwise = (node (CUSTOM_INLINE (T.pack xs) (T.empty)) [] :)-inlineToNodes (Quoted qt ils) =-  ((node (TEXT start) [] : inlinesToNodes ils ++ [node (TEXT end) []]) ++)+  | otherwise = (node (CUSTOM_INLINE (T.pack xs) T.empty) [] :)+inlineToNodes opts (Quoted qt ils) =+  ((node (TEXT start) [] :+   inlinesToNodes opts ils ++ [node (TEXT end) []]) ++)   where (start, end) = case qt of-                          SingleQuote -> (T.pack "‘", T.pack "’")-                          DoubleQuote -> (T.pack "“", T.pack "”")-inlineToNodes (Code _ str) = (node (CODE (T.pack str)) [] :)-inlineToNodes (Math mt str) =+                          SingleQuote+                            | isEnabled Ext_smart opts -> ("'","'")+                            | otherwise -> ("‘", "’")+                          DoubleQuote+                            | isEnabled Ext_smart opts -> ("\"", "\"")+                            | otherwise -> ("“", "”")+inlineToNodes _ (Code _ str) = (node (CODE (T.pack str)) [] :)+inlineToNodes _ (Math mt str) =   case mt of     InlineMath  ->       (node (HTML_INLINE (T.pack ("\\(" ++ str ++ "\\)"))) [] :)     DisplayMath ->       (node (HTML_INLINE (T.pack ("\\[" ++ str ++ "\\]"))) [] :)-inlineToNodes (Span _ ils) = (inlinesToNodes ils ++)-inlineToNodes (Cite _ ils) = (inlinesToNodes ils ++)-inlineToNodes (Note _) = id -- should not occur+inlineToNodes opts (Span _ ils) = (inlinesToNodes opts ils ++)+inlineToNodes opts (Cite _ ils) = (inlinesToNodes opts ils ++)+inlineToNodes _ (Note _) = id -- should not occur -- we remove Note elements in preprocessing
src/Text/Pandoc/Writers/ConTeXt.hs view
@@ -1,6 +1,7 @@-{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE ScopedTypeVariables #-} {--Copyright (C) 2007-2015 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2007-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -19,7 +20,7 @@  {- |    Module      : Text.Pandoc.Writers.ConTeXt-   Copyright   : Copyright (C) 2007-2015 John MacFarlane+   Copyright   : Copyright (C) 2007-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -29,20 +30,24 @@ Conversion of 'Pandoc' format into ConTeXt. -} module Text.Pandoc.Writers.ConTeXt ( writeConTeXt ) where+import Control.Monad.State.Strict+import Data.Char (ord)+import Data.List (intercalate, intersperse)+import Data.Maybe (mapMaybe)+import Data.Text (Text)+import Network.URI (unEscapeString)+import Text.Pandoc.BCP47+import Text.Pandoc.Class (PandocMonad, report, toLang) import Text.Pandoc.Definition-import Text.Pandoc.Shared-import Text.Pandoc.Writers.Shared+import Text.Pandoc.ImageSize+import Text.Pandoc.Logging import Text.Pandoc.Options-import Text.Pandoc.Walk (query)-import Text.Printf ( printf )-import Data.List ( intercalate, intersperse )-import Data.Char ( ord )-import Data.Maybe ( catMaybes )-import Control.Monad.State import Text.Pandoc.Pretty-import Text.Pandoc.ImageSize-import Text.Pandoc.Templates ( renderTemplate' )-import Network.URI ( isURI, unEscapeString )+import Text.Pandoc.Shared+import Text.Pandoc.Templates (renderTemplate')+import Text.Pandoc.Walk (query)+import Text.Pandoc.Writers.Shared+import Text.Printf (printf)  data WriterState =   WriterState { stNextRef          :: Int  -- number of next URL reference@@ -54,33 +59,37 @@ orderedListStyles = cycle "narg"  -- | Convert Pandoc to ConTeXt.-writeConTeXt :: WriterOptions -> Pandoc -> String+writeConTeXt :: PandocMonad m => WriterOptions -> Pandoc -> m Text writeConTeXt options document =   let defaultWriterState = WriterState { stNextRef = 1                                        , stOrderedListLevel = 0                                        , stOptions = options                                        }-  in evalState (pandocToConTeXt options document) defaultWriterState+  in evalStateT (pandocToConTeXt options document) defaultWriterState -pandocToConTeXt :: WriterOptions -> Pandoc -> State WriterState String+type WM = StateT WriterState++pandocToConTeXt :: PandocMonad m => WriterOptions -> Pandoc -> WM m Text pandocToConTeXt options (Pandoc meta blocks) = do   let colwidth = if writerWrapText options == WrapAuto                     then Just $ writerColumns options                     else Nothing+  let render' :: Doc -> Text+      render' = render colwidth   metadata <- metaToJSON options-              (fmap (render colwidth) . blockListToConTeXt)-              (fmap (render colwidth) . inlineListToConTeXt)+              (fmap render' . blockListToConTeXt)+              (fmap render' . inlineListToConTeXt)               meta   body <- mapM (elementToConTeXt options) $ hierarchicalize blocks-  let main = (render colwidth . vcat) body-  let layoutFromMargins = intercalate [','] $ catMaybes $-                              map (\(x,y) ->+  let main = (render' . vcat) body+  let layoutFromMargins = intercalate [','] $ mapMaybe (\(x,y) ->                                 ((x ++ "=") ++) <$> getField y metadata)                               [("leftmargin","margin-left")                               ,("rightmargin","margin-right")                               ,("top","margin-top")                               ,("bottom","margin-bottom")                               ]+  mblang <- fromBCP47 (getLang options meta)   let context =   defField "toc" (writerTableOfContents options)                 $ defField "placelist" (intercalate ("," :: String) $                      take (writerTOCDepth options +@@ -93,14 +102,16 @@                 $ defField "body" main                 $ defField "layout" layoutFromMargins                 $ defField "number-sections" (writerNumberSections options)-                $ metadata-  let context' =  defField "context-lang" (maybe "" (fromBcp47 . splitBy (=='-')) $-                    getField "lang" context)-                $ defField "context-dir" (toContextDir $ getField "dir" context)-                $ context-  return $ case writerTemplate options of-                Nothing  -> main-                Just tpl -> renderTemplate' tpl context'+                $ maybe id (defField "context-lang") mblang+                $ (case getField "papersize" metadata of+                        Just ("a4" :: String) -> resetField "papersize"+                                                    ("A4" :: String)+                        _                     -> id) metadata+  let context' = defField "context-dir" (toContextDir+                                         $ getField "dir" context) context+  case writerTemplate options of+       Nothing  -> return main+       Just tpl -> renderTemplate' tpl context'  toContextDir :: Maybe String -> String toContextDir (Just "rtl") = "r2l"@@ -110,24 +121,24 @@ -- | escape things as needed for ConTeXt escapeCharForConTeXt :: WriterOptions -> Char -> String escapeCharForConTeXt opts ch =- let ligatures = writerTeXLigatures opts in+ let ligatures = isEnabled Ext_smart opts in  case ch of-    '{'    -> "\\{"-    '}'    -> "\\}"-    '\\'   -> "\\letterbackslash{}"-    '$'    -> "\\$"-    '|'    -> "\\letterbar{}"-    '%'    -> "\\letterpercent{}"-    '~'    -> "\\lettertilde{}"-    '#'    -> "\\#"-    '['    -> "{[}"-    ']'    -> "{]}"-    '\160' -> "~"+    '{'      -> "\\{"+    '}'      -> "\\}"+    '\\'     -> "\\letterbackslash{}"+    '$'      -> "\\$"+    '|'      -> "\\letterbar{}"+    '%'      -> "\\letterpercent{}"+    '~'      -> "\\lettertilde{}"+    '#'      -> "\\#"+    '['      -> "{[}"+    ']'      -> "{]}"+    '\160'   -> "~"     '\x2014' | ligatures -> "---"     '\x2013' | ligatures -> "--"     '\x2019' | ligatures -> "'"     '\x2026' -> "\\ldots{}"-    x      -> [x]+    x        -> [x]  -- | Escape string for ConTeXt stringToConTeXt :: WriterOptions -> String -> String@@ -137,11 +148,11 @@ toLabel :: String -> String toLabel z = concatMap go z  where go x-         | elem x ("\\#[]\",{}%()|=" :: String) = "ux" ++ printf "%x" (ord x)+         | x `elem` ("\\#[]\",{}%()|=" :: String) = "ux" ++ printf "%x" (ord x)          | otherwise = [x]  -- | Convert Elements to ConTeXt-elementToConTeXt :: WriterOptions -> Element -> State WriterState Doc+elementToConTeXt :: PandocMonad m => WriterOptions -> Element -> WM m Doc elementToConTeXt _ (Blk block) = blockToConTeXt block elementToConTeXt opts (Sec level _ attr title' elements) = do   header' <- sectionHeader attr level title'@@ -149,8 +160,7 @@   return $ vcat (header' : innerContents)  -- | Convert Pandoc block element to ConTeXt.-blockToConTeXt :: Block-               -> State WriterState Doc+blockToConTeXt :: PandocMonad m => Block -> WM m Doc blockToConTeXt Null = return empty blockToConTeXt (Plain lst) = inlineListToConTeXt lst -- title beginning with fig: indicates that the image is a figure@@ -175,9 +185,12 @@   return $ flush ("\\starttyping" <> cr <> text str <> cr <> "\\stoptyping") $$ blankline   -- blankline because \stoptyping can't have anything after it, inc. '}' blockToConTeXt (RawBlock "context" str) = return $ text str <> blankline-blockToConTeXt (RawBlock _ _ ) = return empty+blockToConTeXt b@(RawBlock _ _ ) = do+  report $ BlockNotRendered b+  return empty blockToConTeXt (Div (ident,_,kvs) bs) = do   let align dir txt = "\\startalignment[" <> dir <> "]" $$ txt $$ "\\stopalignment"+  mblang <- fromBCP47 (lookup "lang" kvs)   let wrapRef txt = if null ident                        then txt                        else ("\\reference" <> brackets (text $ toLabel ident) <>@@ -186,12 +199,12 @@                   Just "rtl" -> align "righttoleft"                   Just "ltr" -> align "lefttoright"                   _          -> id-      wrapLang txt = case lookup "lang" kvs of+      wrapLang txt = case mblang of                        Just lng -> "\\start\\language["-                                     <> text (fromBcp47' lng) <> "]" $$ txt $$ "\\stop"+                                     <> text lng <> "]" $$ txt $$ "\\stop"                        Nothing  -> txt       wrapBlank txt = blankline <> txt <> blankline-  fmap (wrapBlank . wrapLang . wrapDir . wrapRef) $ blockListToConTeXt bs+  (wrapBlank . wrapLang . wrapDir . wrapRef) <$> blockListToConTeXt bs blockToConTeXt (BulletList lst) = do   contents <- mapM listItemToConTeXt lst   return $ ("\\startitemize" <> if isTightList lst@@ -201,9 +214,9 @@ blockToConTeXt (OrderedList (start, style', delim) lst) = do     st <- get     let level = stOrderedListLevel st-    put $ st {stOrderedListLevel = level + 1}+    put st {stOrderedListLevel = level + 1}     contents <- mapM listItemToConTeXt lst-    put $ st {stOrderedListLevel = level}+    put st {stOrderedListLevel = level}     let start' = if start == 1 then "" else "start=" ++ show start     let delim' = case delim of                         DefaultDelim -> ""@@ -246,7 +259,7 @@            if colWidth == 0               then "|"               else ("p(" ++ printf "%.2f" colWidth ++ "\\textwidth)|")-    let colDescriptors = "|" ++ (concat $+    let colDescriptors = "|" ++ concat (                                  zipWith colDescriptor widths aligns)     headers <- if all null heads                   then return empty@@ -261,16 +274,16 @@              "\\HL" $$ headers $$              vcat rows' $$ "\\HL" $$ "\\stoptable" <> blankline -tableRowToConTeXt :: [[Block]] -> State WriterState Doc+tableRowToConTeXt :: PandocMonad m => [[Block]] -> WM m Doc tableRowToConTeXt cols = do   cols' <- mapM blockListToConTeXt cols-  return $ (vcat (map ("\\NC " <>) cols')) $$ "\\NC\\AR"+  return $ vcat (map ("\\NC " <>) cols') $$ "\\NC\\AR" -listItemToConTeXt :: [Block] -> State WriterState Doc+listItemToConTeXt :: PandocMonad m => [Block] -> WM m Doc listItemToConTeXt list = blockListToConTeXt list >>=-  return . ("\\item" $$) . (nest 2)+  return . ("\\item" $$) . nest 2 -defListItemToConTeXt :: ([Inline], [[Block]]) -> State WriterState Doc+defListItemToConTeXt :: PandocMonad m => ([Inline], [[Block]]) -> WM m Doc defListItemToConTeXt (term, defs) = do   term' <- inlineListToConTeXt term   def'  <- liftM vsep $ mapM blockListToConTeXt defs@@ -278,12 +291,13 @@            "\\stopdescription" <> blankline  -- | Convert list of block elements to ConTeXt.-blockListToConTeXt :: [Block] -> State WriterState Doc+blockListToConTeXt :: PandocMonad m => [Block] -> WM m Doc blockListToConTeXt lst = liftM vcat $ mapM blockToConTeXt lst  -- | Convert list of inline elements to ConTeXt.-inlineListToConTeXt :: [Inline]  -- ^ Inlines to convert-                    -> State WriterState Doc+inlineListToConTeXt :: PandocMonad m+                    => [Inline]  -- ^ Inlines to convert+                    -> WM m Doc inlineListToConTeXt lst = liftM hcat $ mapM inlineToConTeXt $ addStruts lst   -- We add a \strut after a line break that precedes a space,   -- or the space gets swallowed@@ -292,13 +306,14 @@              addStruts xs         addStruts (x:xs) = x : addStruts xs         addStruts [] = []-        isSpacey Space = True+        isSpacey Space            = True         isSpacey (Str ('\160':_)) = True-        isSpacey _ = False+        isSpacey _                = False  -- | Convert inline element to ConTeXt-inlineToConTeXt :: Inline    -- ^ Inline to convert-                -> State WriterState Doc+inlineToConTeXt :: PandocMonad m+                => Inline    -- ^ Inline to convert+                -> WM m Doc inlineToConTeXt (Emph lst) = do   contents <- inlineListToConTeXt lst   return $ braces $ "\\em " <> contents@@ -338,8 +353,10 @@   return $ text "\\startformula "  <> text str <> text " \\stopformula" <> space inlineToConTeXt (RawInline "context" str) = return $ text str inlineToConTeXt (RawInline "tex" str) = return $ text str-inlineToConTeXt (RawInline _ _) = return empty-inlineToConTeXt (LineBreak) = return $ text "\\crlf" <> cr+inlineToConTeXt il@(RawInline _ _) = do+  report $ InlineNotRendered il+  return empty+inlineToConTeXt LineBreak = return $ text "\\crlf" <> cr inlineToConTeXt SoftBreak = do   wrapText <- gets (writerWrapText . stOptions)   return $ case wrapText of@@ -348,7 +365,7 @@                WrapPreserve -> cr inlineToConTeXt Space = return space -- Handle HTML-like internal document references to sections-inlineToConTeXt (Link _ txt (('#' : ref), _)) = do+inlineToConTeXt (Link _ txt ('#' : ref, _)) = do   opts <- gets stOptions   contents <-  inlineListToConTeXt txt   let ref' = toLabel $ stringToConTeXt opts ref@@ -374,7 +391,7 @@ inlineToConTeXt (Image attr@(_,cls,_) _ (src, _)) = do   opts <- gets stOptions   let showDim dir = let d = text (show dir) <> "="-                    in case (dimension dir attr) of+                    in case dimension dir attr of                          Just (Pixel a)   ->                            [d <> text (showInInch opts (Pixel a)) <> "in"]                          Just (Percent a) ->@@ -397,28 +414,30 @@ inlineToConTeXt (Note contents) = do   contents' <- blockListToConTeXt contents   let codeBlock x@(CodeBlock _ _) = [x]-      codeBlock _ = []+      codeBlock _                 = []   let codeBlocks = query codeBlock contents   return $ if null codeBlocks               then text "\\footnote{" <> nest 2 contents' <> char '}'               else text "\\startbuffer " <> nest 2 contents' <>                    text "\\stopbuffer\\footnote{\\getbuffer}" inlineToConTeXt (Span (_,_,kvs) ils) = do+  mblang <- fromBCP47 (lookup "lang" kvs)   let wrapDir txt = case lookup "dir" kvs of                       Just "rtl" -> braces $ "\\righttoleft " <> txt                       Just "ltr" -> braces $ "\\lefttoright " <> txt                       _          -> txt-      wrapLang txt = case lookup "lang" kvs of-                       Just lng -> "\\start\\language[" <> text (fromBcp47' lng)+      wrapLang txt = case mblang of+                       Just lng -> "\\start\\language[" <> text lng                                       <> "]" <> txt <> "\\stop "                        Nothing -> txt-  fmap (wrapLang . wrapDir) $ inlineListToConTeXt ils+  (wrapLang . wrapDir) <$> inlineListToConTeXt ils  -- | Craft the section header, inserting the section reference, if supplied.-sectionHeader :: Attr+sectionHeader :: PandocMonad m+              => Attr               -> Int               -> [Inline]-              -> State WriterState Doc+              -> WM m Doc sectionHeader (ident,classes,_) hdrLevel lst = do   contents <- inlineListToConTeXt lst   st <- get@@ -428,53 +447,52 @@                  TopLevelChapter -> hdrLevel - 1                  TopLevelSection -> hdrLevel                  TopLevelDefault -> hdrLevel-  let ident' = toLabel ident+  let ident' = if null ident+                  then empty+                  else brackets (text (toLabel ident))   let (section, chapter) = if "unnumbered" `elem` classes                               then (text "subject", text "title")                               else (text "section", text "chapter")   return $ case level' of-             -1                   -> text "\\part" <> braces contents-             0                    -> char '\\' <> chapter <> braces contents+             -1                   -> text "\\part" <> ident' <> braces contents+             0                    -> char '\\' <> chapter <> ident' <>+                                           braces contents              n | n >= 1 && n <= 5 -> char '\\'                                      <> text (concat (replicate (n - 1) "sub"))                                      <> section-                                     <> (if (not . null) ident'-                                         then brackets (text ident')-                                         else empty)+                                     <> ident'                                      <> braces contents                                      <> blankline              _                    -> contents <> blankline -fromBcp47' :: String -> String-fromBcp47' = fromBcp47 . splitBy (=='-')+fromBCP47 :: PandocMonad m => Maybe String -> WM m (Maybe String)+fromBCP47 mbs = fromBCP47' <$> toLang mbs  -- Takes a list of the constituents of a BCP 47 language code -- and irons out ConTeXt's exceptions -- https://tools.ietf.org/html/bcp47#section-2.1 -- http://wiki.contextgarden.net/Language_Codes-fromBcp47 :: [String] -> String-fromBcp47 []              = ""-fromBcp47 ("ar":"SY":_)   = "ar-sy"-fromBcp47 ("ar":"IQ":_)   = "ar-iq"-fromBcp47 ("ar":"JO":_)   = "ar-jo"-fromBcp47 ("ar":"LB":_)   = "ar-lb"-fromBcp47 ("ar":"DZ":_)   = "ar-dz"-fromBcp47 ("ar":"MA":_)   = "ar-ma"-fromBcp47 ("de":"1901":_) = "deo"-fromBcp47 ("de":"DE":_)   = "de-de"-fromBcp47 ("de":"AT":_)   = "de-at"-fromBcp47 ("de":"CH":_)   = "de-ch"-fromBcp47 ("el":"poly":_) = "agr"-fromBcp47 ("en":"US":_)   = "en-us"-fromBcp47 ("en":"GB":_)   = "en-gb"-fromBcp47 ("grc":_)       = "agr"-fromBcp47 x               = fromIso $ head x-  where-    fromIso "el" = "gr"-    fromIso "eu" = "ba"-    fromIso "he" = "il"-    fromIso "jp" = "ja"-    fromIso "uk" = "ua"-    fromIso "vi" = "vn"-    fromIso "zh" = "cn"-    fromIso l    = l+fromBCP47' :: Maybe Lang -> Maybe String+fromBCP47' (Just (Lang "ar" _ "SY" _)     ) = Just "ar-sy"+fromBCP47' (Just (Lang "ar" _ "IQ" _)     ) = Just "ar-iq"+fromBCP47' (Just (Lang "ar" _ "JO" _)     ) = Just "ar-jo"+fromBCP47' (Just (Lang "ar" _ "LB" _)     ) = Just "ar-lb"+fromBCP47' (Just (Lang "ar" _ "DZ" _)     ) = Just "ar-dz"+fromBCP47' (Just (Lang "ar" _ "MA" _)     ) = Just "ar-ma"+fromBCP47' (Just (Lang "de" _ _ ["1901"]) ) = Just "deo"+fromBCP47' (Just (Lang "de" _ "DE" _)     ) = Just "de-de"+fromBCP47' (Just (Lang "de" _ "AT" _)     ) = Just "de-at"+fromBCP47' (Just (Lang "de" _ "CH" _)     ) = Just "de-ch"+fromBCP47' (Just (Lang "el" _ _ ["poly"]) ) = Just "agr"+fromBCP47' (Just (Lang "en" _ "US" _)     ) = Just "en-us"+fromBCP47' (Just (Lang "en" _ "GB" _)     ) = Just "en-gb"+fromBCP47' (Just (Lang "grc"_  _ _)       ) = Just "agr"+fromBCP47' (Just (Lang "el" _ _ _)        ) = Just "gr"+fromBCP47' (Just (Lang "eu" _ _ _)        ) = Just "ba"+fromBCP47' (Just (Lang "he" _ _ _)        ) = Just "il"+fromBCP47' (Just (Lang "jp" _ _ _)        ) = Just "ja"+fromBCP47' (Just (Lang "uk" _ _ _)        ) = Just "ua"+fromBCP47' (Just (Lang "vi" _ _ _)        ) = Just "vn"+fromBCP47' (Just (Lang "zh" _ _ _)        ) = Just "cn"+fromBCP47' (Just (Lang l _ _ _)           ) = Just l+fromBCP47' Nothing                          = Nothing
src/Text/Pandoc/Writers/Custom.hs view
@@ -1,11 +1,12 @@ {-# OPTIONS_GHC -fno-warn-orphans #-}-{-# LANGUAGE FlexibleInstances, OverloadedStrings,-    ScopedTypeVariables, DeriveDataTypeable, CPP #-}+{-# LANGUAGE CPP                  #-}+{-# LANGUAGE DeriveDataTypeable   #-}+{-# LANGUAGE FlexibleInstances    #-} #if MIN_VERSION_base(4,8,0) #else {-# LANGUAGE OverlappingInstances #-} #endif-{- Copyright (C) 2012-2015 John MacFarlane <jgm@berkeley.edu>+{- Copyright (C) 2012-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -24,7 +25,7 @@  {- |    Module      : Text.Pandoc.Writers.Custom-   Copyright   : Copyright (C) 2012-2015 John MacFarlane+   Copyright   : Copyright (C) 2012-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -35,20 +36,23 @@ a lua writer. -} module Text.Pandoc.Writers.Custom ( writeCustom ) where-import Text.Pandoc.Definition-import Text.Pandoc.Options-import Data.List ( intersperse )-import Data.Char ( toLower )-import Data.Typeable-import Scripting.Lua (LuaState, StackValue, callfunc)-import Text.Pandoc.Writers.Shared-import qualified Scripting.Lua as Lua-import qualified Text.Pandoc.UTF8 as UTF8-import Control.Monad (when) import Control.Exception+import Control.Monad (when)+import Data.Char (toLower)+import Data.List (intersperse) import qualified Data.Map as M+import Data.Text (Text, pack)+import Data.Typeable+import Foreign.Lua (Lua, ToLuaStack (..), callFunc, runLua)+import Foreign.Lua.Api+import GHC.IO.Encoding (getForeignEncoding, setForeignEncoding, utf8)+import Text.Pandoc.Definition+import Text.Pandoc.Error+import Text.Pandoc.Lua.Util (addValue)+import Text.Pandoc.Options import Text.Pandoc.Templates-import GHC.IO.Encoding (getForeignEncoding,setForeignEncoding, utf8)+import qualified Text.Pandoc.UTF8 as UTF8+import Text.Pandoc.Writers.Shared  attrToMap :: Attr -> M.Map String String attrToMap (id',classes,keyvals) = M.fromList@@ -56,119 +60,46 @@     : ("class", unwords classes)     : keyvals -#if MIN_VERSION_hslua(0,4,0)-#if MIN_VERSION_base(4,8,0)-instance {-# OVERLAPS #-} StackValue [Char] where-#else-instance StackValue [Char] where-#endif-  push lua cs = Lua.push lua (UTF8.fromString cs)-  peek lua i = do-                 res <- Lua.peek lua i-                 return $ UTF8.toString `fmap` res-  valuetype _ = Lua.TSTRING-#else-#if MIN_VERSION_base(4,8,0)-instance {-# OVERLAPS #-} StackValue a => StackValue [a] where-#else-instance StackValue a => StackValue [a] where-#endif-  push lua xs = do-    Lua.createtable lua (length xs + 1) 0-    let addValue (i, x) = Lua.push lua x >> Lua.rawseti lua (-2) i-    mapM_ addValue $ zip [1..] xs-  peek lua i = do-    top <- Lua.gettop lua-    let i' = if i < 0 then top + i + 1 else i-    Lua.pushnil lua-    lst <- getList lua i'-    Lua.pop lua 1-    return (Just lst)-  valuetype _ = Lua.TTABLE--getList :: StackValue a => LuaState -> Int -> IO [a]-getList lua i' = do-  continue <- Lua.next lua i'-  if continue-     then do-       next <- Lua.peek lua (-1)-       Lua.pop lua 1-       x <- maybe (fail "peek returned Nothing") return next-       rest <- getList lua i'-       return (x : rest)-     else return []-#endif--instance StackValue Format where-  push lua (Format f) = Lua.push lua (map toLower f)-  peek l n = fmap Format `fmap` Lua.peek l n-  valuetype _ = Lua.TSTRING+instance ToLuaStack Double where+  push = push . (realToFrac :: Double -> LuaNumber) -instance (StackValue a, StackValue b) => StackValue (M.Map a b) where-  push lua m = do-    let xs = M.toList m-    Lua.createtable lua (length xs + 1) 0-    let addValue (k, v) = Lua.push lua k >> Lua.push lua v >>-                          Lua.rawset lua (-3)-    mapM_ addValue xs-  peek _ _ = undefined -- not needed for our purposes-  valuetype _ = Lua.TTABLE+instance ToLuaStack Int where+  push = push . (fromIntegral :: Int -> LuaInteger) -instance (StackValue a, StackValue b) => StackValue (a,b) where-  push lua (k,v) = do-    Lua.createtable lua 2 0-    Lua.push lua k-    Lua.push lua v-    Lua.rawset lua (-3)-  peek _ _ = undefined -- not needed for our purposes-  valuetype _ = Lua.TTABLE+instance ToLuaStack Format where+  push (Format f) = push (map toLower f)  #if MIN_VERSION_base(4,8,0)-instance {-# OVERLAPS #-} StackValue [Inline] where+instance {-# OVERLAPS #-} ToLuaStack [Inline] where #else-instance StackValue [Inline] where+instance ToLuaStack [Inline] where #endif-  push l ils = Lua.push l =<< inlineListToCustom l ils-  peek _ _ = undefined-  valuetype _ = Lua.TSTRING+  push ils = push =<< inlineListToCustom ils  #if MIN_VERSION_base(4,8,0)-instance {-# OVERLAPS #-} StackValue [Block] where+instance {-# OVERLAPS #-} ToLuaStack [Block] where #else-instance StackValue [Block] where+instance ToLuaStack [Block] where #endif-  push l ils = Lua.push l =<< blockListToCustom l ils-  peek _ _ = undefined-  valuetype _ = Lua.TSTRING+  push ils = push =<< blockListToCustom ils -instance StackValue MetaValue where-  push l (MetaMap m) = Lua.push l m-  push l (MetaList xs) = Lua.push l xs-  push l (MetaBool x) = Lua.push l x-  push l (MetaString s) = Lua.push l s-  push l (MetaInlines ils) = Lua.push l ils-  push l (MetaBlocks bs) = Lua.push l bs-  peek _ _ = undefined-  valuetype (MetaMap _) = Lua.TTABLE-  valuetype (MetaList _) = Lua.TTABLE-  valuetype (MetaBool _) = Lua.TBOOLEAN-  valuetype (MetaString _) = Lua.TSTRING-  valuetype (MetaInlines _) = Lua.TSTRING-  valuetype (MetaBlocks _) = Lua.TSTRING+instance ToLuaStack MetaValue where+  push (MetaMap m)       = push m+  push (MetaList xs)     = push xs+  push (MetaBool x)      = push x+  push (MetaString s)    = push s+  push (MetaInlines ils) = push ils+  push (MetaBlocks bs)   = push bs -instance StackValue Citation where-  push lua cit = do-    Lua.createtable lua 6 0-    let addValue (k :: String, v) = Lua.push lua k >> Lua.push lua v >>-                          Lua.rawset lua (-3)-    addValue ("citationId", citationId cit)-    addValue ("citationPrefix", citationPrefix cit)-    addValue ("citationSuffix", citationSuffix cit)-    addValue ("citationMode", show (citationMode cit))-    addValue ("citationNoteNum", citationNoteNum cit)-    addValue ("citationHash", citationHash cit)-  peek = undefined-  valuetype _ = Lua.TTABLE+instance ToLuaStack Citation where+  push cit = do+    createtable 6 0+    addValue "citationId" $ citationId cit+    addValue "citationPrefix" $ citationPrefix cit+    addValue "citationSuffix" $ citationSuffix cit+    addValue "citationMode" $ show (citationMode cit)+    addValue "citationNoteNum" $ citationNoteNum cit+    addValue "citationHash" $ citationHash cit  data PandocLuaException = PandocLuaException String     deriving (Show, Typeable)@@ -176,147 +107,143 @@ instance Exception PandocLuaException  -- | Convert Pandoc to custom markup.-writeCustom :: FilePath -> WriterOptions -> Pandoc -> IO String+writeCustom :: FilePath -> WriterOptions -> Pandoc -> IO Text writeCustom luaFile opts doc@(Pandoc meta _) = do   luaScript <- UTF8.readFile luaFile   enc <- getForeignEncoding   setForeignEncoding utf8-  lua <- Lua.newstate-  Lua.openlibs lua-  status <- Lua.loadstring lua luaScript luaFile-  -- check for error in lua script (later we'll change the return type-  -- to handle this more gracefully):-  when (status /= 0) $-#if MIN_VERSION_hslua(0,4,0)-    Lua.tostring lua 1 >>= throw . PandocLuaException . UTF8.toString-#else-    Lua.tostring lua 1 >>= throw . PandocLuaException-#endif-  Lua.call lua 0 0+  (body, context) <- runLua $ do+    openlibs+    stat <- loadstring luaScript+    -- check for error in lua script (later we'll change the return type+    -- to handle this more gracefully):+    when (stat /= OK) $+      tostring 1 >>= throw . PandocLuaException . UTF8.toString+    call 0 0   -- TODO - call hierarchicalize, so we have that info-  rendered <- docToCustom lua opts doc-  context <- metaToJSON opts-             (blockListToCustom lua)-             (inlineListToCustom lua)-             meta-  Lua.close lua+    rendered <- docToCustom opts doc+    context <- metaToJSON opts+               blockListToCustom+               inlineListToCustom+               meta+    return (rendered, context)   setForeignEncoding enc-  let body = rendered   case writerTemplate opts of-       Nothing  -> return body-       Just tpl -> return $ renderTemplate' tpl $ setField "body" body context+       Nothing  -> return $ pack body+       Just tpl ->+         case applyTemplate (pack tpl) $ setField "body" body context of+              Left e  -> throw (PandocTemplateError e)+              Right r -> return (pack r) -docToCustom :: LuaState -> WriterOptions -> Pandoc -> IO String-docToCustom lua opts (Pandoc (Meta metamap) blocks) = do-  body <- blockListToCustom lua blocks-  callfunc lua "Doc" body metamap (writerVariables opts)+docToCustom :: WriterOptions -> Pandoc -> Lua String+docToCustom opts (Pandoc (Meta metamap) blocks) = do+  body <- blockListToCustom blocks+  callFunc "Doc" body metamap (writerVariables opts)  -- | Convert Pandoc block element to Custom.-blockToCustom :: LuaState      -- ^ Lua state-              -> Block         -- ^ Block element-              -> IO String+blockToCustom :: Block         -- ^ Block element+              -> Lua String -blockToCustom _ Null = return ""+blockToCustom Null = return "" -blockToCustom lua (Plain inlines) = callfunc lua "Plain" inlines+blockToCustom (Plain inlines) = callFunc "Plain" inlines -blockToCustom lua (Para [Image attr txt (src,tit)]) =-  callfunc lua "CaptionedImage" src tit txt (attrToMap attr)+blockToCustom (Para [Image attr txt (src,tit)]) =+  callFunc "CaptionedImage" src tit txt (attrToMap attr) -blockToCustom lua (Para inlines) = callfunc lua "Para" inlines+blockToCustom (Para inlines) = callFunc "Para" inlines -blockToCustom lua (LineBlock linesList) = callfunc lua "LineBlock" linesList+blockToCustom (LineBlock linesList) = callFunc "LineBlock" linesList -blockToCustom lua (RawBlock format str) =-  callfunc lua "RawBlock" format str+blockToCustom (RawBlock format str) =+  callFunc "RawBlock" format str -blockToCustom lua HorizontalRule = callfunc lua "HorizontalRule"+blockToCustom HorizontalRule = callFunc "HorizontalRule" -blockToCustom lua (Header level attr inlines) =-  callfunc lua "Header" level inlines (attrToMap attr)+blockToCustom (Header level attr inlines) =+  callFunc "Header" level inlines (attrToMap attr) -blockToCustom lua (CodeBlock attr str) =-  callfunc lua "CodeBlock" str (attrToMap attr)+blockToCustom (CodeBlock attr str) =+  callFunc "CodeBlock" str (attrToMap attr) -blockToCustom lua (BlockQuote blocks) = callfunc lua "BlockQuote" blocks+blockToCustom (BlockQuote blocks) = callFunc "BlockQuote" blocks -blockToCustom lua (Table capt aligns widths headers rows') =-  callfunc lua "Table" capt (map show aligns) widths headers rows'+blockToCustom (Table capt aligns widths headers rows') =+  callFunc "Table" capt (map show aligns) widths headers rows' -blockToCustom lua (BulletList items) = callfunc lua "BulletList" items+blockToCustom (BulletList items) = callFunc "BulletList" items -blockToCustom lua (OrderedList (num,sty,delim) items) =-  callfunc lua "OrderedList" items num (show sty) (show delim)+blockToCustom (OrderedList (num,sty,delim) items) =+  callFunc "OrderedList" items num (show sty) (show delim) -blockToCustom lua (DefinitionList items) =-  callfunc lua "DefinitionList" items+blockToCustom (DefinitionList items) =+  callFunc "DefinitionList" items -blockToCustom lua (Div attr items) =-  callfunc lua "Div" items (attrToMap attr)+blockToCustom (Div attr items) =+  callFunc "Div" items (attrToMap attr)  -- | Convert list of Pandoc block elements to Custom.-blockListToCustom :: LuaState -- ^ Options-                  -> [Block]       -- ^ List of block elements-                  -> IO String-blockListToCustom lua xs = do-  blocksep <- callfunc lua "Blocksep"-  bs <- mapM (blockToCustom lua) xs+blockListToCustom :: [Block]       -- ^ List of block elements+                  -> Lua String+blockListToCustom xs = do+  blocksep <- callFunc "Blocksep"+  bs <- mapM blockToCustom xs   return $ mconcat $ intersperse blocksep bs  -- | Convert list of Pandoc inline elements to Custom.-inlineListToCustom :: LuaState -> [Inline] -> IO String-inlineListToCustom lua lst = do-  xs <- mapM (inlineToCustom lua) lst-  return $ concat xs+inlineListToCustom :: [Inline] -> Lua String+inlineListToCustom lst = do+  xs <- mapM inlineToCustom lst+  return $ mconcat xs  -- | Convert Pandoc inline element to Custom.-inlineToCustom :: LuaState -> Inline -> IO String+inlineToCustom :: Inline -> Lua String -inlineToCustom lua (Str str) = callfunc lua "Str" str+inlineToCustom (Str str) = callFunc "Str" str -inlineToCustom lua Space = callfunc lua "Space"+inlineToCustom Space = callFunc "Space" -inlineToCustom lua SoftBreak = callfunc lua "SoftBreak"+inlineToCustom SoftBreak = callFunc "SoftBreak" -inlineToCustom lua (Emph lst) = callfunc lua "Emph" lst+inlineToCustom (Emph lst) = callFunc "Emph" lst -inlineToCustom lua (Strong lst) = callfunc lua "Strong" lst+inlineToCustom (Strong lst) = callFunc "Strong" lst -inlineToCustom lua (Strikeout lst) = callfunc lua "Strikeout" lst+inlineToCustom (Strikeout lst) = callFunc "Strikeout" lst -inlineToCustom lua (Superscript lst) = callfunc lua "Superscript" lst+inlineToCustom (Superscript lst) = callFunc "Superscript" lst -inlineToCustom lua (Subscript lst) = callfunc lua "Subscript" lst+inlineToCustom (Subscript lst) = callFunc "Subscript" lst -inlineToCustom lua (SmallCaps lst) = callfunc lua "SmallCaps" lst+inlineToCustom (SmallCaps lst) = callFunc "SmallCaps" lst -inlineToCustom lua (Quoted SingleQuote lst) = callfunc lua "SingleQuoted" lst+inlineToCustom (Quoted SingleQuote lst) = callFunc "SingleQuoted" lst -inlineToCustom lua (Quoted DoubleQuote lst) = callfunc lua "DoubleQuoted" lst+inlineToCustom (Quoted DoubleQuote lst) = callFunc "DoubleQuoted" lst -inlineToCustom lua (Cite cs lst) = callfunc lua "Cite" lst cs+inlineToCustom (Cite cs lst) = callFunc "Cite" lst cs -inlineToCustom lua (Code attr str) =-  callfunc lua "Code" str (attrToMap attr)+inlineToCustom (Code attr str) =+  callFunc "Code" str (attrToMap attr) -inlineToCustom lua (Math DisplayMath str) =-  callfunc lua "DisplayMath" str+inlineToCustom (Math DisplayMath str) =+  callFunc "DisplayMath" str -inlineToCustom lua (Math InlineMath str) =-  callfunc lua "InlineMath" str+inlineToCustom (Math InlineMath str) =+  callFunc "InlineMath" str -inlineToCustom lua (RawInline format str) =-  callfunc lua "RawInline" format str+inlineToCustom (RawInline format str) =+  callFunc "RawInline" format str -inlineToCustom lua (LineBreak) = callfunc lua "LineBreak"+inlineToCustom LineBreak = callFunc "LineBreak" -inlineToCustom lua (Link attr txt (src,tit)) =-  callfunc lua "Link" txt src tit (attrToMap attr)+inlineToCustom (Link attr txt (src,tit)) =+  callFunc "Link" txt src tit (attrToMap attr) -inlineToCustom lua (Image attr alt (src,tit)) =-  callfunc lua "Image" alt src tit (attrToMap attr)+inlineToCustom (Image attr alt (src,tit)) =+  callFunc "Image" alt src tit (attrToMap attr) -inlineToCustom lua (Note contents) = callfunc lua "Note" contents+inlineToCustom (Note contents) = callFunc "Note" contents -inlineToCustom lua (Span attr items) =-  callfunc lua "Span" items (attrToMap attr)+inlineToCustom (Span attr items) =+  callFunc "Span" items (attrToMap attr)
src/Text/Pandoc/Writers/Docbook.hs view
@@ -1,6 +1,7 @@-{-# LANGUAGE OverloadedStrings, PatternGuards #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternGuards     #-} {--Copyright (C) 2006-2015 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2006-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -19,7 +20,7 @@  {- |    Module      : Text.Pandoc.Writers.Docbook-   Copyright   : Copyright (C) 2006-2015 John MacFarlane+   Copyright   : Copyright (C) 2006-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -28,34 +29,43 @@  Conversion of 'Pandoc' documents to Docbook XML. -}-module Text.Pandoc.Writers.Docbook ( writeDocbook) where+module Text.Pandoc.Writers.Docbook ( writeDocbook4, writeDocbook5 ) where+import Control.Monad.Reader+import Data.Char (toLower)+import Data.Generics (everywhere, mkT)+import Data.List (isPrefixOf, isSuffixOf, stripPrefix)+import Data.Monoid (Any (..))+import Data.Text (Text)+import qualified Text.Pandoc.Builder as B+import Text.Pandoc.Class (PandocMonad, report) import Text.Pandoc.Definition-import Text.Pandoc.XML+import Text.Pandoc.Highlighting (languages, languagesByExtension)+import Text.Pandoc.ImageSize+import Text.Pandoc.Logging+import Text.Pandoc.Options+import Text.Pandoc.Pretty import Text.Pandoc.Shared+import Text.Pandoc.Templates (renderTemplate') import Text.Pandoc.Walk+import Text.Pandoc.Writers.Math import Text.Pandoc.Writers.Shared-import Text.Pandoc.Options-import Text.Pandoc.Templates (renderTemplate')-import Text.Pandoc.Readers.TeXMath-import Data.List ( stripPrefix, isPrefixOf, intercalate, isSuffixOf )-import Data.Char ( toLower )-import Data.Monoid ( Any(..) )-import Text.Pandoc.Highlighting ( languages, languagesByExtension )-import Text.Pandoc.Pretty-import Text.Pandoc.ImageSize-import qualified Text.Pandoc.Builder as B+import Text.Pandoc.XML import Text.TeXMath import qualified Text.XML.Light as Xml-import Data.Generics (everywhere, mkT) +data DocBookVersion = DocBook4 | DocBook5+     deriving (Eq, Show)++type DB = ReaderT DocBookVersion+ -- | Convert list of authors to a docbook <author> section-authorToDocbook :: WriterOptions -> [Inline] -> B.Inlines-authorToDocbook opts name' =-  let name = render Nothing $ inlinesToDocbook opts name'-      colwidth = if writerWrapText opts == WrapAuto+authorToDocbook :: PandocMonad m => WriterOptions -> [Inline] -> DB m B.Inlines+authorToDocbook opts name' = do+  name <- render Nothing <$> inlinesToDocbook opts name'+  let colwidth = if writerWrapText opts == WrapAuto                     then Just $ writerColumns opts                     else Nothing-  in  B.rawInline "docbook" $ render colwidth $+  return $ B.rawInline "docbook" $ render colwidth $       if ',' `elem` name          then -- last name first               let (lastname, rest) = break (==',') name@@ -66,52 +76,63 @@               let namewords = words name                   lengthname = length namewords                   (firstname, lastname) = case lengthname of-                    0  -> ("","")-                    1  -> ("", name)-                    n  -> (intercalate " " (take (n-1) namewords), last namewords)+                    0 -> ("","")+                    1 -> ("", name)+                    n -> (unwords (take (n-1) namewords), last namewords)                in inTagsSimple "firstname" (text $ escapeStringForXML firstname) $$                   inTagsSimple "surname" (text $ escapeStringForXML lastname) +writeDocbook4 :: PandocMonad m => WriterOptions -> Pandoc -> m Text+writeDocbook4 opts d =+  runReaderT (writeDocbook opts d) DocBook4++writeDocbook5 :: PandocMonad m => WriterOptions -> Pandoc -> m Text+writeDocbook5 opts d =+  runReaderT (writeDocbook opts d) DocBook5+ -- | Convert Pandoc document to string in Docbook format.-writeDocbook :: WriterOptions -> Pandoc -> String-writeDocbook opts (Pandoc meta blocks) =+writeDocbook :: PandocMonad m => WriterOptions -> Pandoc -> DB m Text+writeDocbook opts (Pandoc meta blocks) = do   let elements = hierarchicalize blocks-      colwidth = if writerWrapText opts == WrapAuto+  let colwidth = if writerWrapText opts == WrapAuto                     then Just $ writerColumns opts                     else Nothing-      render'  = render colwidth-      opts'    = if (maybe False (("/book>" `isSuffixOf`) . trimr)+  let render' :: Doc -> Text+      render' = render colwidth+  let opts'    = if maybe False (("/book>" `isSuffixOf`) . trimr)                             (writerTemplate opts) &&-                     TopLevelDefault == writerTopLevelDivision opts)+                     TopLevelDefault == writerTopLevelDivision opts                     then opts{ writerTopLevelDivision = TopLevelChapter }                     else opts-      -- The numbering here follows LaTeX's internal numbering-      startLvl = case writerTopLevelDivision opts' of+  -- The numbering here follows LaTeX's internal numbering+  let startLvl = case writerTopLevelDivision opts' of                    TopLevelPart    -> -1                    TopLevelChapter -> 0                    TopLevelSection -> 1                    TopLevelDefault -> 1-      auths'   = map (authorToDocbook opts) $ docAuthors meta-      meta'    = B.setMeta "author" auths' meta-      Just metadata = metaToJSON opts-                 (Just . render colwidth . (vcat .-                          (map (elementToDocbook opts' startLvl)) . hierarchicalize))-                 (Just . render colwidth . inlinesToDocbook opts')+  auths' <- mapM (authorToDocbook opts) $ docAuthors meta+  let meta' = B.setMeta "author" auths' meta+  metadata <- metaToJSON opts+                 (fmap (render' . vcat) .+                          mapM (elementToDocbook opts' startLvl) .+                            hierarchicalize)+                 (fmap render' . inlinesToDocbook opts')                  meta'-      main     = render' $ vcat (map (elementToDocbook opts' startLvl) elements)-      context = defField "body" main-              $ defField "mathml" (case writerHTMLMathMethod opts of-                                        MathML _ -> True-                                        _        -> False)-              $ metadata-  in  case writerTemplate opts of-           Nothing   -> main-           Just tpl  -> renderTemplate' tpl context+  main <- (render' . vcat) <$> mapM (elementToDocbook opts' startLvl) elements+  let context = defField "body" main+              $+                  defField "mathml" (case writerHTMLMathMethod opts of+                                          MathML -> True+                                          _      -> False) metadata+  case writerTemplate opts of+       Nothing  -> return main+       Just tpl -> renderTemplate' tpl context  -- | Convert an Element to Docbook.-elementToDocbook :: WriterOptions -> Int -> Element -> Doc+elementToDocbook :: PandocMonad m => WriterOptions -> Int -> Element -> DB m Doc elementToDocbook opts _   (Blk block) = blockToDocbook opts block-elementToDocbook opts lvl (Sec _ _num (id',_,_) title elements) =+elementToDocbook opts lvl (Sec _ _num (id',_,_) title elements) = do+  version <- ask   -- Docbook doesn't allow sections with no content, so insert some if needed   let elements' = if null elements                     then [Blk (Para [])]@@ -119,24 +140,25 @@       tag = case lvl of                  -1                   -> "part"                  0                    -> "chapter"-                 n | n >= 1 && n <= 5 -> if writerDocbook5 opts+                 n | n >= 1 && n <= 5 -> if version == DocBook5                                               then "section"                                               else "sect" ++ show n                  _                    -> "simplesect"-      idName = if writerDocbook5 opts+      idName = if version == DocBook5                  then "xml:id"                  else "id"       idAttr = [(idName, writerIdentifierPrefix opts ++ id') | not (null id')]-      nsAttr = if writerDocbook5 opts && lvl == 0 then [("xmlns", "http://docbook.org/ns/docbook"),("xmlns:xlink", "http://www.w3.org/1999/xlink")]+      nsAttr = if version == DocBook5 && lvl == 0 then [("xmlns", "http://docbook.org/ns/docbook"),("xmlns:xlink", "http://www.w3.org/1999/xlink")]                                       else []       attribs = nsAttr ++ idAttr-  in  inTags True tag attribs $-      inTagsSimple "title" (inlinesToDocbook opts title) $$-      vcat (map (elementToDocbook opts (lvl + 1)) elements')+  contents <- mapM (elementToDocbook opts (lvl + 1)) elements'+  title' <- inlinesToDocbook opts title+  return $ inTags True tag attribs $+      inTagsSimple "title" title' $$ vcat contents  -- | Convert a list of Pandoc blocks to Docbook.-blocksToDocbook :: WriterOptions -> [Block] -> Doc-blocksToDocbook opts = vcat . map (blockToDocbook opts)+blocksToDocbook :: PandocMonad m => WriterOptions -> [Block] -> DB m Doc+blocksToDocbook opts = fmap vcat . mapM (blockToDocbook opts)  -- | Auxiliary function to convert Plain block to Para. plainToPara :: Block -> Block@@ -145,74 +167,82 @@  -- | Convert a list of pairs of terms and definitions into a list of -- Docbook varlistentrys.-deflistItemsToDocbook :: WriterOptions -> [([Inline],[[Block]])] -> Doc+deflistItemsToDocbook :: PandocMonad m+                      => WriterOptions -> [([Inline],[[Block]])] -> DB m Doc deflistItemsToDocbook opts items =-  vcat $ map (\(term, defs) -> deflistItemToDocbook opts term defs) items+  vcat <$> mapM (uncurry (deflistItemToDocbook opts)) items  -- | Convert a term and a list of blocks into a Docbook varlistentry.-deflistItemToDocbook :: WriterOptions -> [Inline] -> [[Block]] -> Doc-deflistItemToDocbook opts term defs =-  let def' = concatMap (map plainToPara) defs-  in  inTagsIndented "varlistentry" $-      inTagsIndented "term" (inlinesToDocbook opts term) $$-      inTagsIndented "listitem" (blocksToDocbook opts def')+deflistItemToDocbook :: PandocMonad m+                     => WriterOptions -> [Inline] -> [[Block]] -> DB m Doc+deflistItemToDocbook opts term defs = do+  term' <- inlinesToDocbook opts term+  def' <- blocksToDocbook opts $ concatMap (map plainToPara) defs+  return $ inTagsIndented "varlistentry" $+      inTagsIndented "term" term' $$+      inTagsIndented "listitem" def'  -- | Convert a list of lists of blocks to a list of Docbook list items.-listItemsToDocbook :: WriterOptions -> [[Block]] -> Doc-listItemsToDocbook opts items = vcat $ map (listItemToDocbook opts) items+listItemsToDocbook :: PandocMonad m => WriterOptions -> [[Block]] -> DB m Doc+listItemsToDocbook opts items = vcat <$> mapM (listItemToDocbook opts) items  -- | Convert a list of blocks into a Docbook list item.-listItemToDocbook :: WriterOptions -> [Block] -> Doc+listItemToDocbook :: PandocMonad m => WriterOptions -> [Block] -> DB m Doc listItemToDocbook opts item =-  inTagsIndented "listitem" $ blocksToDocbook opts $ map plainToPara item+  inTagsIndented "listitem" <$> blocksToDocbook opts (map plainToPara item)  imageToDocbook :: WriterOptions -> Attr -> String -> Doc imageToDocbook _ attr src = selfClosingTag "imagedata" $   ("fileref", src) : idAndRole attr ++ dims   where     dims = go Width "width" ++ go Height "depth"-    go dir dstr = case (dimension dir attr) of+    go dir dstr = case dimension dir attr of                     Just a  -> [(dstr, show a)]                     Nothing -> []  -- | Convert a Pandoc block element to Docbook.-blockToDocbook :: WriterOptions -> Block -> Doc-blockToDocbook _ Null = empty+blockToDocbook :: PandocMonad m => WriterOptions -> Block -> DB m Doc+blockToDocbook _ Null = return empty -- Add ids to paragraphs in divs with ids - this is needed for -- pandoc-citeproc to get link anchors in bibliographies: blockToDocbook opts (Div (ident,_,_) [Para lst]) =   let attribs = [("id", ident) | not (null ident)] in   if hasLineBreaks lst-     then flush $ nowrap $ inTags False "literallayout" attribs-                         $ inlinesToDocbook opts lst-     else inTags True "para" attribs $ inlinesToDocbook opts lst-blockToDocbook opts (Div (ident,_,_) bs) =-  (if null ident-      then mempty-      else selfClosingTag "anchor" [("id", ident)]) $$-  blocksToDocbook opts (map plainToPara bs)-blockToDocbook _ (Header _ _ _) = empty -- should not occur after hierarchicalize+     then (flush . nowrap . inTags False "literallayout" attribs)+                         <$> inlinesToDocbook opts lst+     else inTags True "para" attribs <$> inlinesToDocbook opts lst+blockToDocbook opts (Div (ident,_,_) bs) = do+  contents <- blocksToDocbook opts (map plainToPara bs)+  return $+    (if null ident+        then mempty+        else selfClosingTag "anchor" [("id", ident)]) $$ contents+blockToDocbook _ h@Header{} = do+  -- should not occur after hierarchicalize, except inside lists/blockquotes+  report $ BlockNotRendered h+  return empty blockToDocbook opts (Plain lst) = inlinesToDocbook opts lst -- title beginning with fig: indicates that the image is a figure-blockToDocbook opts (Para [Image attr txt (src,'f':'i':'g':':':_)]) =-  let alt  = inlinesToDocbook opts txt-      capt = if null txt+blockToDocbook opts (Para [Image attr txt (src,'f':'i':'g':':':_)]) = do+  alt <- inlinesToDocbook opts txt+  let capt = if null txt                 then empty                 else inTagsSimple "title" alt-  in  inTagsIndented "figure" $+  return $ inTagsIndented "figure" $         capt $$-        (inTagsIndented "mediaobject" $-           (inTagsIndented "imageobject"-             (imageToDocbook opts attr src)) $$+        inTagsIndented "mediaobject" (+           inTagsIndented "imageobject"+             (imageToDocbook opts attr src) $$            inTagsSimple "textobject" (inTagsSimple "phrase" alt)) blockToDocbook opts (Para lst)-  | hasLineBreaks lst = flush $ nowrap $ inTagsSimple "literallayout" $ inlinesToDocbook opts lst-  | otherwise         = inTagsIndented "para" $ inlinesToDocbook opts lst+  | hasLineBreaks lst = (flush . nowrap . inTagsSimple "literallayout")+                        <$> inlinesToDocbook opts lst+  | otherwise         = inTagsIndented "para" <$> inlinesToDocbook opts lst blockToDocbook opts (LineBlock lns) =   blockToDocbook opts $ linesToPara lns blockToDocbook opts (BlockQuote blocks) =-  inTagsIndented "blockquote" $ blocksToDocbook opts blocks-blockToDocbook _ (CodeBlock (_,classes,_) str) =+  inTagsIndented "blockquote" <$> blocksToDocbook opts blocks+blockToDocbook _ (CodeBlock (_,classes,_) str) = return $   text ("<programlisting" ++ lang ++ ">") <> cr <>      flush (text (escapeStringForXML str) <> cr <> text "</programlisting>")     where lang  = if null langs@@ -224,11 +254,11 @@                            then [s]                            else languagesByExtension . map toLower $ s           langs       = concatMap langsFrom classes-blockToDocbook opts (BulletList lst) =+blockToDocbook opts (BulletList lst) = do   let attribs = [("spacing", "compact") | isTightList lst]-  in  inTags True "itemizedlist" attribs $ listItemsToDocbook opts lst-blockToDocbook _ (OrderedList _ []) = empty-blockToDocbook opts (OrderedList (start, numstyle, _) (first:rest)) =+  inTags True "itemizedlist" attribs <$> listItemsToDocbook opts lst+blockToDocbook _ (OrderedList _ []) = return empty+blockToDocbook opts (OrderedList (start, numstyle, _) (first:rest)) = do   let numeration = case numstyle of                        DefaultStyle -> []                        Decimal      -> [("numeration", "arabic")]@@ -239,40 +269,46 @@                        LowerRoman   -> [("numeration", "lowerroman")]       spacing    = [("spacing", "compact") | isTightList (first:rest)]       attribs    = numeration ++ spacing-      items      = if start == 1-                      then listItemsToDocbook opts (first:rest)-                      else (inTags True "listitem" [("override",show start)]-                           (blocksToDocbook opts $ map plainToPara first)) $$-                           listItemsToDocbook opts rest-  in  inTags True "orderedlist" attribs items-blockToDocbook opts (DefinitionList lst) =+  items <- if start == 1+              then listItemsToDocbook opts (first:rest)+              else do+                first' <- blocksToDocbook opts (map plainToPara first)+                rest' <- listItemsToDocbook opts rest+                return $+                  inTags True "listitem" [("override",show start)] first' $$+                   rest'+  return $ inTags True "orderedlist" attribs items+blockToDocbook opts (DefinitionList lst) = do   let attribs = [("spacing", "compact") | isTightList $ concatMap snd lst]-  in  inTags True "variablelist" attribs $ deflistItemsToDocbook opts lst-blockToDocbook opts (RawBlock f str)-  | f == "docbook" = text str -- raw XML block-  | f == "html"    = if writerDocbook5 opts-                        then empty -- No html in Docbook5-                        else text str -- allow html for backwards compatibility-  | otherwise      = empty-blockToDocbook _ HorizontalRule = empty -- not semantic-blockToDocbook opts (Table caption aligns widths headers rows) =-  let captionDoc   = if null caption-                        then empty-                        else inTagsIndented "title"-                              (inlinesToDocbook opts caption)-      tableType    = if isEmpty captionDoc then "informaltable" else "table"+  inTags True "variablelist" attribs <$> deflistItemsToDocbook opts lst+blockToDocbook _ b@(RawBlock f str)+  | f == "docbook" = return $ text str -- raw XML block+  | f == "html"    = do+                     version <- ask+                     if version == DocBook5+                        then return empty -- No html in Docbook5+                        else return $ text str -- allow html for backwards compatibility+  | otherwise      = do+      report $ BlockNotRendered b+      return empty+blockToDocbook _ HorizontalRule = return empty -- not semantic+blockToDocbook opts (Table caption aligns widths headers rows) = do+  captionDoc <- if null caption+                   then return empty+                   else inTagsIndented "title" <$>+                         inlinesToDocbook opts caption+  let tableType    = if isEmpty captionDoc then "informaltable" else "table"       percent w    = show (truncate (100*w) :: Integer) ++ "*"       coltags = vcat $ zipWith (\w al -> selfClosingTag "colspec"                        ([("colwidth", percent w) | w > 0] ++                         [("align", alignmentToString al)])) widths aligns-      head' = if all null headers-                 then empty-                 else inTagsIndented "thead" $-                         tableRowToDocbook opts headers-      body' = inTagsIndented "tbody" $-              vcat $ map (tableRowToDocbook opts) rows-  in  inTagsIndented tableType $ captionDoc $$-        (inTags True "tgroup" [("cols", show (length headers))] $+  head' <- if all null headers+              then return empty+              else inTagsIndented "thead" <$> tableRowToDocbook opts headers+  body' <- (inTagsIndented "tbody" . vcat) <$>+              mapM (tableRowToDocbook opts) rows+  return $ inTagsIndented tableType $ captionDoc $$+        inTags True "tgroup" [("cols", show (length headers))] (          coltags $$ head' $$ body')  hasLineBreaks :: [Inline] -> Bool@@ -280,101 +316,111 @@   where     removeNote :: Inline -> Inline     removeNote (Note _) = Str ""-    removeNote x = x+    removeNote x        = x     isLineBreak :: Inline -> Any     isLineBreak LineBreak = Any True-    isLineBreak _ = Any False+    isLineBreak _         = Any False  alignmentToString :: Alignment -> [Char] alignmentToString alignment = case alignment of-                                 AlignLeft -> "left"-                                 AlignRight -> "right"-                                 AlignCenter -> "center"+                                 AlignLeft    -> "left"+                                 AlignRight   -> "right"+                                 AlignCenter  -> "center"                                  AlignDefault -> "left" -tableRowToDocbook :: WriterOptions+tableRowToDocbook :: PandocMonad m+                  => WriterOptions                   -> [[Block]]-                  -> Doc+                  -> DB m Doc tableRowToDocbook opts cols =-  inTagsIndented "row" $ vcat $ map (tableItemToDocbook opts) cols+  (inTagsIndented "row" . vcat) <$> mapM (tableItemToDocbook opts) cols -tableItemToDocbook :: WriterOptions+tableItemToDocbook :: PandocMonad m+                   => WriterOptions                    -> [Block]-                   -> Doc+                   -> DB m Doc tableItemToDocbook opts item =-  inTags True "entry" [] $ vcat $ map (blockToDocbook opts) item+  (inTags True "entry" [] . vcat) <$> mapM (blockToDocbook opts) item  -- | Convert a list of inline elements to Docbook.-inlinesToDocbook :: WriterOptions -> [Inline] -> Doc-inlinesToDocbook opts lst = hcat $ map (inlineToDocbook opts) lst+inlinesToDocbook :: PandocMonad m => WriterOptions -> [Inline] -> DB m Doc+inlinesToDocbook opts lst = hcat <$> mapM (inlineToDocbook opts) lst  -- | Convert an inline element to Docbook.-inlineToDocbook :: WriterOptions -> Inline -> Doc-inlineToDocbook _ (Str str) = text $ escapeStringForXML str+inlineToDocbook :: PandocMonad m => WriterOptions -> Inline -> DB m Doc+inlineToDocbook _ (Str str) = return $ text $ escapeStringForXML str inlineToDocbook opts (Emph lst) =-  inTagsSimple "emphasis" $ inlinesToDocbook opts lst+  inTagsSimple "emphasis" <$> inlinesToDocbook opts lst inlineToDocbook opts (Strong lst) =-  inTags False "emphasis" [("role", "strong")] $ inlinesToDocbook opts lst+  inTags False "emphasis" [("role", "strong")] <$> inlinesToDocbook opts lst inlineToDocbook opts (Strikeout lst) =-  inTags False "emphasis" [("role", "strikethrough")] $+  inTags False "emphasis" [("role", "strikethrough")] <$>   inlinesToDocbook opts lst inlineToDocbook opts (Superscript lst) =-  inTagsSimple "superscript" $ inlinesToDocbook opts lst+  inTagsSimple "superscript" <$> inlinesToDocbook opts lst inlineToDocbook opts (Subscript lst) =-  inTagsSimple "subscript" $ inlinesToDocbook opts lst+  inTagsSimple "subscript" <$> inlinesToDocbook opts lst inlineToDocbook opts (SmallCaps lst) =-  inTags False "emphasis" [("role", "smallcaps")] $+  inTags False "emphasis" [("role", "smallcaps")] <$>   inlinesToDocbook opts lst inlineToDocbook opts (Quoted _ lst) =-  inTagsSimple "quote" $ inlinesToDocbook opts lst+  inTagsSimple "quote" <$> inlinesToDocbook opts lst inlineToDocbook opts (Cite _ lst) =   inlinesToDocbook opts lst inlineToDocbook opts (Span (ident,_,_) ils) =-  (if null ident-      then mempty-      else selfClosingTag "anchor" [("id", ident)]) <>+  ((if null ident+       then mempty+       else selfClosingTag "anchor" [("id", ident)]) <>) <$>   inlinesToDocbook opts ils inlineToDocbook _ (Code _ str) =-  inTagsSimple "literal" $ text (escapeStringForXML str)+  return $ inTagsSimple "literal" $ text (escapeStringForXML str) inlineToDocbook opts (Math t str)-  | isMathML (writerHTMLMathMethod opts) =-    case writeMathML dt <$> readTeX str of-      Right r  -> inTagsSimple tagtype-                  $ text $ Xml.ppcElement conf-                  $ fixNS-                  $ removeAttr r-      Left _   -> inlinesToDocbook opts-                  $ texMathToInlines t str-  | otherwise = inlinesToDocbook opts $ texMathToInlines t str-     where (dt, tagtype) = case t of-                            InlineMath  -> (DisplayInline,"inlineequation")-                            DisplayMath -> (DisplayBlock,"informalequation")+  | isMathML (writerHTMLMathMethod opts) = do+    res <- convertMath writeMathML t str+    case res of+         Right r  -> return $ inTagsSimple tagtype+                     $ text $ Xml.ppcElement conf+                     $ fixNS+                     $ removeAttr r+         Left il  -> inlineToDocbook opts il+  | otherwise =+     texMathToInlines t str >>= inlinesToDocbook opts+     where tagtype = case t of+                       InlineMath  -> "inlineequation"+                       DisplayMath -> "informalequation"            conf = Xml.useShortEmptyTags (const False) Xml.defaultConfigPP            removeAttr e = e{ Xml.elAttribs = [] }            fixNS' qname = qname{ Xml.qPrefix = Just "mml" }            fixNS = everywhere (mkT fixNS')-inlineToDocbook _ (RawInline f x) | f == "html" || f == "docbook" = text x-                                  | otherwise                     = empty-inlineToDocbook _ LineBreak = text "\n"-inlineToDocbook _ Space = space+inlineToDocbook _ il@(RawInline f x)+  | f == "html" || f == "docbook" = return $ text x+  | otherwise                     = do+      report $ InlineNotRendered il+      return empty+inlineToDocbook _ LineBreak = return $ text "\n"+-- currently ignore, would require the option to add custom+-- styles to the document+inlineToDocbook _ Space = return space -- because we use \n for LineBreak, we can't do soft breaks:-inlineToDocbook _ SoftBreak = space+inlineToDocbook _ SoftBreak = return space inlineToDocbook opts (Link attr txt (src, _))   | Just email <- stripPrefix "mailto:" src =       let emailLink = inTagsSimple "email" $ text $-                      escapeStringForXML $ email+                      escapeStringForXML email       in  case txt of-           [Str s] | escapeURI s == email -> emailLink-           _             -> inlinesToDocbook opts txt <+>-                              char '(' <> emailLink <> char ')'-  | otherwise =-      (if isPrefixOf "#" src-            then inTags False "link" $ ("linkend", drop 1 src) : idAndRole attr-            else if writerDocbook5 opts+           [Str s] | escapeURI s == email -> return emailLink+           _             -> do contents <- inlinesToDocbook opts txt+                               return $ contents <+>+                                          char '(' <> emailLink <> char ')'+  | otherwise = do+      version <- ask+      (if "#" `isPrefixOf` src+            then inTags False "link" $ ("linkend", writerIdentifierPrefix opts ++ drop 1 src) : idAndRole attr+            else if version == DocBook5                     then inTags False "link" $ ("xlink:href", src) : idAndRole attr-                    else inTags False "ulink" $ ("url", src) : idAndRole attr ) $-        inlinesToDocbook opts txt-inlineToDocbook opts (Image attr _ (src, tit)) =+                    else inTags False "ulink" $ ("url", src) : idAndRole attr )+        <$> inlinesToDocbook opts txt+inlineToDocbook opts (Image attr _ (src, tit)) = return $   let titleDoc = if null tit                    then empty                    else inTagsIndented "objectinfo" $@@ -382,11 +428,11 @@   in  inTagsIndented "inlinemediaobject" $ inTagsIndented "imageobject" $       titleDoc $$ imageToDocbook opts attr src inlineToDocbook opts (Note contents) =-  inTagsIndented "footnote" $ blocksToDocbook opts contents+  inTagsIndented "footnote" <$> blocksToDocbook opts contents  isMathML :: HTMLMathMethod -> Bool-isMathML (MathML _) = True-isMathML _          = False+isMathML MathML = True+isMathML _      = False  idAndRole :: Attr -> [(String, String)] idAndRole (id',cls,_) = ident ++ role
src/Text/Pandoc/Writers/Docx.hs view
@@ -1,6 +1,10 @@-{-# LANGUAGE ScopedTypeVariables, PatternGuards, ViewPatterns #-}++{-# LANGUAGE PatternGuards       #-}+{-# LANGUAGE RankNTypes          #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE ViewPatterns        #-} {--Copyright (C) 2012-2015 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2012-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -19,7 +23,7 @@  {- |    Module      : Text.Pandoc.Writers.Docx-   Copyright   : Copyright (C) 2012-2015 John MacFarlane+   Copyright   : Copyright (C) 2012-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -29,44 +33,46 @@ Conversion of 'Pandoc' documents to docx. -} module Text.Pandoc.Writers.Docx ( writeDocx ) where-import Data.List ( intercalate, isPrefixOf, isSuffixOf )+import Codec.Archive.Zip+import Control.Applicative ((<|>))+import Control.Monad.Except (catchError)+import Control.Monad.Reader+import Control.Monad.State.Strict import qualified Data.ByteString as B import qualified Data.ByteString.Lazy as BL import qualified Data.ByteString.Lazy.Char8 as BL8+import Data.Char (isSpace, ord, toLower)+import Data.List (intercalate, isPrefixOf, isSuffixOf) import qualified Data.Map as M+import Data.Maybe (fromMaybe, isNothing, mapMaybe, maybeToList)+import Data.Monoid ((<>)) import qualified Data.Set as Set-import qualified Text.Pandoc.UTF8 as UTF8-import Codec.Archive.Zip+import qualified Data.Text as T import Data.Time.Clock.POSIX-import System.Environment+import Skylighting+import System.Random (randomR)+import Text.Pandoc.BCP47 (getLang, renderLang)+import Text.Pandoc.Class (PandocMonad, report, toLang)+import qualified Text.Pandoc.Class as P import Text.Pandoc.Compat.Time import Text.Pandoc.Definition import Text.Pandoc.Generic+import Text.Pandoc.Highlighting (highlight) import Text.Pandoc.ImageSize-import Text.Pandoc.Shared hiding (Element)-import Text.Pandoc.Writers.Shared (fixDisplayMath)+import Text.Pandoc.Logging+import Text.Pandoc.MIME (MimeType, extensionFromMimeType, getMimeType,+                         getMimeTypeDef) import Text.Pandoc.Options-import Text.Pandoc.Readers.TeXMath-import Text.Pandoc.Highlighting ( highlight )-import Text.Pandoc.Walk-import Text.XML.Light as XML-import Text.TeXMath import Text.Pandoc.Readers.Docx.StyleMap-import Text.Pandoc.Readers.Docx.Util (elemName)-import Control.Monad.Reader-import Control.Monad.State-import Skylighting-import Data.Unique (hashUnique, newUnique)-import System.Random (randomRIO)+import Text.Pandoc.Shared hiding (Element)+import qualified Text.Pandoc.UTF8 as UTF8+import Text.Pandoc.Walk+import Text.Pandoc.Writers.Math+import Text.Pandoc.Writers.Shared (fixDisplayMath) import Text.Printf (printf)-import qualified Control.Exception as E-import Data.Monoid ((<>))-import qualified Data.Text as T-import Text.Pandoc.MIME (MimeType, getMimeType, getMimeTypeDef,-                         extensionFromMimeType)-import Control.Applicative ((<|>))-import Data.Maybe (fromMaybe, mapMaybe, maybeToList, isNothing)-import Data.Char (ord, isSpace, toLower)+import Text.TeXMath+import Text.XML.Light as XML+import Text.XML.Light.Cursor as XMLC  data ListMarker = NoMarker                 | BulletMarker@@ -79,28 +85,28 @@ listMarkerToId (NumberMarker sty delim n) =   '9' : '9' : styNum : delimNum : show n   where styNum = case sty of-                      DefaultStyle   -> '2'-                      Example        -> '3'-                      Decimal        -> '4'-                      LowerRoman     -> '5'-                      UpperRoman     -> '6'-                      LowerAlpha     -> '7'-                      UpperAlpha     -> '8'+                      DefaultStyle -> '2'+                      Example      -> '3'+                      Decimal      -> '4'+                      LowerRoman   -> '5'+                      UpperRoman   -> '6'+                      LowerAlpha   -> '7'+                      UpperAlpha   -> '8'         delimNum = case delim of-                      DefaultDelim   -> '0'-                      Period         -> '1'-                      OneParen       -> '2'-                      TwoParens      -> '3'+                      DefaultDelim -> '0'+                      Period       -> '1'+                      OneParen     -> '2'+                      TwoParens    -> '3'  data WriterEnv = WriterEnv{ envTextProperties :: [Element]                           , envParaProperties :: [Element]-                          , envRTL :: Bool-                          , envListLevel :: Int-                          , envListNumId :: Int-                          , envInDel :: Bool-                          , envChangesAuthor :: String-                          , envChangesDate :: String-                          , envPrintWidth :: Integer+                          , envRTL            :: Bool+                          , envListLevel      :: Int+                          , envListNumId      :: Int+                          , envInDel          :: Bool+                          , envChangesAuthor  :: String+                          , envChangesDate    :: String+                          , envPrintWidth     :: Integer                           }  defaultWriterEnv :: WriterEnv@@ -117,6 +123,7 @@  data WriterState = WriterState{          stFootnotes      :: [Element]+       , stComments       :: [([(String,String)], [Inline])]        , stSectionIds     :: Set.Set String        , stExternalLinks  :: M.Map String String        , stImages         :: M.Map FilePath (String, String, Maybe MimeType, Element, B.ByteString)@@ -126,13 +133,14 @@        , stStyleMaps      :: StyleMaps        , stFirstPara      :: Bool        , stTocTitle       :: [Inline]-       , stDynamicParaProps :: [String]-       , stDynamicTextProps :: [String]+       , stDynamicParaProps :: Set.Set String+       , stDynamicTextProps :: Set.Set String        }  defaultWriterState :: WriterState defaultWriterState = WriterState{         stFootnotes      = defaultFootnotes+      , stComments       = []       , stSectionIds     = Set.empty       , stExternalLinks  = M.empty       , stImages         = M.empty@@ -141,12 +149,12 @@       , stDelId          = 1       , stStyleMaps      = defaultStyleMaps       , stFirstPara      = False-      , stTocTitle       = normalizeInlines [Str "Table of Contents"]-      , stDynamicParaProps = []-      , stDynamicTextProps = []+      , stTocTitle       = [Str "Table of Contents"]+      , stDynamicParaProps = Set.empty+      , stDynamicTextProps = Set.empty       } -type WS = ReaderT WriterEnv (StateT WriterState IO)+type WS m = ReaderT WriterEnv (StateT WriterState m)  mknode :: Node t => String -> [(String,String)] -> t -> Element mknode s attrs =@@ -169,16 +177,16 @@ renumIdMap _ [] = M.empty renumIdMap n (e:es)   | Just oldId <- findAttr (QName "Id" Nothing Nothing) e =-      M.insert oldId ("rId" ++ (show n)) (renumIdMap (n+1) es)+      M.insert oldId ("rId" ++ show n) (renumIdMap (n+1) es)   | otherwise = renumIdMap n es  replaceAttr :: (QName -> Bool) -> String -> [XML.Attr] -> [XML.Attr] replaceAttr _ _ [] = [] replaceAttr f val (a:as) | f (attrKey a) =-                             (XML.Attr (attrKey a) val) : (replaceAttr f val as)-                         | otherwise = a : (replaceAttr f val as)+                             XML.Attr (attrKey a) val : replaceAttr f val as+                         | otherwise = a : replaceAttr f val as -renumId :: (QName -> Bool) -> (M.Map String String) -> Element -> Element+renumId :: (QName -> Bool) -> M.Map String String -> Element -> Element renumId f renumMap e   | Just oldId <- findAttrBy f e   , Just newId <- M.lookup oldId renumMap =@@ -187,7 +195,7 @@      e { elAttribs = attrs' }   | otherwise = e -renumIds :: (QName -> Bool) -> (M.Map String String) -> [Element] -> [Element]+renumIds :: (QName -> Bool) -> M.Map String String -> [Element] -> [Element] renumIds f renumMap = map (renumId f renumMap)  -- | Certain characters are invalid in XML even if escaped.@@ -207,37 +215,40 @@   | otherwise                     = False  metaValueToInlines :: MetaValue -> [Inline]-metaValueToInlines (MetaString s) = normalizeInlines [Str s]+metaValueToInlines (MetaString s)    = [Str s] metaValueToInlines (MetaInlines ils) = ils-metaValueToInlines (MetaBlocks bs) = query return bs-metaValueToInlines (MetaBool b) = [Str $ show b]-metaValueToInlines _ = []+metaValueToInlines (MetaBlocks bs)   = query return bs+metaValueToInlines (MetaBool b)      = [Str $ show b]+metaValueToInlines _                 = [] --- | Produce an Docx file from a Pandoc document.-writeDocx :: WriterOptions  -- ^ Writer options+++writeDocx :: (PandocMonad m)+          => WriterOptions  -- ^ Writer options           -> Pandoc         -- ^ Document to convert-          -> IO BL.ByteString+          -> m BL.ByteString writeDocx opts doc@(Pandoc meta _) = do-  let datadir = writerUserDataDir opts-  let doc' = walk fixDisplayMath $ doc-  username <- lookup "USERNAME" <$> getEnvironment-  utctime <- getCurrentTime-  distArchive <- getDefaultReferenceDocx datadir-  refArchive <- case writerReferenceDocx opts of-                     Just f  -> liftM (toArchive . toLazy) $ B.readFile f-                     Nothing -> getDefaultReferenceDocx datadir+  let doc' = walk fixDisplayMath doc+  username <- P.lookupEnv "USERNAME"+  utctime <- P.getCurrentTime+  distArchive <- (toArchive . BL.fromStrict) <$>+                      P.readDefaultDataFile "reference.docx"+  refArchive <- case writerReferenceDoc opts of+                     Just f  -> toArchive <$> P.readFileLazy f+                     Nothing -> (toArchive . BL.fromStrict) <$>+                        P.readDataFile "reference.docx"    parsedDoc <- parseXml refArchive distArchive "word/document.xml"   let wname f qn = qPrefix qn == Just "w" && f (qName qn)   let mbsectpr = filterElementName (wname (=="sectPr")) parsedDoc    -- Gets the template size-  let mbpgsz = mbsectpr >>= (filterElementName (wname (=="pgSz")))-  let mbAttrSzWidth = (elAttribs <$> mbpgsz) >>= (lookupAttrBy ((=="w") . qName))+  let mbpgsz = mbsectpr >>= filterElementName (wname (=="pgSz"))+  let mbAttrSzWidth = (elAttribs <$> mbpgsz) >>= lookupAttrBy ((=="w") . qName) -  let mbpgmar = mbsectpr >>= (filterElementName (wname (=="pgMar")))-  let mbAttrMarLeft = (elAttribs <$> mbpgmar) >>= (lookupAttrBy ((=="left") . qName))-  let mbAttrMarRight = (elAttribs <$> mbpgmar) >>= (lookupAttrBy ((=="right") . qName))+  let mbpgmar = mbsectpr >>= filterElementName (wname (=="pgMar"))+  let mbAttrMarLeft = (elAttribs <$> mbpgmar) >>= lookupAttrBy ((=="left") . qName)+  let mbAttrMarRight = (elAttribs <$> mbpgmar) >>= lookupAttrBy ((=="right") . qName)    -- Get the avaible area (converting the size and the margins to int and   -- doing the difference@@ -248,8 +259,29 @@                        )    -- styles+  mblang <- toLang $ getLang opts meta+  let addLang :: Element -> Element+      addLang e = case mblang >>= \l ->+                         (return . XMLC.toTree . go (renderLang l)+                                 . XMLC.fromElement) e of+                    Just (Elem e') -> e'+                    _              -> e -- return original+        where go :: String -> Cursor -> Cursor+              go l cursor = case XMLC.findRec (isLangElt . current) cursor of+                              Nothing -> cursor+                              Just t  -> XMLC.modifyContent (setval l) t+              setval :: String -> Content -> Content+              setval l (Elem e') = Elem $ e'{ elAttribs = map (setvalattr l) $+                                               elAttribs e' }+              setval _ x         = x+              setvalattr :: String -> XML.Attr -> XML.Attr+              setvalattr l (XML.Attr qn@(QName "val" _ _) _) = XML.Attr qn l+              setvalattr _ x                                 = x+              isLangElt (Elem e') = qName (elName e') == "lang"+              isLangElt _         = False+   let stylepath = "word/styles.xml"-  styledoc <- parseXml refArchive distArchive stylepath+  styledoc <- addLang <$> parseXml refArchive distArchive stylepath    -- parse styledoc for heading styles   let styleMaps = getStyleMaps styledoc@@ -271,15 +303,15 @@           envRTL = isRTLmeta         , envChangesAuthor = fromMaybe "unknown" username         , envChangesDate   = formatTime defaultTimeLocale "%FT%XZ" utctime-        , envPrintWidth = (maybe 420 (\x -> quot x 20) pgContentWidth)+        , envPrintWidth = maybe 420 (\x -> quot x 20) pgContentWidth         }  -  ((contents, footnotes), st) <- runStateT-                                 (runReaderT-                                  (writeOpenXML opts{writerWrapText = WrapNone} doc')-                                  env)-                                 initialSt+  ((contents, footnotes, comments), st) <- runStateT+                         (runReaderT+                          (writeOpenXML opts{writerWrapText = WrapNone} doc')+                          env)+                         initialSt   let epochtime = floor $ utcTimeToPOSIXSeconds utctime   let imgs = M.elems $ stImages st @@ -340,6 +372,8 @@                     "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml")                   ,("/word/document.xml",                     "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml")+                  ,("/word/comments.xml",+                    "application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml")                   ,("/word/footnotes.xml",                     "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml")                   ] ++@@ -386,6 +420,9 @@                     ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes",                       "rId7",                       "footnotes.xml")+                    ,("http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments",+                      "rId8",+                      "comments.xml")                     ]    let idMap = renumIdMap (length baserels' + 1) (headers ++ footers)@@ -409,7 +446,7 @@                                  (elChildren sectpr')                         in                          add_attrs (elAttribs sectpr') $ mknode "w:sectPr" [] cs-        Nothing      -> (mknode "w:sectPr" [] ())+        Nothing      -> mknode "w:sectPr" [] ()    -- let sectpr = fromMaybe (mknode "w:sectPr" [] ()) mbsectpr'   let contents' = contents ++ [sectpr]@@ -431,6 +468,10 @@         $ renderXml $ mknode "Relationships" [("xmlns","http://schemas.openxmlformats.org/package/2006/relationships")]         linkrels +  -- comments+  let commentsEntry = toEntry "word/comments.xml" epochtime+        $ renderXml $ mknode "w:comments" stdAttributes comments+   -- styles    -- We only want to inject paragraph and text properties that@@ -438,26 +479,19 @@   -- are normalized as lowercase.   let newDynamicParaProps = filter         (\sty -> isNothing $ M.lookup (toLower <$> sty) $ getMap $ sParaStyleMap styleMaps)-        (stDynamicParaProps st)+        (Set.toList $ stDynamicParaProps st)        newDynamicTextProps = filter         (\sty -> isNothing $ M.lookup (toLower <$> sty) $ getMap $ sCharStyleMap styleMaps)-        (stDynamicTextProps st)+        (Set.toList $ stDynamicTextProps st)    let newstyles = map newParaPropToOpenXml newDynamicParaProps ++                   map newTextPropToOpenXml newDynamicTextProps ++-                  (styleToOpenXml styleMaps $ writerHighlightStyle opts)-  let styledoc' = styledoc{ elContent = modifyContent (elContent styledoc) }-                  where-                    modifyContent-                      | writerHighlight opts = (++ map Elem newstyles)-                      | otherwise = filter notTokStyle-                    notTokStyle (Elem el) = notStyle el || notTokId el-                    notTokStyle _         = True-                    notStyle = (/= elemName' "style") . elName-                    notTokId = maybe True (`notElem` tokStys) . findAttr (elemName' "styleId")-                    tokStys  = "SourceCode" : map show (enumFromTo KeywordTok NormalTok)-                    elemName' = elemName (sNameSpaces styleMaps) "w"+                  (case writerHighlightStyle opts of+                        Nothing  -> []+                        Just sty -> styleToOpenXml styleMaps sty)+  let styledoc' = styledoc{ elContent = elContent styledoc +++                                           map Elem newstyles }   let styleEntry = toEntry stylepath epochtime $ renderXml styledoc'    -- construct word/numbering.xml@@ -472,6 +506,11 @@                                , qName (elName e) == "abstractNum" ] ++                        [Elem e | e <- allElts                                , qName (elName e) == "num" ] }++  let keywords = case lookupMeta "keywords" meta of+                       Just (MetaList xs) -> map stringify xs+                       _                  -> []+   let docPropsPath = "docProps/core.xml"   let docProps = mknode "cp:coreProperties"           [("xmlns:cp","http://schemas.openxmlformats.org/package/2006/metadata/core-properties")@@ -481,6 +520,7 @@           ,("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance")]           $ mknode "dc:title" [] (stringify $ docTitle meta)           : mknode "dc:creator" [] (intercalate "; " (map stringify $ docAuthors meta))+          : mknode "cp:keywords" [] (intercalate ", " keywords)           : (\x -> [ mknode "dcterms:created" [("xsi:type","dcterms:W3CDTF")] x                    , mknode "dcterms:modified" [("xsi:type","dcterms:W3CDTF")] x                    ]) (formatTime defaultTimeLocale "%FT%XZ" utctime)@@ -509,6 +549,7 @@                      , "w:consecutiveHyphenLimit"                      , "w:hyphenationZone"                      , "w:doNotHyphenateCap"+                     , "w:evenAndOddHeaders"                      ]   settingsEntry <- copyChildren refArchive distArchive settingsPath epochtime settingsList @@ -535,6 +576,7 @@   let archive = foldr addEntryToArchive emptyArchive $                   contentTypesEntry : relsEntry : contentEntry : relEntry :                   footnoteRelEntry : numEntry : styleEntry : footnotesEntry :+                  commentsEntry :                   docPropsEntry : docPropsAppEntry : themeEntry :                   fontTableEntry : settingsEntry : webSettingsEntry :                   imageEntries ++ headerFooterEntries ++@@ -599,11 +641,11 @@                              , mknode "w:link" [("w:val","VerbatimChar")] ()                              , mknode "w:pPr" []                                $ mknode "w:wordWrap" [("w:val","off")] ()-                               : ( maybe [] (\col -> [mknode "w:shd" [("w:val","clear"),("w:fill",drop 1 $ fromColor col)] ()])-                                 $ backgroundColor style )+                               :+                         maybe [] (\col -> [mknode "w:shd" [("w:val","clear"),("w:fill",drop 1 $ fromColor col)] ()]) (backgroundColor style)                              ] -copyChildren :: Archive -> Archive -> String -> Integer -> [String] -> IO Entry+copyChildren :: (PandocMonad m) => Archive -> Archive -> String -> Integer -> [String] -> m Entry copyChildren refArchive distArchive path timestamp elNames = do   ref  <- parseXml refArchive distArchive path   dist <- parseXml distArchive distArchive path@@ -622,11 +664,14 @@ baseListId :: Int baseListId = 1000 -mkNumbering :: [ListMarker] -> IO [Element]+mkNumbering :: (PandocMonad m) => [ListMarker] -> m [Element] mkNumbering lists = do   elts <- mapM mkAbstractNum (ordNub lists)   return $ elts ++ zipWith mkNum lists [baseListId..(baseListId + length lists - 1)] +maxListLevel :: Int+maxListLevel = 8+ mkNum :: ListMarker -> Int -> Element mkNum marker numid =   mknode "w:num" [("w:numId",show numid)]@@ -636,15 +681,18 @@        BulletMarker -> []        NumberMarker _ _ start ->           map (\lvl -> mknode "w:lvlOverride" [("w:ilvl",show (lvl :: Int))]-              $ mknode "w:startOverride" [("w:val",show start)] ()) [0..6]+              $ mknode "w:startOverride" [("w:val",show start)] ())+                [0..maxListLevel] -mkAbstractNum :: ListMarker -> IO Element+mkAbstractNum :: (PandocMonad m) => ListMarker -> m Element mkAbstractNum marker = do-  nsid <- randomRIO (0x10000000 :: Integer, 0xFFFFFFFF :: Integer)+  gen <- P.newStdGen+  let (nsid, _) = randomR (0x10000000 :: Integer, 0xFFFFFFFF :: Integer) gen   return $ mknode "w:abstractNum" [("w:abstractNumId",listMarkerToId marker)]     $ mknode "w:nsid" [("w:val", printf "%8x" nsid)] ()     : mknode "w:multiLevelType" [("w:val","multilevel")] ()-    : map (mkLvl marker) [0..6]+    : map (mkLvl marker)+      [0..maxListLevel]  mkLvl :: ListMarker -> Int -> Element mkLvl marker lvl =@@ -675,33 +723,35 @@           bulletFor 3 = "\x2013"           bulletFor 4 = "\x2022"           bulletFor 5 = "\x2013"-          bulletFor _ = "\x2022"-          styleFor UpperAlpha _ = "upperLetter"-          styleFor LowerAlpha _ = "lowerLetter"-          styleFor UpperRoman _ = "upperRoman"-          styleFor LowerRoman _ = "lowerRoman"-          styleFor Decimal _ = "decimal"+          bulletFor x = bulletFor (x `mod` 6)+          styleFor UpperAlpha _   = "upperLetter"+          styleFor LowerAlpha _   = "lowerLetter"+          styleFor UpperRoman _   = "upperRoman"+          styleFor LowerRoman _   = "lowerRoman"+          styleFor Decimal _      = "decimal"           styleFor DefaultStyle 1 = "decimal"           styleFor DefaultStyle 2 = "lowerLetter"           styleFor DefaultStyle 3 = "lowerRoman"           styleFor DefaultStyle 4 = "decimal"           styleFor DefaultStyle 5 = "lowerLetter"-          styleFor DefaultStyle 6 = "lowerRoman"-          styleFor _ _ = "decimal"-          patternFor OneParen s = s ++ ")"+          styleFor DefaultStyle 0 = "lowerRoman"+          styleFor DefaultStyle x = styleFor DefaultStyle (x `mod` 6)+          styleFor _ _            = "decimal"+          patternFor OneParen s  = s ++ ")"           patternFor TwoParens s = "(" ++ s ++ ")"-          patternFor _ s = s ++ "."+          patternFor _ s         = s ++ "." -getNumId :: WS Int+getNumId :: (PandocMonad m) => WS m Int getNumId = (((baseListId - 1) +) . length) `fmap` gets stLists -makeTOC :: WriterOptions -> WS [Element]++makeTOC :: (PandocMonad m) => WriterOptions -> WS m [Element] makeTOC opts | writerTableOfContents opts = do-  let depth = "1-"++(show (writerTOCDepth opts))+  let depth = "1-"++show (writerTOCDepth opts)   let tocCmd = "TOC \\o \""++depth++"\" \\h \\z \\u"   tocTitle <- gets stTocTitle   title <- withParaPropM (pStyleM "TOC Heading") (blocksToOpenXML opts [Para tocTitle])-  return $+  return     [mknode "w:sdt" [] ([       mknode "w:sdtPr" [] (         mknode "w:docPartObj" [] (@@ -725,7 +775,7 @@  -- | Convert Pandoc document to two lists of -- OpenXML elements (the main document and footnotes).-writeOpenXML :: WriterOptions -> Pandoc -> WS ([Element], [Element])+writeOpenXML :: (PandocMonad m) => WriterOptions -> Pandoc -> WS m ([Element], [Element],[Element]) writeOpenXML opts (Pandoc meta blocks) = do   let tit = docTitle meta ++ case lookupMeta "subtitle" meta of                                   Just (MetaBlocks [Plain xs]) -> LineBreak : xs@@ -733,14 +783,14 @@   let auths = docAuthors meta   let dat = docDate meta   let abstract' = case lookupMeta "abstract" meta of-                       Just (MetaBlocks bs) -> bs+                       Just (MetaBlocks bs)   -> bs                        Just (MetaInlines ils) -> [Plain ils]-                       _ -> []+                       _                      -> []   let subtitle' = case lookupMeta "subtitle" meta of                        Just (MetaBlocks [Plain xs]) -> xs                        Just (MetaBlocks [Para  xs]) -> xs                        Just (MetaInlines xs)        -> xs-                       _ -> []+                       _                            -> []   title <- withParaPropM (pStyleM "Title") $ blocksToOpenXML opts [Para tit | not (null tit)]   subtitle <- withParaPropM (pStyleM "Subtitle") $ blocksToOpenXML opts [Para subtitle' | not (null subtitle')]   authors <- withParaProp (pCustomStyle "Author") $ blocksToOpenXML opts $@@ -750,23 +800,40 @@                  then return []                  else withParaProp (pCustomStyle "Abstract") $ blocksToOpenXML opts abstract'   let convertSpace (Str x : Space : Str y : xs) = Str (x ++ " " ++ y) : xs-      convertSpace (Str x : Str y : xs) = Str (x ++ y) : xs-      convertSpace xs = xs+      convertSpace (Str x : Str y : xs)         = Str (x ++ y) : xs+      convertSpace xs                           = xs   let blocks' = bottomUp convertSpace blocks-  doc' <- (setFirstPara >> blocksToOpenXML opts blocks')-  notes' <- reverse `fmap` gets stFootnotes+  doc' <- setFirstPara >> blocksToOpenXML opts blocks'+  notes' <- reverse <$> gets stFootnotes+  comments <- reverse <$> gets stComments+  let toComment (kvs, ils) = do+        annotation <- inlinesToOpenXML opts ils+        return $+          mknode "w:comment" [('w':':':k,v) | (k,v) <- kvs]+            [ mknode "w:p" [] $+              [ mknode "w:pPr" []+                [ mknode "w:pStyle" [("w:val", "CommentText")] () ]+              , mknode "w:r" []+                [ mknode "w:rPr" []+                  [ mknode "w:rStyle" [("w:val", "CommentReference")] ()+                  , mknode "w:annotationRef" [] ()+                  ]+                ]+              ] ++ annotation+            ]+  comments' <- mapM toComment comments   toc <- makeTOC opts   let meta' = title ++ subtitle ++ authors ++ date ++ abstract ++ toc-  return (meta' ++ doc', notes')+  return (meta' ++ doc', notes', comments')  -- | Convert a list of Pandoc blocks to OpenXML.-blocksToOpenXML :: WriterOptions -> [Block] -> WS [Element]+blocksToOpenXML :: (PandocMonad m) => WriterOptions -> [Block] -> WS m [Element] blocksToOpenXML opts bls = concat `fmap` mapM (blockToOpenXML opts) bls  pCustomStyle :: String -> Element pCustomStyle sty = mknode "w:pStyle" [("w:val",sty)] () -pStyleM :: String -> WS XML.Element+pStyleM :: (PandocMonad m) => String -> WS m XML.Element pStyleM styleName = do   styleMaps <- gets stStyleMaps   let sty' = getStyleId styleName $ sParaStyleMap styleMaps@@ -775,61 +842,72 @@ rCustomStyle :: String -> Element rCustomStyle sty = mknode "w:rStyle" [("w:val",sty)] () -rStyleM :: String -> WS XML.Element+rStyleM :: (PandocMonad m) => String -> WS m XML.Element rStyleM styleName = do   styleMaps <- gets stStyleMaps   let sty' = getStyleId styleName $ sCharStyleMap styleMaps   return $ mknode "w:rStyle" [("w:val",sty')] () -getUniqueId :: MonadIO m => m String+getUniqueId :: (PandocMonad m) => m String -- the + 20 is to ensure that there are no clashes with the rIds -- already in word/document.xml.rel-getUniqueId = liftIO $ (show . (+ 20) . hashUnique) `fmap` newUnique+getUniqueId = (show . (+ 20)) <$> P.newUniqueHash  -- | Key for specifying user-defined docx styles. dynamicStyleKey :: String dynamicStyleKey = "custom-style"  -- | Convert a Pandoc block element to OpenXML.-blockToOpenXML :: WriterOptions -> Block -> WS [Element]+blockToOpenXML :: (PandocMonad m) => WriterOptions -> Block -> WS m [Element] blockToOpenXML opts blk = withDirection $ blockToOpenXML' opts blk -blockToOpenXML' :: WriterOptions -> Block -> WS [Element]+blockToOpenXML' :: (PandocMonad m) => WriterOptions -> Block -> WS m [Element] blockToOpenXML' _ Null = return []-blockToOpenXML' opts (Div (ident,classes,kvs) bs)-  | Just sty <- lookup dynamicStyleKey kvs = do-      modify $ \s -> s{stDynamicParaProps = sty : (stDynamicParaProps s)}-      withParaPropM (pStyleM sty) $ blocksToOpenXML opts bs-  | Just "rtl" <- lookup "dir" kvs = do-      let kvs' = filter (("dir", "rtl")/=) kvs-      local (\env -> env { envRTL = True }) $-        blockToOpenXML opts (Div (ident,classes,kvs') bs)-  | Just "ltr" <- lookup "dir" kvs = do-      let kvs' = filter (("dir", "ltr")/=) kvs-      local (\env -> env { envRTL = False }) $-        blockToOpenXML opts (Div (ident,classes,kvs') bs)-blockToOpenXML' opts (Div (_,["references"],_) bs) = do-  let (hs, bs') = span isHeaderBlock bs-  header <- blocksToOpenXML opts hs-  -- We put the Bibliography style on paragraphs after the header-  rest <- withParaPropM (pStyleM "Bibliography") $ blocksToOpenXML opts bs'-  return (header ++ rest)-blockToOpenXML' opts (Div _ bs) = blocksToOpenXML opts bs+blockToOpenXML' opts (Div (ident,classes,kvs) bs) = do+  stylemod <- case lookup dynamicStyleKey kvs of+                   Just sty -> do+                      modify $ \s ->+                        s{stDynamicParaProps = Set.insert sty+                             (stDynamicParaProps s)}+                      return $ withParaPropM (pStyleM sty)+                   _ -> return id+  dirmod <- case lookup "dir" kvs of+                 Just "rtl" -> return $ local (\env -> env { envRTL = True })+                 Just "ltr" -> return $ local (\env -> env { envRTL = False })+                 _ -> return id+  let (hs, bs') = if "references" `elem` classes+                     then span isHeaderBlock bs+                     else ([], bs)+  let bibmod = if "references" `elem` classes+                  then withParaPropM (pStyleM "Bibliography")+                  else id+  header <- dirmod $ stylemod $ blocksToOpenXML opts hs+  contents <- dirmod $ bibmod $ stylemod $ blocksToOpenXML opts bs'+  if null ident+     then return $ header ++ contents+     else do+       id' <- getUniqueId+       let bookmarkStart = mknode "w:bookmarkStart" [("w:id", id')+                                                    ,("w:name",ident)] ()+       let bookmarkEnd = mknode "w:bookmarkEnd" [("w:id", id')] ()+       return $ bookmarkStart : header ++ contents ++ [bookmarkEnd] blockToOpenXML' opts (Header lev (ident,_,_) lst) = do   setFirstPara   paraProps <- withParaPropM (pStyleM ("Heading "++show lev)) $                     getParaProps False   contents <- inlinesToOpenXML opts lst-  usedIdents <- gets stSectionIds-  let bookmarkName = if null ident-                        then uniqueIdent lst usedIdents-                        else ident-  modify $ \s -> s{ stSectionIds = Set.insert bookmarkName $ stSectionIds s }-  id' <- getUniqueId-  let bookmarkStart = mknode "w:bookmarkStart" [("w:id", id')+  if null ident+     then return [mknode "w:p" [] (paraProps ++contents)]+     else do+       let bookmarkName = ident+       modify $ \s -> s{ stSectionIds = Set.insert bookmarkName+                                      $ stSectionIds s }+       id' <- getUniqueId+       let bookmarkStart = mknode "w:bookmarkStart" [("w:id", id')                                                ,("w:name",bookmarkName)] ()-  let bookmarkEnd = mknode "w:bookmarkEnd" [("w:id", id')] ()-  return [mknode "w:p" [] (paraProps ++ [bookmarkStart, bookmarkEnd] ++ contents)]+       let bookmarkEnd = mknode "w:bookmarkEnd" [("w:id", id')] ()+       return [mknode "w:p" [] (paraProps +++               [bookmarkStart] ++ contents ++ [bookmarkEnd])] blockToOpenXML' opts (Plain lst) = withParaProp (pCustomStyle "Compact")   $ blockToOpenXML opts (Para lst) -- title beginning with fig: indicates that the image is a figure@@ -838,7 +916,7 @@   let prop = pCustomStyle $         if null alt         then "Figure"-        else "FigureWithCaption"+        else "CaptionedFigure"   paraProps <- local (\env -> env { envParaProperties = prop : envParaProperties env }) (getParaProps False)   contents <- inlinesToOpenXML opts [Image attr alt (src,tit)]   captionNode <- withParaProp (pCustomStyle "ImageCaption")@@ -860,9 +938,11 @@   contents <- inlinesToOpenXML opts lst   return [mknode "w:p" [] (paraProps' ++ contents)] blockToOpenXML' opts (LineBlock lns) = blockToOpenXML opts $ linesToPara lns-blockToOpenXML' _ (RawBlock format str)+blockToOpenXML' _ b@(RawBlock format str)   | format == Format "openxml" = return [ x | Elem x <- parseXML str ]-  | otherwise                  = return []+  | otherwise                  = do+      report $ BlockNotRendered b+      return [] blockToOpenXML' opts (BlockQuote blocks) = do   p <- withParaPropM (pStyleM "Block Text") $ blocksToOpenXML opts blocks   setFirstPara@@ -914,7 +994,7 @@     caption' ++     [mknode "w:tbl" []       ( mknode "w:tblPr" []-        (   mknode "w:tblStyle" [("w:val","TableNormal")] () :+        (   mknode "w:tblStyle" [("w:val","Table")] () :             mknode "w:tblW" [("w:type", "pct"), ("w:w", show rowwidth)] () :             mknode "w:tblLook" [("w:firstRow","1") | hasHeader ] () :           [ mknode "w:tblCaption" [("w:val", captionStr)] ()@@ -945,7 +1025,7 @@   setFirstPara   return l -definitionListItemToOpenXML  :: WriterOptions -> ([Inline],[[Block]]) -> WS [Element]+definitionListItemToOpenXML  :: (PandocMonad m) => WriterOptions -> ([Inline],[[Block]]) -> WS m [Element] definitionListItemToOpenXML opts (term,defs) = do   term' <- withParaProp (pCustomStyle "DefinitionTerm")            $ blockToOpenXML opts (Para term)@@ -953,12 +1033,12 @@            $ concat `fmap` mapM (blocksToOpenXML opts) defs   return $ term' ++ defs' -addList :: ListMarker -> WS ()+addList :: (PandocMonad m) => ListMarker -> WS m () addList marker = do   lists <- gets stLists   modify $ \st -> st{ stLists = lists ++ [marker] } -listItemToOpenXML :: WriterOptions -> Int -> [Block] -> WS [Element]+listItemToOpenXML :: (PandocMonad m) => WriterOptions -> Int -> [Block] -> WS m [Element] listItemToOpenXML _ _ []                   = return [] listItemToOpenXML opts numid (first:rest) = do   first' <- withNumId numid $ blockToOpenXML opts first@@ -968,36 +1048,36 @@  alignmentToString :: Alignment -> [Char] alignmentToString alignment = case alignment of-                                 AlignLeft -> "left"-                                 AlignRight -> "right"-                                 AlignCenter -> "center"+                                 AlignLeft    -> "left"+                                 AlignRight   -> "right"+                                 AlignCenter  -> "center"                                  AlignDefault -> "left"  -- | Convert a list of inline elements to OpenXML.-inlinesToOpenXML :: WriterOptions -> [Inline] -> WS [Element]+inlinesToOpenXML :: (PandocMonad m) => WriterOptions -> [Inline] -> WS m [Element] inlinesToOpenXML opts lst = concat `fmap` mapM (inlineToOpenXML opts) lst -withNumId :: Int -> WS a -> WS a+withNumId :: (PandocMonad m) => Int -> WS m a -> WS m a withNumId numid = local $ \env -> env{ envListNumId = numid } -asList :: WS a -> WS a+asList :: (PandocMonad m) => WS m a -> WS m a asList = local $ \env -> env{ envListLevel = envListLevel env + 1 } -getTextProps :: WS [Element]+getTextProps :: (PandocMonad m) => WS m [Element] getTextProps = do   props <- asks envTextProperties   return $ if null props               then []               else [mknode "w:rPr" [] props] -withTextProp :: Element -> WS a -> WS a+withTextProp :: PandocMonad m => Element -> WS m a -> WS m a withTextProp d p =   local (\env -> env {envTextProperties = d : envTextProperties env}) p -withTextPropM :: WS Element -> WS a -> WS a+withTextPropM :: PandocMonad m => WS m Element -> WS m a -> WS m a withTextPropM = (. flip withTextProp) . (>>=) -getParaProps :: Bool -> WS [Element]+getParaProps :: PandocMonad m => Bool -> WS m [Element] getParaProps displayMathPara = do   props <- asks envParaProperties   listLevel <- asks envListLevel@@ -1012,77 +1092,113 @@                 [] -> []                 ps -> [mknode "w:pPr" [] ps] -withParaProp :: Element -> WS a -> WS a+withParaProp :: PandocMonad m => Element -> WS m a -> WS m a withParaProp d p =   local (\env -> env {envParaProperties = d : envParaProperties env}) p -withParaPropM :: WS Element -> WS a -> WS a+withParaPropM :: PandocMonad m => WS m Element -> WS m a -> WS m a withParaPropM = (. flip withParaProp) . (>>=) -formattedString :: String -> WS [Element]-formattedString str = do-  props <- getTextProps+formattedString :: PandocMonad m => String -> WS m [Element]+formattedString str =+  -- properly handle soft hyphens+  case splitBy (=='\173') str of+      [w] -> formattedString' w+      ws  -> do+         sh <- formattedRun [mknode "w:softHyphen" [] ()]+         intercalate sh <$> mapM formattedString' ws++formattedString' :: PandocMonad m => String -> WS m [Element]+formattedString' str = do   inDel <- asks envInDel-  return [ mknode "w:r" [] $-             props ++-             [ mknode (if inDel then "w:delText" else "w:t")-               [("xml:space","preserve")] (stripInvalidChars str) ] ]+  formattedRun [ mknode (if inDel then "w:delText" else "w:t")+                 [("xml:space","preserve")] (stripInvalidChars str) ] -setFirstPara :: WS ()+formattedRun :: PandocMonad m => [Element] -> WS m [Element]+formattedRun els = do+  props <- getTextProps+  return [ mknode "w:r" [] $ props ++ els ]++setFirstPara :: PandocMonad m => WS m () setFirstPara =  modify $ \s -> s { stFirstPara = True }  -- | Convert an inline element to OpenXML.-inlineToOpenXML :: WriterOptions -> Inline -> WS [Element]+inlineToOpenXML :: PandocMonad m => WriterOptions -> Inline -> WS m [Element] inlineToOpenXML opts il = withDirection $ inlineToOpenXML' opts il -inlineToOpenXML' :: WriterOptions -> Inline -> WS [Element]-inlineToOpenXML' _ (Str str) = formattedString str+inlineToOpenXML' :: PandocMonad m => WriterOptions -> Inline -> WS m [Element]+inlineToOpenXML' _ (Str str) =+  formattedString str inlineToOpenXML' opts Space = inlineToOpenXML opts (Str " ") inlineToOpenXML' opts SoftBreak = inlineToOpenXML opts (Str " ")-inlineToOpenXML' opts (Span (ident,classes,kvs) ils)-  | Just sty <- lookup dynamicStyleKey kvs = do-      let kvs' = filter ((dynamicStyleKey, sty)/=) kvs-      modify $ \s -> s{stDynamicTextProps = sty : (stDynamicTextProps s)}-      withTextProp (rCustomStyle sty) $-        inlineToOpenXML opts (Span (ident,classes,kvs') ils)-  | Just "rtl" <- lookup "dir" kvs = do-      let kvs' = filter (("dir", "rtl")/=) kvs-      local (\env -> env { envRTL = True }) $-        inlineToOpenXML opts (Span (ident,classes,kvs') ils)-  | Just "ltr" <- lookup "dir" kvs = do-      let kvs' = filter (("dir", "ltr")/=) kvs-      local (\env -> env { envRTL = False }) $-        inlineToOpenXML opts (Span (ident,classes,kvs') ils)-  | "insertion" `elem` classes = do-    defaultAuthor <- asks envChangesAuthor-    defaultDate <- asks envChangesDate-    let author = fromMaybe defaultAuthor (lookup "author" kvs)-        date   = fromMaybe defaultDate (lookup "date" kvs)-    insId <- gets stInsId-    modify $ \s -> s{stInsId = (insId + 1)}-    x <- inlinesToOpenXML opts ils-    return [ mknode "w:ins" [("w:id", (show insId)),-                             ("w:author", author),-                             ("w:date", date)]-             x ]-  | "deletion" `elem` classes = do-    defaultAuthor <- asks envChangesAuthor-    defaultDate <- asks envChangesDate-    let author = fromMaybe defaultAuthor (lookup "author" kvs)-        date   = fromMaybe defaultDate (lookup "date" kvs)-    delId <- gets stDelId-    modify $ \s -> s{stDelId = (delId + 1)}-    x <- local (\env -> env {envInDel = True}) (inlinesToOpenXML opts ils)-    return [ mknode "w:del" [("w:id", (show delId)),-                             ("w:author", author),-                             ("w:date", date)]-             x ]-  | otherwise = do-    let off x = withTextProp (mknode x [("w:val","0")] ())-    ((if "csl-no-emph" `elem` classes then off "w:i" else id) .-     (if "csl-no-strong" `elem` classes then off "w:b" else id) .-     (if "csl-no-smallcaps" `elem` classes then off "w:smallCaps" else id))-      $ inlinesToOpenXML opts ils+inlineToOpenXML' _ (Span (ident,["comment-start"],kvs) ils) = do+  modify $ \st -> st{ stComments = (("id",ident):kvs, ils) : stComments st }+  return [ mknode "w:commentRangeStart" [("w:id", ident)] () ]+inlineToOpenXML' _ (Span (ident,["comment-end"],_) _) =+  return [ mknode "w:commentRangeEnd" [("w:id", ident)] ()+       , mknode "w:r" []+         [ mknode "w:rPr" []+           [ mknode "w:rStyle" [("w:val", "CommentReference")] () ]+         , mknode "w:commentReference" [("w:id", ident)] () ]+       ]+inlineToOpenXML' opts (Span (ident,classes,kvs) ils) = do+  stylemod <- case lookup dynamicStyleKey kvs of+                   Just sty -> do+                      modify $ \s ->+                        s{stDynamicTextProps = Set.insert sty+                              (stDynamicTextProps s)}+                      return $ withTextProp (rCustomStyle sty)+                   _ -> return id+  let dirmod = case lookup "dir" kvs of+                 Just "rtl" -> local (\env -> env { envRTL = True })+                 Just "ltr" -> local (\env -> env { envRTL = False })+                 _          -> id+  let off x = withTextProp (mknode x [("w:val","0")] ())+  let pmod =  (if "csl-no-emph" `elem` classes then off "w:i" else id) .+              (if "csl-no-strong" `elem` classes then off "w:b" else id) .+              (if "csl-no-smallcaps" `elem` classes+                  then off "w:smallCaps"+                  else id)+  insmod <- if "insertion" `elem` classes+               then do+                 defaultAuthor <- asks envChangesAuthor+                 defaultDate <- asks envChangesDate+                 let author = fromMaybe defaultAuthor (lookup "author" kvs)+                     date   = fromMaybe defaultDate (lookup "date" kvs)+                 insId <- gets stInsId+                 modify $ \s -> s{stInsId = insId + 1}+                 return $ \f -> do+                   x <- f+                   return [ mknode "w:ins"+                              [("w:id", (show insId)),+                              ("w:author", author),+                              ("w:date", date)] x ]+               else return id+  delmod <- if "insertion" `elem` classes+               then do+                 defaultAuthor <- asks envChangesAuthor+                 defaultDate <- asks envChangesDate+                 let author = fromMaybe defaultAuthor (lookup "author" kvs)+                     date   = fromMaybe defaultDate (lookup "date" kvs)+                 insId <- gets stInsId+                 modify $ \s -> s{stInsId = insId + 1}+                 return $ \f -> do+                   x <- f+                   return [mknode "w:ins"+                           [("w:id", show insId),+                           ("w:author", author),+                           ("w:date", date)] x]+               else return id+  contents <- insmod $ delmod $ dirmod $ stylemod $ pmod+                     $ inlinesToOpenXML opts ils+  if null ident+     then return contents+     else do+       id' <- getUniqueId+       let bookmarkStart = mknode "w:bookmarkStart" [("w:id", id')+                                                    ,("w:name",ident)] ()+       let bookmarkEnd = mknode "w:bookmarkEnd" [("w:id", id')] ()+       return $ bookmarkStart : contents ++ [bookmarkEnd] inlineToOpenXML' opts (Strong lst) =   withTextProp (mknode "w:b" [] ()) $ inlinesToOpenXML opts lst inlineToOpenXML' opts (Emph lst) =@@ -1100,43 +1216,43 @@   withTextProp (mknode "w:strike" [] ())   $ inlinesToOpenXML opts lst inlineToOpenXML' _ LineBreak = return [br]-inlineToOpenXML' _ (RawInline f str)+inlineToOpenXML' _ il@(RawInline f str)   | f == Format "openxml" = return [ x | Elem x <- parseXML str ]-  | otherwise            = return []+  | otherwise             = do+      report $ InlineNotRendered il+      return [] inlineToOpenXML' opts (Quoted quoteType lst) =   inlinesToOpenXML opts $ [Str open] ++ lst ++ [Str close]     where (open, close) = case quoteType of                             SingleQuote -> ("\x2018", "\x2019")                             DoubleQuote -> ("\x201C", "\x201D") inlineToOpenXML' opts (Math mathType str) = do-  let displayType = if mathType == DisplayMath-                       then DisplayBlock-                       else DisplayInline-  when (displayType == DisplayBlock) setFirstPara-  case writeOMML displayType <$> readTeX str of-        Right r -> return [r]-        Left  e -> do-          warn $ "Cannot convert the following TeX math, skipping:\n" ++ str ++-                 "\n" ++ e-          inlinesToOpenXML opts (texMathToInlines mathType str)+  when (mathType == DisplayMath) setFirstPara+  res <- (lift . lift) (convertMath writeOMML mathType str)+  case res of+       Right r -> return [r]+       Left il -> inlineToOpenXML' opts il inlineToOpenXML' opts (Cite _ lst) = inlinesToOpenXML opts lst inlineToOpenXML' opts (Code attrs str) = do   let unhighlighted = intercalate [br] `fmap`-                       (mapM formattedString $ lines str)+                       mapM formattedString (lines str)       formatOpenXML _fmtOpts = intercalate [br] . map (map toHlTok)       toHlTok (toktype,tok) = mknode "w:r" []                                [ mknode "w:rPr" []                                  [ rCustomStyle (show toktype) ]                                , mknode "w:t" [("xml:space","preserve")] (T.unpack tok) ]   withTextProp (rCustomStyle "VerbatimChar")-    $ if writerHighlight opts-         then case highlight formatOpenXML attrs str of-               Nothing  -> unhighlighted-               Just h   -> return h-         else unhighlighted+    $ if isNothing (writerHighlightStyle opts)+          then unhighlighted+          else case highlight (writerSyntaxMap opts)+                      formatOpenXML attrs str of+                    Right h  -> return h+                    Left msg -> do+                      unless (null msg) $ report $ CouldNotHighlight msg+                      unhighlighted inlineToOpenXML' opts (Note bs) = do   notes <- gets stFootnotes-  notenum <- getUniqueId+  notenum <- (lift . lift) getUniqueId   footnoteStyle <- rStyleM "Footnote Reference"   let notemarker = mknode "w:r" []                    [ mknode "w:rPr" [] footnoteStyle@@ -1151,7 +1267,7 @@                                 , envTextProperties = [] })               (withParaPropM (pStyleM "Footnote Text") $ blocksToOpenXML opts                 $ insertNoteRef bs)-  let newnote = mknode "w:footnote" [("w:id", notenum)] $ contents+  let newnote = mknode "w:footnote" [("w:id", notenum)] contents   modify $ \s -> s{ stFootnotes = newnote : notes }   return [ mknode "w:r" []            [ mknode "w:rPr" [] footnoteStyle@@ -1167,7 +1283,7 @@   id' <- case M.lookup src extlinks of             Just i   -> return i             Nothing  -> do-              i <- ("rId"++) `fmap` getUniqueId+              i <- ("rId"++) `fmap` (lift . lift) getUniqueId               modify $ \st -> st{ stExternalLinks =                         M.insert src i extlinks }               return i@@ -1178,32 +1294,30 @@   imgs <- gets stImages   case M.lookup src imgs of     Just (_,_,_,elt,_) -> return [elt]-    Nothing -> do-      res <- liftIO $-               fetchItem' (writerMediaBag opts) (writerSourceURL opts) src-      case res of-        Left (_ :: E.SomeException) -> do-          warn $ "Could not find image `" ++ src ++ "', skipping..."-          -- emit alt text-          inlinesToOpenXML opts alt-        Right (img, mt) -> do-          ident <- ("rId"++) `fmap` getUniqueId+    Nothing ->+      catchError+      (do (img, mt) <- P.fetchItem src+          ident <- ("rId"++) `fmap` ((lift . lift) getUniqueId)           let (xpt,ypt) = desiredSizeInPoints opts attr-                 (either (const def) id (imageSize img))+                 (either (const def) id (imageSize opts img))           -- 12700 emu = 1 pt-          let (xemu,yemu) = fitToPage (xpt * 12700, ypt * 12700) (pageWidth * 12700)+          let (xemu,yemu) = fitToPage (xpt * 12700, ypt * 12700)+                                  (pageWidth * 12700)           let cNvPicPr = mknode "pic:cNvPicPr" [] $-                           mknode "a:picLocks" [("noChangeArrowheads","1"),("noChangeAspect","1")] ()+                           mknode "a:picLocks" [("noChangeArrowheads","1")+                                               ,("noChangeAspect","1")] ()           let nvPicPr  = mknode "pic:nvPicPr" []                           [ mknode "pic:cNvPr"                               [("descr",src),("id","0"),("name","Picture")] ()                           , cNvPicPr ]           let blipFill = mknode "pic:blipFill" []                            [ mknode "a:blip" [("r:embed",ident)] ()-                           , mknode "a:stretch" [] $ mknode "a:fillRect" [] () ]+                           , mknode "a:stretch" [] $+                             mknode "a:fillRect" [] () ]           let xfrm =    mknode "a:xfrm" []                           [ mknode "a:off" [("x","0"),("y","0")] ()-                          , mknode "a:ext" [("cx",show xemu),("cy",show yemu)] () ]+                          , mknode "a:ext" [("cx",show xemu)+                                           ,("cy",show yemu)] () ]           let prstGeom = mknode "a:prstGeom" [("prst","rect")] $                            mknode "a:avLst" [] ()           let ln =      mknode "a:ln" [("w","9525")]@@ -1213,7 +1327,8 @@           let spPr =    mknode "pic:spPr" [("bwMode","auto")]                           [xfrm, prstGeom, mknode "a:noFill" [] (), ln]           let graphic = mknode "a:graphic" [] $-                          mknode "a:graphicData" [("uri","http://schemas.openxmlformats.org/drawingml/2006/picture")]+                          mknode "a:graphicData"+                            [("uri","http://schemas.openxmlformats.org/drawingml/2006/picture")]                             [ mknode "pic:pic" []                               [ nvPicPr                               , blipFill@@ -1222,8 +1337,12 @@                mknode "w:drawing" [] $                  mknode "wp:inline" []                   [ mknode "wp:extent" [("cx",show xemu),("cy",show yemu)] ()-                  , mknode "wp:effectExtent" [("b","0"),("l","0"),("r","0"),("t","0")] ()-                  , mknode "wp:docPr" [("descr",stringify alt), ("title", title), ("id","1"),("name","Picture")] ()+                  , mknode "wp:effectExtent"+                       [("b","0"),("l","0"),("r","0"),("t","0")] ()+                  , mknode "wp:docPr" [("descr",stringify alt)+                                      ,("title", title)+                                      ,("id","1")+                                      ,("name","Picture")] ()                   , graphic ]           let imgext = case mt >>= extensionFromMimeType of                             Just x    -> '.':x@@ -1233,6 +1352,7 @@                                               Just Gif  -> ".gif"                                               Just Pdf  -> ".pdf"                                               Just Eps  -> ".eps"+                                              Just Svg  -> ".svg"                                               Nothing   -> ""           if null imgext              then -- without an extension there is no rule for content type@@ -1244,28 +1364,35 @@                modify $ \st -> st{ stImages =                    M.insert src (ident, imgpath, mbMimeType, imgElt, img)                            $ stImages st }-               return [imgElt]+               return [imgElt])+      (\e -> do+         report $ CouldNotFetchResource src (show e)+         -- emit alt text+         inlinesToOpenXML opts alt)  br :: Element-br = mknode "w:r" [] [mknode "w:br" [("w:type","textWrapping")] () ]+br = breakElement "textWrapping" +breakElement :: String -> Element+breakElement kind = mknode "w:r" [] [mknode "w:br" [("w:type",kind)] () ]+ -- Word will insert these footnotes into the settings.xml file -- (whether or not they're visible in the document). If they're in the -- file, but not in the footnotes.xml file, it will produce -- problems. So we want to make sure we insert them into our document. defaultFootnotes :: [Element] defaultFootnotes = [ mknode "w:footnote"-                     [("w:type", "separator"), ("w:id", "-1")] $+                     [("w:type", "separator"), ("w:id", "-1")]                      [ mknode "w:p" [] $                        [mknode "w:r" [] $                         [ mknode "w:separator" [] ()]]]                    , mknode "w:footnote"-                     [("w:type", "continuationSeparator"), ("w:id", "0")] $+                     [("w:type", "continuationSeparator"), ("w:id", "0")]                      [ mknode "w:p" [] $                        [ mknode "w:r" [] $                          [ mknode "w:continuationSeparator" [] ()]]]] -parseXml :: Archive -> Archive -> String -> IO Element+parseXml :: (PandocMonad m) => Archive -> Archive -> String -> m Element parseXml refArchive distArchive relpath =   case findEntryByPath relpath refArchive `mplus`          findEntryByPath relpath distArchive of@@ -1280,10 +1407,10 @@ fitToPage (x, y) pageWidth   -- Fixes width to the page width and scales the height   | x > fromIntegral pageWidth =-    (pageWidth, floor $ ((fromIntegral pageWidth) / x) * y)+    (pageWidth, floor $ (fromIntegral pageWidth / x) * y)   | otherwise = (floor x, floor y) -withDirection :: WS a -> WS a+withDirection :: PandocMonad m => WS m a -> WS m a withDirection x = do   isRTL <- asks envRTL   paraProps <- asks envParaProperties@@ -1296,8 +1423,8 @@   if isRTL     -- if we are going right-to-left, we (re?)add the properties.     then flip local x $-         \env -> env { envParaProperties = (mknode "w:bidi" [] ()) : paraProps'-                     , envTextProperties = (mknode "w:rtl" [] ()) : textProps'+         \env -> env { envParaProperties = mknode "w:bidi" [] () : paraProps'+                     , envTextProperties = mknode "w:rtl" [] () : textProps'                      }     else flip local x $ \env -> env { envParaProperties = paraProps'                                     , envTextProperties = textProps'
src/Text/Pandoc/Writers/DokuWiki.hs view
@@ -1,5 +1,5 @@ {--Copyright (C) 2008-2015 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2008-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -18,7 +18,7 @@  {- |    Module      : Text.Pandoc.Writers.DokuWiki-   Copyright   : Copyright (C) 2008-2015 John MacFarlane+   Copyright   : Copyright (C) 2008-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : Clare Macrae <clare.macrae@googlemail.com>@@ -39,71 +39,64 @@ -}  module Text.Pandoc.Writers.DokuWiki ( writeDokuWiki ) where+import Control.Monad (zipWithM)+import Control.Monad.Reader (ReaderT, ask, local, runReaderT)+import Control.Monad.State.Strict (StateT, evalStateT)+import Data.Default (Default (..))+import Data.List (intercalate, intersect, isPrefixOf, transpose)+import Data.Text (Text, pack)+import Text.Pandoc.Class (PandocMonad, report) import Text.Pandoc.Definition-import Text.Pandoc.Options ( WriterOptions(-                                writerTableOfContents-                              , writerTemplate-                              , writerWrapText), WrapOption(..) )-import Text.Pandoc.Shared ( escapeURI, linesToPara, removeFormatting-                          , camelCaseToHyphenated, trimr, normalize, substitute )-import Text.Pandoc.Writers.Shared ( defField, metaToJSON ) import Text.Pandoc.ImageSize-import Text.Pandoc.Templates ( renderTemplate' )-import Data.List ( intersect, intercalate, isPrefixOf, transpose )-import Data.Default (Default(..))-import Network.URI ( isURI )-import Control.Monad ( zipWithM )-import Control.Monad.State ( modify, State, get, evalState )-import Control.Monad.Reader ( ReaderT, runReaderT, ask, local )+import Text.Pandoc.Logging+import Text.Pandoc.Options (WrapOption (..), WriterOptions (writerTableOfContents, writerTemplate, writerWrapText))+import Text.Pandoc.Shared (camelCaseToHyphenated, escapeURI, isURI, linesToPara,+                           removeFormatting, substitute, trimr)+import Text.Pandoc.Templates (renderTemplate')+import Text.Pandoc.Writers.Shared (defField, metaToJSON)  data WriterState = WriterState {-    stNotes     :: Bool            -- True if there are notes   }  data WriterEnvironment = WriterEnvironment {-    stIndent    :: String          -- Indent after the marker at the beginning of list items-  , stUseTags   :: Bool            -- True if we should use HTML tags because we're in a complex list+    stIndent      :: String          -- Indent after the marker at the beginning of list items+  , stUseTags     :: Bool            -- True if we should use HTML tags because we're in a complex list   , stBackSlashLB :: Bool     -- True if we should produce formatted strings with newlines (as in a table cell)   }  instance Default WriterState where-  def = WriterState { stNotes = False }+  def = WriterState {}  instance Default WriterEnvironment where   def = WriterEnvironment { stIndent = ""                           , stUseTags = False                           , stBackSlashLB = False } -type DokuWiki = ReaderT WriterEnvironment (State WriterState)+type DokuWiki m = ReaderT WriterEnvironment (StateT WriterState m)  -- | Convert Pandoc to DokuWiki.-writeDokuWiki :: WriterOptions -> Pandoc -> String+writeDokuWiki :: PandocMonad m => WriterOptions -> Pandoc -> m Text writeDokuWiki opts document =-  runDokuWiki (pandocToDokuWiki opts $ normalize document)+  runDokuWiki (pandocToDokuWiki opts document) -runDokuWiki :: DokuWiki a -> a-runDokuWiki = flip evalState def . flip runReaderT def+runDokuWiki :: PandocMonad m => DokuWiki m a -> m a+runDokuWiki = flip evalStateT def . flip runReaderT def  -- | Return DokuWiki representation of document.-pandocToDokuWiki :: WriterOptions -> Pandoc -> DokuWiki String+pandocToDokuWiki :: PandocMonad m+                 => WriterOptions -> Pandoc -> DokuWiki m Text pandocToDokuWiki opts (Pandoc meta blocks) = do   metadata <- metaToJSON opts               (fmap trimr . blockListToDokuWiki opts)               (inlineListToDokuWiki opts)               meta   body <- blockListToDokuWiki opts blocks-  notesExist <- stNotes <$> get-  let notes = if notesExist-                 then "" -- TODO Was "\n<references />" Check whether I can really remove this:-                         -- if it is definitely to do with footnotes, can remove this whole bit-                 else ""-  let main = body ++ notes+  let main = pack body   let context = defField "body" main-                $ defField "toc" (writerTableOfContents opts)-                $ metadata+                $ defField "toc" (writerTableOfContents opts) metadata   case writerTemplate opts of        Nothing  -> return main-       Just tpl -> return $ renderTemplate' tpl context+       Just tpl -> renderTemplate' tpl context  -- | Escape special characters for DokuWiki. escapeString :: String -> String@@ -112,9 +105,10 @@                substitute "//" "%%//%%"  -- | Convert Pandoc block element to DokuWiki.-blockToDokuWiki :: WriterOptions -- ^ Options+blockToDokuWiki :: PandocMonad m+                => WriterOptions -- ^ Options                 -> Block         -- ^ Block element-                -> DokuWiki String+                -> DokuWiki m String  blockToDokuWiki _ Null = return "" @@ -149,12 +143,13 @@ blockToDokuWiki opts (LineBlock lns) =   blockToDokuWiki opts $ linesToPara lns -blockToDokuWiki _ (RawBlock f str)+blockToDokuWiki _ b@(RawBlock f str)   | f == Format "dokuwiki" = return str   -- See https://www.dokuwiki.org/wiki:syntax   -- use uppercase HTML tag for block-level content:   | f == Format "html"     = return $ "<HTML>\n" ++ str ++ "\n</HTML>"-  | otherwise              = return ""+  | otherwise              = "" <$+         report (BlockNotRendered b)  blockToDokuWiki _ HorizontalRule = return "\n----\n" @@ -177,7 +172,7 @@                        "visualfoxpro", "winbatch", "xml", "xpp", "z80"]   return $ "<code" ++                 (case at of-                      [] -> ">\n"+                      []    -> ">\n"                       (x:_) -> " " ++ x ++ ">\n") ++ str ++ "\n</code>"  blockToDokuWiki opts (BlockQuote blocks) = do@@ -198,7 +193,7 @@   rows' <- mapM (zipWithM (tableItemToDokuWiki opts) aligns) rows   let widths = map (maximum . map length) $ transpose (headers':rows')   let padTo (width, al) s =-          case (width - length s) of+          case width - length s of                x | x > 0 ->                  if al == AlignLeft || al == AlignDefault                     then s ++ replicate x ' '@@ -278,21 +273,27 @@           else "")  -- | Convert bullet list item (list of blocks) to DokuWiki.-listItemToDokuWiki :: WriterOptions -> [Block] -> DokuWiki String+listItemToDokuWiki :: PandocMonad m+                   => WriterOptions -> [Block] -> DokuWiki m String listItemToDokuWiki opts items = do-  contents <- blockListToDokuWiki opts items   useTags <- stUseTags <$> ask   if useTags-     then return $ "<HTML><li></HTML>" ++ contents ++ "<HTML></li></HTML>"+     then do+       contents <- blockListToDokuWiki opts items+       return $ "<HTML><li></HTML>" ++ contents ++ "<HTML></li></HTML>"      else do+       bs <- mapM (blockToDokuWiki opts) items+       let contents = case items of+                           [_, CodeBlock _ _] -> concat bs+                           _                  -> vcat bs        indent <- stIndent <$> ask        backSlash <- stBackSlashLB <$> ask-       let indent' = if backSlash then (drop 2 indent) else indent+       let indent' = if backSlash then drop 2 indent else indent        return $ indent' ++ "* " ++ contents  -- | Convert ordered list item (list of blocks) to DokuWiki. -- | TODO Emiminate dreadful duplication of text from listItemToDokuWiki-orderedListItemToDokuWiki :: WriterOptions -> [Block] -> DokuWiki String+orderedListItemToDokuWiki :: PandocMonad m => WriterOptions -> [Block] -> DokuWiki m String orderedListItemToDokuWiki opts items = do   contents <- blockListToDokuWiki opts items   useTags <- stUseTags <$> ask@@ -301,24 +302,25 @@      else do        indent <- stIndent <$> ask        backSlash <- stBackSlashLB <$> ask-       let indent' = if backSlash then (drop 2 indent) else indent+       let indent' = if backSlash then drop 2 indent else indent        return $ indent' ++ "- " ++ contents  -- | Convert definition list item (label, list of blocks) to DokuWiki.-definitionListItemToDokuWiki :: WriterOptions+definitionListItemToDokuWiki :: PandocMonad m+                             => WriterOptions                              -> ([Inline],[[Block]])-                             -> DokuWiki String+                             -> DokuWiki m String definitionListItemToDokuWiki opts (label, items) = do   labelText <- inlineListToDokuWiki opts label   contents <- mapM (blockListToDokuWiki opts) items   useTags <- stUseTags <$> ask   if useTags      then return $ "<HTML><dt></HTML>" ++ labelText ++ "<HTML></dt></HTML>\n" ++-           (intercalate "\n" $ map (\d -> "<HTML><dd></HTML>" ++ d ++ "<HTML></dd></HTML>") contents)+           intercalate "\n" (map (\d -> "<HTML><dd></HTML>" ++ d ++ "<HTML></dd></HTML>") contents)      else do        indent <- stIndent <$> ask        backSlash <- stBackSlashLB <$> ask-       let indent' = if backSlash then (drop 2 indent) else indent+       let indent' = if backSlash then drop 2 indent else indent        return $ indent' ++ "* **" ++ labelText ++ "** " ++ concat contents  -- | True if the list can be handled by simple wiki markup, False if HTML tags will be needed.@@ -337,18 +339,19 @@ isSimpleListItem []  = True isSimpleListItem [x] =   case x of-       Plain _           -> True-       Para  _           -> True-       BulletList _      -> isSimpleList x-       OrderedList _ _   -> isSimpleList x-       DefinitionList _  -> isSimpleList x-       _                 -> False+       Plain _          -> True+       Para  _          -> True+       BulletList _     -> isSimpleList x+       OrderedList _ _  -> isSimpleList x+       DefinitionList _ -> isSimpleList x+       _                -> False isSimpleListItem [x, y] | isPlainOrPara x =   case y of-       BulletList _      -> isSimpleList y-       OrderedList _ _   -> isSimpleList y-       DefinitionList _  -> isSimpleList y-       _                 -> False+       BulletList _     -> isSimpleList y+       OrderedList _ _  -> isSimpleList y+       DefinitionList _ -> isSimpleList y+       CodeBlock _ _    -> True+       _                -> False isSimpleListItem _ = False  isPlainOrPara :: Block -> Bool@@ -368,14 +371,15 @@   where f '\n' = "\\\\ "         f c    = [c]         g (' ' : '\\':'\\': xs) = xs-        g s = s+        g s                     = s  -- Auxiliary functions for tables: -tableItemToDokuWiki :: WriterOptions-                     -> Alignment-                     -> [Block]-                     -> DokuWiki String+tableItemToDokuWiki :: PandocMonad m+                    => WriterOptions+                    -> Alignment+                    -> [Block]+                    -> DokuWiki m String tableItemToDokuWiki opts align' item = do   let mkcell x = (if align' == AlignRight || align' == AlignCenter                      then "  "@@ -388,22 +392,32 @@   return $ mkcell contents  -- | Convert list of Pandoc block elements to DokuWiki.-blockListToDokuWiki :: WriterOptions -- ^ Options+blockListToDokuWiki :: PandocMonad m+                    => WriterOptions -- ^ Options                     -> [Block]       -- ^ List of block elements-                    -> DokuWiki String+                    -> DokuWiki m String blockListToDokuWiki opts blocks = do   backSlash <- stBackSlashLB <$> ask+  let blocks' = consolidateRawBlocks blocks   if backSlash-    then (backSlashLineBreaks . vcat) <$> mapM (blockToDokuWiki opts) blocks-    else vcat <$> mapM (blockToDokuWiki opts) blocks+    then (backSlashLineBreaks . vcat) <$> mapM (blockToDokuWiki opts) blocks'+    else vcat <$> mapM (blockToDokuWiki opts) blocks' +consolidateRawBlocks :: [Block] -> [Block]+consolidateRawBlocks [] = []+consolidateRawBlocks (RawBlock f1 b1 : RawBlock f2 b2 : xs)+  | f1 == f2 = consolidateRawBlocks (RawBlock f1 (b1 ++ "\n" ++ b2) : xs)+consolidateRawBlocks (x:xs) = x : consolidateRawBlocks xs+ -- | Convert list of Pandoc inline elements to DokuWiki.-inlineListToDokuWiki :: WriterOptions -> [Inline] -> DokuWiki String+inlineListToDokuWiki :: PandocMonad m+                     => WriterOptions -> [Inline] -> DokuWiki m String inlineListToDokuWiki opts lst =-  concat <$> (mapM (inlineToDokuWiki opts) lst)+  concat <$> mapM (inlineToDokuWiki opts) lst  -- | Convert Pandoc inline element to DokuWiki.-inlineToDokuWiki :: WriterOptions -> Inline -> DokuWiki String+inlineToDokuWiki :: PandocMonad m+                 => WriterOptions -> Inline -> DokuWiki m String  inlineToDokuWiki opts (Span _attrs ils) =   inlineListToDokuWiki opts ils@@ -460,12 +474,12 @@                      DisplayMath -> "$$"                      InlineMath  -> "$" -inlineToDokuWiki _ (RawInline f str)+inlineToDokuWiki _ il@(RawInline f str)   | f == Format "dokuwiki" = return str   | f == Format "html"     = return $ "<html>" ++ str ++ "</html>"-  | otherwise              = return ""+  | otherwise              = "" <$ report (InlineNotRendered il) -inlineToDokuWiki _ (LineBreak) = return "\\\\\n"+inlineToDokuWiki _ LineBreak = return "\\\\\n"  inlineToDokuWiki opts SoftBreak =   case writerWrapText opts of@@ -498,7 +512,6 @@  inlineToDokuWiki opts (Note contents) = do   contents' <- blockListToDokuWiki opts contents-  modify (\s -> s { stNotes = True })   return $ "((" ++ contents' ++ "))"   -- note - may not work for notes with multiple blocks @@ -507,7 +520,7 @@   where     toPx = fmap (showInPixel opts) . checkPct     checkPct (Just (Percent _)) = Nothing-    checkPct maybeDim = maybeDim+    checkPct maybeDim           = maybeDim     go (Just w) Nothing  = "?" ++ w     go (Just w) (Just h) = "?" ++ w ++ "x" ++ h     go Nothing  (Just h) = "?0x" ++ h
src/Text/Pandoc/Writers/EPUB.hs view
@@ -1,6 +1,9 @@-{-# LANGUAGE PatternGuards, CPP, ScopedTypeVariables, ViewPatterns, FlexibleContexts #-}+{-# LANGUAGE CPP                 #-}+{-# LANGUAGE FlexibleContexts    #-}+{-# LANGUAGE PatternGuards       #-}+{-# LANGUAGE ScopedTypeVariables #-} {--Copyright (C) 2010-2015 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2010-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -19,7 +22,7 @@  {- |    Module      : Text.Pandoc.Writers.EPUB-   Copyright   : Copyright (C) 2010-2015 John MacFarlane+   Copyright   : Copyright (C) 2010-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -28,47 +31,47 @@  Conversion of 'Pandoc' documents to EPUB. -}-module Text.Pandoc.Writers.EPUB ( writeEPUB ) where-import Data.IORef ( IORef, newIORef, readIORef, modifyIORef )-import qualified Data.Map as M-import qualified Data.Set as Set-import Data.Maybe ( fromMaybe, catMaybes )-import Data.List ( isPrefixOf, isInfixOf, intercalate )-import System.Environment ( getEnv )-import Text.Printf (printf)-import System.FilePath ( takeExtension, takeFileName )-import System.FilePath.Glob ( namesMatching )-import Network.HTTP ( urlEncode )+module Text.Pandoc.Writers.EPUB ( writeEPUB2, writeEPUB3 ) where+import Codec.Archive.Zip (Entry, addEntryToArchive, eRelativePath, emptyArchive,+                          fromArchive, fromEntry, toEntry)+import Control.Monad (mplus, unless, when, zipWithM)+import Control.Monad.Except (catchError, throwError)+import Control.Monad.State.Strict (State, StateT, evalState, evalStateT, get,+                                   gets, lift, modify, put) import qualified Data.ByteString.Lazy as B import qualified Data.ByteString.Lazy.Char8 as B8-import qualified Text.Pandoc.UTF8 as UTF8-import Codec.Archive.Zip ( emptyArchive, addEntryToArchive, eRelativePath, fromEntry                         , Entry, toEntry, fromArchive)-import Data.Time.Clock.POSIX ( getPOSIXTime )-import Text.Pandoc.Compat.Time-import Text.Pandoc.Shared ( renderTags', safeRead, uniqueIdent, trim-                          , normalizeDate, readDataFile, stringify, warn-                          , hierarchicalize, fetchItem' )-import qualified Text.Pandoc.Shared as S (Element(..))+import Data.Char (isAlphaNum, isAscii, isDigit, toLower)+import Data.List (intercalate, isInfixOf, isPrefixOf)+import qualified Data.Map as M+import Data.Maybe (fromMaybe, isNothing, mapMaybe)+import qualified Data.Set as Set+import qualified Data.Text as TS+import qualified Data.Text.Lazy as TL+import Network.HTTP (urlEncode)+import System.FilePath (takeExtension, takeFileName)+import Text.HTML.TagSoup (Tag (TagOpen), fromAttrib, parseTags) import Text.Pandoc.Builder (fromList, setMeta)-import Text.Pandoc.Options ( WriterOptions(..)-                           , WrapOption(..)-                           , HTMLMathMethod(..)-                           , EPUBVersion(..)-                           , ObfuscationMethod(NoObfuscation) )+import Text.Pandoc.Class (PandocMonad, report)+import qualified Text.Pandoc.Class as P+import Text.Pandoc.Compat.Time import Text.Pandoc.Definition-import Text.Pandoc.Walk (walk, walkM, query)-import Control.Monad.State (modify, get, State, put, evalState)-import Control.Monad (mplus, liftM, when)-import Text.XML.Light ( unode, Element(..), unqual, Attr(..), add_attrs-                      , strContent, lookupAttr, Node(..), QName(..), parseXML-                      , onlyElems, node, ppElement)-import Text.Pandoc.UUID (getRandomUUID)-import Text.Pandoc.Writers.HTML ( writeHtml )-import Data.Char ( toLower, isDigit, isAlphaNum )-import Text.Pandoc.MIME (MimeType, getMimeType, extensionFromMimeType)-import qualified Control.Exception as E-import Text.Blaze.Html.Renderer.Utf8 (renderHtml)-import Text.HTML.TagSoup (Tag(TagOpen), fromAttrib, parseTags)+import Text.Pandoc.Error+import Text.Pandoc.Logging+import Text.Pandoc.MIME (MimeType, extensionFromMimeType, getMimeType)+import Text.Pandoc.Options (EPUBVersion (..), HTMLMathMethod (..),+                            ObfuscationMethod (NoObfuscation), WrapOption (..),+                            WriterOptions (..))+import Text.Pandoc.Shared (hierarchicalize, normalizeDate, renderTags',+                           safeRead, stringify, trim, uniqueIdent)+import qualified Text.Pandoc.Shared as S (Element (..))+import qualified Text.Pandoc.UTF8 as UTF8+import Text.Pandoc.UUID (getUUID)+import Text.Pandoc.Walk (query, walk, walkM)+import Text.Pandoc.Writers.HTML (writeHtmlStringForEPUB)+import Text.Printf (printf)+import Text.XML.Light (Attr (..), Element (..), Node (..), QName (..),+                       add_attrs, lookupAttr, node, onlyElems, parseXML,+                       ppElement, showElement, strContent, unode, unqual)  -- A Chapter includes a list of blocks and maybe a section -- number offset.  Note, some chapters are unnumbered. The section@@ -76,51 +79,54 @@ -- in filenames, chapter0003.xhtml. data Chapter = Chapter (Maybe [Int]) [Block] +data EPUBState = EPUBState {+        stMediaPaths  :: [(FilePath, (FilePath, Maybe Entry))]+      }++type E m = StateT EPUBState m+ data EPUBMetadata = EPUBMetadata{-    epubIdentifier         :: [Identifier]-  , epubTitle              :: [Title]-  , epubDate               :: [Date]-  , epubLanguage           :: String-  , epubCreator            :: [Creator]-  , epubContributor        :: [Creator]-  , epubSubject            :: [String]-  , epubDescription        :: Maybe String-  , epubType               :: Maybe String-  , epubFormat             :: Maybe String-  , epubPublisher          :: Maybe String-  , epubSource             :: Maybe String-  , epubRelation           :: Maybe String-  , epubCoverage           :: Maybe String-  , epubRights             :: Maybe String-  , epubCoverImage         :: Maybe String-  , epubStylesheet         :: Maybe Stylesheet-  , epubPageDirection      :: Maybe ProgressionDirection+    epubIdentifier    :: [Identifier]+  , epubTitle         :: [Title]+  , epubDate          :: [Date]+  , epubLanguage      :: String+  , epubCreator       :: [Creator]+  , epubContributor   :: [Creator]+  , epubSubject       :: [String]+  , epubDescription   :: Maybe String+  , epubType          :: Maybe String+  , epubFormat        :: Maybe String+  , epubPublisher     :: Maybe String+  , epubSource        :: Maybe String+  , epubRelation      :: Maybe String+  , epubCoverage      :: Maybe String+  , epubRights        :: Maybe String+  , epubCoverImage    :: Maybe String+  , epubStylesheets   :: [FilePath]+  , epubPageDirection :: Maybe ProgressionDirection+  , epubIbooksFields  :: [(String, String)]   } deriving Show -data Stylesheet = StylesheetPath FilePath-                | StylesheetContents String-                deriving Show- data Date = Date{-    dateText               :: String-  , dateEvent              :: Maybe String+    dateText  :: String+  , dateEvent :: Maybe String   } deriving Show  data Creator = Creator{-    creatorText            :: String-  , creatorRole            :: Maybe String-  , creatorFileAs          :: Maybe String+    creatorText   :: String+  , creatorRole   :: Maybe String+  , creatorFileAs :: Maybe String   } deriving Show  data Identifier = Identifier{-    identifierText         :: String-  , identifierScheme       :: Maybe String+    identifierText   :: String+  , identifierScheme :: Maybe String   } deriving Show  data Title = Title{-    titleText              :: String-  , titleFileAs            :: Maybe String-  , titleType              :: Maybe String+    titleText   :: String+  , titleFileAs :: Maybe String+  , titleType   :: Maybe String   } deriving Show  data ProgressionDirection = LTR | RTL deriving Show@@ -143,15 +149,15 @@ removeNote (Note _) = Str "" removeNote x        = x -getEPUBMetadata :: WriterOptions -> Meta -> IO EPUBMetadata+getEPUBMetadata :: PandocMonad m => WriterOptions -> Meta -> E m EPUBMetadata getEPUBMetadata opts meta = do   let md = metadataFromMeta opts meta-  let elts = onlyElems $ parseXML $ writerEpubMetadata opts+  let elts = maybe [] (onlyElems . parseXML) $ writerEpubMetadata opts   let md' = foldr addMetadataFromXML md elts   let addIdentifier m =        if null (epubIdentifier m)           then do-            randomId <- fmap show getRandomUUID+            randomId <- (show . getUUID) <$> lift P.newStdGen             return $ m{ epubIdentifier = [Identifier randomId Nothing] }           else return m   let addLanguage m =@@ -159,16 +165,19 @@           then case lookup "lang" (writerVariables opts) of                      Just x  -> return m{ epubLanguage = x }                      Nothing -> do-                       localeLang <- E.catch (liftM-                            (map (\c -> if c == '_' then '-' else c) .-                             takeWhile (/='.')) $ getEnv "LANG")-                          (\e -> let _ = (e :: E.SomeException) in return "en-US")+                       mLang <- lift $ P.lookupEnv "LANG"+                       let localeLang =+                             case mLang of+                               Just lang ->+                                 map (\c -> if c == '_' then '-' else c) $+                                 takeWhile (/='.') lang+                               Nothing -> "en-US"                        return m{ epubLanguage = localeLang }           else return m   let fixDate m =        if null (epubDate m)           then do-            currentTime <- getCurrentTime+            currentTime <- lift P.getCurrentTime             return $ m{ epubDate = [ Date{                              dateText = showDateTimeISO8601 currentTime                            , dateEvent = Nothing } ] }@@ -225,13 +234,17 @@ addMetadataFromXML _ md = md  metaValueToString :: MetaValue -> String-metaValueToString (MetaString s) = s+metaValueToString (MetaString s)    = s metaValueToString (MetaInlines ils) = stringify ils-metaValueToString (MetaBlocks bs) = stringify bs-metaValueToString (MetaBool True) = "true"-metaValueToString (MetaBool False) = "false"-metaValueToString _ = ""+metaValueToString (MetaBlocks bs)   = stringify bs+metaValueToString (MetaBool True)   = "true"+metaValueToString (MetaBool False)  = "false"+metaValueToString _                 = "" +metaValueToPaths:: MetaValue -> [FilePath]+metaValueToPaths (MetaList xs) = map metaValueToString xs+metaValueToPaths x             = [metaValueToString x]+ getList :: String -> Meta -> (MetaValue -> a) -> [a] getList s meta handleMetaValue =   case lookupMeta s meta of@@ -267,19 +280,18 @@ getDate :: String -> Meta -> [Date] getDate s meta = getList s meta handleMetaValue   where handleMetaValue (MetaMap m) =-           Date{ dateText = maybe "" id $+           Date{ dateText = fromMaybe "" $                    M.lookup "text" m >>= normalizeDate' . metaValueToString                , dateEvent = metaValueToString <$> M.lookup "event" m }-        handleMetaValue mv = Date { dateText = maybe ""-                                      id $ normalizeDate' $ metaValueToString mv+        handleMetaValue mv = Date { dateText = fromMaybe "" $ normalizeDate' $ metaValueToString mv                                   , dateEvent = Nothing }  simpleList :: String -> Meta -> [String] simpleList s meta =   case lookupMeta s meta of        Just (MetaList xs) -> map metaValueToString xs-       Just x -> [metaValueToString x]-       Nothing -> []+       Just x             -> [metaValueToString x]+       Nothing            -> []  metadataFromMeta :: WriterOptions -> Meta -> EPUBMetadata metadataFromMeta opts meta = EPUBMetadata{@@ -299,8 +311,9 @@     , epubCoverage           = coverage     , epubRights             = rights     , epubCoverImage         = coverImage-    , epubStylesheet         = stylesheet+    , epubStylesheets        = stylesheets     , epubPageDirection      = pageDirection+    , epubIbooksFields       = ibooksFields     }   where identifiers = getIdentifier meta         titles = getTitle meta@@ -320,37 +333,82 @@         rights = metaValueToString <$> lookupMeta "rights" meta         coverImage = lookup "epub-cover-image" (writerVariables opts) `mplus`              (metaValueToString <$> lookupMeta "cover-image" meta)-        stylesheet = (StylesheetContents <$> writerEpubStylesheet opts) `mplus`-                     ((StylesheetPath . metaValueToString) <$>-                       lookupMeta "stylesheet" meta)+        stylesheets = fromMaybe []+                        (metaValueToPaths <$> lookupMeta "stylesheet" meta) +++                      [f | ("css",f) <- writerVariables opts]         pageDirection = case map toLower . metaValueToString <$>                              lookupMeta "page-progression-direction" meta of                               Just "ltr" -> Just LTR                               Just "rtl" -> Just RTL                               _          -> Nothing+        ibooksFields = case lookupMeta "ibooks" meta of+                            Just (MetaMap mp)+                               -> M.toList $ M.map metaValueToString mp+                            _  -> [] +-- | Produce an EPUB2 file from a Pandoc document.+writeEPUB2 :: PandocMonad m+          => WriterOptions  -- ^ Writer options+          -> Pandoc         -- ^ Document to convert+          -> m B.ByteString+writeEPUB2 = writeEPUB EPUB2++-- | Produce an EPUB3 file from a Pandoc document.+writeEPUB3 :: PandocMonad m+          => WriterOptions  -- ^ Writer options+          -> Pandoc         -- ^ Document to convert+          -> m B.ByteString+writeEPUB3 = writeEPUB EPUB3+ -- | Produce an EPUB file from a Pandoc document.-writeEPUB :: WriterOptions  -- ^ Writer options+writeEPUB :: PandocMonad m+          => EPUBVersion+          -> WriterOptions  -- ^ Writer options           -> Pandoc         -- ^ Document to convert-          -> IO B.ByteString-writeEPUB opts doc@(Pandoc meta _) = do-  let version = fromMaybe EPUB2 (writerEpubVersion opts)+          -> m B.ByteString+writeEPUB epubVersion opts doc =+  let initState = EPUBState { stMediaPaths = [] }+  in+    evalStateT (pandocToEPUB epubVersion opts doc)+      initState++pandocToEPUB :: PandocMonad m+             => EPUBVersion+             -> WriterOptions+             -> Pandoc+             -> E m B.ByteString+pandocToEPUB version opts doc@(Pandoc meta _) = do+  let epubSubdir = writerEpubSubdirectory opts+  -- sanity check on epubSubdir+  unless (all (\c -> isAscii c && isAlphaNum c) epubSubdir) $+    throwError $ PandocEpubSubdirectoryError epubSubdir   let epub3 = version == EPUB3-  epochtime <- floor `fmap` getPOSIXTime+  let writeHtml o = fmap (UTF8.fromTextLazy . TL.fromStrict) .+                      writeHtmlStringForEPUB version o+  epochtime <- floor <$> lift P.getPOSIXTime+  metadata <- getEPUBMetadata opts meta   let mkEntry path content = toEntry path epochtime content++  -- stylesheet+  stylesheets <- case epubStylesheets metadata of+                      [] -> (\x -> [B.fromChunks [x]]) <$>+                             P.readDataFile "epub.css"+                      fs -> mapM P.readFileLazy fs+  let stylesheetEntries = zipWith+        (\bs n -> mkEntry ("styles/stylesheet" ++ show n ++ ".css") bs)+        stylesheets [(1 :: Int)..]+   let vars = ("epub3", if epub3 then "true" else "false")-           : ("css", "stylesheet.css")-           : writerVariables opts+           : map (\e -> ("css", "../" ++ eRelativePath e)) stylesheetEntries+           ++ [(x,y) | (x,y) <- writerVariables opts, x /= "css"]   let opts' = opts{ writerEmailObfuscation = NoObfuscation                   , writerSectionDivs = True-                  , writerHtml5 = epub3                   , writerVariables = vars                   , writerHTMLMathMethod =                        if epub3-                          then MathML Nothing+                          then MathML                           else writerHTMLMathMethod opts                   , writerWrapText = WrapAuto }-  metadata <- getEPUBMetadata opts' meta    -- cover page   (cpgEntry, cpicEntry) <-@@ -358,32 +416,32 @@                      Nothing   -> return ([],[])                      Just img  -> do                        let coverImage = "media/" ++ takeFileName img-                       let cpContent = renderHtml $ writeHtml+                       cpContent <- lift $ writeHtml                             opts'{ writerVariables = ("coverpage","true"):vars }                             (Pandoc meta [RawBlock (Format "html") $ "<div id=\"cover-image\">\n<img src=\"" ++ coverImage ++ "\" alt=\"cover image\" />\n</div>"])-                       imgContent <- B.readFile img+                       imgContent <- lift $ P.readFileLazy img                        return ( [mkEntry "cover.xhtml" cpContent]                               , [mkEntry coverImage imgContent] )    -- title page-  let tpContent = renderHtml $ writeHtml opts'{-                      writerVariables = ("titlepage","true"):vars }-                      (Pandoc meta [])-  let tpEntry = mkEntry "title_page.xhtml" tpContent+  tpContent <- lift $ writeHtml opts'{+                                  writerVariables = ("titlepage","true"):vars }+                               (Pandoc meta [])+  let tpEntry = mkEntry "text/title_page.xhtml" tpContent    -- handle pictures-  mediaRef <- newIORef []-  Pandoc _ blocks <- walkM (transformInline opts' mediaRef) doc >>=-                     walkM (transformBlock opts' mediaRef)-  picEntries <- (catMaybes . map (snd . snd)) <$> readIORef mediaRef-+  -- mediaRef <- P.newIORef []+  Pandoc _ blocks <- walkM (transformInline opts') doc >>=+                     walkM transformBlock+  picEntries <- (mapMaybe (snd . snd)) <$> gets stMediaPaths   -- handle fonts   let matchingGlob f = do-        xs <- namesMatching f+        xs <- lift $ P.glob f         when (null xs) $-          warn $ f ++ " did not match any font files."+          report $ CouldNotFetchResource f "glob did not match any font files"         return xs-  let mkFontEntry f = mkEntry (takeFileName f) `fmap` B.readFile f+  let mkFontEntry f = mkEntry ("fonts/" ++ takeFileName f) <$>+                        lift (P.readFileLazy f)   fontFiles <- concat <$> mapM matchingGlob (writerEpubFonts opts')   fontEntries <- mapM mkFontEntry fontFiles @@ -420,7 +478,7 @@         mbnum <- if "unnumbered" `elem` classes                     then return Nothing                     else case splitAt (n - 1) nums of-                              (ks, (m:_)) -> do+                              (ks, m:_) -> do                                 let nums' = ks ++ [m+1]                                 put nums'                                 return $ Just (ks ++ [m])@@ -467,26 +525,25 @@                          Chapter mbnum $ walk fixInternalReferences bs)                  chapters' -  let chapToEntry :: Int -> Chapter -> Entry-      chapToEntry num (Chapter mbnum bs) = mkEntry (showChapter num)-        $ renderHtml-        $ writeHtml opts'{ writerNumberOffset =-            fromMaybe [] mbnum }-        $ case bs of-              (Header _ _ xs : _) ->-                 -- remove notes or we get doubled footnotes-                 Pandoc (setMeta "title" (walk removeNote $ fromList xs)-                            nullMeta) bs-              _                   ->-                 Pandoc nullMeta bs+  let chapToEntry num (Chapter mbnum bs) =+       mkEntry ("text/" ++ showChapter num) <$>+        writeHtml opts'{ writerNumberOffset = fromMaybe [] mbnum } (case bs of+                                                                      (Header _ _ xs : _) ->+                                                                        -- remove notes or we get doubled footnotes+                                                                        Pandoc (setMeta "title" (walk removeNote $ fromList xs)+                                                                                 nullMeta) bs+                                                                      _                   ->+                                                                        Pandoc nullMeta bs) -  let chapterEntries = zipWith chapToEntry [1..] chapters+  chapterEntries <- lift $ zipWithM chapToEntry [1..] chapters    -- incredibly inefficient (TODO):   let containsMathML ent = epub3 &&-                           "<math" `isInfixOf` (B8.unpack $ fromEntry ent)+                           "<math" `isInfixOf`+        B8.unpack (fromEntry ent)   let containsSVG ent    = epub3 &&-                           "<svg" `isInfixOf` (B8.unpack $ fromEntry ent)+                           "<svg" `isInfixOf`+        B8.unpack (fromEntry ent)   let props ent = ["mathml" | containsMathML ent] ++ ["svg" | containsSVG ent]    -- contents.opf@@ -495,8 +552,8 @@                              ("href", eRelativePath ent),                              ("media-type", "application/xhtml+xml")]                             ++ case props ent of-                                    []   -> []-                                    xs   -> [("properties", unwords xs)])+                                    [] -> []+                                    xs -> [("properties", unwords xs)])                         $ ()   let chapterRefNode ent = unode "itemref" !                              [("idref", toId $ eRelativePath ent)] $ ()@@ -511,33 +568,35 @@                             ("media-type", fromMaybe "" $ getMimeType $ eRelativePath ent)] $ ()   let plainTitle = case docTitle' meta of                         [] -> case epubTitle metadata of-                                   []   -> "UNTITLED"+                                   []    -> "UNTITLED"                                    (x:_) -> titleText x                         x  -> stringify x    let tocTitle = fromMaybe plainTitle $                    metaValueToString <$> lookupMeta "toc-title" meta-  let uuid = case epubIdentifier metadata of-                  (x:_) -> identifierText x  -- use first identifier as UUID-                  []    -> error "epubIdentifier is null"  -- shouldn't happen-  currentTime <- getCurrentTime+  uuid <- case epubIdentifier metadata of+            (x:_) -> return $ identifierText x  -- use first identifier as UUID+            []    -> throwError $ PandocShouldNeverHappenError "epubIdentifier is null"  -- shouldn't happen+  currentTime <- lift P.getCurrentTime   let contentsData = UTF8.fromStringLazy $ ppTopElement $         unode "package" ! [("version", case version of                                              EPUB2 -> "2.0"                                              EPUB3 -> "3.0")                           ,("xmlns","http://www.idpf.org/2007/opf")-                          ,("unique-identifier","epub-id-1")] $+                          ,("unique-identifier","epub-id-1")+                          ,("prefix","ibooks: http://vocabulary.itunes.apple.com/rdf/ibooks/vocabulary-extensions-1.0/")] $           [ metadataElement version metadata currentTime           , unode "manifest" $              [ unode "item" ! [("id","ncx"), ("href","toc.ncx")                               ,("media-type","application/x-dtbncx+xml")] $ ()-             , unode "item" ! [("id","style"), ("href","stylesheet.css")-                              ,("media-type","text/css")] $ ()              , unode "item" ! ([("id","nav")                                ,("href","nav.xhtml")                                ,("media-type","application/xhtml+xml")] ++                                [("properties","nav") | epub3 ]) $ ()              ] +++             [ unode "item" ! [("id","style"), ("href",fp)+                              ,("media-type","text/css")] $ () |+                          fp <- map eRelativePath stylesheetEntries ] ++              map chapterNode (cpgEntry ++ (tpEntry : chapterEntries)) ++              (case cpicEntry of                     []    -> []@@ -546,7 +605,8 @@                               (pictureNode x)]) ++              map pictureNode picEntries ++              map fontNode fontEntries-          , unode "spine" ! ([("toc","ncx")] ++ progressionDirection) $+          , unode "spine" ! (+             ("toc","ncx") : progressionDirection) $               case epubCoverImage metadata of                     Nothing -> []                     Just _ -> [ unode "itemref" !@@ -575,38 +635,40 @@    let tocLevel = writerTOCDepth opts -  let navPointNode :: (Int -> String -> String -> [Element] -> Element)-                   -> S.Element -> State Int Element+  let navPointNode :: PandocMonad m+                   => (Int -> [Inline] -> String -> [Element] -> Element)+                   -> S.Element -> StateT Int m Element       navPointNode formatter (S.Sec _ nums (ident,_,_) ils children) = do         n <- get         modify (+1)         let showNums :: [Int] -> String             showNums = intercalate "." . map show-        let tit' = stringify ils         let tit = if writerNumberSections opts && not (null nums)-                     then showNums nums ++ " " ++ tit'-                     else tit'-        let src = case lookup ident reftable of-                       Just x  -> x-                       Nothing -> error (ident ++ " not found in reftable")+                     then Span ("", ["section-header-number"], [])+                           [Str (showNums nums)] : Space : ils+                     else ils+        src <- case lookup ident reftable of+                 Just x  -> return x+                 Nothing -> throwError $ PandocSomeError $ ident ++ " not found in reftable"         let isSec (S.Sec lev _ _ _ _) = lev <= tocLevel-            isSec _                 = False+            isSec _                   = False         let subsecs = filter isSec children         subs <- mapM (navPointNode formatter) subsecs         return $ formatter n tit src subs-      navPointNode _ (S.Blk _) = error "navPointNode encountered Blk"+      navPointNode _ (S.Blk _) = throwError $ PandocSomeError "navPointNode encountered Blk" -  let navMapFormatter :: Int -> String -> String -> [Element] -> Element+  let navMapFormatter :: Int -> [Inline] -> String -> [Element] -> Element       navMapFormatter n tit src subs = unode "navPoint" !                [("id", "navPoint-" ++ show n)] $-                  [ unode "navLabel" $ unode "text" tit-                  , unode "content" ! [("src", src)] $ ()+                  [ unode "navLabel" $ unode "text" $ stringify tit+                  , unode "content" ! [("src", "text/" ++ src)] $ ()                   ] ++ subs    let tpNode = unode "navPoint" !  [("id", "navPoint-0")] $                   [ unode "navLabel" $ unode "text" (stringify $ docTitle' meta)-                  , unode "content" ! [("src","title_page.xhtml")] $ () ]+                  , unode "content" ! [("src","text/title_page.xhtml")] $ () ] +  navMap <- lift $ evalStateT (mapM (navPointNode navMapFormatter) secs) 1   let tocData = UTF8.fromStringLazy $ ppTopElement $         unode "ncx" ! [("version","2005-1")                        ,("xmlns","http://www.daisy.org/z3986/2005/ncx/")] $@@ -623,27 +685,41 @@                         Nothing  -> []                         Just img -> [unode "meta" ! [("name","cover"),                                             ("content", toId img)] $ ()]-          , unode "docTitle" $ unode "text" $ plainTitle+          , unode "docTitle" $ unode "text" plainTitle           , unode "navMap" $-              tpNode : evalState (mapM (navPointNode navMapFormatter) secs) 1+              tpNode : navMap           ]   let tocEntry = mkEntry "toc.ncx" tocData -  let navXhtmlFormatter :: Int -> String -> String -> [Element] -> Element+  let navXhtmlFormatter :: Int -> [Inline] -> String -> [Element] -> Element       navXhtmlFormatter n tit src subs = unode "li" !                                        [("id", "toc-li-" ++ show n)] $-                                            (unode "a" ! [("href",src)]-                                             $ tit)+                                            (unode "a" ! [("href", "text/" +++                                                                   src)]+                                             $ titElements)                                             : case subs of                                                  []    -> []                                                  (_:_) -> [unode "ol" ! [("class","toc")] $ subs]+          where titElements = parseXML titRendered+                titRendered = case P.runPure+                               (writeHtmlStringForEPUB version+                                 opts{ writerTemplate = Nothing }+                                 (Pandoc nullMeta+                                   [Plain $ walk delink tit])) of+                                Left _  -> TS.pack $ stringify tit+                                Right x -> x+                -- can't have a element inside a...+                delink (Link _ ils _) = Span ("", [], []) ils+                delink x              = x    let navtag = if epub3 then "nav" else "div"-  let navBlocks = [RawBlock (Format "html") $ ppElement $+  tocBlocks <- lift $ evalStateT (mapM (navPointNode navXhtmlFormatter) secs) 1+  let navBlocks = [RawBlock (Format "html")+                  $ showElement $ -- prettyprinting introduces bad spaces                    unode navtag ! ([("epub:type","toc") | epub3] ++                                    [("id","toc")]) $                     [ unode "h1" ! [("id","toc-title")] $ tocTitle-                    , unode "ol" ! [("class","toc")] $ evalState (mapM (navPointNode navXhtmlFormatter) secs) 1]]+                    , unode "ol" ! [("class","toc")] $ tocBlocks ]]   let landmarks = if epub3                      then [RawBlock (Format "html") $ ppElement $                             unode "nav" ! [("epub:type","landmarks")@@ -664,8 +740,11 @@                             ]                           ]                      else []-  let navData = renderHtml $ writeHtml-                      opts'{ writerVariables = ("navpage","true"):vars }+  navData <- lift $ writeHtml opts'{ writerVariables = ("navpage","true"):+                     -- remove the leading ../ from stylesheet paths:+                     map (\(k,v) -> if k == "css"+                                       then (k, drop 3 v)+                                       else (k, v)) vars }             (Pandoc (setMeta "title"                      (walk removeNote $ fromList $ docTitle' meta) nullMeta)                (navBlocks ++ landmarks))@@ -679,7 +758,8 @@        unode "container" ! [("version","1.0")               ,("xmlns","urn:oasis:names:tc:opendocument:xmlns:container")] $          unode "rootfiles" $-           unode "rootfile" ! [("full-path","content.opf")+           unode "rootfile" ! [("full-path",+               epubSubdir ++ ['/' | not (null epubSubdir)] ++ "content.opf")                ,("media-type","application/oebps-package+xml")] $ ()   let containerEntry = mkEntry "META-INF/container.xml" containerData @@ -690,26 +770,24 @@             unode "option" ! [("name","specified-fonts")] $ "true"   let appleEntry = mkEntry "META-INF/com.apple.ibooks.display-options.xml" apple -  -- stylesheet-  stylesheet <- case epubStylesheet metadata of-                   Just (StylesheetPath fp)    -> UTF8.readFile fp-                   Just (StylesheetContents s) -> return s-                   Nothing -> UTF8.toString `fmap`-                              readDataFile (writerUserDataDir opts) "epub.css"-  let stylesheetEntry = mkEntry "stylesheet.css" $ UTF8.fromStringLazy stylesheet-+  let addEpubSubdir :: Entry -> Entry+      addEpubSubdir e = e{ eRelativePath =+        epubSubdir ++ ['/' | not (null epubSubdir)] ++ eRelativePath e }   -- construct archive-  let archive = foldr addEntryToArchive emptyArchive-                 (mimetypeEntry : containerEntry : appleEntry : stylesheetEntry : tpEntry :-                  contentsEntry : tocEntry : navEntry :-                  (picEntries ++ cpicEntry ++ cpgEntry ++ chapterEntries ++ fontEntries))+  let archive = foldr addEntryToArchive emptyArchive $+                 [mimetypeEntry, containerEntry, appleEntry] +++                 map addEpubSubdir+                 (tpEntry : contentsEntry : tocEntry : navEntry :+                  (stylesheetEntries ++ picEntries ++ cpicEntry +++                   cpgEntry ++ chapterEntries ++ fontEntries))   return $ fromArchive archive  metadataElement :: EPUBVersion -> EPUBMetadata -> UTCTime -> Element metadataElement version md currentTime =   unode "metadata" ! [("xmlns:dc","http://purl.org/dc/elements/1.1/")                      ,("xmlns:opf","http://www.idpf.org/2007/opf")] $ mdNodes-  where mdNodes = identifierNodes ++ titleNodes ++ dateNodes ++ languageNodes+  where mdNodes = identifierNodes ++ titleNodes ++ dateNodes+                  ++ languageNodes ++ ibooksNodes                   ++ creatorNodes ++ contributorNodes ++ subjectNodes                   ++ descriptionNodes ++ typeNodes ++ formatNodes                   ++ publisherNodes ++ sourceNodes ++ relationNodes@@ -728,6 +806,8 @@                                  [] -> []                                  (x:_) -> [dcNode "date" ! [("id","epub-date")]                                             $ dateText x]+        ibooksNodes = map ibooksNode (epubIbooksFields md)+        ibooksNode (k, v) = unode "meta" ! [("property", "ibooks:" ++ k)] $ v         languageNodes = [dcTag "language" $ epubLanguage md]         creatorNodes = withIds "epub-creator" (toCreatorNode "creator") $                        epubCreator md@@ -747,7 +827,7 @@                                        ("content",toId img)] $ ()])             $ epubCoverImage md         modifiedNodes = [ unode "meta" ! [("property", "dcterms:modified")] $-               (showDateTimeISO8601 currentTime) | version == EPUB3 ]+               showDateTimeISO8601 currentTime | version == EPUB3 ]         dcTag n s = unode ("dc:" ++ n) s         dcTag' n s = [dcTag n s]         toIdentifierNode id' (Identifier txt scheme)@@ -791,99 +871,93 @@              (("id",id') :                 maybe [] (\x -> [("opf:event",x)]) (dateEvent date)) $                  dateText date]-        schemeToOnix "ISBN-10" = "02"-        schemeToOnix "GTIN-13" = "03"-        schemeToOnix "UPC"     = "04"-        schemeToOnix "ISMN-10" = "05"-        schemeToOnix "DOI"     = "06"-        schemeToOnix "LCCN"    = "13"-        schemeToOnix "GTIN-14" = "14"-        schemeToOnix "ISBN-13" = "15"+        schemeToOnix "ISBN-10"              = "02"+        schemeToOnix "GTIN-13"              = "03"+        schemeToOnix "UPC"                  = "04"+        schemeToOnix "ISMN-10"              = "05"+        schemeToOnix "DOI"                  = "06"+        schemeToOnix "LCCN"                 = "13"+        schemeToOnix "GTIN-14"              = "14"+        schemeToOnix "ISBN-13"              = "15"         schemeToOnix "Legal deposit number" = "17"-        schemeToOnix "URN"     = "22"-        schemeToOnix "OCLC"    = "23"-        schemeToOnix "ISMN-13" = "25"-        schemeToOnix "ISBN-A"  = "26"-        schemeToOnix "JP"      = "27"-        schemeToOnix "OLCC"    = "28"-        schemeToOnix _         = "01"+        schemeToOnix "URN"                  = "22"+        schemeToOnix "OCLC"                 = "23"+        schemeToOnix "ISMN-13"              = "25"+        schemeToOnix "ISBN-A"               = "26"+        schemeToOnix "JP"                   = "27"+        schemeToOnix "OLCC"                 = "28"+        schemeToOnix _                      = "01"  showDateTimeISO8601 :: UTCTime -> String showDateTimeISO8601 = formatTime defaultTimeLocale "%FT%TZ" -transformTag :: WriterOptions-             -> IORef [(FilePath, (FilePath, Maybe Entry))] -- ^ (oldpath, newpath, entry) media-             -> Tag String-             -> IO (Tag String)-transformTag opts mediaRef tag@(TagOpen name attr)+transformTag :: PandocMonad m+             => Tag String+             -> E m (Tag String)+transformTag tag@(TagOpen name attr)   | name `elem` ["video", "source", "img", "audio"] &&-    lookup "data-external" attr == Nothing = do+    isNothing (lookup "data-external" attr) = do   let src = fromAttrib "src" tag   let poster = fromAttrib "poster" tag-  newsrc <- modifyMediaRef opts mediaRef src-  newposter <- modifyMediaRef opts mediaRef poster+  newsrc <- modifyMediaRef src+  newposter <- modifyMediaRef poster   let attr' = filter (\(x,_) -> x /= "src" && x /= "poster") attr ++               [("src", newsrc) | not (null newsrc)] ++               [("poster", newposter) | not (null newposter)]   return $ TagOpen name attr'-transformTag _ _ tag = return tag+transformTag tag = return tag -modifyMediaRef :: WriterOptions-               -> IORef [(FilePath, (FilePath, Maybe Entry))]-               -> FilePath-               -> IO FilePath-modifyMediaRef _ _ "" = return ""-modifyMediaRef opts mediaRef oldsrc = do-  media <- readIORef mediaRef+modifyMediaRef :: PandocMonad m+               => FilePath+               -> E m FilePath+modifyMediaRef "" = return ""+modifyMediaRef oldsrc = do+  media <- gets stMediaPaths   case lookup oldsrc media of          Just (n,_) -> return n-         Nothing    -> do-           res <- fetchItem' (writerMediaBag opts)-                    (writerSourceURL opts) oldsrc-           (new, mbEntry) <--                case res of-                      Left _        -> do-                        warn $ "Could not find media `" ++ oldsrc ++ "', skipping..."-                        return (oldsrc, Nothing)-                      Right (img,mbMime) -> do-                        let new = "media/file" ++ show (length media) ++-                               fromMaybe (takeExtension (takeWhile (/='?') oldsrc))-                                 (('.':) <$> (mbMime >>= extensionFromMimeType))-                        epochtime <- floor `fmap` getPOSIXTime-                        let entry = toEntry new epochtime $ B.fromChunks . (:[]) $ img-                        return (new, Just entry)-           modifyIORef mediaRef ( (oldsrc, (new, mbEntry)): )-           return new+         Nothing    -> catchError+           (do (img, mbMime) <- P.fetchItem oldsrc+               let new = "media/file" ++ show (length media) +++                          fromMaybe (takeExtension (takeWhile (/='?') oldsrc))+                          (('.':) <$> (mbMime >>= extensionFromMimeType))+               epochtime <- floor `fmap` lift P.getPOSIXTime+               let entry = toEntry new epochtime (B.fromChunks . (:[]) $ img)+               modify $ \st -> st{ stMediaPaths =+                            (oldsrc, (new, Just entry)):media}+               return new)+           (\e -> do+                report $ CouldNotFetchResource oldsrc (show e)+                return oldsrc) -transformBlock  :: WriterOptions-                -> IORef [(FilePath, (FilePath, Maybe Entry))] -- ^ (oldpath, newpath, entry) media-                -> Block-                -> IO Block-transformBlock opts mediaRef (RawBlock fmt raw)+transformBlock  :: PandocMonad m+                => Block+                -> E m Block+transformBlock (RawBlock fmt raw)   | fmt == Format "html" = do   let tags = parseTags raw-  tags' <- mapM (transformTag opts mediaRef)  tags+  tags' <- mapM transformTag tags   return $ RawBlock fmt (renderTags' tags')-transformBlock _ _ b = return b+transformBlock b = return b -transformInline  :: WriterOptions-                 -> IORef [(FilePath, (FilePath, Maybe Entry))] -- ^ (oldpath, newpath) media+transformInline  :: PandocMonad m+                 => WriterOptions                  -> Inline-                 -> IO Inline-transformInline opts mediaRef (Image attr lab (src,tit)) = do-    newsrc <- modifyMediaRef opts mediaRef src-    return $ Image attr lab (newsrc, tit)-transformInline opts mediaRef (x@(Math t m))+                 -> E m Inline+transformInline _opts (Image attr lab (src,tit)) = do+    newsrc <- modifyMediaRef src+    return $ Image attr lab ("../" ++ newsrc, tit)+transformInline opts (x@(Math t m))   | WebTeX url <- writerHTMLMathMethod opts = do-    newsrc <- modifyMediaRef opts mediaRef (url ++ urlEncode m)+    newsrc <- modifyMediaRef (url ++ urlEncode m)     let mathclass = if t == DisplayMath then "display" else "inline"-    return $ Span ("",["math",mathclass],[]) [Image nullAttr [x] (newsrc, "")]-transformInline opts mediaRef  (RawInline fmt raw)+    return $ Span ("",["math",mathclass],[])+                [Image nullAttr [x] ("../" ++ newsrc, "")]+transformInline _opts (RawInline fmt raw)   | fmt == Format "html" = do   let tags = parseTags raw-  tags' <- mapM (transformTag opts mediaRef) tags+  tags' <- mapM transformTag tags   return $ RawInline fmt (renderTags' tags')-transformInline _ _ x = return x+transformInline _ x = return x  (!) :: (t -> Element) -> [(String, String)] -> t -> Element (!) f attrs n = add_attrs (map (\(k,v) -> Attr (unqual k) v) attrs) (f n)@@ -898,8 +972,8 @@                    let (ds,ys) = break (==';') xs                        rest = drop 1 ys                    in  case safeRead ('\'':'\\':ds ++ "'") of-                          Just x   -> x : unEntity rest-                          Nothing  -> '&':'#':unEntity xs+                          Just x  -> x : unEntity rest+                          Nothing -> '&':'#':unEntity xs         unEntity (x:xs) = x : unEntity xs  mediaTypeOf :: FilePath -> Maybe MimeType@@ -907,7 +981,7 @@   let mediaPrefixes = ["image", "video", "audio"] in   case getMimeType x of     Just y | any (`isPrefixOf` y) mediaPrefixes -> Just y-    _                                           -> Nothing+    _      -> Nothing  -- Returns filename for chapter number. showChapter :: Int -> String
src/Text/Pandoc/Writers/FB2.hs view
@@ -1,8 +1,8 @@ {-# LANGUAGE PatternGuards #-}  {--Copyright (c) 2011-2012, Sergey Astanin-All rights reserved.+Copyright (c) 2011-2012 Sergey Astanin+              2012-2017 John MacFarlane  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -19,48 +19,57 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA -} -{- | Conversion of 'Pandoc' documents to FB2 (FictionBook2) format.+{- |+Module      : Text.Pandoc.Writers.FB2+Copyright   : Copyright (C) 2011-2012 Sergey Astanin+                            2012-2017 John MacFarlane+License     : GNU GPL, version 2 or above +Maintainer  : John MacFarlane+Stability   : alpha+Portability : portable++Conversion of 'Pandoc' documents to FB2 (FictionBook2) format.+ FictionBook is an XML-based e-book format. For more information see: <http://www.fictionbook.org/index.php/Eng:XML_Schema_Fictionbook_2.1>  -} module Text.Pandoc.Writers.FB2 (writeFB2)  where -import Control.Monad.State (StateT, evalStateT, get, modify)-import Control.Monad.State (liftM, liftM2, liftIO)+import Control.Monad (zipWithM)+import Control.Monad.Except (catchError)+import Control.Monad.State.Strict (StateT, evalStateT, get, lift, liftM, modify) import Data.ByteString.Base64 (encode)-import Data.Char (toLower, isSpace, isAscii, isControl)-import Data.List (intersperse, intercalate, isPrefixOf, stripPrefix)+import qualified Data.ByteString.Char8 as B8+import Data.Char (isAscii, isControl, isSpace, toLower) import Data.Either (lefts, rights)-import Network.Browser (browse, request, setAllowRedirects, setOutHandler)-import Network.HTTP (catchIO_, getRequest, getHeaders, getResponseBody)-import Network.HTTP (lookupHeader, HeaderName(..), urlEncode)-import Network.URI (isURI, unEscapeString)-import System.FilePath (takeExtension)+import Data.List (intercalate, intersperse, isPrefixOf, stripPrefix)+import Data.Text (Text, pack)+import Network.HTTP (urlEncode) import Text.XML.Light-import qualified Control.Exception as E-import qualified Data.ByteString as B import qualified Text.XML.Light as X import qualified Text.XML.Light.Cursor as XC +import Text.Pandoc.Class (PandocMonad, report)+import qualified Text.Pandoc.Class as P import Text.Pandoc.Definition-import Text.Pandoc.Options (WriterOptions(..), HTMLMathMethod(..), def)-import Text.Pandoc.Shared (orderedListMarkers, isHeaderBlock, capitalize,-                           linesToPara)+import Text.Pandoc.Logging+import Text.Pandoc.Options (HTMLMathMethod (..), WriterOptions (..), def)+import Text.Pandoc.Shared (capitalize, isHeaderBlock, isURI, orderedListMarkers)  -- | Data to be written at the end of the document: -- (foot)notes, URLs, references, images. data FbRenderState = FbRenderState-    { footnotes :: [ (Int, String, [Content]) ]  -- ^ #, ID, text-    , imagesToFetch :: [ (String, String) ]  -- ^ filename, URL or path-    , parentListMarker :: String  -- ^ list marker of the parent ordered list+    { footnotes         :: [ (Int, String, [Content]) ]  -- ^ #, ID, text+    , imagesToFetch     :: [ (String, String) ]  -- ^ filename, URL or path+    , parentListMarker  :: String  -- ^ list marker of the parent ordered list     , parentBulletLevel :: Int  -- ^ nesting level of the unordered list-    , writerOptions :: WriterOptions+    , writerOptions     :: WriterOptions     } deriving (Show)  -- | FictionBook building monad.-type FBM = StateT FbRenderState IO+type FBM m = StateT FbRenderState m  newFB :: FbRenderState newFB = FbRenderState { footnotes = [], imagesToFetch = []@@ -73,20 +82,27 @@     show InlineImage = "inlineImageType"  -- | Produce an FB2 document from a 'Pandoc' document.-writeFB2 :: WriterOptions    -- ^ conversion options+writeFB2 :: PandocMonad m+         => WriterOptions    -- ^ conversion options          -> Pandoc           -- ^ document to convert-         -> IO String        -- ^ FictionBook2 document (not encoded yet)-writeFB2 opts (Pandoc meta blocks) = flip evalStateT newFB $ do+         -> m Text           -- ^ FictionBook2 document (not encoded yet)+writeFB2 opts doc = flip evalStateT newFB $ pandocToFB2 opts doc++pandocToFB2 :: PandocMonad m+            => WriterOptions+            -> Pandoc+            -> FBM m Text+pandocToFB2 opts (Pandoc meta blocks) = do      modify (\s -> s { writerOptions = opts })      desc <- description meta      fp <- frontpage meta      secs <- renderSections 1 blocks      let body = el "body" $ fp ++ secs      notes <- renderFootnotes-     (imgs,missing) <- liftM imagesToFetch get >>= \s -> liftIO (fetchImages s)+     (imgs,missing) <- fmap imagesToFetch get >>= \s -> lift (fetchImages s)      let body' = replaceImagesWithAlt missing body      let fb2_xml = el "FictionBook" (fb2_attrs, [desc, body'] ++ notes ++ imgs)-     return $ xml_head ++ (showContent fb2_xml) ++ "\n"+     return $ pack $ xml_head ++ showContent fb2_xml ++ "\n"   where   xml_head = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"   fb2_attrs =@@ -94,67 +110,77 @@           xlink = "http://www.w3.org/1999/xlink"       in  [ uattr "xmlns" xmlns           , attr ("xmlns", "l") xlink ]-  ---  frontpage :: Meta -> FBM [Content]-  frontpage meta' = do-      t <- cMapM toXml . docTitle $ meta'-      return $-        [ el "title" (el "p" t)-        , el "annotation" (map (el "p" . cMap plain)-                           (docAuthors meta' ++ [docDate meta']))-        ]-  description :: Meta -> FBM Content-  description meta' = do-      bt <- booktitle meta'-      let as = authors meta'-      dd <- docdate meta'-      return $ el "description"-         [ el "title-info" (bt ++ as ++ dd)-         , el "document-info" [ el "program-used" "pandoc" ] -- FIXME: +version-         ]-  booktitle :: Meta -> FBM [Content]-  booktitle meta' = do-      t <- cMapM toXml . docTitle $ meta'-      return $ if null t-               then []-               else [ el "book-title" t ]-  authors :: Meta -> [Content]-  authors meta' = cMap author (docAuthors meta')-  author :: [Inline] -> [Content]-  author ss =-      let ws = words . cMap plain $ ss-          email = (el "email") `fmap` (take 1 $ filter ('@' `elem`) ws)-          ws' = filter ('@' `notElem`) ws-          names = case ws' of-                    (nickname:[]) -> [ el "nickname" nickname ]-                    (fname:lname:[]) -> [ el "first-name" fname-                                       , el "last-name" lname ]-                    (fname:rest) -> [ el "first-name" fname-                                   , el "middle-name" (concat . init $ rest)-                                   , el "last-name" (last rest) ]-                    ([]) -> []-      in  list $ el "author" (names ++ email)-  docdate :: Meta -> FBM [Content]-  docdate meta' = do-      let ss = docDate meta'-      d <- cMapM toXml ss-      return $ if null d-               then []-               else [el "date" d] +frontpage :: PandocMonad m => Meta -> FBM m [Content]+frontpage meta' = do+  t <- cMapM toXml . docTitle $ meta'+  return+    [ el "title" (el "p" t)+    , el "annotation" (map (el "p" . cMap plain)+                       (docAuthors meta' ++ [docDate meta']))+    ]++description :: PandocMonad m => Meta -> FBM m Content+description meta' = do+  bt <- booktitle meta'+  let as = authors meta'+  dd <- docdate meta'+  let lang = case lookupMeta "lang" meta' of+               Just (MetaInlines [Str s]) -> [el "lang" $ iso639 s]+               Just (MetaString s)        -> [el "lang" $ iso639 s]+               _                          -> []+             where iso639 = takeWhile (/= '-') -- Convert BCP 47 to ISO 639+  return $ el "description"+    [ el "title-info" (bt ++ as ++ dd ++ lang)+    , el "document-info" [ el "program-used" "pandoc" ] -- FIXME: +version+    ]++booktitle :: PandocMonad m => Meta -> FBM m [Content]+booktitle meta' = do+  t <- cMapM toXml . docTitle $ meta'+  return $ if null t+           then []+           else [ el "book-title" t ]++authors :: Meta -> [Content]+authors meta' = cMap author (docAuthors meta')++author :: [Inline] -> [Content]+author ss =+  let ws = words . cMap plain $ ss+      email = el "email" <$> take 1 (filter ('@' `elem`) ws)+      ws' = filter ('@' `notElem`) ws+      names = case ws' of+                [nickname] -> [ el "nickname" nickname ]+                [fname, lname] -> [ el "first-name" fname+                                    , el "last-name" lname ]+                (fname:rest) -> [ el "first-name" fname+                                , el "middle-name" (concat . init $ rest)+                                , el "last-name" (last rest) ]+                [] -> []+  in  list $ el "author" (names ++ email)++docdate :: PandocMonad m => Meta -> FBM m [Content]+docdate meta' = do+  let ss = docDate meta'+  d <- cMapM toXml ss+  return $ if null d+           then []+           else [el "date" d]+ -- | Divide the stream of blocks into sections and convert to XML -- representation.-renderSections :: Int -> [Block] -> FBM [Content]+renderSections :: PandocMonad m => Int -> [Block] -> FBM m [Content] renderSections level blocks = do     let secs = splitSections level blocks     mapM (renderSection level) secs -renderSection :: Int -> ([Inline], [Block]) -> FBM Content+renderSection :: PandocMonad m => Int -> ([Inline], [Block]) -> FBM m Content renderSection level (ttl, body) = do     title <- if null ttl             then return []             else return . list . el "title" . formatTitle $ ttl-    content <- if (hasSubsections body)+    content <- if hasSubsections body                then renderSections (level + 1) body                else cMapM blockToXml body     return $ el "section" (title ++ content)@@ -175,7 +201,7 @@  isLineBreak :: Inline -> Bool isLineBreak LineBreak = True-isLineBreak _ = False+isLineBreak _         = False  -- | Divide the stream of block elements into sections: [(title, blocks)]. splitSections :: Int -> [Block] -> [([Inline], [Block])]@@ -186,17 +212,17 @@     let (lastsec, before) = break sameLevel rblocks         (header, prevblocks) =             case before of-              ((Header n _ title):prevblocks') ->+              (Header n _ title:prevblocks') ->                   if n == level                      then (title, prevblocks')                      else ([], before)               _ -> ([], before)     in (header, reverse lastsec) : revSplit prevblocks   sameLevel (Header n _ _) = n == level-  sameLevel _ = False+  sameLevel _              = False  -- | Make another FictionBook body with footnotes.-renderFootnotes :: FBM [Content]+renderFootnotes :: PandocMonad m => FBM m [Content] renderFootnotes = do   fns <- footnotes `liftM` get   if null fns@@ -205,19 +231,19 @@          el "body" ([uattr "name" "notes"], map renderFN (reverse fns))   where     renderFN (n, idstr, cs) =-        let fn_texts = (el "title" (el "p" (show n))) : cs+        let fn_texts = el "title" (el "p" (show n)) : cs         in  el "section" ([uattr "id" idstr], fn_texts)  -- | Fetch images and encode them for the FictionBook XML. -- Return image data and a list of hrefs of the missing images.-fetchImages :: [(String,String)] -> IO ([Content],[String])+fetchImages :: PandocMonad m => [(String,String)] -> m ([Content],[String]) fetchImages links = do     imgs <- mapM (uncurry fetchImage) links-    return $ (rights imgs, lefts imgs)+    return (rights imgs, lefts imgs)  -- | Fetch image data from disk or from network and make a <binary> XML section. -- Return either (Left hrefOfMissingImage) or (Right xmlContent).-fetchImage :: String -> String -> IO (Either String Content)+fetchImage :: PandocMonad m => String -> String -> m (Either String Content) fetchImage href link = do   mbimg <-       case (isURI link, readDataURI link) of@@ -227,29 +253,26 @@               then return (Just (mime',base64))               else return Nothing        (True, Just _) -> return Nothing  -- not base64-encoded-       (True, Nothing) -> fetchURL link-       (False, _) -> do-        d <- nothingOnError $ B.readFile (unEscapeString link)-        let t = case map toLower (takeExtension link) of-                  ".png" -> Just "image/png"-                  ".jpg" -> Just "image/jpeg"-                  ".jpeg" -> Just "image/jpeg"-                  ".jpe" -> Just "image/jpeg"-                  _ -> Nothing  -- only PNG and JPEG are supported in FB2-        return $ liftM2 (,) t (liftM (toStr . encode) d)+       _               ->+         catchError (do (bs, mbmime) <- P.fetchItem link+                        case mbmime of+                             Nothing -> do+                               report $ CouldNotDetermineMimeType link+                               return Nothing+                             Just mime -> return $ Just (mime,+                                                      B8.unpack $ encode bs))+                    (\e ->+                       do report $ CouldNotFetchResource link (show e)+                          return Nothing)   case mbimg of-    Just (imgtype, imgdata) -> do+    Just (imgtype, imgdata) ->         return . Right $ el "binary"                    ( [uattr "id" href                      , uattr "content-type" imgtype]                    , txt imgdata )     _ -> return (Left ('#':href))-  where-   nothingOnError :: (IO B.ByteString) -> (IO (Maybe B.ByteString))-   nothingOnError action = liftM Just action `E.catch` omnihandler-   omnihandler :: E.SomeException -> IO (Maybe B.ByteString)-   omnihandler _ = return Nothing + -- | Extract mime type and encoded data from the Data URI. readDataURI :: String -- ^ URI             -> Maybe (String,String,Bool,String)@@ -276,8 +299,8 @@ isMimeType s =     case split (=='/') s of       [mtype,msubtype] ->-          ((map toLower mtype) `elem` types-           || "x-" `isPrefixOf` (map toLower mtype))+          (map toLower mtype `elem` types+           || "x-" `isPrefixOf` map toLower mtype)           && all valid mtype           && all valid msubtype       _ -> False@@ -286,68 +309,55 @@    valid c = isAscii c && not (isControl c) && not (isSpace c) &&              c `notElem` "()<>@,;:\\\"/[]?=" --- | Fetch URL, return its Content-Type and binary data on success.-fetchURL :: String -> IO (Maybe (String, String))-fetchURL url = do-  flip catchIO_ (return Nothing) $ do-     r <- browse $ do-           setOutHandler (const (return ()))-           setAllowRedirects True-           liftM snd . request . getRequest $ url-     let content_type = lookupHeader HdrContentType (getHeaders r)-     content <- liftM (Just . toStr . encode . toBS) . getResponseBody $ Right r-     return $ liftM2 (,) content_type content--toBS :: String -> B.ByteString-toBS = B.pack . map (toEnum . fromEnum)--toStr :: B.ByteString -> String-toStr = map (toEnum . fromEnum) . B.unpack- footnoteID :: Int -> String-footnoteID i = "n" ++ (show i)+footnoteID i = "n" ++ show i  linkID :: Int -> String-linkID i = "l" ++ (show i)+linkID i = "l" ++ show i  -- | Convert a block-level Pandoc's element to FictionBook XML representation.-blockToXml :: Block -> FBM [Content]+blockToXml :: PandocMonad m => Block -> FBM m [Content] blockToXml (Plain ss) = cMapM toXml ss  -- FIXME: can lead to malformed FB2 blockToXml (Para [Math DisplayMath formula]) = insertMath NormalImage formula -- title beginning with fig: indicates that the image is a figure blockToXml (Para [Image atr alt (src,'f':'i':'g':':':tit)]) =   insertImage NormalImage (Image atr alt (src,tit))-blockToXml (Para ss) = liftM (list . el "p") $ cMapM toXml ss+blockToXml (Para ss) = (list . el "p") <$> cMapM toXml ss blockToXml (CodeBlock _ s) = return . spaceBeforeAfter .                              map (el "p" . el "code") . lines $ s-blockToXml (RawBlock _ s) = return . spaceBeforeAfter .-                            map (el "p" . el "code") . lines $ s+blockToXml b@(RawBlock _ _) = do+  report $ BlockNotRendered b+  return [] blockToXml (Div _ bs) = cMapM blockToXml bs-blockToXml (BlockQuote bs) = liftM (list . el "cite") $ cMapM blockToXml bs-blockToXml (LineBlock lns) = blockToXml $ linesToPara lns+blockToXml (BlockQuote bs) = (list . el "cite") <$> cMapM blockToXml bs+blockToXml (LineBlock lns) =+  (list . el "poem") <$> mapM stanza (split null lns)+  where+    v xs = el "v" <$> cMapM toXml xs+    stanza xs = el "stanza" <$> mapM v xs blockToXml (OrderedList a bss) = do     state <- get     let pmrk = parentListMarker state-    let markers = map ((pmrk ++ " ") ++) $ orderedListMarkers a+    let markers = map (pmrk ++) $ orderedListMarkers a     let mkitem mrk bs = do-          modify (\s -> s { parentListMarker = mrk })-          itemtext <- cMapM blockToXml . paraToPlain $ bs+          modify (\s -> s { parentListMarker = mrk ++ " "})+          item <- cMapM blockToXml $ plainToPara $ indentBlocks (mrk ++ " ") bs           modify (\s -> s { parentListMarker = pmrk }) -- old parent marker-          return . el "p" $ [ txt mrk, txt " " ] ++ itemtext-    mapM (uncurry mkitem) (zip markers bss)+          return item+    concat <$> zipWithM mkitem markers bss blockToXml (BulletList bss) = do     state <- get     let level = parentBulletLevel state     let pmrk = parentListMarker state     let prefix = replicate (length pmrk) ' '     let bullets = ["\x2022", "\x25e6", "*", "\x2043", "\x2023"]-    let mrk = prefix ++ bullets !! (level `mod` (length bullets))+    let mrk = prefix ++ bullets !! (level `mod` length bullets)     let mkitem bs = do-          modify (\s -> s { parentBulletLevel = (level+1) })-          itemtext <- cMapM blockToXml . paraToPlain $ bs+          modify (\s -> s { parentBulletLevel = level+1 })+          item <- cMapM blockToXml $ plainToPara $ indentBlocks (mrk ++ " ") bs           modify (\s -> s { parentBulletLevel = level }) -- restore bullet level-          return $ el "p" $ [ txt (mrk ++ " ") ] ++ itemtext-    mapM mkitem bss+          return item+    cMapM mkitem bss blockToXml (DefinitionList defs) =     cMapM mkdef defs     where@@ -360,11 +370,13 @@               blocks ++ [Plain [LineBreak]]           else               blocks-      needsBreak (Para _) = False+      needsBreak (Para _)    = False       needsBreak (Plain ins) = LineBreak `notElem` ins-      needsBreak _ = True-blockToXml (Header _ _ _) = -- should never happen, see renderSections-                          error "unexpected header in section text"+      needsBreak _           = True+blockToXml h@Header{} = do+  -- should not occur after hierarchicalize, except inside lists/blockquotes+  report $ BlockNotRendered h+  return [] blockToXml HorizontalRule = return                             [ el "empty-line" ()                             , el "p" (txt (replicate 10 '—'))@@ -372,22 +384,22 @@ blockToXml (Table caption aligns _ headers rows) = do     hd <- mkrow "th" headers aligns     bd <- mapM (\r -> mkrow "td" r aligns) rows-    c <- return . el "emphasis" =<< cMapM toXml caption+    c <- el "emphasis" <$> cMapM toXml caption     return [el "table" (hd : bd), el "p" c]     where-      mkrow :: String -> [TableCell] -> [Alignment] -> FBM Content+      mkrow :: PandocMonad m => String -> [TableCell] -> [Alignment] -> FBM m Content       mkrow tag cells aligns' =-        (el "tr") `liftM` (mapM (mkcell tag) (zip cells aligns'))+        el "tr" <$> mapM (mkcell tag) (zip cells aligns')       ---      mkcell :: String -> (TableCell, Alignment) -> FBM Content+      mkcell :: PandocMonad m => String -> (TableCell, Alignment) -> FBM m Content       mkcell tag (cell, align) = do         cblocks <- cMapM blockToXml cell         return $ el tag ([align_attr align], cblocks)       --       align_attr a = Attr (QName "align" Nothing Nothing) (align_str a)-      align_str AlignLeft = "left"-      align_str AlignCenter = "center"-      align_str AlignRight = "right"+      align_str AlignLeft    = "left"+      align_str AlignCenter  = "center"+      align_str AlignRight   = "right"       align_str AlignDefault = "left" blockToXml Null = return [] @@ -396,21 +408,26 @@ paraToPlain :: [Block] -> [Block] paraToPlain [] = [] paraToPlain (Para inlines : rest) =-    let p = (Plain (inlines ++ [LineBreak]))-    in  p : paraToPlain rest+    Plain inlines : Plain [LineBreak] : paraToPlain rest paraToPlain (p:rest) = p : paraToPlain rest +-- Replace plain text with paragraphs and add line break after paragraphs.+-- It is used to convert plain text from tight list items to paragraphs.+plainToPara :: [Block] -> [Block]+plainToPara [] = []+plainToPara (Plain inlines : rest) =+    Para inlines : plainToPara rest+plainToPara (Para inlines : rest) =+    Para inlines : Plain [LineBreak] : plainToPara rest+plainToPara (p:rest) = p : plainToPara rest+ -- Simulate increased indentation level. Will not really work -- for multi-line paragraphs.-indent :: Block -> Block-indent = indentBlock+indentPrefix :: String -> Block -> Block+indentPrefix spacer = indentBlock   where-  -- indentation space-  spacer :: String-  spacer = replicate 4 ' '-  ---  indentBlock (Plain ins) = Plain ((Str spacer):ins)-  indentBlock (Para ins) = Para ((Str spacer):ins)+  indentBlock (Plain ins) = Plain (Str spacer:ins)+  indentBlock (Para ins) = Para (Str spacer:ins)   indentBlock (CodeBlock a s) =     let s' = unlines . map (spacer++) . lines $ s     in  CodeBlock a s'@@ -420,10 +437,21 @@   -- indent every (explicit) line   indentLines :: [Inline] -> [Inline]   indentLines ins = let lns = split isLineBreak ins :: [[Inline]]-                    in  intercalate [LineBreak] $ map ((Str spacer):) lns+                    in  intercalate [LineBreak] $ map (Str spacer:) lns +indent :: Block -> Block+indent = indentPrefix spacer+  where+  -- indentation space+  spacer :: String+  spacer = replicate 4 ' '++indentBlocks :: String -> [Block] -> [Block]+indentBlocks _ [] = []+indentBlocks prefix (x:xs) = indentPrefix prefix x : map (indentPrefix $ replicate (length prefix) ' ') xs+ -- | Convert a Pandoc's Inline element to FictionBook XML representation.-toXml :: Inline -> FBM [Content]+toXml :: PandocMonad m => Inline -> FBM m [Content] toXml (Str s) = return [txt s] toXml (Span _ ils) = cMapM toXml ils toXml (Emph ss) = list `liftM` wrap "emphasis" ss@@ -444,7 +472,9 @@ toXml SoftBreak = return [txt " "] toXml LineBreak = return [el "empty-line" ()] toXml (Math _ formula) = insertMath InlineImage formula-toXml (RawInline _ _) = return []  -- raw TeX and raw HTML are suppressed+toXml il@(RawInline _ _) = do+  report $ InlineNotRendered il+  return []  -- raw TeX and raw HTML are suppressed toXml (Link _ text (url,ttl)) = do   fns <- footnotes `liftM` get   let n = 1 + length fns@@ -462,7 +492,7 @@                   ( [ attr ("l","href") ('#':ln_id)                     , uattr "type" "note" ]                   , ln_ref) ]-toXml img@(Image _ _ _) = insertImage InlineImage img+toXml img@Image{} = insertImage InlineImage img toXml (Note bs) = do   fns <- footnotes `liftM` get   let n = 1 + length fns@@ -474,9 +504,9 @@                            , uattr "type" "note" ]                          , fn_ref ) -insertMath :: ImageMode -> String -> FBM [Content]+insertMath :: PandocMonad m => ImageMode -> String -> FBM m [Content] insertMath immode formula = do-  htmlMath <- return . writerHTMLMathMethod . writerOptions =<< get+  htmlMath <- fmap (writerHTMLMathMethod . writerOptions) get   case htmlMath of     WebTeX url -> do        let alt = [Code nullAttr formula]@@ -485,7 +515,7 @@        insertImage immode img     _ -> return [el "code" formula] -insertImage :: ImageMode -> Inline -> FBM [Content]+insertImage :: PandocMonad m => ImageMode -> Inline -> FBM m [Content] insertImage immode (Image _ alt (url,ttl)) = do   images <- imagesToFetch `liftM` get   let n = 1 + length images@@ -493,7 +523,7 @@   modify (\s -> s { imagesToFetch = (fname, url) : images })   let ttlattr = case (immode, null ttl) of                   (NormalImage, False) -> [ uattr "title" ttl ]-                  _ -> []+                  _                    -> []   return . list $          el "image" $             [ attr ("l","href") ('#':fname)@@ -517,20 +547,20 @@                  else c         in  case XC.nextDF c' of               (Just cnext) -> replaceAll cnext-              Nothing -> c'  -- end of document+              Nothing      -> c'  -- end of document   --     isImage :: Content -> Bool-    isImage (Elem e) = (elName e) == (uname "image")-    isImage _ = False+    isImage (Elem e) = elName e == uname "image"+    isImage _        = False   ---    isMissing (Elem img@(Element _ _ _ _)) =+    isMissing (Elem img@Element{}) =         let imgAttrs = elAttribs img             badAttrs = map (attr ("l","href")) missingHrefs         in  any (`elem` imgAttrs) badAttrs     isMissing _ = False   --     replaceNode :: Content -> Content-    replaceNode n@(Elem img@(Element _ _ _ _)) =+    replaceNode n@(Elem img@Element{}) =         let attrs = elAttribs img             alt = getAttrVal attrs (uname "alt")             imtype = getAttrVal attrs (qname "l" "type")@@ -551,7 +581,7 @@   -- | Wrap all inlines with an XML tag (given its unqualified name).-wrap :: String -> [Inline] -> FBM Content+wrap :: PandocMonad m => String -> [Inline] -> FBM m Content wrap tagname inlines = el tagname `liftM` cMapM toXml inlines  -- " Create a singleton list.@@ -560,25 +590,25 @@  -- | Convert an 'Inline' to plaintext. plain :: Inline -> String-plain (Str s) = s-plain (Emph ss) = concat (map plain ss)-plain (Span _ ss) = concat (map plain ss)-plain (Strong ss) = concat (map plain ss)-plain (Strikeout ss) = concat (map plain ss)-plain (Superscript ss) = concat (map plain ss)-plain (Subscript ss) = concat (map plain ss)-plain (SmallCaps ss) = concat (map plain ss)-plain (Quoted _ ss) = concat (map plain ss)-plain (Cite _ ss) = concat (map plain ss)  -- FIXME-plain (Code _ s) = s-plain Space = " "-plain SoftBreak = " "-plain LineBreak = "\n"-plain (Math _ s) = s-plain (RawInline _ s) = s+plain (Str s)               = s+plain (Emph ss)             = cMap plain ss+plain (Span _ ss)           = cMap plain ss+plain (Strong ss)           = cMap plain ss+plain (Strikeout ss)        = cMap plain ss+plain (Superscript ss)      = cMap plain ss+plain (Subscript ss)        = cMap plain ss+plain (SmallCaps ss)        = cMap plain ss+plain (Quoted _ ss)         = cMap plain ss+plain (Cite _ ss)           = cMap plain ss  -- FIXME+plain (Code _ s)            = s+plain Space                 = " "+plain SoftBreak             = " "+plain LineBreak             = "\n"+plain (Math _ s)            = s+plain (RawInline _ _)       = "" plain (Link _ text (url,_)) = concat (map plain text ++ [" <", url, ">"])-plain (Image _ alt _) = concat (map plain alt)-plain (Note _) = ""  -- FIXME+plain (Image _ alt _)       = cMap plain alt+plain (Note _)              = ""  -- FIXME  -- | Create an XML element. el :: (Node t)@@ -599,11 +629,11 @@  -- | Create an XML attribute with an unqualified name. uattr :: String -> String -> Text.XML.Light.Attr-uattr name val = Attr (uname name) val+uattr name = Attr (uname name)  -- | Create an XML attribute with a qualified name from given namespace. attr :: (String, String) -> String -> Text.XML.Light.Attr-attr (ns, name) val = Attr (qname ns name) val+attr (ns, name) = Attr (qname ns name)  -- | Unqualified name uname :: String -> QName
src/Text/Pandoc/Writers/HTML.hs view
@@ -1,949 +1,1392 @@-{-# LANGUAGE OverloadedStrings, CPP, ViewPatterns, ScopedTypeVariables #-}-{--Copyright (C) 2006-2015 John MacFarlane <jgm@berkeley.edu>--This program is free software; you can redistribute it and/or modify-it under the terms of the GNU General Public License as published by-the Free Software Foundation; either version 2 of the License, or-(at your option) any later version.--This program is distributed in the hope that it will be useful,-but WITHOUT ANY WARRANTY; without even the implied warranty of-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the-GNU General Public License for more details.--You should have received a copy of the GNU General Public License-along with this program; if not, write to the Free Software-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA--}--{- |-   Module      : Text.Pandoc.Writers.HTML-   Copyright   : Copyright (C) 2006-2015 John MacFarlane-   License     : GNU GPL, version 2 or above--   Maintainer  : John MacFarlane <jgm@berkeley.edu>-   Stability   : alpha-   Portability : portable--Conversion of 'Pandoc' documents to HTML.--}-module Text.Pandoc.Writers.HTML ( writeHtml , writeHtmlString ) where-import Text.Pandoc.Definition-import Data.Monoid ((<>))-import Text.Pandoc.Shared-import Text.Pandoc.Writers.Shared-import Text.Pandoc.Options-import Text.Pandoc.ImageSize-import Text.Pandoc.Templates-import Text.Pandoc.Readers.TeXMath-import Text.Pandoc.Slides-import Text.Pandoc.Highlighting ( highlight, styleToCss,-                                  formatHtmlInline, formatHtmlBlock )-import Text.Pandoc.XML (fromEntities, escapeStringForXML)-import Network.URI ( parseURIReference, URI(..), unEscapeString )-import Network.HTTP ( urlEncode )-import Numeric ( showHex )-import Data.Char ( ord, toLower )-import Data.List ( isPrefixOf, intersperse )-import Data.String ( fromString )-import Data.Maybe ( catMaybes, fromMaybe, isJust )-import Control.Monad.State-import Text.Blaze.Html hiding(contents)-#if MIN_VERSION_blaze_markup(0,6,3)-#else-import Text.Blaze.Internal(preEscapedString)-#endif-#if MIN_VERSION_blaze_html(0,5,1)-import qualified Text.Blaze.XHtml5 as H5-#else-import qualified Text.Blaze.Html5 as H5-#endif-import qualified Text.Blaze.XHtml1.Transitional as H-import qualified Text.Blaze.XHtml1.Transitional.Attributes as A-import Text.Blaze.Html.Renderer.String (renderHtml)-import Text.TeXMath-import Text.XML.Light.Output-import Text.XML.Light (unode, elChildren, unqual)-import qualified Text.XML.Light as XML-import System.FilePath (takeExtension)-import Data.Aeson (Value)--data WriterState = WriterState-    { stNotes            :: [Html]  -- ^ List of notes-    , stMath             :: Bool    -- ^ Math is used in document-    , stQuotes           :: Bool    -- ^ <q> tag is used-    , stHighlighting     :: Bool    -- ^ Syntax highlighting is used-    , stSecNum           :: [Int]   -- ^ Number of current section-    , stElement          :: Bool    -- ^ Processing an Element-    }--defaultWriterState :: WriterState-defaultWriterState = WriterState {stNotes= [], stMath = False, stQuotes = False,-                                  stHighlighting = False, stSecNum = [],-                                  stElement = False}---- Helpers to render HTML with the appropriate function.--strToHtml :: String -> Html-strToHtml ('\'':xs) = preEscapedString "\'" `mappend` strToHtml xs-strToHtml xs@(_:_)  = case break (=='\'') xs of-                           (_ ,[]) -> toHtml xs-                           (ys,zs) -> toHtml ys `mappend` strToHtml zs-strToHtml [] = ""---- | Hard linebreak.-nl :: WriterOptions -> Html-nl opts = if writerWrapText opts == WrapNone-             then mempty-             else preEscapedString "\n"---- | Convert Pandoc document to Html string.-writeHtmlString :: WriterOptions -> Pandoc -> String-writeHtmlString opts d =-  let (body, context) = evalState (pandocToHtml opts d) defaultWriterState-  in  case writerTemplate opts of-           Nothing  -> renderHtml body-           Just tpl -> renderTemplate' tpl $-                         defField "body" (renderHtml body) context---- | Convert Pandoc document to Html structure.-writeHtml :: WriterOptions -> Pandoc -> Html-writeHtml opts d =-  let (body, context) = evalState (pandocToHtml opts d) defaultWriterState-  in  case writerTemplate opts of-           Nothing  -> body-           Just tpl -> renderTemplate' tpl $-                         defField "body" (renderHtml body) context---- result is (title, authors, date, toc, body, new variables)-pandocToHtml :: WriterOptions-             -> Pandoc-             -> State WriterState (Html, Value)-pandocToHtml opts (Pandoc meta blocks) = do-  metadata <- metaToJSON opts-              (fmap renderHtml . blockListToHtml opts)-              (fmap renderHtml . inlineListToHtml opts)-              meta-  let stringifyHTML = escapeStringForXML . stringify-  let authsMeta = map stringifyHTML $ docAuthors meta-  let dateMeta  = stringifyHTML $ docDate meta-  let slideLevel = fromMaybe (getSlideLevel blocks) $ writerSlideLevel opts-  let sects = hierarchicalize $-              if writerSlideVariant opts == NoSlides-                 then blocks-                 else prepSlides slideLevel blocks-  toc <- if writerTableOfContents opts-            then tableOfContents opts sects-            else return Nothing-  blocks' <- liftM (mconcat . intersperse (nl opts)) $-                 mapM (elementToHtml slideLevel opts) sects-  st <- get-  let notes = reverse (stNotes st)-  let thebody = blocks' >> footnoteSection opts notes-  let  math = case writerHTMLMathMethod opts of-                      LaTeXMathML (Just url) ->-                         H.script ! A.src (toValue url)-                                  ! A.type_ "text/javascript"-                                  $ mempty-                      MathML (Just url) ->-                         H.script ! A.src (toValue url)-                                  ! A.type_ "text/javascript"-                                  $ mempty-                      MathJax url ->-                         H.script ! A.src (toValue url)-                                  ! A.type_ "text/javascript"-                                  $ case writerSlideVariant opts of-                                         SlideousSlides ->-                                            preEscapedString-                                            "MathJax.Hub.Queue([\"Typeset\",MathJax.Hub]);"-                                         _ -> mempty-                      JsMath (Just url) ->-                         H.script ! A.src (toValue url)-                                  ! A.type_ "text/javascript"-                                  $ mempty-                      KaTeX js css ->-                         (H.script ! A.src (toValue js) $ mempty) <>-                         (H.link ! A.rel "stylesheet" ! A.href (toValue css)) <>-                         (H.script ! A.type_ "text/javascript" $ toHtml renderKaTeX)-                      _ -> case lookup "mathml-script" (writerVariables opts) of-                                 Just s | not (writerHtml5 opts) ->-                                   H.script ! A.type_ "text/javascript"-                                      $ preEscapedString-                                       ("/*<![CDATA[*/\n" ++ s ++ "/*]]>*/\n")-                                        | otherwise -> mempty-                                 Nothing -> mempty-  let context =   (if stHighlighting st-                      then defField "highlighting-css"-                             (styleToCss $ writerHighlightStyle opts)-                      else id) $-                  (if stMath st-                      then defField "math" (renderHtml math)-                      else id) $-                  defField "quotes" (stQuotes st) $-                  maybe id (defField "toc" . renderHtml) toc $-                  defField "author-meta" authsMeta $-                  maybe id (defField "date-meta") (normalizeDate dateMeta) $-                  defField "pagetitle" (stringifyHTML $ docTitle meta) $-                  defField "idprefix" (writerIdentifierPrefix opts) $-                  -- these should maybe be set in pandoc.hs-                  defField "slidy-url"-                    ("http://www.w3.org/Talks/Tools/Slidy2" :: String) $-                  defField "slideous-url" ("slideous" :: String) $-                  defField "revealjs-url" ("reveal.js" :: String) $-                  defField "s5-url" ("s5/default" :: String) $-                  defField "html5" (writerHtml5 opts) $-                  metadata-  return (thebody, context)---- | Like Text.XHtml's identifier, but adds the writerIdentifierPrefix-prefixedId :: WriterOptions -> String -> Attribute-prefixedId opts s =-  case s of-    ""       -> mempty-    _        -> A.id $ toValue $ writerIdentifierPrefix opts ++ s--toList :: (Html -> Html) -> WriterOptions -> ([Html] -> Html)-toList listop opts items = do-    if (writerIncremental opts)-       then if (writerSlideVariant opts /= RevealJsSlides)-               then (listop $ mconcat items) ! A.class_ "incremental"-               else listop $ mconcat $ map (! A.class_ "fragment") items-       else listop $ mconcat items--unordList :: WriterOptions -> [Html] -> Html-unordList opts = toList H.ul opts . toListItems opts--ordList :: WriterOptions -> [Html] -> Html-ordList opts = toList H.ol opts . toListItems opts--defList :: WriterOptions -> [Html] -> Html-defList opts items = toList H.dl opts (items ++ [nl opts])---- | Construct table of contents from list of elements.-tableOfContents :: WriterOptions -> [Element] -> State WriterState (Maybe Html)-tableOfContents _ [] = return Nothing-tableOfContents opts sects = do-  let opts'        = opts { writerIgnoreNotes = True }-  contents  <- mapM (elementToListItem opts') sects-  let tocList = catMaybes contents-  return $ if null tocList-              then Nothing-              else Just $ unordList opts tocList---- | Convert section number to string-showSecNum :: [Int] -> String-showSecNum = concat . intersperse "." . map show---- | Converts an Element to a list item for a table of contents,--- retrieving the appropriate identifier from state.-elementToListItem :: WriterOptions -> Element -> State WriterState (Maybe Html)--- Don't include the empty headers created in slide shows--- shows when an hrule is used to separate slides without a new title:-elementToListItem _ (Sec _ _ _ [Str "\0"] _) = return Nothing-elementToListItem opts (Sec lev num (id',classes,_) headerText subsecs)-  | lev <= writerTOCDepth opts = do-  let num' = zipWith (+) num (writerNumberOffset opts ++ repeat 0)-  let sectnum = if writerNumberSections opts && not (null num) &&-                   "unnumbered" `notElem` classes-                   then (H.span ! A.class_ "toc-section-number"-                        $ toHtml $ showSecNum num') >> preEscapedString " "-                   else mempty-  txt <- liftM (sectnum >>) $ inlineListToHtml opts headerText-  subHeads <- mapM (elementToListItem opts) subsecs >>= return . catMaybes-  let subList = if null subHeads-                   then mempty-                   else unordList opts subHeads-  -- in reveal.js, we need #/apples, not #apples:-  let revealSlash = ['/' | writerSlideVariant opts == RevealJsSlides]-  return $ Just-         $ if null id'-              then (H.a $ toHtml txt) >> subList-              else (H.a ! A.href (toValue $ "#" ++ revealSlash ++-                    writerIdentifierPrefix opts ++ id')-                       $ toHtml txt) >> subList-elementToListItem _ _ = return Nothing---- | Convert an Element to Html.-elementToHtml :: Int -> WriterOptions -> Element -> State WriterState Html-elementToHtml _slideLevel opts (Blk block) = blockToHtml opts block-elementToHtml slideLevel opts (Sec level num (id',classes,keyvals) title' elements) = do-  let slide = writerSlideVariant opts /= NoSlides && level <= slideLevel-  let num' = zipWith (+) num (writerNumberOffset opts ++ repeat 0)-  modify $ \st -> st{stSecNum = num'}  -- update section number-  let titleSlide = slide && level < slideLevel-  header' <- if title' == [Str "\0"]  -- marker for hrule-                then return mempty-                else do-                  modify (\st -> st{ stElement = True})-                  res <- blockToHtml opts-                           (Header level (id',classes,keyvals) title')-                  modify (\st -> st{ stElement = False})-                  return res--  let isSec (Sec _ _ _ _ _) = True-      isSec (Blk _)         = False-  let isPause (Blk x) = x == Para [Str ".",Space,Str ".",Space,Str "."]-      isPause _       = False-  let fragmentClass = case writerSlideVariant opts of-                           RevealJsSlides  -> "fragment"-                           _               -> "incremental"-  let inDiv xs = Blk (RawBlock (Format "html") ("<div class=\""-                       ++ fragmentClass ++ "\">")) :-                   (xs ++ [Blk (RawBlock (Format "html") "</div>")])-  innerContents <- mapM (elementToHtml slideLevel opts)-                   $ if titleSlide-                        -- title slides have no content of their own-                        then filter isSec elements-                        else case splitBy isPause elements of-                                  []     -> []-                                  (x:xs) -> x ++ concatMap inDiv xs-  let inNl x = mconcat $ nl opts : intersperse (nl opts) x ++ [nl opts]-  let classes' = ["titleslide" | titleSlide] ++ ["slide" | slide] ++-                  ["section" | (slide || writerSectionDivs opts) &&-                               not (writerHtml5 opts) ] ++-                  ["level" ++ show level | slide || writerSectionDivs opts ]-                  ++ classes-  let secttag  = if writerHtml5 opts-                    then H5.section-                    else H.div-  let attr = (id',classes',keyvals)-  return $ if titleSlide-              then (if writerSlideVariant opts == RevealJsSlides-                       then H5.section-                       else id) $ mconcat $-                       (addAttrs opts attr $ secttag $ header') : innerContents-              else if writerSectionDivs opts || slide-                   then addAttrs opts attr-                        $ secttag $ inNl $ header' : innerContents-                   else mconcat $ intersperse (nl opts)-                        $ addAttrs opts attr header' : innerContents---- | Convert list of Note blocks to a footnote <div>.--- Assumes notes are sorted.-footnoteSection :: WriterOptions -> [Html] -> Html-footnoteSection opts notes =-  if null notes-     then mempty-     else nl opts >> (container-          $ nl opts >> hrtag >> nl opts >>-            H.ol (mconcat notes >> nl opts) >> nl opts)-   where container x = if writerHtml5 opts-                          then H5.section ! A.class_ "footnotes" $ x-                          else if writerSlideVariant opts /= NoSlides-                               then H.div ! A.class_ "footnotes slide" $ x-                               else H.div ! A.class_ "footnotes" $ x-         hrtag = if writerHtml5 opts then H5.hr else H.hr---- | Parse a mailto link; return Just (name, domain) or Nothing.-parseMailto :: String -> Maybe (String, String)-parseMailto s = do-  case break (==':') s of-       (xs,':':addr) | map toLower xs == "mailto" -> do-         let (name', rest) = span (/='@') addr-         let domain = drop 1 rest-         return (name', domain)-       _ -> fail "not a mailto: URL"---- | Obfuscate a "mailto:" link.-obfuscateLink :: WriterOptions -> Attr -> Html -> String -> Html-obfuscateLink opts attr txt s | writerEmailObfuscation opts == NoObfuscation =-  addAttrs opts attr $ H.a ! A.href (toValue s) $ txt-obfuscateLink opts attr (renderHtml -> txt) s =-  let meth = writerEmailObfuscation opts-      s' = map toLower (take 7 s) ++ drop 7 s-  in  case parseMailto s' of-        (Just (name', domain)) ->-          let domain'  = substitute "." " dot " domain-              at'      = obfuscateChar '@'-              (linkText, altText) =-                 if txt == drop 7 s' -- autolink-                    then ("e", name' ++ " at " ++ domain')-                    else ("'" ++ obfuscateString txt ++ "'",-                          txt ++ " (" ++ name' ++ " at " ++ domain' ++ ")")-          in  case meth of-                ReferenceObfuscation ->-                     -- need to use preEscapedString or &'s are escaped to &amp; in URL-                     preEscapedString $ "<a href=\"" ++ (obfuscateString s')-                     ++ "\" class=\"email\">" ++ (obfuscateString txt) ++ "</a>"-                JavascriptObfuscation ->-                     (H.script ! A.type_ "text/javascript" $-                     preEscapedString ("\n<!--\nh='" ++-                     obfuscateString domain ++ "';a='" ++ at' ++ "';n='" ++-                     obfuscateString name' ++ "';e=n+a+h;\n" ++-                     "document.write('<a h'+'ref'+'=\"ma'+'ilto'+':'+e+'\" clas'+'s=\"em' + 'ail\">'+" ++-                     linkText  ++ "+'<\\/'+'a'+'>');\n// -->\n")) >>-                     H.noscript (preEscapedString $ obfuscateString altText)-                _ -> error $ "Unknown obfuscation method: " ++ show meth-        _ -> addAttrs opts attr $ H.a ! A.href (toValue s) $ toHtml txt  -- malformed email---- | Obfuscate character as entity.-obfuscateChar :: Char -> String-obfuscateChar char =-  let num    = ord char-      numstr = if even num then show num else "x" ++ showHex num ""-  in  "&#" ++ numstr ++ ";"---- | Obfuscate string using entities.-obfuscateString :: String -> String-obfuscateString = concatMap obfuscateChar . fromEntities--addAttrs :: WriterOptions -> Attr -> Html -> Html-addAttrs opts attr h = foldl (!) h (attrsToHtml opts attr)--toAttrs :: [(String, String)] -> [Attribute]-toAttrs kvs = map (\(x,y) -> customAttribute (fromString x) (toValue y)) kvs--attrsToHtml :: WriterOptions -> Attr -> [Attribute]-attrsToHtml opts (id',classes',keyvals) =-  [prefixedId opts id' | not (null id')] ++-  [A.class_ (toValue $ unwords classes') | not (null classes')] ++ toAttrs keyvals--imgAttrsToHtml :: WriterOptions -> Attr -> [Attribute]-imgAttrsToHtml opts attr =-    attrsToHtml opts (ident,cls,kvs') ++-    toAttrs (dimensionsToAttrList opts attr)-  where-    (ident,cls,kvs) = attr-    kvs' = filter isNotDim kvs-    isNotDim ("width", _)  = False-    isNotDim ("height", _) = False-    isNotDim _ = True--dimensionsToAttrList :: WriterOptions -> Attr -> [(String, String)]-dimensionsToAttrList opts attr = (go Width) ++ (go Height)-  where-    go dir = case (dimension dir attr) of-               (Just (Percent a)) -> [("style", show dir ++ ":" ++ show (Percent a))]-               (Just dim)         -> [(show dir, showInPixel opts dim)]-               _ -> []---imageExts :: [String]-imageExts = [ "art", "bmp", "cdr", "cdt", "cpt", "cr2", "crw", "djvu", "erf",-              "gif", "ico", "ief", "jng", "jpg", "jpeg", "nef", "orf", "pat", "pbm",-              "pcx", "pgm", "png", "pnm", "ppm", "psd", "ras", "rgb", "svg", "tiff",-              "wbmp", "xbm", "xpm", "xwd" ]--treatAsImage :: FilePath -> Bool-treatAsImage fp =-  let path = case uriPath `fmap` parseURIReference fp of-                  Nothing -> fp-                  Just up -> up-      ext  = map toLower $ drop 1 $ takeExtension path-  in  null ext || ext `elem` imageExts---- | Convert Pandoc block element to HTML.-blockToHtml :: WriterOptions -> Block -> State WriterState Html-blockToHtml _ Null = return mempty-blockToHtml opts (Plain lst) = inlineListToHtml opts lst--- title beginning with fig: indicates that the image is a figure-blockToHtml opts (Para [Image attr txt (s,'f':'i':'g':':':tit)]) = do-  img <- inlineToHtml opts (Image attr txt (s,tit))-  let tocapt = if writerHtml5 opts-                  then H5.figcaption-                  else H.p ! A.class_ "caption"-  capt <- if null txt-             then return mempty-             else tocapt `fmap` inlineListToHtml opts txt-  return $ if writerHtml5 opts-              then H5.figure $ mconcat-                    [nl opts, img, capt, nl opts]-              else H.div ! A.class_ "figure" $ mconcat-                    [nl opts, img, nl opts, capt, nl opts]-blockToHtml opts (Para lst)-  | isEmptyRaw lst = return mempty-  | otherwise = do-      contents <- inlineListToHtml opts lst-      return $ H.p contents-  where-    isEmptyRaw [RawInline f _] = f /= (Format "html")-    isEmptyRaw _                 = False-blockToHtml opts (LineBlock lns) =-  if writerWrapText opts == WrapNone-  then blockToHtml opts $ linesToPara lns-  else do-    let lf = preEscapedString "\n"-    htmlLines <- mconcat . intersperse lf <$> mapM (inlineListToHtml opts) lns-    return $ H.div ! A.style "white-space: pre-line;" $ htmlLines-blockToHtml opts (Div attr@(ident, classes, kvs) bs) = do-  let speakerNotes = "notes" `elem` classes-  -- we don't want incremental output inside speaker notes, see #1394-  let opts' = if speakerNotes then opts{ writerIncremental = False } else opts-  contents <- blockListToHtml opts' bs-  let contents' = nl opts >> contents >> nl opts-  let (divtag, classes') = if writerHtml5 opts && "section" `elem` classes-                              then (H5.section, filter (/= "section") classes)-                              else (H.div, classes)-  return $-     if speakerNotes-        then case writerSlideVariant opts of-                  RevealJsSlides -> addAttrs opts' attr $ H5.aside $ contents'-                  DZSlides       -> (addAttrs opts' attr $ H5.div $ contents')-                                      ! (H5.customAttribute "role" "note")-                  NoSlides       -> addAttrs opts' attr $ H.div $ contents'-                  _              -> mempty-        else addAttrs opts (ident, classes', kvs) $ divtag $ contents'-blockToHtml opts (RawBlock f str)-  | f == Format "html" = return $ preEscapedString str-  | (f == Format "latex" || f == Format "tex") &&-     allowsMathEnvironments (writerHTMLMathMethod opts) &&-     isMathEnvironment str = blockToHtml opts $ Plain [Math DisplayMath str]-  | otherwise          = return mempty-blockToHtml opts (HorizontalRule) = return $ if writerHtml5 opts then H5.hr else H.hr-blockToHtml opts (CodeBlock (id',classes,keyvals) rawCode) = do-  let tolhs = isEnabled Ext_literate_haskell opts &&-                any (\c -> map toLower c == "haskell") classes &&-                any (\c -> map toLower c == "literate") classes-      classes' = if tolhs-                    then map (\c -> if map toLower c == "haskell"-                                       then "literatehaskell"-                                       else c) classes-                    else classes-      adjCode  = if tolhs-                    then unlines . map ("> " ++) . lines $ rawCode-                    else rawCode-      hlCode   = if writerHighlight opts -- check highlighting options-                    then highlight formatHtmlBlock (id',classes',keyvals) adjCode-                    else Nothing-  case hlCode of-         Nothing -> return $ addAttrs opts (id',classes,keyvals)-                           $ H.pre $ H.code $ toHtml adjCode-         Just  h -> modify (\st -> st{ stHighlighting = True }) >>-                    return (addAttrs opts (id',[],keyvals) h)-blockToHtml opts (BlockQuote blocks) =-  -- in S5, treat list in blockquote specially-  -- if default is incremental, make it nonincremental;-  -- otherwise incremental-  if writerSlideVariant opts /= NoSlides-     then let inc = not (writerIncremental opts) in-          case blocks of-             [BulletList lst]  -> blockToHtml (opts {writerIncremental = inc})-                                  (BulletList lst)-             [OrderedList attribs lst] ->-                                  blockToHtml (opts {writerIncremental = inc})-                                  (OrderedList attribs lst)-             [DefinitionList lst] ->-                                  blockToHtml (opts {writerIncremental = inc})-                                  (DefinitionList lst)-             _                 -> do contents <- blockListToHtml opts blocks-                                     return $ H.blockquote-                                            $ nl opts >> contents >> nl opts-     else do-       contents <- blockListToHtml opts blocks-       return $ H.blockquote $ nl opts >> contents >> nl opts-blockToHtml opts (Header level attr@(_,classes,_) lst) = do-  contents <- inlineListToHtml opts lst-  secnum <- liftM stSecNum get-  let contents' = if writerNumberSections opts && not (null secnum)-                     && "unnumbered" `notElem` classes-                     then (H.span ! A.class_ "header-section-number" $ toHtml-                          $ showSecNum secnum) >> strToHtml " " >> contents-                     else contents-  inElement <- gets stElement-  return $ (if inElement then id else addAttrs opts attr)-         $ case level of-              1 -> H.h1 contents'-              2 -> H.h2 contents'-              3 -> H.h3 contents'-              4 -> H.h4 contents'-              5 -> H.h5 contents'-              6 -> H.h6 contents'-              _ -> H.p contents'-blockToHtml opts (BulletList lst) = do-  contents <- mapM (blockListToHtml opts) lst-  return $ unordList opts contents-blockToHtml opts (OrderedList (startnum, numstyle, _) lst) = do-  contents <- mapM (blockListToHtml opts) lst-  let numstyle' = case numstyle of-                       Example -> "decimal"-                       _       -> camelCaseToHyphenated $ show numstyle-  let attribs = (if startnum /= 1-                   then [A.start $ toValue startnum]-                   else []) ++-                (if numstyle == Example-                    then [A.class_ "example"]-                    else []) ++-                (if numstyle /= DefaultStyle-                   then if writerHtml5 opts-                           then [A.type_ $-                                 case numstyle of-                                      Decimal    -> "1"-                                      LowerAlpha -> "a"-                                      UpperAlpha -> "A"-                                      LowerRoman -> "i"-                                      UpperRoman -> "I"-                                      _          -> "1"]-                           else [A.style $ toValue $ "list-style-type: " ++-                                   numstyle']-                   else [])-  return $ foldl (!) (ordList opts contents) attribs-blockToHtml opts (DefinitionList lst) = do-  contents <- mapM (\(term, defs) ->-                  do term' <- if null term-                                 then return mempty-                                 else liftM H.dt $ inlineListToHtml opts term-                     defs' <- mapM ((liftM (\x -> H.dd $ (x >> nl opts))) .-                                    blockListToHtml opts) defs-                     return $ mconcat $ nl opts : term' : nl opts :-                                        intersperse (nl opts) defs') lst-  return $ defList opts contents-blockToHtml opts (Table capt aligns widths headers rows') = do-  captionDoc <- if null capt-                   then return mempty-                   else do-                     cs <- inlineListToHtml opts capt-                     return $ H.caption cs >> nl opts-  let percent w = show (truncate (100*w) :: Integer) ++ "%"-  let coltags = if all (== 0.0) widths-                   then mempty-                   else do-                     H.colgroup $ do-                       nl opts-                       mapM_ (\w -> do-                            if writerHtml5 opts-                               then H.col ! A.style (toValue $ "width: " ++-                                                      percent w)-                               else H.col ! A.width (toValue $ percent w)-                            nl opts) widths-                     nl opts-  head' <- if all null headers-              then return mempty-              else do-                contents <- tableRowToHtml opts aligns 0 headers-                return $ H.thead (nl opts >> contents) >> nl opts-  body' <- liftM (\x -> H.tbody (nl opts >> mconcat x)) $-               zipWithM (tableRowToHtml opts aligns) [1..] rows'-  let tbl = H.table $-              nl opts >> captionDoc >> coltags >> head' >> body' >> nl opts-  let totalWidth = sum widths-  -- When widths of columns are < 100%, we need to set width for the whole-  -- table, or some browsers give us skinny columns with lots of space between:-  return $ if totalWidth == 0 || totalWidth == 1-              then tbl-              else tbl ! A.style (toValue $ "width:" ++-                              show (round (totalWidth * 100) :: Int) ++ "%;")--tableRowToHtml :: WriterOptions-               -> [Alignment]-               -> Int-               -> [[Block]]-               -> State WriterState Html-tableRowToHtml opts aligns rownum cols' = do-  let mkcell = if rownum == 0 then H.th else H.td-  let rowclass = case rownum of-                      0                  -> "header"-                      x | x `rem` 2 == 1 -> "odd"-                      _                  -> "even"-  cols'' <- sequence $ zipWith-            (\alignment item -> tableItemToHtml opts mkcell alignment item)-            aligns cols'-  return $ (H.tr ! A.class_ rowclass $ nl opts >> mconcat cols'')-          >> nl opts--alignmentToString :: Alignment -> [Char]-alignmentToString alignment = case alignment of-                                 AlignLeft    -> "left"-                                 AlignRight   -> "right"-                                 AlignCenter  -> "center"-                                 AlignDefault -> ""--tableItemToHtml :: WriterOptions-                -> (Html -> Html)-                -> Alignment-                -> [Block]-                -> State WriterState Html-tableItemToHtml opts tag' align' item = do-  contents <- blockListToHtml opts item-  let alignStr = alignmentToString align'-  let attribs = if writerHtml5 opts-                   then A.style (toValue $ "text-align: " ++ alignStr ++ ";")-                   else A.align (toValue alignStr)-  let tag'' = if null alignStr-                 then tag'-                 else tag' ! attribs-  return $ (tag'' $ contents) >> nl opts--toListItems :: WriterOptions -> [Html] -> [Html]-toListItems opts items = map (toListItem opts) items ++ [nl opts]--toListItem :: WriterOptions -> Html -> Html-toListItem opts item = nl opts >> H.li item--blockListToHtml :: WriterOptions -> [Block] -> State WriterState Html-blockListToHtml opts lst =-  fmap (mconcat . intersperse (nl opts)) $ mapM (blockToHtml opts) lst---- | Convert list of Pandoc inline elements to HTML.-inlineListToHtml :: WriterOptions -> [Inline] -> State WriterState Html-inlineListToHtml opts lst =-  mapM (inlineToHtml opts) lst >>= return . mconcat---- | Annotates a MathML expression with the tex source-annotateMML :: XML.Element -> String -> XML.Element-annotateMML e tex = math (unode "semantics" [cs, unode "annotation" (annotAttrs, tex)])-  where-    cs = case elChildren e of-          [] -> unode "mrow" ()-          [x] -> x-          xs -> unode "mrow" xs-    math childs = XML.Element q as [XML.Elem childs] l-      where-        (XML.Element q as _ l) = e-    annotAttrs = [XML.Attr (unqual "encoding") "application/x-tex"]----- | Convert Pandoc inline element to HTML.-inlineToHtml :: WriterOptions -> Inline -> State WriterState Html-inlineToHtml opts inline =-  case inline of-    (Str str)        -> return $ strToHtml str-    (Space)          -> return $ strToHtml " "-    (SoftBreak)      -> return $ case writerWrapText opts of-                                       WrapNone     -> preEscapedString " "-                                       WrapAuto     -> preEscapedString " "-                                       WrapPreserve -> preEscapedString "\n"-    (LineBreak)      -> return $ (if writerHtml5 opts then H5.br else H.br)-                                 <> strToHtml "\n"-    (Span (id',classes,kvs) ils)-                     -> inlineListToHtml opts ils >>=-                           return . addAttrs opts attr' . H.span-                        where attr' = (id',classes',kvs')-                              classes' = filter (`notElem` ["csl-no-emph",-                                              "csl-no-strong",-                                              "csl-no-smallcaps"]) classes-                              kvs' = if null styles-                                        then kvs-                                        else (("style", concat styles) : kvs)-                              styles = ["font-style:normal;"-                                         | "csl-no-emph" `elem` classes]-                                    ++ ["font-weight:normal;"-                                         | "csl-no-strong" `elem` classes]-                                    ++ ["font-variant:normal;"-                                         | "csl-no-smallcaps" `elem` classes]-    (Emph lst)       -> inlineListToHtml opts lst >>= return . H.em-    (Strong lst)     -> inlineListToHtml opts lst >>= return . H.strong-    (Code attr str)  -> case hlCode of-                             Nothing -> return-                                        $ addAttrs opts attr-                                        $ H.code $ strToHtml str-                             Just  h -> do-                               modify $ \st -> st{ stHighlighting = True }-                               return $ addAttrs opts (id',[],keyvals) h-                        where (id',_,keyvals) = attr-                              hlCode = if writerHighlight opts-                                          then highlight formatHtmlInline attr str-                                          else Nothing-    (Strikeout lst)  -> inlineListToHtml opts lst >>=-                        return . H.del-    (SmallCaps lst)   -> inlineListToHtml opts lst >>=-                         return . (H.span ! A.style "font-variant: small-caps;")-    (Superscript lst) -> inlineListToHtml opts lst >>= return . H.sup-    (Subscript lst)   -> inlineListToHtml opts lst >>= return . H.sub-    (Quoted quoteType lst) ->-                        let (leftQuote, rightQuote) = case quoteType of-                              SingleQuote -> (strToHtml "‘",-                                              strToHtml "’")-                              DoubleQuote -> (strToHtml "“",-                                              strToHtml "”")-                        in  if writerHtmlQTags opts-                               then do-                                 modify $ \st -> st{ stQuotes = True }-                                 H.q `fmap` inlineListToHtml opts lst-                               else (\x -> leftQuote >> x >> rightQuote)-                                    `fmap` inlineListToHtml opts lst-    (Math t str) -> do-      modify (\st -> st {stMath = True})-      let mathClass = toValue $ ("math " :: String) ++-                      if t == InlineMath then "inline" else "display"-      case writerHTMLMathMethod opts of-           LaTeXMathML _ ->-              -- putting LaTeXMathML in container with class "LaTeX" prevents-              -- non-math elements on the page from being treated as math by-              -- the javascript-              return $ H.span ! A.class_ "LaTeX" $-                     case t of-                       InlineMath  -> toHtml ("$" ++ str ++ "$")-                       DisplayMath -> toHtml ("$$" ++ str ++ "$$")-           JsMath _ -> do-              let m = preEscapedString str-              return $ case t of-                       InlineMath -> H.span ! A.class_ mathClass $ m-                       DisplayMath -> H.div ! A.class_ mathClass $ m-           WebTeX url -> do-              let imtag = if writerHtml5 opts then H5.img else H.img-              let m = imtag ! A.style "vertical-align:middle"-                            ! A.src (toValue $ url ++ urlEncode str)-                            ! A.alt (toValue str)-                            ! A.title (toValue str)-              let brtag = if writerHtml5 opts then H5.br else H.br-              return $ case t of-                        InlineMath  -> m-                        DisplayMath -> brtag >> m >> brtag-           GladTeX ->-              return $ case t of-                         InlineMath -> preEscapedString $ "<EQ ENV=\"math\">" ++ str ++ "</EQ>"-                         DisplayMath -> preEscapedString $ "<EQ ENV=\"displaymath\">" ++ str ++ "</EQ>"-           MathML _ -> do-              let dt = if t == InlineMath-                          then DisplayInline-                          else DisplayBlock-              let conf = useShortEmptyTags (const False)-                           defaultConfigPP-              case writeMathML dt <$> readTeX str of-                    Right r  -> return $ preEscapedString $-                        ppcElement conf (annotateMML r str)-                    Left _   -> inlineListToHtml opts-                        (texMathToInlines t str) >>=-                        return .  (H.span ! A.class_ mathClass)-           MathJax _ -> return $ H.span ! A.class_ mathClass $ toHtml $-              case t of-                InlineMath  -> "\\(" ++ str ++ "\\)"-                DisplayMath -> "\\[" ++ str ++ "\\]"-           KaTeX _ _ -> return $ H.span ! A.class_ mathClass $-              toHtml (case t of-                        InlineMath -> str-                        DisplayMath -> "\\displaystyle " ++ str)-           PlainMath -> do-              x <- inlineListToHtml opts (texMathToInlines t str)-              let m = H.span ! A.class_ mathClass $ x-              let brtag = if writerHtml5 opts then H5.br else H.br-              return  $ case t of-                         InlineMath  -> m-                         DisplayMath -> brtag >> m >> brtag-    (RawInline f str)-      | f == Format "html" -> return $ preEscapedString str-      | otherwise          -> return mempty-    (Link attr txt (s,_)) | "mailto:" `isPrefixOf` s -> do-                        linkText <- inlineListToHtml opts txt-                        return $ obfuscateLink opts attr linkText s-    (Link attr txt (s,tit)) -> do-                        linkText <- inlineListToHtml opts txt-                        let s' = case s of-                                      '#':xs | writerSlideVariant opts ==-                                            RevealJsSlides -> '#':'/':xs-                                      _ -> s-                        let link = H.a ! A.href (toValue s') $ linkText-                        let link' = if txt == [Str (unEscapeString s)]-                                       then link ! A.class_ "uri"-                                       else link-                        let link'' = addAttrs opts attr link'-                        return $ if null tit-                                    then link''-                                    else link'' ! A.title (toValue tit)-    (Image attr txt (s,tit)) | treatAsImage s -> do-                        let alternate' = stringify txt-                        let attributes = [A.src $ toValue s] ++-                                         [A.title $ toValue tit | not (null tit)] ++-                                         [A.alt $ toValue alternate' | not (null txt)] ++-                                         imgAttrsToHtml opts attr-                        let tag = if writerHtml5 opts then H5.img else H.img-                        return $ foldl (!) tag attributes-                        -- note:  null title included, as in Markdown.pl-    (Image attr _ (s,tit)) -> do-                        let attributes = [A.src $ toValue s] ++-                                         [A.title $ toValue tit | not (null tit)] ++-                                         imgAttrsToHtml opts attr-                        return $ foldl (!) H5.embed attributes-                        -- note:  null title included, as in Markdown.pl-    (Note contents)-      | writerIgnoreNotes opts -> return mempty-      | otherwise              -> do-                        notes <- gets stNotes-                        let number = (length notes) + 1-                        let ref = show number-                        htmlContents <- blockListToNote opts ref contents-                        -- push contents onto front of notes-                        modify $ \st -> st {stNotes = (htmlContents:notes)}-                        let revealSlash = ['/' | writerSlideVariant opts-                                                 == RevealJsSlides]-                        let link = H.a ! A.href (toValue $ "#" ++-                                         revealSlash ++-                                         writerIdentifierPrefix opts ++ "fn" ++ ref)-                                       ! A.class_ "footnoteRef"-                                       ! prefixedId opts ("fnref" ++ ref)-                                       $ (if isJust (writerEpubVersion opts)-                                             then id-                                             else H.sup)-                                       $ toHtml ref-                        return $ case writerEpubVersion opts of-                                      Just EPUB3 -> link ! customAttribute "epub:type" "noteref"-                                      _          -> link-    (Cite cits il)-> do contents <- inlineListToHtml opts il-                        let citationIds = unwords $ map citationId cits-                        let result = H.span ! A.class_ "citation" $ contents-                        return $ if writerHtml5 opts-                                    then result ! customAttribute "data-cites" (toValue citationIds)-                                    else result--blockListToNote :: WriterOptions -> String -> [Block] -> State WriterState Html-blockListToNote opts ref blocks =-  -- If last block is Para or Plain, include the backlink at the end of-  -- that block. Otherwise, insert a new Plain block with the backlink.-  let backlink = [Link nullAttr [Str "↩"] ("#" ++ writerIdentifierPrefix opts ++ "fnref" ++ ref,[])]-      blocks'  = if null blocks-                    then []-                    else let lastBlock   = last blocks-                             otherBlocks = init blocks-                         in  case lastBlock of-                                  (Para lst)  -> otherBlocks ++-                                                 [Para (lst ++ backlink)]-                                  (Plain lst) -> otherBlocks ++-                                                 [Plain (lst ++ backlink)]-                                  _           -> otherBlocks ++ [lastBlock,-                                                 Plain backlink]-  in  do contents <- blockListToHtml opts blocks'-         let noteItem = H.li ! (prefixedId opts ("fn" ++ ref)) $ contents-         let noteItem' = case writerEpubVersion opts of-                              Just EPUB3 -> noteItem ! customAttribute "epub:type" "footnote"-                              _          -> noteItem-         return $ nl opts >> noteItem'---- Javascript snippet to render all KaTeX elements-renderKaTeX :: String-renderKaTeX = unlines [-    "window.onload = function(){var mathElements = document.getElementsByClassName(\"math\");"-  , "for (var i=0; i < mathElements.length; i++)"-  , "{"-  , " var texText = mathElements[i].firstChild"-  , " katex.render(texText.data, mathElements[i])"-  , "}}"-  ]--isMathEnvironment :: String -> Bool-isMathEnvironment s = "\\begin{" `isPrefixOf` s &&-                         envName `elem` mathmlenvs-  where envName = takeWhile (/= '}') (drop 7 s)-        mathmlenvs = [ "align"-                     , "align*"-                     , "alignat"-                     , "alignat*"-                     , "aligned"-                     , "alignedat"-                     , "array"-                     , "Bmatrix"-                     , "bmatrix"-                     , "cases"-                     , "CD"-                     , "eqnarray"-                     , "eqnarray*"-                     , "equation"-                     , "equation*"-                     , "gather"-                     , "gather*"-                     , "gathered"-                     , "matrix"-                     , "multline"-                     , "multline*"-                     , "pmatrix"-                     , "smallmatrix"-                     , "split"-                     , "subarray"-                     , "Vmatrix"-                     , "vmatrix" ]--allowsMathEnvironments :: HTMLMathMethod -> Bool-allowsMathEnvironments (MathJax _) = True-allowsMathEnvironments (MathML _)  = True-allowsMathEnvironments (WebTeX _)  = True-allowsMathEnvironments _           = False+{-# LANGUAGE CPP                 #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE ViewPatterns        #-}+{-+Copyright (C) 2006-2017 John MacFarlane <jgm@berkeley.edu>++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation; either version 2 of the License, or+(at your option) any later version.++This program is distributed in the hope that it will be useful,+but WITHOUT ANY WARRANTY; without even the implied warranty of+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+GNU General Public License for more details.++You should have received a copy of the GNU General Public License+along with this program; if not, write to the Free Software+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+-}++{- |+   Module      : Text.Pandoc.Writers.HTML+   Copyright   : Copyright (C) 2006-2017 John MacFarlane+   License     : GNU GPL, version 2 or above++   Maintainer  : John MacFarlane <jgm@berkeley.edu>+   Stability   : alpha+   Portability : portable++Conversion of 'Pandoc' documents to HTML.+-}+module Text.Pandoc.Writers.HTML (+  writeHtml4,+  writeHtml4String,+  writeHtml5,+  writeHtml5String,+  writeHtmlStringForEPUB,+  writeS5,+  writeSlidy,+  writeSlideous,+  writeDZSlides,+  writeRevealJs+  ) where+import Control.Monad.State.Strict+import Data.Char (ord, toLower)+import Data.List (intercalate, intersperse, isPrefixOf, partition)+import Data.Maybe (catMaybes, fromMaybe, isJust, isNothing)+import Data.Monoid ((<>))+import qualified Data.Set as Set+import Data.String (fromString)+import Data.Text (Text)+import qualified Data.Text.Lazy as TL+import Network.HTTP (urlEncode)+import Network.URI (URI (..), parseURIReference, unEscapeString)+import Numeric (showHex)+import Text.Blaze.Html hiding (contents)+import Text.Pandoc.Definition+import Text.Pandoc.Highlighting (formatHtmlBlock, formatHtmlInline, highlight,+                                 styleToCss)+import Text.Pandoc.ImageSize+import Text.Pandoc.Options+import Text.Pandoc.Shared+import Text.Pandoc.Slides+import Text.Pandoc.Templates+import Text.Pandoc.Walk+import Text.Pandoc.Writers.Math+import Text.Pandoc.Writers.Shared+import Text.Pandoc.XML (escapeStringForXML, fromEntities)+#if MIN_VERSION_blaze_markup(0,6,3)+#else+import Text.Blaze.Internal (preEscapedString, preEscapedText)+#endif+#if MIN_VERSION_blaze_html(0,5,1)+import qualified Text.Blaze.XHtml5 as H5+#else+import qualified Text.Blaze.Html5 as H5+#endif+import Control.Monad.Except (throwError)+import Data.Aeson (Value)+import System.FilePath (takeBaseName, takeExtension)+import Text.Blaze.Html.Renderer.Text (renderHtml)+import qualified Text.Blaze.XHtml1.Transitional as H+import qualified Text.Blaze.XHtml1.Transitional.Attributes as A+import Text.Pandoc.Class (PandocMonad, report)+import Text.Pandoc.Error+import Text.Pandoc.Logging+import Text.TeXMath+import Text.XML.Light (elChildren, unode, unqual)+import qualified Text.XML.Light as XML+import Text.XML.Light.Output++data WriterState = WriterState+    { stNotes        :: [Html]  -- ^ List of notes+    , stMath         :: Bool    -- ^ Math is used in document+    , stQuotes       :: Bool    -- ^ <q> tag is used+    , stHighlighting :: Bool    -- ^ Syntax highlighting is used+    , stSecNum       :: [Int]   -- ^ Number of current section+    , stElement      :: Bool    -- ^ Processing an Element+    , stHtml5        :: Bool    -- ^ Use HTML5+    , stEPUBVersion  :: Maybe EPUBVersion -- ^ EPUB version if for epub+    , stSlideVariant :: HTMLSlideVariant+    }++defaultWriterState :: WriterState+defaultWriterState = WriterState {stNotes= [], stMath = False, stQuotes = False,+                                  stHighlighting = False, stSecNum = [],+                                  stElement = False, stHtml5 = False,+                                  stEPUBVersion = Nothing,+                                  stSlideVariant = NoSlides}++-- Helpers to render HTML with the appropriate function.++strToHtml :: String -> Html+strToHtml ('\'':xs) = preEscapedString "\'" `mappend` strToHtml xs+strToHtml xs@(_:_)  = case break (=='\'') xs of+                           (_ ,[]) -> toHtml xs+                           (ys,zs) -> toHtml ys `mappend` strToHtml zs+strToHtml [] = ""++-- | Hard linebreak.+nl :: WriterOptions -> Html+nl opts = if writerWrapText opts == WrapNone+             then mempty+             else preEscapedString "\n"++-- | Convert Pandoc document to Html 5 string.+writeHtml5String :: PandocMonad m => WriterOptions -> Pandoc -> m Text+writeHtml5String = writeHtmlString'+                      defaultWriterState{ stHtml5 = True }++-- | Convert Pandoc document to Html 5 structure.+writeHtml5 :: PandocMonad m => WriterOptions -> Pandoc -> m Html+writeHtml5 = writeHtml' defaultWriterState{ stHtml5 = True }++-- | Convert Pandoc document to Html 4 string.+writeHtml4String :: PandocMonad m => WriterOptions -> Pandoc -> m Text+writeHtml4String = writeHtmlString'+                      defaultWriterState{ stHtml5 = False }++-- | Convert Pandoc document to Html 4 structure.+writeHtml4 :: PandocMonad m => WriterOptions -> Pandoc -> m Html+writeHtml4 = writeHtml' defaultWriterState{ stHtml5 = False }++-- | Convert Pandoc document to Html appropriate for an epub version.+writeHtmlStringForEPUB :: PandocMonad m+                       => EPUBVersion -> WriterOptions -> Pandoc+                       -> m Text+writeHtmlStringForEPUB version o = writeHtmlString'+                      defaultWriterState{ stHtml5 = version == EPUB3,+                                          stEPUBVersion = Just version } o++-- | Convert Pandoc document to Reveal JS HTML slide show.+writeRevealJs :: PandocMonad m+              => WriterOptions -> Pandoc -> m Text+writeRevealJs = writeHtmlSlideShow' RevealJsSlides++-- | Convert Pandoc document to S5 HTML slide show.+writeS5 :: PandocMonad m+        => WriterOptions -> Pandoc -> m Text+writeS5 = writeHtmlSlideShow' S5Slides++-- | Convert Pandoc document to Slidy HTML slide show.+writeSlidy :: PandocMonad m+           => WriterOptions -> Pandoc -> m Text+writeSlidy = writeHtmlSlideShow' SlidySlides++-- | Convert Pandoc document to Slideous HTML slide show.+writeSlideous :: PandocMonad m+              => WriterOptions -> Pandoc -> m Text+writeSlideous = writeHtmlSlideShow' SlideousSlides++-- | Convert Pandoc document to DZSlides HTML slide show.+writeDZSlides :: PandocMonad m+              => WriterOptions -> Pandoc -> m Text+writeDZSlides = writeHtmlSlideShow' DZSlides++writeHtmlSlideShow' :: PandocMonad m+                    => HTMLSlideVariant -> WriterOptions -> Pandoc -> m Text+writeHtmlSlideShow' variant = writeHtmlString'+    defaultWriterState{ stSlideVariant = variant+                      , stHtml5 = case variant of+                                       RevealJsSlides -> True+                                       S5Slides       -> False+                                       SlidySlides    -> False+                                       DZSlides       -> True+                                       SlideousSlides -> False+                                       NoSlides       -> False+                      }++renderHtml' :: Html -> Text+renderHtml' = TL.toStrict . renderHtml++writeHtmlString' :: PandocMonad m+                 => WriterState -> WriterOptions -> Pandoc -> m Text+writeHtmlString' st opts d = do+  (body, context) <- evalStateT (pandocToHtml opts d) st+  case writerTemplate opts of+       Nothing -> return $ renderHtml' body+       Just tpl -> do+         -- warn if empty lang+         when (isNothing (getField "lang" context :: Maybe String)) $+           report NoLangSpecified+         -- check for empty pagetitle+         context' <-+            case getField "pagetitle" context of+                 Just (s :: String) | not (null s) -> return context+                 _ -> do+                   let fallback = fromMaybe "Untitled" $ takeBaseName <$>+                           lookup "sourcefile" (writerVariables opts)+                   report $ NoTitleElement fallback+                   return $ resetField "pagetitle" fallback context+         renderTemplate' tpl $+                    defField "body" (renderHtml' body) context'++writeHtml' :: PandocMonad m => WriterState -> WriterOptions -> Pandoc -> m Html+writeHtml' st opts d =+  case writerTemplate opts of+       Just _ -> preEscapedText <$> writeHtmlString' st opts d+       Nothing  -> do+        (body, _) <- evalStateT (pandocToHtml opts d) st+        return body++-- result is (title, authors, date, toc, body, new variables)+pandocToHtml :: PandocMonad m+             => WriterOptions+             -> Pandoc+             -> StateT WriterState m (Html, Value)+pandocToHtml opts (Pandoc meta blocks) = do+  metadata <- metaToJSON opts+              (fmap renderHtml' . blockListToHtml opts)+              (fmap renderHtml' . inlineListToHtml opts)+              meta+  let stringifyHTML = escapeStringForXML . stringify+  let authsMeta = map stringifyHTML $ docAuthors meta+  let dateMeta  = stringifyHTML $ docDate meta+  let slideLevel = fromMaybe (getSlideLevel blocks) $ writerSlideLevel opts+  slideVariant <- gets stSlideVariant+  let sects = hierarchicalize $+              if slideVariant == NoSlides+                 then blocks+                 else prepSlides slideLevel blocks+  toc <- if writerTableOfContents opts && slideVariant /= S5Slides+            then fmap renderHtml' <$> tableOfContents opts sects+            else return Nothing+  blocks' <- liftM (mconcat . intersperse (nl opts)) $+                 mapM (elementToHtml slideLevel opts) sects+  st <- get+  notes <- footnoteSection opts (reverse (stNotes st))+  let thebody = blocks' >> notes+  let  math = case writerHTMLMathMethod opts of+                      LaTeXMathML (Just url) ->+                         H.script ! A.src (toValue url)+                                  ! A.type_ "text/javascript"+                                  $ mempty+                      MathJax url+                        | slideVariant /= RevealJsSlides ->+                        -- mathjax is handled via a special plugin in revealjs+                         H.script ! A.src (toValue url)+                                  ! A.type_ "text/javascript"+                                  $ case slideVariant of+                                         SlideousSlides ->+                                            preEscapedString+                                            "MathJax.Hub.Queue([\"Typeset\",MathJax.Hub]);"+                                         _ -> mempty+                      JsMath (Just url) ->+                         H.script ! A.src (toValue url)+                                  ! A.type_ "text/javascript"+                                  $ mempty+                      KaTeX url ->+                         (H.script !+                           A.src (toValue $ url ++ "katex.min.js") $ mempty) <>+                         (H.script !+                           A.src (toValue $ url ++ "contrib/auto-render.min.js")+                             $ mempty) <>+                         (+                                  H.script+                            "document.addEventListener(\"DOMContentLoaded\", function() {\n  renderMathInElement(document.body);\n});") <>+                         (H.link ! A.rel "stylesheet" !+                           A.href (toValue $ url ++ "katex.min.css"))++                      _ -> case lookup "mathml-script" (writerVariables opts) of+                                 Just s | not (stHtml5 st) ->+                                   H.script ! A.type_ "text/javascript"+                                      $ preEscapedString+                                       ("/*<![CDATA[*/\n" ++ s ++ "/*]]>*/\n")+                                        | otherwise -> mempty+                                 Nothing -> mempty+  let context =   (if stHighlighting st+                      then case writerHighlightStyle opts of+                                Just sty -> defField "highlighting-css"+                                              (styleToCss sty)+                                Nothing  -> id+                      else id) $+                  (if stMath st+                      then defField "math" (renderHtml' math)+                      else id) $+                  defField "mathjax"+                      (case writerHTMLMathMethod opts of+                            MathJax _ -> True+                            _         -> False) $+                  defField "quotes" (stQuotes st) $+                  -- for backwards compatibility we populate toc+                  -- with the contents of the toc, rather than a+                  -- boolean:+                  maybe id (defField "toc") toc $+                  maybe id (defField "table-of-contents") toc $+                  defField "author-meta" authsMeta $+                  maybe id (defField "date-meta") (normalizeDate dateMeta) $+                  defField "pagetitle" (stringifyHTML (docTitle meta)) $+                  defField "idprefix" (writerIdentifierPrefix opts) $+                  -- these should maybe be set in pandoc.hs+                  defField "slidy-url"+                    ("https://www.w3.org/Talks/Tools/Slidy2" :: String) $+                  defField "slideous-url" ("slideous" :: String) $+                  defField "revealjs-url" ("reveal.js" :: String) $+                  defField "s5-url" ("s5/default" :: String) $+                  defField "html5" (stHtml5 st)+                  metadata+  return (thebody, context)++-- | Like Text.XHtml's identifier, but adds the writerIdentifierPrefix+prefixedId :: WriterOptions -> String -> Attribute+prefixedId opts s =+  case s of+    "" -> mempty+    _  -> A.id $ toValue $ writerIdentifierPrefix opts ++ s++toList :: PandocMonad m+       => (Html -> Html)+       -> WriterOptions+       -> [Html]+       -> StateT WriterState m Html+toList listop opts items = do+    slideVariant <- gets stSlideVariant+    return $+      if writerIncremental opts+         then if slideVariant /= RevealJsSlides+                 then  listop (mconcat items) ! A.class_ "incremental"+                 else listop $ mconcat $ map (! A.class_ "fragment") items+         else listop $ mconcat items++unordList :: PandocMonad m+          => WriterOptions -> [Html] -> StateT WriterState m Html+unordList opts = toList H.ul opts . toListItems opts++ordList :: PandocMonad m+        => WriterOptions -> [Html] -> StateT WriterState m Html+ordList opts = toList H.ol opts . toListItems opts++defList :: PandocMonad m+        => WriterOptions -> [Html] -> StateT WriterState m Html+defList opts items = toList H.dl opts (items ++ [nl opts])++-- | Construct table of contents from list of elements.+tableOfContents :: PandocMonad m => WriterOptions -> [Element] -> StateT WriterState m (Maybe Html)+tableOfContents _ [] = return Nothing+tableOfContents opts sects = do+  contents  <- mapM (elementToListItem opts) sects+  let tocList = catMaybes contents+  if null tocList+     then return Nothing+     else Just <$> unordList opts tocList++-- | Convert section number to string+showSecNum :: [Int] -> String+showSecNum = intercalate "." . map show++-- | Converts an Element to a list item for a table of contents,+-- retrieving the appropriate identifier from state.+elementToListItem :: PandocMonad m => WriterOptions -> Element -> StateT WriterState m (Maybe Html)+-- Don't include the empty headers created in slide shows+-- shows when an hrule is used to separate slides without a new title:+elementToListItem _ (Sec _ _ _ [Str "\0"] _) = return Nothing+elementToListItem opts (Sec lev num (id',classes,_) headerText subsecs)+  | lev <= writerTOCDepth opts = do+  let num' = zipWith (+) num (writerNumberOffset opts ++ repeat 0)+  let sectnum = if writerNumberSections opts && not (null num) &&+                   "unnumbered" `notElem` classes+                   then (H.span ! A.class_ "toc-section-number"+                        $ toHtml $ showSecNum num') >> preEscapedString " "+                   else mempty+  txt <- liftM (sectnum >>) $ inlineListToHtml opts $ walk deNote headerText+  subHeads <- mapM (elementToListItem opts) subsecs >>= return . catMaybes+  subList <- if null subHeads+                then return mempty+                else unordList opts subHeads+  -- in reveal.js, we need #/apples, not #apples:+  slideVariant <- gets stSlideVariant+  let revealSlash = ['/' | slideVariant== RevealJsSlides]+  return $ Just+         $ if null id'+              then  H.a (toHtml txt) >> subList+              else (H.a ! A.href (toValue $ "#" ++ revealSlash +++                    writerIdentifierPrefix opts ++ id')+                       $ toHtml txt) >> subList+elementToListItem _ _ = return Nothing++-- | Convert an Element to Html.+elementToHtml :: PandocMonad m => Int -> WriterOptions -> Element -> StateT WriterState m Html+elementToHtml _slideLevel opts (Blk block) = blockToHtml opts block+elementToHtml slideLevel opts (Sec level num (id',classes,keyvals) title' elements) = do+  slideVariant <- gets stSlideVariant+  let slide = slideVariant /= NoSlides && level <= slideLevel+  let num' = zipWith (+) num (writerNumberOffset opts ++ repeat 0)+  modify $ \st -> st{stSecNum = num'}  -- update section number+  html5 <- gets stHtml5+  let titleSlide = slide && level < slideLevel+  header' <- if title' == [Str "\0"]  -- marker for hrule+                then return mempty+                else do+                  modify (\st -> st{ stElement = True})+                  let level' = if level <= slideLevel &&+                                  slideVariant == SlidySlides+                                  then 1 -- see #3566+                                  else level+                  res <- blockToHtml opts+                           (Header level' (id',classes,keyvals) title')+                  modify (\st -> st{ stElement = False})+                  return res++  let isSec (Sec{}) = True+      isSec (Blk _) = False+  let isPause (Blk x) = x == Para [Str ".",Space,Str ".",Space,Str "."]+      isPause _       = False+  let fragmentClass = case slideVariant of+                           RevealJsSlides -> "fragment"+                           _              -> "incremental"+  let inDiv xs = Blk (RawBlock (Format "html") ("<div class=\""+                       ++ fragmentClass ++ "\">")) :+                   (xs ++ [Blk (RawBlock (Format "html") "</div>")])+  innerContents <- mapM (elementToHtml slideLevel opts)+                   $ if titleSlide+                        -- title slides have no content of their own+                        then filter isSec elements+                        else case splitBy isPause elements of+                                  []     -> []+                                  (x:xs) -> x ++ concatMap inDiv xs+  let inNl x = mconcat $ nl opts : intersperse (nl opts) x ++ [nl opts]+  let classes' = ["titleslide" | titleSlide] ++ ["slide" | slide] +++                  ["section" | (slide || writerSectionDivs opts) &&+                               not html5 ] +++                  ["level" ++ show level | slide || writerSectionDivs opts ]+                  ++ classes+  let secttag  = if html5+                    then H5.section+                    else H.div+  let attr = (id',classes',keyvals)+  if titleSlide+     then do+       t <- addAttrs opts attr $+                   secttag header'+       return $+         (if slideVariant == RevealJsSlides+                then H5.section+                else id) $ mconcat $ t : innerContents+     else if writerSectionDivs opts || slide+          then addAttrs opts attr+               $ secttag $ inNl $ header' : innerContents+          else do+            t <- addAttrs opts attr header'+            return $ mconcat $ intersperse (nl opts) (t : innerContents)++-- | Convert list of Note blocks to a footnote <div>.+-- Assumes notes are sorted.+footnoteSection :: PandocMonad m+                => WriterOptions -> [Html] -> StateT WriterState m Html+footnoteSection opts notes = do+  html5 <- gets stHtml5+  slideVariant <- gets stSlideVariant+  let hrtag = if html5 then H5.hr else H.hr+  let container x+        | html5 = H5.section ! A.class_ "footnotes" $ x+        | slideVariant /= NoSlides = H.div ! A.class_ "footnotes slide" $ x+        | otherwise = H.div ! A.class_ "footnotes" $ x+  return $+    if null notes+       then mempty+       else nl opts >> container (nl opts >> hrtag >> nl opts >>+              H.ol (mconcat notes >> nl opts) >> nl opts)++-- | Parse a mailto link; return Just (name, domain) or Nothing.+parseMailto :: String -> Maybe (String, String)+parseMailto s =+  case break (==':') s of+       (xs,':':addr) | map toLower xs == "mailto" -> do+         let (name', rest) = span (/='@') addr+         let domain = drop 1 rest+         return (name', domain)+       _ -> fail "not a mailto: URL"++-- | Obfuscate a "mailto:" link.+obfuscateLink :: PandocMonad m+              => WriterOptions -> Attr -> Html -> String+              -> StateT WriterState m Html+obfuscateLink opts attr txt s | writerEmailObfuscation opts == NoObfuscation =+  addAttrs opts attr $ H.a ! A.href (toValue s) $ txt+obfuscateLink opts attr (TL.unpack . renderHtml -> txt) s =+  let meth = writerEmailObfuscation opts+      s' = map toLower (take 7 s) ++ drop 7 s+  in  case parseMailto s' of+        (Just (name', domain)) ->+          let domain'  = substitute "." " dot " domain+              at'      = obfuscateChar '@'+              (linkText, altText) =+                 if txt == drop 7 s' -- autolink+                    then ("e", name' ++ " at " ++ domain')+                    else ("'" ++ obfuscateString txt ++ "'",+                          txt ++ " (" ++ name' ++ " at " ++ domain' ++ ")")+              (_, classNames, _) = attr+              classNamesStr = concatMap (' ':) classNames+          in  case meth of+                ReferenceObfuscation ->+                     -- need to use preEscapedString or &'s are escaped to &amp; in URL+                     return $+                     preEscapedString $ "<a href=\"" ++ obfuscateString s'+                     ++ "\" class=\"email\">" ++ obfuscateString txt ++ "</a>"+                JavascriptObfuscation ->+                     return $+                     (H.script ! A.type_ "text/javascript" $+                     preEscapedString ("\n<!--\nh='" +++                     obfuscateString domain ++ "';a='" ++ at' ++ "';n='" +++                     obfuscateString name' ++ "';e=n+a+h;\n" +++                     "document.write('<a h'+'ref'+'=\"ma'+'ilto'+':'+e+'\" clas'+'s=\"em' + 'ail" +++                     classNamesStr ++ "\">'+" +++                     linkText  ++ "+'<\\/'+'a'+'>');\n// -->\n")) >>+                     H.noscript (preEscapedString $ obfuscateString altText)+                _ -> throwError $ PandocSomeError $ "Unknown obfuscation method: " ++ show meth+        _ -> addAttrs opts attr $ H.a ! A.href (toValue s) $ toHtml txt  -- malformed email++-- | Obfuscate character as entity.+obfuscateChar :: Char -> String+obfuscateChar char =+  let num    = ord char+      numstr = if even num then show num else "x" ++ showHex num ""+  in  "&#" ++ numstr ++ ";"++-- | Obfuscate string using entities.+obfuscateString :: String -> String+obfuscateString = concatMap obfuscateChar . fromEntities++addAttrs :: PandocMonad m+         => WriterOptions -> Attr -> Html -> StateT WriterState m Html+addAttrs opts attr h = foldl (!) h <$> attrsToHtml opts attr++toAttrs :: PandocMonad m+        => [(String, String)] -> StateT WriterState m [Attribute]+toAttrs kvs = do+  html5 <- gets stHtml5+  return $ map (\(x,y) ->+     customAttribute+        (fromString (if not html5 || x `Set.member` html5Attributes+                                  || "data-" `isPrefixOf` x+                        then x+                        else "data-" ++ x)) (toValue y)) kvs++attrsToHtml :: PandocMonad m+            => WriterOptions -> Attr -> StateT WriterState m [Attribute]+attrsToHtml opts (id',classes',keyvals) = do+  attrs <- toAttrs keyvals+  return $+    [prefixedId opts id' | not (null id')] +++    [A.class_ (toValue $ unwords classes') | not (null classes')] ++ attrs++imgAttrsToHtml :: PandocMonad m+               => WriterOptions -> Attr -> StateT WriterState m [Attribute]+imgAttrsToHtml opts attr = do+  attrs <- attrsToHtml opts (ident,cls,kvs')+  dimattrs <- toAttrs (dimensionsToAttrList attr)+  return $ attrs ++ dimattrs+  where+    (ident,cls,kvs) = attr+    kvs' = filter isNotDim kvs+    isNotDim ("width", _)  = False+    isNotDim ("height", _) = False+    isNotDim _             = True++dimensionsToAttrList :: Attr -> [(String, String)]+dimensionsToAttrList attr = consolidateStyles $ go Width ++ go Height+  where+    consolidateStyles :: [(String, String)] -> [(String, String)]+    consolidateStyles xs =+      case partition isStyle xs of+           ([], _)    -> xs+           (ss, rest) -> ("style", intercalate ";" $ map snd ss) : rest+    isStyle ("style", _) = True+    isStyle _            = False+    go dir = case dimension dir attr of+               (Just (Pixel a)) -> [(show dir, show a)]+               (Just x)         -> [("style", show dir ++ ":" ++ show x)]+               Nothing          -> []++imageExts :: [String]+imageExts = [ "art", "bmp", "cdr", "cdt", "cpt", "cr2", "crw", "djvu", "erf",+              "gif", "ico", "ief", "jng", "jpg", "jpeg", "nef", "orf", "pat", "pbm",+              "pcx", "pgm", "png", "pnm", "ppm", "psd", "ras", "rgb", "svg", "tiff",+              "wbmp", "xbm", "xpm", "xwd" ]++treatAsImage :: FilePath -> Bool+treatAsImage fp =+  let path = fromMaybe fp (uriPath `fmap` parseURIReference fp)+      ext  = map toLower $ drop 1 $ takeExtension path+  in  null ext || ext `elem` imageExts++figure :: PandocMonad m+       => WriterOptions -> Attr -> [Inline] -> (String, String)+       -> StateT WriterState m Html+figure opts attr txt (s,tit) = do+  img <- inlineToHtml opts (Image attr txt (s,tit))+  html5 <- gets stHtml5+  let tocapt = if html5+                  then H5.figcaption+                  else H.p ! A.class_ "caption"+  capt <- if null txt+             then return mempty+             else tocapt `fmap` inlineListToHtml opts txt+  return $ if html5+              then H5.figure $ mconcat+                    [nl opts, img, capt, nl opts]+              else H.div ! A.class_ "figure" $ mconcat+                    [nl opts, img, nl opts, capt, nl opts]++-- | Convert Pandoc block element to HTML.+blockToHtml :: PandocMonad m => WriterOptions -> Block -> StateT WriterState m Html+blockToHtml _ Null = return mempty+blockToHtml opts (Plain lst) = inlineListToHtml opts lst+blockToHtml opts (Para [Image attr@(_,classes,_) txt (src,tit)])+  | "stretch" `elem` classes = do+  slideVariant <- gets stSlideVariant+  case slideVariant of+       RevealJsSlides ->+         -- a "stretched" image in reveal.js must be a direct child+         -- of the slide container+         inlineToHtml opts (Image attr txt (src, tit))+       _ -> figure opts attr txt (src, tit)+-- title beginning with fig: indicates that the image is a figure+blockToHtml opts (Para [Image attr txt (s,'f':'i':'g':':':tit)]) =+  figure opts attr txt (s,tit)+blockToHtml opts (Para lst)+  | isEmptyRaw lst = return mempty+  | otherwise = do+      contents <- inlineListToHtml opts lst+      return $ H.p contents+  where+    isEmptyRaw [RawInline f _] = f `notElem` [Format "html",+                                    Format "html4", Format "html5"]+    isEmptyRaw _               = False+blockToHtml opts (LineBlock lns) =+  if writerWrapText opts == WrapNone+  then blockToHtml opts $ linesToPara lns+  else do+    let lf = preEscapedString "\n"+    htmlLines <- mconcat . intersperse lf <$> mapM (inlineListToHtml opts) lns+    return $ H.div ! A.class_ "line-block" $ htmlLines+blockToHtml opts (Div attr@(ident, classes, kvs') bs) = do+  html5 <- gets stHtml5+  let kvs = kvs' +++        if "column" `elem` classes+           then let w = fromMaybe "48%" (lookup "width" kvs')+                in  [("style", "width:" ++ w ++ ";min-width:" ++ w +++                      ";vertical-align:top;")]+           else []+  let speakerNotes = "notes" `elem` classes+  -- we don't want incremental output inside speaker notes, see #1394+  let opts' = if speakerNotes then opts{ writerIncremental = False } else opts+  contents <- blockListToHtml opts' bs+  let contents' = nl opts >> contents >> nl opts+  let (divtag, classes') = if html5 && "section" `elem` classes+                              then (H5.section, filter (/= "section") classes)+                              else (H.div, classes)+  slideVariant <- gets stSlideVariant+  if speakerNotes+     then case slideVariant of+               RevealJsSlides -> addAttrs opts' attr $+                           H5.aside contents'+               DZSlides       -> do+                 t <- addAttrs opts' attr $+                             H5.div contents'+                 return $ t ! H5.customAttribute "role" "note"+               NoSlides       -> addAttrs opts' attr $+                           H.div contents'+               _              -> return mempty+     else addAttrs opts (ident, classes', kvs) $+              divtag contents'+blockToHtml opts (RawBlock f str) = do+  ishtml <- isRawHtml f+  if ishtml+     then return $ preEscapedString str+     else if (f == Format "latex" || f == Format "tex") &&+             allowsMathEnvironments (writerHTMLMathMethod opts) &&+             isMathEnvironment str+             then blockToHtml opts $ Plain [Math DisplayMath str]+             else do+               report $ BlockNotRendered (RawBlock f str)+               return mempty+blockToHtml _ HorizontalRule = do+  html5 <- gets stHtml5+  return $ if html5 then H5.hr else H.hr+blockToHtml opts (CodeBlock (id',classes,keyvals) rawCode) = do+  let tolhs = isEnabled Ext_literate_haskell opts &&+                any (\c -> map toLower c == "haskell") classes &&+                any (\c -> map toLower c == "literate") classes+      classes' = if tolhs+                    then map (\c -> if map toLower c == "haskell"+                                       then "literatehaskell"+                                       else c) classes+                    else classes+      adjCode  = if tolhs+                    then unlines . map ("> " ++) . lines $ rawCode+                    else rawCode+      hlCode   = if isJust (writerHighlightStyle opts)+                    then highlight (writerSyntaxMap opts) formatHtmlBlock+                            (id',classes',keyvals) adjCode+                    else Left ""+  case hlCode of+         Left msg -> do+           unless (null msg) $+             report $ CouldNotHighlight msg+           addAttrs opts (id',classes,keyvals)+             $ H.pre $ H.code $ toHtml adjCode+         Right h -> modify (\st -> st{ stHighlighting = True }) >>+                    addAttrs opts (id',[],keyvals) h+blockToHtml opts (BlockQuote blocks) = do+  -- in S5, treat list in blockquote specially+  -- if default is incremental, make it nonincremental;+  -- otherwise incremental+  slideVariant <- gets stSlideVariant+  if slideVariant /= NoSlides+     then let inc = not (writerIncremental opts) in+          case blocks of+             [BulletList lst]  -> blockToHtml (opts {writerIncremental = inc})+                                  (BulletList lst)+             [OrderedList attribs lst] ->+                                  blockToHtml (opts {writerIncremental = inc})+                                  (OrderedList attribs lst)+             [DefinitionList lst] ->+                                  blockToHtml (opts {writerIncremental = inc})+                                  (DefinitionList lst)+             _                 -> do contents <- blockListToHtml opts blocks+                                     return $ H.blockquote+                                            $ nl opts >> contents >> nl opts+     else do+       contents <- blockListToHtml opts blocks+       return $ H.blockquote $ nl opts >> contents >> nl opts+blockToHtml opts (Header level attr@(_,classes,_) lst) = do+  contents <- inlineListToHtml opts lst+  secnum <- liftM stSecNum get+  let contents' = if writerNumberSections opts && not (null secnum)+                     && "unnumbered" `notElem` classes+                     then (H.span ! A.class_ "header-section-number" $ toHtml+                          $ showSecNum secnum) >> strToHtml " " >> contents+                     else contents+  inElement <- gets stElement+  (if inElement then return else addAttrs opts attr)+         $ case level of+              1 -> H.h1 contents'+              2 -> H.h2 contents'+              3 -> H.h3 contents'+              4 -> H.h4 contents'+              5 -> H.h5 contents'+              6 -> H.h6 contents'+              _ -> H.p contents'+blockToHtml opts (BulletList lst) = do+  contents <- mapM (blockListToHtml opts) lst+  unordList opts contents+blockToHtml opts (OrderedList (startnum, numstyle, _) lst) = do+  contents <- mapM (blockListToHtml opts) lst+  html5 <- gets stHtml5+  let numstyle' = case numstyle of+                       Example -> "decimal"+                       _       -> camelCaseToHyphenated $ show numstyle+  let attribs = ([A.start $ toValue startnum | startnum /= 1]) +++                ([A.class_ "example" | numstyle == Example]) +++                (if numstyle /= DefaultStyle+                   then if html5+                           then [A.type_ $+                                 case numstyle of+                                      Decimal    -> "1"+                                      LowerAlpha -> "a"+                                      UpperAlpha -> "A"+                                      LowerRoman -> "i"+                                      UpperRoman -> "I"+                                      _          -> "1"]+                           else [A.style $ toValue $ "list-style-type: " +++                                   numstyle']+                   else [])+  l <- ordList opts contents+  return $ foldl (!) l attribs+blockToHtml opts (DefinitionList lst) = do+  contents <- mapM (\(term, defs) ->+                  do term' <- if null term+                                 then return mempty+                                 else liftM H.dt $ inlineListToHtml opts term+                     defs' <- mapM (liftM (\x -> H.dd $ (x >> nl opts)) .+                                    blockListToHtml opts) defs+                     return $ mconcat $ nl opts : term' : nl opts :+                                        intersperse (nl opts) defs') lst+  defList opts contents+blockToHtml opts (Table capt aligns widths headers rows') = do+  captionDoc <- if null capt+                   then return mempty+                   else do+                     cs <- inlineListToHtml opts capt+                     return $ H.caption cs >> nl opts+  html5 <- gets stHtml5+  let percent w = show (truncate (100*w) :: Integer) ++ "%"+  let coltags = if all (== 0.0) widths+                   then mempty+                   else do+                     H.colgroup $ do+                       nl opts+                       mapM_ (\w -> do+                            if html5+                               then H.col ! A.style (toValue $ "width: " +++                                                      percent w)+                               else H.col ! A.width (toValue $ percent w)+                            nl opts) widths+                     nl opts+  head' <- if all null headers+              then return mempty+              else do+                contents <- tableRowToHtml opts aligns 0 headers+                return $ H.thead (nl opts >> contents) >> nl opts+  body' <- liftM (\x -> H.tbody (nl opts >> mconcat x)) $+               zipWithM (tableRowToHtml opts aligns) [1..] rows'+  let tbl = H.table $+              nl opts >> captionDoc >> coltags >> head' >> body' >> nl opts+  let totalWidth = sum widths+  -- When widths of columns are < 100%, we need to set width for the whole+  -- table, or some browsers give us skinny columns with lots of space between:+  return $ if totalWidth == 0 || totalWidth == 1+              then tbl+              else tbl ! A.style (toValue $ "width:" +++                              show (round (totalWidth * 100) :: Int) ++ "%;")++tableRowToHtml :: PandocMonad m+               => WriterOptions+               -> [Alignment]+               -> Int+               -> [[Block]]+               -> StateT WriterState m Html+tableRowToHtml opts aligns rownum cols' = do+  let mkcell = if rownum == 0 then H.th else H.td+  let rowclass = case rownum of+                      0 -> "header"+                      x | x `rem` 2 == 1 -> "odd"+                      _ -> "even"+  cols'' <- zipWithM+            (\alignment item -> tableItemToHtml opts mkcell alignment item)+            aligns cols'+  return $ (H.tr ! A.class_ rowclass $ nl opts >> mconcat cols'')+          >> nl opts++alignmentToString :: Alignment -> [Char]+alignmentToString alignment = case alignment of+                                 AlignLeft    -> "left"+                                 AlignRight   -> "right"+                                 AlignCenter  -> "center"+                                 AlignDefault -> ""++tableItemToHtml :: PandocMonad m+                => WriterOptions+                -> (Html -> Html)+                -> Alignment+                -> [Block]+                -> StateT WriterState m Html+tableItemToHtml opts tag' align' item = do+  contents <- blockListToHtml opts item+  html5 <- gets stHtml5+  let alignStr = alignmentToString align'+  let attribs = if html5+                   then A.style (toValue $ "text-align: " ++ alignStr ++ ";")+                   else A.align (toValue alignStr)+  let tag'' = if null alignStr+                 then tag'+                 else tag' ! attribs+  return $ (+              tag'' contents) >> nl opts++toListItems :: WriterOptions -> [Html] -> [Html]+toListItems opts items = map (toListItem opts) items ++ [nl opts]++toListItem :: WriterOptions -> Html -> Html+toListItem opts item = nl opts >> H.li item++blockListToHtml :: PandocMonad m => WriterOptions -> [Block] -> StateT WriterState m Html+blockListToHtml opts lst =+  (mconcat . intersperse (nl opts)) <$> mapM (blockToHtml opts) lst++-- | Convert list of Pandoc inline elements to HTML.+inlineListToHtml :: PandocMonad m => WriterOptions -> [Inline] -> StateT WriterState m Html+inlineListToHtml opts lst =+  mapM (inlineToHtml opts) lst >>= return . mconcat++-- | Annotates a MathML expression with the tex source+annotateMML :: XML.Element -> String -> XML.Element+annotateMML e tex = math (unode "semantics" [cs, unode "annotation" (annotAttrs, tex)])+  where+    cs = case elChildren e of+          []  -> unode "mrow" ()+          [x] -> x+          xs  -> unode "mrow" xs+    math childs = XML.Element q as [XML.Elem childs] l+      where+        (XML.Element q as _ l) = e+    annotAttrs = [XML.Attr (unqual "encoding") "application/x-tex"]+++-- | Convert Pandoc inline element to HTML.+inlineToHtml :: PandocMonad m+             => WriterOptions -> Inline -> StateT WriterState m Html+inlineToHtml opts inline = do+  html5 <- gets stHtml5+  case inline of+    (Str str)        -> return $ strToHtml str+    Space          -> return $ strToHtml " "+    SoftBreak      -> return $ case writerWrapText opts of+                                     WrapNone     -> preEscapedString " "+                                     WrapAuto     -> preEscapedString " "+                                     WrapPreserve -> preEscapedString "\n"+    LineBreak      -> return $ (if html5 then H5.br else H.br)+                                 <> strToHtml "\n"+    (Span (id',classes,kvs) ils)+                     -> inlineListToHtml opts ils >>=+                           addAttrs opts attr' . H.span+                        where attr' = (id',classes',kvs')+                              classes' = filter (`notElem` ["csl-no-emph",+                                              "csl-no-strong",+                                              "csl-no-smallcaps"]) classes+                              kvs' = if null styles+                                        then kvs+                                        else ("style", concat styles) : kvs+                              styles = ["font-style:normal;"+                                         | "csl-no-emph" `elem` classes]+                                    ++ ["font-weight:normal;"+                                         | "csl-no-strong" `elem` classes]+                                    ++ ["font-variant:normal;"+                                         | "csl-no-smallcaps" `elem` classes]+    (Emph lst)       -> inlineListToHtml opts lst >>= return . H.em+    (Strong lst)     -> inlineListToHtml opts lst >>= return . H.strong+    (Code attr str)  -> case hlCode of+                             Left msg -> do+                               unless (null msg) $+                                 report $ CouldNotHighlight msg+                               addAttrs opts attr $ H.code $ strToHtml str+                             Right h -> do+                               modify $ \st -> st{ stHighlighting = True }+                               addAttrs opts (id',[],keyvals) h+                        where (id',_,keyvals) = attr+                              hlCode = if isJust (writerHighlightStyle opts)+                                          then highlight+                                                 (writerSyntaxMap opts)+                                                 formatHtmlInline attr str+                                          else Left ""+    (Strikeout lst)  -> inlineListToHtml opts lst >>=+                        return . H.del+    (SmallCaps lst)   -> inlineListToHtml opts lst >>=+                         return . (H.span ! A.class_ "smallcaps")+    (Superscript lst) -> inlineListToHtml opts lst >>= return . H.sup+    (Subscript lst)   -> inlineListToHtml opts lst >>= return . H.sub+    (Quoted quoteType lst) ->+                        let (leftQuote, rightQuote) = case quoteType of+                              SingleQuote -> (strToHtml "‘",+                                              strToHtml "’")+                              DoubleQuote -> (strToHtml "“",+                                              strToHtml "”")+                        in  if writerHtmlQTags opts+                               then do+                                 modify $ \st -> st{ stQuotes = True }+                                 H.q `fmap` inlineListToHtml opts lst+                               else (\x -> leftQuote >> x >> rightQuote)+                                    `fmap` inlineListToHtml opts lst+    (Math t str) -> do+      modify (\st -> st {stMath = True})+      let mathClass = toValue $ ("math " :: String) +++                      if t == InlineMath then "inline" else "display"+      case writerHTMLMathMethod opts of+           LaTeXMathML _ ->+              -- putting LaTeXMathML in container with class "LaTeX" prevents+              -- non-math elements on the page from being treated as math by+              -- the javascript+              return $ H.span ! A.class_ "LaTeX" $+                     case t of+                       InlineMath  -> toHtml ("$" ++ str ++ "$")+                       DisplayMath -> toHtml ("$$" ++ str ++ "$$")+           JsMath _ -> do+              let m = preEscapedString str+              return $ case t of+                       InlineMath  -> H.span ! A.class_ mathClass $ m+                       DisplayMath -> H.div ! A.class_ mathClass $ m+           WebTeX url -> do+              let imtag = if html5 then H5.img else H.img+              let m = imtag ! A.style "vertical-align:middle"+                            ! A.src (toValue $ url ++ urlEncode str)+                            ! A.alt (toValue str)+                            ! A.title (toValue str)+              let brtag = if html5 then H5.br else H.br+              return $ case t of+                        InlineMath  -> m+                        DisplayMath -> brtag >> m >> brtag+           GladTeX ->+              return $ case t of+                         InlineMath -> preEscapedString $ "<EQ ENV=\"math\">" ++ str ++ "</EQ>"+                         DisplayMath -> preEscapedString $ "<EQ ENV=\"displaymath\">" ++ str ++ "</EQ>"+           MathML -> do+              let conf = useShortEmptyTags (const False)+                           defaultConfigPP+              res <- lift $ convertMath writeMathML t str+              case res of+                    Right r  -> return $ preEscapedString $+                        ppcElement conf (annotateMML r str)+                    Left il  -> (H.span ! A.class_ mathClass) <$>+                                   inlineToHtml opts il+           MathJax _ -> return $ H.span ! A.class_ mathClass $ toHtml $+              case t of+                InlineMath  -> "\\(" ++ str ++ "\\)"+                DisplayMath -> "\\[" ++ str ++ "\\]"+           KaTeX _ -> return $ H.span ! A.class_ mathClass $ toHtml $+              case t of+                InlineMath  -> "\\(" ++ str ++ "\\)"+                DisplayMath -> "\\[" ++ str ++ "\\]"+           PlainMath -> do+              x <- lift (texMathToInlines t str) >>= inlineListToHtml opts+              let m = H.span ! A.class_ mathClass $ x+              let brtag = if html5 then H5.br else H.br+              return  $ case t of+                         InlineMath  -> m+                         DisplayMath -> brtag >> m >> brtag+    (RawInline f str) -> do+      ishtml <- isRawHtml f+      if ishtml+         then return $ preEscapedString str+         else if (f == Format "latex" || f == Format "tex") &&+                "\\begin" `isPrefixOf` str &&+                allowsMathEnvironments (writerHTMLMathMethod opts) &&+                isMathEnvironment str+                then inlineToHtml opts $ Math DisplayMath str+                else do+                  report $ InlineNotRendered inline+                  return mempty+    (Link attr txt (s,_)) | "mailto:" `isPrefixOf` s -> do+                        linkText <- inlineListToHtml opts txt+                        obfuscateLink opts attr linkText s+    (Link (ident,classes,kvs) txt (s,tit)) -> do+                        linkText <- inlineListToHtml opts txt+                        slideVariant <- gets stSlideVariant+                        let s' = case s of+                                   '#':xs -> let prefix = if slideVariant == RevealJsSlides+                                                             then "/"+                                                             else writerIdentifierPrefix opts+                                             in  '#' : prefix ++ xs+                                   _ -> s+                        let link = H.a ! A.href (toValue s') $ linkText+                        let attr = if txt == [Str (unEscapeString s)]+                                      then (ident, "uri" : classes, kvs)+                                      else (ident, classes, kvs)+                        link' <- addAttrs opts attr link+                        return $ if null tit+                                    then link'+                                    else link' ! A.title (toValue tit)+    (Image attr txt (s,tit)) | treatAsImage s -> do+                        let alternate' = stringify txt+                        slideVariant <- gets stSlideVariant+                        let isReveal = slideVariant == RevealJsSlides+                        attrs <- imgAttrsToHtml opts attr+                        let attributes =+                              -- reveal.js uses data-src for lazy loading+                              (if isReveal+                                  then customAttribute "data-src" $ toValue s+                                  else A.src $ toValue s) :+                              [A.title $ toValue tit | not (null tit)] +++                              [A.alt $ toValue alternate' | not (null txt)] +++                              attrs+                        let tag = if html5 then H5.img else H.img+                        return $ foldl (!) tag attributes+                        -- note:  null title included, as in Markdown.pl+    (Image attr _ (s,tit)) -> do+                        slideVariant <- gets stSlideVariant+                        let isReveal = slideVariant == RevealJsSlides+                        attrs <- imgAttrsToHtml opts attr+                        let attributes =+                              (if isReveal+                                  then customAttribute "data-src" $ toValue s+                                  else A.src $ toValue s) :+                              [A.title $ toValue tit | not (null tit)] +++                              attrs+                        return $ foldl (!) H5.embed attributes+                        -- note:  null title included, as in Markdown.pl+    (Note contents) -> do+                        notes <- gets stNotes+                        let number = length notes + 1+                        let ref = show number+                        htmlContents <- blockListToNote opts ref contents+                        epubVersion <- gets stEPUBVersion+                        -- push contents onto front of notes+                        modify $ \st -> st {stNotes = htmlContents:notes}+                        slideVariant <- gets stSlideVariant+                        let revealSlash = ['/' | slideVariant == RevealJsSlides]+                        let link = H.a ! A.href (toValue $ "#" +++                                         revealSlash +++                                         writerIdentifierPrefix opts ++ "fn" ++ ref)+                                       ! A.class_ "footnoteRef"+                                       ! prefixedId opts ("fnref" ++ ref)+                                       $ (if isJust epubVersion+                                             then id+                                             else H.sup)+                                       $ toHtml ref+                        return $ case epubVersion of+                                      Just EPUB3 -> link ! customAttribute "epub:type" "noteref"+                                      _          -> link+    (Cite cits il)-> do contents <- inlineListToHtml opts il+                        let citationIds = unwords $ map citationId cits+                        let result = H.span ! A.class_ "citation" $ contents+                        return $ if html5+                                    then result ! customAttribute "data-cites" (toValue citationIds)+                                    else result++blockListToNote :: PandocMonad m => WriterOptions -> String -> [Block] -> StateT WriterState m Html+blockListToNote opts ref blocks =+  -- If last block is Para or Plain, include the backlink at the end of+  -- that block. Otherwise, insert a new Plain block with the backlink.+  let backlink = [Link ("",["footnoteBack"],[]) [Str "↩"] ("#" ++ writerIdentifierPrefix opts ++ "fnref" ++ ref,[])]+      blocks'  = if null blocks+                    then []+                    else let lastBlock   = last blocks+                             otherBlocks = init blocks+                         in  case lastBlock of+                                  (Para lst)  -> otherBlocks +++                                                 [Para (lst ++ backlink)]+                                  (Plain lst) -> otherBlocks +++                                                 [Plain (lst ++ backlink)]+                                  _           -> otherBlocks ++ [lastBlock,+                                                 Plain backlink]+  in  do contents <- blockListToHtml opts blocks'+         let noteItem = H.li ! prefixedId opts ("fn" ++ ref) $ contents+         epubVersion <- gets stEPUBVersion+         let noteItem' = case epubVersion of+                              Just EPUB3 -> noteItem ! customAttribute "epub:type" "footnote"+                              _          -> noteItem+         return $ nl opts >> noteItem'++isMathEnvironment :: String -> Bool+isMathEnvironment s = "\\begin{" `isPrefixOf` s &&+                         envName `elem` mathmlenvs+  where envName = takeWhile (/= '}') (drop 7 s)+        mathmlenvs = [ "align"+                     , "align*"+                     , "alignat"+                     , "alignat*"+                     , "aligned"+                     , "alignedat"+                     , "array"+                     , "Bmatrix"+                     , "bmatrix"+                     , "cases"+                     , "CD"+                     , "eqnarray"+                     , "eqnarray*"+                     , "equation"+                     , "equation*"+                     , "gather"+                     , "gather*"+                     , "gathered"+                     , "matrix"+                     , "multline"+                     , "multline*"+                     , "pmatrix"+                     , "smallmatrix"+                     , "split"+                     , "subarray"+                     , "Vmatrix"+                     , "vmatrix" ]++allowsMathEnvironments :: HTMLMathMethod -> Bool+allowsMathEnvironments (MathJax _) = True+allowsMathEnvironments MathML      = True+allowsMathEnvironments (WebTeX _)  = True+allowsMathEnvironments _           = False++isRawHtml :: PandocMonad m => Format -> StateT WriterState m Bool+isRawHtml f = do+  html5 <- gets stHtml5+  return $ f == Format "html" ||+           ((html5 && f == Format "html5") || f == Format "html4")++html5Attributes :: Set.Set String+html5Attributes = Set.fromList+  [ "abbr"+  , "accept"+  , "accept-charset"+  , "accesskey"+  , "action"+  , "allowfullscreen"+  , "allowpaymentrequest"+  , "allowusermedia"+  , "alt"+  , "as"+  , "async"+  , "autocomplete"+  , "autofocus"+  , "autoplay"+  , "charset"+  , "checked"+  , "cite"+  , "class"+  , "color"+  , "cols"+  , "colspan"+  , "content"+  , "contenteditable"+  , "controls"+  , "coords"+  , "crossorigin"+  , "data"+  , "datetime"+  , "default"+  , "defer"+  , "dir"+  , "dirname"+  , "disabled"+  , "download"+  , "draggable"+  , "enctype"+  , "for"+  , "form"+  , "formaction"+  , "formenctype"+  , "formmethod"+  , "formnovalidate"+  , "formtarget"+  , "headers"+  , "height"+  , "hidden"+  , "high"+  , "href"+  , "hreflang"+  , "http-equiv"+  , "id"+  , "inputmode"+  , "integrity"+  , "is"+  , "ismap"+  , "itemid"+  , "itemprop"+  , "itemref"+  , "itemscope"+  , "itemtype"+  , "kind"+  , "label"+  , "lang"+  , "list"+  , "loop"+  , "low"+  , "manifest"+  , "max"+  , "maxlength"+  , "media"+  , "method"+  , "min"+  , "minlength"+  , "multiple"+  , "muted"+  , "name"+  , "nomodule"+  , "nonce"+  , "novalidate"+  , "onabort"+  , "onafterprint"+  , "onauxclick"+  , "onbeforeprint"+  , "onbeforeunload"+  , "onblur"+  , "oncancel"+  , "oncanplay"+  , "oncanplaythrough"+  , "onchange"+  , "onclick"+  , "onclose"+  , "oncontextmenu"+  , "oncopy"+  , "oncuechange"+  , "oncut"+  , "ondblclick"+  , "ondrag"+  , "ondragend"+  , "ondragenter"+  , "ondragexit"+  , "ondragleave"+  , "ondragover"+  , "ondragstart"+  , "ondrop"+  , "ondurationchange"+  , "onemptied"+  , "onended"+  , "onerror"+  , "onfocus"+  , "onhashchange"+  , "oninput"+  , "oninvalid"+  , "onkeydown"+  , "onkeypress"+  , "onkeyup"+  , "onlanguagechange"+  , "onload"+  , "onloadeddata"+  , "onloadedmetadata"+  , "onloadend"+  , "onloadstart"+  , "onmessage"+  , "onmessageerror"+  , "onmousedown"+  , "onmouseenter"+  , "onmouseleave"+  , "onmousemove"+  , "onmouseout"+  , "onmouseover"+  , "onmouseup"+  , "onoffline"+  , "ononline"+  , "onpagehide"+  , "onpageshow"+  , "onpaste"+  , "onpause"+  , "onplay"+  , "onplaying"+  , "onpopstate"+  , "onprogress"+  , "onratechange"+  , "onrejectionhandled"+  , "onreset"+  , "onresize"+  , "onscroll"+  , "onsecuritypolicyviolation"+  , "onseeked"+  , "onseeking"+  , "onselect"+  , "onstalled"+  , "onstorage"+  , "onsubmit"+  , "onsuspend"+  , "ontimeupdate"+  , "ontoggle"+  , "onunhandledrejection"+  , "onunload"+  , "onvolumechange"+  , "onwaiting"+  , "onwheel"+  , "open"+  , "optimum"+  , "pattern"+  , "ping"+  , "placeholder"+  , "playsinline"+  , "poster"+  , "preload"+  , "readonly"+  , "referrerpolicy"+  , "rel"+  , "required"+  , "reversed"+  , "rows"+  , "rowspan"+  , "sandbox"+  , "scope"+  , "selected"+  , "shape"+  , "size"+  , "sizes"+  , "slot"+  , "span"+  , "spellcheck"+  , "src"+  , "srcdoc"+  , "srclang"+  , "srcset"+  , "start"+  , "step"+  , "style"+  , "tabindex"+  , "target"+  , "title"+  , "translate"+  , "type"+  , "typemustmatch"+  , "updateviacache"+  , "usemap"+  , "value"+  , "width"+  , "workertype"+  , "wrap"+  ]
src/Text/Pandoc/Writers/Haddock.hs view
@@ -1,6 +1,8 @@-{-# LANGUAGE OverloadedStrings, TupleSections, ScopedTypeVariables #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TupleSections       #-} {--Copyright (C) 2014 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2014-2015, 2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -19,7 +21,7 @@  {- |    Module      : Text.Pandoc.Writers.Haddock-   Copyright   : Copyright (C) 2014 John MacFarlane+   Copyright   : Copyright (C) 2014-2015,2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -31,17 +33,19 @@ Haddock:  <http://www.haskell.org/haddock/doc/html/> -} module Text.Pandoc.Writers.Haddock (writeHaddock) where+import Control.Monad.State.Strict+import Data.Default+import Data.List (intersperse, transpose)+import Data.Text (Text)+import Text.Pandoc.Class (PandocMonad, report) import Text.Pandoc.Definition-import Text.Pandoc.Templates (renderTemplate')-import Text.Pandoc.Shared-import Text.Pandoc.Writers.Shared+import Text.Pandoc.Logging import Text.Pandoc.Options-import Data.List ( intersperse, transpose ) import Text.Pandoc.Pretty-import Control.Monad.State-import Text.Pandoc.Readers.TeXMath (texMathToInlines)-import Network.URI (isURI)-import Data.Default+import Text.Pandoc.Shared+import Text.Pandoc.Templates (renderTemplate')+import Text.Pandoc.Writers.Math (texMathToInlines)+import Text.Pandoc.Writers.Shared  type Notes = [[Block]] data WriterState = WriterState { stNotes :: Notes }@@ -49,13 +53,14 @@   where def = WriterState{ stNotes = [] }  -- | Convert Pandoc to Haddock.-writeHaddock :: WriterOptions -> Pandoc -> String+writeHaddock :: PandocMonad m => WriterOptions -> Pandoc -> m Text writeHaddock opts document =-  evalState (pandocToHaddock opts{+  evalStateT (pandocToHaddock opts{                   writerWrapText = writerWrapText opts } document) def  -- | Return haddock representation of document.-pandocToHaddock :: WriterOptions -> Pandoc -> State WriterState String+pandocToHaddock :: PandocMonad m+                => WriterOptions -> Pandoc -> StateT WriterState m Text pandocToHaddock opts (Pandoc meta blocks) = do   let colwidth = if writerWrapText opts == WrapAuto                     then Just $ writerColumns opts@@ -63,22 +68,22 @@   body <- blockListToHaddock opts blocks   st <- get   notes' <- notesToHaddock opts (reverse $ stNotes st)-  let render' :: Doc -> String+  let render' :: Doc -> Text       render' = render colwidth   let main = render' $ body <>                (if isEmpty notes' then empty else blankline <> notes')   metadata <- metaToJSON opts-               (fmap (render colwidth) . blockListToHaddock opts)-               (fmap (render colwidth) . inlineListToHaddock opts)+               (fmap render' . blockListToHaddock opts)+               (fmap render' . inlineListToHaddock opts)                meta-  let context  = defField "body" main-               $ metadata+  let context  = defField "body" main metadata   case writerTemplate opts of           Nothing  -> return main-          Just tpl -> return $ renderTemplate' tpl context+          Just tpl -> renderTemplate' tpl context  -- | Return haddock representation of notes.-notesToHaddock :: WriterOptions -> [[Block]] -> State WriterState Doc+notesToHaddock :: PandocMonad m+               => WriterOptions -> [[Block]] -> StateT WriterState m Doc notesToHaddock opts notes =   if null notes      then return empty@@ -92,9 +97,10 @@   where haddockEscapes = backslashEscapes "\\/'`\"@<"  -- | Convert Pandoc block element to haddock.-blockToHaddock :: WriterOptions -- ^ Options-                -> Block         -- ^ Block element-                -> State WriterState Doc+blockToHaddock :: PandocMonad m+               => WriterOptions -- ^ Options+               -> Block         -- ^ Block element+               -> StateT WriterState m Doc blockToHaddock _ Null = return empty blockToHaddock opts (Div _ ils) = do   contents <- blockListToHaddock opts ils@@ -110,10 +116,12 @@   (<> blankline) `fmap` blockToHaddock opts (Plain inlines) blockToHaddock opts (LineBlock lns) =   blockToHaddock opts $ linesToPara lns-blockToHaddock _ (RawBlock f str)-  | f == "haddock" = do+blockToHaddock _ b@(RawBlock f str)+  | f == "haddock" =       return $ text str <> text "\n"-  | otherwise = return empty+  | otherwise = do+    report $ BlockNotRendered b+    return empty blockToHaddock opts HorizontalRule =   return $ blankline <> text (replicate (writerColumns opts) '_') <> blankline blockToHaddock opts (Header level (ident,_,_) inlines) = do@@ -141,16 +149,16 @@       isPlainBlock _         = False   let hasBlocks = not (all isPlainBlock $ concat . concat $ headers:rows)   (nst,tbl) <- case True of-                _ | isSimple -> fmap (nest 2,) $+                _ | isSimple -> (nest 2,) <$>                          pandocTable opts (all null headers) aligns widths                              rawHeaders rawRows-                  | not hasBlocks -> fmap (nest 2,) $+                  | not hasBlocks -> (nest 2,) <$>                          pandocTable opts (all null headers) aligns widths                              rawHeaders rawRows-                  | otherwise -> fmap (id,) $-                         gridTable opts (all null headers) aligns widths-                             rawHeaders rawRows-  return $ (prefixed "> " $ nst $ tbl $$ blankline $$ caption'') $$ blankline+                  | otherwise -> (id,) <$>+                         gridTable opts blockListToHaddock+                          (all null headers) aligns widths headers rows+  return $ prefixed "> " (nst $ tbl $$ blankline $$ caption'') $$ blankline blockToHaddock opts (BulletList items) = do   contents <- mapM (bulletListItemToHaddock opts) items   return $ cat contents <> blankline@@ -160,15 +168,16 @@   let markers' = map (\m -> if length m < 3                                then m ++ replicate (3 - length m) ' '                                else m) markers-  contents <- mapM (\(item, num) -> orderedListItemToHaddock opts item num) $+  contents <- mapM (uncurry (orderedListItemToHaddock opts)) $               zip markers' items   return $ cat contents <> blankline blockToHaddock opts (DefinitionList items) = do   contents <- mapM (definitionListItemToHaddock opts) items   return $ cat contents <> blankline -pandocTable :: WriterOptions -> Bool -> [Alignment] -> [Double]-            -> [Doc] -> [[Doc]] -> State WriterState Doc+pandocTable :: PandocMonad m+            => WriterOptions -> Bool -> [Alignment] -> [Double]+            -> [Doc] -> [[Doc]] -> StateT WriterState m Doc pandocTable opts headless aligns widths rawHeaders rawRows =  do   let isSimple = all (==0) widths   let alignHeader alignment = case alignment of@@ -184,18 +193,17 @@                               (floor . (fromIntegral (writerColumns opts) *))                               widths   let makeRow = hcat . intersperse (lblock 1 (text " ")) .-                   (zipWith3 alignHeader aligns widthsInChars)+                   zipWith3 alignHeader aligns widthsInChars   let rows' = map makeRow rawRows   let head' = makeRow rawHeaders   let maxRowHeight = maximum $ map height (head':rows')   let underline = cat $ intersperse (text " ") $                   map (\width -> text (replicate width '-')) widthsInChars-  let border = if maxRowHeight > 1-                  then text (replicate (sum widthsInChars +-                          length widthsInChars - 1) '-')-                  else if headless-                          then underline-                          else empty+  let border+        | maxRowHeight > 1 = text (replicate (sum widthsInChars ++                 length widthsInChars - 1) '-')+        | headless = underline+        | otherwise = empty   let head'' = if headless                   then empty                   else border <> cr <> head'@@ -207,35 +215,9 @@                   else border   return $ head'' $$ underline $$ body $$ bottom -gridTable :: WriterOptions -> Bool -> [Alignment] -> [Double]-          -> [Doc] -> [[Doc]] -> State WriterState Doc-gridTable opts headless _aligns widths headers' rawRows =  do-  let numcols = length headers'-  let widths' = if all (==0) widths-                   then replicate numcols (1.0 / fromIntegral numcols)-                   else widths-  let widthsInChars = map (floor . (fromIntegral (writerColumns opts) *)) widths'-  let hpipeBlocks blocks = hcat [beg, middle, end]-        where h       = maximum (map height blocks)-              sep'    = lblock 3 $ vcat (map text $ replicate h " | ")-              beg     = lblock 2 $ vcat (map text $ replicate h "| ")-              end     = lblock 2 $ vcat (map text $ replicate h " |")-              middle  = chomp $ hcat $ intersperse sep' blocks-  let makeRow = hpipeBlocks . zipWith lblock widthsInChars-  let head' = makeRow headers'-  let rows' = map (makeRow . map chomp) rawRows-  let border ch = char '+' <> char ch <>-                  (hcat $ intersperse (char ch <> char '+' <> char ch) $-                          map (\l -> text $ replicate l ch) widthsInChars) <>-                  char ch <> char '+'-  let body = vcat $ intersperse (border '-') rows'-  let head'' = if headless-                  then empty-                  else head' $$ border '='-  return $ border '-' $$ head'' $$ body $$ border '-'- -- | Convert bullet list item (list of blocks) to haddock-bulletListItemToHaddock :: WriterOptions -> [Block] -> State WriterState Doc+bulletListItemToHaddock :: PandocMonad m+                        => WriterOptions -> [Block] -> StateT WriterState m Doc bulletListItemToHaddock opts items = do   contents <- blockListToHaddock opts items   let sps = replicate (writerTabStop opts - 2) ' '@@ -250,22 +232,24 @@   return $ hang (writerTabStop opts) start $ contents' <> cr  -- | Convert ordered list item (a list of blocks) to haddock-orderedListItemToHaddock :: WriterOptions -- ^ options-                          -> String        -- ^ list item marker-                          -> [Block]       -- ^ list item (list of blocks)-                          -> State WriterState Doc+orderedListItemToHaddock :: PandocMonad m+                         => WriterOptions -- ^ options+                         -> String        -- ^ list item marker+                         -> [Block]       -- ^ list item (list of blocks)+                         -> StateT WriterState m Doc orderedListItemToHaddock opts marker items = do   contents <- blockListToHaddock opts items   let sps = case length marker - writerTabStop opts of                    n | n > 0 -> text $ replicate n ' '-                   _         -> text " "+                   _ -> text " "   let start = text marker <> sps   return $ hang (writerTabStop opts) start $ contents <> cr  -- | Convert definition list item (label, list of blocks) to haddock-definitionListItemToHaddock :: WriterOptions-                             -> ([Inline],[[Block]])-                             -> State WriterState Doc+definitionListItemToHaddock :: PandocMonad m+                            => WriterOptions+                            -> ([Inline],[[Block]])+                            -> StateT WriterState m Doc definitionListItemToHaddock opts (label, defs) = do   labelText <- inlineListToHaddock opts label   defs' <- mapM (mapM (blockToHaddock opts)) defs@@ -273,19 +257,22 @@   return $ nowrap (brackets labelText) <> cr <> contents <> cr  -- | Convert list of Pandoc block elements to haddock-blockListToHaddock :: WriterOptions -- ^ Options-                    -> [Block]       -- ^ List of block elements-                    -> State WriterState Doc+blockListToHaddock :: PandocMonad m+                   => WriterOptions -- ^ Options+                   -> [Block]       -- ^ List of block elements+                   -> StateT WriterState m Doc blockListToHaddock opts blocks =   mapM (blockToHaddock opts) blocks >>= return . cat  -- | Convert list of Pandoc inline elements to haddock.-inlineListToHaddock :: WriterOptions -> [Inline] -> State WriterState Doc+inlineListToHaddock :: PandocMonad m+                    => WriterOptions -> [Inline] -> StateT WriterState m Doc inlineListToHaddock opts lst =   mapM (inlineToHaddock opts) lst >>= return . cat  -- | Convert Pandoc inline element to haddock.-inlineToHaddock :: WriterOptions -> Inline -> State WriterState Doc+inlineToHaddock :: PandocMonad m+                => WriterOptions -> Inline -> StateT WriterState m Doc inlineToHaddock opts (Span (ident,_,_) ils) = do   contents <- inlineListToHaddock opts ils   if not (null ident) && null ils@@ -315,18 +302,20 @@   return $ "“" <> contents <> "”" inlineToHaddock _ (Code _ str) =   return $ "@" <> text (escapeString str) <> "@"-inlineToHaddock _ (Str str) = do+inlineToHaddock _ (Str str) =   return $ text $ escapeString str inlineToHaddock opts (Math mt str) = do   let adjust x = case mt of                       DisplayMath -> cr <> x <> cr                       InlineMath  -> x-  adjust `fmap` (inlineListToHaddock opts $ texMathToInlines mt str)-inlineToHaddock _ (RawInline f str)+  adjust <$> (lift (texMathToInlines mt str) >>= inlineListToHaddock opts)+inlineToHaddock _ il@(RawInline f str)   | f == "haddock" = return $ text str-  | otherwise = return empty+  | otherwise = do+    report $ InlineNotRendered il+    return empty -- no line break in haddock (see above on CodeBlock)-inlineToHaddock _ (LineBreak) = return cr+inlineToHaddock _ LineBreak = return cr inlineToHaddock opts SoftBreak =   case writerWrapText opts of        WrapAuto     -> return space@@ -339,7 +328,7 @@   let useAuto = isURI src &&                 case txt of                       [Str s] | escapeURI s == src -> True-                      _                            -> False+                      _       -> False   return $ nowrap $ "<" <> text src <>            (if useAuto then empty else space <> linktext) <> ">" inlineToHaddock opts (Image attr alternate (source, tit)) = do
src/Text/Pandoc/Writers/ICML.hs view
@@ -1,8 +1,10 @@-{-# LANGUAGE OverloadedStrings, FlexibleContexts #-}+{-# LANGUAGE FlexibleContexts    #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE ScopedTypeVariables #-}  {- |    Module      : Text.Pandoc.Writers.ICML-   Copyright   : Copyright (C) 2013-2016 github.com/mb21+   Copyright   : Copyright (C) 2013-2017 github.com/mb21    License     : GNU GPL, version 2 or above     Stability   : alpha@@ -14,20 +16,25 @@ into InDesign with File -> Place. -} module Text.Pandoc.Writers.ICML (writeICML) where+import Control.Monad.Except (catchError)+import Control.Monad.State.Strict+import Data.List (intersperse, isInfixOf, isPrefixOf, stripPrefix)+import Data.Maybe (fromMaybe)+import qualified Data.Set as Set+import Data.Text as Text (breakOnAll, pack)+import Data.Text (Text)+import Text.Pandoc.Class (PandocMonad, report)+import qualified Text.Pandoc.Class as P import Text.Pandoc.Definition-import Text.Pandoc.XML-import Text.Pandoc.Readers.TeXMath (texMathToInlines)-import Text.Pandoc.Writers.Shared-import Text.Pandoc.Shared (linesToPara, splitBy, fetchItem, warn)+import Text.Pandoc.ImageSize+import Text.Pandoc.Logging import Text.Pandoc.Options-import Text.Pandoc.Templates (renderTemplate') import Text.Pandoc.Pretty-import Text.Pandoc.ImageSize-import Data.List (isPrefixOf, isInfixOf, stripPrefix, intersperse)-import Data.Text as Text (breakOnAll, pack)-import Control.Monad.State-import Network.URI (isURI)-import qualified Data.Set as Set+import Text.Pandoc.Shared (isURI, linesToPara, splitBy)+import Text.Pandoc.Templates (renderTemplate')+import Text.Pandoc.Writers.Math (texMathToInlines)+import Text.Pandoc.Writers.Shared+import Text.Pandoc.XML  type Style = [String] type Hyperlink = [(Int, String)]@@ -40,7 +47,7 @@   , maxListDepth :: Int   } -type WS a = StateT WriterState IO a+type WS m = StateT WriterState m  defaultWriterState :: WriterState defaultWriterState = WriterState{@@ -121,13 +128,13 @@ footnoteName      = "Footnote" citeName          = "Cite" - -- | Convert Pandoc document to string in ICML format.-writeICML :: WriterOptions -> Pandoc -> IO String+writeICML :: PandocMonad m => WriterOptions -> Pandoc -> m Text writeICML opts (Pandoc meta blocks) = do   let colwidth = if writerWrapText opts == WrapAuto                     then Just $ writerColumns opts                     else Nothing+      render' :: Doc -> Text       render' = render colwidth       renderMeta f s = liftM (render' . fst) $ runStateT (f opts [] s) defaultWriterState   metadata <- metaToJSON opts@@ -139,18 +146,15 @@       context = defField "body" main               $ defField "charStyles" (render' $ charStylesToDoc st)               $ defField "parStyles"  (render' $ parStylesToDoc st)-              $ defField "hyperlinks" (render' $ hyperlinksToDoc $ links st)-              $ metadata-  return $ case writerTemplate opts of-                Nothing  -> main-                Just tpl -> renderTemplate' tpl context+              $ defField "hyperlinks" (render' $ hyperlinksToDoc $ links st) metadata+  case writerTemplate opts of+       Nothing  -> return main+       Just tpl -> renderTemplate' tpl context  -- | Auxilary functions for parStylesToDoc and charStylesToDoc. contains :: String -> (String, (String, String)) -> [(String, String)] contains s rule =-  if isInfixOf (fst rule) s-     then [snd rule]-     else []+  [snd rule | isInfixOf (fst rule) s]  -- | The monospaced font to use as default. monospacedFont :: Doc@@ -174,7 +178,7 @@   where     makeStyle s =       let countSubStrs sub str = length $ Text.breakOnAll (Text.pack sub) (Text.pack str)-          attrs = concat $ map (contains s) $ [+          attrs = concatMap (contains s) [                                (defListTermName, ("BulletsAndNumberingListType", "BulletList"))                              , (defListTermName, ("FontStyle", "Bold"))                              , (tableHeaderName, ("FontStyle", "Bold"))@@ -200,9 +204,9 @@             where               numbering | isOrderedList = [("NumberingExpression", "^#.^t"), ("NumberingLevel", show nOrds)]                         | otherwise     = []-              listType | isOrderedList && (not $ isInfixOf subListParName s)+              listType | isOrderedList && not (isInfixOf subListParName s)                            = [("BulletsAndNumberingListType", "NumberedList")]-                       | isBulletList && (not $ isInfixOf subListParName s)+                       | isBulletList && not (isInfixOf subListParName s)                            = [("BulletsAndNumberingListType", "BulletList")]                        | otherwise = []               indent = [("LeftIndent", show indt)]@@ -210,9 +214,9 @@                   nBlockQuotes = countSubStrs blockQuoteName s                   nDefLists = countSubStrs defListDefName s                   indt = max 0 $ defaultListIndent*(nBuls + nOrds - 1) + defaultIndent*(nBlockQuotes + nDefLists)-          props = inTags True "Properties" [] $ (basedOn $$ tabList $$ numbForm)+          props = inTags True "Properties" [] (basedOn $$ tabList $$ numbForm)             where-              font = if isInfixOf codeBlockName s+              font = if codeBlockName `isInfixOf` s                         then monospacedFont                         else empty               basedOn = inTags False "BasedOn" [("type", "object")] (text "$ID/NormalParagraphStyle") $$ font@@ -239,7 +243,7 @@ charStylesToDoc st = vcat $ map makeStyle $ Set.toAscList $ inlineStyles st   where     makeStyle s =-      let attrs = concat $ map (contains s) [+      let attrs = concatMap (contains s) [                                (strikeoutName,   ("StrikeThru", "true"))                              , (superscriptName, ("Position", "Superscript"))                              , (subscriptName,   ("Position", "Subscript"))@@ -253,7 +257,7 @@                     inTags False "BasedOn" [("type", "object")] (text "$ID/NormalCharacterStyle") $$ font                   where                     font =-                      if isInfixOf codeName s+                      if codeName `isInfixOf` s                          then monospacedFont                          else empty       in  inTags True "CharacterStyle" ([("Self", "CharacterStyle/"++s), ("Name", s)] ++ attrs') props@@ -273,23 +277,22 @@     hyp (ident, url) = hdest $$ hlink       where         hdest = selfClosingTag "HyperlinkURLDestination"-                  [("Self", "HyperlinkURLDestination/"++(escapeColons url)), ("Name","link"), ("DestinationURL",url), ("DestinationUniqueKey","1")] -- HyperlinkURLDestination with more than one colon crashes CS6+                  [("Self", "HyperlinkURLDestination/"++escapeColons url), ("Name","link"), ("DestinationURL",url), ("DestinationUniqueKey","1")] -- HyperlinkURLDestination with more than one colon crashes CS6         hlink = inTags True "Hyperlink" [("Self","uf-"++show ident),  ("Name",url),                     ("Source","htss-"++show ident), ("Visible","true"), ("DestinationUniqueKey","1")]                   $ inTags True "Properties" []                   $ inTags False "BorderColor" [("type","enumeration")] (text "Black")-                  $$ (inTags False "Destination" [("type","object")]-                  $ text $ "HyperlinkURLDestination/"++(escapeColons (escapeStringForXML url))) -- HyperlinkURLDestination with more than one colon crashes CS6+                  $$ inTags False "Destination" [("type","object")] (text $ "HyperlinkURLDestination/"++(escapeColons (escapeStringForXML url))) -- HyperlinkURLDestination with more than one colon crashes CS6   -- | Convert a list of Pandoc blocks to ICML.-blocksToICML :: WriterOptions -> Style -> [Block] -> WS Doc+blocksToICML :: PandocMonad m => WriterOptions -> Style -> [Block] -> WS m Doc blocksToICML opts style lst = do   docs <- mapM (blockToICML opts style) lst   return $ intersperseBrs docs  -- | Convert a Pandoc block element to ICML.-blockToICML :: WriterOptions -> Style -> Block -> WS Doc+blockToICML :: PandocMonad m => WriterOptions -> Style -> Block -> WS m Doc blockToICML opts style (Plain lst) = parStyle opts style lst -- title beginning with fig: indicates that the image is a figure blockToICML opts style (Para img@[Image _ txt (_,'f':'i':'g':':':_)]) = do@@ -299,10 +302,12 @@ blockToICML opts style (Para lst) = parStyle opts (paragraphName:style) lst blockToICML opts style (LineBlock lns) =   blockToICML opts style $ linesToPara lns-blockToICML opts style (CodeBlock _ str) = parStyle opts (codeBlockName:style) $ [Str str]-blockToICML _ _ (RawBlock f str)+blockToICML opts style (CodeBlock _ str) = parStyle opts (codeBlockName:style) [Str str]+blockToICML _ _ b@(RawBlock f str)   | f == Format "icml" = return $ text str-  | otherwise          = return empty+  | otherwise          = do+      report $ BlockNotRendered b+      return empty blockToICML opts style (BlockQuote blocks) = blocksToICML opts (blockQuoteName:style) blocks blockToICML opts style (OrderedList attribs lst) = listItemsToICML opts orderedListName style (Just attribs) lst blockToICML opts style (BulletList lst) = listItemsToICML opts bulletListName style Nothing lst@@ -343,11 +348,10 @@                     then rows                     else headers:rows       cells <- rowsToICML tabl (0::Int)-      let colWidths w = if w > 0-                           then [("SingleColumnWidth",show $ 500 * w)]-                           else []-      let tupToDoc tup = selfClosingTag "Column" $ [("Name",show $ fst tup)] ++ (colWidths $ snd tup)-      let colDescs = vcat $ map tupToDoc $ zip [0..nrCols-1] widths+      let colWidths w =+            [("SingleColumnWidth",show $ 500 * w) | w > 0]+      let tupToDoc tup = selfClosingTag "Column" $ ("Name",show $ fst tup) : (colWidths $ snd tup)+      let colDescs = vcat $ zipWith (curry tupToDoc) [0..nrCols-1] widths       let tableDoc = return $ inTags True "Table" [                          ("AppliedTableStyle","TableStyle/Table")                        , ("HeaderRowCount", nrHeaders)@@ -359,7 +363,7 @@ blockToICML _ _ Null = return empty  -- | Convert a list of lists of blocks to ICML list items.-listItemsToICML :: WriterOptions -> String -> Style -> Maybe ListAttributes -> [[Block]] -> WS Doc+listItemsToICML :: PandocMonad m => WriterOptions -> String -> Style -> Maybe ListAttributes -> [[Block]] -> WS m Doc listItemsToICML _ _ _ _ [] = return empty listItemsToICML opts listType style attribs (first:rest) = do   st <- get@@ -374,18 +378,17 @@   return $ intersperseBrs docs  -- | Convert a list of blocks to ICML list items.-listItemToICML :: WriterOptions -> Style -> Bool-> Maybe ListAttributes -> [Block] -> WS Doc+listItemToICML :: PandocMonad m => WriterOptions -> Style -> Bool-> Maybe ListAttributes -> [Block] -> WS m Doc listItemToICML opts style isFirst attribs item =   let makeNumbStart (Just (beginsWith, numbStl, _)) =         let doN DefaultStyle = []-            doN LowerRoman = [lowerRomanName]-            doN UpperRoman = [upperRomanName]-            doN LowerAlpha = [lowerAlphaName]-            doN UpperAlpha = [upperAlphaName]-            doN _ = []-            bw = if beginsWith > 1-                    then [beginsWithName ++ show beginsWith]-                    else []+            doN LowerRoman   = [lowerRomanName]+            doN UpperRoman   = [upperRomanName]+            doN LowerAlpha   = [lowerAlphaName]+            doN UpperAlpha   = [upperAlphaName]+            doN _            = []+            bw =+              [beginsWithName ++ show beginsWith | beginsWith > 1]         in  doN numbStl ++ bw       makeNumbStart Nothing = []       stl = if isFirst@@ -394,26 +397,26 @@       stl' = makeNumbStart attribs ++ stl   in  if length item > 1          then do-           let insertTab (Para lst) = blockToICML opts (subListParName:style) $ Para $ (Str "\t"):lst+           let insertTab (Para lst) = blockToICML opts (subListParName:style) $ Para $ Str "\t":lst                insertTab block      = blockToICML opts style block            f <- blockToICML opts stl' $ head item            r <- mapM insertTab $ tail item            return $ intersperseBrs (f : r)          else blocksToICML opts stl' item -definitionListItemToICML :: WriterOptions -> Style -> ([Inline],[[Block]]) -> WS Doc+definitionListItemToICML :: PandocMonad m => WriterOptions -> Style -> ([Inline],[[Block]]) -> WS m Doc definitionListItemToICML opts style (term,defs) = do   term' <- parStyle opts (defListTermName:style) term   defs' <- mapM (blocksToICML opts (defListDefName:style)) defs-  return $ intersperseBrs $ (term' : defs')+  return $ intersperseBrs (term' : defs')   -- | Convert a list of inline elements to ICML.-inlinesToICML :: WriterOptions -> Style -> [Inline] -> WS Doc+inlinesToICML :: PandocMonad m => WriterOptions -> Style -> [Inline] -> WS m Doc inlinesToICML opts style lst = vcat `fmap` mapM (inlineToICML opts style) (mergeSpaces lst)  -- | Convert an inline element to ICML.-inlineToICML :: WriterOptions -> Style -> Inline -> WS Doc+inlineToICML :: PandocMonad m => WriterOptions -> Style -> Inline -> WS m Doc inlineToICML _    style (Str str) = charStyle style $ text $ escapeStringForXML str inlineToICML opts style (Emph lst) = inlinesToICML opts (emphName:style) lst inlineToICML opts style (Strong lst) = inlinesToICML opts (strongName:style) lst@@ -433,17 +436,20 @@        WrapPreserve -> charStyle style cr inlineToICML _ style LineBreak = charStyle style $ text lineSeparator inlineToICML opts style (Math mt str) =-  cat <$> mapM (inlineToICML opts style) (texMathToInlines mt str)-inlineToICML _ _ (RawInline f str)+  lift (texMathToInlines mt str) >>=+    (fmap cat . mapM (inlineToICML opts style))+inlineToICML _ _ il@(RawInline f str)   | f == Format "icml" = return $ text str-  | otherwise          = return empty+  | otherwise          = do+      report $ InlineNotRendered il+      return empty inlineToICML opts style (Link _ lst (url, title)) = do   content <- inlinesToICML opts (linkName:style) lst   state $ \st ->             let ident = if null $ links st                            then 1::Int-                           else 1 + (fst $ head $ links st)-                newst = st{ links = (ident, url):(links st) }+                           else 1 + fst (head $ links st)+                newst = st{ links = (ident, url):links st }                 cont  = inTags True "HyperlinkTextSource"                          [("Self","htss-"++show ident), ("Name",title), ("Hidden","false")] content             in  (cont, newst)@@ -452,9 +458,9 @@ inlineToICML opts style (Span _ lst) = inlinesToICML opts style lst  -- | Convert a list of block elements to an ICML footnote.-footnoteToICML :: WriterOptions -> Style -> [Block] -> WS Doc+footnoteToICML :: PandocMonad m => WriterOptions -> Style -> [Block] -> WS m Doc footnoteToICML opts style lst =-  let insertTab (Para ls) = blockToICML opts (footnoteName:style) $ Para $ (Str "\t"):ls+  let insertTab (Para ls) = blockToICML opts (footnoteName:style) $ Para $ Str "\t":ls       insertTab block     = blockToICML opts (footnoteName:style) block   in  do     contents <- mapM insertTab lst@@ -466,24 +472,24 @@  -- | Auxiliary function to merge Space elements into the adjacent Strs. mergeSpaces :: [Inline] -> [Inline]-mergeSpaces ((Str s):(x:((Str s'):xs))) | isSp x =+mergeSpaces (Str s:(x:(Str s':xs))) | isSp x =   mergeSpaces $ Str(s++" "++s') : xs-mergeSpaces (x:((Str s):xs)) | isSp x = mergeSpaces $ Str (" "++s) : xs-mergeSpaces ((Str s):(x:xs)) | isSp x = mergeSpaces $ Str (s++" ") : xs-mergeSpaces (x:xs) = x : (mergeSpaces xs)+mergeSpaces (x:(Str s:xs)) | isSp x = mergeSpaces $ Str (" "++s) : xs+mergeSpaces (Str s:(x:xs)) | isSp x = mergeSpaces $ Str (s++" ") : xs+mergeSpaces (x:xs) = x : mergeSpaces xs mergeSpaces []     = []  isSp :: Inline -> Bool-isSp Space = True+isSp Space     = True isSp SoftBreak = True-isSp _ = False+isSp _         = False  -- | Intersperse line breaks intersperseBrs :: [Doc] -> Doc intersperseBrs = vcat . intersperse (selfClosingTag "Br" []) . filter (not . isEmpty)  -- | Wrap a list of inline elements in an ICML Paragraph Style-parStyle :: WriterOptions -> Style -> [Inline] -> WS Doc+parStyle :: PandocMonad m => WriterOptions -> Style -> [Inline] -> WS m Doc parStyle opts style lst =   let slipIn x y = if null y                       then x@@ -498,7 +504,7 @@                             begins = filter (isPrefixOf beginsWithName) style                         in  if null begins                                then ats-                               else let i = maybe "" id $ stripPrefix beginsWithName $ head begins+                               else let i = fromMaybe "" $ stripPrefix beginsWithName $ head begins                                     in  ("NumberingStartAt", i) : ats                    else [attrs]   in  do@@ -507,16 +513,16 @@       state $ \st -> (cont, st{ blockStyles = Set.insert stlStr $ blockStyles st })  -- | Wrap a Doc in an ICML Character Style.-charStyle :: Style -> Doc -> WS Doc+charStyle :: PandocMonad m => Style -> Doc -> WS m Doc charStyle style content =   let (stlStr, attrs) = styleToStrAttr style       doc = inTags True "CharacterStyleRange" attrs $ inTagsSimple "Content" $ flush content-  in  do+  in       state $ \st ->-        let styles = if null stlStr-                        then st-                        else st{ inlineStyles = Set.insert stlStr $ inlineStyles st }-        in  (doc, styles)+    let styles = if null stlStr+                    then st+                    else st{ inlineStyles = Set.insert stlStr $ inlineStyles st }+    in  (doc, styles)  -- | Transform a Style to a tuple of String (eliminating duplicates and ordered) and corresponding attribute. styleToStrAttr :: Style -> (String, [(String, String)])@@ -529,20 +535,18 @@   in  (stlStr, attrs)  -- | Assemble an ICML Image.-imageICML :: WriterOptions -> Style -> Attr -> Target -> WS Doc+imageICML :: PandocMonad m => WriterOptions -> Style -> Attr -> Target -> WS m Doc imageICML opts style attr (src, _) = do-  res  <- liftIO $ fetchItem (writerSourceURL opts) src-  imgS <- case res of-            Left (_) -> do-              warn $ "Could not find image `" ++ src ++ "', skipping..."-              return def-            Right (img, _) -> do-              case imageSize img of+  imgS <- catchError+          (do (img, _) <- P.fetchItem src+              case imageSize opts img of                 Right size -> return size                 Left msg   -> do-                  warn $ "Could not determine image size in `" ++-                    src ++ "': " ++ msg-                  return def+                  report $ CouldNotDetermineImageSize src msg+                  return def)+           (\e -> do+               report $ CouldNotFetchResource src (show e)+               return def)   let (ow, oh) = sizeInPoints imgS       (imgWidth, imgHeight) = desiredSizeInPoints opts attr imgS       hw = showFl $ ow / 2@@ -571,6 +575,5 @@                    ]       doc    = inTags True "CharacterStyleRange" attrs                  $ inTags True "Rectangle" [("Self","uec"), ("StrokeWeight", "0"),-                     ("ItemTransform", scale++" "++hw++" -"++hh)]-                 $ (props $$ image)+                     ("ItemTransform", scale++" "++hw++" -"++hh)] (props $$ image)   state $ \st -> (doc, st{ inlineStyles = Set.insert stlStr $ inlineStyles st } )
+ src/Text/Pandoc/Writers/JATS.hs view
@@ -0,0 +1,442 @@+{-# LANGUAGE OverloadedStrings #-}++{-+Copyright (C) 2006-2017 John MacFarlane <jgm@berkeley.edu>++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation; either version 2 of the License, or+(at your option) any later version.++This program is distributed in the hope that it will be useful,+but WITHOUT ANY WARRANTY; without even the implied warranty of+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+GNU General Public License for more details.++You should have received a copy of the GNU General Public License+along with this program; if not, write to the Free Software+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+-}+{- |+   Module      : Text.Pandoc.Writers.JATS+   Copyright   : Copyright (C) 2017 John MacFarlane+   License     : GNU GPL, version 2 or above++   Maintainer  : John MacFarlane <jgm@berkeley.edu>+   Stability   : alpha+   Portability : portable++Conversion of 'Pandoc' documents to JATS XML.+Reference:+https://jats.nlm.nih.gov/publishing/tag-library/1.1d3/element/mml-math.html+-}+module Text.Pandoc.Writers.JATS ( writeJATS ) where+import Control.Monad.Reader+import Data.Char (toLower)+import Data.Generics (everywhere, mkT)+import Data.List (isSuffixOf, partition)+import Data.Maybe (fromMaybe)+import Data.Text (Text)+import qualified Text.Pandoc.Builder as B+import Text.Pandoc.Class (PandocMonad, report)+import Text.Pandoc.Definition+import Text.Pandoc.Highlighting (languages, languagesByExtension)+import Text.Pandoc.Logging+import Text.Pandoc.MIME (getMimeType)+import Text.Pandoc.Options+import Text.Pandoc.Pretty+import Text.Pandoc.Shared+import Text.Pandoc.Templates (renderTemplate')+import Text.Pandoc.Writers.Math+import Text.Pandoc.Writers.Shared+import Text.Pandoc.XML+import Text.TeXMath+import qualified Text.XML.Light as Xml++data JATSVersion = JATS1_1+     deriving (Eq, Show)++type DB = ReaderT JATSVersion++-- | Convert list of authors to a docbook <author> section+authorToJATS :: PandocMonad m => WriterOptions -> [Inline] -> DB m B.Inlines+authorToJATS opts name' = do+  name <- render Nothing <$> inlinesToJATS opts name'+  let colwidth = if writerWrapText opts == WrapAuto+                    then Just $ writerColumns opts+                    else Nothing+  return $ B.rawInline "docbook" $ render colwidth $+      if ',' `elem` name+         then -- last name first+              let (lastname, rest) = break (==',') name+                  firstname = triml rest in+              inTagsSimple "firstname" (text $ escapeStringForXML firstname) <>+              inTagsSimple "surname" (text $ escapeStringForXML lastname)+         else -- last name last+              let namewords = words name+                  lengthname = length namewords+                  (firstname, lastname) = case lengthname of+                    0 -> ("","")+                    1 -> ("", name)+                    n -> (unwords (take (n-1) namewords), last namewords)+               in inTagsSimple "firstname" (text $ escapeStringForXML firstname) $$+                  inTagsSimple "surname" (text $ escapeStringForXML lastname)++writeJATS :: PandocMonad m => WriterOptions -> Pandoc -> m Text+writeJATS opts d =+  runReaderT (docToJATS opts d) JATS1_1++-- | Convert Pandoc document to string in JATS format.+docToJATS :: PandocMonad m => WriterOptions -> Pandoc -> DB m Text+docToJATS opts (Pandoc meta blocks) = do+  let isBackBlock (Div ("refs",_,_) _) = True+      isBackBlock _                    = False+  let (backblocks, bodyblocks) = partition isBackBlock blocks+  let elements = hierarchicalize bodyblocks+  let backElements = hierarchicalize backblocks+  let colwidth = if writerWrapText opts == WrapAuto+                    then Just $ writerColumns opts+                    else Nothing+  let render'  :: Doc -> Text+      render'  = render colwidth+  let opts'    = if maybe False (("/book>" `isSuffixOf`) . trimr)+                            (writerTemplate opts) &&+                     TopLevelDefault == writerTopLevelDivision opts+                    then opts{ writerTopLevelDivision = TopLevelChapter }+                    else opts+  -- The numbering here follows LaTeX's internal numbering+  let startLvl = case writerTopLevelDivision opts' of+                   TopLevelPart    -> -1+                   TopLevelChapter -> 0+                   TopLevelSection -> 1+                   TopLevelDefault -> 1+  auths' <- mapM (authorToJATS opts) $ docAuthors meta+  let meta' = B.setMeta "author" auths' meta+  metadata <- metaToJSON opts+                 (fmap (render' . vcat) .+                          mapM (elementToJATS opts' startLvl) .+                            hierarchicalize)+                 (fmap render' . inlinesToJATS opts')+                 meta'+  main <- (render' . vcat) <$>+            mapM (elementToJATS opts' startLvl) elements+  back <- (render' . vcat) <$>+            mapM (elementToJATS opts' startLvl) backElements+  let context = defField "body" main+              $ defField "back" back+              $ defField "mathml" (case writerHTMLMathMethod opts of+                                        MathML -> True+                                        _      -> False) metadata+  case writerTemplate opts of+       Nothing  -> return main+       Just tpl -> renderTemplate' tpl context++-- | Convert an Element to JATS.+elementToJATS :: PandocMonad m => WriterOptions -> Int -> Element -> DB m Doc+elementToJATS opts _   (Blk block) = blockToJATS opts block+elementToJATS opts lvl (Sec _ _num (id',_,kvs) title elements) = do+  let idAttr = [("id", writerIdentifierPrefix opts ++ id') | not (null id')]+  let otherAttrs = ["sec-type", "specific-use"]+  let attribs = idAttr ++ [(k,v) | (k,v) <- kvs, k `elem` otherAttrs]+  contents <- mapM (elementToJATS opts (lvl + 1)) elements+  title' <- inlinesToJATS opts title+  return $ inTags True "sec" attribs $+      inTagsSimple "title" title' $$ vcat contents++-- | Convert a list of Pandoc blocks to JATS.+blocksToJATS :: PandocMonad m => WriterOptions -> [Block] -> DB m Doc+blocksToJATS opts = fmap vcat . mapM (blockToJATS opts)++-- | Auxiliary function to convert Plain block to Para.+plainToPara :: Block -> Block+plainToPara (Plain x) = Para x+plainToPara x         = x++-- | Convert a list of pairs of terms and definitions into a list of+-- JATS varlistentrys.+deflistItemsToJATS :: PandocMonad m+                      => WriterOptions -> [([Inline],[[Block]])] -> DB m Doc+deflistItemsToJATS opts items =+  vcat <$> mapM (uncurry (deflistItemToJATS opts)) items++-- | Convert a term and a list of blocks into a JATS varlistentry.+deflistItemToJATS :: PandocMonad m+                     => WriterOptions -> [Inline] -> [[Block]] -> DB m Doc+deflistItemToJATS opts term defs = do+  term' <- inlinesToJATS opts term+  def' <- blocksToJATS opts $ concatMap (map plainToPara) defs+  return $ inTagsIndented "def-item" $+      inTagsIndented "term" term' $$+      inTagsIndented "def" def'++-- | Convert a list of lists of blocks to a list of JATS list items.+listItemsToJATS :: PandocMonad m+                => WriterOptions -> Maybe [String] -> [[Block]] -> DB m Doc+listItemsToJATS opts markers items =+  case markers of+       Nothing -> vcat <$> mapM (listItemToJATS opts Nothing) items+       Just ms -> vcat <$> zipWithM (listItemToJATS opts) (map Just ms) items++-- | Convert a list of blocks into a JATS list item.+listItemToJATS :: PandocMonad m+               => WriterOptions -> Maybe String -> [Block] -> DB m Doc+listItemToJATS opts mbmarker item = do+  contents <- blocksToJATS opts item+  return $ inTagsIndented "list-item" $+           maybe empty (\lbl -> inTagsIndented "label" (text lbl)) mbmarker+           $$ contents++-- | Convert a Pandoc block element to JATS.+blockToJATS :: PandocMonad m => WriterOptions -> Block -> DB m Doc+blockToJATS _ Null = return empty+-- Bibliography reference:+blockToJATS opts (Div ('r':'e':'f':'-':_,_,_) [Para lst]) =+  inlinesToJATS opts lst+blockToJATS opts (Div ("refs",_,_) xs) = do+  contents <- blocksToJATS opts xs+  return $ inTagsIndented "ref-list" contents+blockToJATS opts (Div (ident,_,kvs) bs) = do+  contents <- blocksToJATS opts bs+  let attr = [("id", ident) | not (null ident)] +++             [("xml:lang",l) | ("lang",l) <- kvs] +++             [(k,v) | (k,v) <- kvs, k `elem` ["specific-use",+                 "content-type", "orientation", "position"]]+  return $ inTags True "boxed-text" attr contents+blockToJATS _ h@(Header{}) = do+  -- should not occur after hierarchicalize, except inside lists/blockquotes+  report $ BlockNotRendered h+  return empty+-- No Plain, everything needs to be in a block-level tag+blockToJATS opts (Plain lst) = blockToJATS opts (Para lst)+-- title beginning with fig: indicates that the image is a figure+blockToJATS opts (Para [Image (ident,_,kvs) txt+  (src,'f':'i':'g':':':tit)]) = do+  alt <- inlinesToJATS opts txt+  let capt = if null txt+                then empty+                else inTagsSimple "caption" alt+  let attr = [("id", ident) | not (null ident)] +++             [(k,v) | (k,v) <- kvs, k `elem` ["fig-type", "orientation",+                                              "position", "specific-use"]]+  let mbMT = getMimeType src+  let maintype = fromMaybe "image" $+                  lookup "mimetype" kvs `mplus`+                  (takeWhile (/='/') <$> mbMT)+  let subtype = fromMaybe "" $+                  lookup "mime-subtype" kvs `mplus`+                  ((drop 1 . dropWhile (/='/')) <$> mbMT)+  let graphicattr = [("mimetype",maintype),+                     ("mime-subtype",drop 1 subtype),+                     ("xlink:href",src),  -- do we need to URL escape this?+                     ("xlink:title",tit)]+  return $ inTags True "fig" attr $+              capt $$ selfClosingTag "graphic" graphicattr+blockToJATS opts (Para lst) =+  inTagsIndented "p" <$> inlinesToJATS opts lst+blockToJATS opts (LineBlock lns) =+  blockToJATS opts $ linesToPara lns+blockToJATS opts (BlockQuote blocks) =+  inTagsIndented "disp-quote" <$> blocksToJATS opts blocks+blockToJATS _ (CodeBlock (ident,classes,kvs) str) = return $+  inTags False tag attr (flush (text (escapeStringForXML str)))+    where attr  = [("id",ident) | not (null ident)] +++                  [("language",lang) | not (null lang)] +++                  [(k,v) | (k,v) <- kvs, k `elem` ["code-type",+                    "code-version", "executable",+                    "language-version", "orientation",+                    "platforms", "position", "specific-use"]]+          tag   = if null lang then "preformat" else "code"+          lang  = case langs of+                     (l:_) -> escapeStringForXML l+                     []    -> ""+          isLang l    = map toLower l `elem` map (map toLower) languages+          langsFrom s = if isLang s+                           then [s]+                           else languagesByExtension . map toLower $ s+          langs       = concatMap langsFrom classes+blockToJATS _ (BulletList []) = return empty+blockToJATS opts (BulletList lst) =+  inTags True "list" [("list-type", "bullet")] <$>+  listItemsToJATS opts Nothing lst+blockToJATS _ (OrderedList _ []) = return empty+blockToJATS opts (OrderedList (start, numstyle, delimstyle) items) = do+  let listType = case numstyle of+                       DefaultStyle -> "order"+                       Decimal      -> "order"+                       Example      -> "order"+                       UpperAlpha   -> "alpha-upper"+                       LowerAlpha   -> "alpha-lower"+                       UpperRoman   -> "roman-upper"+                       LowerRoman   -> "roman-lower"+  let simpleList = start == 1 && (delimstyle == DefaultDelim ||+                                  delimstyle == Period)+  let markers = if simpleList+                   then Nothing+                   else Just $+                          orderedListMarkers (start, numstyle, delimstyle)+  inTags True "list" [("list-type", listType)] <$>+    listItemsToJATS opts markers items+blockToJATS opts (DefinitionList lst) =+  inTags True "def-list" [] <$> deflistItemsToJATS opts lst+blockToJATS _ b@(RawBlock f str)+  | f == "jats"    = return $ text str -- raw XML block+  | otherwise      = do+      report $ BlockNotRendered b+      return empty+blockToJATS _ HorizontalRule = return empty -- not semantic+blockToJATS opts (Table [] aligns widths headers rows) = do+  let percent w    = show (truncate (100*w) :: Integer) ++ "*"+  let coltags = vcat $ zipWith (\w al -> selfClosingTag "col"+                       ([("width", percent w) | w > 0] +++                        [("align", alignmentToString al)])) widths aligns+  thead <- if all null headers+              then return empty+              else inTagsIndented "thead" <$> tableRowToJATS opts True headers+  tbody <- (inTagsIndented "tbody" . vcat) <$>+                mapM (tableRowToJATS opts False) rows+  return $ inTags True "table" [] $ coltags $$ thead $$ tbody+blockToJATS opts (Table caption aligns widths headers rows) = do+  captionDoc <- inTagsIndented "caption" <$> blockToJATS opts (Para caption)+  tbl <- blockToJATS opts (Table [] aligns widths headers rows)+  return $ inTags True "table-wrap" [] $ captionDoc $$ tbl++alignmentToString :: Alignment -> [Char]+alignmentToString alignment = case alignment of+                                 AlignLeft    -> "left"+                                 AlignRight   -> "right"+                                 AlignCenter  -> "center"+                                 AlignDefault -> "left"++tableRowToJATS :: PandocMonad m+                  => WriterOptions+                  -> Bool+                  -> [[Block]]+                  -> DB m Doc+tableRowToJATS opts isHeader cols =+  (inTagsIndented "tr" . vcat) <$> mapM (tableItemToJATS opts isHeader) cols++tableItemToJATS :: PandocMonad m+                   => WriterOptions+                   -> Bool+                   -> [Block]+                   -> DB m Doc+tableItemToJATS opts isHeader item =+  (inTags True (if isHeader then "th" else "td") [] . vcat) <$>+    mapM (blockToJATS opts) item++-- | Convert a list of inline elements to JATS.+inlinesToJATS :: PandocMonad m => WriterOptions -> [Inline] -> DB m Doc+inlinesToJATS opts lst = hcat <$> mapM (inlineToJATS opts) lst++-- | Convert an inline element to JATS.+inlineToJATS :: PandocMonad m => WriterOptions -> Inline -> DB m Doc+inlineToJATS _ (Str str) = return $ text $ escapeStringForXML str+inlineToJATS opts (Emph lst) =+  inTagsSimple "italic" <$> inlinesToJATS opts lst+inlineToJATS opts (Strong lst) =+  inTags False "bold" [("role", "strong")] <$> inlinesToJATS opts lst+inlineToJATS opts (Strikeout lst) =+  inTagsSimple "strike" <$> inlinesToJATS opts lst+inlineToJATS opts (Superscript lst) =+  inTagsSimple "sup" <$> inlinesToJATS opts lst+inlineToJATS opts (Subscript lst) =+  inTagsSimple "sub" <$> inlinesToJATS opts lst+inlineToJATS opts (SmallCaps lst) =+  inTags False "sc" [("role", "smallcaps")] <$>+  inlinesToJATS opts lst+inlineToJATS opts (Quoted SingleQuote lst) = do+  contents <- inlinesToJATS opts lst+  return $ char '‘' <> contents <> char '’'+inlineToJATS opts (Quoted DoubleQuote lst) = do+  contents <- inlinesToJATS opts lst+  return $ char '“' <> contents <> char '”'+inlineToJATS _ (Code _ str) =+  return $ inTagsSimple "monospace" $ text (escapeStringForXML str)+inlineToJATS _ il@(RawInline f x)+  | f == "jats" = return $ text x+  | otherwise   = do+      report $ InlineNotRendered il+      return empty+inlineToJATS _ LineBreak = return $ selfClosingTag "break" []+inlineToJATS _ Space = return space+inlineToJATS opts SoftBreak+  | writerWrapText opts == WrapPreserve = return cr+  | otherwise = return space+inlineToJATS opts (Note contents) =+  -- TODO technically only <p> tags are allowed inside+  inTagsIndented "fn" <$> blocksToJATS opts contents+inlineToJATS opts (Cite _ lst) =+  -- TODO revisit this after examining the jats.csl pipeline+  inlinesToJATS opts lst+inlineToJATS opts (Span ("",_,[]) ils) = inlinesToJATS opts ils+inlineToJATS opts (Span (ident,_,kvs) ils) = do+  contents <- inlinesToJATS opts ils+  let attr = [("id",ident) | not (null ident)] +++             [("xml:lang",l) | ("lang",l) <- kvs] +++             [(k,v) | (k,v) <- kvs+                    ,  k `elem` ["content-type", "rationale",+                                 "rid", "specific-use"]]+  return $ selfClosingTag "milestone-start" attr <> contents <>+           selfClosingTag "milestone-end" []+inlineToJATS _ (Math t str) = do+  let addPref (Xml.Attr q v)+         | Xml.qName q == "xmlns" = Xml.Attr q{ Xml.qName = "xmlns:mml" } v+         | otherwise = Xml.Attr q v+  let fixNS' e = e{ Xml.elName =+                         (Xml.elName e){ Xml.qPrefix = Just "mml" } }+  let fixNS = everywhere (mkT fixNS') .+              (\e -> e{ Xml.elAttribs = map addPref (Xml.elAttribs e) })+  let conf = Xml.useShortEmptyTags (const False) Xml.defaultConfigPP+  res <- convertMath writeMathML t str+  let tagtype = case t of+                     DisplayMath -> "disp-formula"+                     InlineMath  -> "inline-formula"+  let rawtex = inTagsSimple "tex-math"+                                $ text "<![CDATA[" <>+                                  text str <>+                                  text "]]>"+  return $ inTagsSimple tagtype $+             case res of+                   Right r  -> inTagsSimple "alternatives" $+                                  cr <> rawtex $$+                                  text (Xml.ppcElement conf $ fixNS r)+                   Left _   -> rawtex+inlineToJATS _ (Link _attr [Str t] ('m':'a':'i':'l':'t':'o':':':email, _))+  | escapeURI t == email =+  return $ inTagsSimple "email" $ text (escapeStringForXML email)+inlineToJATS opts (Link (ident,_,kvs) txt ('#':src, _)) = do+  let attr = [("id", ident) | not (null ident)] +++             [("alt", stringify txt),+              ("rid", src)] +++             [(k,v) | (k,v) <- kvs, k `elem` ["ref-type", "specific-use"]]+  contents <- inlinesToJATS opts txt+  return $ inTags False "xref" attr contents+inlineToJATS opts (Link (ident,_,kvs) txt (src, tit)) = do+  let attr = [("id", ident) | not (null ident)] +++             [("ext-link-type", "uri"),+              ("xlink:href", src)] +++             [("xlink:title", tit) | not (null tit)] +++             [(k,v) | (k,v) <- kvs, k `elem` ["assigning-authority",+                                              "specific-use", "xlink:actuate",+                                              "xlink:role", "xlink:show",+                                              "xlink:type"]]+  contents <- inlinesToJATS opts txt+  return $ inTags False "ext-link" attr contents+inlineToJATS _ (Image (ident,_,kvs) _ (src, tit)) = do+  let mbMT = getMimeType src+  let maintype = fromMaybe "image" $+                  lookup "mimetype" kvs `mplus`+                  (takeWhile (/='/') <$> mbMT)+  let subtype = fromMaybe "" $+                  lookup "mime-subtype" kvs `mplus`+                  ((drop 1 . dropWhile (/='/')) <$> mbMT)+  let attr = [("id", ident) | not (null ident)] +++             [("mimetype", maintype),+              ("mime-subtype", subtype),+              ("xlink:href", src)] +++             [("xlink:title", tit) | not (null tit)] +++             [(k,v) | (k,v) <- kvs, k `elem` ["baseline-shift",+                        "content-type", "specific-use", "xlink:actuate",+                        "xlink:href", "xlink:role", "xlink:show",+                        "xlink:type"]]+  return $ selfClosingTag "inline-graphic" attr
src/Text/Pandoc/Writers/LaTeX.hs view
@@ -1,7 +1,8 @@-{-# LANGUAGE OverloadedStrings, ScopedTypeVariables,-             PatternGuards #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE PatternGuards       #-}+{-# LANGUAGE ScopedTypeVariables #-} {--Copyright (C) 2006-2015 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2006-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -20,7 +21,7 @@  {- |    Module      : Text.Pandoc.Writers.LaTeX-   Copyright   : Copyright (C) 2006-2015 John MacFarlane+   Copyright   : Copyright (C) 2006-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -29,37 +30,44 @@  Conversion of 'Pandoc' format into LaTeX. -}-module Text.Pandoc.Writers.LaTeX ( writeLaTeX ) where+module Text.Pandoc.Writers.LaTeX (+    writeLaTeX+  , writeBeamer+  ) where+import Control.Applicative ((<|>))+import Control.Monad.State.Strict+import Data.Aeson (FromJSON, object, (.=))+import Data.Char (isAlphaNum, isAscii, isDigit, isLetter, isPunctuation, ord,+                  toLower)+import Data.List (foldl', intercalate, intersperse, isInfixOf, nubBy,+                  stripPrefix, (\\))+import Data.Maybe (catMaybes, fromMaybe, isJust, mapMaybe)+import Data.Text (Text)+import qualified Data.Text as T+import Network.URI (unEscapeString)+import Text.Pandoc.BCP47 (Lang (..), getLang, renderLang)+import Text.Pandoc.Class (PandocMonad, report, toLang) import Text.Pandoc.Definition-import Text.Pandoc.Walk-import Text.Pandoc.Shared-import Text.Pandoc.Writers.Shared+import Text.Pandoc.Highlighting (formatLaTeXBlock, formatLaTeXInline, highlight,+                                 styleToLaTeX, toListingsLanguage)+import Text.Pandoc.ImageSize+import Text.Pandoc.Logging import Text.Pandoc.Options-import Text.Pandoc.Templates-import Text.Printf ( printf )-import Network.URI ( isURI, unEscapeString )-import Data.Aeson (object, (.=), FromJSON)-import Data.List ( (\\), isInfixOf, stripPrefix, intercalate, intersperse,-                   nub, nubBy, foldl' )-import Data.Char ( toLower, isPunctuation, isAscii, isLetter, isDigit,-                   ord, isAlphaNum )-import Data.Maybe ( fromMaybe, isJust, catMaybes )-import qualified Data.Text as T-import Control.Applicative ((<|>))-import Control.Monad.State-import qualified Text.Parsec as P import Text.Pandoc.Pretty-import Text.Pandoc.ImageSize+import Text.Pandoc.Shared import Text.Pandoc.Slides-import Text.Pandoc.Highlighting (highlight, styleToLaTeX,-                                 formatLaTeXInline, formatLaTeXBlock,-                                 toListingsLanguage)+import Text.Pandoc.Templates+import Text.Pandoc.Walk+import Text.Pandoc.Writers.Shared+import qualified Text.Parsec as P+import Text.Printf (printf)  data WriterState =   WriterState { stInNote        :: Bool          -- true if we're in a note               , stInQuote       :: Bool          -- true if in a blockquote               , stInMinipage    :: Bool          -- true if in minipage               , stInHeading     :: Bool          -- true if in a section heading+              , stInItem        :: Bool          -- true if in \item[..]               , stNotes         :: [Doc]         -- notes in a minipage               , stOLLevel       :: Int           -- level of ordered list nesting               , stOptions       :: WriterOptions -- writer options, so they don't have to be parameter@@ -74,49 +82,75 @@               , stHighlighting  :: Bool          -- true if document has highlighted code               , stIncremental   :: Bool          -- true if beamer lists should be displayed bit by bit               , stInternalLinks :: [String]      -- list of internal link targets-              , stUsesEuro      :: Bool          -- true if euro symbol used+              , stBeamer        :: Bool          -- produce beamer+              , stEmptyLine     :: Bool          -- true if no content on line               } +startingState :: WriterOptions -> WriterState+startingState options = WriterState {+                  stInNote = False+                , stInQuote = False+                , stInMinipage = False+                , stInHeading = False+                , stInItem = False+                , stNotes = []+                , stOLLevel = 1+                , stOptions = options+                , stVerbInNote = False+                , stTable = False+                , stStrikeout = False+                , stUrl = False+                , stGraphics = False+                , stLHS = False+                , stBook = case writerTopLevelDivision options of+                                TopLevelPart    -> True+                                TopLevelChapter -> True+                                _               -> False+                , stCsquotes = False+                , stHighlighting = False+                , stIncremental = writerIncremental options+                , stInternalLinks = []+                , stBeamer = False+                , stEmptyLine = True }+ -- | Convert Pandoc to LaTeX.-writeLaTeX :: WriterOptions -> Pandoc -> String+writeLaTeX :: PandocMonad m => WriterOptions -> Pandoc -> m Text writeLaTeX options document =-  evalState (pandocToLaTeX options document) $-  WriterState { stInNote = False, stInQuote = False,-                stInMinipage = False, stInHeading = False,-                stNotes = [], stOLLevel = 1,-                stOptions = options, stVerbInNote = False,-                stTable = False, stStrikeout = False,-                stUrl = False, stGraphics = False,-                stLHS = False,-                stBook = (case writerTopLevelDivision options of-                           TopLevelPart    -> True-                           TopLevelChapter -> True-                           _               -> False),-                stCsquotes = False, stHighlighting = False,-                stIncremental = writerIncremental options,-                stInternalLinks = [], stUsesEuro = False }+  evalStateT (pandocToLaTeX options document) $+    startingState options -pandocToLaTeX :: WriterOptions -> Pandoc -> State WriterState String+-- | Convert Pandoc to LaTeX Beamer.+writeBeamer :: PandocMonad m => WriterOptions -> Pandoc -> m Text+writeBeamer options document =+  evalStateT (pandocToLaTeX options document) $+    (startingState options){ stBeamer = True }++type LW m = StateT WriterState m++pandocToLaTeX :: PandocMonad m+              => WriterOptions -> Pandoc -> LW m Text pandocToLaTeX options (Pandoc meta blocks) = do   -- Strip off final 'references' header if --natbib or --biblatex   let method = writerCiteMethod options   let blocks' = if method == Biblatex || method == Natbib                    then case reverse blocks of-                             (Div (_,["references"],_) _):xs -> reverse xs-                             _ -> blocks+                             Div (_,["references"],_) _:xs -> reverse xs+                             _                             -> blocks                    else blocks   -- see if there are internal links-  let isInternalLink (Link _ _ ('#':xs,_))  = [xs]-      isInternalLink _                      = []+  let isInternalLink (Link _ _ ('#':xs,_)) = [xs]+      isInternalLink _                     = []   modify $ \s -> s{ stInternalLinks = query isInternalLink blocks' }-  let template = maybe "" id $ writerTemplate options+  let template = fromMaybe "" $ writerTemplate options   -- set stBook depending on documentclass   let colwidth = if writerWrapText options == WrapAuto                     then Just $ writerColumns options                     else Nothing+  let render' :: Doc -> Text+      render' = render colwidth   metadata <- metaToJSON options-              (fmap (render colwidth) . blockListToLaTeX)-              (fmap (render colwidth) . inlineListToLaTeX)+              (fmap render' . blockListToLaTeX)+              (fmap render' . inlineListToLaTeX)               meta   let bookClasses = ["memoir","book","report","scrreprt","scrbook"]   let documentClass = case P.parse pDocumentClass "template" template of@@ -143,25 +177,38 @@                                else case last blocks' of                                  Header 1 _ il -> (init blocks', il)                                  _             -> (blocks', [])-  blocks''' <- if writerBeamer options+  beamer <- gets stBeamer+  blocks''' <- if beamer                   then toSlides blocks''                   else return blocks''   body <- mapM (elementToLaTeX options) $ hierarchicalize blocks'''-  (biblioTitle :: String) <- liftM (render colwidth) $ inlineListToLaTeX lastHeader-  let main = render colwidth $ vsep body+  (biblioTitle :: Text) <- render' <$> inlineListToLaTeX lastHeader+  let main = render' $ vsep body   st <- get   titleMeta <- stringToLaTeX TextString $ stringify $ docTitle meta   authorsMeta <- mapM (stringToLaTeX TextString . stringify) $ docAuthors meta-  let docLangs = nub $ query (extract "lang") blocks+  docLangs <- catMaybes <$>+      mapM (toLang . Just) (ordNub (query (extract "lang") blocks))   let hasStringValue x = isJust (getField x metadata :: Maybe String)-  let geometryFromMargins = intercalate [','] $ catMaybes $-                              map (\(x,y) ->+  let geometryFromMargins = intercalate [','] $ mapMaybe (\(x,y) ->                                 ((x ++ "=") ++) <$> getField y metadata)                               [("lmargin","margin-left")                               ,("rmargin","margin-right")                               ,("tmargin","margin-top")                               ,("bmargin","margin-bottom")                               ]+  let toPolyObj lang = object [ "name"    .= T.pack name+                              , "options" .= T.pack opts ]+        where+          (name, opts) = toPolyglossia lang+  mblang <- toLang $ case getLang options meta of+                          Just l -> Just l+                          Nothing | null docLangs -> Nothing+                                  | otherwise     -> Just "en"+  -- we need a default here since lang is used in template conditionals++  let dirs = query (extract "dir") blocks+   let context  =  defField "toc" (writerTableOfContents options) $                   defField "toc-depth" (show (writerTOCDepth options -                                               if stBook st@@ -170,7 +217,7 @@                   defField "body" main $                   defField "title-meta" titleMeta $                   defField "author-meta" (intercalate "; " authorsMeta) $-                  defField "documentclass" (if writerBeamer options+                  defField "documentclass" (if beamer                                                then ("beamer" :: String)                                                else if stBook st                                                     then "book"@@ -183,12 +230,14 @@                   defField "lhs" (stLHS st) $                   defField "graphics" (stGraphics st) $                   defField "book-class" (stBook st) $-                  defField "euro" (stUsesEuro st) $                   defField "listings" (writerListings options || stLHS st) $-                  defField "beamer" (writerBeamer options) $+                  defField "beamer" beamer $                   (if stHighlighting st-                      then defField "highlighting-macros" (styleToLaTeX-                                $ writerHighlightStyle options )+                      then case writerHighlightStyle options of+                                Just sty ->+                                   defField "highlighting-macros"+                                      (styleToLaTeX sty)+                                Nothing -> id                       else id) $                   (case writerCiteMethod options of                          Natbib   -> defField "biblio-title" biblioTitle .@@ -196,26 +245,24 @@                          Biblatex -> defField "biblio-title" biblioTitle .                                      defField "biblatex" True                          _        -> id) $-                  -- set lang to something so polyglossia/babel is included-                  defField "lang" (if null docLangs then ""::String else "en") $-                  defField "otherlangs" docLangs $                   defField "colorlinks" (any hasStringValue                            ["citecolor", "urlcolor", "linkcolor", "toccolor"]) $-                  defField "dir" (if (null $ query (extract "dir") blocks)-                                     then ""::String-                                     else "ltr") $+                  (if null dirs+                     then id+                     else defField "dir" ("ltr" :: String)) $                   defField "section-titles" True $                   defField "geometry" geometryFromMargins $+                  (case getField "papersize" metadata of+                        Just ("A4" :: String) -> resetField "papersize"+                                                    ("a4" :: String)+                        _                     -> id)                   metadata-  let toPolyObj lang = object [ "name"    .= T.pack name-                              , "options" .= T.pack opts ]-        where-          (name, opts) = toPolyglossia lang-  let lang = maybe [] (splitBy (=='-')) $ getField "lang" context-      otherlangs = maybe [] (map $ splitBy (=='-')) $ getField "otherlangs" context   let context' =-          defField "babel-lang" (toBabel lang)-        $ defField "babel-otherlangs" (map toBabel otherlangs)+          -- note: lang is used in some conditionals in the template,+          -- so we need to set it if we have any babel/polyglossia:+          maybe id (defField "lang" . renderLang) mblang+        $ maybe id (defField "babel-lang" . toBabel) mblang+        $ defField "babel-otherlangs" (map toBabel docLangs)         $ defField "babel-newcommands" (concatMap (\(poly, babel) ->             -- \textspanish and \textgalician are already used by babel             -- save them as \oritext... and let babel use that@@ -235,23 +282,19 @@             -- eliminate duplicates that have same polyglossia name             $ nubBy (\a b -> fst a == fst b)             -- find polyglossia and babel names of languages used in the document-            $ map (\l ->-              let lng = splitBy (=='-') l-              in  (fst $ toPolyglossia lng, toBabel lng)-              )-            docLangs )-        $ defField "polyglossia-lang" (toPolyObj lang)-        $ defField "polyglossia-otherlangs" (map toPolyObj otherlangs)-        $ defField "latex-dir-rtl" (case (getField "dir" context)::Maybe String of-                                      Just "rtl" -> True-                                      _          -> False)-        $ context-  return $ case writerTemplate options of-                Nothing  -> main-                Just tpl -> renderTemplate' tpl context'+            $ map (\l -> (fst $ toPolyglossia l, toBabel l)) docLangs+          )+        $ maybe id (defField "polyglossia-lang" . toPolyObj) mblang+        $ defField "polyglossia-otherlangs" (map toPolyObj docLangs)+        $+                  defField "latex-dir-rtl"+           (getField "dir" context == Just ("rtl" :: String)) context+  case writerTemplate options of+       Nothing  -> return main+       Just tpl -> renderTemplate' tpl context'  -- | Convert Elements to LaTeX-elementToLaTeX :: WriterOptions -> Element -> State WriterState Doc+elementToLaTeX :: PandocMonad m => WriterOptions -> Element -> LW m Doc elementToLaTeX _ (Blk block) = blockToLaTeX block elementToLaTeX opts (Sec level _ (id',classes,_) title' elements) = do   modify $ \s -> s{stInHeading = True}@@ -266,18 +309,15 @@                    deriving (Eq)  -- escape things as needed for LaTeX-stringToLaTeX :: StringContext -> String -> State WriterState String+stringToLaTeX :: PandocMonad m => StringContext -> String -> LW m String stringToLaTeX  _     []     = return "" stringToLaTeX  ctx (x:xs) = do   opts <- gets stOptions   rest <- stringToLaTeX ctx xs-  let ligatures = writerTeXLigatures opts && ctx == TextString+  let ligatures = isEnabled Ext_smart opts && ctx == TextString   let isUrl = ctx == URLString-  when (x == '€') $-     modify $ \st -> st{ stUsesEuro = True }   return $     case x of-       '€' -> "\\euro{}" ++ rest        '{' -> "\\{" ++ rest        '}' -> "\\}" ++ rest        '`' | ctx == CodeString -> "\\textasciigrave{}" ++ rest@@ -311,26 +351,26 @@        '\x2013' | ligatures -> "--" ++ rest        _        -> x : rest -toLabel :: String -> State WriterState String+toLabel :: PandocMonad m => String -> LW m String toLabel z = go `fmap` stringToLaTeX URLString z  where go [] = ""        go (x:xs)          | (isLetter x || isDigit x) && isAscii x = x:go xs-         | elem x ("_-+=:;." :: String) = x:go xs+         | x `elem` ("_-+=:;." :: String) = x:go xs          | otherwise = "ux" ++ printf "%x" (ord x) ++ go xs  -- | Puts contents into LaTeX command. inCmd :: String -> Doc -> Doc inCmd cmd contents = char '\\' <> text cmd <> braces contents -toSlides :: [Block] -> State WriterState [Block]+toSlides :: PandocMonad m => [Block] -> LW m [Block] toSlides bs = do   opts <- gets stOptions   let slideLevel = fromMaybe (getSlideLevel bs) $ writerSlideLevel opts   let bs' = prepSlides slideLevel bs-  concat `fmap` (mapM (elementToBeamer slideLevel) $ hierarchicalize bs')+  concat `fmap` mapM (elementToBeamer slideLevel) (hierarchicalize bs') -elementToBeamer :: Int -> Element -> State WriterState [Block]+elementToBeamer :: PandocMonad m => Int -> Element -> LW m [Block] elementToBeamer _slideLevel (Blk b) = return [b] elementToBeamer slideLevel  (Sec lvl _num (ident,classes,kvs) tit elts)   | lvl >  slideLevel = do@@ -340,7 +380,7 @@              : bs ++ [RawBlock "latex" "\\end{block}"]   | lvl <  slideLevel = do       bs <- concat `fmap` mapM (elementToBeamer slideLevel) elts-      return $ (Header lvl (ident,classes,kvs) tit) : bs+      return $ Header lvl (ident,classes,kvs) tit : bs   | otherwise = do -- lvl == slideLevel       -- note: [fragile] is required or verbatim breaks       let hasCodeBlock (CodeBlock _ _) = [True]@@ -358,10 +398,19 @@       let options = if null optionslist                        then ""                        else "[" ++ intercalate "," optionslist ++ "]"-      let slideStart = Para $ RawInline "latex" ("\\begin{frame}" ++ options) :-                if tit == [Str "\0"]  -- marker for hrule-                   then []-                   else (RawInline "latex" "{") : tit ++ [RawInline "latex" "}"]+      let latex = RawInline (Format "latex")+      slideTitle <-+            if tit == [Str "\0"] -- marker for hrule+               then return []+               else+                 if null ident+                    then return $ latex "{" : tit ++ [latex "}"]+                    else do+                      ref <- toLabel ident+                      return $ latex ("{%\n\\protect\\hypertarget{" +++                                ref ++ "}{%\n") : tit ++ [latex "}}"]+      let slideStart = Para $+              RawInline "latex" ("\\begin{frame}" ++ options) : slideTitle       let slideEnd = RawBlock "latex" "\\end{frame}"       -- now carve up slide into blocks if there are sections inside       bs <- concat `fmap` mapM (elementToBeamer slideLevel) elts@@ -376,26 +425,49 @@ isLineBreakOrSpace :: Inline -> Bool isLineBreakOrSpace LineBreak = True isLineBreakOrSpace SoftBreak = True-isLineBreakOrSpace Space = True-isLineBreakOrSpace _ = False+isLineBreakOrSpace Space     = True+isLineBreakOrSpace _         = False  -- | Convert Pandoc block element to LaTeX.-blockToLaTeX :: Block     -- ^ Block to convert-             -> State WriterState Doc+blockToLaTeX :: PandocMonad m+             => Block     -- ^ Block to convert+             -> LW m Doc blockToLaTeX Null = return empty blockToLaTeX (Div (identifier,classes,kvs) bs) = do-  beamer <- writerBeamer `fmap` gets stOptions-  ref <- toLabel identifier-  let linkAnchor = if null identifier-                      then empty-                      else "\\hypertarget" <> braces (text ref) <>-                             braces empty+  beamer <- gets stBeamer+  linkAnchor' <- hypertarget True identifier empty+  -- see #2704 for the motivation for adding \leavevmode:+  let linkAnchor =+       case bs of+            Para _ : _+              | not (isEmpty linkAnchor')+              -> "\\leavevmode" <> linkAnchor' <> "%"+            _ -> linkAnchor'   let align dir txt = inCmd "begin" dir $$ txt $$ inCmd "end" dir-  let wrapDir = case lookup "dir" kvs of+  lang <- toLang $ lookup "lang" kvs+  let wrapColumns = if "columns" `elem` classes+                       then \contents ->+                          inCmd "begin" "columns" <> brackets "T"+                              $$ contents+                              $$ inCmd "end" "columns"+                       else id+      wrapColumn  = if "column" `elem` classes+                       then \contents ->+                          let fromPct xs =+                                case reverse xs of+                                     '%':ds -> '0':'.': reverse ds+                                     _      -> xs+                              w = maybe "0.48" fromPct (lookup "width" kvs)+                          in  inCmd "begin" "column" <>+                              braces (text w <> "\\textwidth")+                              $$ contents+                              $$ inCmd "end" "column"+                       else id+      wrapDir = case lookup "dir" kvs of                   Just "rtl" -> align "RTL"                   Just "ltr" -> align "LTR"                   _          -> id-      wrapLang txt = case lookup "lang" kvs of+      wrapLang txt = case lang of                        Just lng -> let (l, o) = toPolyglossiaEnv lng                                        ops = if null o                                                 then ""@@ -407,12 +479,14 @@       wrapNotes txt = if beamer && "notes" `elem` classes                           then "\\note" <> braces txt -- speaker notes                           else linkAnchor $$ txt-  fmap (wrapDir . wrapLang . wrapNotes) $ blockListToLaTeX bs+  (wrapColumns . wrapColumn . wrapDir . wrapLang . wrapNotes)+    <$> blockListToLaTeX bs blockToLaTeX (Plain lst) =   inlineListToLaTeX $ dropWhile isLineBreakOrSpace lst -- title beginning with fig: indicates that the image is a figure blockToLaTeX (Para [Image attr@(ident, _, _) txt (src,'f':'i':'g':':':tit)]) = do   inNote <- gets stInNote+  inMinipage <- gets stInMinipage   modify $ \st -> st{ stInMinipage = True, stNotes = [] }   capt <- inlineListToLaTeX txt   notes <- gets stNotes@@ -426,25 +500,26 @@   let footnotes = notesToLaTeX notes   lab <- labelFor ident   let caption = "\\caption" <> captForLof <> braces capt <> lab-  figure <- hypertarget ident (cr <>-            "\\begin{figure}" $$ "\\centering" $$ img $$-            caption $$ "\\end{figure}" <> cr)-  return $ if inNote-              -- can't have figures in notes+  let figure = cr <> "\\begin{figure}" $$ "\\centering" $$ img $$+              caption $$ "\\end{figure}" <> cr+  figure' <- hypertarget True ident figure+  return $ if inNote || inMinipage+              -- can't have figures in notes or minipage (here, table cell)+              -- http://www.tex.ac.uk/FAQ-ouparmd.html               then "\\begin{center}" $$ img $+$ capt $$ "\\end{center}"-              else figure $$ footnotes+              else figure' $$ footnotes -- . . . indicates pause in beamer slides blockToLaTeX (Para [Str ".",Space,Str ".",Space,Str "."]) = do-  beamer <- writerBeamer `fmap` gets stOptions+  beamer <- gets stBeamer   if beamer      then blockToLaTeX (RawBlock "latex" "\\pause")      else inlineListToLaTeX [Str ".",Space,Str ".",Space,Str "."] blockToLaTeX (Para lst) =   inlineListToLaTeX $ dropWhile isLineBreakOrSpace lst-blockToLaTeX (LineBlock lns) = do+blockToLaTeX (LineBlock lns) =   blockToLaTeX $ linesToPara lns blockToLaTeX (BlockQuote lst) = do-  beamer <- writerBeamer `fmap` gets stOptions+  beamer <- gets stBeamer   case lst of        [b] | beamer && isListBlock b -> do          oldIncremental <- gets stIncremental@@ -460,11 +535,11 @@          return $ "\\begin{quote}" $$ contents $$ "\\end{quote}" blockToLaTeX (CodeBlock (identifier,classes,keyvalAttr) str) = do   opts <- gets stOptions-  ref <- toLabel identifier-  let linkAnchor = if null identifier+  lab <- labelFor identifier+  linkAnchor' <- hypertarget True identifier lab+  let linkAnchor = if isEmpty linkAnchor'                       then empty-                      else "\\hypertarget" <> braces (text ref) <>-                                braces ("\\label" <> braces (text ref))+                      else linkAnchor' <> "%"   let lhsCodeBlock = do         modify $ \s -> s{ stLHS = True }         return $ flush (linkAnchor $$ "\\begin{code}" $$ text str $$@@ -479,6 +554,7 @@                  text str $$ text ("\\end{" ++ env ++ "}")) <> cr   let listingsCodeBlock = do         st <- get+        ref <- toLabel identifier         let params = if writerListings (stOptions st)                      then (case getListingsLanguage classes of                                 Just l  -> [ "language=" ++ mbBraced l ]@@ -495,9 +571,6 @@                                 else [ "label=" ++ ref ])                       else []-            mbBraced x = if not (all isAlphaNum x)-                            then "{" <> x <> "}"-                            else x             printParams                 | null params = empty                 | otherwise   = brackets $ hcat (intersperse ", "@@ -505,24 +578,34 @@         return $ flush ("\\begin{lstlisting}" <> printParams $$ text str $$                  "\\end{lstlisting}") $$ cr   let highlightedCodeBlock =-        case highlight formatLaTeXBlock ("",classes,keyvalAttr) str of-               Nothing -> rawCodeBlock-               Just  h -> modify (\st -> st{ stHighlighting = True }) >>-                          return (flush $ linkAnchor $$ text (T.unpack h))+        case highlight (writerSyntaxMap opts)+                 formatLaTeXBlock ("",classes,keyvalAttr) str of+               Left msg -> do+                 unless (null msg) $+                   report $ CouldNotHighlight msg+                 rawCodeBlock+               Right h -> do+                  st <- get+                  when (stInNote st) $ modify (\s -> s{ stVerbInNote = True })+                  modify (\s -> s{ stHighlighting = True })+                  return (flush $ linkAnchor $$ text (T.unpack h))   case () of      _ | isEnabled Ext_literate_haskell opts && "haskell" `elem` classes &&-         "literate" `elem` classes                      -> lhsCodeBlock-       | writerListings opts                            -> listingsCodeBlock-       | writerHighlight opts && not (null classes)     -> highlightedCodeBlock-       | otherwise                                      -> rawCodeBlock-blockToLaTeX (RawBlock f x)+         "literate" `elem` classes           -> lhsCodeBlock+       | writerListings opts                 -> listingsCodeBlock+       | not (null classes) && isJust (writerHighlightStyle opts)+                                             -> highlightedCodeBlock+       | otherwise                           -> rawCodeBlock+blockToLaTeX b@(RawBlock f x)   | f == Format "latex" || f == Format "tex"                         = return $ text x-  | otherwise           = return empty+  | otherwise           = do+      report $ BlockNotRendered b+      return empty blockToLaTeX (BulletList []) = return empty  -- otherwise latex error blockToLaTeX (BulletList lst) = do   incremental <- gets stIncremental-  beamer <- writerBeamer `fmap` gets stOptions+  beamer <- gets stBeamer   let inc = if beamer && incremental then "[<+->]" else ""   items <- mapM listItemToLaTeX lst   let spacing = if isTightList lst@@ -538,6 +621,7 @@   put $ st {stOLLevel = oldlevel + 1}   items <- mapM listItemToLaTeX lst   modify (\s -> s {stOLLevel = oldlevel})+  let beamer = stBeamer st   let tostyle x = case numstyle of                        Decimal      -> "\\arabic" <> braces x                        UpperRoman   -> "\\Roman" <> braces x@@ -547,15 +631,24 @@                        Example      -> "\\arabic" <> braces x                        DefaultStyle -> "\\arabic" <> braces x   let todelim x = case numdelim of-                       OneParen    -> x <> ")"-                       TwoParens   -> parens x-                       Period      -> x <> "."-                       _           -> x <> "."+                       OneParen  -> x <> ")"+                       TwoParens -> parens x+                       Period    -> x <> "."+                       _         -> x <> "."+  let exemplar = case numstyle of+                       Decimal      -> "1"+                       UpperRoman   -> "I"+                       LowerRoman   -> "i"+                       UpperAlpha   -> "A"+                       LowerAlpha   -> "a"+                       Example      -> "1"+                       DefaultStyle -> "1"   let enum = text $ "enum" ++ map toLower (toRomanNumeral oldlevel)-  let stylecommand = if numstyle == DefaultStyle && numdelim == DefaultDelim-                        then empty-                        else "\\def" <> "\\label" <> enum <>-                              braces (todelim $ tostyle enum)+  let stylecommand+        | numstyle == DefaultStyle && numdelim == DefaultDelim = empty+        | beamer = brackets (todelim exemplar)+        | otherwise = "\\def" <> "\\label" <> enum <>+          braces (todelim $ tostyle enum)   let resetcounter = if start == 1 || oldlevel > 4                         then empty                         else "\\setcounter" <> braces enum <>@@ -579,7 +672,8 @@                    else empty   return $ text ("\\begin{description}" ++ inc) $$ spacing $$ vcat items $$                "\\end{description}"-blockToLaTeX HorizontalRule = return $+blockToLaTeX HorizontalRule =+            return   "\\begin{center}\\rule{0.5\\linewidth}{\\linethickness}\\end{center}" blockToLaTeX (Header level (id',classes,_) lst) = do   modify $ \s -> s{stInHeading = True}@@ -587,33 +681,35 @@   modify $ \s -> s{stInHeading = False}   return hdr blockToLaTeX (Table caption aligns widths heads rows) = do-  headers <- if all null heads-                then return empty-                else do-                    contents <- (tableRowToLaTeX True aligns widths) heads-                    return ("\\toprule" $$ contents $$ "\\midrule")-  let endhead = if all null heads-                   then empty-                   else text "\\endhead"-  let endfirsthead = if all null heads-                       then empty-                       else text "\\endfirsthead"+  let toHeaders hs = do contents <- tableRowToLaTeX True aligns widths hs+                        return ("\\toprule" $$ contents $$ "\\midrule")+  let removeNote (Note _) = Span ("", [], []) []+      removeNote x        = x   captionText <- inlineListToLaTeX caption+  firsthead <- if isEmpty captionText || all null heads+                  then return empty+                  else ($$ text "\\endfirsthead") <$> toHeaders heads+  head' <- if all null heads+              then return empty+              -- avoid duplicate notes in head and firsthead:+              else ($$ text "\\endhead") <$>+                   toHeaders (if isEmpty firsthead+                                 then heads+                                 else walk removeNote heads)   let capt = if isEmpty captionText                 then empty-                else text "\\caption" <> braces captionText <> "\\tabularnewline"-                         $$ headers-                         $$ endfirsthead+                else text "\\caption" <>+                      braces captionText <> "\\tabularnewline"   rows' <- mapM (tableRowToLaTeX False aligns widths) rows-  let colDescriptors = text $ concat $ map toColDescriptor aligns+  let colDescriptors = text $ concatMap toColDescriptor aligns   modify $ \s -> s{ stTable = True }   return $ "\\begin{longtable}[]" <>               braces ("@{}" <> colDescriptors <> "@{}")               -- the @{} removes extra space at beginning and end          $$ capt+         $$ firsthead          $$ (if all null heads then "\\toprule" else empty)-         $$ headers-         $$ endhead+         $$ head'          $$ vcat rows'          $$ "\\bottomrule"          $$ "\\end{longtable}"@@ -626,14 +722,16 @@          AlignCenter  -> "c"          AlignDefault -> "l" -blockListToLaTeX :: [Block] -> State WriterState Doc-blockListToLaTeX lst = vsep `fmap` mapM blockToLaTeX lst+blockListToLaTeX :: PandocMonad m => [Block] -> LW m Doc+blockListToLaTeX lst =+  vsep `fmap` mapM (\b -> setEmptyLine True >> blockToLaTeX b) lst -tableRowToLaTeX :: Bool+tableRowToLaTeX :: PandocMonad m+                => Bool                 -> [Alignment]                 -> [Double]                 -> [[Block]]-                -> State WriterState Doc+                -> LW m Doc tableRowToLaTeX header aligns widths cols = do   -- scale factor compensates for extra space between columns   -- so the whole table isn't larger than columnwidth@@ -672,10 +770,10 @@ -- math breaks in simple tables. displayMathToInline :: Inline -> Inline displayMathToInline (Math DisplayMath x) = Math InlineMath x-displayMathToInline x = x+displayMathToInline x                    = x -tableCellToLaTeX :: Bool -> (Double, Alignment, [Block])-                 -> State WriterState Doc+tableCellToLaTeX :: PandocMonad m => Bool -> (Double, Alignment, [Block])+                 -> LW m Doc tableCellToLaTeX _      (0,     _,     blocks) =   blockListToLaTeX $ walk fixLineBreaks $ walk displayMathToInline blocks tableCellToLaTeX header (width, align, blocks) = do@@ -691,7 +789,7 @@                AlignDefault -> "\\raggedright"   return $ ("\\begin{minipage}" <> valign <>             braces (text (printf "%.2f\\columnwidth" width)) <>-            (halign <> "\\strut" <> cr <> cellContents <> "\\strut" <> cr) <>+            (halign <> cr <> cellContents <> "\\strut" <> cr) <>             "\\end{minipage}") $$             notesToLaTeX notes @@ -708,19 +806,22 @@                      $ map (\x -> "\\footnotetext" <> braces x)                      $ reverse ns) -listItemToLaTeX :: [Block] -> State WriterState Doc+listItemToLaTeX :: PandocMonad m => [Block] -> LW m Doc listItemToLaTeX lst   -- we need to put some text before a header if it's the first   -- element in an item. This will look ugly in LaTeX regardless, but   -- this will keep the typesetter from throwing an error.-  | ((Header _ _ _) :_) <- lst =-    blockListToLaTeX lst >>= return . (text "\\item ~" $$) . (nest 2)+  | (Header _ _ _ :_) <- lst =+    blockListToLaTeX lst >>= return . (text "\\item ~" $$) . nest 2   | otherwise = blockListToLaTeX lst >>= return .  (text "\\item" $$) .-                      (nest 2)+                      nest 2 -defListItemToLaTeX :: ([Inline], [[Block]]) -> State WriterState Doc+defListItemToLaTeX :: PandocMonad m => ([Inline], [[Block]]) -> LW m Doc defListItemToLaTeX (term, defs) = do+    -- needed to turn off 'listings' because it breaks inside \item[...]:+    modify $ \s -> s{stInItem = True}     term' <- inlineListToLaTeX term+    modify $ \s -> s{stInItem = False}     -- put braces around term if it contains an internal link,     -- since otherwise we get bad bracket interactions: \item[\hyperref[..]     let isInternalLink (Link _ _ ('#':_,_)) = True@@ -730,32 +831,33 @@                     else term'     def'  <- liftM vsep $ mapM blockListToLaTeX defs     return $ case defs of-     (((Header _ _ _) : _) : _) ->+     ((Header _ _ _ : _) : _) ->        "\\item" <> brackets term'' <> " ~ " $$ def'      _                          ->        "\\item" <> brackets term'' $$ def'  -- | Craft the section header, inserting the secton reference, if supplied.-sectionHeader :: Bool    -- True for unnumbered+sectionHeader :: PandocMonad m+              => Bool    -- True for unnumbered               -> [Char]               -> Int               -> [Inline]-              -> State WriterState Doc+              -> LW m Doc sectionHeader unnumbered ident level lst = do   txt <- inlineListToLaTeX lst   plain <- stringToLaTeX TextString $ concatMap stringify lst-  let removeInvalidInline (Note _)      = []+  let removeInvalidInline (Note _)             = []       removeInvalidInline (Span (id', _, _) _) | not (null id') = []-      removeInvalidInline (Image _ _ _) = []-      removeInvalidInline x             = [x]+      removeInvalidInline (Image{})            = []+      removeInvalidInline x                    = [x]   let lstNoNotes = foldr (mappend . (\x -> walkM removeInvalidInline x)) mempty lst   txtNoNotes <- inlineListToLaTeX lstNoNotes   -- footnotes in sections don't work (except for starred variants)   -- unless you specify an optional argument:   -- \section[mysec]{mysec\footnote{blah}}-  optional <- if unnumbered || lstNoNotes == lst || lstNoNotes == []+  optional <- if unnumbered || lstNoNotes == lst || null lstNoNotes                  then return empty-                 else do+                 else                    return $ brackets txtNoNotes   let contents = if render Nothing txt == plain                     then braces txt@@ -767,7 +869,8 @@   let topLevelDivision = if book && writerTopLevelDivision opts == TopLevelDefault                          then TopLevelChapter                          else writerTopLevelDivision opts-  let level' = if writerBeamer opts &&+  beamer <- gets stBeamer+  let level' = if beamer &&                   topLevelDivision `elem` [TopLevelPart, TopLevelChapter]                -- beamer has parts but no chapters                then if level == 1 then -1 else level - 1@@ -794,7 +897,8 @@   lab <- labelFor ident   let star = if unnumbered && level' < 4 then text "*" else empty   let stuffing = star <> optional <> contents-  stuffing' <- hypertarget ident $ text ('\\':sectionType) <> stuffing <> lab+  stuffing' <- hypertarget True ident $+                  text ('\\':sectionType) <> stuffing <> lab   return $ if level' > 5               then txt               else prefix $$ stuffing'@@ -804,28 +908,28 @@                                 braces txtNoNotes                          else empty -hypertarget :: String -> Doc -> State WriterState Doc-hypertarget ident x = do+hypertarget :: PandocMonad m => Bool -> String -> Doc -> LW m Doc+hypertarget _ "" x    = return x+hypertarget addnewline ident x = do   ref <- text `fmap` toLabel ident-  internalLinks <- gets stInternalLinks-  return $-    if ident `elem` internalLinks-       then text "\\hypertarget"+  return $ text "\\hypertarget"               <> braces ref-              <> braces x-       else x+              <> braces ((if addnewline && not (isEmpty x)+                             then ("%" <> cr)+                             else empty) <> x) -labelFor :: String -> State WriterState Doc+labelFor :: PandocMonad m => String -> LW m Doc labelFor ""    = return empty labelFor ident = do   ref <- text `fmap` toLabel ident   return $ text "\\label" <> braces ref  -- | Convert list of inline elements to LaTeX.-inlineListToLaTeX :: [Inline]  -- ^ Inlines to convert-                  -> State WriterState Doc+inlineListToLaTeX :: PandocMonad m+                  => [Inline]  -- ^ Inlines to convert+                  -> LW m Doc inlineListToLaTeX lst =-  mapM inlineToLaTeX (fixBreaks $ fixLineInitialSpaces lst)+  mapM inlineToLaTeX (fixLineInitialSpaces lst)     >>= return . hcat     -- nonbreaking spaces (~) in LaTeX don't work after line breaks,     -- so we turn nbsps after hard breaks to \hspace commands.@@ -837,43 +941,35 @@        fixNbsps s = let (ys,zs) = span (=='\160') s                     in  replicate (length ys) hspace ++ [Str zs]        hspace = RawInline "latex" "\\hspace*{0.333em}"-       -- linebreaks after blank lines cause problems:-       fixBreaks [] = []-       fixBreaks ys@(LineBreak : LineBreak : _) =-         case span (== LineBreak) ys of-               (lbs, rest) -> RawInline "latex"-                               ("\\\\[" ++ show (length lbs) ++-                                "\\baselineskip]") : fixBreaks rest-       fixBreaks (y:ys) = y : fixBreaks ys  isQuoted :: Inline -> Bool isQuoted (Quoted _ _) = True-isQuoted _ = False+isQuoted _            = False  -- | Convert inline element to LaTeX-inlineToLaTeX :: Inline    -- ^ Inline to convert-              -> State WriterState Doc+inlineToLaTeX :: PandocMonad m+              => Inline    -- ^ Inline to convert+              -> LW m Doc inlineToLaTeX (Span (id',classes,kvs) ils) = do-  ref <- toLabel id'-  let linkAnchor = if null id'-                      then empty-                      else "\\protect\\hypertarget" <> braces (text ref) <>-                             braces empty+  linkAnchor <- hypertarget False id' empty+  lang <- toLang $ lookup "lang" kvs   let cmds = ["textup" | "csl-no-emph" `elem` classes] ++              ["textnormal" | "csl-no-strong" `elem` classes ||                              "csl-no-smallcaps" `elem` classes] ++              ["RL" | ("dir", "rtl") `elem` kvs] ++              ["LR" | ("dir", "ltr") `elem` kvs] ++-             (case lookup "lang" kvs of-                Just lng -> let (l, o) = toPolyglossia $ splitBy (=='-') lng+             (case lang of+                Just lng -> let (l, o) = toPolyglossia lng                                 ops = if null o then "" else ("[" ++ o ++ "]")                             in  ["text" ++ l ++ ops]                 Nothing  -> [])   contents <- inlineListToLaTeX ils-  return $ linkAnchor <>-           if null cmds-              then braces contents-              else foldr inCmd contents cmds+  return $ (if null id'+               then empty+               else "\\protect" <> linkAnchor) <>+           (if null cmds+               then braces contents+               else foldr inCmd contents cmds) inlineToLaTeX (Emph lst) =   inlineListToLaTeX lst >>= return . inCmd "emph" inlineToLaTeX (Strong lst) =@@ -886,7 +982,7 @@   return $ inCmd "sout" contents inlineToLaTeX (Superscript lst) =   inlineListToLaTeX lst >>= return . inCmd "textsuperscript"-inlineToLaTeX (Subscript lst) = do+inlineToLaTeX (Subscript lst) =   inlineListToLaTeX lst >>= return . inCmd "textsubscript" inlineToLaTeX (SmallCaps lst) =   inlineListToLaTeX lst >>= return . inCmd "textsc"@@ -901,26 +997,39 @@ inlineToLaTeX (Code (_,classes,_) str) = do   opts <- gets stOptions   inHeading <- gets stInHeading+  inItem <- gets stInItem+  let listingsCode = do+        let listingsopt = case getListingsLanguage classes of+                               Just l  -> "[language=" ++ mbBraced l ++ "]"+                               Nothing -> ""+        inNote <- gets stInNote+        when inNote $ modify $ \s -> s{ stVerbInNote = True }+        let chr = case "!\"&'()*,-./:;?@_" \\ str of+                       (c:_) -> c+                       []    -> '!'+        let str' = escapeStringUsing (backslashEscapes "\\{}%") str+        -- we always put lstinline in a dummy 'passthrough' command+        -- (defined in the default template) so that we don't have+        -- to change the way we escape characters depending on whether+        -- the lstinline is inside another command.  See #1629:+        return $ text $ "\\passthrough{\\lstinline" ++ listingsopt ++ [chr] ++ str' ++ [chr] ++ "}"+  let rawCode = liftM (text . (\s -> "\\texttt{" ++ escapeSpaces s ++ "}"))+                 $ stringToLaTeX CodeString str+                where escapeSpaces =  concatMap+                         (\c -> if c == ' ' then "\\ " else [c])+  let highlightCode =+        case highlight (writerSyntaxMap opts)+                 formatLaTeXInline ("",classes,[]) str of+               Left msg -> do+                 unless (null msg) $ report $ CouldNotHighlight msg+                 rawCode+               Right h -> modify (\st -> st{ stHighlighting = True }) >>+                          return (text (T.unpack h))   case () of-     _ | writerListings opts  && not inHeading      -> listingsCode-       | writerHighlight opts && not (null classes) -> highlightCode+     _ | writerListings opts  && not (inHeading || inItem) -> listingsCode+       | isJust (writerHighlightStyle opts) && not (null classes)+                                                    -> highlightCode        | otherwise                                  -> rawCode-   where listingsCode = do-           inNote <- gets stInNote-           when inNote $ modify $ \s -> s{ stVerbInNote = True }-           let chr = case "!\"&'()*,-./:;?@_" \\ str of-                          (c:_) -> c-                          []    -> '!'-           return $ text $ "\\lstinline" ++ [chr] ++ str ++ [chr]-         highlightCode = do-           case highlight formatLaTeXInline ("",classes,[]) str of-                  Nothing -> rawCode-                  Just  h -> modify (\st -> st{ stHighlighting = True }) >>-                             return (text (T.unpack h))-         rawCode = liftM (text . (\s -> "\\texttt{" ++ escapeSpaces s ++ "}"))-                          $ stringToLaTeX CodeString str-           where-             escapeSpaces =  concatMap (\c -> if c == ' ' then "\\ " else [c]) inlineToLaTeX (Quoted qt lst) = do   contents <- inlineListToLaTeX lst   csquotes <- liftM stCsquotes get@@ -928,32 +1037,43 @@   if csquotes      then return $ "\\enquote" <> braces contents      else do-       let s1 = if (not (null lst)) && (isQuoted (head lst))+       let s1 = if not (null lst) && isQuoted (head lst)                    then "\\,"                    else empty-       let s2 = if (not (null lst)) && (isQuoted (last lst))+       let s2 = if not (null lst) && isQuoted (last lst)                    then "\\,"                    else empty        let inner = s1 <> contents <> s2        return $ case qt of                 DoubleQuote ->-                   if writerTeXLigatures opts+                   if isEnabled Ext_smart opts                       then text "``" <> inner <> text "''"                       else char '\x201C' <> inner <> char '\x201D'                 SingleQuote ->-                   if writerTeXLigatures opts+                   if isEnabled Ext_smart opts                       then char '`' <> inner <> char '\''                       else char '\x2018' <> inner <> char '\x2019'-inlineToLaTeX (Str str) = liftM text $ stringToLaTeX TextString str-inlineToLaTeX (Math InlineMath str) =+inlineToLaTeX (Str str) = do+  setEmptyLine False+  liftM text $ stringToLaTeX TextString str+inlineToLaTeX (Math InlineMath str) = do+  setEmptyLine False   return $ "\\(" <> text str <> "\\)"-inlineToLaTeX (Math DisplayMath str) =+inlineToLaTeX (Math DisplayMath str) = do+  setEmptyLine False   return $ "\\[" <> text str <> "\\]"-inlineToLaTeX (RawInline f str)+inlineToLaTeX il@(RawInline f str)   | f == Format "latex" || f == Format "tex"-                        = return $ text str-  | otherwise           = return empty-inlineToLaTeX (LineBreak) = return $ "\\\\" <> cr+                        = do+      setEmptyLine False+      return $ text str+  | otherwise           = do+      report $ InlineNotRendered il+      return empty+inlineToLaTeX LineBreak = do+  emptyLine <- gets stEmptyLine+  setEmptyLine True+  return $ (if emptyLine then "~" else "") <> "\\\\" <> cr inlineToLaTeX SoftBreak = do   wrapText <- gets (writerWrapText . stOptions)   case wrapText of@@ -982,11 +1102,15 @@                 src' <- stringToLaTeX URLString (escapeURI src)                 return $ text ("\\href{" ++ src' ++ "}{") <>                          contents <> char '}'+inlineToLaTeX il@(Image _ _ ('d':'a':'t':'a':':':_, _)) = do+  report $ InlineNotRendered il+  return empty inlineToLaTeX (Image attr _ (source, _)) = do+  setEmptyLine False   modify $ \s -> s{ stGraphics = True }   opts <- gets stOptions   let showDim dir = let d = text (show dir) <> "="-                    in case (dimension dir attr) of+                    in case dimension dir attr of                          Just (Pixel a)   ->                            [d <> text (showInInch opts (Pixel a)) <> "in"]                          Just (Percent a) ->@@ -1008,6 +1132,7 @@     (if inHeading then "\\protect\\includegraphics" else "\\includegraphics") <>     dims <> braces (text source'') inlineToLaTeX (Note contents) = do+  setEmptyLine False   inMinipage <- gets stInMinipage   modify (\s -> s{stInNote = True})   contents' <- blockListToLaTeX contents@@ -1016,9 +1141,9 @@                    (CodeBlock _ _ : _) -> cr                    _                   -> empty   let noteContents = nest 2 contents' <> optnl-  opts <- gets stOptions+  beamer <- gets stBeamer   -- in beamer slides, display footnote from current overlay forward-  let beamerMark = if writerBeamer opts+  let beamerMark = if beamer                       then text "<.->"                       else empty   modify $ \st -> st{ stNotes = noteContents : stNotes st }@@ -1035,8 +1160,12 @@   where ltx = RawInline (Format "latex") protectCode (x : xs) = x : protectCode xs -citationsToNatbib :: [Citation] -> State WriterState Doc-citationsToNatbib (one:[])+setEmptyLine :: PandocMonad m => Bool -> LW m ()+setEmptyLine b = modify $ \st -> st{ stEmptyLine = b }++citationsToNatbib :: PandocMonad m => [Citation] -> LW m Doc+citationsToNatbib+            [one]   = citeCommand c p s k   where     Citation { citationId = k@@ -1046,8 +1175,8 @@              }       = one     c = case m of-             AuthorInText     -> "citet"-             SuppressAuthor  -> "citeyearpar"+             AuthorInText   -> "citet"+             SuppressAuthor -> "citeyearpar"              NormalCitation -> "citep"  citationsToNatbib cits@@ -1056,9 +1185,11 @@   where      noPrefix  = all (null . citationPrefix)      noSuffix  = all (null . citationSuffix)-     ismode m  = all (((==) m)  . citationMode)-     p         = citationPrefix  $ head $ cits-     s         = citationSuffix  $ last $ cits+     ismode m  = all ((==) m  . citationMode)+     p         = citationPrefix  $+                 head cits+     s         = citationSuffix  $+                 last cits      ks        = intercalate ", " $ map citationId cits  citationsToNatbib (c:cs) | citationMode c == AuthorInText = do@@ -1082,17 +1213,20 @@                SuppressAuthor -> citeCommand "citeyear" p s k                NormalCitation -> citeCommand "citealp"  p s k -citeCommand :: String -> [Inline] -> [Inline] -> String -> State WriterState Doc+citeCommand :: PandocMonad m+            => String -> [Inline] -> [Inline] -> String -> LW m Doc citeCommand c p s k = do   args <- citeArguments p s k   return $ text ("\\" ++ c) <> args -citeArguments :: [Inline] -> [Inline] -> String -> State WriterState Doc+citeArguments :: PandocMonad m+              => [Inline] -> [Inline] -> String -> LW m Doc citeArguments p s k = do   let s' = case s of-        (Str (x:[]) : r) | isPunctuation x -> dropWhile (== Space) r+        (Str+                    [x] : r) | isPunctuation x -> dropWhile (== Space) r         (Str (x:xs) : r) | isPunctuation x -> Str xs : r-        _                                  -> s+        _                -> s   pdoc <- inlineListToLaTeX p   sdoc <- inlineListToLaTeX s'   let optargs = case (isEmpty pdoc, isEmpty sdoc) of@@ -1101,8 +1235,9 @@                      (_   , _    ) -> brackets pdoc <> brackets sdoc   return $ optargs <> braces (text k) -citationsToBiblatex :: [Citation] -> State WriterState Doc-citationsToBiblatex (one:[])+citationsToBiblatex :: PandocMonad m => [Citation] -> LW m Doc+citationsToBiblatex+            [one]   = citeCommand cmd p s k     where        Citation { citationId = k@@ -1133,15 +1268,20 @@  -- Determine listings language from list of class attributes. getListingsLanguage :: [String] -> Maybe String-getListingsLanguage [] = Nothing-getListingsLanguage (x:xs) = toListingsLanguage x <|> getListingsLanguage xs+getListingsLanguage xs+  = foldr ((<|>) . toListingsLanguage) Nothing xs +mbBraced :: String -> String+mbBraced x = if not (all isAlphaNum x)+                then "{" <> x <> "}"+                else x+ -- Extract a key from divs and spans extract :: String -> Block -> [String] extract key (Div attr _)     = lookKey key attr-extract key (Plain ils)      = concatMap (extractInline key) ils-extract key (Para ils)       = concatMap (extractInline key) ils-extract key (Header _ _ ils) = concatMap (extractInline key) ils+extract key (Plain ils)      = query (extractInline key) ils+extract key (Para ils)       = query (extractInline key) ils+extract key (Header _ _ ils) = query (extractInline key) ils extract _ _                  = []  -- Extract a key from spans@@ -1154,85 +1294,95 @@ lookKey key (_,_,kvs) =  maybe [] words $ lookup key kvs  -- In environments \Arabic instead of \arabic is used-toPolyglossiaEnv :: String -> (String, String)+toPolyglossiaEnv :: Lang -> (String, String) toPolyglossiaEnv l =-  case toPolyglossia $ (splitBy (=='-')) l of+  case toPolyglossia l of     ("arabic", o) -> ("Arabic", o)     x             -> x  -- Takes a list of the constituents of a BCP 47 language code and -- converts it to a Polyglossia (language, options) tuple -- http://mirrors.ctan.org/macros/latex/contrib/polyglossia/polyglossia.pdf-toPolyglossia :: [String] -> (String, String)-toPolyglossia ("ar":"DZ":_)        = ("arabic", "locale=algeria")-toPolyglossia ("ar":"IQ":_)        = ("arabic", "locale=mashriq")-toPolyglossia ("ar":"JO":_)        = ("arabic", "locale=mashriq")-toPolyglossia ("ar":"LB":_)        = ("arabic", "locale=mashriq")-toPolyglossia ("ar":"LY":_)        = ("arabic", "locale=libya")-toPolyglossia ("ar":"MA":_)        = ("arabic", "locale=morocco")-toPolyglossia ("ar":"MR":_)        = ("arabic", "locale=mauritania")-toPolyglossia ("ar":"PS":_)        = ("arabic", "locale=mashriq")-toPolyglossia ("ar":"SY":_)        = ("arabic", "locale=mashriq")-toPolyglossia ("ar":"TN":_)        = ("arabic", "locale=tunisia")-toPolyglossia ("de":"1901":_)      = ("german", "spelling=old")-toPolyglossia ("de":"AT":"1901":_) = ("german", "variant=austrian, spelling=old")-toPolyglossia ("de":"AT":_)        = ("german", "variant=austrian")-toPolyglossia ("de":"CH":"1901":_) = ("german", "variant=swiss, spelling=old")-toPolyglossia ("de":"CH":_)        = ("german", "variant=swiss")-toPolyglossia ("de":_)             = ("german", "")-toPolyglossia ("dsb":_)            = ("lsorbian", "")-toPolyglossia ("el":"polyton":_)   = ("greek",   "variant=poly")-toPolyglossia ("en":"AU":_)        = ("english", "variant=australian")-toPolyglossia ("en":"CA":_)        = ("english", "variant=canadian")-toPolyglossia ("en":"GB":_)        = ("english", "variant=british")-toPolyglossia ("en":"NZ":_)        = ("english", "variant=newzealand")-toPolyglossia ("en":"UK":_)        = ("english", "variant=british")-toPolyglossia ("en":"US":_)        = ("english", "variant=american")-toPolyglossia ("grc":_)            = ("greek",   "variant=ancient")-toPolyglossia ("hsb":_)            = ("usorbian", "")-toPolyglossia ("la":"x":"classic":_) = ("latin", "variant=classic")-toPolyglossia ("sl":_)             = ("slovenian", "")-toPolyglossia x                    = (commonFromBcp47 x, "")+toPolyglossia :: Lang -> (String, String)+toPolyglossia (Lang "ar" _ "DZ" _)        = ("arabic", "locale=algeria")+toPolyglossia (Lang "ar" _ "IQ" _)        = ("arabic", "locale=mashriq")+toPolyglossia (Lang "ar" _ "JO" _)        = ("arabic", "locale=mashriq")+toPolyglossia (Lang "ar" _ "LB" _)        = ("arabic", "locale=mashriq")+toPolyglossia (Lang "ar" _ "LY" _)        = ("arabic", "locale=libya")+toPolyglossia (Lang "ar" _ "MA" _)        = ("arabic", "locale=morocco")+toPolyglossia (Lang "ar" _ "MR" _)        = ("arabic", "locale=mauritania")+toPolyglossia (Lang "ar" _ "PS" _)        = ("arabic", "locale=mashriq")+toPolyglossia (Lang "ar" _ "SY" _)        = ("arabic", "locale=mashriq")+toPolyglossia (Lang "ar" _ "TN" _)        = ("arabic", "locale=tunisia")+toPolyglossia (Lang "de" _ _ vars)+  | "1901" `elem` vars                    = ("german", "spelling=old")+toPolyglossia (Lang "de" _ "AT" vars)+  | "1901" `elem` vars                    = ("german", "variant=austrian, spelling=old")+toPolyglossia (Lang "de" _ "AT" _)        = ("german", "variant=austrian")+toPolyglossia (Lang "de" _ "CH" vars)+  | "1901" `elem` vars                    = ("german", "variant=swiss, spelling=old")+toPolyglossia (Lang "de" _ "CH" _)        = ("german", "variant=swiss")+toPolyglossia (Lang "de" _ _ _)           = ("german", "")+toPolyglossia (Lang "dsb" _ _ _)          = ("lsorbian", "")+toPolyglossia (Lang "el" _ "polyton" _)   = ("greek",   "variant=poly")+toPolyglossia (Lang "en" _ "AU" _)        = ("english", "variant=australian")+toPolyglossia (Lang "en" _ "CA" _)        = ("english", "variant=canadian")+toPolyglossia (Lang "en" _ "GB" _)        = ("english", "variant=british")+toPolyglossia (Lang "en" _ "NZ" _)        = ("english", "variant=newzealand")+toPolyglossia (Lang "en" _ "UK" _)        = ("english", "variant=british")+toPolyglossia (Lang "en" _ "US" _)        = ("english", "variant=american")+toPolyglossia (Lang "grc" _ _ _)          = ("greek",   "variant=ancient")+toPolyglossia (Lang "hsb" _ _  _)         = ("usorbian", "")+toPolyglossia (Lang "la" _ _ vars)+  | "x-classic" `elem` vars               = ("latin", "variant=classic")+toPolyglossia (Lang "sl" _ _ _)           = ("slovenian", "")+toPolyglossia x                           = (commonFromBcp47 x, "")  -- Takes a list of the constituents of a BCP 47 language code and -- converts it to a Babel language string. -- http://mirrors.ctan.org/macros/latex/required/babel/base/babel.pdf -- List of supported languages (slightly outdated): -- http://tug.ctan.org/language/hyph-utf8/doc/generic/hyph-utf8/hyphenation.pdf-toBabel :: [String] -> String-toBabel ("de":"1901":_)      = "german"-toBabel ("de":"AT":"1901":_) = "austrian"-toBabel ("de":"AT":_)        = "naustrian"-toBabel ("de":"CH":"1901":_) = "swissgerman"-toBabel ("de":"CH":_)        = "nswissgerman"-toBabel ("de":_)             = "ngerman"-toBabel ("dsb":_)            = "lowersorbian"-toBabel ("el":"polyton":_)   = "polutonikogreek"-toBabel ("en":"AU":_)        = "australian"-toBabel ("en":"CA":_)        = "canadian"-toBabel ("en":"GB":_)        = "british"-toBabel ("en":"NZ":_)        = "newzealand"-toBabel ("en":"UK":_)        = "british"-toBabel ("en":"US":_)        = "american"-toBabel ("fr":"CA":_)        = "canadien"-toBabel ("fra":"aca":_)      = "acadian"-toBabel ("grc":_)            = "polutonikogreek"-toBabel ("hsb":_)            = "uppersorbian"-toBabel ("la":"x":"classic":_) = "classiclatin"-toBabel ("sl":_)             = "slovene"-toBabel x                    = commonFromBcp47 x+toBabel :: Lang -> String+toBabel (Lang "de" _ "AT" vars)+  | "1901" `elem` vars                  = "austrian"+  | otherwise                           = "naustrian"+toBabel (Lang "de" _ "CH" vars)+  | "1901" `elem` vars                  = "swissgerman"+  | otherwise                           = "nswissgerman"+toBabel (Lang "de" _ _ vars)+  | "1901" `elem` vars                  = "german"+  | otherwise                           = "ngerman"+toBabel (Lang "dsb" _ _ _)              = "lowersorbian"+toBabel (Lang "el" _ _ vars)+  | "polyton" `elem` vars               = "polutonikogreek"+toBabel (Lang "en" _ "AU" _)            = "australian"+toBabel (Lang "en" _ "CA" _)            = "canadian"+toBabel (Lang "en" _ "GB" _)            = "british"+toBabel (Lang "en" _ "NZ" _)            = "newzealand"+toBabel (Lang "en" _ "UK" _)            = "british"+toBabel (Lang "en" _ "US" _)            = "american"+toBabel (Lang "fr" _ "CA" _)            = "canadien"+toBabel (Lang "fra" _ _ vars)+  | "aca" `elem` vars                   = "acadian"+toBabel (Lang "grc" _ _ _)              = "polutonikogreek"+toBabel (Lang "hsb" _ _ _)              = "uppersorbian"+toBabel (Lang "la" _ _ vars)+  | "x-classic" `elem` vars             = "classiclatin"+toBabel (Lang "sl" _ _ _)               = "slovene"+toBabel x                               = commonFromBcp47 x  -- Takes a list of the constituents of a BCP 47 language code -- and converts it to a string shared by Babel and Polyglossia. -- https://tools.ietf.org/html/bcp47#section-2.1-commonFromBcp47 :: [String] -> String-commonFromBcp47 [] = ""-commonFromBcp47 ("pt":"BR":_)            = "brazil"+commonFromBcp47 :: Lang -> String+commonFromBcp47 (Lang "pt" _ "BR" _)            = "brazil" -- Note: documentation says "brazilian" works too, but it doesn't seem to work -- on some systems.  See #2953.-commonFromBcp47 ("sr":"Cyrl":_)          = "serbianc"-commonFromBcp47 ("zh":"Latn":"pinyin":_) = "pinyin"-commonFromBcp47 x = fromIso $ head x+commonFromBcp47 (Lang "sr" "Cyrl" _ _)          = "serbianc"+commonFromBcp47 (Lang "zh" "Latn" _ vars)+  | "pinyin" `elem` vars                        = "pinyin"+commonFromBcp47 (Lang l _ _ _) = fromIso l   where     fromIso "af"  = "afrikaans"     fromIso "am"  = "amharic"@@ -1315,10 +1465,6 @@     fromIso "ur"  = "urdu"     fromIso "vi"  = "vietnamese"     fromIso _     = ""--deNote :: Inline -> Inline-deNote (Note _) = RawInline (Format "latex") ""-deNote x = x  pDocumentOptions :: P.Parsec String () [String] pDocumentOptions = do
src/Text/Pandoc/Writers/Man.hs view
@@ -1,5 +1,6 @@+{-# LANGUAGE OverloadedStrings #-} {--Copyright (C) 2007-2015 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2007-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -18,7 +19,7 @@  {- |    Module      : Text.Pandoc.Writers.Man-   Copyright   : Copyright (C) 2007-2015 John MacFarlane+   Copyright   : Copyright (C) 2007-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -29,79 +30,95 @@  -} module Text.Pandoc.Writers.Man ( writeMan) where+import Control.Monad.State.Strict+import Data.List (intercalate, intersperse, sort, stripPrefix)+import qualified Data.Map as Map+import Data.Maybe (fromMaybe)+import Data.Text (Text)+import qualified Data.Text as T+import Text.Pandoc.Builder (deleteMeta)+import Text.Pandoc.Class (PandocMonad, report) import Text.Pandoc.Definition-import Text.Pandoc.Templates-import Text.Pandoc.Shared-import Text.Pandoc.Writers.Shared+import Text.Pandoc.Logging import Text.Pandoc.Options-import Text.Pandoc.Readers.TeXMath-import Text.Printf ( printf )-import Data.List ( stripPrefix, intersperse, intercalate )-import Data.Maybe (fromMaybe) import Text.Pandoc.Pretty-import Text.Pandoc.Builder (deleteMeta)-import Control.Monad.State+import Text.Pandoc.Shared+import Text.Pandoc.Templates+import Text.Pandoc.Writers.Math+import Text.Pandoc.Writers.Shared+import Text.Printf (printf)  type Notes = [[Block]]-data WriterState = WriterState { stNotes  :: Notes-                               , stHasTables :: Bool }+data WriterState = WriterState { stNotes        :: Notes+                               , stFontFeatures :: Map.Map Char Bool+                               , stHasTables    :: Bool } +defaultWriterState :: WriterState+defaultWriterState = WriterState { stNotes = []+                                 , stFontFeatures  = Map.fromList [+                                                       ('I',False)+                                                     , ('B',False)+                                                     , ('C',False)+                                                     ]+                                 , stHasTables  = False }+ -- | Convert Pandoc to Man.-writeMan :: WriterOptions -> Pandoc -> String-writeMan opts document = evalState (pandocToMan opts document) (WriterState [] False)+writeMan :: PandocMonad m => WriterOptions -> Pandoc -> m Text+writeMan opts document =+  evalStateT (pandocToMan opts document) defaultWriterState  -- | Return groff man representation of document.-pandocToMan :: WriterOptions -> Pandoc -> State WriterState String+pandocToMan :: PandocMonad m => WriterOptions -> Pandoc -> StateT WriterState m Text pandocToMan opts (Pandoc meta blocks) = do   let colwidth = if writerWrapText opts == WrapAuto                     then Just $ writerColumns opts                     else Nothing-  let render' = render colwidth+  let render' :: Doc -> Text+      render' = render colwidth   titleText <- inlineListToMan opts $ docTitle meta   let title' = render' titleText   let setFieldsFromTitle =-       case break (== ' ') title' of-           (cmdName, rest) -> case break (=='(') cmdName of-                                   (xs, '(':ys) | not (null ys) &&-                                                  last ys == ')' ->+       case T.break (== ' ') title' of+           (cmdName, rest) -> case T.break (=='(') cmdName of+                                   (xs, ys) | "(" `T.isPrefixOf` ys+                                                && ")" `T.isSuffixOf` ys ->                                      defField "title" xs .-                                     defField "section" (init ys) .-                                     case splitBy (=='|') rest of+                                     defField "section" (T.init $ T.drop 1 ys) .+                                     case T.splitOn "|" rest of                                           (ft:hds) ->-                                            defField "footer" (trim ft) .+                                            defField "footer" (T.strip ft) .                                             defField "header"-                                               (trim $ concat hds)+                                               (T.strip $ mconcat hds)                                           [] -> id                                    _  -> defField "title" title'   metadata <- metaToJSON opts-              (fmap (render colwidth) . blockListToMan opts)-              (fmap (render colwidth) . inlineListToMan opts)+              (fmap render' . blockListToMan opts)+              (fmap render' . inlineListToMan opts)               $ deleteMeta "title" meta   body <- blockListToMan opts blocks-  notes <- liftM stNotes get+  notes <- gets stNotes   notes' <- notesToMan opts (reverse notes)   let main = render' $ body $$ notes' $$ text ""-  hasTables <- liftM stHasTables get+  hasTables <- gets stHasTables   let context = defField "body" main               $ setFieldsFromTitle               $ defField "has-tables" hasTables               $ defField "hyphenate" True-              $ defField "pandoc-version" pandocVersion-              $ metadata+              $ defField "pandoc-version" pandocVersion metadata   case writerTemplate opts of        Nothing  -> return main-       Just tpl -> return $ renderTemplate' tpl context+       Just tpl -> renderTemplate' tpl context  -- | Return man representation of notes.-notesToMan :: WriterOptions -> [[Block]] -> State WriterState Doc+notesToMan :: PandocMonad m => WriterOptions -> [[Block]] -> StateT WriterState m Doc notesToMan opts notes =   if null notes      then return empty-     else mapM (\(num, note) -> noteToMan opts num note) (zip [1..] notes) >>=+     else mapM (uncurry (noteToMan opts)) (zip [1..] notes) >>=           return . (text ".SH NOTES" $$) . vcat  -- | Return man representation of a note.-noteToMan :: WriterOptions -> Int -> [Block] -> State WriterState Doc+noteToMan :: PandocMonad m => WriterOptions -> Int -> [Block] -> StateT WriterState m Doc noteToMan opts num note = do   contents <- blockListToMan opts note   let marker = cr <> text ".SS " <> brackets (text (show num))@@ -123,11 +140,11 @@  -- | Escape a literal (code) section for Man. escapeCode :: String -> String-escapeCode = concat . intersperse "\n" . map escapeLine . lines  where+escapeCode = intercalate "\n" . map escapeLine . lines  where   escapeLine codeline =     case escapeStringUsing (manEscapes ++ backslashEscapes "\t ") codeline of       a@('.':_) -> "\\&" ++ a-      b       -> b+      b         -> b  -- We split inline lists into sentences, and print one sentence per -- line.  groff/troff treats the line-ending period differently.@@ -139,8 +156,8 @@ breakSentence xs =   let isSentenceEndInline (Str ys@(_:_)) | last ys == '.' = True       isSentenceEndInline (Str ys@(_:_)) | last ys == '?' = True-      isSentenceEndInline (LineBreak) = True-      isSentenceEndInline _         = False+      isSentenceEndInline LineBreak      = True+      isSentenceEndInline _              = False       (as, bs) = break isSentenceEndInline xs   in  case bs of            []             -> (as, [])@@ -160,9 +177,10 @@   in  if null rest then [sent] else sent : splitSentences rest  -- | Convert Pandoc block element to man.-blockToMan :: WriterOptions -- ^ Options-                -> Block         -- ^ Block element-                -> State WriterState Doc+blockToMan :: PandocMonad m+           => WriterOptions -- ^ Options+           -> Block         -- ^ Block element+           -> StateT WriterState m Doc blockToMan _ Null = return empty blockToMan opts (Div _ bs) = blockListToMan opts bs blockToMan opts (Plain inlines) =@@ -173,9 +191,11 @@   return $ text ".PP" $$ contents blockToMan opts (LineBlock lns) =   blockToMan opts $ linesToPara lns-blockToMan _ (RawBlock f str)+blockToMan _ b@(RawBlock f str)   | f == Format "man" = return $ text str-  | otherwise         = return empty+  | otherwise         = do+      report $ BlockNotRendered b+      return empty blockToMan _ HorizontalRule = return $ text ".PP" $$ text "   *   *   *   *   *" blockToMan opts (Header level _ inlines) = do   contents <- inlineListToMan opts inlines@@ -205,12 +225,12 @@                    then repeat ""                    else map (printf "w(%0.1fn)" . (70 *)) widths   -- 78n default width - 8n indent = 70n-  let coldescriptions = text $ intercalate " "+  let coldescriptions = text $ unwords                         (zipWith (\align width -> aligncode align ++ width)                         alignments iwidths) ++ "."   colheadings <- mapM (blockListToMan opts) headers   let makeRow cols = text "T{" $$-                     (vcat $ intersperse (text "T}@T{") cols) $$+                     vcat (intersperse (text "T}@T{") cols) $$                      text "T}"   let colheadings' = if all null headers                         then empty@@ -227,7 +247,8 @@   return (vcat contents) blockToMan opts (OrderedList attribs items) = do   let markers = take (length items) $ orderedListMarkers attribs-  let indent = 1 + (maximum $ map length markers)+  let indent = 1 ++                     maximum (map length markers)   contents <- mapM (\(num, item) -> orderedListItemToMan opts num indent item) $               zip markers items   return (vcat contents)@@ -236,11 +257,11 @@   return (vcat contents)  -- | Convert bullet list item (list of blocks) to man.-bulletListItemToMan :: WriterOptions -> [Block] -> State WriterState Doc+bulletListItemToMan :: PandocMonad m => WriterOptions -> [Block] -> StateT WriterState m Doc bulletListItemToMan _ [] = return empty-bulletListItemToMan opts ((Para first):rest) =-  bulletListItemToMan opts ((Plain first):rest)-bulletListItemToMan opts ((Plain first):rest) = do+bulletListItemToMan opts (Para first:rest) =+  bulletListItemToMan opts (Plain first:rest)+bulletListItemToMan opts (Plain first:rest) = do   first' <- blockToMan opts (Plain first)   rest' <- blockListToMan opts rest   let first'' = text ".IP \\[bu] 2" $$ first'@@ -254,14 +275,15 @@   return $ text "\\[bu] .RS 2" $$ first' $$ rest' $$ text ".RE"  -- | Convert ordered list item (a list of blocks) to man.-orderedListItemToMan :: WriterOptions -- ^ options-                          -> String   -- ^ order marker for list item-                          -> Int      -- ^ number of spaces to indent-                          -> [Block]  -- ^ list item (list of blocks)-                          -> State WriterState Doc+orderedListItemToMan :: PandocMonad m+                     => WriterOptions -- ^ options+                     -> String   -- ^ order marker for list item+                     -> Int      -- ^ number of spaces to indent+                     -> [Block]  -- ^ list item (list of blocks)+                     -> StateT WriterState m Doc orderedListItemToMan _ _ _ [] = return empty-orderedListItemToMan opts num indent ((Para first):rest) =-  orderedListItemToMan opts num indent ((Plain first):rest)+orderedListItemToMan opts num indent (Para first:rest) =+  orderedListItemToMan opts num indent (Plain first:rest) orderedListItemToMan opts num indent (first:rest) = do   first' <- blockToMan opts first   rest' <- blockListToMan opts rest@@ -273,44 +295,47 @@   return $ first'' $$ rest''  -- | Convert definition list item (label, list of blocks) to man.-definitionListItemToMan :: WriterOptions-                             -> ([Inline],[[Block]])-                             -> State WriterState Doc+definitionListItemToMan :: PandocMonad m+                        => WriterOptions+                        -> ([Inline],[[Block]])+                        -> StateT WriterState m Doc definitionListItemToMan opts (label, defs) = do   labelText <- inlineListToMan opts label   contents <- if null defs                  then return empty-                 else liftM vcat $ forM defs $ \blocks -> do-                        let (first, rest) = case blocks of-                              ((Para x):y) -> (Plain x,y)-                              (x:y)        -> (x,y)-                              []           -> error "blocks is null"-                        rest' <- liftM vcat $-                                  mapM (\item -> blockToMan opts item) rest-                        first' <- blockToMan opts first-                        return $ first' $$ text ".RS" $$ rest' $$ text ".RE"+                 else liftM vcat $ forM defs $ \blocks ->+                        case blocks of+                          (x:xs) -> do+                            first' <- blockToMan opts $+                                      case x of+                                           Para y -> Plain y+                                           _      -> x+                            rest' <- liftM vcat $ mapM+                                        (\item -> blockToMan opts item) xs+                            return $ first' $$+                                     text ".RS" $$ rest' $$ text ".RE"+                          [] -> return empty   return $ text ".TP" $$ nowrap (text ".B " <> labelText) $$ contents  -- | Convert list of Pandoc block elements to man.-blockListToMan :: WriterOptions -- ^ Options-                    -> [Block]       -- ^ List of block elements-                    -> State WriterState Doc+blockListToMan :: PandocMonad m+               => WriterOptions -- ^ Options+               -> [Block]       -- ^ List of block elements+               -> StateT WriterState m Doc blockListToMan opts blocks =   mapM (blockToMan opts) blocks >>= (return . vcat)  -- | Convert list of Pandoc inline elements to man.-inlineListToMan :: WriterOptions -> [Inline] -> State WriterState Doc+inlineListToMan :: PandocMonad m => WriterOptions -> [Inline] -> StateT WriterState m Doc inlineListToMan opts lst = mapM (inlineToMan opts) lst >>= (return . hcat)  -- | Convert Pandoc inline element to man.-inlineToMan :: WriterOptions -> Inline -> State WriterState Doc+inlineToMan :: PandocMonad m => WriterOptions -> Inline -> StateT WriterState m Doc inlineToMan opts (Span _ ils) = inlineListToMan opts ils-inlineToMan opts (Emph lst) = do-  contents <- inlineListToMan opts lst-  return $ text "\\f[I]" <> contents <> text "\\f[]"-inlineToMan opts (Strong lst) = do-  contents <- inlineListToMan opts lst-  return $ text "\\f[B]" <> contents <> text "\\f[]"+inlineToMan opts (Emph lst) =+  withFontFeature 'I' (inlineListToMan opts lst)+inlineToMan opts (Strong lst) =+  withFontFeature 'B' (inlineListToMan opts lst) inlineToMan opts (Strikeout lst) = do   contents <- inlineListToMan opts lst   return $ text "[STRIKEOUT:" <> contents <> char ']'@@ -330,19 +355,21 @@ inlineToMan opts (Cite _ lst) =   inlineListToMan opts lst inlineToMan _ (Code _ str) =-  return $ text $ "\\f[C]" ++ escapeCode str ++ "\\f[]"+  withFontFeature 'C' (return (text $ escapeCode str)) inlineToMan _ (Str str@('.':_)) =   return $ afterBreak "\\&" <> text (escapeString str) inlineToMan _ (Str str) = return $ text $ escapeString str inlineToMan opts (Math InlineMath str) =-  inlineListToMan opts $ texMathToInlines InlineMath str+  lift (texMathToInlines InlineMath str) >>= inlineListToMan opts inlineToMan opts (Math DisplayMath str) = do-  contents <- inlineListToMan opts $ texMathToInlines DisplayMath str+  contents <- lift (texMathToInlines DisplayMath str) >>= inlineListToMan opts   return $ cr <> text ".RS" $$ contents $$ text ".RE"-inlineToMan _ (RawInline f str)+inlineToMan _ il@(RawInline f str)   | f == Format "man" = return $ text str-  | otherwise         = return empty-inlineToMan _ (LineBreak) = return $+  | otherwise         = do+      report $ InlineNotRendered il+      return empty+inlineToMan _ LineBreak = return $   cr <> text ".PD 0" $$ text ".P" $$ text ".PD" <> cr inlineToMan _ SoftBreak = return space inlineToMan _ Space = return space@@ -355,7 +382,7 @@                                  char '<' <> text srcSuffix <> char '>'            _                  -> linktext <> text " (" <> text src <> char ')' inlineToMan opts (Image attr alternate (source, tit)) = do-  let txt = if (null alternate) || (alternate == [Str ""]) ||+  let txt = if null alternate || (alternate == [Str ""]) ||                (alternate == [Str source]) -- to prevent autolinks                then [Str "image"]                else alternate@@ -364,6 +391,24 @@ inlineToMan _ (Note contents) = do   -- add to notes in state   modify $ \st -> st{ stNotes = contents : stNotes st }-  notes <- liftM stNotes get-  let ref = show $ (length notes)+  notes <- gets stNotes+  let ref = show (length notes)   return $ char '[' <> text ref <> char ']'++fontChange :: PandocMonad m => StateT WriterState m Doc+fontChange = do+  features <- gets stFontFeatures+  let filling = sort [c | (c,True) <- Map.toList features]+  return $ text $ "\\f[" ++ filling ++ "]"++withFontFeature :: PandocMonad m+                => Char+                -> StateT WriterState m Doc+                -> StateT WriterState m Doc+withFontFeature c action = do+  modify $ \st -> st{ stFontFeatures = Map.adjust not c $ stFontFeatures st }+  begin <- fontChange+  d <- action+  modify $ \st -> st{ stFontFeatures = Map.adjust not c $ stFontFeatures st }+  end <- fontChange+  return $ begin <> d <> end
src/Text/Pandoc/Writers/Markdown.hs view
@@ -1,6 +1,9 @@-{-# LANGUAGE OverloadedStrings, TupleSections, ScopedTypeVariables, MultiWayIf #-}+{-# LANGUAGE MultiWayIf          #-}+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TupleSections       #-} {--Copyright (C) 2006-2015 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2006-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -19,7 +22,7 @@  {- |    Module      : Text.Pandoc.Writers.Markdown-   Copyright   : Copyright (C) 2006-2015 John MacFarlane+   Copyright   : Copyright (C) 2006-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -31,47 +34,50 @@ Markdown:  <http://daringfireball.net/projects/markdown/> -} module Text.Pandoc.Writers.Markdown (writeMarkdown, writePlain) where-import Text.Pandoc.Definition-import Text.Pandoc.Walk-import Text.Pandoc.Templates (renderTemplate')-import Text.Pandoc.Shared-import Text.Pandoc.Writers.Shared-import Text.Pandoc.Options-import Text.Pandoc.Parsing hiding (blankline, blanklines, char, space)-import Data.Maybe (fromMaybe)-import Data.Monoid (Any(..))-import Data.List ( group, stripPrefix, find, intersperse, transpose, sortBy )-import Data.Char ( isSpace, isPunctuation, ord, chr )-import Data.Ord ( comparing )-import Text.Pandoc.Pretty import Control.Monad.Reader-import Control.Monad.State-import Text.Pandoc.Writers.HTML (writeHtmlString)-import Text.Pandoc.Readers.TeXMath (texMathToInlines)-import Text.HTML.TagSoup (parseTags, isTagText, Tag(..))-import Network.URI (isURI)+import Control.Monad.State.Strict+import Data.Char (chr, isPunctuation, isSpace, ord) import Data.Default-import Data.Yaml (Value(Object,String,Array,Bool,Number)) import qualified Data.HashMap.Strict as H-import qualified Data.Vector as V-import qualified Data.Text as T+import Data.List (find, group, intersperse, sortBy, stripPrefix, transpose)+import qualified Data.Map as M+import Data.Maybe (fromMaybe)+import Data.Monoid (Any (..))+import Data.Ord (comparing) import qualified Data.Set as Set-import Network.HTTP ( urlEncode )+import Data.Text (Text)+import qualified Data.Text as T+import qualified Data.Vector as V+import Data.Yaml (Value (Array, Bool, Number, Object, String))+import Network.HTTP (urlEncode)+import Text.HTML.TagSoup (Tag (..), isTagText, parseTags)+import Text.Pandoc.Class (PandocMonad, report)+import Text.Pandoc.Definition+import Text.Pandoc.Logging+import Text.Pandoc.Options+import Text.Pandoc.Parsing hiding (blankline, blanklines, char, space)+import Text.Pandoc.Pretty+import Text.Pandoc.Shared+import Text.Pandoc.Templates (renderTemplate')+import Text.Pandoc.Walk+import Text.Pandoc.Writers.HTML (writeHtml5String)+import Text.Pandoc.Writers.Math (texMathToInlines)+import Text.Pandoc.Writers.Shared  type Notes = [[Block]]-type Ref   = ([Inline], Target, Attr)+type Ref   = (Doc, Target, Attr) type Refs  = [Ref] -type MD = ReaderT WriterEnv (State WriterState)+type MD m = ReaderT WriterEnv (StateT WriterState m) -evalMD :: MD a -> WriterEnv -> WriterState -> a-evalMD md env st = evalState (runReaderT md env) st+evalMD :: PandocMonad m => MD m a -> WriterEnv -> WriterState -> m a+evalMD md env st = evalStateT (runReaderT md env) st -data WriterEnv = WriterEnv { envInList         :: Bool-                           , envPlain          :: Bool+data WriterEnv = WriterEnv { envInList          :: Bool+                           , envPlain           :: Bool                            , envRefShortcutable :: Bool                            , envBlockLevel      :: Int-                           , envEscapeSpaces   :: Bool+                           , envEscapeSpaces    :: Bool                            }  instance Default WriterEnv@@ -82,21 +88,26 @@                         , envEscapeSpaces    = False                         } -data WriterState = WriterState { stNotes :: Notes-                               , stRefs  :: Refs-                               , stIds   :: Set.Set String+data WriterState = WriterState { stNotes   :: Notes+                               , stRefs    :: Refs+                               , stKeys    :: M.Map Key+                                                (M.Map (Target, Attr) Int)+                               , stLastIdx  :: Int+                               , stIds     :: Set.Set String                                , stNoteNum :: Int                                }  instance Default WriterState   where def = WriterState{ stNotes = []                          , stRefs = []+                         , stKeys = M.empty+                         , stLastIdx = 0                          , stIds = Set.empty                          , stNoteNum = 1                          }  -- | Convert Pandoc to Markdown.-writeMarkdown :: WriterOptions -> Pandoc -> String+writeMarkdown :: PandocMonad m => WriterOptions -> Pandoc -> m Text writeMarkdown opts document =   evalMD (pandocToMarkdown opts{              writerWrapText = if isEnabled Ext_hard_line_breaks opts@@ -106,7 +117,7 @@  -- | Convert Pandoc to plain text (like markdown, but without links, -- pictures, or inline formatting).-writePlain :: WriterOptions -> Pandoc -> String+writePlain :: PandocMonad m => WriterOptions -> Pandoc -> m Text writePlain opts document =   evalMD (pandocToMarkdown opts document) def{ envPlain = True } def @@ -155,8 +166,7 @@                  | otherwise      -> (k' <> ":") $$ x                (k', Object _, x)  -> (k' <> ":") $$ nest 2 x                (_, String "", _)  -> empty-               (k', _, x)  | k == "meta-json"  -> empty-                           | otherwise -> k' <> ":" <> space <> hang 2 "" x)+               (k', _, x)         -> k' <> ":" <> space <> hang 2 "" x)        $ sortBy (comparing fst) $ H.toList hashmap jsonToYaml (Array vec) =   vcat $ map (\v -> hang 2 "- " (jsonToYaml v)) $ V.toList vec@@ -171,15 +181,17 @@ jsonToYaml _ = empty  -- | Return markdown representation of document.-pandocToMarkdown :: WriterOptions -> Pandoc -> MD String+pandocToMarkdown :: PandocMonad m => WriterOptions -> Pandoc -> MD m Text pandocToMarkdown opts (Pandoc meta blocks) = do   let colwidth = if writerWrapText opts == WrapAuto                     then Just $ writerColumns opts                     else Nothing   isPlain <- asks envPlain-  metadata <- metaToJSON opts-               (fmap (render colwidth) . blockListToMarkdown opts)-               (fmap (render colwidth) . inlineListToMarkdown opts)+  let render' :: Doc -> Text+      render' = render colwidth . chomp+  metadata <- metaToJSON'+               (fmap render' . blockListToMarkdown opts)+               (fmap render' . blockToMarkdown opts . Plain)                meta   let title' = maybe empty text $ getField "title" metadata   let authors' = maybe [] (map text) $ getField "author" metadata@@ -196,49 +208,51 @@                                | otherwise -> empty                         Nothing -> empty   let headerBlocks = filter isHeaderBlock blocks-  let toc = if writerTableOfContents opts-               then tableOfContents opts headerBlocks-               else empty+  toc <- if writerTableOfContents opts+         then render' <$> tableOfContents opts headerBlocks+         else return ""   -- Strip off final 'references' header if markdown citations enabled   let blocks' = if isEnabled Ext_citations opts                    then case reverse blocks of                              (Div (_,["references"],_) _):xs -> reverse xs-                             _ -> blocks+                             _                               -> blocks                    else blocks   body <- blockListToMarkdown opts blocks'   notesAndRefs' <- notesAndRefs opts-  let render' :: Doc -> String-      render' = render colwidth   let main = render' $ body <> notesAndRefs'-  let context  = defField "toc" (render' toc)+  let context  = -- for backwards compatibility we populate toc+                 -- with the contents of the toc, rather than a+                 -- boolean:+                 defField "toc" toc+               $ defField "table-of-contents" toc                $ defField "body" main                $ (if isNullMeta meta                      then id                      else defField "titleblock" (render' titleblock))-               $ metadata+               $ addVariablesToJSON opts metadata   case writerTemplate opts of        Nothing  -> return main-       Just tpl -> return $ renderTemplate' tpl context+       Just tpl -> renderTemplate' tpl context  -- | Return markdown representation of reference key table.-refsToMarkdown :: WriterOptions -> Refs -> MD Doc+refsToMarkdown :: PandocMonad m => WriterOptions -> Refs -> MD m Doc refsToMarkdown opts refs = mapM (keyToMarkdown opts) refs >>= return . vcat  -- | Return markdown representation of a reference key.-keyToMarkdown :: WriterOptions+keyToMarkdown :: PandocMonad m+              => WriterOptions               -> Ref-              -> MD Doc-keyToMarkdown opts (label, (src, tit), attr) = do-  label' <- inlineListToMarkdown opts label+              -> MD m Doc+keyToMarkdown opts (label', (src, tit), attr) = do   let tit' = if null tit                 then empty                 else space <> "\"" <> text tit <> "\""   return $ nest 2 $ hang 2             ("[" <> label' <> "]:" <> space) (text src <> tit')-            <> linkAttributes opts attr+            <+> linkAttributes opts attr  -- | Return markdown representation of notes.-notesToMarkdown :: WriterOptions -> [[Block]] -> MD Doc+notesToMarkdown :: PandocMonad m => WriterOptions -> [[Block]] -> MD m Doc notesToMarkdown opts notes = do   n <- gets stNoteNum   notes' <- mapM (\(num, note) -> noteToMarkdown opts num note) (zip [n..] notes)@@ -246,7 +260,7 @@   return $ vsep notes'  -- | Return markdown representation of a note.-noteToMarkdown :: WriterOptions -> Int -> [Block] -> MD Doc+noteToMarkdown :: PandocMonad m => WriterOptions -> Int -> [Block] -> MD m Doc noteToMarkdown opts num blocks = do   contents  <- blockListToMarkdown opts blocks   let num' = text $ writerIdentifierPrefix opts ++ show num@@ -256,34 +270,45 @@   let markerSize = 4 + offset num'   let spacer = case writerTabStop opts - markerSize of                      n | n > 0  -> text $ replicate n ' '-                     _          -> text " "+                     _ -> text " "   return $ if isEnabled Ext_footnotes opts               then hang (writerTabStop opts) (marker <> spacer) contents               else marker <> spacer <> contents  -- | Escape special characters for Markdown. escapeString :: WriterOptions -> String -> String-escapeString opts = escapeStringUsing markdownEscapes-  where markdownEscapes = ('<', "&lt;") : ('>', "&gt;") :-                          backslashEscapes specialChars-        specialChars =-                (if isEnabled Ext_superscript opts-                    then ('^':)-                    else id) .-                (if isEnabled Ext_subscript opts-                    then ('~':)-                    else id) .-                (if isEnabled Ext_tex_math_dollars opts-                    then ('$':)-                    else id) $-                "\\`*_[]#"+escapeString _  [] = []+escapeString opts (c:cs) =+  case c of+       '<' | isEnabled Ext_all_symbols_escapable opts ->+              '\\' : '<' : escapeString opts cs+           | otherwise -> "&lt;" ++ escapeString opts cs+       '>' | isEnabled Ext_all_symbols_escapable opts ->+              '\\' : '>' : escapeString opts cs+           | otherwise -> "&gt;" ++ escapeString opts cs+       _ | c `elem` ['\\','`','*','_','[',']','#'] ->+              '\\':c:escapeString opts cs+       '|' | isEnabled Ext_pipe_tables opts -> '\\':'|':escapeString opts cs+       '^' | isEnabled Ext_superscript opts -> '\\':'^':escapeString opts cs+       '~' | isEnabled Ext_subscript opts -> '\\':'~':escapeString opts cs+       '$' | isEnabled Ext_tex_math_dollars opts -> '\\':'$':escapeString opts cs+       '\'' | isEnabled Ext_smart opts -> '\\':'\'':escapeString opts cs+       '"' | isEnabled Ext_smart opts -> '\\':'"':escapeString opts cs+       '-' | isEnabled Ext_smart opts ->+              case cs of+                   '-':_ -> '\\':'-':escapeString opts cs+                   _     -> '-':escapeString opts cs+       '.' | isEnabled Ext_smart opts ->+              case cs of+                   '.':'.':rest -> '\\':'.':'.':'.':escapeString opts rest+                   _            -> '.':escapeString opts cs+       _ -> c : escapeString opts cs  -- | Construct table of contents from list of header blocks.-tableOfContents :: WriterOptions -> [Block] -> Doc+tableOfContents :: PandocMonad m => WriterOptions -> [Block] -> m Doc tableOfContents opts headers =-  let opts' = opts { writerIgnoreNotes = True }-      contents = BulletList $ map (elementToListItem opts) $ hierarchicalize headers-  in  evalMD (blockToMarkdown opts' contents) def def+  let contents = BulletList $ map (elementToListItem opts) $ hierarchicalize headers+  in  evalMD (blockToMarkdown opts contents) def def  -- | Converts an Element to a list item for a table of contents, elementToListItem :: WriterOptions -> Element -> [Block]@@ -292,8 +317,9 @@     [ BulletList (map (elementToListItem opts) subsecs) |       not (null subsecs) && lev < writerTOCDepth opts ]    where headerLink = if null ident-                         then headerText-                         else [Link nullAttr headerText ('#':ident, "")]+                         then walk deNote headerText+                         else [Link nullAttr (walk deNote headerText)+                                 ('#':ident, "")] elementToListItem _ (Blk _) = []  attrsToMarkdown :: Attr -> Doc@@ -331,10 +357,10 @@ beginsWithOrderedListMarker :: String -> Bool beginsWithOrderedListMarker str =   case runParser olMarker defaultParserState "para start" (take 10 str) of-         Left  _  -> False-         Right _  -> True+         Left  _ -> False+         Right _ -> True -notesAndRefs :: WriterOptions -> MD Doc+notesAndRefs :: PandocMonad m => WriterOptions -> MD m Doc notesAndRefs opts = do   notes' <- reverse <$> gets stNotes >>= notesToMarkdown opts   modify $ \s -> s { stNotes = [] }@@ -345,16 +371,17 @@         if | writerReferenceLocation opts == EndOfDocument -> empty            | isEmpty notes' && isEmpty refs' -> empty            | otherwise -> blankline-  +   return $     (if isEmpty notes' then empty else blankline <> notes') <>     (if isEmpty refs' then empty else blankline <> refs') <>     endSpacing  -- | Convert Pandoc block element to markdown.-blockToMarkdown :: WriterOptions -- ^ Options+blockToMarkdown :: PandocMonad m+                => WriterOptions -- ^ Options                 -> Block         -- ^ Block element-                -> MD Doc+                -> MD m Doc blockToMarkdown opts blk =   local (\env -> env {envBlockLevel = envBlockLevel env + 1}) $   do doc <- blockToMarkdown' opts blk@@ -363,9 +390,10 @@        then notesAndRefs opts >>= (\d -> return $ doc <> d)        else return doc -blockToMarkdown' :: WriterOptions -- ^ Options-                -> Block         -- ^ Block element-                -> MD Doc+blockToMarkdown' :: PandocMonad m+                 => WriterOptions -- ^ Options+                 -> Block         -- ^ Block element+                 -> MD m Doc blockToMarkdown' _ Null = return empty blockToMarkdown' opts (Div attrs ils) = do   contents <- blockListToMarkdown opts ils@@ -382,13 +410,28 @@                     then Just $ writerColumns opts                     else Nothing   let rendered = render colwidth contents-  let escapeDelimiter (x:xs) | x `elem` (".()" :: String) = '\\':x:xs-                             | otherwise                  = x : escapeDelimiter xs-      escapeDelimiter []                                  = []-  let contents' = if isEnabled Ext_all_symbols_escapable opts &&-                     not isPlain && beginsWithOrderedListMarker rendered-                     then text $ escapeDelimiter rendered-                     else contents+  let escapeMarker (x:xs) | x `elem` (".()" :: String) = '\\':x:xs+                          | otherwise                  = x : escapeMarker xs+      escapeMarker []                                  = []+  let contents' =+       case rendered of+            '%':_ | isEnabled Ext_pandoc_title_block opts &&+                    isEnabled Ext_all_symbols_escapable opts ->+                    "\\" <> contents+            '+':s:_ | not isPlain && isSpace s -> "\\" <> contents+            '*':s:_ | not isPlain && isSpace s -> "\\" <> contents+            '-':s:_ | not isPlain && isSpace s -> "\\" <> contents+            '+':[]  | not isPlain -> "\\" <> contents+            '*':[]  | not isPlain -> "\\" <> contents+            '-':[]  | not isPlain -> "\\" <> contents+            '|':_ | (isEnabled Ext_line_blocks opts ||+                     isEnabled Ext_pipe_tables opts)+                    && isEnabled Ext_all_symbols_escapable opts+                  -> "\\" <> contents+            _ | not isPlain && beginsWithOrderedListMarker rendered+                  && isEnabled Ext_all_symbols_escapable opts+                  -> text $ escapeMarker rendered+              | otherwise -> contents   return $ contents' <> cr -- title beginning with fig: indicates figure blockToMarkdown' opts (Para [Image attr alt (src,'f':'i':'g':':':tit)]) =@@ -401,9 +444,11 @@     mdLines <- mapM (inlineListToMarkdown opts) lns     return $ (vcat $ map (hang 2 (text "| ")) mdLines) <> blankline   else blockToMarkdown opts $ linesToPara lns-blockToMarkdown' opts (RawBlock f str)-  | f == "markdown" = return $ text str <> text "\n"-  | f == "html" && isEnabled Ext_raw_html opts = do+blockToMarkdown' opts b@(RawBlock f str)+  | f `elem` ["markdown", "markdown_github", "markdown_phpextra",+              "markdown_mmd", "markdown_strict"]+              = return $ text str <> text "\n"+  | f `elem` ["html", "html5", "html4"] && isEnabled Ext_raw_html opts = do     plain <- asks envPlain     return $ if plain                 then empty@@ -415,7 +460,9 @@     return $ if plain                 then empty                 else text str <> text "\n"-  | otherwise = return empty+  | otherwise = do+      report $ BlockNotRendered b+      return empty blockToMarkdown' opts HorizontalRule = do   return $ blankline <> text (replicate (writerColumns opts) '-') <> blankline blockToMarkdown' opts (Header level attr inlines) = do@@ -442,6 +489,8 @@                                     space <> attrsToMarkdown attr                      | otherwise -> empty   contents <- inlineListToMarkdown opts $+                 -- ensure no newlines; see #3736+                 walk lineBreakToSpace $                  if level == 1 && plain                     then capitalize inlines                     else inlines@@ -497,39 +546,60 @@   contents <- blockListToMarkdown opts blocks   return $ (prefixed leader contents) <> blankline blockToMarkdown' opts t@(Table caption aligns widths headers rows) =  do+  let numcols = maximum (length aligns : length widths :+                           map length (headers:rows))   caption' <- inlineListToMarkdown opts caption   let caption'' = if null caption || not (isEnabled Ext_table_captions opts)-                     then empty-                     else blankline <> ": " <> caption' <> blankline-  rawHeaders <- mapM (blockListToMarkdown opts) headers-  rawRows <- mapM (mapM (blockListToMarkdown opts)) rows+                     then blankline+                     else blankline $$ (": " <> caption') $$ blankline   let isLineBreak LineBreak = Any True       isLineBreak _         = Any False-  let isSimple = all (==0) widths &&-                 not ( getAny (query isLineBreak (headers:rows)) )+  let hasLineBreak = getAny . query isLineBreak+  let isSimpleCell [Plain ils] = not (hasLineBreak ils)+      isSimpleCell [Para ils ] = not (hasLineBreak ils)+      isSimpleCell []          = True+      isSimpleCell _           = False+  let hasSimpleCells = all isSimpleCell (concat (headers:rows))+  let isSimple = hasSimpleCells && all (==0) widths   let isPlainBlock (Plain _) = True       isPlainBlock _         = False   let hasBlocks = not (all isPlainBlock $ concat . concat $ headers:rows)-  (nst,tbl) <- case True of-                _ | isSimple &&-                    isEnabled Ext_simple_tables opts -> fmap (nest 2,) $-                         pandocTable opts (all null headers) aligns widths-                             rawHeaders rawRows-                  | isSimple &&-                    isEnabled Ext_pipe_tables opts -> fmap (id,) $-                         pipeTable (all null headers) aligns rawHeaders rawRows-                  | not hasBlocks &&-                    isEnabled Ext_multiline_tables opts -> fmap (nest 2,) $-                         pandocTable opts (all null headers) aligns widths-                             rawHeaders rawRows-                  | isEnabled Ext_grid_tables opts -> fmap (id,) $-                         gridTable opts (all null headers) aligns widths-                             rawHeaders rawRows-                  | isEnabled Ext_raw_html opts -> fmap (id,) $-                         return $ text $ writeHtmlString def-                                $ Pandoc nullMeta [t]-                  | otherwise -> return $ (id, text "[TABLE]")-  return $ nst $ tbl $$ blankline $$ caption'' $$ blankline+  let padRow r = case numcols - length r of+                       x | x > 0 -> r ++ replicate x empty+                         | otherwise -> r+  rawHeaders <- padRow <$> mapM (blockListToMarkdown opts) headers+  rawRows <- mapM (fmap padRow . mapM (blockListToMarkdown opts)) rows+  let aligns' = case numcols - length aligns of+                     x | x > 0 -> aligns ++ replicate x AlignDefault+                       | otherwise -> aligns+  let widths' = case numcols - length widths of+                     x | x > 0 -> widths ++ replicate x 0.0+                       | otherwise -> widths+  (nst,tbl) <-+     case True of+          _ | isSimple &&+              isEnabled Ext_simple_tables opts -> fmap (nest 2,) $+                   pandocTable opts False (all null headers) aligns' widths'+                       rawHeaders rawRows+            | isSimple &&+              isEnabled Ext_pipe_tables opts -> fmap (id,) $+                   pipeTable (all null headers) aligns' rawHeaders rawRows+            | not hasBlocks &&+              isEnabled Ext_multiline_tables opts -> fmap (nest 2,) $+                   pandocTable opts True (all null headers) aligns' widths'+                       rawHeaders rawRows+            | isEnabled Ext_grid_tables opts &&+               writerColumns opts >= 8 * numcols -> (id,) <$>+                gridTable opts blockListToMarkdown+                  (all null headers) aligns' widths' headers rows+            | isEnabled Ext_raw_html opts -> fmap (id,) $+                   (text . T.unpack) <$>+                   (writeHtml5String def $ Pandoc nullMeta [t])+            | hasSimpleCells &&+              isEnabled Ext_pipe_tables opts -> fmap (id,) $+                   pipeTable (all null headers) aligns' rawHeaders rawRows+            | otherwise -> return $ (id, text "[TABLE]")+  return $ nst $ tbl $$ caption'' $$ blankline blockToMarkdown' opts (BulletList items) = do   contents <- inList $ mapM (bulletListItemToMarkdown opts) items   return $ cat contents <> blankline@@ -550,7 +620,7 @@   contents <- inList $ mapM (definitionListItemToMarkdown opts) items   return $ cat contents <> blankline -inList :: MD a -> MD a+inList :: Monad m => MD m a -> MD m a inList p = local (\env -> env {envInList = True}) p  addMarkdownAttribute :: String -> String@@ -562,7 +632,7 @@                                  x /= "markdown"]        _ -> s -pipeTable :: Bool -> [Alignment] -> [Doc] -> [[Doc]] -> MD Doc+pipeTable :: PandocMonad m => Bool -> [Alignment] -> [Doc] -> [[Doc]] -> MD m Doc pipeTable headless aligns rawHeaders rawRows = do   let sp = text " "   let blockFor AlignLeft   x y = lblock (x + 2) (sp <> y) <> lblock 0 empty@@ -590,9 +660,10 @@   let body   = vcat $ map torow rawRows   return $ header $$ border $$ body -pandocTable :: WriterOptions -> Bool -> [Alignment] -> [Double]-            -> [Doc] -> [[Doc]] -> MD Doc-pandocTable opts headless aligns widths rawHeaders rawRows = do+pandocTable :: PandocMonad m+            => WriterOptions -> Bool -> Bool -> [Alignment] -> [Double]+            -> [Doc] -> [[Doc]] -> MD m Doc+pandocTable opts multiline headless aligns widths rawHeaders rawRows = do   let isSimple = all (==0) widths   let alignHeader alignment = case alignment of                                 AlignLeft    -> lblock@@ -609,23 +680,21 @@   let minNumChars = (+ 2) . maximum . map minOffset   let columns = transpose (rawHeaders : rawRows)   -- minimal column width without wrapping a single word-  let noWordWrapWidth-        | writerWrapText opts == WrapAuto-                              = fromIntegral $ maximum (map minNumChars columns)-        | otherwise           = fromIntegral $ maximum (map    numChars columns)-  let relWidth w = floor $ max (fromIntegral (writerColumns opts) * w)-                               (noWordWrapWidth * w / minimum widths)+  let relWidth w col =+         max (floor $ fromIntegral (writerColumns opts) * w)+             (if writerWrapText opts == WrapAuto+                 then minNumChars col+                 else numChars col)   let widthsInChars         | isSimple  = map numChars columns-        | otherwise = map relWidth widths+        | otherwise = zipWith relWidth widths columns   let makeRow = hcat . intersperse (lblock 1 (text " ")) .                    (zipWith3 alignHeader aligns widthsInChars)   let rows' = map makeRow rawRows   let head' = makeRow rawHeaders-  let maxRowHeight = maximum $ map height (head':rows')   let underline = cat $ intersperse (text " ") $                   map (\width -> text (replicate width '-')) widthsInChars-  let border = if maxRowHeight > 1+  let border = if multiline                   then text (replicate (sum widthsInChars +                           length widthsInChars - 1) '-')                   else if headless@@ -634,7 +703,7 @@   let head'' = if headless                   then empty                   else border <> cr <> head'-  let body = if maxRowHeight > 1+  let body = if multiline                 then vsep rows'                 else vcat rows'   let bottom = if headless@@ -642,62 +711,15 @@                   else border   return $ head'' $$ underline $$ body $$ bottom -gridTable :: WriterOptions -> Bool -> [Alignment] -> [Double]-          -> [Doc] -> [[Doc]] -> MD Doc-gridTable opts headless aligns widths headers' rawRows =  do-  let numcols = length headers'-  let widths' = if all (==0) widths-                   then replicate numcols (1.0 / fromIntegral numcols)-                   else widths-  let widthsInChars = map-         ((\x -> x - 3) . floor . (fromIntegral (writerColumns opts) *)) widths'-  let hpipeBlocks blocks = hcat [beg, middle, end]-        where h       = maximum (1 : map height blocks)-              sep'    = lblock 3 $ vcat (map text $ replicate h " | ")-              beg     = lblock 2 $ vcat (map text $ replicate h "| ")-              end     = lblock 2 $ vcat (map text $ replicate h " |")-              middle  = chomp $ hcat $ intersperse sep' blocks-  let makeRow = hpipeBlocks . zipWith lblock widthsInChars-  let head' = makeRow headers'-  let rows' = map (makeRow . map chomp) rawRows-  let borderpart ch align widthInChars =-        let widthInChars' = if widthInChars < 1 then 1 else widthInChars-        in (if (align == AlignLeft || align == AlignCenter)-               then char ':'-               else char ch) <>-           text (replicate widthInChars' ch) <>-           (if (align == AlignRight || align == AlignCenter)-               then char ':'-               else char ch)-  let border ch aligns' widthsInChars' =-        char '+' <>-        hcat (intersperse (char '+') (zipWith (borderpart ch)-                aligns' widthsInChars')) <> char '+'-  let body = vcat $ intersperse (border '-' (repeat AlignDefault) widthsInChars)-                    rows'-  let head'' = if headless-                  then empty-                  else head' $$ border '=' aligns widthsInChars-  if headless-     then return $-           border '-' aligns widthsInChars $$-           body $$-           border '-' (repeat AlignDefault) widthsInChars-     else return $-           border '-' (repeat AlignDefault) widthsInChars $$-           head'' $$-           body $$-           border '-' (repeat AlignDefault) widthsInChars- itemEndsWithTightList :: [Block] -> Bool itemEndsWithTightList bs =   case bs of         [Plain _, BulletList xs]    -> isTightList xs         [Plain _, OrderedList _ xs] -> isTightList xs-        _ -> False+        _                           -> False  -- | Convert bullet list item (list of blocks) to markdown.-bulletListItemToMarkdown :: WriterOptions -> [Block] -> MD Doc+bulletListItemToMarkdown :: PandocMonad m => WriterOptions -> [Block] -> MD m Doc bulletListItemToMarkdown opts bs = do   contents <- blockListToMarkdown opts bs   let sps = replicate (writerTabStop opts - 2) ' '@@ -709,15 +731,16 @@   return $ hang (writerTabStop opts) start $ contents' <> cr  -- | Convert ordered list item (a list of blocks) to markdown.-orderedListItemToMarkdown :: WriterOptions -- ^ options+orderedListItemToMarkdown :: PandocMonad m+                          => WriterOptions -- ^ options                           -> String        -- ^ list item marker                           -> [Block]       -- ^ list item (list of blocks)-                          -> MD Doc+                          -> MD m Doc orderedListItemToMarkdown opts marker bs = do   contents <- blockListToMarkdown opts bs   let sps = case length marker - writerTabStop opts of                    n | n > 0 -> text $ replicate n ' '-                   _         -> text " "+                   _ -> text " "   let start = text marker <> sps   -- remove trailing blank line if item ends with a tight list   let contents' = if itemEndsWithTightList bs@@ -726,9 +749,10 @@   return $ hang (writerTabStop opts) start $ contents' <> cr  -- | Convert definition list item (label, list of blocks) to markdown.-definitionListItemToMarkdown :: WriterOptions+definitionListItemToMarkdown :: PandocMonad m+                             => WriterOptions                              -> ([Inline],[[Block]])-                             -> MD Doc+                             -> MD m Doc definitionListItemToMarkdown opts (label, defs) = do   labelText <- inlineListToMarkdown opts label   defs' <- mapM (mapM (blockToMarkdown opts)) defs@@ -739,7 +763,7 @@        let leader  = if isPlain then "   " else ":  "        let sps = case writerTabStop opts - 3 of                       n | n > 0   -> text $ replicate n ' '-                      _           -> text " "+                      _ -> text " "        if isEnabled Ext_compact_definition_lists opts           then do             let contents = vcat $ map (\d -> hang tabStop (leader <> sps)@@ -750,7 +774,7 @@                                 $ vcat d <> cr) defs'             let isTight = case defs of                                ((Plain _ : _): _) -> True-                               _ -> False+                               _                  -> False             return $ blankline <> nowrap labelText <>                      (if isTight then cr else blankline) <> contents <> blankline      else do@@ -758,75 +782,129 @@                 vsep (map vsep defs') <> blankline  -- | Convert list of Pandoc block elements to markdown.-blockListToMarkdown :: WriterOptions -- ^ Options+blockListToMarkdown :: PandocMonad m+                    => WriterOptions -- ^ Options                     -> [Block]       -- ^ List of block elements-                    -> MD Doc-blockListToMarkdown opts blocks =+                    -> MD m Doc+blockListToMarkdown opts blocks = do+  inlist <- asks envInList+  isPlain <- asks envPlain+  -- a) insert comment between list and indented code block, or the+  -- code block will be treated as a list continuation paragraph+  -- b) change Plain to Para unless it's followed by a RawBlock+  -- or has a list as its parent (#3487)+  let fixBlocks (b : CodeBlock attr x : rest)+         | (not (isEnabled Ext_fenced_code_blocks opts) || attr == nullAttr)+             && isListBlock b = b : commentSep : CodeBlock attr x :+                                fixBlocks rest+      fixBlocks (b1@(BulletList _) : b2@(BulletList _) : bs) =+           b1 : commentSep : fixBlocks (b2:bs)+      fixBlocks (b1@(OrderedList _ _) : b2@(OrderedList _ _) : bs) =+           b1 : commentSep : fixBlocks (b2:bs)+      fixBlocks (b1@(DefinitionList _) : b2@(DefinitionList _) : bs) =+           b1 : commentSep : fixBlocks (b2:bs)+      fixBlocks (Plain ils : bs@(RawBlock{}:_)) =+           Plain ils : fixBlocks bs+      fixBlocks (Plain ils : bs) | inlist =+           Plain ils : fixBlocks bs+      fixBlocks (Plain ils : bs) =+           Para ils : fixBlocks bs+      fixBlocks (x : xs)             = x : fixBlocks xs+      fixBlocks []                   = []+      isListBlock (BulletList _)     = True+      isListBlock (OrderedList _ _)  = True+      isListBlock (DefinitionList _) = True+      isListBlock _                  = False+      commentSep  = if isPlain+                       then Null+                       else if isEnabled Ext_raw_html opts+                            then RawBlock "html" "<!-- -->\n"+                            else RawBlock "markdown" "&nbsp;\n"   mapM (blockToMarkdown opts) (fixBlocks blocks) >>= return . cat-    -- insert comment between list and indented code block, or the-    -- code block will be treated as a list continuation paragraph-    where fixBlocks (b : CodeBlock attr x : rest)-            | (not (isEnabled Ext_fenced_code_blocks opts) || attr == nullAttr)-                && isListBlock b = b : commentSep : CodeBlock attr x :-                                   fixBlocks rest-          fixBlocks (b1@(BulletList _) : b2@(BulletList _) : bs) =-               b1 : commentSep : fixBlocks (b2:bs)-          fixBlocks (b1@(OrderedList _ _) : b2@(OrderedList _ _) : bs) =-               b1 : commentSep : fixBlocks (b2:bs)-          fixBlocks (b1@(DefinitionList _) : b2@(DefinitionList _) : bs) =-               b1 : commentSep : fixBlocks (b2:bs)-          fixBlocks (x : xs)             = x : fixBlocks xs-          fixBlocks []                   = []-          isListBlock (BulletList _)     = True-          isListBlock (OrderedList _ _)  = True-          isListBlock (DefinitionList _) = True-          isListBlock _                  = False-          commentSep                     = if isEnabled Ext_raw_html opts-                                              then RawBlock "html" "<!-- -->\n"-                                              else RawBlock "markdown" "&nbsp;" +getKey :: Doc -> Key+getKey = toKey . render Nothing+ -- | Get reference for target; if none exists, create unique one and return. --   Prefer label if possible; otherwise, generate a unique key.-getReference :: Attr -> [Inline] -> Target -> MD [Inline]+getReference :: PandocMonad m => Attr -> Doc -> Target -> MD m Doc getReference attr label target = do-  st <- get-  case find (\(_,t,a) -> t == target && a == attr) (stRefs st) of+  refs <- gets stRefs+  case find (\(_,t,a) -> t == target && a == attr) refs of     Just (ref, _, _) -> return ref     Nothing       -> do-      let label' = case find (\(l,_,_) -> l == label) (stRefs st) of-                      Just _ -> -- label is used; generate numerical label-                             case find (\n -> notElem [Str (show n)]-                                                      (map (\(l,_,_) -> l) (stRefs st)))-                                       [1..(10000 :: Integer)] of-                                  Just x  -> [Str (show x)]-                                  Nothing -> error "no unique label"-                      Nothing -> label-      modify (\s -> s{ stRefs = (label', target, attr) : stRefs st })-      return label'+      keys <- gets stKeys+      case M.lookup (getKey label) keys of+           Nothing -> do -- no other refs with this label+             (lab', idx) <- if isEmpty label+                               then do+                                 i <- (+ 1) <$> gets stLastIdx+                                 modify $ \s -> s{ stLastIdx = i }+                                 return (text (show i), i)+                               else return (label, 0)+             modify (\s -> s{+               stRefs = (lab', target, attr) : refs,+               stKeys = M.insert (getKey label)+                           (M.insert (target, attr) idx mempty)+                                 (stKeys s) })+             return lab' +           Just km -> do -- we have refs with this label+             case M.lookup (target, attr) km of+                  Just i -> do+                    let lab' = label <> if i == 0+                                           then mempty+                                           else text (show i)+                    -- make sure it's in stRefs; it may be+                    -- a duplicate that was printed in a previous+                    -- block:+                    when ((lab', target, attr) `notElem` refs) $+                       modify (\s -> s{+                         stRefs = (lab', target, attr) : refs })+                    return lab'+                  Nothing -> do -- but this one is to a new target+                    i <- (+ 1) <$> gets stLastIdx+                    modify $ \s -> s{ stLastIdx = i }+                    let lab' = text (show i)+                    modify (\s -> s{+                       stRefs = (lab', target, attr) : refs,+                       stKeys = M.insert (getKey label)+                                   (M.insert (target, attr) i km)+                                         (stKeys s) })+                    return lab'+ -- | Convert list of Pandoc inline elements to markdown.-inlineListToMarkdown :: WriterOptions -> [Inline] -> MD Doc+inlineListToMarkdown :: PandocMonad m => WriterOptions -> [Inline] -> MD m Doc inlineListToMarkdown opts lst = do   inlist <- asks envInList   go (if inlist then avoidBadWrapsInList lst else lst)   where go [] = return empty         go (i:is) = case i of             (Link _ _ _) -> case is of-                -- If a link is followed by another link or '[' we don't shortcut-                (Link _ _ _):_                -> unshortcutable-                Space:(Link _ _ _):_          -> unshortcutable-                Space:(Str('[':_)):_          -> unshortcutable-                Space:(RawInline _ ('[':_)):_ -> unshortcutable-                Space:(Cite _ _):_            -> unshortcutable-                SoftBreak:(Link _ _ _):_      -> unshortcutable-                SoftBreak:(Str('[':_)):_      -> unshortcutable+                -- If a link is followed by another link, or '[', '(' or ':'+                -- then we don't shortcut+                (Link _ _ _):_                    -> unshortcutable+                Space:(Link _ _ _):_              -> unshortcutable+                Space:(Str('[':_)):_              -> unshortcutable+                Space:(RawInline _ ('[':_)):_     -> unshortcutable+                Space:(Cite _ _):_                -> unshortcutable+                SoftBreak:(Link _ _ _):_          -> unshortcutable+                SoftBreak:(Str('[':_)):_          -> unshortcutable                 SoftBreak:(RawInline _ ('[':_)):_ -> unshortcutable-                SoftBreak:(Cite _ _):_        -> unshortcutable-                (Cite _ _):_                  -> unshortcutable-                Str ('[':_):_                 -> unshortcutable-                (RawInline _ ('[':_)):_       -> unshortcutable-                (RawInline _ (' ':'[':_)):_   -> unshortcutable-                _                             -> shortcutable+                SoftBreak:(Cite _ _):_            -> unshortcutable+                LineBreak:(Link _ _ _):_          -> unshortcutable+                LineBreak:(Str('[':_)):_          -> unshortcutable+                LineBreak:(RawInline _ ('[':_)):_ -> unshortcutable+                LineBreak:(Cite _ _):_            -> unshortcutable+                (Cite _ _):_                      -> unshortcutable+                Str ('[':_):_                     -> unshortcutable+                Str ('(':_):_                     -> unshortcutable+                Str (':':_):_                     -> unshortcutable+                (RawInline _ ('[':_)):_           -> unshortcutable+                (RawInline _ ('(':_)):_           -> unshortcutable+                (RawInline _ (':':_)):_           -> unshortcutable+                (RawInline _ (' ':'[':_)):_       -> unshortcutable+                _                                 -> shortcutable             _ -> shortcutable           where shortcutable = liftM2 (<>) (inlineToMarkdown opts i) (go is)                 unshortcutable = do@@ -836,9 +914,9 @@                     fmap (iMark <>) (go is)  isSp :: Inline -> Bool-isSp Space = True+isSp Space     = True isSp SoftBreak = True-isSp _ = False+isSp _         = False  avoidBadWrapsInList :: [Inline] -> [Inline] avoidBadWrapsInList [] = []@@ -857,7 +935,7 @@ avoidBadWrapsInList (x:xs) = x : avoidBadWrapsInList xs  isOrderedListMarker :: String -> Bool-isOrderedListMarker xs = (last xs `elem` ['.',')']) &&+isOrderedListMarker xs = not (null xs) && (last xs `elem` ['.',')']) &&               isRight (runParser (anyOrderedListMarker >> eof)                        defaultParserState "" xs) @@ -866,27 +944,30 @@ isRight (Left  _) = False  -- | Convert Pandoc inline element to markdown.-inlineToMarkdown :: WriterOptions -> Inline -> MD Doc+inlineToMarkdown :: PandocMonad m => WriterOptions -> Inline -> MD m Doc inlineToMarkdown opts (Span attrs ils) = do   plain <- asks envPlain   contents <- inlineListToMarkdown opts ils   return $ case plain of                 True -> contents-                False | isEnabled Ext_bracketed_spans opts ->-                        "[" <> contents <> "]" <>-                          if attrs == nullAttr-                             then "{}"-                             else linkAttributes opts attrs+                False | attrs == nullAttr -> contents+                      | isEnabled Ext_bracketed_spans opts ->+                        let attrs' = if attrs /= nullAttr+                                        then attrsToMarkdown attrs+                                        else empty+                        in "[" <> contents <> "]" <> attrs'                       | isEnabled Ext_raw_html opts ||                         isEnabled Ext_native_spans opts ->                         tagWithAttrs "span" attrs <> contents <> text "</span>"                       | otherwise -> contents+inlineToMarkdown _ (Emph []) = return empty inlineToMarkdown opts (Emph lst) = do   plain <- asks envPlain   contents <- inlineListToMarkdown opts lst   return $ if plain               then "_" <> contents <> "_"               else "*" <> contents <> "*"+inlineToMarkdown _ (Strong []) = return empty inlineToMarkdown opts (Strong lst) = do   plain <- asks envPlain   if plain@@ -894,6 +975,7 @@      else do        contents <- inlineListToMarkdown opts lst        return $ "**" <> contents <> "**"+inlineToMarkdown _ (Strikeout []) = return empty inlineToMarkdown opts (Strikeout lst) = do   contents <- inlineListToMarkdown opts lst   return $ if isEnabled Ext_strikeout opts@@ -901,6 +983,7 @@               else if isEnabled Ext_raw_html opts                        then "<s>" <> contents <> "</s>"                        else contents+inlineToMarkdown _ (Superscript []) = return empty inlineToMarkdown opts (Superscript lst) =   local (\env -> env {envEscapeSpaces = True}) $ do     contents <- inlineListToMarkdown opts lst@@ -908,14 +991,12 @@                 then "^" <> contents <> "^"                 else if isEnabled Ext_raw_html opts                          then "<sup>" <> contents <> "</sup>"-                         else case (render Nothing contents) of-                                   ds | all (\d -> d >= '0' && d <= '9') ds-                                     -> text (map toSuperscript ds)-                                   _ -> contents-                          where toSuperscript '1' = '\x00B9'-                                toSuperscript '2' = '\x00B2'-                                toSuperscript '3' = '\x00B3'-                                toSuperscript c = chr (0x2070 + (ord c - 48))+                         else+                           let rendered = render Nothing contents+                           in  case mapM toSuperscript rendered of+                                    Just r  -> text r+                                    Nothing -> text $ "^(" ++ rendered ++ ")"+inlineToMarkdown _ (Subscript []) = return empty inlineToMarkdown opts (Subscript lst) =   local (\env -> env {envEscapeSpaces = True}) $ do     contents <- inlineListToMarkdown opts lst@@ -923,27 +1004,27 @@                 then "~" <> contents <> "~"                 else if isEnabled Ext_raw_html opts                          then "<sub>" <> contents <> "</sub>"-                         else case (render Nothing contents) of-                                   ds | all (\d -> d >= '0' && d <= '9') ds-                                     -> text (map toSubscript ds)-                                   _ -> contents-                          where toSubscript c = chr (0x2080 + (ord c - 48))+                         else+                           let rendered = render Nothing contents+                           in  case mapM toSubscript rendered of+                                    Just r  -> text r+                                    Nothing -> text $ "_(" ++ rendered ++ ")" inlineToMarkdown opts (SmallCaps lst) = do   plain <- asks envPlain   if not plain &&      (isEnabled Ext_raw_html opts || isEnabled Ext_native_spans opts)-     then do-       contents <- inlineListToMarkdown opts lst-       return $ tagWithAttrs "span"-                 ("",[],[("style","font-variant:small-caps;")])-             <> contents <> text "</span>"+     then inlineToMarkdown opts (Span ("",["smallcaps"],[]) lst)      else inlineListToMarkdown opts $ capitalize lst inlineToMarkdown opts (Quoted SingleQuote lst) = do   contents <- inlineListToMarkdown opts lst-  return $ "‘" <> contents <> "’"+  return $ if isEnabled Ext_smart opts+              then "'" <> contents <> "'"+              else "‘" <> contents <> "’" inlineToMarkdown opts (Quoted DoubleQuote lst) = do   contents <- inlineListToMarkdown opts lst-  return $ "“" <> contents <> "”"+  return $ if isEnabled Ext_smart opts+              then "\"" <> contents <> "\""+              else "“" <> contents <> "”" inlineToMarkdown opts (Code attr str) = do   let tickGroups = filter (\s -> '`' `elem` s) $ group str   let longest    = if null tickGroups@@ -960,9 +1041,13 @@      else return $ text (marker ++ spacer ++ str ++ spacer ++ marker) <> attrs inlineToMarkdown opts (Str str) = do   isPlain <- asks envPlain-  if isPlain-     then return $ text str-     else return $ text $ escapeString opts str+  let str' = (if isEnabled Ext_smart opts+                 then unsmartify opts+                 else id) $+              if isPlain+                 then str+                 else escapeString opts str+  return $ text str' inlineToMarkdown opts (Math InlineMath str) =   case writerHTMLMathMethod opts of        WebTeX url ->@@ -976,9 +1061,9 @@              return $ "\\\\(" <> text str <> "\\\\)"          | otherwise -> do              plain <- asks envPlain-             inlineListToMarkdown opts $-               (if plain then makeMathPlainer else id) $-               texMathToInlines InlineMath str+             texMathToInlines InlineMath str >>=+               inlineListToMarkdown opts .+                 (if plain then makeMathPlainer else id) inlineToMarkdown opts (Math DisplayMath str) =   case writerHTMLMathMethod opts of       WebTeX url -> (\x -> blankline <> x <> blankline) `fmap`@@ -991,15 +1076,19 @@         | isEnabled Ext_tex_math_double_backslash opts ->             return $ "\\\\[" <> text str <> "\\\\]"         | otherwise -> (\x -> cr <> x <> cr) `fmap`-              inlineListToMarkdown opts (texMathToInlines DisplayMath str)-inlineToMarkdown opts (RawInline f str) = do+            (texMathToInlines DisplayMath str >>= inlineListToMarkdown opts)+inlineToMarkdown opts il@(RawInline f str) = do   plain <- asks envPlain-  if not plain &&-     ( f == "markdown" ||+  if (plain && f == "plain") || (not plain &&+     ( f `elem` ["markdown", "markdown_github", "markdown_phpextra",+                 "markdown_mmd", "markdown_strict"] ||        (isEnabled Ext_raw_tex opts && (f == "latex" || f == "tex")) ||-       (isEnabled Ext_raw_html opts && f == "html") )+       (isEnabled Ext_raw_html opts && f `elem` ["html", "html4", "html5"])+     ))     then return $ text str-    else return empty+    else do+      report $ InlineNotRendered il+      return empty inlineToMarkdown opts (LineBreak) = do   plain <- asks envPlain   if plain || isEnabled Ext_hard_line_breaks opts@@ -1052,7 +1141,8 @@   | isEnabled Ext_raw_html opts &&     not (isEnabled Ext_link_attributes opts) &&     attr /= nullAttr = -- use raw HTML-    return $ text $ trim $ writeHtmlString def $ Pandoc nullMeta [Plain [lnk]]+    (text . T.unpack . T.strip) <$>+      writeHtml5String def (Pandoc nullMeta [Plain [lnk]])   | otherwise = do   plain <- asks envPlain   linktext <- inlineListToMarkdown opts txt@@ -1063,20 +1153,20 @@   let useAuto = isURI src &&                 case txt of                       [Str s] | escapeURI s == srcSuffix -> True-                      _                                  -> False+                      _       -> False   let useRefLinks = writerReferenceLinks opts && not useAuto   shortcutable <- asks envRefShortcutable   let useShortcutRefLinks = shortcutable &&                             isEnabled Ext_shortcut_reference_links opts-  ref <- if useRefLinks then getReference attr txt (src, tit) else return []-  reftext <- inlineListToMarkdown opts ref+  reftext <- if useRefLinks then getReference attr linktext (src, tit)+                            else return empty   return $ if useAuto               then if plain                       then text srcSuffix                       else "<" <> text srcSuffix <> ">"               else if useRefLinks                       then let first  = "[" <> linktext <> "]"-                               second = if txt == ref+                               second = if getKey linktext == getKey reftext                                            then if useShortcutRefLinks                                                    then ""                                                    else "[]"@@ -1091,7 +1181,8 @@   | isEnabled Ext_raw_html opts &&     not (isEnabled Ext_link_attributes opts) &&     attr /= nullAttr = -- use raw HTML-    return $ text $ trim $ writeHtmlString def $ Pandoc nullMeta [Plain [img]]+    (text . T.unpack . T.strip) <$>+      writeHtml5String def (Pandoc nullMeta [Plain [img]])   | otherwise = do   plain <- asks envPlain   let txt = if null alternate || alternate == [Str source]@@ -1114,4 +1205,36 @@ makeMathPlainer = walk go   where   go (Emph xs) = Span nullAttr xs-  go x = x+  go x         = x++toSuperscript :: Char -> Maybe Char+toSuperscript '1' = Just '\x00B9'+toSuperscript '2' = Just '\x00B2'+toSuperscript '3' = Just '\x00B3'+toSuperscript '+' = Just '\x207A'+toSuperscript '-' = Just '\x207B'+toSuperscript '=' = Just '\x207C'+toSuperscript '(' = Just '\x207D'+toSuperscript ')' = Just '\x207E'+toSuperscript c+  | c >= '0' && c <= '9' =+                 Just $ chr (0x2070 + (ord c - 48))+  | isSpace c = Just c+  | otherwise = Nothing++toSubscript :: Char -> Maybe Char+toSubscript '+' = Just '\x208A'+toSubscript '-' = Just '\x208B'+toSubscript '=' = Just '\x208C'+toSubscript '(' = Just '\x208D'+toSubscript ')' = Just '\x208E'+toSubscript c+  | c >= '0' && c <= '9' =+                 Just $ chr (0x2080 + (ord c - 48))+  | isSpace c = Just c+  | otherwise = Nothing++lineBreakToSpace :: Inline -> Inline+lineBreakToSpace LineBreak = Space+lineBreakToSpace SoftBreak = Space+lineBreakToSpace x         = x
+ src/Text/Pandoc/Writers/Math.hs view
@@ -0,0 +1,56 @@+module Text.Pandoc.Writers.Math+  ( texMathToInlines+  , convertMath+  , defaultMathJaxURL+  , defaultKaTeXURL+  )+where++import Text.Pandoc.Class+import Text.Pandoc.Definition+import Text.Pandoc.Logging+import Text.TeXMath (DisplayType (..), Exp, readTeX, writePandoc)++-- | Converts a raw TeX math formula to a list of 'Pandoc' inlines.+-- Defaults to raw formula between @$@ or @$$@ characters if entire formula+-- can't be converted.+texMathToInlines :: PandocMonad m+                 => MathType+                 -> String    -- ^ String to parse (assumes @'\n'@ line endings)+                 -> m [Inline]+texMathToInlines mt inp = do+  res <- convertMath writePandoc mt inp+  case res of+       Right (Just ils)  -> return ils+       Right Nothing   -> do+         report $ CouldNotConvertTeXMath inp ""+         return [mkFallback mt inp]+       Left il           -> return [il]++mkFallback :: MathType -> String -> Inline+mkFallback mt str = Str (delim ++ str ++ delim)+   where delim = case mt of+                      DisplayMath -> "$$"+                      InlineMath  -> "$"++-- | Converts a raw TeX math formula using a writer function,+-- issuing a warning and producing a fallback (a raw string)+-- on failure.+convertMath :: PandocMonad m+            => (DisplayType -> [Exp] -> a) -> MathType -> String+            -> m (Either Inline a)+convertMath writer mt str =+  case writer dt <$> readTeX str of+       Right r  -> return (Right r)+       Left e   -> do+         report $ CouldNotConvertTeXMath str e+         return (Left $ mkFallback mt str)+   where dt = case mt of+                   DisplayMath -> DisplayBlock+                   InlineMath  -> DisplayInline++defaultMathJaxURL :: String+defaultMathJaxURL = "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/"++defaultKaTeXURL :: String+defaultKaTeXURL = "https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.8.3/"
src/Text/Pandoc/Writers/MediaWiki.hs view
@@ -1,5 +1,5 @@ {--Copyright (C) 2008-2015 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2008-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -18,7 +18,7 @@  {- |    Module      : Text.Pandoc.Writers.MediaWiki-   Copyright   : Copyright (C) 2008-2015 John MacFarlane+   Copyright   : Copyright (C) 2008-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -30,41 +30,44 @@ MediaWiki:  <http://www.mediawiki.org/wiki/MediaWiki> -} module Text.Pandoc.Writers.MediaWiki ( writeMediaWiki ) where+import Control.Monad.Reader+import Control.Monad.State.Strict+import Data.List (intercalate)+import qualified Data.Set as Set+import Data.Text (Text, pack)+import Text.Pandoc.Class (PandocMonad, report) import Text.Pandoc.Definition+import Text.Pandoc.ImageSize+import Text.Pandoc.Logging import Text.Pandoc.Options-import Text.Pandoc.Shared-import Text.Pandoc.Writers.Shared import Text.Pandoc.Pretty (render)-import Text.Pandoc.ImageSize+import Text.Pandoc.Shared import Text.Pandoc.Templates (renderTemplate')-import Text.Pandoc.XML ( escapeStringForXML )-import Data.List ( intersect, intercalate )-import Network.URI ( isURI )-import Control.Monad.Reader-import Control.Monad.State+import Text.Pandoc.Writers.Shared+import Text.Pandoc.XML (escapeStringForXML)  data WriterState = WriterState {-    stNotes     :: Bool            -- True if there are notes-  , stOptions   :: WriterOptions   -- writer options+    stNotes   :: Bool            -- True if there are notes+  , stOptions :: WriterOptions   -- writer options   }  data WriterReader = WriterReader {-    options     :: WriterOptions -- Writer options-  , listLevel   :: String        -- String at beginning of list items, e.g. "**"-  , useTags     :: Bool          -- True if we should use HTML tags because we're in a complex list+    options   :: WriterOptions -- Writer options+  , listLevel :: String        -- String at beginning of list items, e.g. "**"+  , useTags   :: Bool          -- True if we should use HTML tags because we're in a complex list   } -type MediaWikiWriter = ReaderT WriterReader (State WriterState)+type MediaWikiWriter m = ReaderT WriterReader (StateT WriterState m)  -- | Convert Pandoc to MediaWiki.-writeMediaWiki :: WriterOptions -> Pandoc -> String+writeMediaWiki :: PandocMonad m => WriterOptions -> Pandoc -> m Text writeMediaWiki opts document =   let initialState = WriterState { stNotes = False, stOptions = opts }       env = WriterReader { options = opts, listLevel = [], useTags = False }-  in  evalState (runReaderT (pandocToMediaWiki document) env) initialState+  in  evalStateT (runReaderT (pandocToMediaWiki document) env) initialState  -- | Return MediaWiki representation of document.-pandocToMediaWiki :: Pandoc -> MediaWikiWriter String+pandocToMediaWiki :: PandocMonad m => Pandoc -> MediaWikiWriter m Text pandocToMediaWiki (Pandoc meta blocks) = do   opts <- asks options   metadata <- metaToJSON opts@@ -79,8 +82,8 @@   let main = body ++ notes   let context = defField "body" main                 $ defField "toc" (writerTableOfContents opts) metadata-  return $ case writerTemplate opts of-                Nothing  -> main+  pack <$> case writerTemplate opts of+                Nothing  -> return main                 Just tpl -> renderTemplate' tpl context  -- | Escape special characters for MediaWiki.@@ -88,8 +91,9 @@ escapeString =  escapeStringForXML  -- | Convert Pandoc block element to MediaWiki.-blockToMediaWiki :: Block         -- ^ Block element-                 -> MediaWikiWriter String+blockToMediaWiki :: PandocMonad m+                 => Block         -- ^ Block element+                 -> MediaWikiWriter m String  blockToMediaWiki Null = return "" @@ -123,10 +127,10 @@ blockToMediaWiki (LineBlock lns) =   blockToMediaWiki $ linesToPara lns -blockToMediaWiki (RawBlock f str)+blockToMediaWiki b@(RawBlock f str)   | f == Format "mediawiki" = return str   | f == Format "html"      = return str-  | otherwise               = return ""+  | otherwise               = "" <$ report (BlockNotRendered b)  blockToMediaWiki HorizontalRule = return "\n-----\n" @@ -136,23 +140,15 @@   return $ eqs ++ " " ++ contents ++ " " ++ eqs ++ "\n"  blockToMediaWiki (CodeBlock (_,classes,_) str) = do-  let at  = classes `intersect` ["actionscript", "ada", "apache", "applescript", "asm", "asp",-                       "autoit", "bash", "blitzbasic", "bnf", "c", "c_mac", "caddcl", "cadlisp", "cfdg", "cfm",-                       "cpp", "cpp-qt", "csharp", "css", "d", "delphi", "diff", "div", "dos", "eiffel", "fortran",-                       "freebasic", "gml", "groovy", "html4strict", "idl", "ini", "inno", "io", "java", "java5",-                       "javascript", "latex", "lisp", "lua", "matlab", "mirc", "mpasm", "mysql", "nsis", "objc",-                       "ocaml", "ocaml-brief", "oobas", "oracle8", "pascal", "perl", "php", "php-brief", "plsql",-                       "python", "qbasic", "rails", "reg", "robots", "ruby", "sas", "scheme", "sdlbasic",-                       "smalltalk", "smarty", "sql", "tcl", "", "thinbasic", "tsql", "vb", "vbnet", "vhdl",-                       "visualfoxpro", "winbatch", "xml", "xpp", "z80"]+  let at  = Set.fromList classes `Set.intersection` highlightingLangs   return $-    if null at-       then "<pre" ++ (if null classes-                          then ">"-                          else " class=\"" ++ unwords classes ++ "\">") ++-            escapeString str ++ "</pre>"-       else "<source lang=\"" ++ head at ++ "\">" ++ str ++ "</source>"-            -- note:  no escape!+    case Set.toList at of+       [] -> "<pre" ++ (if null classes+                           then ">"+                           else " class=\"" ++ unwords classes ++ "\">") +++             escapeString str ++ "</pre>"+       (l:_) -> "<source lang=\"" ++ l ++ "\">" ++ str ++ "</source>"+            -- note:  no escape!  even for <!  blockToMediaWiki (BlockQuote blocks) = do   contents <- blockListToMediaWiki blocks@@ -218,7 +214,7 @@           else "")  -- | Convert bullet or ordered list item (list of blocks) to MediaWiki.-listItemToMediaWiki :: [Block] -> MediaWikiWriter String+listItemToMediaWiki :: PandocMonad m => [Block] -> MediaWikiWriter m String listItemToMediaWiki items = do   contents <- blockListToMediaWiki items   tags <- asks useTags@@ -229,8 +225,9 @@        return $ marker ++ " " ++ contents  -- | Convert definition list item (label, list of blocks) to MediaWiki.-definitionListItemToMediaWiki :: ([Inline],[[Block]])-                              -> MediaWikiWriter String+definitionListItemToMediaWiki :: PandocMonad m+                              => ([Inline],[[Block]])+                              -> MediaWikiWriter m String definitionListItemToMediaWiki (label, items) = do   labelText <- inlineListToMediaWiki label   contents <- mapM blockListToMediaWiki items@@ -259,18 +256,18 @@ isSimpleListItem []  = True isSimpleListItem [x] =   case x of-       Plain _           -> True-       Para  _           -> True-       BulletList _      -> isSimpleList x-       OrderedList _ _   -> isSimpleList x-       DefinitionList _  -> isSimpleList x-       _                 -> False+       Plain _          -> True+       Para  _          -> True+       BulletList _     -> isSimpleList x+       OrderedList _ _  -> isSimpleList x+       DefinitionList _ -> isSimpleList x+       _                -> False isSimpleListItem [x, y] | isPlainOrPara x =   case y of-       BulletList _      -> isSimpleList y-       OrderedList _ _   -> isSimpleList y-       DefinitionList _  -> isSimpleList y-       _                 -> False+       BulletList _     -> isSimpleList y+       OrderedList _ _  -> isSimpleList y+       DefinitionList _ -> isSimpleList y+       _                -> False isSimpleListItem _ = False  isPlainOrPara :: Block -> Bool@@ -284,20 +281,22 @@  -- Auxiliary functions for tables: -tableRowToMediaWiki :: Bool+tableRowToMediaWiki :: PandocMonad m+                    => Bool                     -> [Alignment]                     -> [Double]                     -> (Int, [[Block]])-                    -> MediaWikiWriter String+                    -> MediaWikiWriter m String tableRowToMediaWiki headless alignments widths (rownum, cells) = do   cells' <- mapM (tableCellToMediaWiki headless rownum)           $ zip3 alignments widths cells   return $ unlines cells' -tableCellToMediaWiki :: Bool+tableCellToMediaWiki :: PandocMonad m+                     => Bool                      -> Int                      -> (Alignment, Double, [Block])-                     -> MediaWikiWriter String+                     -> MediaWikiWriter m String tableCellToMediaWiki headless rownum (alignment, width, bs) = do   contents <- blockListToMediaWiki bs   let marker = if rownum == 1 && not headless then "!" else "|"@@ -322,13 +321,13 @@                                  AlignCenter  -> "center"                                  AlignDefault -> "left" -imageToMediaWiki :: Attr -> MediaWikiWriter String+imageToMediaWiki :: PandocMonad m => Attr -> MediaWikiWriter m String imageToMediaWiki attr = do   opts <- gets stOptions   let (_, cls, _) = attr       toPx = fmap (showInPixel opts) . checkPct       checkPct (Just (Percent _)) = Nothing-      checkPct maybeDim = maybeDim+      checkPct maybeDim           = maybeDim       go (Just w) Nothing  = '|':w ++ "px"       go (Just w) (Just h) = '|':w ++ "x" ++ h ++ "px"       go Nothing  (Just h) = "|x" ++ h ++ "px"@@ -340,18 +339,19 @@   return $ dims ++ classes  -- | Convert list of Pandoc block elements to MediaWiki.-blockListToMediaWiki :: [Block]       -- ^ List of block elements-                     -> MediaWikiWriter String+blockListToMediaWiki :: PandocMonad m+                     => [Block]       -- ^ List of block elements+                     -> MediaWikiWriter m String blockListToMediaWiki blocks =   fmap vcat $ mapM blockToMediaWiki blocks  -- | Convert list of Pandoc inline elements to MediaWiki.-inlineListToMediaWiki :: [Inline] -> MediaWikiWriter String+inlineListToMediaWiki :: PandocMonad m => [Inline] -> MediaWikiWriter m String inlineListToMediaWiki lst =   fmap concat $ mapM inlineToMediaWiki lst  -- | Convert Pandoc inline element to MediaWiki.-inlineToMediaWiki :: Inline -> MediaWikiWriter String+inlineToMediaWiki :: PandocMonad m => Inline -> MediaWikiWriter m String  inlineToMediaWiki (Span attrs ils) = do   contents <- inlineListToMediaWiki ils@@ -394,22 +394,28 @@  inlineToMediaWiki (Str str) = return $ escapeString str -inlineToMediaWiki (Math _ str) = return $ "<math>" ++ str ++ "</math>"-                               -- note:  str should NOT be escaped+inlineToMediaWiki (Math mt str) = return $+  "<math display=\"" +++  (if mt == DisplayMath then "block" else "inline") +++  "\">" ++ str ++ "</math>"+  -- note:  str should NOT be escaped -inlineToMediaWiki (RawInline f str)+inlineToMediaWiki il@(RawInline f str)   | f == Format "mediawiki" = return str   | f == Format "html"      = return str-  | otherwise               = return ""+  | otherwise               = "" <$ report (InlineNotRendered il) -inlineToMediaWiki (LineBreak) = return "<br />\n"+inlineToMediaWiki LineBreak = return "<br />\n"  inlineToMediaWiki SoftBreak = do   wrapText <- gets (writerWrapText . stOptions)+  listlevel <- asks listLevel   case wrapText of        WrapAuto     -> return " "        WrapNone     -> return " "-       WrapPreserve -> return "\n"+       WrapPreserve -> if null listlevel+                          then return "\n"+                          else return " "  inlineToMediaWiki Space = return " " @@ -437,5 +443,636 @@ inlineToMediaWiki (Note contents) = do   contents' <- blockListToMediaWiki contents   modify (\s -> s { stNotes = True })-  return $ "<ref>" ++ contents' ++ "</ref>"-  -- note - may not work for notes with multiple blocks+  return $ "<ref>" ++ stripTrailingNewlines contents' ++ "</ref>"+  -- note - does not work for notes with multiple blocks++highlightingLangs :: Set.Set String+highlightingLangs = Set.fromList [+  "abap",+  "abl",+  "abnf",+  "aconf",+  "actionscript",+  "actionscript3",+  "ada",+  "ada2005",+  "ada95",+  "adl",+  "agda",+  "ahk",+  "alloy",+  "ambienttalk",+  "ambienttalk/2",+  "antlr",+  "antlr-actionscript",+  "antlr-as",+  "antlr-c#",+  "antlr-cpp",+  "antlr-csharp",+  "antlr-java",+  "antlr-objc",+  "antlr-perl",+  "antlr-python",+  "antlr-rb",+  "antlr-ruby",+  "apache",+  "apacheconf",+  "apl",+  "applescript",+  "arduino",+  "arexx",+  "as",+  "as3",+  "asm",+  "aspectj",+  "aspx-cs",+  "aspx-vb",+  "asy",+  "asymptote",+  "at",+  "autohotkey",+  "autoit",+  "awk",+  "b3d",+  "basemake",+  "bash",+  "basic",+  "bat",+  "batch",+  "bbcode",+  "because",+  "befunge",+  "bf",+  "blitzbasic",+  "blitzmax",+  "bmax",+  "bnf",+  "boo",+  "boogie",+  "bplus",+  "brainfuck",+  "bro",+  "bsdmake",+  "bugs",+  "c",+  "c#",+  "c++",+  "c++-objdumb",+  "c-objdump",+  "ca65",+  "cadl",+  "camkes",+  "cbmbas",+  "ceylon",+  "cf3",+  "cfc",+  "cfengine3",+  "cfg",+  "cfm",+  "cfs",+  "chai",+  "chaiscript",+  "chapel",+  "cheetah",+  "chpl",+  "cirru",+  "cl",+  "clay",+  "clipper",+  "clj",+  "cljs",+  "clojure",+  "clojurescript",+  "cmake",+  "cobol",+  "cobolfree",+  "coffee",+  "coffee-script",+  "coffeescript",+  "common-lisp",+  "componentpascal",+  "console",+  "control",+  "coq",+  "cp",+  "cpp",+  "cpp-objdump",+  "cpsa",+  "crmsh",+  "croc",+  "cry",+  "cryptol",+  "csh",+  "csharp",+  "csound",+  "csound-csd",+  "csound-document",+  "csound-orc",+  "csound-sco",+  "csound-score",+  "css",+  "css+django",+  "css+erb",+  "css+genshi",+  "css+genshitext",+  "css+jinja",+  "css+lasso",+  "css+mako",+  "css+mozpreproc",+  "css+myghty",+  "css+php",+  "css+ruby",+  "css+smarty",+  "cu",+  "cucumber",+  "cuda",+  "cxx-objdump",+  "cypher",+  "cython",+  "d",+  "d-objdump",+  "dart",+  "debcontrol",+  "debsources",+  "delphi",+  "dg",+  "diff",+  "django",+  "docker",+  "dockerfile",+  "dosbatch",+  "doscon",+  "dosini",+  "dpatch",+  "dtd",+  "duby",+  "duel",+  "dylan",+  "dylan-console",+  "dylan-lid",+  "dylan-repl",+  "earl-grey",+  "earlgrey",+  "easytrieve",+  "ebnf",+  "ec",+  "ecl",+  "eg",+  "eiffel",+  "elisp",+  "elixir",+  "elm",+  "emacs",+  "erb",+  "erl",+  "erlang",+  "evoque",+  "ex",+  "exs",+  "ezhil",+  "factor",+  "fan",+  "fancy",+  "felix",+  "fish",+  "fishshell",+  "flx",+  "fortran",+  "fortranfixed",+  "foxpro",+  "fsharp",+  "fy",+  "gap",+  "gas",+  "gawk",+  "genshi",+  "genshitext",+  "gherkin",+  "glsl",+  "gnuplot",+  "go",+  "golo",+  "gooddata-cl",+  "gosu",+  "groff",+  "groovy",+  "gst",+  "haml",+  "handlebars",+  "haskell",+  "haxe",+  "haxeml",+  "hexdump",+  "hs",+  "html",+  "html+cheetah",+  "html+django",+  "html+erb",+  "html+evoque",+  "html+genshi",+  "html+handlebars",+  "html+jinja",+  "html+kid",+  "html+lasso",+  "html+mako",+  "html+myghty",+  "html+php",+  "html+ruby",+  "html+smarty",+  "html+spitfire",+  "html+twig",+  "html+velocity",+  "htmlcheetah",+  "htmldjango",+  "http",+  "hx",+  "hxml",+  "hxsl",+  "hy",+  "hybris",+  "hylang",+  "i6",+  "i6t",+  "i7",+  "idl",+  "idl4",+  "idr",+  "idris",+  "iex",+  "igor",+  "igorpro",+  "ik",+  "inform6",+  "inform7",+  "ini",+  "io",+  "ioke",+  "irb",+  "irc",+  "isabelle",+  "j",+  "jade",+  "jags",+  "jasmin",+  "jasminxt",+  "java",+  "javascript",+  "javascript+cheetah",+  "javascript+django",+  "javascript+erb",+  "javascript+genshi",+  "javascript+genshitext",+  "javascript+jinja",+  "javascript+lasso",+  "javascript+mako",+  "javascript+mozpreproc",+  "javascript+myghty",+  "javascript+php",+  "javascript+ruby",+  "javascript+smarty",+  "javascript+spitfire",+  "jbst",+  "jcl",+  "jinja",+  "jl",+  "jlcon",+  "jproperties",+  "js",+  "js+cheetah",+  "js+django",+  "js+erb",+  "js+genshi",+  "js+genshitext",+  "js+jinja",+  "js+lasso",+  "js+mako",+  "js+myghty",+  "js+php",+  "js+ruby",+  "js+smarty",+  "js+spitfire",+  "json",+  "json-ld",+  "jsonld",+  "jsonml+bst",+  "jsp",+  "julia",+  "kal",+  "kconfig",+  "kernel-config",+  "kid",+  "koka",+  "kotlin",+  "ksh",+  "lagda",+  "lasso",+  "lassoscript",+  "latex",+  "lcry",+  "lcryptol",+  "lean",+  "less",+  "lhaskell",+  "lhs",+  "lid",+  "lidr",+  "lidris",+  "lighttpd",+  "lighty",+  "limbo",+  "linux-config",+  "liquid",+  "lisp",+  "literate-agda",+  "literate-cryptol",+  "literate-haskell",+  "literate-idris",+  "live-script",+  "livescript",+  "llvm",+  "logos",+  "logtalk",+  "lsl",+  "lua",+  "m2",+  "make",+  "makefile",+  "mako",+  "man",+  "maql",+  "mask",+  "mason",+  "mathematica",+  "matlab",+  "matlabsession",+  "mawk",+  "menuconfig",+  "mf",+  "minid",+  "mma",+  "modelica",+  "modula2",+  "moin",+  "monkey",+  "moo",+  "moocode",+  "moon",+  "moonscript",+  "mozhashpreproc",+  "mozpercentpreproc",+  "mq4",+  "mq5",+  "mql",+  "mql4",+  "mql5",+  "msc",+  "mscgen",+  "mupad",+  "mxml",+  "myghty",+  "mysql",+  "nasm",+  "nawk",+  "nb",+  "nemerle",+  "nesc",+  "newlisp",+  "newspeak",+  "nginx",+  "nim",+  "nimrod",+  "nit",+  "nix",+  "nixos",+  "nroff",+  "nsh",+  "nsi",+  "nsis",+  "numpy",+  "obj-c",+  "obj-c++",+  "obj-j",+  "objc",+  "objc++",+  "objdump",+  "objdump-nasm",+  "objective-c",+  "objective-c++",+  "objective-j",+  "objectivec",+  "objectivec++",+  "objectivej",+  "objectpascal",+  "objj",+  "ocaml",+  "octave",+  "odin",+  "ooc",+  "opa",+  "openbugs",+  "openedge",+  "pacmanconf",+  "pan",+  "parasail",+  "pas",+  "pascal",+  "pawn",+  "pcmk",+  "perl",+  "perl6",+  "php",+  "php3",+  "php4",+  "php5",+  "pig",+  "pike",+  "pkgconfig",+  "pl",+  "pl6",+  "plpgsql",+  "po",+  "posh",+  "postgres",+  "postgres-console",+  "postgresql",+  "postgresql-console",+  "postscr",+  "postscript",+  "pot",+  "pov",+  "powershell",+  "praat",+  "progress",+  "prolog",+  "properties",+  "proto",+  "protobuf",+  "ps1",+  "ps1con",+  "psm1",+  "psql",+  "puppet",+  "py",+  "py3",+  "py3tb",+  "pycon",+  "pypy",+  "pypylog",+  "pyrex",+  "pytb",+  "python",+  "python3",+  "pyx",+  "qbasic",+  "qbs",+  "qml",+  "qvt",+  "qvto",+  "r",+  "racket",+  "ragel",+  "ragel-c",+  "ragel-cpp",+  "ragel-d",+  "ragel-em",+  "ragel-java",+  "ragel-objc",+  "ragel-rb",+  "ragel-ruby",+  "raw",+  "rb",+  "rbcon",+  "rconsole",+  "rd",+  "rebol",+  "red",+  "red/system",+  "redcode",+  "registry",+  "resource",+  "resourcebundle",+  "rest",+  "restructuredtext",+  "rexx",+  "rhtml",+  "rkt",+  "roboconf-graph",+  "roboconf-instances",+  "robotframework",+  "rout",+  "rql",+  "rsl",+  "rst",+  "rts",+  "ruby",+  "rust",+  "s",+  "sage",+  "salt",+  "sass",+  "sc",+  "scala",+  "scaml",+  "scheme",+  "scilab",+  "scm",+  "scss",+  "sh",+  "shell",+  "shell-session",+  "shen",+  "slim",+  "sls",+  "smali",+  "smalltalk",+  "smarty",+  "sml",+  "snobol",+  "sources.list",+  "sourceslist",+  "sp",+  "sparql",+  "spec",+  "spitfire",+  "splus",+  "sql",+  "sqlite3",+  "squeak",+  "squid",+  "squid.conf",+  "squidconf",+  "ssp",+  "st",+  "stan",+  "supercollider",+  "sv",+  "swift",+  "swig",+  "systemverilog",+  "tads3",+  "tap",+  "tcl",+  "tcsh",+  "tcshcon",+  "tea",+  "termcap",+  "terminfo",+  "terraform",+  "tex",+  "text",+  "tf",+  "thrift",+  "todotxt",+  "trac-wiki",+  "trafficscript",+  "treetop",+  "ts",+  "turtle",+  "twig",+  "typescript",+  "udiff",+  "urbiscript",+  "v",+  "vala",+  "vapi",+  "vb.net",+  "vbnet",+  "vctreestatus",+  "velocity",+  "verilog",+  "vfp",+  "vgl",+  "vhdl",+  "vim",+  "winbatch",+  "winbugs",+  "x10",+  "xbase",+  "xml",+  "xml+cheetah",+  "xml+django",+  "xml+erb",+  "xml+evoque",+  "xml+genshi",+  "xml+jinja",+  "xml+kid",+  "xml+lasso",+  "xml+mako",+  "xml+myghty",+  "xml+php",+  "xml+ruby",+  "xml+smarty",+  "xml+spitfire",+  "xml+velocity",+  "xq",+  "xql",+  "xqm",+  "xquery",+  "xqy",+  "xslt",+  "xten",+  "xtend",+  "xul+mozpreproc",+  "yaml",+  "yaml+jinja",+  "zephir" ]
+ src/Text/Pandoc/Writers/Ms.hs view
@@ -0,0 +1,639 @@+{-+Copyright (C) 2007-2017 John MacFarlane <jgm@berkeley.edu>++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation; either version 2 of the License, or+(at your option) any later version.++This program is distributed in the hope that it will be useful,+but WITHOUT ANY WARRANTY; without even the implied warranty of+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+GNU General Public License for more details.++You should have received a copy of the GNU General Public License+along with this program; if not, write to the Free Software+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+-}++{- |+   Module      : Text.Pandoc.Writers.Ms+   Copyright   : Copyright (C) 2007-2017 John MacFarlane+   License     : GNU GPL, version 2 or above++   Maintainer  : John MacFarlane <jgm@berkeley.edu>+   Stability   : alpha+   Portability : portable++Conversion of 'Pandoc' documents to groff ms format.++TODO:++[ ] use base URL to construct absolute URLs from relative ones for external+    links+[ ] is there a better way to do strikeout?+[ ] tight/loose list distinction+-}++module Text.Pandoc.Writers.Ms ( writeMs ) where+import Control.Monad.State.Strict+import Data.Char (isLower, isUpper, toUpper)+import Data.List (intercalate, intersperse, sort)+import qualified Data.Map as Map+import Data.Maybe (catMaybes, fromMaybe)+import Data.Text (Text)+import qualified Data.Text as T+import Network.URI (escapeURIString, isAllowedInURI)+import Skylighting+import System.FilePath (takeExtension)+import Text.Pandoc.Class (PandocMonad, report)+import Text.Pandoc.Definition+import Text.Pandoc.Highlighting+import Text.Pandoc.ImageSize+import Text.Pandoc.Logging+import Text.Pandoc.Options+import Text.Pandoc.Pretty+import Text.Pandoc.Shared+import Text.Pandoc.Templates+import Text.Pandoc.Writers.Math+import Text.Pandoc.Writers.Shared+import Text.Printf (printf)+import Text.TeXMath (writeEqn)++data WriterState = WriterState { stHasInlineMath :: Bool+                               , stFirstPara     :: Bool+                               , stNotes         :: [Note]+                               , stSmallCaps     :: Bool+                               , stHighlighting  :: Bool+                               , stFontFeatures  :: Map.Map Char Bool+                               }++defaultWriterState :: WriterState+defaultWriterState = WriterState{ stHasInlineMath = False+                                , stFirstPara     = True+                                , stNotes         = []+                                , stSmallCaps     = False+                                , stHighlighting  = False+                                , stFontFeatures  = Map.fromList [+                                                       ('I',False)+                                                     , ('B',False)+                                                     , ('C',False)+                                                     ]+                                }++type Note = [Block]++type MS = StateT WriterState++-- | Convert Pandoc to Ms.+writeMs :: PandocMonad m => WriterOptions -> Pandoc -> m Text+writeMs opts document =+  evalStateT (pandocToMs opts document) defaultWriterState++-- | Return groff ms representation of document.+pandocToMs :: PandocMonad m => WriterOptions -> Pandoc -> MS m Text+pandocToMs opts (Pandoc meta blocks) = do+  let colwidth = if writerWrapText opts == WrapAuto+                    then Just $ writerColumns opts+                    else Nothing+  let render' :: Doc -> Text+      render' = render colwidth+  metadata <- metaToJSON opts+              (fmap render' . blockListToMs opts)+              (fmap render' . inlineListToMs' opts)+              meta+  body <- blockListToMs opts blocks+  let main = render' body+  hasInlineMath <- gets stHasInlineMath+  let titleMeta = (escapeString . stringify) $ docTitle meta+  let authorsMeta = map (escapeString . stringify) $ docAuthors meta+  hasHighlighting <- gets stHighlighting+  let highlightingMacros = if hasHighlighting+                              then case writerHighlightStyle opts of+                                        Nothing  -> mempty+                                        Just sty -> render' $ styleToMs sty+                              else mempty++  let context = defField "body" main+              $ defField "has-inline-math" hasInlineMath+              $ defField "hyphenate" True+              $ defField "pandoc-version" pandocVersion+              $ defField "toc" (writerTableOfContents opts)+              $ defField "title-meta" titleMeta+              $ defField "author-meta" (intercalate "; " authorsMeta)+              $ defField "highlighting-macros" highlightingMacros metadata+  case writerTemplate opts of+       Nothing  -> return main+       Just tpl -> renderTemplate' tpl context++-- | Association list of characters to escape.+msEscapes :: Map.Map Char String+msEscapes = Map.fromList+              [ ('\160', "\\~")+              , ('\'', "\\[aq]")+              , ('`', "\\`")+              , ('\8217', "'")+              , ('"', "\\[dq]")+              , ('\x2014', "\\[em]")+              , ('\x2013', "\\[en]")+              , ('\x2026', "\\&...")+              , ('~', "\\[ti]")+              , ('^', "\\[ha]")+              , ('-', "\\-")+              , ('@', "\\@")+              , ('\\', "\\\\")+              ]++escapeChar :: Char -> String+escapeChar c = fromMaybe [c] (Map.lookup c msEscapes)++-- | Escape | character, used to mark inline math, inside math.+escapeBar :: String -> String+escapeBar = concatMap go+  where go '|' = "\\[u007C]"+        go c   = [c]++-- | Escape special characters for Ms.+escapeString :: String -> String+escapeString = concatMap escapeChar++escapeUri :: String -> String+escapeUri = escapeURIString (\c -> c /= '@' && isAllowedInURI c)++toSmallCaps :: String -> String+toSmallCaps [] = []+toSmallCaps (c:cs)+  | isLower c = let (lowers,rest) = span isLower (c:cs)+                in  "\\s-2" ++ escapeString (map toUpper lowers) +++                    "\\s0" ++ toSmallCaps rest+  | isUpper c = let (uppers,rest) = span isUpper (c:cs)+                in  escapeString uppers ++ toSmallCaps rest+  | otherwise = escapeChar c ++ toSmallCaps cs++-- | Escape a literal (code) section for Ms.+escapeCode :: String -> String+escapeCode = intercalate "\n" . map escapeLine . lines+  where escapeCodeChar ' '  = "\\ "+        escapeCodeChar '\t' = "\\\t"+        escapeCodeChar c    = escapeChar c+        escapeLine codeline =+          case concatMap escapeCodeChar codeline of+            a@('.':_) -> "\\&" ++ a+            b         -> b++-- We split inline lists into sentences, and print one sentence per+-- line.  groff/troff treats the line-ending period differently.+-- See http://code.google.com/p/pandoc/issues/detail?id=148.++-- | Returns the first sentence in a list of inlines, and the rest.+breakSentence :: [Inline] -> ([Inline], [Inline])+breakSentence [] = ([],[])+breakSentence xs =+  let isSentenceEndInline (Str ys@(_:_)) | last ys == '.' = True+      isSentenceEndInline (Str ys@(_:_)) | last ys == '?' = True+      isSentenceEndInline LineBreak      = True+      isSentenceEndInline _              = False+      (as, bs) = break isSentenceEndInline xs+  in  case bs of+           []             -> (as, [])+           [c]            -> (as ++ [c], [])+           (c:Space:cs)   -> (as ++ [c], cs)+           (c:SoftBreak:cs) -> (as ++ [c], cs)+           (Str ".":Str (')':ys):cs) -> (as ++ [Str ".", Str (')':ys)], cs)+           (x@(Str ('.':')':_)):cs) -> (as ++ [x], cs)+           (LineBreak:x@(Str ('.':_)):cs) -> (as ++[LineBreak], x:cs)+           (c:cs)         -> (as ++ [c] ++ ds, es)+              where (ds, es) = breakSentence cs++-- | Split a list of inlines into sentences.+splitSentences :: [Inline] -> [[Inline]]+splitSentences xs =+  let (sent, rest) = breakSentence xs+  in  if null rest then [sent] else sent : splitSentences rest++blockToMs :: PandocMonad m+          => WriterOptions -- ^ Options+          -> Block         -- ^ Block element+          -> MS m Doc+blockToMs _ Null = return empty+blockToMs opts (Div _ bs) = do+  setFirstPara+  res <- blockListToMs opts bs+  setFirstPara+  return res+blockToMs opts (Plain inlines) =+  liftM vcat $ mapM (inlineListToMs' opts) $ splitSentences inlines+blockToMs opts (Para [Image attr alt (src,_tit)])+  | let ext = takeExtension src in (ext == ".ps" || ext == ".eps") = do+  let (mbW,mbH) = (inPoints opts <$> dimension Width attr,+                   inPoints opts <$> dimension Height attr)+  let sizeAttrs = case (mbW, mbH) of+                       (Just wp, Nothing) -> space <> doubleQuotes+                              (text (show (floor wp :: Int) ++ "p"))+                       (Just wp, Just hp) -> space <> doubleQuotes+                              (text (show (floor wp :: Int) ++ "p")) <>+                              space <>+                              doubleQuotes (text (show (floor hp :: Int)))+                       _ -> empty+  capt <- inlineListToMs' opts alt+  return $ nowrap (text ".PSPIC -C " <>+             doubleQuotes (text (escapeString src)) <>+             sizeAttrs) $$+           text ".ce 1000" $$+           capt $$+           text ".ce 0"+blockToMs opts (Para inlines) = do+  firstPara <- gets stFirstPara+  resetFirstPara+  contents <- liftM vcat $ mapM (inlineListToMs' opts) $+    splitSentences inlines+  return $ text (if firstPara then ".LP" else ".PP") $$ contents+blockToMs _ b@(RawBlock f str)+  | f == Format "ms" = return $ text str+  | otherwise        = do+      report $ BlockNotRendered b+      return empty+blockToMs _ HorizontalRule = do+  resetFirstPara+  return $ text ".HLINE"+blockToMs opts (Header level (ident,classes,_) inlines) = do+  setFirstPara+  contents <- inlineListToMs' opts $ map breakToSpace inlines+  let (heading, secnum) = if writerNumberSections opts &&+                              "unnumbered" `notElem` classes+                             then (".NH", "\\*[SN]")+                             else (".SH", "")+  let anchor = if null ident+                  then empty+                  else nowrap $+                         text ".pdfhref M " <> doubleQuotes (text ident)+  let bookmark = text ".pdfhref O " <> text (show level ++ " ") <>+                      doubleQuotes (text $ secnum +++                                      (if null secnum+                                          then ""+                                          else "  ") +++                                      escapeString (stringify inlines))+  let backlink = nowrap (text ".pdfhref L -D " <>+       doubleQuotes (text ident) <> space <> text "\\") <> cr <>+       text " -- "+  let tocEntry = if writerTableOfContents opts &&+                     level <= writerTOCDepth opts+                    then text ".XS"+                         $$ backlink <> doubleQuotes (+                            nowrap (text (replicate level '\t') <>+                             (if null secnum+                                 then empty+                                 else text secnum <> text "\\~\\~")+                              <> contents))+                         $$ text ".XE"+                    else empty+  modify $ \st -> st{ stFirstPara = True }+  return $ (text heading <> space <> text (show level)) $$+           contents $$+           bookmark $$+           anchor $$+           tocEntry+blockToMs opts (CodeBlock attr str) = do+  hlCode <- highlightCode opts attr str+  setFirstPara+  return $+    text ".IP" $$+    text ".nf" $$+    text "\\f[C]" $$+    hlCode $$+    text "\\f[]" $$+    text ".fi"+blockToMs opts (LineBlock ls) = do+  resetFirstPara+  blockToMs opts $ Para $ intercalate [LineBreak] ls+blockToMs opts (BlockQuote blocks) = do+  setFirstPara+  contents <- blockListToMs opts blocks+  setFirstPara+  return $ text ".RS" $$ contents $$ text ".RE"+blockToMs opts (Table caption alignments widths headers rows) =+  let aligncode AlignLeft    = "l"+      aligncode AlignRight   = "r"+      aligncode AlignCenter  = "c"+      aligncode AlignDefault = "l"+  in do+  caption' <- inlineListToMs' opts caption+  let iwidths = if all (== 0) widths+                   then repeat ""+                   else map (printf "w(%0.1fn)" . (70 *)) widths+  -- 78n default width - 8n indent = 70n+  let coldescriptions = text $ unwords+                        (zipWith (\align width -> aligncode align ++ width)+                        alignments iwidths) ++ "."+  colheadings <- mapM (blockListToMs opts) headers+  let makeRow cols = text "T{" $$+                     vcat (intersperse (text "T}\tT{") cols) $$+                     text "T}"+  let colheadings' = if all null headers+                        then empty+                        else makeRow colheadings $$ char '_'+  body <- mapM (\row -> do+                         cols <- mapM (blockListToMs opts) row+                         return $ makeRow cols) rows+  setFirstPara+  return $ text ".PP" $$ caption' $$+           text ".TS" $$ text "delim(@@) tab(\t);" $$ coldescriptions $$+           colheadings' $$ vcat body $$ text ".TE"++blockToMs opts (BulletList items) = do+  contents <- mapM (bulletListItemToMs opts) items+  setFirstPara+  return (vcat contents)+blockToMs opts (OrderedList attribs items) = do+  let markers = take (length items) $ orderedListMarkers attribs+  let indent = 2 ++                     maximum (map length markers)+  contents <- mapM (\(num, item) -> orderedListItemToMs opts num indent item) $+              zip markers items+  setFirstPara+  return (vcat contents)+blockToMs opts (DefinitionList items) = do+  contents <- mapM (definitionListItemToMs opts) items+  setFirstPara+  return (vcat contents)++-- | Convert bullet list item (list of blocks) to ms.+bulletListItemToMs :: PandocMonad m => WriterOptions -> [Block] -> MS m Doc+bulletListItemToMs _ [] = return empty+bulletListItemToMs opts (Para first:rest) =+  bulletListItemToMs opts (Plain first:rest)+bulletListItemToMs opts (Plain first:rest) = do+  first' <- blockToMs opts (Plain first)+  rest' <- blockListToMs opts rest+  let first'' = text ".IP \\[bu] 3" $$ first'+  let rest''  = if null rest+                   then empty+                   else text ".RS 3" $$ rest' $$ text ".RE"+  return (first'' $$ rest'')+bulletListItemToMs opts (first:rest) = do+  first' <- blockToMs opts first+  rest' <- blockListToMs opts rest+  return $ text "\\[bu] .RS 3" $$ first' $$ rest' $$ text ".RE"++-- | Convert ordered list item (a list of blocks) to ms.+orderedListItemToMs :: PandocMonad m+                    => WriterOptions -- ^ options+                    -> String   -- ^ order marker for list item+                    -> Int      -- ^ number of spaces to indent+                    -> [Block]  -- ^ list item (list of blocks)+                    -> MS m Doc+orderedListItemToMs _ _ _ [] = return empty+orderedListItemToMs opts num indent (Para first:rest) =+  orderedListItemToMs opts num indent (Plain first:rest)+orderedListItemToMs opts num indent (first:rest) = do+  first' <- blockToMs opts first+  rest' <- blockListToMs opts rest+  let num' = printf ("%" ++ show (indent - 1) ++ "s") num+  let first'' = text (".IP \"" ++ num' ++ "\" " ++ show indent) $$ first'+  let rest''  = if null rest+                   then empty+                   else text ".RS " <> text (show indent) $$+                         rest' $$ text ".RE"+  return $ first'' $$ rest''++-- | Convert definition list item (label, list of blocks) to ms.+definitionListItemToMs :: PandocMonad m+                       => WriterOptions+                       -> ([Inline],[[Block]])+                       -> MS m Doc+definitionListItemToMs opts (label, defs) = do+  labelText <- inlineListToMs' opts $ map breakToSpace label+  contents <- if null defs+                 then return empty+                 else liftM vcat $ forM defs $ \blocks -> do+                        let (first, rest) = case blocks of+                              (Para x:y) -> (Plain x,y)+                              (x:y)      -> (x,y)+                              []         -> (Plain [], [])+                                               -- should not happen+                        rest' <- liftM vcat $+                                  mapM (\item -> blockToMs opts item) rest+                        first' <- blockToMs opts first+                        return $ first' $$ text ".RS" $$ rest' $$ text ".RE"+  return $ nowrap (text ".IP " <> doubleQuotes labelText) $$ contents++-- | Convert list of Pandoc block elements to ms.+blockListToMs :: PandocMonad m+              => WriterOptions -- ^ Options+              -> [Block]       -- ^ List of block elements+              -> MS m Doc+blockListToMs opts blocks =+  mapM (blockToMs opts) blocks >>= (return . vcat)++-- | Convert list of Pandoc inline elements to ms.+inlineListToMs :: PandocMonad m => WriterOptions -> [Inline] -> MS m Doc+-- if list starts with ., insert a zero-width character \& so it+-- won't be interpreted as markup if it falls at the beginning of a line.+inlineListToMs opts lst = hcat <$> mapM (inlineToMs opts) lst++-- This version to be used when there is no further inline content;+-- forces a note at the end.+inlineListToMs' :: PandocMonad m => WriterOptions -> [Inline] -> MS m Doc+inlineListToMs' opts lst = do+  x <- hcat <$> mapM (inlineToMs opts) lst+  y <- handleNotes opts empty+  return $ x <> y++-- | Convert Pandoc inline element to ms.+inlineToMs :: PandocMonad m => WriterOptions -> Inline -> MS m Doc+inlineToMs opts (Span _ ils) = inlineListToMs opts ils+inlineToMs opts (Emph lst) =+  withFontFeature 'I' (inlineListToMs opts lst)+inlineToMs opts (Strong lst) =+  withFontFeature 'B' (inlineListToMs opts lst)+inlineToMs opts (Strikeout lst) = do+  contents <- inlineListToMs opts lst+  -- we use grey color instead of strikeout, which seems quite+  -- hard to do in groff for arbitrary bits of text+  return $ text "\\m[strikecolor]" <> contents <> text "\\m[]"+inlineToMs opts (Superscript lst) = do+  contents <- inlineListToMs opts lst+  return $ text "\\*{" <> contents <> text "\\*}"+inlineToMs opts (Subscript lst) = do+  contents <- inlineListToMs opts lst+  return $ text "\\*<" <> contents <> text "\\*>"+inlineToMs opts (SmallCaps lst) = do+  -- see https://lists.gnu.org/archive/html/groff/2015-01/msg00016.html+  modify $ \st -> st{ stSmallCaps = not (stSmallCaps st) }+  res <- inlineListToMs opts lst+  modify $ \st -> st{ stSmallCaps = not (stSmallCaps st) }+  return res+inlineToMs opts (Quoted SingleQuote lst) = do+  contents <- inlineListToMs opts lst+  return $ char '`' <> contents <> char '\''+inlineToMs opts (Quoted DoubleQuote lst) = do+  contents <- inlineListToMs opts lst+  return $ text "\\[lq]" <> contents <> text "\\[rq]"+inlineToMs opts (Cite _ lst) =+  inlineListToMs opts lst+inlineToMs opts (Code attr str) = do+  hlCode <- highlightCode opts attr str+  withFontFeature 'C' (return hlCode)+inlineToMs _ (Str str) = do+  let shim = case str of+                  '.':_ -> afterBreak "\\&"+                  _     -> empty+  smallcaps <- gets stSmallCaps+  if smallcaps+     then return $ shim <> text (toSmallCaps str)+     else return $ shim <> text (escapeString str)+inlineToMs opts (Math InlineMath str) = do+  modify $ \st -> st{ stHasInlineMath = True }+  res <- convertMath writeEqn InlineMath str+  case res of+       Left il -> inlineToMs opts il+       Right r -> return $ text "@" <> text (escapeBar r) <> text "@"+inlineToMs opts (Math DisplayMath str) = do+  res <- convertMath writeEqn InlineMath str+  case res of+       Left il -> do+         contents <- inlineToMs opts il+         return $ cr <> text ".RS" $$ contents $$ text ".RE"+       Right r -> return $+            cr <> text ".EQ" $$ text (escapeBar r) $$ text ".EN"+inlineToMs _ il@(RawInline f str)+  | f == Format "ms" = return $ text str+  | otherwise        = do+    report $ InlineNotRendered il+    return empty+inlineToMs _ LineBreak = return $ cr <> text ".br" <> cr+inlineToMs opts SoftBreak =+  handleNotes opts $+    case writerWrapText opts of+         WrapAuto     -> space+         WrapNone     -> space+         WrapPreserve -> cr+inlineToMs opts Space = handleNotes opts space+inlineToMs opts (Link _ txt ('#':ident, _)) = do+  -- internal link+  contents <- inlineListToMs' opts $ map breakToSpace txt+  return $ text "\\c" <> cr <> nowrap (text ".pdfhref L -D " <>+       doubleQuotes (text ident) <> text " -A " <>+       doubleQuotes (text "\\c") <> space <> text "\\") <> cr <>+       text " -- " <> doubleQuotes (nowrap contents) <> cr <> text "\\&"+inlineToMs opts (Link _ txt (src, _)) = do+  -- external link+  contents <- inlineListToMs' opts $ map breakToSpace txt+  return $ text "\\c" <> cr <> nowrap (text ".pdfhref W -D " <>+       doubleQuotes (text (escapeUri src)) <> text " -A " <>+       doubleQuotes (text "\\c") <> space <> text "\\") <> cr <>+       text " -- " <> doubleQuotes (nowrap contents) <> cr <> text "\\&"+inlineToMs _ (Image _ alternate (_, _)) =+  return $ char '[' <> text "IMAGE: " <>+           text (escapeString (stringify alternate)) <> char ']'+inlineToMs _ (Note contents) = do+  modify $ \st -> st{ stNotes = contents : stNotes st }+  return $ text "\\**"++handleNotes :: PandocMonad m => WriterOptions -> Doc -> MS m Doc+handleNotes opts fallback = do+  notes <- gets stNotes+  if null notes+     then return fallback+     else do+       modify $ \st -> st{ stNotes = [] }+       vcat <$> mapM (handleNote opts) notes++handleNote :: PandocMonad m => WriterOptions -> Note -> MS m Doc+handleNote opts bs = do+  -- don't start with Paragraph or we'll get a spurious blank+  -- line after the note ref:+  let bs' = case bs of+                 (Para ils : rest) -> Plain ils : rest+                 _                 -> bs+  contents <- blockListToMs opts bs'+  return $ cr <> text ".FS" $$ contents $$ text ".FE" <> cr++fontChange :: PandocMonad m => MS m Doc+fontChange = do+  features <- gets stFontFeatures+  let filling = sort [c | (c,True) <- Map.toList features]+  return $ text $ "\\f[" ++ filling ++ "]"++withFontFeature :: PandocMonad m => Char -> MS m Doc -> MS m Doc+withFontFeature c action = do+  modify $ \st -> st{ stFontFeatures = Map.adjust not c $ stFontFeatures st }+  begin <- fontChange+  d <- action+  modify $ \st -> st{ stFontFeatures = Map.adjust not c $ stFontFeatures st }+  end <- fontChange+  return $ begin <> d <> end++setFirstPara :: PandocMonad m => MS m ()+setFirstPara = modify $ \st -> st{ stFirstPara = True }++resetFirstPara :: PandocMonad m => MS m ()+resetFirstPara = modify $ \st -> st{ stFirstPara = False }++breakToSpace :: Inline -> Inline+breakToSpace SoftBreak = Space+breakToSpace LineBreak = Space+breakToSpace x         = x++-- Highlighting++styleToMs :: Style -> Doc+styleToMs sty = vcat $ colordefs ++ map (toMacro sty) alltoktypes+  where alltoktypes = enumFromTo KeywordTok NormalTok+        colordefs = map toColorDef allcolors+        toColorDef c = text (".defcolor " +++            hexColor c ++ " rgb #" ++ hexColor c)+        allcolors = catMaybes $ ordNub $+          [defaultColor sty, backgroundColor sty,+           lineNumberColor sty, lineNumberBackgroundColor sty] +++           concatMap (colorsForToken. snd) (tokenStyles sty)+        colorsForToken ts = [tokenColor ts, tokenBackground ts]++hexColor :: Color -> String+hexColor (RGB r g b) = printf "%02x%02x%02x" r g b++toMacro :: Style -> TokenType -> Doc+toMacro sty toktype =+  nowrap (text ".ds " <> text (show toktype) <> text " " <>+            setbg <> setcolor <> setfont <>+            text "\\\\$1" <>+            resetfont <> resetcolor <> resetbg)+  where setcolor = maybe empty fgcol tokCol+        resetcolor = maybe empty (const $ text "\\\\m[]") tokCol+        setbg = empty -- maybe empty bgcol tokBg+        resetbg = empty -- maybe empty (const $ text "\\\\M[]") tokBg+        fgcol c = text $ "\\\\m[" ++ hexColor c ++ "]"+        -- bgcol c = text $ "\\\\M[" ++ hexColor c ++ "]"+        setfont = if tokBold || tokItalic+                     then text $ "\\\\f[C" ++ ['B' | tokBold] +++                          ['I' | tokItalic] ++ "]"+                     else empty+        resetfont = if tokBold || tokItalic+                       then text "\\\\f[C]"+                       else empty+        tokSty = lookup toktype (tokenStyles sty)+        tokCol = (tokSty >>= tokenColor) `mplus` defaultColor sty+        -- tokBg  = (tokSty >>= tokenBackground) `mplus` backgroundColor sty+        tokBold = fromMaybe False (tokenBold <$> tokSty)+        tokItalic = fromMaybe False (tokenItalic <$> tokSty)+        -- tokUnderline = fromMaybe False (tokSty >>= tokUnderline)+        -- lnColor = lineNumberColor sty+        -- lnBkgColor = lineNumberBackgroundColor sty++msFormatter :: FormatOptions -> [SourceLine] -> Doc+msFormatter _fmtopts =+  vcat . map fmtLine+  where fmtLine = hcat . map fmtToken+        fmtToken (toktype, tok) = text "\\*" <>+           brackets (text (show toktype) <> text " \""+             <> text (escapeCode (T.unpack tok)) <> text "\"")++highlightCode :: PandocMonad m => WriterOptions -> Attr -> String -> MS m Doc+highlightCode opts attr str =+  case highlight (writerSyntaxMap opts) msFormatter attr str of+         Left msg -> do+           unless (null msg) $ report $ CouldNotHighlight msg+           return $ text (escapeCode str)+         Right h -> do+           modify (\st -> st{ stHighlighting = True })+           return h
+ src/Text/Pandoc/Writers/Muse.hs view
@@ -0,0 +1,373 @@+{-# LANGUAGE OverloadedStrings #-}+{-+Copyright (C) 2017 Alexander Krotov <ilabdsf@gmail.com>++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation; either version 2 of the License, or+(at your option) any later version.++This program is distributed in the hope that it will be useful,+but WITHOUT ANY WARRANTY; without even the implied warranty of+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+GNU General Public License for more details.++You should have received a copy of the GNU General Public License+along with this program; if not, write to the Free Software+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA+-}++{- |+   Module      : Text.Pandoc.Writers.Muse+   Copyright   : Copyright (C) 2017 Alexander Krotov+   License     : GNU GPL, version 2 or above++   Maintainer  : Alexander Krotov <ilabdsf@gmail.com>+   Stability   : stable+   Portability : portable++Conversion of 'Pandoc' documents to Muse.++This module is mostly intended for <https://amusewiki.org/ Amusewiki> markup support,+as described by <https://amusewiki.org/library/manual Text::Amuse markup manual>.+Original <https://www.gnu.org/software/emacs-muse/ Emacs Muse> markup support+is a secondary goal.++Where Text::Amuse markup+<https://metacpan.org/pod/Text::Amuse#DIFFERENCES-WITH-THE-ORIGINAL-EMACS-MUSE-MARKUP differs>+from <https://www.gnu.org/software/emacs-muse/manual/ Emacs Muse markup>,+Text::Amuse markup is supported.+For example, native tables are always used instead of Org Mode tables.+However, @\<literal style="html">@ tag is used for HTML raw blocks+even though it is supported only in Emacs Muse.+-}+module Text.Pandoc.Writers.Muse (writeMuse) where+import Control.Monad.State.Strict+import Data.Text (Text)+import Data.List (intersperse, transpose, isInfixOf)+import System.FilePath (takeExtension)+import Text.Pandoc.Class (PandocMonad)+import Text.Pandoc.Definition+import Text.Pandoc.Options+import Text.Pandoc.Pretty+import Text.Pandoc.Shared+import Text.Pandoc.Templates (renderTemplate')+import Text.Pandoc.Writers.Math+import Text.Pandoc.Writers.Shared+import qualified Data.Set as Set++type Notes = [[Block]]+data WriterState =+  WriterState { stNotes       :: Notes+              , stOptions     :: WriterOptions+              , stTopLevel    :: Bool+              , stInsideBlock :: Bool+              , stIds         :: Set.Set String+              }++-- | Convert Pandoc to Muse.+writeMuse :: PandocMonad m+          => WriterOptions+          -> Pandoc+          -> m Text+writeMuse opts document =+  let st = WriterState { stNotes = []+                       , stOptions = opts+                       , stTopLevel = True+                       , stInsideBlock = False+                       , stIds = Set.empty+                       }+  in evalStateT (pandocToMuse document) st++-- | Return Muse representation of document.+pandocToMuse :: PandocMonad m+             => Pandoc+             -> StateT WriterState m Text+pandocToMuse (Pandoc meta blocks) = do+  opts <- gets stOptions+  let colwidth = if writerWrapText opts == WrapAuto+                    then Just $ writerColumns opts+                    else Nothing+  let render' :: Doc -> Text+      render' = render Nothing+  metadata <- metaToJSON opts+               (fmap render' . blockListToMuse)+               (fmap render' . inlineListToMuse)+               meta+  body <- blockListToMuse blocks+  notes <- liftM (reverse . stNotes) get >>= notesToMuse+  let main = render colwidth $ body $+$ notes+  let context = defField "body" main metadata+  case writerTemplate opts of+       Nothing  -> return main+       Just tpl -> renderTemplate' tpl context++-- | Helper function for flatBlockListToMuse+-- | Render all blocks and insert blank lines between the first two+catWithBlankLines :: PandocMonad m+                  => [Block]       -- ^ List of block elements+                  -> Int           -- ^ Number of blank lines+                  -> StateT WriterState m Doc+catWithBlankLines (b : bs) n = do+  b' <- blockToMuse b+  bs' <- flatBlockListToMuse bs+  return $ b' <> blanklines n <> bs'+catWithBlankLines _ _ = error "Expected at least one block"++-- | Convert list of Pandoc block elements to Muse+-- | without setting stTopLevel.+flatBlockListToMuse :: PandocMonad m+                => [Block]       -- ^ List of block elements+                -> StateT WriterState m Doc+flatBlockListToMuse bs@(BulletList _ : BulletList _ : _) = catWithBlankLines bs 2+flatBlockListToMuse bs@(OrderedList (_, style1, _) _ : OrderedList (_, style2, _) _ : _) =+  catWithBlankLines bs (if style1' == style2' then 2 else 0)+    where+      style1' = normalizeStyle style1+      style2' = normalizeStyle style2+      normalizeStyle DefaultStyle = Decimal+      normalizeStyle s = s+flatBlockListToMuse bs@(DefinitionList _ : DefinitionList _ : _) = catWithBlankLines bs 2+flatBlockListToMuse bs@(_ : _) = catWithBlankLines bs 0+flatBlockListToMuse [] = return mempty++-- | Convert list of Pandoc block elements to Muse.+blockListToMuse :: PandocMonad m+                => [Block]       -- ^ List of block elements+                -> StateT WriterState m Doc+blockListToMuse blocks = do+  oldState <- get+  modify $ \s -> s { stTopLevel = not $ stInsideBlock s+                   , stInsideBlock = True+                   }+  result <- flatBlockListToMuse blocks+  modify $ \s -> s { stTopLevel = stTopLevel oldState+                   , stInsideBlock = stInsideBlock oldState+                   }+  return result++-- | Convert Pandoc block element to Muse.+blockToMuse :: PandocMonad m+            => Block         -- ^ Block element+            -> StateT WriterState m Doc+blockToMuse (Plain inlines) = inlineListToMuse inlines+blockToMuse (Para inlines) = do+  contents <- inlineListToMuse inlines+  return $ contents <> blankline+blockToMuse (LineBlock lns) = do+  let splitStanza [] = []+      splitStanza xs = case break (== mempty) xs of+        (l, [])  -> [l]+        (l, _:r) -> l : splitStanza r+  let joinWithLinefeeds  = nowrap . mconcat . intersperse cr+  let joinWithBlankLines = mconcat . intersperse blankline+  let prettyfyStanza ls  = joinWithLinefeeds <$> mapM inlineListToMuse ls+  contents <- joinWithBlankLines <$> mapM prettyfyStanza (splitStanza lns)+  return $ blankline $$ "<verse>" $$ contents $$ "</verse>" <> blankline+blockToMuse (CodeBlock (_,_,_) str) =+  return $ "<example>" $$ text str $$ "</example>" $$ blankline+blockToMuse (RawBlock (Format format) str) =+  return $ blankline $$ "<literal style=\"" <> text format <> "\">" $$+           text str $$ "</literal>" $$ blankline+blockToMuse (BlockQuote blocks) = do+  contents <- flatBlockListToMuse blocks+  return $ blankline+        <> "<quote>"+        $$ nest 0 contents -- nest 0 to remove trailing blank lines+        $$ "</quote>"+        <> blankline+blockToMuse (OrderedList (start, style, _) items) = do+  let markers = take (length items) $ orderedListMarkers+                                      (start, style, Period)+  let maxMarkerLength = maximum $ map length markers+  let markers' = map (\m -> let s = maxMarkerLength - length m+                            in  m ++ replicate s ' ') markers+  contents <- zipWithM orderedListItemToMuse markers' items+  -- ensure that sublists have preceding blank line+  topLevel <- gets stTopLevel+  return $ cr $$ (if topLevel then nest 1 else id) (vcat contents) $$ blankline+  where orderedListItemToMuse :: PandocMonad m+                              => String   -- ^ marker for list item+                              -> [Block]  -- ^ list item (list of blocks)+                              -> StateT WriterState m Doc+        orderedListItemToMuse marker item = do+        contents <- blockListToMuse item+        return $ hang (length marker + 1) (text marker <> space) contents+blockToMuse (BulletList items) = do+  contents <- mapM bulletListItemToMuse items+  -- ensure that sublists have preceding blank line+  topLevel <- gets stTopLevel+  return $ cr $$ (if topLevel then nest 1 else id) (vcat contents) $$ blankline+  where bulletListItemToMuse :: PandocMonad m+                             => [Block]+                             -> StateT WriterState m Doc+        bulletListItemToMuse item = do+          contents <- blockListToMuse item+          return $ hang 2 "- " contents+blockToMuse (DefinitionList items) = do+  contents <- mapM definitionListItemToMuse items+  return $ cr $$ nest 1 (vcat contents) $$ blankline+  where definitionListItemToMuse :: PandocMonad m+                                 => ([Inline], [[Block]])+                                 -> StateT WriterState m Doc+        definitionListItemToMuse (label, defs) = do+          label' <- inlineListToMuse label+          contents <- liftM vcat $ mapM blockListToMuse defs+          let label'' = label' <> " :: "+          let ind = offset label''+          return $ hang ind label'' contents+blockToMuse (Header level (ident,_,_) inlines) = do+  opts <- gets stOptions+  contents <- inlineListToMuse inlines++  ids <- gets stIds+  let autoId = uniqueIdent inlines ids+  modify $ \st -> st{ stIds = Set.insert autoId ids }++  let attr' = if null ident || (isEnabled Ext_auto_identifiers opts && ident == autoId)+                 then empty+                 else "#" <> text ident <> cr+  let header' = text $ replicate level '*'+  return $ blankline <> nowrap (header' <> space <> contents)+                 <> blankline <> attr'+-- https://www.gnu.org/software/emacs-muse/manual/muse.html#Horizontal-Rules-and-Anchors+blockToMuse HorizontalRule = return $ blankline $$ "----" $$ blankline+blockToMuse (Table caption _ _ headers rows) =  do+  caption' <- inlineListToMuse caption+  headers' <- mapM blockListToMuse headers+  rows' <- mapM (mapM blockListToMuse) rows+  let noHeaders = all null headers++  let numChars = maximum . map offset+  -- FIXME: width is not being used.+  let widthsInChars =+       map numChars $ transpose (headers' : rows')+  -- FIXME: Muse doesn't allow blocks with height more than 1.+  let hpipeBlocks sep blocks = hcat $ intersperse sep' blocks+        where h      = maximum (1 : map height blocks)+              sep'   = lblock (length sep) $ vcat (replicate h (text sep))+  let makeRow sep = (" " <>) . hpipeBlocks sep . zipWith lblock widthsInChars+  let head' = makeRow " || " headers'+  let rowSeparator = if noHeaders then " | " else " |  "+  rows'' <- mapM (\row -> do cols <- mapM blockListToMuse row+                             return $ makeRow rowSeparator cols) rows+  let body = vcat rows''+  return $  (if noHeaders then empty else head')+         $$ body+         $$ (if null caption then empty else " |+ " <> caption' <> " +|")+         $$ blankline+blockToMuse (Div _ bs) = blockListToMuse bs+blockToMuse Null = return empty++-- | Return Muse representation of notes.+notesToMuse :: PandocMonad m+            => Notes+            -> StateT WriterState m Doc+notesToMuse notes = liftM vsep (zipWithM noteToMuse [1 ..] notes)++-- | Return Muse representation of a note.+noteToMuse :: PandocMonad m+           => Int+           -> [Block]+           -> StateT WriterState m Doc+noteToMuse num note = do+  contents <- blockListToMuse note+  let marker = "[" ++ show num ++ "] "+  return $ hang (length marker) (text marker) contents++-- | Escape special characters for Muse.+escapeString :: String -> String+escapeString s =+  "<verbatim>" +++  substitute "</verbatim>" "<</verbatim><verbatim>/verbatim>" s +++  "</verbatim>"++-- | Escape special characters for Muse if needed.+conditionalEscapeString :: String -> String+conditionalEscapeString s+  | any (`elem` ("*<=>[]|" :: String)) s ||+    "::" `isInfixOf` s = escapeString s+  | otherwise = s++-- | Convert list of Pandoc inline elements to Muse.+inlineListToMuse :: PandocMonad m+                 => [Inline]+                 -> StateT WriterState m Doc+inlineListToMuse lst = liftM hcat (mapM inlineToMuse lst)++-- | Convert Pandoc inline element to Muse.+inlineToMuse :: PandocMonad m+             => Inline+             -> StateT WriterState m Doc+inlineToMuse (Str str) = return $ text $ conditionalEscapeString str+inlineToMuse (Emph lst) = do+  contents <- inlineListToMuse lst+  return $ "<em>" <> contents <> "</em>"+inlineToMuse (Strong lst) = do+  contents <- inlineListToMuse lst+  return $ "<strong>" <> contents <> "</strong>"+inlineToMuse (Strikeout lst) = do+  contents <- inlineListToMuse lst+  return $ "<del>" <> contents <> "</del>"+inlineToMuse (Superscript lst) = do+  contents <- inlineListToMuse lst+  return $ "<sup>" <> contents <> "</sup>"+inlineToMuse (Subscript lst) = do+  contents <- inlineListToMuse lst+  return $ "<sub>" <> contents <> "</sub>"+inlineToMuse (SmallCaps lst) = inlineListToMuse lst+inlineToMuse (Quoted SingleQuote lst) = do+  contents <- inlineListToMuse lst+  return $ "'" <> contents <> "'"+inlineToMuse (Quoted DoubleQuote lst) = do+  contents <- inlineListToMuse lst+  return $ "\"" <> contents <> "\""+-- Amusewiki does not support <cite> tag,+-- and Emacs Muse citation support is limited+-- (https://www.gnu.org/software/emacs-muse/manual/html_node/Citations.html#Citation)+-- so just fallback to expanding inlines.+inlineToMuse (Cite _  lst) = inlineListToMuse lst+inlineToMuse (Code _ str) = return $+  "<code>" <> text (conditionalEscapeString str) <> "</code>"+inlineToMuse (Math InlineMath str) =+  lift (texMathToInlines InlineMath str) >>= inlineListToMuse+inlineToMuse (Math DisplayMath str) = do+  contents <- lift (texMathToInlines DisplayMath str) >>= inlineListToMuse+  return $ "<verse>" <> contents <> "</verse>" <> blankline+inlineToMuse (RawInline (Format f) str) =+  return $ "<literal style=\"" <> text f <> "\">" <> text str <> "</literal>"+inlineToMuse LineBreak = return $ "<br>" <> cr+inlineToMuse Space = return space+inlineToMuse SoftBreak = do+  wrapText <- gets $ writerWrapText . stOptions+  return $ if wrapText == WrapPreserve then cr else space+inlineToMuse (Link _ txt (src, _)) =+  case txt of+        [Str x] | escapeURI x == src ->+             return $ "[[" <> text (escapeLink x) <> "]]"+        _ -> do contents <- inlineListToMuse txt+                return $ "[[" <> text (escapeLink src) <> "][" <> contents <> "]]"+  where escapeLink lnk = escapeURI (if isImageUrl lnk then "URL:" ++ lnk else lnk)+        -- Taken from muse-image-regexp defined in Emacs Muse file lisp/muse-regexps.el+        imageExtensions = [".eps", ".gif", ".jpg", ".jpeg", ".pbm", ".png", ".tiff", ".xbm", ".xpm"]+        isImageUrl = (`elem` imageExtensions) . takeExtension+inlineToMuse (Image attr alt (source,'f':'i':'g':':':title)) =+  inlineToMuse (Image attr alt (source,title))+inlineToMuse (Image _ inlines (source, title)) = do+  alt <- inlineListToMuse inlines+  let title' = if null title+                  then if null inlines+                          then ""+                          else "[" <> alt <> "]"+                  else "[" <> text title <> "]"+  return $ "[[" <> text source <> "]" <> title' <> "]"+inlineToMuse (Note contents) = do+  -- add to notes in state+  notes <- gets stNotes+  modify $ \st -> st { stNotes = contents:notes }+  let ref = show $ length notes + 1+  return $ "[" <> text ref <> "]"+inlineToMuse (Span (_,name:_,_) inlines) = do+  contents <- inlineListToMuse inlines+  return $ "<class name=\"" <> text name <> "\">" <> contents <> "</class>"+inlineToMuse (Span _ lst) = inlineListToMuse lst
src/Text/Pandoc/Writers/Native.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE OverloadedStrings #-} {--Copyright (C) 2006-2015 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2006-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -19,7 +19,7 @@  {- |    Module      : Text.Pandoc.Writers.Native-   Copyright   : Copyright (C) 2006-2015 John MacFarlane+   Copyright   : Copyright (C) 2006-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -30,14 +30,17 @@ -} module Text.Pandoc.Writers.Native ( writeNative ) where-import Text.Pandoc.Options ( WriterOptions(..), WrapOption(..) )-import Data.List ( intersperse )+import Data.List (intersperse)+import Data.Text (Text)+import Text.Pandoc.Class (PandocMonad) import Text.Pandoc.Definition+import Text.Pandoc.Options (WrapOption (..), WriterOptions (..)) import Text.Pandoc.Pretty  prettyList :: [Doc] -> Doc prettyList ds =-  "[" <> (cat $ intersperse (cr <> ",") $ map (nest 1) ds) <> "]"+  "[" <>+  cat (intersperse (cr <> ",") $ map (nest 1) ds) <> "]"  -- | Prettyprint Pandoc block element. prettyBlock :: Block -> Doc@@ -47,12 +50,12 @@   "BlockQuote" $$ prettyList (map prettyBlock blocks) prettyBlock (OrderedList attribs blockLists) =   "OrderedList" <> space <> text (show attribs) $$-  (prettyList $ map (prettyList . map prettyBlock) blockLists)+  prettyList (map (prettyList . map prettyBlock) blockLists) prettyBlock (BulletList blockLists) =   "BulletList" $$-  (prettyList $ map (prettyList . map prettyBlock) blockLists)+  prettyList (map (prettyList . map prettyBlock) blockLists) prettyBlock (DefinitionList items) = "DefinitionList" $$-  (prettyList $ map deflistitem items)+  prettyList (map deflistitem items)     where deflistitem (term, defs) = "(" <> text (show term) <> "," <> cr <>            nest 1 (prettyList $ map (prettyList . map prettyBlock) defs) <> ")" prettyBlock (Table caption aligns widths header rows) =@@ -66,8 +69,8 @@ prettyBlock block = text $ show block  -- | Prettyprint Pandoc document.-writeNative :: WriterOptions -> Pandoc -> String-writeNative opts (Pandoc meta blocks) =+writeNative :: PandocMonad m => WriterOptions -> Pandoc -> m Text+writeNative opts (Pandoc meta blocks) = return $   let colwidth = if writerWrapText opts == WrapAuto                     then Just $ writerColumns opts                     else Nothing
src/Text/Pandoc/Writers/ODT.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE ScopedTypeVariables #-} {--Copyright (C) 2008-2015 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2008-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -19,7 +19,7 @@  {- |    Module      : Text.Pandoc.Writers.ODT-   Copyright   : Copyright (C) 2008-2015 John MacFarlane+   Copyright   : Copyright (C) 2008-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -29,49 +29,70 @@ Conversion of 'Pandoc' documents to ODT. -} module Text.Pandoc.Writers.ODT ( writeODT ) where-import Data.IORef-import Data.List ( isPrefixOf )-import Data.Maybe ( fromMaybe )-import Text.XML.Light.Output-import Text.TeXMath-import qualified Data.ByteString.Lazy as B-import Text.Pandoc.UTF8 ( fromStringLazy ) import Codec.Archive.Zip-import Text.Pandoc.Options ( WriterOptions(..), WrapOption(..) )-import Text.Pandoc.Shared ( stringify, fetchItem', warn,-                            getDefaultReferenceODT )-import Text.Pandoc.ImageSize-import Text.Pandoc.MIME ( getMimeType, extensionFromMimeType )+import Control.Monad.Except (catchError)+import Control.Monad.State.Strict+import qualified Data.ByteString.Lazy as B+import Data.Generics (everywhere', mkT)+import Data.List (isPrefixOf)+import Data.Maybe (fromMaybe)+import qualified Data.Text.Lazy as TL+import System.FilePath (takeDirectory, takeExtension, (<.>))+import Text.Pandoc.BCP47 (Lang (..), getLang, renderLang)+import Text.Pandoc.Class (PandocMonad, report, toLang)+import qualified Text.Pandoc.Class as P import Text.Pandoc.Definition+import Text.Pandoc.ImageSize+import Text.Pandoc.Logging+import Text.Pandoc.MIME (extensionFromMimeType, getMimeType)+import Text.Pandoc.Options (WrapOption (..), WriterOptions (..))+import Text.Pandoc.Pretty+import Text.Pandoc.Shared (stringify)+import Text.Pandoc.UTF8 (fromStringLazy, fromTextLazy, toStringLazy) import Text.Pandoc.Walk-import Text.Pandoc.Writers.Shared ( fixDisplayMath )-import Text.Pandoc.Writers.OpenDocument ( writeOpenDocument )-import Control.Monad (liftM)+import Text.Pandoc.Writers.OpenDocument (writeOpenDocument)+import Text.Pandoc.Writers.Shared (fixDisplayMath) import Text.Pandoc.XML-import Text.Pandoc.Pretty-import qualified Control.Exception as E-import Data.Time.Clock.POSIX ( getPOSIXTime )-import System.FilePath ( takeExtension, takeDirectory, (<.>))+import Text.TeXMath+import Text.XML.Light +data ODTState = ODTState { stEntries :: [Entry]+                         }++type O m = StateT ODTState m+ -- | Produce an ODT file from a Pandoc document.-writeODT :: WriterOptions  -- ^ Writer options+writeODT :: PandocMonad m+         => WriterOptions  -- ^ Writer options          -> Pandoc         -- ^ Document to convert-         -> IO B.ByteString-writeODT opts doc@(Pandoc meta _) = do-  let datadir = writerUserDataDir opts+         -> m B.ByteString+writeODT  opts doc =+  let initState = ODTState{ stEntries = []+                          }+  in+    evalStateT (pandocToODT opts doc) initState++-- | Produce an ODT file from a Pandoc document.+pandocToODT :: PandocMonad m+            => WriterOptions  -- ^ Writer options+            -> Pandoc         -- ^ Document to convert+            -> O m B.ByteString+pandocToODT opts doc@(Pandoc meta _) = do   let title = docTitle meta+  lang <- toLang (getLang opts meta)   refArchive <--       case writerReferenceODT opts of-             Just f -> liftM toArchive $ B.readFile f-             Nothing -> getDefaultReferenceODT datadir+       case writerReferenceDoc opts of+             Just f -> liftM toArchive $ lift $ P.readFileLazy f+             Nothing -> lift $ (toArchive . B.fromStrict) <$>+                                P.readDataFile "reference.odt"   -- handle formulas and pictures-  picEntriesRef <- newIORef ([] :: [Entry])-  doc' <- walkM (transformPicMath opts picEntriesRef) $ walk fixDisplayMath doc-  let newContents = writeOpenDocument opts{writerWrapText = WrapNone} doc'-  epochtime <- floor `fmap` getPOSIXTime+  -- picEntriesRef <- P.newIORef ([] :: [Entry])+  doc' <- walkM (transformPicMath opts) $ walk fixDisplayMath doc+  newContents <- lift $ writeOpenDocument opts{writerWrapText = WrapNone} doc'+  epochtime <- floor `fmap` lift P.getPOSIXTime   let contentEntry = toEntry "content.xml" epochtime-                     $ fromStringLazy newContents-  picEntries <- readIORef picEntriesRef+                     $ fromTextLazy $ TL.fromStrict newContents+  picEntries <- gets stEntries   let archive = foldr addEntryToArchive refArchive                 $ contentEntry : picEntries   -- construct META-INF/manifest.xml based on archive@@ -90,10 +111,9 @@         $ fromStringLazy $ render Nothing         $ text "<?xml version=\"1.0\" encoding=\"utf-8\"?>"         $$-         ( inTags True "manifest:manifest"+         (inTags True "manifest:manifest"             [("xmlns:manifest","urn:oasis:names:tc:opendocument:xmlns:manifest:1.0")-            ,("manifest:version","1.2")]-            $ ( selfClosingTag "manifest:file-entry"+            ,("manifest:version","1.2")] ( selfClosingTag "manifest:file-entry"                  [("manifest:media-type","application/vnd.oasis.opendocument.text")                  ,("manifest:full-path","/")]                 $$ vcat ( map toFileEntry $ files )@@ -105,78 +125,106 @@        $ fromStringLazy $ render Nothing        $ text "<?xml version=\"1.0\" encoding=\"utf-8\"?>"        $$-        ( inTags True "office:document-meta"+        (inTags True "office:document-meta"            [("xmlns:office","urn:oasis:names:tc:opendocument:xmlns:office:1.0")            ,("xmlns:xlink","http://www.w3.org/1999/xlink")            ,("xmlns:dc","http://purl.org/dc/elements/1.1/")            ,("xmlns:meta","urn:oasis:names:tc:opendocument:xmlns:meta:1.0")            ,("xmlns:ooo","http://openoffice.org/2004/office")            ,("xmlns:grddl","http://www.w3.org/2003/g/data-view#")-           ,("office:version","1.2")]-           $ ( inTagsSimple "office:meta"-                $ ( inTagsSimple "dc:title" (text $ escapeStringForXML (stringify title))-                  )+           ,("office:version","1.2")] ( inTagsSimple "office:meta" $+                 ( inTagsSimple "dc:title"+                      (text $ escapeStringForXML (stringify title))+                   $$+                   case lang of+                        Just l -> inTagsSimple "dc:language"+                                    (text (escapeStringForXML (renderLang l)))+                        Nothing -> empty+                 )              )         )   -- make sure mimetype is first   let mimetypeEntry = toEntry "mimetype" epochtime                       $ fromStringLazy "application/vnd.oasis.opendocument.text"-  let archive'' = addEntryToArchive mimetypeEntry+  archive'' <- updateStyleWithLang lang+                  $ addEntryToArchive mimetypeEntry                   $ addEntryToArchive metaEntry archive'   return $ fromArchive archive'' +updateStyleWithLang :: PandocMonad m => Maybe Lang -> Archive -> O m Archive+updateStyleWithLang Nothing arch = return arch+updateStyleWithLang (Just lang) arch = do+  epochtime <- floor `fmap` lift P.getPOSIXTime+  return arch{ zEntries = [if eRelativePath e == "styles.xml"+                              then case parseXMLDoc+                                      (toStringLazy (fromEntry e)) of+                                      Nothing -> e+                                      Just d ->+                                        toEntry "styles.xml" epochtime+                                        ( fromStringLazy+                                        . ppTopElement+                                        . addLang lang $ d )+                              else e+                            | e <- zEntries arch] }++addLang :: Lang -> Element -> Element+addLang lang = everywhere' (mkT updateLangAttr)+    where updateLangAttr (Attr n@(QName "language" _ (Just "fo")) _)+                           = Attr n (langLanguage lang)+          updateLangAttr (Attr n@(QName "country" _ (Just "fo")) _)+                           = Attr n (langRegion lang)+          updateLangAttr x = x+ -- | transform both Image and Math elements-transformPicMath :: WriterOptions -> IORef [Entry] -> Inline -> IO Inline-transformPicMath opts entriesRef (Image attr@(id', cls, _) lab (src,t)) = do-  res <- fetchItem' (writerMediaBag opts) (writerSourceURL opts) src-  case res of-     Left (_ :: E.SomeException) -> do-       warn $ "Could not find image `" ++ src ++ "', skipping..."-       return $ Emph lab-     Right (img, mbMimeType) -> do-       (ptX, ptY) <- case imageSize img of+transformPicMath :: PandocMonad m => WriterOptions ->Inline -> O m Inline+transformPicMath opts (Image attr@(id', cls, _) lab (src,t)) = catchError+   (do (img, mbMimeType) <- P.fetchItem src+       (ptX, ptY) <- case imageSize opts img of                        Right s  -> return $ sizeInPoints s                        Left msg -> do-                         warn $ "Could not determine image size in `" ++-                           src ++ "': " ++ msg+                         report $ CouldNotDetermineImageSize src msg                          return (100, 100)        let dims =              case (getDim Width, getDim Height) of                (Just w, Just h)              -> [("width", show w), ("height", show h)]-               (Just w@(Percent _), Nothing) -> [("width", show w), ("style:rel-height", "scale")]-               (Nothing, Just h@(Percent _)) -> [("style:rel-width", "scale"), ("height", show h)]+               (Just w@(Percent p), Nothing) -> [("width", show w), ("height", show (p / ratio) ++ "%")]+               (Nothing, Just h@(Percent p)) -> [("width", show (p * ratio) ++ "%"), ("height", show h)]                (Just w@(Inch i), Nothing)    -> [("width", show w), ("height", show (i / ratio) ++ "in")]                (Nothing, Just h@(Inch i))    -> [("width", show (i * ratio) ++ "in"), ("height", show h)]                _                             -> [("width", show ptX ++ "pt"), ("height", show ptY ++ "pt")]              where                ratio = ptX / ptY-               getDim dir = case (dimension dir attr) of+               getDim dir = case dimension dir attr of                               Just (Percent i) -> Just $ Percent i                               Just dim         -> Just $ Inch $ inInch opts dim                               Nothing          -> Nothing        let  newattr = (id', cls, dims)-       entries <- readIORef entriesRef+       entries <- gets stEntries        let extension = fromMaybe (takeExtension $ takeWhile (/='?') src)                            (mbMimeType >>= extensionFromMimeType)        let newsrc = "Pictures/" ++ show (length entries) <.> extension        let toLazy = B.fromChunks . (:[])-       epochtime <- floor `fmap` getPOSIXTime+       epochtime <- floor `fmap` lift P.getPOSIXTime        let entry = toEntry newsrc epochtime $ toLazy img-       modifyIORef entriesRef (entry:)-       return $ Image newattr lab (newsrc, t)-transformPicMath _ entriesRef (Math t math) = do-  entries <- readIORef entriesRef+       modify $ \st -> st{ stEntries = entry : entries }+       return $ Image newattr lab (newsrc, t))+   (\e -> do+       report $ CouldNotFetchResource src (show e)+       return $ Emph lab)++transformPicMath _ (Math t math) = do+  entries <- gets stEntries   let dt = if t == InlineMath then DisplayInline else DisplayBlock   case writeMathML dt <$> readTeX math of        Left  _ -> return $ Math t math        Right r -> do          let conf = useShortEmptyTags (const False) defaultConfigPP          let mathml = ppcTopElement conf r-         epochtime <- floor `fmap` getPOSIXTime+         epochtime <- floor `fmap` (lift P.getPOSIXTime)          let dirname = "Formula-" ++ show (length entries) ++ "/"          let fname = dirname ++ "content.xml"          let entry = toEntry fname epochtime (fromStringLazy mathml)-         modifyIORef entriesRef (entry:)+         modify $ \st -> st{ stEntries = entry : entries }          return $ RawInline (Format "opendocument") $ render Nothing $            inTags False "draw:frame" [("text:anchor-type",                                        if t == DisplayMath@@ -189,4 +237,4 @@                                         , ("xlink:show", "embed")                                         , ("xlink:actuate", "onLoad")] -transformPicMath _ _ x = return x+transformPicMath _ x = return x
src/Text/Pandoc/Writers/OPML.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE CPP #-} {--Copyright (C) 2013-2015 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2013-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -19,7 +19,7 @@  {- |    Module      : Text.Pandoc.Writers.OPML-   Copyright   : Copyright (C) 2013-2015 John MacFarlane+   Copyright   : Copyright (C) 2013-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -29,41 +29,46 @@ Conversion of 'Pandoc' documents to OPML XML. -} module Text.Pandoc.Writers.OPML ( writeOPML) where+import Control.Monad.Except (throwError)+import Data.Text (Text, unpack)+import qualified Data.Text as T+import qualified Text.Pandoc.Builder as B+import Text.Pandoc.Class (PandocMonad)+import Text.Pandoc.Compat.Time import Text.Pandoc.Definition-import Text.Pandoc.XML-import Text.Pandoc.Writers.Shared-import Text.Pandoc.Shared+import Text.Pandoc.Error import Text.Pandoc.Options+import Text.Pandoc.Pretty+import Text.Pandoc.Shared import Text.Pandoc.Templates (renderTemplate')-import Text.Pandoc.Writers.HTML (writeHtmlString)+import Text.Pandoc.Writers.HTML (writeHtml5String) import Text.Pandoc.Writers.Markdown (writeMarkdown)-import Text.Pandoc.Pretty-import Text.Pandoc.Compat.Time-import qualified Text.Pandoc.Builder as B+import Text.Pandoc.Writers.Shared+import Text.Pandoc.XML  -- | Convert Pandoc document to string in OPML format.-writeOPML :: WriterOptions -> Pandoc -> String-writeOPML opts (Pandoc meta blocks) =+writeOPML :: PandocMonad m => WriterOptions -> Pandoc -> m Text+writeOPML opts (Pandoc meta blocks) = do   let elements = hierarchicalize blocks       colwidth = if writerWrapText opts == WrapAuto                     then Just $ writerColumns opts                     else Nothing       meta' = B.setMeta "date" (B.str $ convertDate $ docDate meta) meta-      Just metadata = metaToJSON opts-                      (Just . writeMarkdown def . Pandoc nullMeta)-                      (Just . trimr . writeMarkdown def . Pandoc nullMeta .-                         (\ils -> [Plain ils]))-                      meta'-      main     = render colwidth $ vcat (map (elementToOPML opts) elements)-      context = defField "body" main metadata-  in  case writerTemplate opts of-           Nothing  -> main-           Just tpl -> renderTemplate' tpl context+  metadata <- metaToJSON opts+              (writeMarkdown def . Pandoc nullMeta)+              (\ils -> T.stripEnd <$> writeMarkdown def (Pandoc nullMeta [Plain ils]))+              meta'+  main <- (render colwidth . vcat) <$> mapM (elementToOPML opts) elements+  let context = defField "body" main metadata+  case writerTemplate opts of+       Nothing  -> return main+       Just tpl -> renderTemplate' tpl context -writeHtmlInlines :: [Inline] -> String-writeHtmlInlines ils = trim $ writeHtmlString def-                            $ Pandoc nullMeta [Plain ils] +writeHtmlInlines :: PandocMonad m => [Inline] -> m Text+writeHtmlInlines ils =+  T.strip <$> writeHtml5String def (Pandoc nullMeta [Plain ils])+ -- date format: RFC 822: Thu, 14 Jul 2005 23:41:05 GMT showDateTimeRFC822 :: UTCTime -> String showDateTimeRFC822 = formatTime defaultTimeLocale "%a, %d %b %Y %X %Z"@@ -75,20 +80,27 @@ #else   parseTime #endif-  defaultTimeLocale "%F" =<< (normalizeDate $ stringify ils)+  defaultTimeLocale "%F" =<< normalizeDate (stringify ils)  -- | Convert an Element to OPML.-elementToOPML :: WriterOptions -> Element -> Doc-elementToOPML _ (Blk _) = empty-elementToOPML opts (Sec _ _num _ title elements) =-  let isBlk (Blk _) = True-      isBlk _     = False-      fromBlk (Blk x) = x-      fromBlk _ = error "fromBlk called on non-block"+elementToOPML :: PandocMonad m => WriterOptions -> Element -> m Doc+elementToOPML _ (Blk _) = return empty+elementToOPML opts (Sec _ _num _ title elements) = do+  let isBlk :: Element -> Bool+      isBlk (Blk _) = True+      isBlk _       = False++      fromBlk :: PandocMonad m => Element -> m Block+      fromBlk (Blk x) = return x+      fromBlk _ = throwError $ PandocSomeError "fromBlk called on non-block"+       (blocks, rest) = span isBlk elements-      attrs = [("text", writeHtmlInlines title)] ++-              [("_note", writeMarkdown def (Pandoc nullMeta-                              (map fromBlk blocks)))-                | not (null blocks)]-  in  inTags True "outline" attrs $-      vcat (map (elementToOPML opts) rest)+  htmlIls <- writeHtmlInlines title+  md <- if null blocks+        then return mempty+        else do blks <- mapM fromBlk blocks+                writeMarkdown def $ Pandoc nullMeta blks+  let attrs = ("text", unpack htmlIls) :+              [("_note", unpack md) | not (null blocks)]+  o <- mapM (elementToOPML opts) rest+  return $ inTags True "outline" attrs $ vcat o
src/Text/Pandoc/Writers/OpenDocument.hs view
@@ -1,6 +1,8 @@-{-# LANGUAGE PatternGuards, OverloadedStrings, FlexibleContexts #-}+{-# LANGUAGE FlexibleContexts  #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternGuards     #-} {--Copyright (C) 2008-2015 Andrea Rossato <andrea.rossato@ing.unitn.it>+Copyright (C) 2008-2017 Andrea Rossato <andrea.rossato@ing.unitn.it>                         and John MacFarlane.  This program is free software; you can redistribute it and/or modify@@ -20,7 +22,7 @@  {- |    Module      : Text.Pandoc.Writers.OpenDocument-   Copyright   : Copyright (C) 2008-2015 Andrea Rossato and John MacFarlane+   Copyright   : Copyright (C) 2008-2017 Andrea Rossato and John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : Andrea Rossato <andrea.rossato@ing.unitn.it>@@ -30,32 +32,38 @@ Conversion of 'Pandoc' documents to OpenDocument XML. -} module Text.Pandoc.Writers.OpenDocument ( writeOpenDocument ) where+import Control.Arrow ((***), (>>>))+import Control.Monad.State.Strict hiding (when)+import Data.Char (chr)+import Data.List (sortBy)+import qualified Data.Map as Map+import Data.Ord (comparing)+import qualified Data.Set as Set+import Data.Text (Text)+import Text.Pandoc.BCP47 (Lang (..), parseBCP47)+import Text.Pandoc.Class (PandocMonad, report) import Text.Pandoc.Definition+import Text.Pandoc.Logging import Text.Pandoc.Options-import Text.Pandoc.XML+import Text.Pandoc.Pretty import Text.Pandoc.Shared (linesToPara) import Text.Pandoc.Templates (renderTemplate')-import Text.Pandoc.Readers.TeXMath-import Text.Pandoc.Pretty-import Text.Printf ( printf )-import Control.Arrow ( (***), (>>>) )-import Control.Monad.State hiding ( when )-import Data.Char (chr)-import qualified Data.Set as Set-import qualified Data.Map as Map+import Text.Pandoc.Writers.Math import Text.Pandoc.Writers.Shared-import Data.List (sortBy)-import Data.Ord (comparing)+import Text.Pandoc.XML+import Text.Printf (printf)  -- | Auxiliary function to convert Plain block to Para. plainToPara :: Block -> Block plainToPara (Plain x) = Para x-plainToPara x = x+plainToPara x         = x  -- -- OpenDocument writer -- +type OD m = StateT WriterState m+ data WriterState =     WriterState { stNotes         :: [Doc]                 , stTableStyles   :: [Doc]@@ -88,46 +96,46 @@ when :: Bool -> Doc -> Doc when p a = if p then a else empty -addTableStyle :: Doc -> State WriterState ()+addTableStyle :: PandocMonad m => Doc -> OD m () addTableStyle i = modify $ \s -> s { stTableStyles = i : stTableStyles s } -addNote :: Doc -> State WriterState ()+addNote :: PandocMonad m => Doc -> OD m () addNote i = modify $ \s -> s { stNotes = i : stNotes s } -addParaStyle :: Doc -> State WriterState ()+addParaStyle :: PandocMonad m => Doc -> OD m () addParaStyle i = modify $ \s -> s { stParaStyles = i : stParaStyles s } -addTextStyle :: Set.Set TextStyle -> (String, Doc) -> State WriterState ()+addTextStyle :: PandocMonad m => Set.Set TextStyle -> (String, Doc) -> OD m () addTextStyle attrs i = modify $ \s ->   s { stTextStyles = Map.insert attrs i (stTextStyles s) } -addTextStyleAttr :: TextStyle -> State WriterState ()+addTextStyleAttr :: PandocMonad m => TextStyle -> OD m () addTextStyleAttr t = modify $ \s ->   s { stTextStyleAttr = Set.insert t (stTextStyleAttr s) } -increaseIndent :: State WriterState ()+increaseIndent :: PandocMonad m => OD m () increaseIndent = modify $ \s -> s { stIndentPara = 1 + stIndentPara s } -resetIndent :: State WriterState ()-resetIndent = modify $ \s -> s { stIndentPara = (stIndentPara s) - 1 }+resetIndent :: PandocMonad m => OD m ()+resetIndent = modify $ \s -> s { stIndentPara = stIndentPara s - 1 } -inTightList :: State WriterState a -> State WriterState a+inTightList :: PandocMonad m => OD m a -> OD m a inTightList  f = modify (\s -> s { stTight = True  }) >> f >>= \r ->                  modify (\s -> s { stTight = False }) >> return r -setInDefinitionList :: Bool -> State WriterState ()+setInDefinitionList :: PandocMonad m => Bool -> OD m () setInDefinitionList b = modify $  \s -> s { stInDefinition = b } -setFirstPara :: State WriterState ()+setFirstPara :: PandocMonad m => OD m () setFirstPara =  modify $  \s -> s { stFirstPara = True } -inParagraphTags :: Doc -> State WriterState Doc+inParagraphTags :: PandocMonad m => Doc -> OD m Doc inParagraphTags d | isEmpty d = return empty inParagraphTags d = do   b <- gets stFirstPara   a <- if b        then do modify $ \st -> st { stFirstPara = False }-               return $ [("text:style-name", "First_20_paragraph")]+               return [("text:style-name", "First_20_paragraph")]        else    return   [("text:style-name", "Text_20_body")]   return $ inTags False "text:p" a d @@ -137,7 +145,7 @@ inSpanTags :: String -> Doc -> Doc inSpanTags s = inTags False "text:span" [("text:style-name",s)] -withTextStyle :: TextStyle -> State WriterState a -> State WriterState a+withTextStyle :: PandocMonad m => TextStyle -> OD m a -> OD m a withTextStyle s f = do   oldTextStyleAttr <- gets stTextStyleAttr   addTextStyleAttr s@@ -145,7 +153,7 @@   modify $ \st -> st{ stTextStyleAttr = oldTextStyleAttr }   return res -inTextStyle :: Doc -> State WriterState Doc+inTextStyle :: PandocMonad m => Doc -> OD m Doc inTextStyle d = do   at <- gets stTextStyleAttr   if Set.null at@@ -161,12 +169,12 @@                      inTags False "style:style"                        [("style:name", styleName)                        ,("style:family", "text")]-                    $ selfClosingTag "style:text-properties"-                       (concatMap textStyleAttr (Set.toList at)))+                       $ selfClosingTag "style:text-properties"+                          (concatMap textStyleAttr (Set.toList at)))               return $ inTags False                   "text:span" [("text:style-name",styleName)] d -inHeaderTags :: Int -> Doc -> State WriterState Doc+inHeaderTags :: PandocMonad m => Int -> Doc -> OD m Doc inHeaderTags i d =   return $ inTags False "text:h" [ ("text:style-name", "Heading_20_" ++ show i)                                  , ("text:outline-level", show i)] d@@ -189,64 +197,67 @@         rm        [] = empty  -- | Convert Pandoc document to string in OpenDocument format.-writeOpenDocument :: WriterOptions -> Pandoc -> String-writeOpenDocument opts (Pandoc meta blocks) =+writeOpenDocument :: PandocMonad m => WriterOptions -> Pandoc -> m Text+writeOpenDocument opts (Pandoc meta blocks) = do   let colwidth = if writerWrapText opts == WrapAuto                     then Just $ writerColumns opts                     else Nothing+  let render' :: Doc -> Text       render' = render colwidth-      ((body, metadata),s) = flip runState+  ((body, metadata),s) <- flip runStateT         defaultWriterState $ do            m <- metaToJSON opts-                  (fmap (render colwidth) . blocksToOpenDocument opts)-                  (fmap (render colwidth) . inlinesToOpenDocument opts)+                  (fmap render' . blocksToOpenDocument opts)+                  (fmap render' . inlinesToOpenDocument opts)                   meta            b <- render' `fmap` blocksToOpenDocument opts blocks            return (b, m)-      styles   = stTableStyles s ++ stParaStyles s ++-                     map snd (reverse $ sortBy (comparing fst) $-                        Map.elems (stTextStyles s))+  let styles   = stTableStyles s ++ stParaStyles s +++                     map snd (sortBy (flip (comparing fst)) (+                        Map.elems (stTextStyles s)))       listStyle (n,l) = inTags True "text:list-style"                           [("style:name", "L" ++ show n)] (vcat l)-      listStyles  = map listStyle (stListStyles s)-      automaticStyles = vcat $ reverse $ styles ++ listStyles-      context = defField "body" body-              $ defField "automatic-styles" (render' automaticStyles)-              $ metadata-  in  case writerTemplate opts of-           Nothing  -> body-           Just tpl -> renderTemplate' tpl context+  let listStyles  = map listStyle (stListStyles s)+  let automaticStyles = vcat $ reverse $ styles ++ listStyles+  let context = defField "body" body+              $ defField "toc" (writerTableOfContents opts)+              $defField "automatic-styles" (render' automaticStyles) metadata+  case writerTemplate opts of+       Nothing  -> return body+       Just tpl -> renderTemplate' tpl context -withParagraphStyle :: WriterOptions -> String -> [Block] -> State WriterState Doc+withParagraphStyle :: PandocMonad m+                   => WriterOptions -> String -> [Block] -> OD m Doc withParagraphStyle  o s (b:bs)     | Para l <- b = go =<< inParagraphTagsWithStyle s <$> inlinesToOpenDocument o l     | otherwise   = go =<< blockToOpenDocument o b     where go i = (<>) i <$>  withParagraphStyle o s bs withParagraphStyle _ _ [] = return empty -inPreformattedTags :: String -> State WriterState Doc+inPreformattedTags :: PandocMonad m => String -> OD m Doc inPreformattedTags s = do   n <- paraStyle [("style:parent-style-name","Preformatted_20_Text")]   return . inParagraphTagsWithStyle ("P" ++ show n) . handleSpaces $ s -orderedListToOpenDocument :: WriterOptions -> Int -> [[Block]] -> State WriterState Doc+orderedListToOpenDocument :: PandocMonad m+                          => WriterOptions -> Int -> [[Block]] -> OD m Doc orderedListToOpenDocument o pn bs =     vcat . map (inTagsIndented "text:list-item") <$>     mapM (orderedItemToOpenDocument o pn . map plainToPara) bs -orderedItemToOpenDocument :: WriterOptions -> Int -> [Block] -> State WriterState Doc-orderedItemToOpenDocument  o n (b:bs)-    | OrderedList a l <- b = newLevel a l-    | Para          l <- b = go =<< inParagraphTagsWithStyle ("P" ++ show n) <$> inlinesToOpenDocument o l-    | otherwise            = go =<< blockToOpenDocument o b-    where-      go i = ($$) i <$> orderedItemToOpenDocument o n bs-      newLevel a l = do-        nn <- length <$> gets stParaStyles-        ls <- head   <$> gets stListStyles-        modify $ \s -> s { stListStyles = orderedListLevelStyle a ls : tail (stListStyles s) }-        inTagsIndented "text:list" <$> orderedListToOpenDocument o nn l-orderedItemToOpenDocument  _ _ [] = return empty+orderedItemToOpenDocument :: PandocMonad m+                          => WriterOptions -> Int -> [Block] -> OD m Doc+orderedItemToOpenDocument  o n bs = vcat <$> mapM go bs+ where go (OrderedList a l) = newLevel a l+       go (Para          l) = inParagraphTagsWithStyle ("P" ++ show n) <$>+                                inlinesToOpenDocument o l+       go b                 = blockToOpenDocument o b+       newLevel a l = do+         nn <- length <$> gets stParaStyles+         ls <- head   <$> gets stListStyles+         modify $ \s -> s { stListStyles = orderedListLevelStyle a ls :+                                 drop 1 (stListStyles s) }+         inTagsIndented "text:list" <$> orderedListToOpenDocument o nn l  isTightList :: [[Block]] -> Bool isTightList []          = False@@ -254,7 +265,8 @@     | Plain {} : _ <- b = True     | otherwise         = False -newOrderedListStyle :: Bool -> ListAttributes -> State WriterState (Int,Int)+newOrderedListStyle :: PandocMonad m+                    => Bool -> ListAttributes -> OD m (Int,Int) newOrderedListStyle b a = do   ln <- (+) 1 . length  <$> gets stListStyles   let nbs = orderedListLevelStyle a (ln, [])@@ -262,7 +274,8 @@   modify $ \s -> s { stListStyles = nbs : stListStyles s }   return (ln,pn) -bulletListToOpenDocument :: WriterOptions -> [[Block]] -> State WriterState Doc+bulletListToOpenDocument :: PandocMonad m+                         => WriterOptions -> [[Block]] -> OD m Doc bulletListToOpenDocument o b = do   ln <- (+) 1 . length <$> gets stListStyles   (pn,ns) <- if isTightList b then inTightList (bulletListStyle ln) else bulletListStyle ln@@ -270,37 +283,40 @@   is <- listItemsToOpenDocument ("P" ++ show pn) o b   return $ inTags True "text:list" [("text:style-name", "L" ++ show ln)] is -listItemsToOpenDocument :: String -> WriterOptions -> [[Block]] -> State WriterState Doc+listItemsToOpenDocument :: PandocMonad m+                        => String -> WriterOptions -> [[Block]] -> OD m Doc listItemsToOpenDocument s o is =     vcat . map (inTagsIndented "text:list-item") <$> mapM (withParagraphStyle o s . map plainToPara) is -deflistItemToOpenDocument :: WriterOptions -> ([Inline],[[Block]]) -> State WriterState Doc+deflistItemToOpenDocument :: PandocMonad m+                          => WriterOptions -> ([Inline],[[Block]]) -> OD m Doc deflistItemToOpenDocument o (t,d) = do   let ts = if isTightList d            then "Definition_20_Term_20_Tight"       else "Definition_20_Term"       ds = if isTightList d            then "Definition_20_Definition_20_Tight" else "Definition_20_Definition"   t' <- withParagraphStyle o ts [Para t]-  d' <- liftM vcat $ mapM (withParagraphStyle o ds . (map plainToPara)) d+  d' <- liftM vcat $ mapM (withParagraphStyle o ds . map plainToPara) d   return $ t' $$ d' -inBlockQuote :: WriterOptions -> Int -> [Block] -> State WriterState Doc+inBlockQuote :: PandocMonad m+             => WriterOptions -> Int -> [Block] -> OD m Doc inBlockQuote  o i (b:bs)     | BlockQuote l <- b = do increaseIndent                              ni <- paraStyle                                    [("style:parent-style-name","Quotations")]                              go =<< inBlockQuote o ni (map plainToPara l)-    | Para       l <- b = do go =<< inParagraphTagsWithStyle ("P" ++ show  i) <$> inlinesToOpenDocument o l-    | otherwise         = do go =<< blockToOpenDocument o b+    | Para       l <- b = go =<< inParagraphTagsWithStyle ("P" ++ show  i) <$> inlinesToOpenDocument o l+    | otherwise         = go =<< blockToOpenDocument o b     where go  block  = ($$) block <$> inBlockQuote o i bs inBlockQuote     _ _ [] =  resetIndent >> return empty  -- | Convert a list of Pandoc blocks to OpenDocument.-blocksToOpenDocument :: WriterOptions -> [Block] -> State WriterState Doc+blocksToOpenDocument :: PandocMonad m => WriterOptions -> [Block] -> OD m Doc blocksToOpenDocument o b = vcat <$> mapM (blockToOpenDocument o) b  -- | Convert a Pandoc block element to OpenDocument.-blockToOpenDocument :: WriterOptions -> Block -> State WriterState Doc+blockToOpenDocument :: PandocMonad m => WriterOptions -> Block -> OD m Doc blockToOpenDocument o bs     | Plain          b <- bs = if null b                                   then return empty@@ -311,7 +327,8 @@                                   then return empty                                   else inParagraphTags =<< inlinesToOpenDocument o b     | LineBlock      b <- bs = blockToOpenDocument o $ linesToPara b-    | Div _ xs         <- bs = blocksToOpenDocument o xs+    | Div attr xs      <- bs = withLangFromAttr attr+                                  (blocksToOpenDocument o xs)     | Header     i _ b <- bs = setFirstPara >>                                (inHeaderTags  i =<< inlinesToOpenDocument o b)     | BlockQuote     b <- bs = setFirstPara >> mkBlockQuote b@@ -324,7 +341,9 @@                                 [ ("text:style-name", "Horizontal_20_Line") ])     | RawBlock f     s <- bs = if f == Format "opendocument"                                   then return $ text s-                                  else return empty+                                  else do+                                    report $ BlockNotRendered bs+                                    return empty     | Null             <- bs = return empty     | otherwise              = return empty     where@@ -370,17 +389,23 @@         captionDoc <- withParagraphStyle o "FigureCaption" [Para caption]         return $ imageDoc $$ captionDoc -colHeadsToOpenDocument :: WriterOptions -> String -> [String] -> [[Block]] -> State WriterState Doc+colHeadsToOpenDocument :: PandocMonad m+                       => WriterOptions -> String -> [String] -> [[Block]]+                       -> OD m Doc colHeadsToOpenDocument o tn ns hs =     inTagsIndented "table:table-header-rows" . inTagsIndented "table:table-row" . vcat <$>     mapM (tableItemToOpenDocument o tn) (zip ns hs) -tableRowToOpenDocument :: WriterOptions -> String -> [String] -> [[Block]] -> State WriterState Doc+tableRowToOpenDocument :: PandocMonad m+                       => WriterOptions -> String -> [String] -> [[Block]]+                       -> OD m Doc tableRowToOpenDocument o tn ns cs =     inTagsIndented "table:table-row" . vcat <$>     mapM (tableItemToOpenDocument o tn) (zip ns cs) -tableItemToOpenDocument :: WriterOptions -> String -> (String,[Block])-> State WriterState Doc+tableItemToOpenDocument :: PandocMonad m+                        => WriterOptions -> String -> (String,[Block])+                        -> OD m Doc tableItemToOpenDocument o tn (n,i) =   let a = [ ("table:style-name" , tn ++ ".A1" )           , ("office:value-type", "string"     )@@ -389,10 +414,10 @@       withParagraphStyle o n (map plainToPara i)  -- | Convert a list of inline elements to OpenDocument.-inlinesToOpenDocument :: WriterOptions -> [Inline] -> State WriterState Doc+inlinesToOpenDocument :: PandocMonad m => WriterOptions -> [Inline] -> OD m Doc inlinesToOpenDocument o l = hcat <$> toChunks o l -toChunks :: WriterOptions -> [Inline] -> State WriterState [Doc]+toChunks :: PandocMonad m => WriterOptions -> [Inline] -> OD m [Doc] toChunks _ [] = return [] toChunks o (x : xs)   | isChunkable x = do@@ -407,21 +432,21 @@   where (ys, zs) = span isChunkable xs  isChunkable :: Inline -> Bool-isChunkable (Str _) = True-isChunkable Space   = True+isChunkable (Str _)   = True+isChunkable Space     = True isChunkable SoftBreak = True-isChunkable _ = False+isChunkable _         = False  -- | Convert an inline element to OpenDocument.-inlineToOpenDocument :: WriterOptions -> Inline -> State WriterState Doc+inlineToOpenDocument :: PandocMonad m => WriterOptions -> Inline -> OD m Doc inlineToOpenDocument o ils   = case ils of     Space         -> return space     SoftBreak      | writerWrapText o == WrapPreserve                   -> return $ preformatted "\n"-     | otherwise  -> return $ space-    Span _ xs     -> inlinesToOpenDocument o xs+     | otherwise  ->return space+    Span attr xs  -> withLangFromAttr attr (inlinesToOpenDocument o xs)     LineBreak     -> return $ selfClosingTag "text:line-break" []     Str         s -> return $ handleSpaces $ escapeStringForXML s     Emph        l -> withTextStyle Italic $ inlinesToOpenDocument o l@@ -432,11 +457,14 @@     SmallCaps   l -> withTextStyle SmallC $ inlinesToOpenDocument o l     Quoted    t l -> inQuotes t <$> inlinesToOpenDocument o l     Code      _ s -> inlinedCode $ preformatted s-    Math      t s -> inlinesToOpenDocument o (texMathToInlines t s)+    Math      t s -> lift (texMathToInlines t s) >>=+                         inlinesToOpenDocument o     Cite      _ l -> inlinesToOpenDocument o l     RawInline f s -> if f == Format "opendocument"                        then return $ text s-                       else return empty+                       else do+                         report $ InlineNotRendered ils+                         return empty     Link _ l (s,t) ->  mkLink s t <$> inlinesToOpenDocument o l     Image attr _ (s,t) -> mkImg attr s t     Note        l  -> mkNote l@@ -453,8 +481,6 @@                let getDims [] = []                    getDims (("width", w) :xs) = ("svg:width", w)  : getDims xs                    getDims (("height", h):xs) = ("svg:height", h) : getDims xs-                   getDims (x@("style:rel-width", _) :xs) = x : getDims xs-                   getDims (x@("style:rel-height", _):xs) = x : getDims xs                    getDims (_:xs) =                             getDims xs                return $ inTags False "draw:frame"                         (("draw:name", "img" ++ show id') : getDims kvs) $@@ -473,18 +499,18 @@         addNote nn         return nn -bulletListStyle :: Int -> State WriterState (Int,(Int,[Doc]))-bulletListStyle l =-    let doStyles  i = inTags True "text:list-level-style-bullet"-                      [ ("text:level"      , show (i + 1)       )-                      , ("text:style-name" , "Bullet_20_Symbols")-                      , ("style:num-suffix", "."                )-                      , ("text:bullet-char", [bulletList !! i]  )-                      ] (listLevelStyle (1 + i))-        bulletList  = map chr $ cycle [8226,8227,8259]-        listElStyle = map doStyles [0..9]-    in  do pn <- paraListStyle l-           return (pn, (l, listElStyle))+bulletListStyle :: PandocMonad m => Int -> OD m (Int,(Int,[Doc]))+bulletListStyle l = do+  let doStyles  i = inTags True "text:list-level-style-bullet"+                    [ ("text:level"      , show (i + 1)       )+                    , ("text:style-name" , "Bullet_20_Symbols")+                    , ("style:num-suffix", "."                )+                    , ("text:bullet-char", [bulletList !! i]  )+                    ] (listLevelStyle (1 + i))+      bulletList  = map chr $ cycle [8226,9702,9642]+      listElStyle = map doStyles [0..9]+  pn <- paraListStyle l+  return (pn, (l, listElStyle))  orderedListLevelStyle :: ListAttributes -> (Int, [Doc]) -> (Int,[Doc]) orderedListLevelStyle (s,n, d) (l,ls) =@@ -494,11 +520,11 @@                                    ,("style:num-suffix", ")")]                       _         -> [("style:num-suffix", ".")]         format    = case n of-                      UpperAlpha   -> "A"-                      LowerAlpha   -> "a"-                      UpperRoman   -> "I"-                      LowerRoman   -> "i"-                      _            -> "1"+                      UpperAlpha -> "A"+                      LowerAlpha -> "a"+                      UpperRoman -> "I"+                      LowerRoman -> "i"+                      _          -> "1"         listStyle = inTags True "text:list-level-style-number"                     ([ ("text:level"      , show $ 1 + length ls  )                      , ("text:style-name" , "Numbering_20_Symbols")@@ -509,10 +535,10 @@  listLevelStyle :: Int -> Doc listLevelStyle i =-    let indent = show (0.25 * fromIntegral i :: Double) in+    let indent = show (0.4 * fromIntegral (i - 1) :: Double) in     selfClosingTag "style:list-level-properties"                        [ ("text:space-before"   , indent ++ "in")-                       , ("text:min-label-width",       "0.25in")]+                       , ("text:min-label-width",       "0.4in")]  tableStyle :: Int -> [(Char,Double)] -> Doc tableStyle num wcs =@@ -529,7 +555,7 @@                          [ ("style:name"  , tableId ++ "." ++ [c])                          , ("style:family", "table-column"       )] $                          selfClosingTag "style:table-column-properties"-                         [("style:rel-column-width", printf "%d*" $ (floor $ w * 65535 :: Integer))]+                         [("style:rel-column-width", printf "%d*" (floor $ w * 65535 :: Integer))]         cellStyle      = inTags True "style:style"                          [ ("style:name"  , tableId ++ ".A1")                          , ("style:family", "table-cell"    )] $@@ -538,10 +564,10 @@         columnStyles   = map colStyle wcs     in  table $$ vcat columnStyles $$ cellStyle -paraStyle :: [(String,String)] -> State WriterState Int+paraStyle :: PandocMonad m => [(String,String)] -> OD m Int paraStyle attrs = do   pn <- (+)   1 . length       <$> gets stParaStyles-  i  <- (*) 0.5 . fromIntegral <$> gets stIndentPara :: State WriterState Double+  i  <- (*) (0.5 :: Double) . fromIntegral <$> gets stIndentPara   b  <- gets stInDefinition   t  <- gets stTight   let styleAttr = [ ("style:name"             , "P" ++ show pn)@@ -557,12 +583,14 @@                            , ("style:auto-text-indent" , "false"  )]                       else []       attributes = indent ++ tight-      paraProps = when (not $ null attributes) $-                    selfClosingTag "style:paragraph-properties" attributes+      paraProps = if null attributes+                     then mempty+                     else selfClosingTag+                             "style:paragraph-properties" attributes   addParaStyle $ inTags True "style:style" (styleAttr ++ attrs) paraProps   return pn -paraListStyle :: Int -> State WriterState Int+paraListStyle :: PandocMonad m => Int -> OD m Int paraListStyle l = paraStyle   [("style:parent-style-name","Text_20_body")   ,("style:list-style-name", "L" ++ show l )]@@ -582,7 +610,14 @@                      [ ("fo:text-align", x)                      , ("style:justify-single-word", "false")] -data TextStyle = Italic | Bold | Strike | Sub | Sup | SmallC | Pre+data TextStyle = Italic+               | Bold+               | Strike+               | Sub+               | Sup+               | SmallC+               | Pre+               | Language Lang                deriving ( Eq,Ord )  textStyleAttr :: TextStyle -> [(String,String)]@@ -600,4 +635,18 @@     | Pre    <- s = [("style:font-name"              ,"Courier New")                     ,("style:font-name-asian"        ,"Courier New")                     ,("style:font-name-complex"      ,"Courier New")]+    | Language lang <- s+                  = [("fo:language"                  ,langLanguage lang)+                    ,("fo:country"                   ,langRegion lang)]     | otherwise   = []++withLangFromAttr :: PandocMonad m => Attr -> OD m a -> OD m a+withLangFromAttr (_,_,kvs) action =+  case lookup "lang" kvs of+       Nothing -> action+       Just l  ->+         case parseBCP47 l of+              Right lang -> withTextStyle (Language lang) action+              Left _ -> do+                report $ InvalidLang l+                action
src/Text/Pandoc/Writers/Org.hs view
@@ -1,8 +1,8 @@ {-# LANGUAGE OverloadedStrings #-} {- Copyright (C) 2010-2015 Puneeth Chaganti <punchagan@gmail.com>-                        Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>,-                        and John MacFarlane <jgm@berkeley.edu>+              2010-2017 John MacFarlane <jgm@berkeley.edu>+              2016-2017 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -21,10 +21,12 @@  {- |    Module      : Text.Pandoc.Writers.Org-   Copyright   : Copyright (C) 2010-2015 Puneeth Chaganti and John MacFarlane+  Copyright    : © 2010-2015 Puneeth Chaganti <punchagan@gmail.com>+                   2010-2017 John MacFarlane <jgm@berkeley.edu>+                   2016-2017 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>    License     : GNU GPL, version 2 or above -   Maintainer  : Puneeth Chaganti <punchagan@gmail.com>+   Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>    Stability   : alpha    Portability : portable @@ -32,64 +34,67 @@  Org-Mode:  <http://orgmode.org> -}-module Text.Pandoc.Writers.Org ( writeOrg) where+module Text.Pandoc.Writers.Org (writeOrg) where+import Control.Monad.State.Strict+import Data.Char (isAlphaNum, toLower)+import Data.List (intersect, intersperse, isPrefixOf, partition, transpose)+import Data.Text (Text)+import Text.Pandoc.Class (PandocMonad, report) import Text.Pandoc.Definition+import Text.Pandoc.Logging import Text.Pandoc.Options-import Text.Pandoc.Shared-import Text.Pandoc.Writers.Shared import Text.Pandoc.Pretty+import Text.Pandoc.Shared import Text.Pandoc.Templates (renderTemplate')-import Data.Char ( isAlphaNum, toLower )-import Data.List ( isPrefixOf, intersect, intersperse, partition, transpose )-import Control.Monad.State+import Text.Pandoc.Writers.Shared  data WriterState =-  WriterState { stNotes     :: [[Block]]-              , stLinks     :: Bool-              , stImages    :: Bool-              , stHasMath   :: Bool-              , stOptions   :: WriterOptions+  WriterState { stNotes   :: [[Block]]+              , stHasMath :: Bool+              , stOptions :: WriterOptions               } +type Org = StateT WriterState+ -- | Convert Pandoc to Org.-writeOrg :: WriterOptions -> Pandoc -> String-writeOrg opts document =-  let st = WriterState { stNotes = [], stLinks = False,-                         stImages = False, stHasMath = False,+writeOrg :: PandocMonad m => WriterOptions -> Pandoc -> m Text+writeOrg opts document = do+  let st = WriterState { stNotes = [],+                         stHasMath = False,                          stOptions = opts }-  in evalState (pandocToOrg document) st+  evalStateT (pandocToOrg document) st  -- | Return Org representation of document.-pandocToOrg :: Pandoc -> State WriterState String+pandocToOrg :: PandocMonad m => Pandoc -> Org m Text pandocToOrg (Pandoc meta blocks) = do-  opts <- liftM stOptions get+  opts <- gets stOptions   let colwidth = if writerWrapText opts == WrapAuto                     then Just $ writerColumns opts                     else Nothing+  let render' :: Doc -> Text+      render' = render colwidth   metadata <- metaToJSON opts-               (fmap (render colwidth) . blockListToOrg)-               (fmap (render colwidth) . inlineListToOrg)+               (fmap render' . blockListToOrg)+               (fmap render' . inlineListToOrg)                meta   body <- blockListToOrg blocks-  notes <- liftM (reverse . stNotes) get >>= notesToOrg-  -- note that the notes may contain refs, so we do them first-  hasMath <- liftM stHasMath get-  let main = render colwidth $ foldl ($+$) empty $ [body, notes]+  notes <- gets (reverse . stNotes) >>= notesToOrg+  hasMath <- gets stHasMath+  let main = render colwidth . foldl ($+$) empty $ [body, notes]   let context = defField "body" main-              $ defField "math" hasMath+              . defField "math" hasMath               $ metadata   case writerTemplate opts of        Nothing  -> return main-       Just tpl -> return $ renderTemplate' tpl context+       Just tpl -> renderTemplate' tpl context  -- | Return Org representation of notes.-notesToOrg :: [[Block]] -> State WriterState Doc+notesToOrg :: PandocMonad m => [[Block]] -> Org m Doc notesToOrg notes =-  mapM (\(num, note) -> noteToOrg num note) (zip [1..] notes) >>=-  return . vsep+  vsep <$> zipWithM noteToOrg [1..] notes  -- | Return Org representation of a note.-noteToOrg :: Int -> [Block] -> State WriterState Doc+noteToOrg :: PandocMonad m => Int -> [Block] -> Org m Doc noteToOrg num note = do   contents <- blockListToOrg note   let marker = "[fn:" ++ show num ++ "] "@@ -109,8 +114,9 @@   f == Format "latex" || f == Format "tex" || f == Format "org"  -- | Convert Pandoc block element to Org.-blockToOrg :: Block         -- ^ Block element-           -> State WriterState Doc+blockToOrg :: PandocMonad m+           => Block         -- ^ Block element+           -> Org m Doc blockToOrg Null = return empty blockToOrg (Div (_,classes@(cls:_),kvs) bs) | "drawer" `elem` classes = do   contents <- blockListToOrg bs@@ -123,36 +129,25 @@            blankline $$ contents $$            blankline $$ drawerEndTag $$            blankline-blockToOrg (Div attrs bs) = do+blockToOrg (Div (ident, classes, kv) bs) = do   contents <- blockListToOrg bs+  -- if one class looks like the name of a greater block then output as such:+  -- The ID, if present, is added via the #+NAME keyword; other classes and+  -- key-value pairs are kept as #+ATTR_HTML attributes.   let isGreaterBlockClass = (`elem` ["center", "quote"]) . map toLower-  return $ case attrs of-    ("", [], []) ->-      -- nullAttr, treat contents as if it wasn't wrapped-      blankline $$ contents $$ blankline-    (ident, [], []) ->-      -- only an id: add id as an anchor, unwrap the rest-      blankline $$ "<<" <> text ident <> ">>" $$ contents $$ blankline-    (ident, classes, kv) ->-      -- if one class looks like the name of a greater block then output as-      -- such: The ID, if present, is added via the #+NAME keyword; other-      -- classes and key-value pairs are kept as #+ATTR_HTML attributes.-      let-        (blockTypeCand, classes') = partition isGreaterBlockClass classes-      in case blockTypeCand of-        (blockType:classes'') ->-          blankline $$ attrHtml (ident, classes'' <> classes', kv) $$-          "#+BEGIN_" <> text blockType $$ contents $$-          "#+END_" <> text blockType $$ blankline-        _                     ->-          -- fallback: wrap in div tags-          let-            startTag = tagWithAttrs "div" attrs-            endTag = text "</div>"-          in blankline $$ "#+BEGIN_HTML" $$-             nest 2 startTag $$ "#+END_HTML" $$ blankline $$-             contents $$ blankline $$ "#+BEGIN_HTML" $$-             nest 2 endTag $$ "#+END_HTML" $$ blankline+      (blockTypeCand, classes') = partition isGreaterBlockClass classes+  return $ case blockTypeCand of+    (blockType:classes'') ->+      blankline $$ attrHtml (ident, classes'' <> classes', kv) $$+      "#+BEGIN_" <> text blockType $$ contents $$+      "#+END_" <> text blockType $$ blankline+    _                     ->+      -- fallback with id: add id as an anchor if present, discard classes and+      -- key-value pairs, unwrap the content.+      let contents' = if not (null ident)+                      then "<<" <> text ident <> ">>" $$ contents+                      else contents+      in blankline $$ contents' $$ blankline blockToOrg (Plain inlines) = inlineListToOrg inlines -- title beginning with fig: indicates that the image is a figure blockToOrg (Para [Image attr txt (src,'f':'i':'g':':':tit)]) = do@@ -167,7 +162,7 @@ blockToOrg (LineBlock lns) = do   let splitStanza [] = []       splitStanza xs = case break (== mempty) xs of-        (l, [])  -> l : []+        (l, [])  -> [l]         (l, _:r) -> l : splitStanza r   let joinWithLinefeeds  = nowrap . mconcat . intersperse cr   let joinWithBlankLines = mconcat . intersperse blankline@@ -178,9 +173,11 @@ blockToOrg (RawBlock "html" str) =   return $ blankline $$ "#+BEGIN_HTML" $$            nest 2 (text str) $$ "#+END_HTML" $$ blankline-blockToOrg (RawBlock f str) | isRawFormat f =-  return $ text str-blockToOrg (RawBlock _ _) = return empty+blockToOrg b@(RawBlock f str)+  | isRawFormat f = return $ text str+  | otherwise     = do+      report $ BlockNotRendered b+      return empty blockToOrg HorizontalRule = return $ blankline $$ "--------------" $$ blankline blockToOrg (Header level attr inlines) = do   contents <- inlineListToOrg inlines@@ -190,7 +187,7 @@                   else cr <> nest (level + 1) (propertiesDrawer attr)   return $ headerStr <> " " <> contents <> drawerStr <> blankline blockToOrg (CodeBlock (_,classes,_) str) = do-  opts <- stOptions <$> get+  opts <- gets stOptions   let tabstop = writerTabStop opts   let at = map pandocLangToOrg classes `intersect` orgLangIdentifiers   let (beg, end) = case at of@@ -205,7 +202,7 @@   caption'' <- inlineListToOrg caption'   let caption = if null caption'                    then empty-                   else ("#+CAPTION: " <> caption'')+                   else "#+CAPTION: " <> caption''   headers' <- mapM blockListToOrg headers   rawRows <- mapM (mapM blockListToOrg) rows   let numChars = maximum . map offset@@ -215,16 +212,16 @@   -- FIXME: Org doesn't allow blocks with height more than 1.   let hpipeBlocks blocks = hcat [beg, middle, end]         where h      = maximum (1 : map height blocks)-              sep'   = lblock 3 $ vcat (map text $ replicate h " | ")-              beg    = lblock 2 $ vcat (map text $ replicate h "| ")-              end    = lblock 2 $ vcat (map text $ replicate h " |")+              sep'   = lblock 3 $ vcat (replicate h (text " | "))+              beg    = lblock 2 $ vcat (replicate h (text "| "))+              end    = lblock 2 $ vcat (replicate h (text " |"))               middle = hcat $ intersperse sep' blocks   let makeRow = hpipeBlocks . zipWith lblock widthsInChars   let head' = makeRow headers'   rows' <- mapM (\row -> do cols <- mapM blockListToOrg row                             return $ makeRow cols) rows   let border ch = char '|' <> char ch <>-                  (hcat $ intersperse (char ch <> char '+' <> char ch) $+                  (hcat . intersperse (char ch <> char '+' <> char ch) $                           map (\l -> text $ replicate l ch) widthsInChars) <>                   char ch <> char '|'   let body = vcat rows'@@ -245,8 +242,7 @@   let maxMarkerLength = maximum $ map length markers   let markers' = map (\m -> let s = maxMarkerLength - length m                             in  m ++ replicate s ' ') markers-  contents <- mapM (\(item, num) -> orderedListItemToOrg item num) $-              zip markers' items+  contents <- zipWithM orderedListItemToOrg markers' items   -- ensure that sublists have preceding blank line   return $ blankline $$ vcat contents $$ blankline blockToOrg (DefinitionList items) = do@@ -254,25 +250,27 @@   return $ vcat contents $$ blankline  -- | Convert bullet list item (list of blocks) to Org.-bulletListItemToOrg :: [Block] -> State WriterState Doc+bulletListItemToOrg :: PandocMonad m => [Block] -> Org m Doc bulletListItemToOrg items = do   contents <- blockListToOrg items-  return $ hang 3 "-  " (contents <> cr)+  return $ hang 2 "- " (contents <> cr)  -- | Convert ordered list item (a list of blocks) to Org.-orderedListItemToOrg :: String   -- ^ marker for list item+orderedListItemToOrg :: PandocMonad m+                     => String   -- ^ marker for list item                      -> [Block]  -- ^ list item (list of blocks)-                     -> State WriterState Doc+                     -> Org m Doc orderedListItemToOrg marker items = do   contents <- blockListToOrg items   return $ hang (length marker + 1) (text marker <> space) (contents <> cr)  -- | Convert defintion list item (label, list of blocks) to Org.-definitionListItemToOrg :: ([Inline], [[Block]]) -> State WriterState Doc+definitionListItemToOrg :: PandocMonad m+                        => ([Inline], [[Block]]) -> Org m Doc definitionListItemToOrg (label, defs) = do   label' <- inlineListToOrg label-  contents <- liftM vcat $ mapM blockListToOrg defs-  return $ hang 3 "-  " $ label' <> " :: " <> (contents <> cr)+  contents <- vcat <$> mapM blockListToOrg defs+  return . hang 2 "- " $ label' <> " :: " <> (contents <> cr)  -- | Convert list of key/value pairs to Org :PROPERTIES: drawer. propertiesDrawer :: Attr -> Doc@@ -280,8 +278,8 @@   let     drawerStart = text ":PROPERTIES:"     drawerEnd   = text ":END:"-    kv'  = if (classes == mempty) then kv  else ("CLASS", unwords classes):kv-    kv'' = if (ident == mempty)   then kv' else ("CUSTOM_ID", ident):kv'+    kv'  = if classes == mempty then kv  else ("CLASS", unwords classes):kv+    kv'' = if ident == mempty   then kv' else ("CUSTOM_ID", ident):kv'     properties = vcat $ map kvToOrgProperty kv''   in     drawerStart <> cr <> properties <> cr <> drawerEnd@@ -294,23 +292,26 @@ attrHtml (""   , []     , []) = mempty attrHtml (ident, classes, kvs) =   let-    name = if (null ident) then mempty else "#+NAME: " <> text ident <> cr+    name = if null ident then mempty else "#+NAME: " <> text ident <> cr     keyword = "#+ATTR_HTML"     classKv = ("class", unwords classes)     kvStrings = map (\(k,v) -> ":" <> k <> " " <> v) (classKv:kvs)   in name <> keyword <> ": " <> text (unwords kvStrings) <> cr  -- | Convert list of Pandoc block elements to Org.-blockListToOrg :: [Block]       -- ^ List of block elements-               -> State WriterState Doc-blockListToOrg blocks = mapM blockToOrg blocks >>= return . vcat+blockListToOrg :: PandocMonad m+               => [Block]       -- ^ List of block elements+               -> Org m Doc+blockListToOrg blocks = vcat <$> mapM blockToOrg blocks  -- | Convert list of Pandoc inline elements to Org.-inlineListToOrg :: [Inline] -> State WriterState Doc-inlineListToOrg lst = mapM inlineToOrg lst >>= return . hcat+inlineListToOrg :: PandocMonad m+                => [Inline]+                -> Org m Doc+inlineListToOrg lst = hcat <$> mapM inlineToOrg lst  -- | Convert Pandoc inline element to Org.-inlineToOrg :: Inline -> State WriterState Doc+inlineToOrg :: PandocMonad m => Inline -> Org m Doc inlineToOrg (Span (uid, [], []) []) =   return $ "<<" <> text uid <> ">>" inlineToOrg (Span _ lst) =@@ -339,50 +340,48 @@   return $ "\"" <> contents <> "\"" inlineToOrg (Cite _  lst) = inlineListToOrg lst inlineToOrg (Code _ str) = return $ "=" <> text str <> "="-inlineToOrg (Str str) = return $ text $ escapeString str+inlineToOrg (Str str) = return . text $ escapeString str inlineToOrg (Math t str) = do   modify $ \st -> st{ stHasMath = True }   return $ if t == InlineMath               then "$" <> text str <> "$"               else "$$" <> text str <> "$$"-inlineToOrg (RawInline f@(Format f') str) =-  return $ if isRawFormat f-           then text str-           else "@@" <> text f' <> ":" <> text str <> "@@"-inlineToOrg (LineBreak) = return (text "\\\\" <> cr)+inlineToOrg il@(RawInline f str)+  | isRawFormat f = return $ text str+  | otherwise     = do+      report $ InlineNotRendered il+      return empty+inlineToOrg LineBreak = return (text "\\\\" <> cr) inlineToOrg Space = return space inlineToOrg SoftBreak = do   wrapText <- gets (writerWrapText . stOptions)   case wrapText of-       WrapPreserve   -> return cr-       WrapAuto       -> return space-       WrapNone       -> return space-inlineToOrg (Link _ txt (src, _)) = do+       WrapPreserve -> return cr+       WrapAuto     -> return space+       WrapNone     -> return space+inlineToOrg (Link _ txt (src, _)) =   case txt of         [Str x] | escapeURI x == src ->  -- autolink-             do modify $ \s -> s{ stLinks = True }-                return $ "[[" <> text (orgPath x) <> "]]"+             return $ "[[" <> text (orgPath x) <> "]]"         _ -> do contents <- inlineListToOrg txt-                modify $ \s -> s{ stLinks = True }                 return $ "[[" <> text (orgPath src) <> "][" <> contents <> "]]"-inlineToOrg (Image _ _ (source, _)) = do-  modify $ \s -> s{ stImages = True }+inlineToOrg (Image _ _ (source, _)) =   return $ "[[" <> text (orgPath source) <> "]]" inlineToOrg (Note contents) = do   -- add to notes in state-  notes <- get >>= (return . stNotes)+  notes <- gets stNotes   modify $ \st -> st { stNotes = contents:notes }-  let ref = show $ (length notes) + 1+  let ref = show $ length notes + 1   return $ "[fn:" <> text ref <> "]"  orgPath :: String -> String orgPath src =   case src of-    []                 -> mempty         -- wiki link-    ('#':xs)           -> xs             -- internal link-    _ | isUrl src      -> src-    _ | isFilePath src -> src-    _                  -> "file:" <> src+    []      -> mempty         -- wiki link+    ('#':_) -> src            -- internal link+    _       | isUrl src      -> src+    _       | isFilePath src -> src+    _       -> "file:" <> src  where    isFilePath :: String -> Bool    isFilePath cs = any (`isPrefixOf` cs) ["/", "./", "../", "file:"]
src/Text/Pandoc/Writers/RST.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE OverloadedStrings #-} {--Copyright (C) 2006-2015 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2006-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -19,7 +19,7 @@  {- |    Module      : Text.Pandoc.Writers.RST-   Copyright   : Copyright (C) 2006-2015 John MacFarlane+   Copyright   : Copyright (C) 2006-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -31,19 +31,21 @@ reStructuredText:  <http://docutils.sourceforge.net/rst.html> -} module Text.Pandoc.Writers.RST ( writeRST ) where+import Control.Monad.State.Strict+import Data.Char (isSpace, toLower)+import Data.List (isPrefixOf, stripPrefix)+import Data.Maybe (fromMaybe)+import Data.Text (Text, stripEnd)+import qualified Text.Pandoc.Builder as B+import Text.Pandoc.Class (PandocMonad, report) import Text.Pandoc.Definition+import Text.Pandoc.ImageSize+import Text.Pandoc.Logging import Text.Pandoc.Options+import Text.Pandoc.Pretty import Text.Pandoc.Shared-import Text.Pandoc.Writers.Shared-import Text.Pandoc.ImageSize import Text.Pandoc.Templates (renderTemplate')-import Text.Pandoc.Builder (deleteMeta)-import Data.Maybe (fromMaybe)-import Data.List ( isPrefixOf, stripPrefix, intersperse, transpose )-import Network.URI (isURI)-import Text.Pandoc.Pretty-import Control.Monad.State-import Data.Char (isSpace, toLower)+import Text.Pandoc.Writers.Shared  type Refs = [([Inline], Target)] @@ -55,97 +57,102 @@               , stHasRawTeX   :: Bool               , stOptions     :: WriterOptions               , stTopLevel    :: Bool+              , stLastNested  :: Bool               } +type RST = StateT WriterState+ -- | Convert Pandoc to RST.-writeRST :: WriterOptions -> Pandoc -> String-writeRST opts document =+writeRST :: PandocMonad m => WriterOptions -> Pandoc -> m Text+writeRST opts document = do   let st = WriterState { stNotes = [], stLinks = [],                          stImages = [], stHasMath = False,                          stHasRawTeX = False, stOptions = opts,-                         stTopLevel = True}-  in evalState (pandocToRST document) st+                         stTopLevel = True, stLastNested = False}+  evalStateT (pandocToRST document) st  -- | Return RST representation of document.-pandocToRST :: Pandoc -> State WriterState String+pandocToRST :: PandocMonad m => Pandoc -> RST m Text pandocToRST (Pandoc meta blocks) = do-  opts <- liftM stOptions get+  opts <- gets stOptions   let colwidth = if writerWrapText opts == WrapAuto                     then Just $ writerColumns opts                     else Nothing+  let render' :: Doc -> Text+      render' = render colwidth   let subtit = case lookupMeta "subtitle" meta of                     Just (MetaBlocks [Plain xs]) -> xs-                    _ -> []+                    _                            -> []   title <- titleToRST (docTitle meta) subtit   metadata <- metaToJSON opts-                (fmap (render colwidth) . blockListToRST)-                (fmap (trimr . render colwidth) . inlineListToRST)-                $ deleteMeta "title" $ deleteMeta "subtitle" meta+                (fmap render' . blockListToRST)+                (fmap (stripEnd . render') . inlineListToRST)+                $ B.deleteMeta "title" $ B.deleteMeta "subtitle" meta   body <- blockListToRST' True $ case writerTemplate opts of                                       Just _  -> normalizeHeadings 1 blocks                                       Nothing -> blocks-  notes <- liftM (reverse . stNotes) get >>= notesToRST+  notes <- gets (reverse . stNotes) >>= notesToRST   -- note that the notes may contain refs, so we do them first-  refs <- liftM (reverse . stLinks) get >>= refsToRST-  pics <- liftM (reverse . stImages) get >>= pictRefsToRST-  hasMath <- liftM stHasMath get-  rawTeX <- liftM stHasRawTeX get-  let main = render colwidth $ foldl ($+$) empty $ [body, notes, refs, pics]+  refs <- gets (reverse . stLinks) >>= refsToRST+  pics <- gets (reverse . stImages) >>= pictRefsToRST+  hasMath <- gets stHasMath+  rawTeX <- gets stHasRawTeX+  let main = render' $ foldl ($+$) empty [body, notes, refs, pics]   let context = defField "body" main               $ defField "toc" (writerTableOfContents opts)               $ defField "toc-depth" (show $ writerTOCDepth opts)               $ defField "math" hasMath               $ defField "title" (render Nothing title :: String)               $ defField "math" hasMath-              $ defField "rawtex" rawTeX-              $ metadata+              $ defField "rawtex" rawTeX metadata   case writerTemplate opts of        Nothing  -> return main-       Just tpl -> return $ renderTemplate' tpl context+       Just tpl -> renderTemplate' tpl context   where     normalizeHeadings lev (Header l a i:bs) =       Header lev a i:normalizeHeadings (lev+1) cont ++ normalizeHeadings lev bs'       where (cont,bs') = break (headerLtEq l) bs             headerLtEq level (Header l' _ _) = l' <= level-            headerLtEq _ _ = False+            headerLtEq _ _                   = False     normalizeHeadings lev (b:bs) = b:normalizeHeadings lev bs     normalizeHeadings _   []     = []  -- | Return RST representation of reference key table.-refsToRST :: Refs -> State WriterState Doc+refsToRST :: PandocMonad m => Refs -> RST m Doc refsToRST refs = mapM keyToRST refs >>= return . vcat  -- | Return RST representation of a reference key.-keyToRST :: ([Inline], (String, String))-         -> State WriterState Doc+keyToRST :: PandocMonad m => ([Inline], (String, String)) -> RST m Doc keyToRST (label, (src, _)) = do   label' <- inlineListToRST label-  let label'' = if ':' `elem` ((render Nothing label') :: String)+  let label'' = if ':' `elem` (render Nothing label' :: String)                    then char '`' <> label' <> char '`'                    else label'   return $ nowrap $ ".. _" <> label'' <> ": " <> text src  -- | Return RST representation of notes.-notesToRST :: [[Block]] -> State WriterState Doc+notesToRST :: PandocMonad m => [[Block]] -> RST m Doc notesToRST notes =-  mapM (\(num, note) -> noteToRST num note) (zip [1..] notes) >>=+  mapM (uncurry noteToRST) (zip [1..] notes) >>=   return . vsep  -- | Return RST representation of a note.-noteToRST :: Int -> [Block] -> State WriterState Doc+noteToRST :: PandocMonad m => Int -> [Block] -> RST m Doc noteToRST num note = do   contents <- blockListToRST note   let marker = ".. [" <> text (show num) <> "]"   return $ nowrap $ marker $$ nest 3 contents  -- | Return RST representation of picture reference table.-pictRefsToRST :: [([Inline], (Attr, String, String, Maybe String))]-              -> State WriterState Doc+pictRefsToRST :: PandocMonad m+              => [([Inline], (Attr, String, String, Maybe String))]+              -> RST m Doc pictRefsToRST refs = mapM pictToRST refs >>= return . vcat  -- | Return RST representation of a picture substitution reference.-pictToRST :: ([Inline], (Attr, String, String, Maybe String))-          -> State WriterState Doc+pictToRST :: PandocMonad m+          => ([Inline], (Attr, String, String, Maybe String))+          -> RST m Doc pictToRST (label, (attr, src, _, mbtarget)) = do   label' <- inlineListToRST label   dims   <- imageDimsToRST attr@@ -160,10 +167,27 @@                  Just t  -> "   :target: " <> text t  -- | Escape special characters for RST.-escapeString :: String -> String-escapeString = escapeStringUsing (backslashEscapes "`\\|*_")+escapeString :: WriterOptions -> String -> String+escapeString = escapeString' True+  where+  escapeString' _ _  [] = []+  escapeString' firstChar opts (c:cs) =+    case c of+         _ | c `elem` ['\\','`','*','_','|'] &&+             (firstChar || null cs) -> '\\':c:escapeString' False opts cs+         '\'' | isEnabled Ext_smart opts -> '\\':'\'':escapeString' False opts cs+         '"' | isEnabled Ext_smart opts -> '\\':'"':escapeString' False opts cs+         '-' | isEnabled Ext_smart opts ->+                case cs of+                     '-':_ -> '\\':'-':escapeString' False opts cs+                     _     -> '-':escapeString' False opts cs+         '.' | isEnabled Ext_smart opts ->+                case cs of+                     '.':'.':rest -> '\\':'.':'.':'.':escapeString' False opts rest+                     _            -> '.':escapeString' False opts cs+         _ -> c : escapeString' False opts cs -titleToRST :: [Inline] -> [Inline] -> State WriterState Doc+titleToRST :: PandocMonad m => [Inline] -> [Inline] -> RST m Doc titleToRST [] _ = return empty titleToRST tit subtit = do   title <- inlineListToRST tit@@ -179,8 +203,9 @@          border = text (replicate len c)  -- | Convert Pandoc block element to RST.-blockToRST :: Block         -- ^ Block element-           -> State WriterState Doc+blockToRST :: PandocMonad m+           => Block         -- ^ Block element+           -> RST m Doc blockToRST Null = return empty blockToRST (Div attr bs) = do   contents <- blockListToRST bs@@ -200,7 +225,7 @@                    else ":figclass: " <> text (unwords cls)   return $ hang 3 ".. " (fig $$ alt $$ classes $$ dims $+$ capt) $$ blankline blockToRST (Para inlines)-  | LineBreak `elem` inlines = do -- use line block if LineBreaks+  | LineBreak `elem` inlines =       linesToLineBlock $ splitBy (==LineBreak) inlines   | otherwise = do       contents <- inlineListToRST inlines@@ -211,17 +236,22 @@   | f == "rst" = return $ text str   | otherwise  = return $ blankline <> ".. raw:: " <>                     text (map toLower f') $+$-                    (nest 3 $ text str) $$ blankline+                    nest 3 (text str) $$ blankline blockToRST HorizontalRule =   return $ blankline $$ "--------------" $$ blankline blockToRST (Header level (name,classes,_) inlines) = do   contents <- inlineListToRST inlines+  -- we calculate the id that would be used by auto_identifiers+  -- so we know whether to print an explicit identifier+  let autoId = uniqueIdent inlines mempty   isTopLevel <- gets stTopLevel   if isTopLevel     then do           let headerChar = if level > 5 then ' ' else "=-~^'" !! (level - 1)           let border = text $ replicate (offset contents) headerChar-          return $ nowrap $ contents $$ border $$ blankline+          let anchor | null name || name == autoId = empty+                     | otherwise = ".. " <> text name <> ":" $$ blankline+          return $ nowrap $ anchor $$ contents $$ border $$ blankline     else do           let rub     = "rubric:: " <> contents           let name' | null name    = empty@@ -230,7 +260,7 @@                     | otherwise    = ":class: " <> text (unwords classes)           return $ nowrap $ hang 3 ".. " (rub $$ name' $$ cls) $$ blankline blockToRST (CodeBlock (_,classes,kvs) str) = do-  opts <- stOptions <$> get+  opts <- gets stOptions   let tabstop = writerTabStop opts   let startnum = maybe "" (\x -> " " <> text x) $ lookup "startFrom" kvs   let numberlines = if "numberLines" `elem` classes@@ -246,58 +276,38 @@              (lang:_) -> (".. code:: " <> text lang) $$ numberlines)           $+$ nest tabstop (text str) $$ blankline blockToRST (BlockQuote blocks) = do-  tabstop <- get >>= (return . writerTabStop . stOptions)+  tabstop <- gets $ writerTabStop . stOptions   contents <- blockListToRST blocks-  return $ (nest tabstop contents) <> blankline-blockToRST (Table caption _ widths headers rows) =  do+  return $ nest tabstop contents <> blankline+blockToRST (Table caption aligns widths headers rows) = do   caption' <- inlineListToRST caption-  let caption'' = if null caption-                     then empty-                     else blankline <> text "Table: " <> caption'-  headers' <- mapM blockListToRST headers-  rawRows <- mapM (mapM blockListToRST) rows-  -- let isSimpleCell [Plain _] = True-  --     isSimpleCell [Para _]  = True-  --     isSimpleCell []        = True-  --     isSimpleCell _         = False-  -- let isSimple = all (==0) widths && all (all isSimpleCell) rows-  let numChars = maximum . map offset-  opts <- get >>= return . stOptions-  let widthsInChars =-       if all (== 0) widths-          then map ((+2) . numChars) $ transpose (headers' : rawRows)-          else map (floor . (fromIntegral (writerColumns opts) *)) widths-  let hpipeBlocks blocks = hcat [beg, middle, end]-        where h      = height (hcat blocks)-              sep'   = lblock 3 $ vcat (map text $ replicate h " | ")-              beg    = lblock 2 $ vcat (map text $ replicate h "| ")-              end    = lblock 2 $ vcat (map text $ replicate h " |")-              middle = hcat $ intersperse sep' blocks-  let makeRow = hpipeBlocks . zipWith lblock widthsInChars-  let head' = makeRow headers'-  let rows' = map makeRow rawRows-  let border ch = char '+' <> char ch <>-                  (hcat $ intersperse (char ch <> char '+' <> char ch) $-                          map (\l -> text $ replicate l ch) widthsInChars) <>-                  char ch <> char '+'-  let body = vcat $ intersperse (border '-') rows'-  let head'' = if all null headers-                  then empty-                  else head' $$ border '='-  return $ border '-' $$ head'' $$ body $$ border '-' $$ caption'' $$ blankline+  let blocksToDoc opts bs = do+         oldOpts <- gets stOptions+         modify $ \st -> st{ stOptions = opts }+         result <- blockListToRST bs+         modify $ \st -> st{ stOptions = oldOpts }+         return result+  opts <- gets stOptions+  tbl <- gridTable opts blocksToDoc (all null headers)+            (map (const AlignDefault) aligns) widths+            headers rows+  return $ if null caption+              then tbl $$ blankline+              else (".. table:: " <> caption') $$ blankline $$ nest 3 tbl $$+                   blankline blockToRST (BulletList items) = do   contents <- mapM bulletListItemToRST items   -- ensure that sublists have preceding blank line   return $ blankline $$ chomp (vcat contents) $$ blankline blockToRST (OrderedList (start, style', delim) items) = do   let markers = if start == 1 && style' == DefaultStyle && delim == DefaultDelim-                   then take (length items) $ repeat "#."+                   then replicate (length items) "#."                    else take (length items) $ orderedListMarkers                                               (start, style', delim)   let maxMarkerLength = maximum $ map length markers   let markers' = map (\m -> let s = maxMarkerLength - length m                             in  m ++ replicate s ' ') markers-  contents <- mapM (\(item, num) -> orderedListItemToRST item num) $+  contents <- mapM (uncurry orderedListItemToRST) $               zip markers' items   -- ensure that sublists have preceding blank line   return $ blankline $$ chomp (vcat contents) $$ blankline@@ -307,51 +317,76 @@   return $ blankline $$ chomp (vcat contents) $$ blankline  -- | Convert bullet list item (list of blocks) to RST.-bulletListItemToRST :: [Block] -> State WriterState Doc+bulletListItemToRST :: PandocMonad m => [Block] -> RST m Doc bulletListItemToRST items = do   contents <- blockListToRST items   return $ hang 3 "-  " $ contents <> cr  -- | Convert ordered list item (a list of blocks) to RST.-orderedListItemToRST :: String   -- ^ marker for list item+orderedListItemToRST :: PandocMonad m+                     => String   -- ^ marker for list item                      -> [Block]  -- ^ list item (list of blocks)-                     -> State WriterState Doc+                     -> RST m Doc orderedListItemToRST marker items = do   contents <- blockListToRST items   let marker' = marker ++ " "   return $ hang (length marker') (text marker') $ contents <> cr  -- | Convert defintion list item (label, list of blocks) to RST.-definitionListItemToRST :: ([Inline], [[Block]]) -> State WriterState Doc+definitionListItemToRST :: PandocMonad m => ([Inline], [[Block]]) -> RST m Doc definitionListItemToRST (label, defs) = do   label' <- inlineListToRST label   contents <- liftM vcat $ mapM blockListToRST defs-  tabstop <- get >>= (return . writerTabStop . stOptions)-  return $ label' $$ nest tabstop (nestle contents <> cr)+  tabstop <- gets $ writerTabStop . stOptions+  return $ nowrap label' $$ nest tabstop (nestle contents <> cr)  -- | Format a list of lines as line block.-linesToLineBlock :: [[Inline]] -> State WriterState Doc+linesToLineBlock :: PandocMonad m => [[Inline]] -> RST m Doc linesToLineBlock inlineLines = do   lns <- mapM inlineListToRST inlineLines-  return $ (vcat $ map (hang 2 (text "| ")) lns) <> blankline+  return $+                      vcat (map (hang 2 (text "| ")) lns) <> blankline  -- | Convert list of Pandoc block elements to RST.-blockListToRST' :: Bool+blockListToRST' :: PandocMonad m+                => Bool                 -> [Block]       -- ^ List of block elements-                -> State WriterState Doc+                -> RST m Doc blockListToRST' topLevel blocks = do   tl <- gets stTopLevel-  modify (\s->s{stTopLevel=topLevel})-  res <- vcat `fmap` mapM blockToRST blocks+  modify (\s->s{stTopLevel=topLevel, stLastNested=False})+  res <- vcat `fmap` mapM blockToRST' blocks   modify (\s->s{stTopLevel=tl})   return res -blockListToRST :: [Block]       -- ^ List of block elements-               -> State WriterState Doc+blockToRST' :: PandocMonad m => Block -> RST m Doc+blockToRST' (x@BlockQuote{}) = do+  lastNested <- gets stLastNested+  res <- blockToRST x+  modify (\s -> s{stLastNested = True})+  return $ if lastNested+              then ".." $+$ res+              else res+blockToRST' x = do+  modify (\s -> s{stLastNested =+    case x of+         Para [Image _ _ (_,'f':'i':'g':':':_)] -> True+         Para{}                                 -> False+         Plain{}                                -> False+         Header{}                               -> False+         LineBlock{}                            -> False+         HorizontalRule                         -> False+         _                                      -> True+    })+  blockToRST x++blockListToRST :: PandocMonad m+               => [Block]       -- ^ List of block elements+               -> RST m Doc blockListToRST = blockListToRST' False  -- | Convert list of Pandoc inline elements to RST.-inlineListToRST :: [Inline] -> State WriterState Doc+inlineListToRST :: PandocMonad m => [Inline] -> RST m Doc inlineListToRST lst =   mapM inlineToRST (removeSpaceAfterDisplayMath $ insertBS lst) >>=     return . hcat@@ -362,7 +397,7 @@         removeSpaceAfterDisplayMath [] = []         insertBS :: [Inline] -> [Inline] -- insert '\ ' where needed         insertBS (x:y:z:zs)-          | isComplex y && (surroundComplex x z) =+          | isComplex y && surroundComplex x z =               x : y : insertBS (z : zs)         insertBS (x:y:zs)           | isComplex x && not (okAfterComplex y) =@@ -396,23 +431,28 @@         okBeforeComplex (Str (c:_)) = isSpace c || c `elem` ("-:/'\"<([{–—" :: String)         okBeforeComplex _ = False         isComplex :: Inline -> Bool-        isComplex (Emph _) = True-        isComplex (Strong _) = True-        isComplex (SmallCaps _) = True-        isComplex (Strikeout _) = True+        isComplex (Emph _)        = True+        isComplex (Strong _)      = True+        isComplex (SmallCaps _)   = True+        isComplex (Strikeout _)   = True         isComplex (Superscript _) = True-        isComplex (Subscript _) = True-        isComplex (Link _ _ _) = True-        isComplex (Image _ _ _) = True-        isComplex (Code _ _) = True-        isComplex (Math _ _) = True-        isComplex (Cite _ (x:_)) = isComplex x-        isComplex (Span _ (x:_)) = isComplex x-        isComplex _ = False+        isComplex (Subscript _)   = True+        isComplex (Link{})        = True+        isComplex (Image{})       = True+        isComplex (Code _ _)      = True+        isComplex (Math _ _)      = True+        isComplex (Cite _ (x:_))  = isComplex x+        isComplex (Span _ (x:_))  = isComplex x+        isComplex _               = False  -- | Convert Pandoc inline element to RST.-inlineToRST :: Inline -> State WriterState Doc-inlineToRST (Span _ ils) = inlineListToRST ils+inlineToRST :: PandocMonad m => Inline -> RST m Doc+inlineToRST (Span (_,_,kvs) ils) = do+  contents <- inlineListToRST ils+  return $+    case lookup "role" kvs of+          Just role -> ":" <> text role <> ":`" <> contents <> "`"+          Nothing   -> contents inlineToRST (Emph lst) = do   contents <- inlineListToRST lst   return $ "*" <> contents <> "*"@@ -431,14 +471,33 @@ inlineToRST (SmallCaps lst) = inlineListToRST lst inlineToRST (Quoted SingleQuote lst) = do   contents <- inlineListToRST lst-  return $ "‘" <> contents <> "’"+  opts <- gets stOptions+  if isEnabled Ext_smart opts+     then return $ "'" <> contents <> "'"+     else return $ "‘" <> contents <> "’" inlineToRST (Quoted DoubleQuote lst) = do   contents <- inlineListToRST lst-  return $ "“" <> contents <> "”"+  opts <- gets stOptions+  if isEnabled Ext_smart opts+     then return $ "\"" <> contents <> "\""+     else return $ "“" <> contents <> "”" inlineToRST (Cite _  lst) =   inlineListToRST lst-inlineToRST (Code _ str) = return $ "``" <> text str <> "``"-inlineToRST (Str str) = return $ text $ escapeString str+inlineToRST (Code _ str) = do+  opts <- gets stOptions+  -- we trim the string because the delimiters must adjoin a+  -- non-space character; see #3496+  -- we use :literal: when the code contains backticks, since+  -- :literal: allows backslash-escapes; see #3974+  return $ if '`' `elem` str+              then ":literal:`" <> text (escapeString opts (trim str)) <> "`"+              else "``" <> text (trim str) <> "``"+inlineToRST (Str str) = do+  opts <- gets stOptions+  return $ text $+    (if isEnabled Ext_smart opts+        then unsmartify opts+        else id) $ escapeString opts str inlineToRST (Math t str) = do   modify $ \st -> st{ stHasMath = True }   return $ if t == InlineMath@@ -447,20 +506,20 @@                    then blankline $$ ".. math::" $$                         blankline $$ nest 3 (text str) $$ blankline                    else blankline $$ (".. math:: " <> text str) $$ blankline-inlineToRST (RawInline f x)+inlineToRST il@(RawInline f x)   | f == "rst" = return $ text x   | f == "latex" || f == "tex" = do       modify $ \st -> st{ stHasRawTeX = True }       return $ ":raw-latex:`" <> text x <> "`"-  | otherwise  = return empty-inlineToRST (LineBreak) = return cr -- there's no line break in RST (see Para)+  | otherwise  = empty <$ report (InlineNotRendered il)+inlineToRST LineBreak = return cr -- there's no line break in RST (see Para) inlineToRST Space = return space inlineToRST SoftBreak = do-  wrapText <- gets (writerWrapText . stOptions)+  wrapText <- gets $ writerWrapText . stOptions   case wrapText of-        WrapPreserve  -> return cr-        WrapAuto      -> return space-        WrapNone      -> return space+        WrapPreserve -> return cr+        WrapAuto     -> return space+        WrapNone     -> return space -- autolink inlineToRST (Link _ [Str str] (src, _))   | isURI src &&@@ -473,15 +532,15 @@   label <- registerImage attr alt (imgsrc,imgtit) (Just src)   return $ "|" <> label <> "|" inlineToRST (Link _ txt (src, tit)) = do-  useReferenceLinks <- get >>= return . writerReferenceLinks . stOptions-  linktext <- inlineListToRST $ normalizeSpaces txt+  useReferenceLinks <- gets $ writerReferenceLinks . stOptions+  linktext <- inlineListToRST $ B.toList . B.trimInlines . B.fromList $ txt   if useReferenceLinks-    then do refs <- get >>= return . stLinks+    then do refs <- gets stLinks             case lookup txt refs of                  Just (src',tit') ->                    if src == src' && tit == tit'                       then return $ "`" <> linktext <> "`_"-                      else do -- duplicate label, use non-reference link+                      else                         return $ "`" <> linktext <> " <" <> text src <> ">`__"                  Nothing -> do                    modify $ \st -> st { stLinks = (txt,(src,tit)):refs }@@ -494,12 +553,12 @@   -- add to notes in state   notes <- gets stNotes   modify $ \st -> st { stNotes = contents:notes }-  let ref = show $ (length notes) + 1+  let ref = show $ length notes + 1   return $ " [" <> text ref <> "]_" -registerImage :: Attr -> [Inline] -> Target -> Maybe String -> State WriterState Doc+registerImage :: PandocMonad m => Attr -> [Inline] -> Target -> Maybe String -> RST m Doc registerImage attr alt (src,tit) mbtarget = do-  pics <- get >>= return . stImages+  pics <- gets stImages   txt <- case lookup alt pics of                Just (a,s,t,mbt) | (a,s,t,mbt) == (attr,src,tit,mbtarget)                  -> return alt@@ -512,14 +571,14 @@                  return alt'   inlineListToRST txt -imageDimsToRST :: Attr -> State WriterState Doc+imageDimsToRST :: PandocMonad m => Attr -> RST m Doc imageDimsToRST attr = do   let (ident, _, _) = attr       name = if null ident                 then empty                 else ":name: " <> text ident       showDim dir = let cols d = ":" <> text (show dir) <> ": " <> text (show d)-                    in  case (dimension dir attr) of+                    in  case dimension dir attr of                           Just (Percent a) ->                             case dir of                               Height -> empty
src/Text/Pandoc/Writers/RTF.hs view
@@ -1,5 +1,6 @@+{-# LANGUAGE ScopedTypeVariables #-} {--Copyright (C) 2006-2015 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2006-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -18,7 +19,7 @@  {- |    Module      : Text.Pandoc.Writers.RTF-   Copyright   : Copyright (C) 2006-2015 John MacFarlane+   Copyright   : Copyright (C) 2006-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -27,103 +28,124 @@  Conversion of 'Pandoc' documents to RTF (rich text format). -}-module Text.Pandoc.Writers.RTF ( writeRTF, writeRTFWithEmbeddedImages ) where+module Text.Pandoc.Writers.RTF ( writeRTF+                               ) where+import Control.Monad.Except (catchError, throwError)+import qualified Data.ByteString as B+import Data.Char (chr, isDigit, ord)+import Data.List (intercalate, isSuffixOf)+import qualified Data.Map as M+import Data.Text (Text)+import qualified Data.Text as T+import Text.Pandoc.Class (PandocMonad, report)+import qualified Text.Pandoc.Class as P import Text.Pandoc.Definition+import Text.Pandoc.Error+import Text.Pandoc.ImageSize+import Text.Pandoc.Logging import Text.Pandoc.Options import Text.Pandoc.Shared-import Text.Pandoc.Writers.Shared-import Text.Pandoc.Readers.TeXMath import Text.Pandoc.Templates (renderTemplate') import Text.Pandoc.Walk-import Data.List ( isSuffixOf, intercalate )-import Data.Char ( ord, chr, isDigit )-import qualified Data.ByteString as B-import qualified Data.Map as M-import Text.Printf ( printf )-import Text.Pandoc.ImageSize+import Text.Pandoc.Writers.Math+import Text.Pandoc.Writers.Shared+import Text.Printf (printf)  -- | Convert Image inlines into a raw RTF embedded image, read from a file, -- or a MediaBag, or the internet. -- If file not found or filetype not jpeg or png, leave the inline unchanged.-rtfEmbedImage :: WriterOptions -> Inline -> IO Inline-rtfEmbedImage opts x@(Image attr _ (src,_)) = do-  result <- fetchItem' (writerMediaBag opts) (writerSourceURL opts) src-  case result of-       Right (imgdata, Just mime)-         | mime == "image/jpeg" || mime == "image/png" -> do-         let bytes = map (printf "%02x") $ B.unpack imgdata-         let filetype = case mime of-                             "image/jpeg" -> "\\jpegblip"-                             "image/png"  -> "\\pngblip"-                             _            -> error "Unknown file type"-         sizeSpec <- case imageSize imgdata of-                             Left msg -> do-                               warn $ "Could not determine image size in `" ++-                                 src ++ "': " ++ msg-                               return ""-                             Right sz -> return $ "\\picw" ++ show xpx ++-                                        "\\pich" ++ show ypx ++-                                        "\\picwgoal" ++ show (floor (xpt * 20) :: Integer)-                                        ++ "\\pichgoal" ++ show (floor (ypt * 20) :: Integer)-                                -- twip = 1/1440in = 1/20pt-                                where (xpx, ypx) = sizeInPixels sz-                                      (xpt, ypt) = desiredSizeInPoints opts attr sz-         let raw = "{\\pict" ++ filetype ++ sizeSpec ++ "\\bin " ++-                    concat bytes ++ "}"-         return $ if B.null imgdata-                     then x-                     else RawInline (Format "rtf") raw-       _ -> return x+rtfEmbedImage :: PandocMonad m => WriterOptions -> Inline -> m Inline+rtfEmbedImage opts x@(Image attr _ (src,_)) = catchError+  (do result <- P.fetchItem src+      case result of+           (imgdata, Just mime)+             | mime == "image/jpeg" || mime == "image/png" -> do+             let bytes = map (printf "%02x") $ B.unpack imgdata+             filetype <-+                case mime of+                     "image/jpeg" -> return "\\jpegblip"+                     "image/png"  -> return "\\pngblip"+                     _            -> throwError $+                                         PandocShouldNeverHappenError $+                                         "Unknown file type " ++ mime+             sizeSpec <-+                case imageSize opts imgdata of+                     Left msg -> do+                       report $ CouldNotDetermineImageSize src msg+                       return ""+                     Right sz -> return $ "\\picw" ++ show xpx +++                                "\\pich" ++ show ypx +++                                "\\picwgoal" ++ show (floor (xpt * 20) :: Integer)+                                ++ "\\pichgoal" ++ show (floor (ypt * 20) :: Integer)+                        -- twip = 1/1440in = 1/20pt+                        where (xpx, ypx) = sizeInPixels sz+                              (xpt, ypt) = desiredSizeInPoints opts attr sz+             let raw = "{\\pict" ++ filetype ++ sizeSpec ++ "\\bin " +++                        concat bytes ++ "}"+             if B.null imgdata+                then do+                  report $ CouldNotFetchResource src "image contained no data"+                  return x+                else return $ RawInline (Format "rtf") raw+             | otherwise -> do+               report $ CouldNotFetchResource src "image is not a jpeg or png"+               return x+           (_, Nothing) -> do+             report $ CouldNotDetermineMimeType src+             return x)+  (\e -> do+     report $ CouldNotFetchResource src (show e)+     return x) rtfEmbedImage _ x = return x --- | Convert Pandoc to a string in rich text format, with--- images embedded as encoded binary data.-writeRTFWithEmbeddedImages :: WriterOptions -> Pandoc -> IO String-writeRTFWithEmbeddedImages options doc =-  writeRTF options `fmap` walkM (rtfEmbedImage options) doc- -- | Convert Pandoc to a string in rich text format.-writeRTF :: WriterOptions -> Pandoc -> String-writeRTF options (Pandoc meta@(Meta metamap) blocks) =+writeRTF :: PandocMonad m => WriterOptions -> Pandoc -> m Text+writeRTF options doc = do+  -- handle images+  Pandoc meta@(Meta metamap) blocks <- walkM (rtfEmbedImage options) doc   let spacer = not $ all null $ docTitle meta : docDate meta : docAuthors meta-      toPlain (MetaBlocks [Para ils]) = MetaInlines ils-      toPlain x = x-      -- adjust title, author, date so we don't get para inside para-      meta'  = Meta $ M.adjust toPlain "title"+  let toPlain (MetaBlocks [Para ils]) = MetaInlines ils+      toPlain x                       = x+  -- adjust title, author, date so we don't get para inside para+  let meta'  = Meta $ M.adjust toPlain "title"                     . M.adjust toPlain "author"                     . M.adjust toPlain "date"                     $ metamap-      Just metadata = metaToJSON options-              (Just . concatMap (blockToRTF 0 AlignDefault))-              (Just . inlineListToRTF)+  metadata <- metaToJSON options+              (fmap concat . mapM (blockToRTF 0 AlignDefault))+              inlinesToRTF               meta'-      body = concatMap (blockToRTF 0 AlignDefault) blocks-      isTOCHeader (Header lev _ _) = lev <= writerTOCDepth options-      isTOCHeader _ = False-      context = defField "body" body+  body <- blocksToRTF 0 AlignDefault blocks+  let isTOCHeader (Header lev _ _) = lev <= writerTOCDepth options+      isTOCHeader _                = False+  toc <- tableOfContents $ filter isTOCHeader blocks+  let context = defField "body" body               $ defField "spacer" spacer-              $ (if writerTableOfContents options-                    then defField "toc"-                          (tableOfContents $ filter isTOCHeader blocks)-                    else id)-              $ metadata-  in  case writerTemplate options of+              $(if writerTableOfContents options+                   then defField "table-of-contents" toc+                        -- for backwards compatibility,+                        -- we populate toc with the contents+                        -- of the toc rather than a boolean:+                        . defField "toc" toc+                   else id) metadata+  T.pack <$>+      case writerTemplate options of            Just tpl -> renderTemplate' tpl context-           Nothing  -> case reverse body of+           Nothing  -> return $+                       case reverse body of                             ('\n':_) -> body                             _        -> body ++ "\n"  -- | Construct table of contents from list of header blocks.-tableOfContents :: [Block] -> String-tableOfContents headers =-  let contentsTree = hierarchicalize headers-  in  concatMap (blockToRTF 0 AlignDefault) $-      [Header 1 nullAttr [Str "Contents"],-       BulletList (map elementToListItem contentsTree)]+tableOfContents :: PandocMonad m => [Block] -> m String+tableOfContents headers = do+  let contents = map elementToListItem $ hierarchicalize headers+  blocksToRTF 0 AlignDefault+      [Header 1 nullAttr [Str "Contents"], BulletList contents]  elementToListItem :: Element -> [Block] elementToListItem (Blk _) = []-elementToListItem (Sec _ _ _ sectext subsecs) = [Plain sectext] +++elementToListItem (Sec _ _ _ sectext subsecs) = Plain sectext :   if null subsecs      then []      else [BulletList (map elementToListItem subsecs)]@@ -140,11 +162,11 @@                    lower = r + 0xDC00                in enc (chr upper) ++ enc (chr lower) ++ handleUnicode cs           else enc c ++ handleUnicode cs-     else c:(handleUnicode cs)+     else c:handleUnicode cs   where     surrogate x = not (   (0x0000 <= ord x && ord x <= 0xd7ff)                        || (0xe000 <= ord x && ord x <= 0xffff) )-    enc x = '\\':'u':(show (ord x)) ++ "?"+    enc x = '\\':'u':show (ord x) ++ "?"  -- | Escape special characters. escapeSpecial :: String -> String@@ -175,13 +197,13 @@              -> String rtfParSpaced spaceAfter indent firstLineIndent alignment content =   let alignString = case alignment of-                           AlignLeft -> "\\ql "-                           AlignRight -> "\\qr "-                           AlignCenter -> "\\qc "+                           AlignLeft    -> "\\ql "+                           AlignRight   -> "\\qr "+                           AlignCenter  -> "\\qc "                            AlignDefault -> "\\ql "   in  "{\\pard " ++ alignString ++-      "\\f0 \\sa" ++ (show spaceAfter) ++ " \\li" ++ (show indent) ++-      " \\fi" ++ (show firstLineIndent) ++ " " ++ content ++ "\\par}\n"+      "\\f0 \\sa" ++ show spaceAfter ++ " \\li" ++ show indent +++      " \\fi" ++ show firstLineIndent ++ " " ++ content ++ "\\par}\n"  -- | Default paragraph. rtfPar :: Int       -- ^ block indent (in twips)@@ -221,143 +243,181 @@               _ -> orderedListMarkers (start, LowerAlpha, Period)      else orderedListMarkers (start, style, delim) +blocksToRTF :: PandocMonad m+            => Int+            -> Alignment+            -> [Block]+            -> m String+blocksToRTF indent align = fmap concat . mapM (blockToRTF indent align)+ -- | Convert Pandoc block element to RTF.-blockToRTF :: Int       -- ^ indent level+blockToRTF :: PandocMonad m+           => Int       -- ^ indent level            -> Alignment -- ^ alignment            -> Block     -- ^ block to convert-           -> String-blockToRTF _ _ Null = ""+           -> m String+blockToRTF _ _ Null = return "" blockToRTF indent alignment (Div _ bs) =-  concatMap (blockToRTF indent alignment) bs+  blocksToRTF indent alignment bs blockToRTF indent alignment (Plain lst) =-  rtfCompact indent 0 alignment $ inlineListToRTF lst+  rtfCompact indent 0 alignment <$> inlinesToRTF lst blockToRTF indent alignment (Para lst) =-  rtfPar indent 0 alignment $ inlineListToRTF lst+  rtfPar indent 0 alignment <$> inlinesToRTF lst blockToRTF indent alignment (LineBlock lns) =   blockToRTF indent alignment $ linesToPara lns blockToRTF indent alignment (BlockQuote lst) =-  concatMap (blockToRTF (indent + indentIncrement) alignment) lst+  blocksToRTF (indent + indentIncrement) alignment lst blockToRTF indent _ (CodeBlock _ str) =-  rtfPar indent 0 AlignLeft ("\\f1 " ++ (codeStringToRTF str))-blockToRTF _ _ (RawBlock f str)-  | f == Format "rtf" = str-  | otherwise         = ""-blockToRTF indent alignment (BulletList lst) = spaceAtEnd $-  concatMap (listItemToRTF alignment indent (bulletMarker indent)) lst-blockToRTF indent alignment (OrderedList attribs lst) = spaceAtEnd $ concat $-  zipWith (listItemToRTF alignment indent) (orderedMarkers indent attribs) lst-blockToRTF indent alignment (DefinitionList lst) = spaceAtEnd $-  concatMap (definitionListItemToRTF alignment indent) lst-blockToRTF indent _ HorizontalRule =+  return $ rtfPar indent 0 AlignLeft ("\\f1 " ++ codeStringToRTF str)+blockToRTF _ _ b@(RawBlock f str)+  | f == Format "rtf" = return str+  | otherwise         = do+      report $ BlockNotRendered b+      return ""+blockToRTF indent alignment (BulletList lst) = (spaceAtEnd . concat) <$>+  mapM (listItemToRTF alignment indent (bulletMarker indent)) lst+blockToRTF indent alignment (OrderedList attribs lst) =+  (spaceAtEnd . concat) <$>+   mapM (uncurry (listItemToRTF alignment indent))+   (zip (orderedMarkers indent attribs) lst)+blockToRTF indent alignment (DefinitionList lst) = (spaceAtEnd . concat) <$>+  mapM (definitionListItemToRTF alignment indent) lst+blockToRTF indent _ HorizontalRule = return $   rtfPar indent 0 AlignCenter "\\emdash\\emdash\\emdash\\emdash\\emdash"-blockToRTF indent alignment (Header level _ lst) = rtfPar indent 0 alignment $-  "\\b \\fs" ++ (show (40 - (level * 4))) ++ " " ++ inlineListToRTF lst-blockToRTF indent alignment (Table caption aligns sizes headers rows) =-  (if all null headers-      then ""-      else tableRowToRTF True indent aligns sizes headers) ++-  concatMap (tableRowToRTF False indent aligns sizes) rows ++-  rtfPar indent 0 alignment (inlineListToRTF caption)+blockToRTF indent alignment (Header level _ lst) = do+  contents <- inlinesToRTF lst+  return $ rtfPar indent 0 alignment $+             "\\b \\fs" ++ show (40 - (level * 4)) ++ " " ++ contents+blockToRTF indent alignment (Table caption aligns sizes headers rows) = do+  caption' <- inlinesToRTF caption+  header' <- if all null headers+                then return ""+                else tableRowToRTF True indent aligns sizes headers+  rows' <- concat <$> mapM (tableRowToRTF False indent aligns sizes) rows+  return $ header' ++ rows' ++ rtfPar indent 0 alignment caption' -tableRowToRTF :: Bool -> Int -> [Alignment] -> [Double] -> [[Block]] -> String-tableRowToRTF header indent aligns sizes' cols =+tableRowToRTF :: PandocMonad m+              => Bool -> Int -> [Alignment] -> [Double] -> [[Block]] -> m String+tableRowToRTF header indent aligns sizes' cols = do   let totalTwips = 6 * 1440 -- 6 inches-      sizes = if all (== 0) sizes'-                 then take (length cols) $ repeat (1.0 / fromIntegral (length cols))+  let sizes = if all (== 0) sizes'+                 then replicate (length cols) (1.0 / fromIntegral (length cols))                  else sizes'-      columns = concat $ zipWith (tableItemToRTF indent) aligns cols-      rightEdges = tail $ scanl (\sofar new -> sofar + floor (new * totalTwips))+  columns <- concat <$> mapM (uncurry (tableItemToRTF indent))+                         (zip aligns cols)+  let rightEdges = tail $ scanl (\sofar new -> sofar + floor (new * totalTwips))                                 (0 :: Integer) sizes-      cellDefs = map (\edge -> (if header+  let cellDefs = map (\edge -> (if header                                    then "\\clbrdrb\\brdrs"                                    else "") ++ "\\cellx" ++ show edge)                      rightEdges-      start = "{\n\\trowd \\trgaph120\n" ++ concat cellDefs ++ "\n" +++  let start = "{\n\\trowd \\trgaph120\n" ++ concat cellDefs ++ "\n" ++               "\\trkeep\\intbl\n{\n"-      end = "}\n\\intbl\\row}\n"-  in  start ++ columns ++ end+  let end = "}\n\\intbl\\row}\n"+  return $ start ++ columns ++ end -tableItemToRTF :: Int -> Alignment -> [Block] -> String-tableItemToRTF indent alignment item =-  let contents = concatMap (blockToRTF indent alignment) item-  in  "{" ++ substitute "\\pard" "\\pard\\intbl" contents ++ "\\cell}\n"+tableItemToRTF :: PandocMonad m => Int -> Alignment -> [Block] -> m String+tableItemToRTF indent alignment item = do+  contents <- blocksToRTF indent alignment item+  return $ "{" ++ substitute "\\pard" "\\pard\\intbl" contents ++ "\\cell}\n"  -- | Ensure that there's the same amount of space after compact -- lists as after regular lists. spaceAtEnd :: String -> String spaceAtEnd str =-  if isSuffixOf "\\par}\n" str-     then (take ((length str) - 6) str) ++ "\\sa180\\par}\n"+  if "\\par}\n" `isSuffixOf` str+     then take ((length str) - 6) str ++ "\\sa180\\par}\n"      else str  -- | Convert list item (list of blocks) to RTF.-listItemToRTF :: Alignment  -- ^ alignment+listItemToRTF :: PandocMonad m+              => Alignment  -- ^ alignment               -> Int        -- ^ indent level               -> String     -- ^ list start marker               -> [Block]    -- ^ list item (list of blocks)-              -> [Char]-listItemToRTF alignment indent marker [] =-  rtfCompact (indent + listIncrement) (0 - listIncrement) alignment-             (marker ++ "\\tx" ++ (show listIncrement) ++ "\\tab ")-listItemToRTF alignment indent marker list =-  let (first:rest) = map (blockToRTF (indent + listIncrement) alignment) list-      listMarker = "\\fi" ++ show (0 - listIncrement) ++ " " ++ marker ++ "\\tx" ++-                      show listIncrement ++ "\\tab"-      insertListMarker ('\\':'f':'i':'-':d:xs) | isDigit d =+              -> m String+listItemToRTF alignment indent marker [] = return $+  rtfCompact (indent + listIncrement) (negate listIncrement) alignment+             (marker ++ "\\tx" ++ show listIncrement ++ "\\tab ")+listItemToRTF alignment indent marker list = do+  (first:rest) <- mapM (blockToRTF (indent + listIncrement) alignment) list+  let listMarker = "\\fi" ++ show (negate listIncrement) ++ " " ++ marker +++                   "\\tx" ++ show listIncrement ++ "\\tab"+  let insertListMarker ('\\':'f':'i':'-':d:xs) | isDigit d =         listMarker ++ dropWhile isDigit xs       insertListMarker ('\\':'f':'i':d:xs) | isDigit d =         listMarker ++ dropWhile isDigit xs       insertListMarker (x:xs) =         x : insertListMarker xs       insertListMarker [] = []-      -- insert the list marker into the (processed) first block-  in  insertListMarker first ++ concat rest+   -- insert the list marker into the (processed) first block+  return $ insertListMarker first ++ concat rest  -- | Convert definition list item (label, list of blocks) to RTF.-definitionListItemToRTF :: Alignment          -- ^ alignment+definitionListItemToRTF :: PandocMonad m+                        => Alignment          -- ^ alignment                         -> Int                -- ^ indent level                         -> ([Inline],[[Block]]) -- ^ list item (list of blocks)-                        -> [Char]-definitionListItemToRTF alignment indent (label, defs) =-  let labelText = blockToRTF indent alignment (Plain label)-      itemsText = concatMap (blockToRTF (indent + listIncrement) alignment) $-                    concat defs-  in  labelText ++ itemsText+                        -> m String+definitionListItemToRTF alignment indent (label, defs) = do+  labelText <- blockToRTF indent alignment (Plain label)+  itemsText <- blocksToRTF (indent + listIncrement) alignment (concat defs)+  return $ labelText ++ itemsText  -- | Convert list of inline items to RTF.-inlineListToRTF :: [Inline]   -- ^ list of inlines to convert-                -> String-inlineListToRTF lst = concatMap inlineToRTF lst+inlinesToRTF :: PandocMonad m+             => [Inline]   -- ^ list of inlines to convert+             -> m String+inlinesToRTF lst = concat <$> mapM inlineToRTF lst  -- | Convert inline item to RTF.-inlineToRTF :: Inline         -- ^ inline to convert-            -> String-inlineToRTF (Span _ lst) = inlineListToRTF lst-inlineToRTF (Emph lst) = "{\\i " ++ (inlineListToRTF lst) ++ "}"-inlineToRTF (Strong lst) = "{\\b " ++ (inlineListToRTF lst) ++ "}"-inlineToRTF (Strikeout lst) = "{\\strike " ++ (inlineListToRTF lst) ++ "}"-inlineToRTF (Superscript lst) = "{\\super " ++ (inlineListToRTF lst) ++ "}"-inlineToRTF (Subscript lst) = "{\\sub " ++ (inlineListToRTF lst) ++ "}"-inlineToRTF (SmallCaps lst) = "{\\scaps " ++ (inlineListToRTF lst) ++ "}"-inlineToRTF (Quoted SingleQuote lst) =-  "\\u8216'" ++ (inlineListToRTF lst) ++ "\\u8217'"-inlineToRTF (Quoted DoubleQuote lst) =-  "\\u8220\"" ++ (inlineListToRTF lst) ++ "\\u8221\""-inlineToRTF (Code _ str) = "{\\f1 " ++ (codeStringToRTF str) ++ "}"-inlineToRTF (Str str) = stringToRTF str-inlineToRTF (Math t str) = inlineListToRTF $ texMathToInlines t str-inlineToRTF (Cite _ lst) = inlineListToRTF lst-inlineToRTF (RawInline f str)-  | f == Format "rtf" = str-  | otherwise         = ""-inlineToRTF (LineBreak) = "\\line "-inlineToRTF SoftBreak = " "-inlineToRTF Space = " "-inlineToRTF (Link _ text (src, _)) =-  "{\\field{\\*\\fldinst{HYPERLINK \"" ++ (codeStringToRTF src) ++-  "\"}}{\\fldrslt{\\ul\n" ++ (inlineListToRTF text) ++ "\n}}}\n"+inlineToRTF :: PandocMonad m+            => Inline         -- ^ inline to convert+            -> m String+inlineToRTF (Span _ lst) = inlinesToRTF lst+inlineToRTF (Emph lst) = do+  contents <- inlinesToRTF lst+  return $ "{\\i " ++ contents ++ "}"+inlineToRTF (Strong lst) = do+  contents <- inlinesToRTF lst+  return $ "{\\b " ++ contents ++ "}"+inlineToRTF (Strikeout lst) = do+  contents <- inlinesToRTF lst+  return $ "{\\strike " ++ contents ++ "}"+inlineToRTF (Superscript lst) = do+  contents <- inlinesToRTF lst+  return $ "{\\super " ++ contents ++ "}"+inlineToRTF (Subscript lst) = do+  contents <- inlinesToRTF lst+  return $ "{\\sub " ++ contents ++ "}"+inlineToRTF (SmallCaps lst) = do+  contents <- inlinesToRTF lst+  return $ "{\\scaps " ++ contents ++ "}"+inlineToRTF (Quoted SingleQuote lst) = do+  contents <- inlinesToRTF lst+  return $ "\\u8216'" ++ contents ++ "\\u8217'"+inlineToRTF (Quoted DoubleQuote lst) = do+  contents <- inlinesToRTF lst+  return $ "\\u8220\"" ++ contents ++ "\\u8221\""+inlineToRTF (Code _ str) = return $ "{\\f1 " ++ codeStringToRTF str ++ "}"+inlineToRTF (Str str) = return $ stringToRTF str+inlineToRTF (Math t str) = texMathToInlines t str >>= inlinesToRTF+inlineToRTF (Cite _ lst) = inlinesToRTF lst+inlineToRTF il@(RawInline f str)+  | f == Format "rtf" = return str+  | otherwise         = do+      return $ InlineNotRendered il+      return ""+inlineToRTF LineBreak = return "\\line "+inlineToRTF SoftBreak = return " "+inlineToRTF Space = return " "+inlineToRTF (Link _ text (src, _)) = do+  contents <- inlinesToRTF text+  return $ "{\\field{\\*\\fldinst{HYPERLINK \"" ++ codeStringToRTF src +++    "\"}}{\\fldrslt{\\ul\n" ++ contents ++ "\n}}}\n" inlineToRTF (Image _ _ (source, _)) =-  "{\\cf1 [image: " ++ source ++ "]\\cf0}"-inlineToRTF (Note contents) =-  "{\\super\\chftn}{\\*\\footnote\\chftn\\~\\plain\\pard " ++-  (concatMap (blockToRTF 0 AlignDefault) contents) ++ "}"+  return $ "{\\cf1 [image: " ++ source ++ "]\\cf0}"+inlineToRTF (Note contents) = do+  body <- concat <$> mapM (blockToRTF 0 AlignDefault) contents+  return $ "{\\super\\chftn}{\\*\\footnote\\chftn\\~\\plain\\pard " +++    body ++ "}"
src/Text/Pandoc/Writers/Shared.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE OverloadedStrings #-} {--Copyright (C) 2013-2015 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2013-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -19,7 +19,7 @@  {- |    Module      : Text.Pandoc.Writers.Shared-   Copyright   : Copyright (C) 2013-2015 John MacFarlane+   Copyright   : Copyright (C) 2013-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -30,62 +30,89 @@ -} module Text.Pandoc.Writers.Shared (                        metaToJSON+                     , metaToJSON'+                     , addVariablesToJSON                      , getField                      , setField+                     , resetField                      , defField                      , tagWithAttrs                      , fixDisplayMath+                     , unsmartify+                     , gridTable                      ) where-import Text.Pandoc.Definition-import Text.Pandoc.Pretty-import Text.Pandoc.XML (escapeStringForXML)-import Control.Monad (liftM)-import Text.Pandoc.Options (WriterOptions(..))+import Control.Monad (zipWithM)+import Data.Aeson (FromJSON (..), Result (..), ToJSON (..), Value (Object),+                   encode, fromJSON) import qualified Data.HashMap.Strict as H+import Data.List (groupBy, intersperse, transpose) import qualified Data.Map as M+import Data.Maybe (isJust) import qualified Data.Text as T-import Data.Aeson (FromJSON(..), fromJSON, ToJSON (..), Value(Object), Result(..), encode)-import Text.Pandoc.UTF8 (toStringLazy) import qualified Data.Traversable as Traversable-import Data.List ( groupBy )-import Data.Maybe ( isJust )+import qualified Text.Pandoc.Builder as Builder+import Text.Pandoc.Definition+import Text.Pandoc.Options+import Text.Pandoc.Pretty+import Text.Pandoc.UTF8 (toStringLazy)+import Text.Pandoc.XML (escapeStringForXML)  -- | Create JSON value for template from a 'Meta' and an association list -- of variables, specified at the command line or in the writer. -- Variables overwrite metadata fields with the same names. -- If multiple variables are set with the same name, a list is--- assigned.-metaToJSON :: Monad m+-- assigned.  Does nothing if 'writerTemplate' is Nothing.+metaToJSON :: (Functor m, Monad m, ToJSON a)            => WriterOptions-           -> ([Block] -> m String)-           -> ([Inline] -> m String)+           -> ([Block] -> m a)+           -> ([Inline] -> m a)            -> Meta            -> m Value-metaToJSON opts blockWriter inlineWriter (Meta metamap)-  | isJust (writerTemplate opts) = do-    let baseContext = foldl (\acc (x,y) -> setField x y acc) (Object H.empty)-                      $ writerVariables opts-    renderedMap <- Traversable.mapM-                   (metaValueToJSON blockWriter inlineWriter)-                   metamap-    let metadata = M.foldWithKey defField baseContext renderedMap-    return $ defField "meta-json" (toStringLazy $ encode metadata) metadata+metaToJSON opts blockWriter inlineWriter meta+  | isJust (writerTemplate opts) =+    addVariablesToJSON opts <$> metaToJSON' blockWriter inlineWriter meta   | otherwise = return (Object H.empty) -metaValueToJSON :: Monad m-                => ([Block] -> m String)-                -> ([Inline] -> m String)+-- | Like 'metaToJSON', but does not include variables and is+-- not sensitive to 'writerTemplate'.+metaToJSON' :: (Functor m, Monad m, ToJSON a)+           => ([Block] -> m a)+           -> ([Inline] -> m a)+           -> Meta+           -> m Value+metaToJSON' blockWriter inlineWriter (Meta metamap) = do+  renderedMap <- Traversable.mapM+                 (metaValueToJSON blockWriter inlineWriter)+                 metamap+  return $ M.foldrWithKey defField (Object H.empty) renderedMap++-- | Add variables to JSON object, replacing any existing values.+-- Also include @meta-json@, a field containing a string representation+-- of the original JSON object itself, prior to addition of variables.+addVariablesToJSON :: WriterOptions -> Value -> Value+addVariablesToJSON opts metadata =+  foldl (\acc (x,y) -> setField x y acc)+       (defField "meta-json" (toStringLazy $ encode metadata) (Object mempty))+       (writerVariables opts)+    `combineMetadata` metadata+  where combineMetadata (Object o1) (Object o2) = Object $ H.union o1 o2+        combineMetadata x _                     = x++metaValueToJSON :: (Functor m, Monad m, ToJSON a)+                => ([Block] -> m a)+                -> ([Inline] -> m a)                 -> MetaValue                 -> m Value-metaValueToJSON blockWriter inlineWriter (MetaMap metamap) = liftM toJSON $+metaValueToJSON blockWriter inlineWriter (MetaMap metamap) = toJSON <$>   Traversable.mapM (metaValueToJSON blockWriter inlineWriter) metamap-metaValueToJSON blockWriter inlineWriter (MetaList xs) = liftM toJSON $+metaValueToJSON blockWriter inlineWriter (MetaList xs) = toJSON <$>   Traversable.mapM (metaValueToJSON blockWriter inlineWriter) xs metaValueToJSON _ _ (MetaBool b) = return $ toJSON b-metaValueToJSON _ _ (MetaString s) = return $ toJSON s-metaValueToJSON blockWriter _ (MetaBlocks bs) = liftM toJSON $ blockWriter bs-metaValueToJSON _ inlineWriter (MetaInlines bs) = liftM toJSON $ inlineWriter bs+metaValueToJSON _ inlineWriter (MetaString s) = toJSON <$>+  inlineWriter (Builder.toList (Builder.text s))+metaValueToJSON blockWriter _ (MetaBlocks bs) = toJSON <$> blockWriter bs+metaValueToJSON _ inlineWriter (MetaInlines is) = toJSON <$> inlineWriter is  -- | Retrieve a field value from a JSON object. getField :: FromJSON a@@ -111,10 +138,22 @@   Object $ H.insertWith combine (T.pack field) (toJSON val) hashmap   where combine newval oldval =           case fromJSON oldval of-                Success xs  -> toJSON $ xs ++ [newval]-                _           -> toJSON [oldval, newval]+                Success xs -> toJSON $ xs ++ [newval]+                _          -> toJSON [oldval, newval] setField _ _  x = x +resetField :: ToJSON a+           => String+           -> a+           -> Value+           -> Value+-- | Reset a field of a JSON object.  If the field already has a value,+-- the new value replaces it.+-- This is a utility function to be used in preparing template contexts.+resetField field val (Object hashmap) =+  Object $ H.insert (T.pack field) (toJSON val) hashmap+resetField _ _  x = x+ defField :: ToJSON a          => String          -> a@@ -148,9 +187,9 @@  stripLeadingTrailingSpace :: [Inline] -> [Inline] stripLeadingTrailingSpace = go . reverse . go . reverse-  where go (Space:xs) = xs+  where go (Space:xs)     = xs         go (SoftBreak:xs) = xs-        go xs         = xs+        go xs             = xs  -- Put display math in its own block (for ODT/DOCX). fixDisplayMath :: Block -> Block@@ -167,3 +206,99 @@        groupBy (\x y -> (isDisplayMath x && isDisplayMath y) ||                          not (isDisplayMath x || isDisplayMath y)) lst fixDisplayMath x = x++unsmartify :: WriterOptions -> String -> String+unsmartify opts ('\8217':xs) = '\'' : unsmartify opts xs+unsmartify opts ('\8230':xs) = "..." ++ unsmartify opts xs+unsmartify opts ('\8211':xs)+  | isEnabled Ext_old_dashes opts = '-' : unsmartify opts xs+  | otherwise                     = "--" ++ unsmartify opts xs+unsmartify opts ('\8212':xs)+  | isEnabled Ext_old_dashes opts = "--" ++ unsmartify opts xs+  | otherwise                     = "---" ++ unsmartify opts xs+unsmartify opts ('\8220':xs) = '"' : unsmartify opts xs+unsmartify opts ('\8221':xs) = '"' : unsmartify opts xs+unsmartify opts ('\8216':xs) = '\'' : unsmartify opts xs+unsmartify opts (x:xs) = x : unsmartify opts xs+unsmartify _ [] = []++gridTable :: Monad m+          => WriterOptions+          -> (WriterOptions -> [Block] -> m Doc)+          -> Bool -- ^ headless+          -> [Alignment]+          -> [Double]+          -> [[Block]]+          -> [[[Block]]]+          -> m Doc+gridTable opts blocksToDoc headless aligns widths headers rows = do+  let numcols = maximum (length aligns : length widths :+                           map length (headers:rows))+  let handleGivenWidths widths' = do+        let widthsInChars' = map (+                      (\x -> if x < 1 then 1 else x) .+                      (\x -> x - 3) . floor .+                      (fromIntegral (writerColumns opts) *)+                      ) widths'+        rawHeaders' <- zipWithM blocksToDoc+            (map (\w -> opts{writerColumns =+                      min (w - 2) (writerColumns opts)}) widthsInChars')+            headers+        rawRows' <- mapM+             (\cs -> zipWithM blocksToDoc+               (map (\w -> opts{writerColumns =+                         min (w - 2) (writerColumns opts)}) widthsInChars')+               cs)+             rows+        return (widthsInChars', rawHeaders', rawRows')+  let handleZeroWidths = do+        rawHeaders' <- mapM (blocksToDoc opts) headers+        rawRows' <- mapM (mapM (blocksToDoc opts)) rows+        let numChars [] = 0+            numChars xs = maximum . map offset $ xs+        let widthsInChars' =+                map numChars $ transpose (rawHeaders' : rawRows')+        if sum widthsInChars' > writerColumns opts+           then -- use even widths+                handleGivenWidths+                  (replicate numcols (1.0 / fromIntegral numcols) :: [Double])+           else return (widthsInChars', rawHeaders', rawRows')+  (widthsInChars, rawHeaders, rawRows) <- if all (== 0) widths+                                             then handleZeroWidths+                                             else handleGivenWidths widths+  let hpipeBlocks blocks = hcat [beg, middle, end]+        where h       = maximum (1 : map height blocks)+              sep'    = lblock 3 $ vcat (replicate h (text " | "))+              beg     = lblock 2 $ vcat (replicate h (text "| "))+              end     = lblock 2 $ vcat (replicate h (text " |"))+              middle  = chomp $ hcat $ intersperse sep' blocks+  let makeRow = hpipeBlocks . zipWith lblock widthsInChars+  let head' = makeRow rawHeaders+  let rows' = map (makeRow . map chomp) rawRows+  let borderpart ch align widthInChars =+           (if align == AlignLeft || align == AlignCenter+               then char ':'+               else char ch) <>+           text (replicate widthInChars ch) <>+           (if align == AlignRight || align == AlignCenter+               then char ':'+               else char ch)+  let border ch aligns' widthsInChars' =+        char '+' <>+        hcat (intersperse (char '+') (zipWith (borderpart ch)+                aligns' widthsInChars')) <> char '+'+  let body = vcat $ intersperse (border '-' (repeat AlignDefault) widthsInChars)+                    rows'+  let head'' = if headless+                  then empty+                  else head' $$ border '=' aligns widthsInChars+  if headless+     then return $+           border '-' aligns widthsInChars $$+           body $$+           border '-' (repeat AlignDefault) widthsInChars+     else return $+           border '-' (repeat AlignDefault) widthsInChars $$+           head'' $$+           body $$+           border '-' (repeat AlignDefault) widthsInChars
src/Text/Pandoc/Writers/TEI.hs view
@@ -1,6 +1,7 @@-{-# LANGUAGE OverloadedStrings, PatternGuards #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternGuards     #-} {--Copyright (C) 2006-2015 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2006-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -19,7 +20,7 @@  {- |    Module      : Text.Pandoc.Writers.Docbook-   Copyright   : Copyright (C) 2006-2015 John MacFarlane+   Copyright   : Copyright (C) 2006-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -29,63 +30,67 @@ Conversion of 'Pandoc' documents to Docbook XML. -} module Text.Pandoc.Writers.TEI (writeTEI) where+import Data.Char (toLower)+import Data.List (isPrefixOf, stripPrefix)+import Data.Text (Text)+import qualified Text.Pandoc.Builder as B+import Text.Pandoc.Class (PandocMonad, report) import Text.Pandoc.Definition-import Text.Pandoc.XML-import Text.Pandoc.Shared-import Text.Pandoc.Writers.Shared+import Text.Pandoc.Highlighting (languages, languagesByExtension)+import Text.Pandoc.ImageSize+import Text.Pandoc.Logging import Text.Pandoc.Options-import Text.Pandoc.Templates (renderTemplate')-import Data.List ( stripPrefix, isPrefixOf )-import Data.Char ( toLower )-import Text.Pandoc.Highlighting ( languages, languagesByExtension ) import Text.Pandoc.Pretty-import Text.Pandoc.ImageSize-import qualified Text.Pandoc.Builder as B+import Text.Pandoc.Shared+import Text.Pandoc.Templates (renderTemplate')+import Text.Pandoc.Writers.Shared+import Text.Pandoc.XML  -- | Convert list of authors to a docbook <author> section-authorToTEI :: WriterOptions -> [Inline] -> B.Inlines-authorToTEI opts name' =-  let name = render Nothing $ inlinesToTEI opts name'-      colwidth = if writerWrapText opts == WrapAuto+authorToTEI :: PandocMonad m => WriterOptions -> [Inline] -> m B.Inlines+authorToTEI opts name' = do+  name <- render Nothing <$> inlinesToTEI opts name'+  let colwidth = if writerWrapText opts == WrapAuto                     then Just $ writerColumns opts                     else Nothing-  in  B.rawInline "tei" $ render colwidth $+  return $ B.rawInline "tei" $ render colwidth $       inTagsSimple "author" (text $ escapeStringForXML name)  -- | Convert Pandoc document to string in Docbook format.-writeTEI :: WriterOptions -> Pandoc -> String-writeTEI opts (Pandoc meta blocks) =+writeTEI :: PandocMonad m => WriterOptions -> Pandoc -> m Text+writeTEI opts (Pandoc meta blocks) = do   let elements = hierarchicalize blocks       colwidth = if writerWrapText opts == WrapAuto                     then Just $ writerColumns opts                     else Nothing+      render' :: Doc -> Text       render' = render colwidth       startLvl = case writerTopLevelDivision opts of                    TopLevelPart    -> -1                    TopLevelChapter -> 0                    TopLevelSection -> 1                    TopLevelDefault -> 1-      auths'   = map (authorToTEI opts) $ docAuthors meta-      meta'    = B.setMeta "author" auths' meta-      Just metadata = metaToJSON opts-                 (Just . render colwidth . (vcat .-                          (map (elementToTEI opts startLvl)) . hierarchicalize))-                 (Just . render colwidth . inlinesToTEI opts)+  auths'      <- mapM (authorToTEI opts) $ docAuthors meta+  let meta'    = B.setMeta "author" auths' meta+  metadata <- metaToJSON opts+                 (fmap (render' . vcat) .+                   mapM (elementToTEI opts startLvl) . hierarchicalize)+                 (fmap render' . inlinesToTEI opts)                  meta'-      main    = render' $ vcat (map (elementToTEI opts startLvl) elements)-      context = defField "body" main-              $ defField "mathml" (case writerHTMLMathMethod opts of-                                        MathML _ -> True-                                        _        -> False)-              $ metadata-  in  case writerTemplate opts of-           Nothing  -> main-           Just tpl -> renderTemplate' tpl context+  main    <- (render' . vcat) <$> mapM (elementToTEI opts startLvl) elements+  let context = defField "body" main+              $+                  defField "mathml" (case writerHTMLMathMethod opts of+                                          MathML -> True+                                          _      -> False) metadata+  case writerTemplate opts of+       Nothing  -> return main+       Just tpl -> renderTemplate' tpl context  -- | Convert an Element to TEI.-elementToTEI :: WriterOptions -> Int -> Element -> Doc+elementToTEI :: PandocMonad m => WriterOptions -> Int -> Element -> m Doc elementToTEI opts _   (Blk block) = blockToTEI opts block-elementToTEI opts lvl (Sec _ _num (id',_,_) title elements) =+elementToTEI opts lvl (Sec _ _num (id',_,_) title elements) = do   -- TEI doesn't allow sections with no content, so insert some if needed   let elements' = if null elements                     then [Blk (Para [])]@@ -96,14 +101,15 @@                    | n == 0           -> "chapter"                    | n >= 1 && n <= 5 -> "level" ++ show n                    | otherwise        -> "section"-  in inTags True "div" [("type", divType) | not (null id')] $---                        ("id", writerIdentifierPrefix opts ++ id') | not (null id')] $-      inTagsSimple "head" (inlinesToTEI opts title) $$-      vcat (map (elementToTEI opts (lvl + 1)) elements')+  contents <- vcat <$> mapM (elementToTEI opts (lvl + 1)) elements'+  titleContents <- inlinesToTEI opts title+  return $ inTags True "div" (("type", divType) :+    [("id", writerIdentifierPrefix opts ++ id') | not (null id')]) $+      inTagsSimple "head" titleContents $$ contents  -- | Convert a list of Pandoc blocks to TEI.-blocksToTEI :: WriterOptions -> [Block] -> Doc-blocksToTEI opts = vcat . map (blockToTEI opts)+blocksToTEI :: PandocMonad m => WriterOptions -> [Block] -> m Doc+blocksToTEI opts bs = vcat <$> mapM (blockToTEI opts) bs  -- | Auxiliary function to convert Plain block to Para. plainToPara :: Block -> Block@@ -112,48 +118,54 @@  -- | Convert a list of pairs of terms and definitions into a TEI -- list with labels and items.-deflistItemsToTEI :: WriterOptions -> [([Inline],[[Block]])] -> Doc+deflistItemsToTEI :: PandocMonad m+                  => WriterOptions -> [([Inline],[[Block]])] -> m Doc deflistItemsToTEI opts items =- vcat $ map (\(term, defs) -> deflistItemToTEI opts term defs) items+ vcat <$> mapM (uncurry (deflistItemToTEI opts)) items  -- | Convert a term and a list of blocks into a TEI varlistentry.-deflistItemToTEI :: WriterOptions -> [Inline] -> [[Block]] -> Doc-deflistItemToTEI opts term defs =-  let def' = concatMap (map plainToPara) defs-  in  inTagsIndented "label" (inlinesToTEI opts term) $$-      inTagsIndented "item" (blocksToTEI opts def')+deflistItemToTEI :: PandocMonad m+                 => WriterOptions -> [Inline] -> [[Block]] -> m Doc+deflistItemToTEI opts term defs = do+  term' <- inlinesToTEI opts term+  defs' <- blocksToTEI opts $ concatMap (map plainToPara) defs+  return $ inTagsIndented "label" term' $$+           inTagsIndented "item" defs'  -- | Convert a list of lists of blocks to a list of TEI list items.-listItemsToTEI :: WriterOptions -> [[Block]] -> Doc-listItemsToTEI opts items = vcat $ map (listItemToTEI opts) items+listItemsToTEI :: PandocMonad m => WriterOptions -> [[Block]] -> m Doc+listItemsToTEI opts items = vcat <$> mapM (listItemToTEI opts) items  -- | Convert a list of blocks into a TEI list item.-listItemToTEI :: WriterOptions -> [Block] -> Doc+listItemToTEI :: PandocMonad m => WriterOptions -> [Block] -> m Doc listItemToTEI opts item =-  inTagsIndented "item" $ blocksToTEI opts $ map plainToPara item+  inTagsIndented "item" <$> blocksToTEI opts (map plainToPara item) -imageToTEI :: WriterOptions -> Attr -> String -> Doc-imageToTEI _ attr src = selfClosingTag "graphic" $+imageToTEI :: PandocMonad m => WriterOptions -> Attr -> String -> m Doc+imageToTEI _ attr src = return $ selfClosingTag "graphic" $   ("url", src) : idAndRole attr ++ dims   where     dims = go Width "width" ++ go Height "depth"-    go dir dstr = case (dimension dir attr) of+    go dir dstr = case dimension dir attr of                     Just a  -> [(dstr, show a)]                     Nothing -> []  -- | Convert a Pandoc block element to TEI.-blockToTEI :: WriterOptions -> Block -> Doc-blockToTEI _ Null = empty+blockToTEI :: PandocMonad m => WriterOptions -> Block -> m Doc+blockToTEI _ Null = return empty -- Add ids to paragraphs in divs with ids - this is needed for -- pandoc-citeproc to get link anchors in bibliographies:-blockToTEI opts (Div (ident,_,_) [Para lst]) =-  let attribs = [("id", ident) | not (null ident)] in-      inTags False "p" attribs $ inlinesToTEI opts lst+blockToTEI opts (Div (ident,_,_) [Para lst]) = do+  let attribs = [("id", ident) | not (null ident)]+  inTags False "p" attribs <$> inlinesToTEI opts lst blockToTEI opts (Div _ bs) = blocksToTEI opts $ map plainToPara bs-blockToTEI _ (Header _ _ _) = empty -- should not occur after hierarchicalize+blockToTEI _ h@(Header{}) = do+  -- should not occur after hierarchicalize, except inside lists/blockquotes+  report $ BlockNotRendered h+  return empty -- For TEI simple, text must be within containing block element, so--- we use plainToPara to ensure that Plain text ends up contained by--- something.+-- we use treat as Para to ensure that Plain text ends up contained by+-- something: blockToTEI opts (Plain lst) = blockToTEI opts $ Para lst -- title beginning with fig: indicates that the image is a figure --blockToTEI opts (Para [Image attr txt (src,'f':'i':'g':':':_)]) =@@ -168,13 +180,13 @@ --             (imageToTEI opts attr src)) $$ --           inTagsSimple "textobject" (inTagsSimple "phrase" alt)) blockToTEI opts (Para lst) =-  inTags False "p" [] $ inlinesToTEI opts lst+  inTags False "p" [] <$> inlinesToTEI opts lst blockToTEI opts (LineBlock lns) =   blockToTEI opts $ linesToPara lns blockToTEI opts (BlockQuote blocks) =-  inTagsIndented "quote" $ blocksToTEI opts blocks+  inTagsIndented "quote" <$> blocksToTEI opts blocks blockToTEI _ (CodeBlock (_,classes,_) str) =-  text ("<ab type='codeblock " ++ lang ++ "'>") <> cr <>+  return $ text ("<ab type='codeblock " ++ lang ++ "'>") <> cr <>      flush (text (escapeStringForXML str) <> cr <> text "</ab>")     where lang  = if null langs                      then ""@@ -184,11 +196,11 @@                            then [s]                            else languagesByExtension . map toLower $ s           langs       = concatMap langsFrom classes-blockToTEI opts (BulletList lst) =+blockToTEI opts (BulletList lst) = do   let attribs = [("type", "unordered")]-  in  inTags True "list" attribs $ listItemsToTEI opts lst-blockToTEI _ (OrderedList _ []) = empty-blockToTEI opts (OrderedList (start, numstyle, _) (first:rest)) =+  inTags True "list" attribs <$> listItemsToTEI opts lst+blockToTEI _ (OrderedList _ []) = return empty+blockToTEI opts (OrderedList (start, numstyle, _) (first:rest)) = do   let attribs = case numstyle of                        DefaultStyle -> []                        Decimal      -> [("type", "ordered:arabic")]@@ -197,120 +209,133 @@                        LowerAlpha   -> [("type", "ordered:loweralpha")]                        UpperRoman   -> [("type", "ordered:upperroman")]                        LowerRoman   -> [("type", "ordered:lowerroman")]-      items      = if start == 1-                      then listItemsToTEI opts (first:rest)-                      else (inTags True "item" [("n",show start)]-                           (blocksToTEI opts $ map plainToPara first)) $$-                           listItemsToTEI opts rest-  in  inTags True "list" attribs items-blockToTEI opts (DefinitionList lst) =+  items <- if start == 1+              then listItemsToTEI opts (first:rest)+              else do+                fi <- blocksToTEI opts $ map plainToPara first+                re <- listItemsToTEI opts rest+                return $ inTags True "item" [("n",show start)] fi $$ re+  return $ inTags True "list" attribs items+blockToTEI opts (DefinitionList lst) = do   let attribs = [("type", "definition")]-  in  inTags True "list" attribs $ deflistItemsToTEI opts lst-blockToTEI _ (RawBlock f str)-  | f == "tei"     = text str -- raw TEI block (should such a thing exist).---  | f == "html"    = text str -- allow html for backwards compatibility-  | otherwise      = empty-blockToTEI _ HorizontalRule =-  selfClosingTag "milestone" [("unit","undefined"), ("type","separator"),("rendition","line")]+  inTags True "list" attribs <$> deflistItemsToTEI opts lst+blockToTEI _ b@(RawBlock f str)+  | f == "tei"     = return $ text str+  -- raw TEI block (should such a thing exist).+  | otherwise      = do+    report $ BlockNotRendered b+    return empty+blockToTEI _ HorizontalRule = return $+  selfClosingTag "milestone" [("unit","undefined")+                             ,("type","separator")+                             ,("rendition","line")]  -- | TEI Tables -- TEI Simple's tables are composed of cells and rows; other -- table info in the AST is here lossily discard.-blockToTEI opts (Table _ _ _ headers rows) =-  let-    headers' = tableHeadersToTEI opts headers---    headers' = if all null headers---               then return empty---               else tableRowToTEI opts headers-  in-    inTags True "table" [] $-    vcat $ [headers'] <> map (tableRowToTEI opts) rows+blockToTEI opts (Table _ _ _ headers rows) = do+  headers' <- tableHeadersToTEI opts headers+  rows' <- mapM (tableRowToTEI opts) rows+  return $ inTags True "table" [] $ headers' $$ vcat rows' -tableRowToTEI :: WriterOptions-                  -> [[Block]]-                  -> Doc+tableRowToTEI :: PandocMonad m+              => WriterOptions+              -> [[Block]]+              -> m Doc tableRowToTEI opts cols =-  inTagsIndented "row" $ vcat $ map (tableItemToTEI opts) cols+  (inTagsIndented "row" . vcat) <$> mapM (tableItemToTEI opts) cols -tableHeadersToTEI :: WriterOptions+tableHeadersToTEI :: PandocMonad m+                  => WriterOptions                   -> [[Block]]-                  -> Doc+                  -> m Doc tableHeadersToTEI opts cols =-  inTags True "row" [("role","label")] $ vcat $ map (tableItemToTEI opts) cols+  (inTags True "row" [("role","label")] . vcat) <$>+    mapM (tableItemToTEI opts) cols -tableItemToTEI :: WriterOptions-                  -> [Block]-                  -> Doc+tableItemToTEI :: PandocMonad m+               => WriterOptions+               -> [Block]+               -> m Doc tableItemToTEI opts item =-  inTags False "cell" [] $ vcat $ map (blockToTEI opts) item+  (inTags False "cell" [] . vcat) <$> mapM (blockToTEI opts) item  -- | Convert a list of inline elements to TEI.-inlinesToTEI :: WriterOptions -> [Inline] -> Doc-inlinesToTEI opts lst = hcat $ map (inlineToTEI opts) lst+inlinesToTEI :: PandocMonad m => WriterOptions -> [Inline] -> m Doc+inlinesToTEI opts lst = hcat <$> mapM (inlineToTEI opts) lst  -- | Convert an inline element to TEI.-inlineToTEI :: WriterOptions -> Inline -> Doc-inlineToTEI _ (Str str) = text $ escapeStringForXML str+inlineToTEI :: PandocMonad m => WriterOptions -> Inline -> m Doc+inlineToTEI _ (Str str) = return $ text $ escapeStringForXML str inlineToTEI opts (Emph lst) =-  inTags False "hi" [("rendition","simple:italic")] $ inlinesToTEI opts lst+  inTags False "hi" [("rendition","simple:italic")] <$> inlinesToTEI opts lst inlineToTEI opts (Strong lst) =-  inTags False "hi" [("rendition", "simple:bold")] $ inlinesToTEI opts lst+  inTags False "hi" [("rendition", "simple:bold")] <$> inlinesToTEI opts lst inlineToTEI opts (Strikeout lst) =-  inTags False "hi" [("rendition", "simple:strikethrough")] $+  inTags False "hi" [("rendition", "simple:strikethrough")] <$>   inlinesToTEI opts lst inlineToTEI opts (Superscript lst) =-  inTags False "hi" [("rendition", "simple:superscript")] $ inlinesToTEI opts lst+  inTags False "hi" [("rendition", "simple:superscript")] <$>+    inlinesToTEI opts lst inlineToTEI opts (Subscript lst) =-  inTags False "hi" [("rendition", "simple:subscript")] $ inlinesToTEI opts lst+  inTags False "hi" [("rendition", "simple:subscript")] <$>+    inlinesToTEI opts lst inlineToTEI opts (SmallCaps lst) =-  inTags False "hi" [("rendition", "simple:smallcaps")] $-  inlinesToTEI opts lst+  inTags False "hi" [("rendition", "simple:smallcaps")] <$>+    inlinesToTEI opts lst inlineToTEI opts (Quoted _ lst) =-  inTagsSimple "quote" $ inlinesToTEI opts lst+  inTagsSimple "quote" <$> inlinesToTEI opts lst inlineToTEI opts (Cite _ lst) =   inlinesToTEI opts lst inlineToTEI opts (Span _ ils) =   inlinesToTEI opts ils-inlineToTEI _ (Code _ str) =+inlineToTEI _ (Code _ str) = return $   inTags False "seg" [("type","code")] $ text (escapeStringForXML str) -- Distinguish display from inline math by wrapping the former in a "figure."-inlineToTEI _ (Math t str) =+inlineToTEI _ (Math t str) = return $   case t of     InlineMath  -> inTags False "formula" [("notation","TeX")] $-                   text (str)+                   text str     DisplayMath -> inTags True "figure" [("type","math")] $-                   inTags False "formula" [("notation","TeX")] $ text (str)+                   inTags False "formula" [("notation","TeX")] $ text str -inlineToTEI _ (RawInline f x) | f == "tei"     = text x-                              | otherwise      = empty-inlineToTEI _ LineBreak = selfClosingTag "lb" []-inlineToTEI _ Space = space+inlineToTEI _ il@(RawInline f x) | f == "tei"     = return $ text x+                                 | otherwise      = empty <$+                                     report (InlineNotRendered il)+inlineToTEI _ LineBreak = return $ selfClosingTag "lb" []+inlineToTEI _ Space =+            return space -- because we use \n for LineBreak, we can't do soft breaks:-inlineToTEI _ SoftBreak = space+inlineToTEI _ SoftBreak =+            return space inlineToTEI opts (Link attr txt (src, _))-  | Just email <- stripPrefix "mailto:" src =+  | Just email <- stripPrefix "mailto:" src = do       let emailLink = text $-                      escapeStringForXML $ email-      in  case txt of-           [Str s] | escapeURI s == email -> emailLink-           _             -> inlinesToTEI opts txt <+>-                              char '(' <> emailLink <> char ')'+                      escapeStringForXML email+      case txt of+           [Str s] | escapeURI s == email ->+                       return emailLink+           _             -> do+              linktext <- inlinesToTEI opts txt+              return $ linktext <+> char '(' <> emailLink <> char ')'   | otherwise =-      (if isPrefixOf "#" src+      (if "#" `isPrefixOf` src             then inTags False "ref" $ ("target", drop 1 src) : idAndRole attr-            else inTags False "ref" $ ("target", src) : idAndRole attr ) $+            else inTags False "ref" $ ("target", src) : idAndRole attr ) <$>         inlinesToTEI opts txt-inlineToTEI opts (Image attr description (src, tit)) =+inlineToTEI opts (Image attr description (src, tit)) = do   let titleDoc = if null tit                    then empty-                   else inTags False "figDesc" [] (text $ escapeStringForXML tit)-      imageDesc = if null description-                  then empty-                  else inTags False "head" [] (inlinesToTEI opts description)-  in  inTagsIndented "figure" $ imageDesc $$-      imageToTEI opts attr src $$ titleDoc+                   else inTags False "figDesc" []+                           (text $ escapeStringForXML tit)+  imageDesc <- if null description+                  then return empty+                  else inTags False "head" []+                         <$> inlinesToTEI opts description+  img <- imageToTEI opts attr src+  return $ inTagsIndented "figure" $ imageDesc $$ img $$ titleDoc inlineToTEI opts (Note contents) =-  inTagsIndented "note" $ blocksToTEI opts contents+  inTagsIndented "note" <$> blocksToTEI opts contents  idAndRole :: Attr -> [(String, String)] idAndRole (id',cls,_) = ident ++ role
src/Text/Pandoc/Writers/Texinfo.hs view
@@ -1,6 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {--Copyright (C) 2008-2015 John MacFarlane and Peter Wang+Copyright (C) 2008-2017 John MacFarlane+              2012 Peter Wang  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -19,7 +20,8 @@  {- |    Module      : Text.Pandoc.Writers.Texinfo-   Copyright   : Copyright (C) 2008-2015 John MacFarlane and Peter Wang+   Copyright   : Copyright (C) 2008-2017 John MacFarlane+                               2012 Peter Wang    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -29,21 +31,26 @@ Conversion of 'Pandoc' format into Texinfo. -} module Text.Pandoc.Writers.Texinfo ( writeTexinfo ) where+import Control.Monad.Except (throwError)+import Control.Monad.State.Strict+import Data.Char (chr, ord)+import Data.List (maximumBy, transpose)+import Data.Ord (comparing)+import qualified Data.Set as Set+import Data.Text (Text)+import Network.URI (unEscapeString)+import System.FilePath+import Text.Pandoc.Class (PandocMonad, report) import Text.Pandoc.Definition+import Text.Pandoc.Error+import Text.Pandoc.ImageSize+import Text.Pandoc.Logging import Text.Pandoc.Options+import Text.Pandoc.Pretty import Text.Pandoc.Shared-import Text.Pandoc.Writers.Shared import Text.Pandoc.Templates (renderTemplate')-import Text.Printf ( printf )-import Data.List ( transpose, maximumBy )-import Data.Ord ( comparing )-import Data.Char ( chr, ord )-import Control.Monad.State-import Text.Pandoc.Pretty-import Text.Pandoc.ImageSize-import Network.URI ( isURI, unEscapeString )-import System.FilePath-import qualified Data.Set as Set+import Text.Pandoc.Writers.Shared+import Text.Printf (printf)  data WriterState =   WriterState { stStrikeout   :: Bool  -- document contains strikeout@@ -59,10 +66,12 @@  - generated .texi files don't work when run through texi2dvi  -} +type TI m = StateT WriterState m+ -- | Convert Pandoc to Texinfo.-writeTexinfo :: WriterOptions -> Pandoc -> String+writeTexinfo :: PandocMonad m => WriterOptions -> Pandoc -> m Text writeTexinfo options document =-  evalState (pandocToTexinfo options $ wrapTop document) $+  evalStateT (pandocToTexinfo options $ wrapTop document)   WriterState { stStrikeout = False, stSuperscript = False,                 stEscapeComma = False, stSubscript = False,                 stIdentifiers = Set.empty, stOptions = options}@@ -72,16 +81,18 @@ wrapTop (Pandoc meta blocks) =   Pandoc meta (Header 0 nullAttr (docTitle meta) : blocks) -pandocToTexinfo :: WriterOptions -> Pandoc -> State WriterState String+pandocToTexinfo :: PandocMonad m => WriterOptions -> Pandoc -> TI m Text pandocToTexinfo options (Pandoc meta blocks) = do   let titlePage = not $ all null                       $ docTitle meta : docDate meta : docAuthors meta   let colwidth = if writerWrapText options == WrapAuto                     then Just $ writerColumns options                     else Nothing+  let render' :: Doc -> Text+      render' = render colwidth   metadata <- metaToJSON options-              (fmap (render colwidth) . blockListToTexinfo)-              (fmap (render colwidth) . inlineListToTexinfo)+              (fmap render' . blockListToTexinfo)+              (fmap render' . inlineListToTexinfo)               meta   main <- blockListToTexinfo blocks   st <- get@@ -91,11 +102,11 @@               $ defField "titlepage" titlePage               $ defField "subscript" (stSubscript st)               $ defField "superscript" (stSuperscript st)-              $ defField "strikeout" (stStrikeout st)-              $ metadata+              $+        defField "strikeout" (stStrikeout st) metadata   case writerTemplate options of        Nothing  -> return body-       Just tpl -> return $ renderTemplate' tpl context+       Just tpl -> renderTemplate' tpl context  -- | Escape things as needed for Texinfo. stringToTexinfo :: String -> String@@ -110,7 +121,7 @@                          , ('\x2019', "'")                          ] -escapeCommas :: State WriterState Doc -> State WriterState Doc+escapeCommas :: PandocMonad m => TI m Doc -> TI m Doc escapeCommas parser = do   oldEscapeComma <- gets stEscapeComma   modify $ \st -> st{ stEscapeComma = True }@@ -123,8 +134,9 @@ inCmd cmd contents = char '@' <> text cmd <> braces contents  -- | Convert Pandoc block element to Texinfo.-blockToTexinfo :: Block     -- ^ Block to convert-               -> State WriterState Doc+blockToTexinfo :: PandocMonad m+               => Block     -- ^ Block to convert+               -> TI m Doc  blockToTexinfo Null = return empty @@ -154,17 +166,19 @@            contents $$            text "@end quotation" -blockToTexinfo (CodeBlock _ str) = do+blockToTexinfo (CodeBlock _ str) =   return $ blankline $$-           text "@verbatim" $$-           flush (text str) $$-           text "@end verbatim" <> blankline+         text "@verbatim" $$+         flush (text str) $$+         text "@end verbatim" <> blankline -blockToTexinfo (RawBlock f str)+blockToTexinfo b@(RawBlock f str)   | f == "texinfo" = return $ text str   | f == "latex" || f == "tex" =                       return $ text "@tex" $$ text str $$ text "@end tex"-  | otherwise      = return empty+  | otherwise      = do+      report $ BlockNotRendered b+      return empty  blockToTexinfo (BulletList lst) = do   items <- mapM listItemToTexinfo lst@@ -204,7 +218,7 @@              text "@bigskip@hrule@bigskip" $$              text "@end iftex" $$              text "@ifnottex" $$-             text (take 72 $ repeat '-') $$+             text (replicate 72 '-') $$              text "@end ifnottex"  blockToTexinfo (Header 0 _ lst) = do@@ -214,23 +228,27 @@   return $ text "@node Top" $$            text "@top " <> txt <> blankline -blockToTexinfo (Header level _ lst) = do-  node <- inlineListForNode lst-  txt <- inlineListToTexinfo lst-  idsUsed <- gets stIdentifiers-  let id' = uniqueIdent lst idsUsed-  modify $ \st -> st{ stIdentifiers = Set.insert id' idsUsed }-  return $ if (level > 0) && (level <= 4)-              then blankline <> text "@node " <> node $$-                   text (seccmd level) <> txt $$-                   text "@anchor" <> braces (text $ '#':id')-              else txt-  where-    seccmd 1 = "@chapter "-    seccmd 2 = "@section "-    seccmd 3 = "@subsection "-    seccmd 4 = "@subsubsection "-    seccmd _ = error "illegal seccmd level"+blockToTexinfo (Header level _ lst)+  | level < 1 || level > 4 = blockToTexinfo (Para lst)+  | otherwise = do+    node <- inlineListForNode lst+    txt <- inlineListToTexinfo lst+    idsUsed <- gets stIdentifiers+    let id' = uniqueIdent lst idsUsed+    modify $ \st -> st{ stIdentifiers = Set.insert id' idsUsed }+    sec <- seccmd level+    return $ if (level > 0) && (level <= 4)+                then blankline <> text "@node " <> node $$+                     text sec <> txt $$+                     text "@anchor" <> braces (text $ '#':id')+                else txt+    where+      seccmd :: PandocMonad m => Int -> TI m String+      seccmd 1 = return "@chapter "+      seccmd 2 = return "@section "+      seccmd 3 = return "@subsection "+      seccmd 4 = return "@subsubsection "+      seccmd _ = throwError $ PandocSomeError "illegal seccmd level"  blockToTexinfo (Table caption aligns widths heads rows) = do   headers <- if all null heads@@ -256,28 +274,32 @@                    inCmd "caption" captionText $$                    text "@end float" -tableHeadToTexinfo :: [Alignment]+tableHeadToTexinfo :: PandocMonad m+                   => [Alignment]                    -> [[Block]]-                   -> State WriterState Doc+                   -> TI m Doc tableHeadToTexinfo = tableAnyRowToTexinfo "@headitem " -tableRowToTexinfo :: [Alignment]+tableRowToTexinfo :: PandocMonad m+                  => [Alignment]                   -> [[Block]]-                  -> State WriterState Doc+                  -> TI m Doc tableRowToTexinfo = tableAnyRowToTexinfo "@item " -tableAnyRowToTexinfo :: String+tableAnyRowToTexinfo :: PandocMonad m+                     => String                      -> [Alignment]                      -> [[Block]]-                     -> State WriterState Doc+                     -> TI m Doc tableAnyRowToTexinfo itemtype aligns cols =   zipWithM alignedBlock aligns cols >>=   return . (text itemtype $$) . foldl (\row item -> row $$   (if isEmpty row then empty else text " @tab ") <> item) empty -alignedBlock :: Alignment+alignedBlock :: PandocMonad m+             => Alignment              -> [Block]-             -> State WriterState Doc+             -> TI m Doc -- XXX @flushleft and @flushright text won't get word wrapped.  Since word -- wrapping is more important than alignment, we ignore the alignment. alignedBlock _ = blockListToTexinfo@@ -292,8 +314,9 @@ -}  -- | Convert Pandoc block elements to Texinfo.-blockListToTexinfo :: [Block]-                   -> State WriterState Doc+blockListToTexinfo :: PandocMonad m+                   => [Block]+                   -> TI m Doc blockListToTexinfo [] = return empty blockListToTexinfo (x:xs) = do   x' <- blockToTexinfo x@@ -316,8 +339,8 @@     Para _ -> do       xs' <- blockListToTexinfo xs       case xs of-           ((CodeBlock _ _):_) -> return $ x' $$ xs'-           _                   -> return $ x' $+$ xs'+           (CodeBlock _ _:_) -> return $ x' $$ xs'+           _                 -> return $ x' $+$ xs'     _ -> do       xs' <- blockListToTexinfo xs       return $ x' $$ xs'@@ -335,15 +358,17 @@     _ ->       collectNodes level xs -makeMenuLine :: Block-             -> State WriterState Doc+makeMenuLine :: PandocMonad m+             => Block+             -> TI m Doc makeMenuLine (Header _ _ lst) = do   txt <- inlineListForNode lst   return $ text "* " <> txt <> text "::"-makeMenuLine _ = error "makeMenuLine called with non-Header block"+makeMenuLine _ = throwError $ PandocSomeError "makeMenuLine called with non-Header block" -listItemToTexinfo :: [Block]-                  -> State WriterState Doc+listItemToTexinfo :: PandocMonad m+                  => [Block]+                  -> TI m Doc listItemToTexinfo lst = do   contents <- blockListToTexinfo lst   let spacer = case reverse lst of@@ -351,8 +376,9 @@                     _          -> empty   return $ text "@item" $$ contents <> spacer -defListItemToTexinfo :: ([Inline], [[Block]])-                     -> State WriterState Doc+defListItemToTexinfo :: PandocMonad m+                     => ([Inline], [[Block]])+                     -> TI m Doc defListItemToTexinfo (term, defs) = do     term' <- inlineListToTexinfo term     let defToTexinfo bs = do d <- blockListToTexinfo bs@@ -363,13 +389,15 @@     return $ text "@item " <> term' $+$ vcat defs'  -- | Convert list of inline elements to Texinfo.-inlineListToTexinfo :: [Inline]  -- ^ Inlines to convert-                  -> State WriterState Doc+inlineListToTexinfo :: PandocMonad m+                    => [Inline]  -- ^ Inlines to convert+                    -> TI m Doc inlineListToTexinfo lst = mapM inlineToTexinfo lst >>= return . hcat  -- | Convert list of inline elements to Texinfo acceptable for a node name.-inlineListForNode :: [Inline]  -- ^ Inlines to convert-                  -> State WriterState Doc+inlineListForNode :: PandocMonad m+                  => [Inline]  -- ^ Inlines to convert+                  -> TI m Doc inlineListForNode = return . text . stringToTexinfo .                     filter (not . disallowedInNode) . stringify @@ -378,8 +406,9 @@ disallowedInNode c = c `elem` (".,:()" :: String)  -- | Convert inline element to Texinfo-inlineToTexinfo :: Inline    -- ^ Inline to convert-                -> State WriterState Doc+inlineToTexinfo :: PandocMonad m+                => Inline    -- ^ Inline to convert+                -> TI m Doc  inlineToTexinfo (Span _ lst) =   inlineListToTexinfo lst@@ -408,7 +437,7 @@ inlineToTexinfo (SmallCaps lst) =   inlineListToTexinfo lst >>= return . inCmd "sc" -inlineToTexinfo (Code _ str) = do+inlineToTexinfo (Code _ str) =   return $ text $ "@code{" ++ stringToTexinfo str ++ "}"  inlineToTexinfo (Quoted SingleQuote lst) = do@@ -423,12 +452,14 @@   inlineListToTexinfo lst inlineToTexinfo (Str str) = return $ text (stringToTexinfo str) inlineToTexinfo (Math _ str) = return $ inCmd "math" $ text str-inlineToTexinfo (RawInline f str)+inlineToTexinfo il@(RawInline f str)   | f == "latex" || f == "tex" =                       return $ text "@tex" $$ text str $$ text "@end tex"   | f == "texinfo" =  return $ text str-  | otherwise      =  return empty-inlineToTexinfo (LineBreak) = return $ text "@*" <> cr+  | otherwise      =  do+      report $ InlineNotRendered il+      return empty+inlineToTexinfo LineBreak = return $ text "@*" <> cr inlineToTexinfo SoftBreak = do   wrapText <- gets (writerWrapText . stOptions)   case wrapText of@@ -441,7 +472,7 @@   contents <- escapeCommas $ inlineListToTexinfo txt   return $ text "@ref" <>            braces (text (stringToTexinfo src) <> text "," <> contents)-inlineToTexinfo (Link _ txt (src, _)) = do+inlineToTexinfo (Link _ txt (src, _)) =   case txt of         [Str x] | escapeURI x == src ->  -- autolink              do return $ text $ "@url{" ++ x ++ "}"@@ -453,7 +484,7 @@ inlineToTexinfo (Image attr alternate (source, _)) = do   content <- escapeCommas $ inlineListToTexinfo alternate   opts <- gets stOptions-  let showDim dim = case (dimension dim attr) of+  let showDim dim = case dimension dim attr of                       (Just (Pixel a))   -> showInInch opts (Pixel a) ++ "in"                       (Just (Percent _)) -> ""                       (Just d)           -> show d
src/Text/Pandoc/Writers/Textile.hs view
@@ -1,5 +1,5 @@ {--Copyright (C) 2010-2015 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2010-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -18,7 +18,7 @@  {- |    Module      : Text.Pandoc.Writers.Textile-   Copyright   : Copyright (C) 2010-2015 John MacFarlane+   Copyright   : Copyright (C) 2010-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -30,17 +30,20 @@ Textile:  <http://thresholdstate.com/articles/4312/the-textile-reference-manual> -} module Text.Pandoc.Writers.Textile ( writeTextile ) where+import Control.Monad.State.Strict+import Data.Char (isSpace)+import Data.List (intercalate)+import Data.Text (Text, pack)+import Text.Pandoc.Class (PandocMonad, report) import Text.Pandoc.Definition+import Text.Pandoc.ImageSize+import Text.Pandoc.Logging import Text.Pandoc.Options-import Text.Pandoc.Shared import Text.Pandoc.Pretty (render)-import Text.Pandoc.ImageSize-import Text.Pandoc.Writers.Shared+import Text.Pandoc.Shared import Text.Pandoc.Templates (renderTemplate')-import Text.Pandoc.XML ( escapeStringForXML )-import Data.List ( intercalate )-import Control.Monad.State-import Data.Char ( isSpace )+import Text.Pandoc.Writers.Shared+import Text.Pandoc.XML (escapeStringForXML)  data WriterState = WriterState {     stNotes     :: [String]        -- Footnotes@@ -49,29 +52,34 @@   , stUseTags   :: Bool            -- True if we should use HTML tags because we're in a complex list   } +type TW = StateT WriterState+ -- | Convert Pandoc to Textile.-writeTextile :: WriterOptions -> Pandoc -> String+writeTextile :: PandocMonad m => WriterOptions -> Pandoc -> m Text writeTextile opts document =-  evalState (pandocToTextile opts document)-            WriterState { stNotes = [], stListLevel = [], stStartNum = Nothing,+  evalStateT (pandocToTextile opts document)+            WriterState { stNotes = [],+                          stListLevel = [],+                          stStartNum = Nothing,                           stUseTags = False }  -- | Return Textile representation of document.-pandocToTextile :: WriterOptions -> Pandoc -> State WriterState String+pandocToTextile :: PandocMonad m+                => WriterOptions -> Pandoc -> TW m Text pandocToTextile opts (Pandoc meta blocks) = do   metadata <- metaToJSON opts (blockListToTextile opts)                  (inlineListToTextile opts) meta   body <- blockListToTextile opts blocks-  notes <- liftM (unlines . reverse . stNotes) get-  let main = body ++ if null notes then "" else ("\n\n" ++ notes)+  notes <- gets $ unlines . reverse . stNotes+  let main = pack $ body ++ if null notes then "" else ("\n\n" ++ notes)   let context = defField "body" main metadata   case writerTemplate opts of-       Nothing  -> return main-       Just tpl -> return $ renderTemplate' tpl context+         Nothing  -> return main+         Just tpl -> renderTemplate' tpl context -withUseTags :: State WriterState a -> State WriterState a+withUseTags :: PandocMonad m => TW m a -> TW m a withUseTags action = do-  oldUseTags <- liftM stUseTags get+  oldUseTags <- gets stUseTags   modify $ \s -> s { stUseTags = True }   result <- action   modify $ \s -> s { stUseTags = oldUseTags }@@ -101,9 +109,10 @@ escapeStringForTextile = concatMap escapeCharForTextile  -- | Convert Pandoc block element to Textile.-blockToTextile :: WriterOptions -- ^ Options-                -> Block         -- ^ Block element-                -> State WriterState String+blockToTextile :: PandocMonad m+               => WriterOptions -- ^ Options+               -> Block         -- ^ Block element+               -> TW m String  blockToTextile _ Null = return "" @@ -123,8 +132,8 @@   return $ im ++ "\n" ++ capt  blockToTextile opts (Para inlines) = do-  useTags <- liftM stUseTags get-  listLevel <- liftM stListLevel get+  useTags <- gets stUseTags+  listLevel <- gets stListLevel   contents <- inlineListToTextile opts inlines   return $ if useTags               then "<p>" ++ contents ++ "</p>"@@ -133,9 +142,11 @@ blockToTextile opts (LineBlock lns) =   blockToTextile opts $ linesToPara lns -blockToTextile _ (RawBlock f str)+blockToTextile _ b@(RawBlock f str)   | f == Format "html" || f == Format "textile" = return str-  | otherwise                                   = return ""+  | otherwise                                   = do+      report $ BlockNotRendered b+      return ""  blockToTextile _ HorizontalRule = return "<hr />\n" @@ -211,7 +222,7 @@             "<tbody>\n" ++ unlines body' ++ "</tbody>\n</table>\n"  blockToTextile opts x@(BulletList items) = do-  oldUseTags <- liftM stUseTags get+  oldUseTags <- gets stUseTags   let useTags = oldUseTags || not (isSimpleList x)   if useTags      then do@@ -219,13 +230,13 @@         return $ "<ul>\n" ++ vcat contents ++ "\n</ul>\n"      else do         modify $ \s -> s { stListLevel = stListLevel s ++ "*" }-        level <- get >>= return . length . stListLevel+        level <- gets $ length . stListLevel         contents <- mapM (listItemToTextile opts) items         modify $ \s -> s { stListLevel = init (stListLevel s) }         return $ vcat contents ++ (if level > 1 then "" else "\n")  blockToTextile opts x@(OrderedList attribs@(start, _, _) items) = do-  oldUseTags <- liftM stUseTags get+  oldUseTags <- gets stUseTags   let useTags = oldUseTags || not (isSimpleList x)   if useTags      then do@@ -237,7 +248,7 @@                          , stStartNum = if start > 1                                            then Just start                                            else Nothing }-        level <- get >>= return . length . stListLevel+        level <- gets $ length . stListLevel         contents <- mapM (listItemToTextile opts) items         modify $ \s -> s { stListLevel = init (stListLevel s),                            stStartNum = Nothing }@@ -261,10 +272,11 @@           else "")  -- | Convert bullet or ordered list item (list of blocks) to Textile.-listItemToTextile :: WriterOptions -> [Block] -> State WriterState String+listItemToTextile :: PandocMonad m+                  => WriterOptions -> [Block] -> TW m String listItemToTextile opts items = do   contents <- blockListToTextile opts items-  useTags <- get >>= return . stUseTags+  useTags <- gets stUseTags   if useTags      then return $ "<li>" ++ contents ++ "</li>"      else do@@ -277,14 +289,15 @@             Nothing -> return $ marker ++ " " ++ contents  -- | Convert definition list item (label, list of blocks) to Textile.-definitionListItemToTextile :: WriterOptions+definitionListItemToTextile :: PandocMonad m+                            => WriterOptions                              -> ([Inline],[[Block]])-                             -> State WriterState String+                             -> TW m String definitionListItemToTextile opts (label, items) = do   labelText <- inlineListToTextile opts label   contents <- mapM (blockListToTextile opts) items   return $ "<dt>" ++ labelText ++ "</dt>\n" ++-          (intercalate "\n" $ map (\d -> "<dd>" ++ d ++ "</dd>") contents)+          intercalate "\n" (map (\d -> "<dd>" ++ d ++ "</dd>") contents)  -- | True if the list can be handled by simple wiki markup, False if HTML tags will be needed. isSimpleList :: Block -> Bool@@ -301,16 +314,16 @@ isSimpleListItem []  = True isSimpleListItem [x] =   case x of-       Plain _           -> True-       Para  _           -> True-       BulletList _      -> isSimpleList x-       OrderedList _ _   -> isSimpleList x-       _                 -> False+       Plain _         -> True+       Para  _         -> True+       BulletList _    -> isSimpleList x+       OrderedList _ _ -> isSimpleList x+       _               -> False isSimpleListItem [x, y] | isPlainOrPara x =   case y of-       BulletList _      -> isSimpleList y-       OrderedList _ _   -> isSimpleList y-       _                 -> False+       BulletList _    -> isSimpleList y+       OrderedList _ _ -> isSimpleList y+       _               -> False isSimpleListItem _ = False  isPlainOrPara :: Block -> Bool@@ -325,18 +338,19 @@ -- Auxiliary functions for tables. (TODO: these are common to HTML, MediaWiki, -- and Textile writers, and should be abstracted out.) -tableRowToTextile :: WriterOptions-                    -> [String]-                    -> Int-                    -> [[Block]]-                    -> State WriterState String+tableRowToTextile :: PandocMonad m+                  => WriterOptions+                  -> [String]+                  -> Int+                  -> [[Block]]+                  -> TW m String tableRowToTextile opts alignStrings rownum cols' = do   let celltype = if rownum == 0 then "th" else "td"   let rowclass = case rownum of-                      0                  -> "header"+                      0 -> "header"                       x | x `rem` 2 == 1 -> "odd"-                      _                  -> "even"-  cols'' <- sequence $ zipWith+                      _ -> "even"+  cols'' <- zipWithM             (\alignment item -> tableItemToTextile opts celltype alignment item)             alignStrings cols'   return $ "<tr class=\"" ++ rowclass ++ "\">\n" ++ unlines cols'' ++ "</tr>"@@ -348,11 +362,12 @@                                  AlignCenter  -> "center"                                  AlignDefault -> "left" -tableItemToTextile :: WriterOptions-                     -> String-                     -> String-                     -> [Block]-                     -> State WriterState String+tableItemToTextile :: PandocMonad m+                   => WriterOptions+                   -> String+                   -> String+                   -> [Block]+                   -> TW m String tableItemToTextile opts celltype align' item = do   let mkcell x = "<" ++ celltype ++ " align=\"" ++ align' ++ "\">" ++                     x ++ "</" ++ celltype ++ ">"@@ -360,19 +375,21 @@   return $ mkcell contents  -- | Convert list of Pandoc block elements to Textile.-blockListToTextile :: WriterOptions -- ^ Options-                    -> [Block]       -- ^ List of block elements-                    -> State WriterState String+blockListToTextile :: PandocMonad m+                   => WriterOptions -- ^ Options+                   -> [Block]       -- ^ List of block elements+                   -> TW m String blockListToTextile opts blocks =   mapM (blockToTextile opts) blocks >>= return . vcat  -- | Convert list of Pandoc inline elements to Textile.-inlineListToTextile :: WriterOptions -> [Inline] -> State WriterState String+inlineListToTextile :: PandocMonad m+                    => WriterOptions -> [Inline] -> TW m String inlineListToTextile opts lst =   mapM (inlineToTextile opts) lst >>= return . concat  -- | Convert Pandoc inline element to Textile.-inlineToTextile :: WriterOptions -> Inline -> State WriterState String+inlineToTextile :: PandocMonad m => WriterOptions -> Inline -> TW m String  inlineToTextile opts (Span _ lst) =   inlineListToTextile opts lst@@ -429,13 +446,15 @@ inlineToTextile _ (Math _ str) =   return $ "<span class=\"math\">" ++ escapeStringForXML str ++ "</math>" -inlineToTextile opts (RawInline f str)+inlineToTextile opts il@(RawInline f str)   | f == Format "html" || f == Format "textile" = return str   | (f == Format "latex" || f == Format "tex") &&      isEnabled Ext_raw_tex opts                 = return str-  | otherwise                                   = return ""+  | otherwise                                   = do+      report $ InlineNotRendered il+      return "" -inlineToTextile _ (LineBreak) = return "\n"+inlineToTextile _ LineBreak = return "\n"  inlineToTextile _ SoftBreak = return " " @@ -464,7 +483,7 @@                    then ""                    else "(" ++ unwords cls ++ ")"       showDim dir = let toCss str = Just $ show dir ++ ":" ++ str ++ ";"-                    in case (dimension dir attr) of+                    in case dimension dir attr of                          Just (Percent a) -> toCss $ show (Percent a)                          Just dim         -> toCss $ showInPixel opts dim ++ "px"                          Nothing          -> Nothing@@ -476,7 +495,7 @@   return $ "!" ++ classes ++ styles ++ source ++ txt ++ "!"  inlineToTextile opts (Note contents) = do-  curNotes <- liftM stNotes get+  curNotes <- gets stNotes   let newnum = length curNotes + 1   contents' <- blockListToTextile opts contents   let thisnote = "fn" ++ show newnum ++ ". " ++ contents' ++ "\n"
src/Text/Pandoc/Writers/ZimWiki.hs view
@@ -1,5 +1,6 @@ {--Copyright (C) 2008-2015 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2008-2017 John MacFarlane <jgm@berkeley.edu>+              2017 Alex Ivkin  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -18,11 +19,11 @@  {- |    Module      : Text.Pandoc.Writers.ZimWiki-   Copyright   : Copyright (C) 2008-2015 John MacFarlane, 2016 Alex Ivkin+   Copyright   : Copyright (C) 2008-2017 John MacFarlane, 2017 Alex Ivkin    License     : GNU GPL, version 2 or above     Maintainer  : Alex Ivkin <alex@ivkin.net>-   Stability   : alpha+   Stability   : beta    Portability : portable  Conversion of 'Pandoc' documents to ZimWiki markup.@@ -31,48 +32,53 @@ -}  module Text.Pandoc.Writers.ZimWiki ( writeZimWiki ) where+import Control.Monad (zipWithM)+import Control.Monad.State.Strict (StateT, evalStateT, gets, modify)+import Data.Default (Default (..))+import Data.List (intercalate, isInfixOf, isPrefixOf, transpose)+import qualified Data.Map as Map+import Data.Maybe (fromMaybe)+import Data.Text (Text, breakOnAll, pack)+import Text.Pandoc.Class (PandocMonad, report) import Text.Pandoc.Definition-import Text.Pandoc.Options ( WriterOptions(writerTableOfContents, writerTemplate, writerWrapText), WrapOption(..) )-import Text.Pandoc.Shared ( escapeURI, linesToPara, removeFormatting, trimr-                          , substitute )-import Text.Pandoc.Writers.Shared ( defField, metaToJSON ) import Text.Pandoc.ImageSize-import Text.Pandoc.Templates ( renderTemplate' )-import Data.List ( intercalate, isPrefixOf, transpose, isInfixOf )-import Data.Text ( breakOnAll, pack )-import Data.Default (Default(..))-import Network.URI ( isURI )-import Control.Monad ( zipWithM )-import Control.Monad.State ( modify, State, get, evalState )---import Control.Monad.Reader ( ReaderT, runReaderT, ask, local )+import Text.Pandoc.Logging+import Text.Pandoc.Options (WrapOption (..), WriterOptions (writerTableOfContents, writerTemplate, writerWrapText))+import Text.Pandoc.Shared (escapeURI, isURI, linesToPara, removeFormatting,+                           substitute, trimr)+import Text.Pandoc.Templates (renderTemplate')+import Text.Pandoc.Writers.Shared (defField, metaToJSON)  data WriterState = WriterState {-    stItemNum   :: Int,-    stIndent    :: String          -- Indent after the marker at the beginning of list items+    stItemNum :: Int,+    stIndent  :: String,         -- Indent after the marker at the beginning of list items+    stInTable :: Bool,           -- Inside a table+    stInLink  :: Bool            -- Inside a link description   }  instance Default WriterState where-  def = WriterState { stItemNum = 1, stIndent = "" }+  def = WriterState { stItemNum = 1, stIndent = "", stInTable = False, stInLink = False } +type ZW = StateT WriterState+ -- | Convert Pandoc to ZimWiki.-writeZimWiki :: WriterOptions -> Pandoc -> String-writeZimWiki opts document = evalState (pandocToZimWiki opts document) (WriterState 1 "")+writeZimWiki :: PandocMonad m => WriterOptions -> Pandoc -> m Text+writeZimWiki opts document = evalStateT (pandocToZimWiki opts document) def  -- | Return ZimWiki representation of document.-pandocToZimWiki :: WriterOptions -> Pandoc -> State WriterState String+pandocToZimWiki :: PandocMonad m => WriterOptions -> Pandoc -> ZW m Text pandocToZimWiki opts (Pandoc meta blocks) = do   metadata <- metaToJSON opts               (fmap trimr . blockListToZimWiki opts)               (inlineListToZimWiki opts)               meta-  body <- blockListToZimWiki opts blocks+  body <- pack <$> blockListToZimWiki opts blocks   --let header = "Content-Type: text/x-zim-wiki\nWiki-Format: zim 0.4\n"   let main = body   let context = defField "body" main-                $ defField "toc" (writerTableOfContents opts)-                $ metadata+                $ defField "toc" (writerTableOfContents opts) metadata   case writerTemplate opts of-       Just tpl -> return $ renderTemplate' tpl context+       Just tpl -> renderTemplate' tpl context        Nothing  -> return main  -- | Escape special characters for ZimWiki.@@ -83,7 +89,7 @@                substitute "//" "''//''"  -- | Convert Pandoc block element to ZimWiki.-blockToZimWiki :: WriterOptions -> Block -> State WriterState String+blockToZimWiki :: PandocMonad m => WriterOptions -> Block -> ZW m String  blockToZimWiki _ Null = return "" @@ -107,18 +113,20 @@   return $ "{{" ++ prefix ++ src ++ imageDims opts attr ++ opt ++ "}}\n"  blockToZimWiki opts (Para inlines) = do-  indent <- stIndent <$> get-  -- useTags <- stUseTags <$> get+  indent <- gets stIndent+  -- useTags <- gets stUseTags   contents <- inlineListToZimWiki opts inlines   return $ contents ++ if null indent then "\n" else "" -blockToZimWiki opts (LineBlock lns) = do+blockToZimWiki opts (LineBlock lns) =   blockToZimWiki opts $ linesToPara lns -blockToZimWiki opts (RawBlock f str)+blockToZimWiki opts b@(RawBlock f str)   | f == Format "zimwiki"  = return str-  | f == Format "html"     = do cont <- indentFromHTML opts str; return cont-  | otherwise              = return ""+  | f == Format "html"     = indentFromHTML opts str+  | otherwise              = do+      report $ BlockNotRendered b+      return ""  blockToZimWiki _ HorizontalRule = return "\n----\n" @@ -128,9 +136,13 @@   return $ eqs ++ " " ++ contents ++ " " ++ eqs ++ "\n"  blockToZimWiki _ (CodeBlock (_,classes,_) str) = do+  -- Remap languages into the gtksourceview2 convention that ZimWiki source code plugin is using+  let langal = [("javascript", "js"), ("bash", "sh"), ("winbatch", "dosbatch")]+  let langmap = Map.fromList langal   return $ case classes of-                []              -> "'''\n" ++ cleanupCode str ++ "\n'''\n" -- no lang block is a quote block-                (x:_)   -> "{{{code: lang=\"" ++ x ++ "\" linenumbers=\"True\"\n" ++ str ++ "\n}}}\n"    -- for zim's code plugin, go verbatim on the lang spec+                []      -> "'''\n" ++ cleanupCode str ++ "\n'''\n"   -- turn no lang block into a quote block+                (x:_)   -> "{{{code: lang=\"" +++                        (fromMaybe x (Map.lookup x langmap)) ++ "\" linenumbers=\"True\"\n" ++ str ++ "\n}}}\n"  -- for zim's code plugin, go verbatim on the lang spec  blockToZimWiki opts (BlockQuote blocks) = do   contents <- blockListToZimWiki opts blocks@@ -143,12 +155,12 @@                       c <- inlineListToZimWiki opts capt                       return $ "" ++ c ++ "\n"   headers' <- if all null headers-                 then zipWithM (tableItemToZimWiki opts) aligns (rows !! 0)-                 else zipWithM (tableItemToZimWiki opts) aligns headers+                 then zipWithM (tableItemToZimWiki opts) aligns (head rows)+                 else mapM ((inlineListToZimWiki opts) . removeFormatting)headers  -- emphasis, links etc. are not allowed in table headers   rows' <- mapM (zipWithM (tableItemToZimWiki opts) aligns) rows   let widths = map (maximum . map length) $ transpose (headers':rows')   let padTo (width, al) s =-          case (width - length s) of+          case width - length s of                x | x > 0 ->                  if al == AlignLeft || al == AlignDefault                     then s ++ replicate x ' '@@ -157,63 +169,63 @@                             else replicate (x `div` 2) ' ' ++                                  s ++ replicate (x - x `div` 2) ' '                  | otherwise -> s-  let borderCell (width, al) _ =-                 if al == AlignLeft-                    then ":"++ replicate (width-1) '-'-                        else if al == AlignDefault-                        then replicate width '-'-                        else if al == AlignRight-                            then replicate (width-1) '-' ++ ":"-                            else ":" ++ replicate (width-2) '-' ++ ":"+  let borderCell (width, al) _+        | al == AlignLeft = ":"++ replicate (width-1) '-'+        | al == AlignDefault = replicate width '-'+        | al == AlignRight = replicate (width-1) '-' ++ ":"+        | otherwise = ":" ++ replicate (width-2) '-' ++ ":"   let underheader  = "|" ++ intercalate "|" (zipWith borderCell (zip widths aligns) headers') ++ "|"-  let renderRow sep cells = sep ++ intercalate sep (zipWith padTo (zip widths aligns) cells) ++ sep+  let renderRow cells = "|" ++ intercalate "|" (zipWith padTo (zip widths aligns) cells) ++ "|"   return $ captionDoc ++-           (if null headers' then "" else renderRow "|" headers' ++ "\n") ++ underheader ++ "\n" ++-           unlines (map (renderRow "|") rows')+           (if null headers' then "" else renderRow headers' ++ "\n") ++ underheader ++ "\n" +++           unlines (map renderRow rows')  blockToZimWiki opts (BulletList items) = do-  indent <- stIndent <$> get+  indent <- gets stIndent   modify $ \s -> s { stIndent = stIndent s ++ "\t" }-  contents <- (mapM (listItemToZimWiki opts) items)+  contents <- mapM (listItemToZimWiki opts) items   modify $ \s -> s{ stIndent = indent } -- drop 1 (stIndent s) }   return $ vcat contents ++ if null indent then "\n" else ""  blockToZimWiki opts (OrderedList _ items) = do-  indent <- stIndent <$> get+  indent <- gets stIndent   modify $ \s -> s { stIndent = stIndent s ++ "\t", stItemNum = 1 }-  contents <- (mapM (orderedListItemToZimWiki opts) items)+  contents <- mapM (orderedListItemToZimWiki opts) items   modify $ \s -> s{ stIndent = indent } -- drop 1 (stIndent s) }   return $ vcat contents ++ if null indent then "\n" else ""  blockToZimWiki opts (DefinitionList items) = do-  contents <- (mapM (definitionListItemToZimWiki opts) items)+  contents <- mapM (definitionListItemToZimWiki opts) items   return $ vcat contents -definitionListItemToZimWiki :: WriterOptions -> ([Inline],[[Block]]) -> State WriterState String+definitionListItemToZimWiki :: PandocMonad m+                            => WriterOptions+                            -> ([Inline],[[Block]])+                            -> ZW m String definitionListItemToZimWiki opts (label, items) = do   labelText <- inlineListToZimWiki opts label   contents <- mapM (blockListToZimWiki opts) items-  indent <- stIndent <$> get+  indent <- gets stIndent   return $ indent ++ "* **" ++ labelText ++ "** " ++ concat contents  -- Auxiliary functions for lists:-indentFromHTML :: WriterOptions -> String -> State WriterState String+indentFromHTML :: PandocMonad m => WriterOptions -> String -> ZW m String indentFromHTML _ str = do-   indent <- stIndent  <$> get-   itemnum <- stItemNum  <$> get-   if isInfixOf "<li>" str then return $ indent ++ show itemnum ++ "."-        else if isInfixOf "</li>" str then return "\n"-                else if isInfixOf "<li value=" str then do+   indent <- gets stIndent+   itemnum <- gets stItemNum+   if "<li>" `isInfixOf` str then return $ indent ++ show itemnum ++ "."+        else if "</li>" `isInfixOf` str then return "\n"+                else if "<li value=" `isInfixOf` str then do                         -- poor man's cut                         let val = drop 10 $ reverse $ drop 1 $ reverse str                         --let val = take ((length valls) - 2) valls                         modify $ \s -> s { stItemNum = read val }                         return ""-                        else if isInfixOf "<ol>" str then do+                        else if "<ol>" `isInfixOf` str then do                                 let olcount=countSubStrs "<ol>" str                                 modify $ \s -> s { stIndent = stIndent s ++ replicate olcount '\t', stItemNum = 1 }                                 return ""-                                else if isInfixOf "</ol>" str then do+                                else if "</ol>" `isInfixOf` str then do                                         let olcount=countSubStrs "/<ol>" str                                         modify $ \s -> s{ stIndent = drop olcount (stIndent s) }                                         return ""@@ -230,23 +242,25 @@ vcat = intercalate "\n"  -- | Convert bullet list item (list of blocks) to ZimWiki.-listItemToZimWiki :: WriterOptions -> [Block] -> State WriterState String+listItemToZimWiki :: PandocMonad m => WriterOptions -> [Block] -> ZW m String listItemToZimWiki opts items = do   contents <- blockListToZimWiki opts items-  indent <- stIndent <$> get+  indent <- gets stIndent   return $ indent ++ "* " ++ contents  -- | Convert ordered list item (list of blocks) to ZimWiki.-orderedListItemToZimWiki :: WriterOptions -> [Block] -> State WriterState String+orderedListItemToZimWiki :: PandocMonad m+                         => WriterOptions -> [Block] -> ZW m String orderedListItemToZimWiki opts items = do   contents <- blockListToZimWiki opts items-  indent <- stIndent <$> get-  itemnum <- stItemNum  <$> get+  indent <- gets stIndent+  itemnum <- gets stItemNum   --modify $ \s -> s { stItemNum = itemnum + 1 } -- this is not strictly necessary for zim as zim does its own renumbering   return $ indent ++ show itemnum ++ ". " ++ contents  -- Auxiliary functions for tables:-tableItemToZimWiki :: WriterOptions -> Alignment -> [Block] -> State WriterState String+tableItemToZimWiki :: PandocMonad m+                   => WriterOptions -> Alignment -> [Block] -> ZW m String tableItemToZimWiki opts align' item = do   let mkcell x = (if align' == AlignRight || align' == AlignCenter                      then "  "@@ -254,19 +268,24 @@                  (if align' == AlignLeft || align' == AlignCenter                      then "  "                      else "")-  contents <- blockListToZimWiki opts item -- local (\s -> s { stBackSlashLB = True }) $+  modify $ \s -> s { stInTable = True }+  contents <- blockListToZimWiki opts item+  modify $ \s -> s { stInTable = False }   return $ mkcell contents  -- | Convert list of Pandoc block elements to ZimWiki.-blockListToZimWiki :: WriterOptions -> [Block] -> State WriterState String+blockListToZimWiki :: PandocMonad m+                   => WriterOptions -> [Block] -> ZW m String blockListToZimWiki opts blocks = vcat <$> mapM (blockToZimWiki opts) blocks  -- | Convert list of Pandoc inline elements to ZimWiki.-inlineListToZimWiki :: WriterOptions -> [Inline] -> State WriterState String-inlineListToZimWiki opts lst =  concat <$> (mapM (inlineToZimWiki opts) lst)+inlineListToZimWiki :: PandocMonad m+                    => WriterOptions -> [Inline] -> ZW m String+inlineListToZimWiki opts lst =  concat <$> mapM (inlineToZimWiki opts) lst  -- | Convert Pandoc inline element to ZimWiki.-inlineToZimWiki :: WriterOptions -> Inline -> State WriterState String+inlineToZimWiki :: PandocMonad m+                => WriterOptions -> Inline -> ZW m String  inlineToZimWiki opts (Emph lst) = do   contents <- inlineListToZimWiki opts lst@@ -304,7 +323,15 @@  inlineToZimWiki _ (Code _ str) = return $ "''" ++ str ++ "''" -inlineToZimWiki _ (Str str) = return $ escapeString str+inlineToZimWiki _ (Str str) = do+  inTable <- gets stInTable+  inLink  <- gets stInLink+  if inTable+      then return $ substitute "|" "\\|" . escapeString $ str+      else+          if inLink+          then return str+          else return $ escapeString str  inlineToZimWiki _ (Math mathType str) = return $ delim ++ str ++ delim   -- note:  str should NOT be escaped   where delim = case mathType of@@ -312,12 +339,18 @@                      InlineMath  -> "$"  -- | f == Format "html"     = return $ "<html>" ++ str ++ "</html>"-inlineToZimWiki opts (RawInline f str)+inlineToZimWiki opts il@(RawInline f str)   | f == Format "zimwiki" = return str-  | f == Format "html"     = do cont <- indentFromHTML opts str; return cont-  | otherwise              = return ""+  | f == Format "html"     = indentFromHTML opts str+  | otherwise              = do+      report $ InlineNotRendered il+      return "" -inlineToZimWiki _ (LineBreak) = return "\n" -- was \\\\+inlineToZimWiki _ LineBreak = do+  inTable <- gets stInTable+  if inTable+      then return "\\n"+      else return "\n"  inlineToZimWiki opts SoftBreak =   case writerWrapText opts of@@ -328,37 +361,45 @@ inlineToZimWiki _ Space = return " "  inlineToZimWiki opts (Link _ txt (src, _)) = do-  label <- inlineListToZimWiki opts txt+  inTable <- gets stInTable+  modify $ \s -> s { stInLink = True }+  label <- inlineListToZimWiki opts $ removeFormatting txt -- zim does not allow formatting in link text, it takes the text verbatim, no need to escape it+  modify $ \s -> s { stInLink = False }+  let label'= if inTable+            then "" -- no label is allowed in a table+            else "|"++label   case txt of      [Str s] | "mailto:" `isPrefixOf` src -> return $ "<" ++ s ++ ">"              | escapeURI s == src -> return src      _  -> if isURI src-              then return $ "[[" ++ src  ++ "|" ++ label ++ "]]"-              else return $ "[[" ++ src' ++ "|" ++ label ++ "]]"+              then return $ "[[" ++ src  ++ label' ++ "]]"+              else return $ "[[" ++ src' ++ label' ++ "]]"                      where src' = case src of                                      '/':xs -> xs  -- with leading / it's a                                      _      -> src -- link to a help page inlineToZimWiki opts (Image attr alt (source, tit)) = do   alt' <- inlineListToZimWiki opts alt-  let txt = case (tit, alt) of-              ("", []) -> ""-              ("", _ ) -> "|" ++ alt'-              (_ , _ ) -> "|" ++ tit+  inTable <- gets stInTable+  let txt = case (tit, alt, inTable) of+              ("",[], _)      -> ""+              ("", _, False ) -> "|" ++ alt'+              (_ , _, False ) -> "|" ++ tit+              (_ , _, True )  -> ""       -- Relative links fail isURI and receive a colon       prefix = if isURI source then "" else ":"   return $ "{{" ++ prefix ++ source ++ imageDims opts attr ++ txt ++ "}}"  inlineToZimWiki opts (Note contents) = do+  -- no concept of notes in zim wiki, use a text block   contents' <- blockListToZimWiki opts contents-  return $ "((" ++ contents' ++ "))"-  -- note - may not work for notes with multiple blocks+  return $ " **{Note:** " ++ trimr contents' ++ "**}**"  imageDims :: WriterOptions -> Attr -> String imageDims opts attr = go (toPx $ dimension Width attr) (toPx $ dimension Height attr)   where     toPx = fmap (showInPixel opts) . checkPct     checkPct (Just (Percent _)) = Nothing-    checkPct maybeDim = maybeDim+    checkPct maybeDim           = maybeDim     go (Just w) Nothing  = "?" ++ w     go (Just w) (Just h) = "?" ++ w ++ "x" ++ h     go Nothing  (Just h) = "?0x" ++ h
src/Text/Pandoc/XML.hs view
@@ -1,5 +1,5 @@ {--Copyright (C) 2006-2016 John MacFarlane <jgm@berkeley.edu>+Copyright (C) 2006-2017 John MacFarlane <jgm@berkeley.edu>  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by@@ -18,7 +18,7 @@  {- |    Module      : Text.Pandoc.XML-   Copyright   : Copyright (C) 2006-2016 John MacFarlane+   Copyright   : Copyright (C) 2006-2017 John MacFarlane    License     : GNU GPL, version 2 or above     Maintainer  : John MacFarlane <jgm@berkeley.edu>@@ -36,18 +36,20 @@                          toEntities,                          fromEntities ) where -import Text.Pandoc.Pretty-import Data.Char (ord, isAscii, isSpace)+import Data.Char (isAscii, isSpace, ord)+import Data.Text (Text)+import qualified Data.Text as T import Text.HTML.TagSoup.Entity (lookupEntity)+import Text.Pandoc.Pretty  -- | Escape one character as needed for XML. escapeCharForXML :: Char -> String escapeCharForXML x = case x of-                       '&'    -> "&amp;"-                       '<'    -> "&lt;"-                       '>'    -> "&gt;"-                       '"'    -> "&quot;"-                       c      -> [c]+                       '&' -> "&amp;"+                       '<' -> "&lt;"+                       '>' -> "&gt;"+                       '"' -> "&quot;"+                       c   -> [c]  -- | Escape string as needed for XML.  Entity references are not preserved. escapeStringForXML :: String -> String@@ -91,11 +93,10 @@ inTagsIndented tagType = inTags True tagType []  -- | Escape all non-ascii characters using numerical entities.-toEntities :: String -> String-toEntities [] = ""-toEntities (c:cs)-  | isAscii c = c : toEntities cs-  | otherwise = "&#" ++ show (ord c) ++ ";" ++ toEntities cs+toEntities :: Text -> Text+toEntities = T.concatMap go+  where go c | isAscii c = T.singleton c+             | otherwise = T.pack ("&#" ++ show (ord c) ++ ";")  -- Unescapes XML entities fromEntities :: String -> String@@ -108,8 +109,8 @@                              (zs,    ys) -> (zs,ys)           ent' = case ent of                       '#':'X':ys -> '#':'x':ys  -- workaround tagsoup bug-                      '#':_ -> ent-                      _     -> ent ++ ";"+                      '#':_      -> ent+                      _          -> ent ++ ";"  fromEntities (x:xs) = x : fromEntities xs fromEntities [] = []
stack.yaml view
@@ -1,14 +1,18 @@ flags:   pandoc:     trypandoc: false-    https: true     embed_data_files: false     old-locale: false     network-uri: true packages: - '.' extra-deps:-- pandoc-types-1.17.0.5-- skylighting-0.1.1.5-- texmath-0.9-resolver: lts-9.2+- pandoc-types-1.17.2+- hslua-0.9.2+- skylighting-0.4.2+- cmark-gfm-0.1.1+- QuickCheck-2.10.0.1+- tasty-quickcheck-0.9.1+- doctemplates-0.2.1+- haddock-library-1.4.3+resolver: lts-9.9
+ test/Tests/Command.hs view
@@ -0,0 +1,95 @@+module Tests.Command (findPandoc, runTest, tests)+where++import Data.Algorithm.Diff+import qualified Data.ByteString as BS+import Data.List (isSuffixOf)+import Prelude hiding (readFile)+import System.Directory+import System.Exit+import System.FilePath (joinPath, splitDirectories, takeDirectory, (</>))+import System.IO (hPutStr, stderr)+import System.IO.Unsafe (unsafePerformIO)+import System.Process+import Test.Tasty+import Test.Tasty.HUnit+import Tests.Helpers+import Text.Pandoc+import qualified Text.Pandoc.UTF8 as UTF8++-- | Run a test with normalize function, return True if test passed.+runTest :: String    -- ^ Title of test+        -> FilePath  -- ^ Path to pandoc+        -> String    -- ^ Shell command+        -> String    -- ^ Input text+        -> String    -- ^ Expected output+        -> TestTree+runTest testname pandocpath cmd inp norm = testCase testname $ do+  let findDynlibDir []           = Nothing+      findDynlibDir ("build":xs) = Just $ joinPath (reverse xs) </> "build"+      findDynlibDir (_:xs)       = findDynlibDir xs+  let mbDynlibDir = findDynlibDir (reverse $ splitDirectories $+                                   takeDirectory $ takeWhile (/=' ') cmd)+  let dynlibEnv = case mbDynlibDir of+                       Nothing  -> []+                       Just d   -> [("DYLD_LIBRARY_PATH", d),+                                    ("LD_LIBRARY_PATH", d)]+  let env' = dynlibEnv ++ [("PATH",takeDirectory pandocpath),("TMP","."),("LANG","en_US.UTF-8"),("HOME", "./"),("pandoc_datadir", "..")]+  let pr = (shell cmd){ env = Just env' }+  (ec, out', err') <- readCreateProcessWithExitCode pr inp+  -- filter \r so the tests will work on Windows machines+  let out = filter (/= '\r') $ err' ++ out'+  result  <- if ec == ExitSuccess+                then do+                  if out == norm+                     then return TestPassed+                     else return+                          $ TestFailed cmd "expected"+                          $ getDiff (lines out) (lines norm)+                else do+                  hPutStr stderr err'+                  return $ TestError ec+  assertBool (show result) (result == TestPassed)++tests :: TestTree+tests = unsafePerformIO $ do+  pandocpath <- findPandoc+  files <- filter (".md" `isSuffixOf`) <$>+               getDirectoryContents "command"+  let cmds = map (extractCommandTest pandocpath) files+  return $ testGroup "Command:" cmds++isCodeBlock :: Block -> Bool+isCodeBlock (CodeBlock _ _) = True+isCodeBlock _               = False++extractCode :: Block -> String+extractCode (CodeBlock _ code) = code+extractCode _                  = ""++dropPercent :: String -> String+dropPercent ('%':xs) = dropWhile (== ' ') xs+dropPercent xs       = xs++runCommandTest :: FilePath -> (Int, String) -> TestTree+runCommandTest pandocpath (num, code) =+  let codelines = lines code+      (continuations, r1) = span ("\\" `isSuffixOf`) codelines+      (cmd, r2) = (dropPercent (unwords (map init continuations ++ take 1 r1)),+                   drop 1 r1)+      (inplines, r3) = break (=="^D") r2+      normlines = takeWhile (/=".") (drop 1 r3)+      input = unlines inplines+      norm = unlines normlines+      shcmd = cmd -- trimr $ takeDirectory pandocpath </> cmd+  in  runTest ("#" ++ show num) pandocpath shcmd input norm++extractCommandTest :: FilePath -> FilePath -> TestTree+extractCommandTest pandocpath fp = unsafePerformIO $ do+  contents <- UTF8.toText <$> BS.readFile ("command" </> fp)+  Pandoc _ blocks <- runIOorExplode (readMarkdown+                        def{ readerExtensions = pandocExtensions } contents)+  let codeblocks = map extractCode $ filter isCodeBlock $ blocks+  let cases = map (runCommandTest pandocpath) $ zip [1..] codeblocks+  return $ testGroup fp cases+
+ test/Tests/Helpers.hs view
@@ -0,0 +1,138 @@+{-# LANGUAGE FlexibleInstances    #-}+{-# LANGUAGE TypeSynonymInstances #-}+-- Utility functions for the test suite.++module Tests.Helpers ( test+                     , TestResult(..)+                     , showDiff+                     , findPandoc+                     , (=?>)+                     , purely+                     , ToString(..)+                     , ToPandoc(..)+                     )+                     where++import Data.Algorithm.Diff+import qualified Data.Map as M+import Data.Text (Text, unpack)+import System.Directory+import System.Environment.Executable (getExecutablePath)+import System.Exit+import System.FilePath+import Test.Tasty+import Test.Tasty.HUnit+import Text.Pandoc.Builder (Blocks, Inlines, doc, plain)+import Text.Pandoc.Class+import Text.Pandoc.Definition+import Text.Pandoc.Options+import Text.Pandoc.Shared (trimr)+import Text.Pandoc.Writers.Native (writeNative)+import Text.Printf++test :: (ToString a, ToString b, ToString c)+     => (a -> b)  -- ^ function to test+     -> String    -- ^ name of test case+     -> (a, c)    -- ^ (input, expected value)+     -> TestTree+test fn name (input, expected) =+  testCase name' $ assertBool msg (actual' == expected')+     where msg = nl ++ dashes "input" ++ nl ++ input' ++ nl +++                 dashes "result" ++ nl +++                 unlines (map vividize diff) +++                 dashes ""+           nl = "\n"+           name'   = if length name > 54+                        then take 52 name ++ "..."  -- avoid wide output+                        else name+           input'  = toString input+           actual' = lines $ toString $ fn input+           expected' = lines $ toString expected+           diff = getDiff expected' actual'+           dashes "" = replicate 72 '-'+           dashes x  = replicate (72 - length x - 5) '-' ++ " " ++ x ++ " ---"++data TestResult = TestPassed+                | TestError ExitCode+                | TestFailed String FilePath [Diff String]+     deriving (Eq)++instance Show TestResult where+  show TestPassed     = "PASSED"+  show (TestError ec) = "ERROR " ++ show ec+  show (TestFailed cmd file d) = '\n' : dash +++                                 "\n--- " ++ file +++                                 "\n+++ " ++ cmd ++ "\n" ++ showDiff (1,1) d +++                                 dash+    where dash = replicate 72 '-'++showDiff :: (Int,Int) -> [Diff String] -> String+showDiff _ []             = ""+showDiff (l,r) (First ln : ds) =+  printf "+%4d " l ++ ln ++ "\n" ++ showDiff (l+1,r) ds+showDiff (l,r) (Second ln : ds) =+  printf "-%4d " r ++ ln ++ "\n" ++ showDiff (l,r+1) ds+showDiff (l,r) (Both _ _ : ds) =+  showDiff (l+1,r+1) ds++-- | Find pandoc executable relative to test-pandoc+-- First, try in same directory (e.g. if both in ~/.cabal/bin)+-- Second, try ../pandoc (e.g. if in dist/XXX/build/test-pandoc)+findPandoc :: IO FilePath+findPandoc = do+  testExePath <- getExecutablePath+  let testExeDir = takeDirectory testExePath+  found <- doesFileExist (testExeDir </> "pandoc")+  return $ if found+              then testExeDir </> "pandoc"+              else case splitDirectories testExeDir of+                         [] -> error "test-pandoc: empty testExeDir"+                         xs -> joinPath (init xs) </> "pandoc" </> "pandoc"+++vividize :: Diff String -> String+vividize (Both s _) = "  " ++ s+vividize (First s)  = "- " ++ s+vividize (Second s) = "+ " ++ s++purely :: (b -> PandocPure a) -> b -> a+purely f = either (error . show) id . runPure . f++infix 5 =?>+(=?>) :: a -> b -> (a,b)+x =?> y = (x, y)++class ToString a where+  toString :: a -> String++instance ToString Pandoc where+  toString d = unpack $+     purely (writeNative def{ writerTemplate = s }) $ toPandoc d+   where s = case d of+                  (Pandoc (Meta m) _)+                    | M.null m  -> Nothing+                    | otherwise -> Just "" -- need this to get meta output++instance ToString Blocks where+  toString = unpack . purely (writeNative def) . toPandoc++instance ToString Inlines where+  toString = trimr . unpack . purely (writeNative def) . toPandoc++instance ToString String where+  toString = id++instance ToString Text where+  toString = unpack++class ToPandoc a where+  toPandoc :: a -> Pandoc++instance ToPandoc Pandoc where+  toPandoc = id++instance ToPandoc Blocks where+  toPandoc = doc++instance ToPandoc Inlines where+  toPandoc = doc . plain
+ test/Tests/Lua.hs view
@@ -0,0 +1,106 @@+{-# LANGUAGE OverloadedStrings #-}+module Tests.Lua ( tests ) where++import Control.Monad (when)+import System.FilePath ((</>))+import Test.Tasty (TestTree, localOption)+import Test.Tasty.HUnit (Assertion, assertEqual, testCase)+import Test.Tasty.QuickCheck (QuickCheckTests (..), ioProperty, testProperty)+import Text.Pandoc.Arbitrary ()+import Text.Pandoc.Builder (bulletList, doc, doubleQuoted, emph, linebreak,+                            para, plain, rawBlock, singleQuoted, space, str,+                            strong, (<>))+import Text.Pandoc.Class (runIOorExplode)+import Text.Pandoc.Definition (Block, Inline, Meta, Pandoc)+import Text.Pandoc.Lua++import Foreign.Lua++tests :: [TestTree]+tests = map (localOption (QuickCheckTests 20))+  [ testProperty "inline elements can be round-tripped through the lua stack" $+    \x -> ioProperty (roundtripEqual (x::Inline))++  , testProperty "block elements can be round-tripped through the lua stack" $+    \x -> ioProperty (roundtripEqual (x::Block))++  , testProperty "meta blocks can be round-tripped through the lua stack" $+    \x -> ioProperty (roundtripEqual (x::Meta))++  , testProperty "documents can be round-tripped through the lua stack" $+    \x -> ioProperty (roundtripEqual (x::Pandoc))++  , testCase "macro expansion via filter" $+    assertFilterConversion "a '{{helloworld}}' string is expanded"+      "strmacro.lua"+      (doc . para $ str "{{helloworld}}")+      (doc . para . emph $ str "Hello, World")++  , testCase "convert all plains to paras" $+    assertFilterConversion "plains become para"+      "plain-to-para.lua"+      (doc $ bulletList [plain (str "alfa"), plain (str "bravo")])+      (doc $ bulletList [para (str "alfa"), para (str "bravo")])++  , testCase "make hello world document" $+    assertFilterConversion "Document contains 'Hello, World!'"+      "hello-world-doc.lua"+      (doc . para $ str "Hey!" <> linebreak <> str "What's up?")+      (doc . para $ str "Hello," <> space <> str "World!")++  , testCase "implicit doc filter" $+    assertFilterConversion "Document contains 'Hello, World!'"+      "implicit-doc-filter.lua"+      (doc . plain $ linebreak)+      (doc . para $ str "Hello," <> space <> str "World!")++  , testCase "parse raw markdown blocks" $+    assertFilterConversion "raw markdown block is converted"+      "markdown-reader.lua"+      (doc $ rawBlock "markdown" "*charly* **delta**")+      (doc . para $ emph "charly" <> space <> strong "delta")++  , testCase "allow shorthand functions for quote types" $+    assertFilterConversion "single quoted becomes double quoted string"+      "single-to-double-quoted.lua"+      (doc . para . singleQuoted $ str "simple")+      (doc . para . doubleQuoted $ str "simple")++  , testCase "Count inlines via metatable catch-all" $+    assertFilterConversion "filtering with metatable catch-all failed"+      "metatable-catch-all.lua"+      (doc . para $ "four words, three spaces")+      (doc . para $ str "7")++  , testCase "Count blocks via Block-specific catch-all" $+    assertFilterConversion "filtering with Block catch-all failed"+      "block-count.lua"+      (doc $ para "one" <> para "two")+      (doc $ para "2")+  ]++assertFilterConversion :: String -> FilePath -> Pandoc -> Pandoc -> Assertion+assertFilterConversion msg filterPath docIn docExpected = do+  docEither <- runIOorExplode $+               runLuaFilter (Just "../data") ("lua" </> filterPath) [] docIn+  case docEither of+    Left _       -> fail "lua filter failed"+    Right docRes -> assertEqual msg docExpected docRes++roundtripEqual :: (Eq a, FromLuaStack a, ToLuaStack a) => a -> IO Bool+roundtripEqual x = (x ==) <$> roundtripped+ where+  roundtripped :: (FromLuaStack a, ToLuaStack a) => IO a+  roundtripped = runLua $ do+    openlibs+    pushPandocModule (Just "../data")+    setglobal "pandoc"+    oldSize <- gettop+    push x+    size <- gettop+    when ((size - oldSize) /= 1) $+      error ("not exactly one additional element on the stack: " ++ show size)+    res <- peekEither (-1)+    case res of+      Left _  -> error "could not read from stack"+      Right y -> return y
+ test/Tests/Old.hs view
@@ -0,0 +1,281 @@+module Tests.Old (tests) where++import Data.Algorithm.Diff+import Prelude hiding (readFile)+import System.Exit+import System.FilePath (joinPath, splitDirectories, (<.>), (</>))+import System.IO.Temp (withTempFile)+import System.Process (runProcess, waitForProcess)+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.Golden.Advanced (goldenTest)+import Tests.Helpers hiding (test)+import qualified Text.Pandoc.UTF8 as UTF8++tests :: [TestTree]+tests = [ testGroup "markdown"+          [ testGroup "writer"+            $ writerTests "markdown" ++ lhsWriterTests "markdown"+          , testGroup "reader"+            [ test "basic" ["-r", "markdown", "-w", "native", "-s"]+              "testsuite.txt" "testsuite.native"+            , test "tables" ["-r", "markdown", "-w", "native", "--columns=80"]+              "tables.txt" "tables.native"+            , test "pipe tables" ["-r", "markdown", "-w", "native", "--columns=80"]+              "pipe-tables.txt" "pipe-tables.native"+            , test "more" ["-r", "markdown", "-w", "native", "-s"]+              "markdown-reader-more.txt" "markdown-reader-more.native"+            , lhsReaderTest "markdown+lhs"+            ]+          , testGroup "citations"+            [ test "citations" ["-r", "markdown", "-w", "native"]+              "markdown-citations.txt" "markdown-citations.native"+            ]+          ]+        , testGroup "rst"+          [ testGroup "writer" (writerTests "rst" ++ lhsWriterTests "rst")+          , testGroup "reader"+            [ test "basic" ["-r", "rst+smart", "-w", "native",+              "-s", "--columns=80"] "rst-reader.rst" "rst-reader.native"+            , test "tables" ["-r", "rst", "-w", "native", "--columns=80"]+              "tables.rst" "tables-rstsubset.native"+            , lhsReaderTest "rst+lhs"+            ]+          ]+        , testGroup "latex"+          [ testGroup "writer" (writerTests "latex" ++ lhsWriterTests "latex")+          , testGroup "reader"+            [ test "basic" ["-r", "latex+raw_tex", "-w", "native", "-s"]+              "latex-reader.latex" "latex-reader.native"+            , lhsReaderTest "latex+lhs"+            ]+          ]+        , testGroup "html"+          [ testGroup "writer" (writerTests "html4" ++ writerTests "html5" +++                                lhsWriterTests "html")+          , test "reader" ["-r", "html", "-w", "native", "-s"]+            "html-reader.html" "html-reader.native"+          ]+        , testGroup "s5"+          [ s5WriterTest "basic" ["-s"] "s5"+          , s5WriterTest "fancy" ["-s","-m","-i"] "s5"+          , s5WriterTest "fragment" [] "html4"+          , s5WriterTest "inserts"  ["-s", "-H", "insert",+            "-B", "insert", "-A", "insert", "-c", "main.css"] "html4"+          ]+        , testGroup "textile"+          [ testGroup "writer" $ writerTests "textile"+          , test "reader" ["-r", "textile", "-w", "native", "-s"]+            "textile-reader.textile" "textile-reader.native"+          ]+        , testGroup "docbook"+          [ testGroup "writer" $ writerTests "docbook4"+          , test "reader" ["-r", "docbook", "-w", "native", "-s"]+            "docbook-reader.docbook" "docbook-reader.native"+          , test "reader" ["-r", "docbook", "-w", "native", "-s"]+            "docbook-xref.docbook" "docbook-xref.native"+          ]+        , testGroup "docbook5"+          [ testGroup "writer" $ writerTests "docbook5"+          ]+        , testGroup "jats"+          [ testGroup "writer" $ writerTests "jats"+          ]+        , testGroup "native"+          [ testGroup "writer" $ writerTests "native"+          , test "reader" ["-r", "native", "-w", "native", "-s"]+            "testsuite.native" "testsuite.native"+          ]+        , testGroup "fb2"+          [ fb2WriterTest "basic" [] "fb2/basic.markdown" "fb2/basic.fb2"+          , fb2WriterTest "titles" [] "fb2/titles.markdown" "fb2/titles.fb2"+          , fb2WriterTest "images" [] "fb2/images.markdown" "fb2/images.fb2"+          , fb2WriterTest "images-embedded" [] "fb2/images-embedded.html" "fb2/images-embedded.fb2"+          , fb2WriterTest "math" [] "fb2/math.markdown" "fb2/math.fb2"+          , fb2WriterTest "tables" [] "tables.native" "tables.fb2"+          , fb2WriterTest "testsuite" [] "testsuite.native" "writer.fb2"+          ]+        , testGroup "mediawiki"+          [ testGroup "writer" $ writerTests "mediawiki"+          , test "reader" ["-r", "mediawiki", "-w", "native", "-s"]+            "mediawiki-reader.wiki" "mediawiki-reader.native"+          ]+        , testGroup "vimwiki"+          [ test "reader" ["-r", "vimwiki", "-w", "native", "-s"]+            "vimwiki-reader.wiki" "vimwiki-reader.native"+          ]+        , testGroup "dokuwiki"+          [ testGroup "writer" $ writerTests "dokuwiki"+          , test "inline_formatting" ["-r", "native", "-w", "dokuwiki", "-s"]+            "dokuwiki_inline_formatting.native" "dokuwiki_inline_formatting.dokuwiki"+          , test "multiblock table" ["-r", "native", "-w", "dokuwiki", "-s"]+            "dokuwiki_multiblock_table.native" "dokuwiki_multiblock_table.dokuwiki"+          , test "external images" ["-r", "native", "-w", "dokuwiki", "-s"]+            "dokuwiki_external_images.native" "dokuwiki_external_images.dokuwiki"+          ]+        , testGroup "opml"+          [ test "basic" ["-r", "native", "-w", "opml", "--columns=78", "-s"]+             "testsuite.native" "writer.opml"+          , test "reader" ["-r", "opml", "-w", "native", "-s"]+            "opml-reader.opml" "opml-reader.native"+          ]+        , testGroup "haddock"+          [ testGroup "writer" $ writerTests "haddock"+          , test "reader" ["-r", "haddock", "-w", "native", "-s"]+            "haddock-reader.haddock" "haddock-reader.native"+          ]+        , testGroup "txt2tags"+          [ test "reader" ["-r", "t2t", "-w", "native", "-s"]+              "txt2tags.t2t" "txt2tags.native" ]+        , testGroup "epub" [+            test "features" ["-r", "epub", "-w", "native"]+              "epub/features.epub" "epub/features.native"+          , test "wasteland" ["-r", "epub", "-w", "native"]+              "epub/wasteland.epub" "epub/wasteland.native"+          , test "formatting" ["-r", "epub", "-w", "native"]+              "epub/formatting.epub" "epub/formatting.native"+          ]+        , testGroup "twiki"+          [ test "reader" ["-r", "twiki", "-w", "native", "-s"]+              "twiki-reader.twiki" "twiki-reader.native" ]+        , testGroup "tikiwiki"+          [ test "reader" ["-r", "tikiwiki", "-w", "native", "-s"]+              "tikiwiki-reader.tikiwiki" "tikiwiki-reader.native" ]+        , testGroup "other writers" $ map (\f -> testGroup f $ writerTests f)+          [ "opendocument" , "context" , "texinfo", "icml", "tei"+          , "man" , "plain" , "rtf", "org", "asciidoc", "zimwiki"+          ]+        , testGroup "writers-lang-and-dir"+          [ test "latex" ["-f", "native", "-t", "latex", "-s"]+            "writers-lang-and-dir.native" "writers-lang-and-dir.latex"+          , test "context" ["-f", "native", "-t", "context", "-s"]+            "writers-lang-and-dir.native" "writers-lang-and-dir.context"+          ]+        , testGroup "muse"+          [ testGroup "writer" $ writerTests "muse"+          ]+        , testGroup "ms"+          [ testGroup "writer" $ writerTests "ms"+          ]+        , testGroup "creole"+          [ test "reader" ["-r", "creole", "-w", "native", "-s"]+            "creole-reader.txt" "creole-reader.native"+          ]+        ]++-- makes sure file is fully closed after reading+readFile' :: FilePath -> IO String+readFile' f = do s <- UTF8.readFile f+                 return $! (length s `seq` s)++lhsWriterTests :: String -> [TestTree]+lhsWriterTests format+  = [ t "lhs to normal" format+    , t "lhs to lhs"    (format ++ "+lhs")+    ]+  where+    t n f = test n ["--wrap=preserve", "-r", "native", "-s", "-w", f]+             "lhs-test.native" ("lhs-test" <.> f)++lhsReaderTest :: String -> TestTree+lhsReaderTest format =+  test "lhs" ["-r", format, "-w", "native"]+    ("lhs-test" <.> format) norm+   where norm = if format == "markdown+lhs"+                   then "lhs-test-markdown.native"+                   else "lhs-test.native"++writerTests :: String -> [TestTree]+writerTests format+  = [ test "basic"  (opts ++ ["-s"]) "testsuite.native" ("writer" <.> format)+    , test "tables" opts             "tables.native"    ("tables" <.> format)+    ]+  where+    opts = ["-r", "native", "-w", format, "--columns=78",+            "--variable", "pandoc-version="]++s5WriterTest :: String -> [String] -> String -> TestTree+s5WriterTest modifier opts format+  = test (format ++ " writer (" ++ modifier ++ ")")+    (["-r", "native", "-w", format] ++ opts)+    "s5.native"  ("s5-" ++ modifier <.> "html")++fb2WriterTest :: String -> [String] -> String -> String -> TestTree+fb2WriterTest title opts inputfile normfile =+  testWithNormalize (ignoreBinary . formatXML)+                    title (["-t", "fb2"]++opts) inputfile normfile+  where+    formatXML xml = splitTags $ zip xml (drop 1 xml)+    splitTags []               = []+    splitTags [end]            = fst end : snd end : []+    splitTags (('>','<'):rest) = ">\n" ++ splitTags rest+    splitTags ((c,_):rest)     = c : splitTags rest+    ignoreBinary = unlines . filter (not . startsWith "<binary ") . lines+    startsWith tag str = all (uncurry (==)) $ zip tag str++-- | Run a test without normalize function, return True if test passed.+test :: String    -- ^ Title of test+     -> [String]  -- ^ Options to pass to pandoc+     -> String    -- ^ Input filepath+     -> FilePath  -- ^ Norm (for test results) filepath+     -> TestTree+test = testWithNormalize id++-- | Run a test with normalize function, return True if test passed.+testWithNormalize  :: (String -> String) -- ^ Normalize function for output+                   -> String    -- ^ Title of test+                   -> [String]  -- ^ Options to pass to pandoc+                   -> String    -- ^ Input filepath+                   -> FilePath  -- ^ Norm (for test results) filepath+                   -> TestTree+testWithNormalize normalizer testname opts inp norm =+  goldenTest testname getExpected getActual+    (compareValues norm options) updateGolden+  where getExpected = normalizer <$> readFile' norm+        getActual   =+          withTempFile "." "pandoc-test" $ \outputPath hOut -> do+            withTempFile "." "pandoc-test" $ \errorPath hErr -> do+              pandocPath <- findPandoc+              let mbDynlibDir = findDynlibDir (reverse $+                                 splitDirectories pandocPath)+              let dynlibEnv = case mbDynlibDir of+                                   Nothing  -> []+                                   Just d   -> [("DYLD_LIBRARY_PATH", d),+                                                ("LD_LIBRARY_PATH", d)]+              let env = dynlibEnv +++                        [("TMP","."),("LANG","en_US.UTF-8"),("HOME", "./"),+                         ("pandoc_datadir","..")]+              ph <- runProcess pandocPath options Nothing+                    (Just env) Nothing (Just hOut) (Just hErr)+              ec <- waitForProcess ph+              if ec == ExitSuccess+                 then+                   -- filter \r so the tests will work on Windows machines+                   (filter (/='\r') . normalizer) <$> readFile' outputPath+                 else do+                   errcontents <- UTF8.readFile errorPath+                   fail $ "Pandoc failed with " ++ show ec +++                           if null errcontents+                              then ""+                              else '\n':errcontents+        updateGolden = UTF8.writeFile norm+        options = ["--quiet"] ++ [inp] ++ opts++compareValues :: FilePath -> [String] -> String -> String -> IO (Maybe String)+compareValues norm options expected actual = do+  pandocPath <- findPandoc+  let cmd  = pandocPath ++ " " ++ unwords options+  let dash = replicate 72 '-'+  let diff = getDiff (lines actual) (lines expected)+  if expected == actual+     then return Nothing+     else return $ Just $+        '\n' : dash +++        "\n--- " ++ norm +++        "\n+++ " ++ cmd ++ "\n" +++        showDiff (1,1) diff ++ dash++findDynlibDir :: [FilePath] -> Maybe FilePath+findDynlibDir []           = Nothing+findDynlibDir ("build":xs) = Just $ joinPath (reverse xs) </> "build"+findDynlibDir (_:xs)       = findDynlibDir xs+
+ test/Tests/Readers/Creole.hs view
@@ -0,0 +1,273 @@+{-# LANGUAGE OverloadedStrings #-}+module Tests.Readers.Creole (tests) where++import Data.Text (Text)+import qualified Data.Text as T+import Test.Tasty+import Tests.Helpers+import Text.Pandoc+import Text.Pandoc.Arbitrary ()+import Text.Pandoc.Builder++creole :: Text -> Pandoc+creole = purely $ readCreole def{ readerStandalone = True }++infix 4 =:+(=:) :: ToString c+     => String -> (Text, c) -> TestTree+(=:) = test creole++tests :: [TestTree]+tests = [+  testGroup "Basic Text Formatting" [+          "bold, single line, fully delimited" =:+          "only **bold** is bold"+          =?> para ("only " <> strong "bold" <> " is bold")+        , "italics, single line, fully delimited" =:+          "only //this// is in italics"+          =?> para ("only " <> emph "this" <> " is in italics")+        , "bold in italics, fully delimited" =:+          "//**this**// is in bold italics"+          =?> para (emph (strong "this") <> " is in bold italics")+        , "italics in bold, fully delimited" =:+          "**//this//** is in bold italics"+          =?> para (strong (emph "this") <> " is in bold italics")++        , "escape bold marker" =:+          "~**not bold" =?> para "**not bold"+        , "escape italics marker" =:+          "~//not in italics" =?> para "//not in italics"++        , "inline nowiki, simple" =:+          "this is {{{**not** ~interpreted}}} at all"+          =?> para ("this is " <> code "**not** ~interpreted" <> " at all")+        , "inline nowiki, curly braces inside" =:+          "this is {{{{{{//including// some `}' chars}}}}}}"+          =?> para ("this is " <> code "{{{//including// some `}' chars}}}")++        , "placeholder" =:+          "foo <<<place holder>>> bar"+          =?> para "foo bar"+        , "placeholder escaped" =:+          "foo ~<<<no place holder>>> bar"+          =?> para "foo <<<no place holder>>> bar"+        ]+  , testGroup "Headers" [+          "header level 1, no space, no trailing =" =:+          "= Top-Level Header"+          =?> header 1 (str "Top-Level Header")+        , "header level 1, leading space, trailing =" =:+          " = Top-Level Header = "+          =?> header 1 (str "Top-Level Header")+        , "header level 2, no space, no trailing =" =:+          "== Second Level"+          =?> header 2 (str "Second Level")+        , "header level 2, leading space, no trailing =" =:+          "   == Second Level"+          =?> header 2 (str "Second Level")+        , "header level 3, no space, no trailing =" =:+          "=== Third"+          =?> header 3 (str "Third")+        , "header level 3, no space, > 3 trailing =" =:+          "=== Third ======="+          =?> header 3 (str "Third")+        , "header level 4, no space, no trailing =" =:+          "==== Fourth Level Heading"+          =?> header 4 (str "Fourth Level Heading")+        , "header level 4, no space, < 4 trailing =" =:+          "==== Fourth Level Heading =="+          =?> header 4 (str "Fourth Level Heading")+        , "header level 5, no space, no trailing =" =:+          "===== Fifth"+          =?> header 5 (str "Fifth")+        , "header level 6, no space, no trailing =" =:+          "====== Sixth"+          =?> header 6 (str "Sixth")+        ]+  , testGroup "Paragraphs" [+          "paragraphs: multiple, one line" =:+          "first line\n\nanother line\n"+          =?> para "first line" <> para "another line"+          ]+  , testGroup "Lists" [+          "unordered list, two entries, one separating space" =:+          "* foo\n* bar"+          =?> bulletList [ plain "foo", plain "bar" ]+        , "unordered list, three entries, one separating space" =:+          "* foo\n* bar\n* baz"+          =?> bulletList [ plain "foo", plain "bar", plain "baz" ]+        , "para followed by, unordered list, two entries, one separating space" =:+          "blubber\n* foo\n* bar"+          =?> para "blubber" <> bulletList [ plain "foo", plain "bar" ]+        , "nested unordered list, one separating space" =:+          "* foo\n** bar\n** baz\n* blubb"+          =?> bulletList [ plain "foo"+                         <> bulletList [ plain "bar", plain "baz" ]+                         , plain "blubb" ]+        , "nested many unordered lists, one separating space" =:+          ("* foo\n** bar\n*** third\n*** third two\n** baz\n*** third again\n"+           <> "**** fourth\n***** fith\n* blubb")+          =?> bulletList [ plain "foo"+                           <> bulletList [ plain "bar"+                                           <> bulletList [ plain "third"+                                                         , plain "third two"]+                                         , plain "baz"+                                           <> bulletList [ plain "third again"+                                                         <> bulletList [+                                                             plain "fourth"+                                                             <> bulletList [+                                                                 plain "fith"+                                                                 ]+                                                             ]+                                                         ]+                                         ]+                         , plain "blubb" ]+        , "nested unordered list, mixed separating space" =:+          "*foo\n   **   bar\n    **baz\n *      blubb"+          =?> bulletList [ plain "foo"+                         <> bulletList [ plain "bar", plain "baz" ]+                         , plain "blubb" ]+        , "ordered list, two entries, one separating space" =:+          "# foo\n# bar"+          =?> orderedList [ plain "foo", plain "bar" ]+        , "ordered list, three entries, one separating space" =:+          "# foo\n# bar\n# baz"+          =?> orderedList [ plain "foo", plain "bar", plain "baz" ]+        , "para followed by, ordered list, two entries, one separating space" =:+          "blubber\n# foo\n# bar"+          =?> para "blubber" <> orderedList [ plain "foo", plain "bar" ]+        , "nested ordered list, one separating space" =:+          "# foo\n## bar\n## baz\n# blubb"+          =?> orderedList [ plain "foo"+                         <> orderedList [ plain "bar", plain "baz" ]+                         , plain "blubb" ]+        , "nested many ordered lists, one separating space" =:+          ("# foo\n## bar\n### third\n### third two\n## baz\n### third again\n"+           <> "#### fourth\n##### fith\n# blubb")+          =?> orderedList [ plain "foo"+                           <> orderedList [ plain "bar"+                                           <> orderedList [ plain "third"+                                                         , plain "third two"]+                                         , plain "baz"+                                           <> orderedList [ plain "third again"+                                                         <> orderedList [+                                                             plain "fourth"+                                                             <> orderedList [+                                                                 plain "fith"+                                                                 ]+                                                             ]+                                                         ]+                                         ]+                         , plain "blubb" ]+        , "nested ordered list, mixed separating space" =:+          "#foo\n   ##   bar\n    ##baz\n #      blubb"+          =?> orderedList [ plain "foo"+                         <> orderedList [ plain "bar", plain "baz" ]+                         , plain "blubb" ]+        , "mixed nested ordered and unordered lists, one separating space" =:+          ("# foo\n** bar\n### third\n### third two\n** baz\n### third again\n"+           <> "#### fourth\n***** fith\n# blubb")+          =?> orderedList [ plain "foo"+                           <> bulletList [ plain "bar"+                                           <> orderedList [ plain "third"+                                                         , plain "third two"]+                                         , plain "baz"+                                           <> orderedList [ plain "third again"+                                                         <> orderedList [+                                                             plain "fourth"+                                                             <> bulletList [+                                                                 plain "fith"+                                                                 ]+                                                             ]+                                                         ]+                                         ]+                         , plain "blubb" ]+        ]+  , testGroup "NoWiki" [+          "quoted block, simple" =:+          "{{{\nfoo bar\n  //baz//\n}}}"+          =?> codeBlock "foo bar\n  //baz//"+        , "quoted block, curly bracket exception" =:+          "{{{\nfoo bar\n  }}}\nbaz\n }}}\n}}}"+          =?> codeBlock "foo bar\n }}}\nbaz\n}}}"+        , "forced line breaks" =:+          "{{{no break!\\\\here}}} but a break\\\\here!"+          =?> para (code "no break!\\\\here" <> " but a break"+                    <> linebreak <> "here!")+        ]+  , testGroup "Images and Links" [+          "image simple" =:+          "{{foo.png}}" =?> para (image "foo.png" "" (str ""))+        , "image with alt text" =:+          "Image of a bar: {{/path/to/bar.png|A Bar}} look at it!"+          =?> para ("Image of a bar: "+                    <> image "/path/to/bar.png" "" (str "A Bar") <> " look at it!")++        , "auto link" =:+          "foo http://foo.example.com/bar/baz.html bar"+          =?> para ("foo "+                    <> link "http://foo.example.com/bar/baz.html" ""+                     (str "http://foo.example.com/bar/baz.html")+                    <> " bar")+        , "escaped auto link" =:+          "foo ~http://foo.example.com/bar/baz.html bar"+          =?> para ("foo http://foo.example.com/bar/baz.html bar")+        , "wiki link simple" =:+          "foo [[http://foo.example.com/foo.png]] bar"+          =?> para ("foo "+                    <> link "http://foo.example.com/foo.png" ""+                     (str "http://foo.example.com/foo.png")+                    <> " bar")+        , "wiki link with name" =:+          "foo [[http://foo.example.com/foo.png|my link]] bar"+          =?> para ("foo "+                    <> link "http://foo.example.com/foo.png" ""+                     (str "my link")+                    <> " bar")+        , "image link" =:+          "[[http://foo.example.com/|{{foo.png}}]]"+          =?> para (link "http://foo.example.com/" "" (image "foo.png" "" (str "")))+        ]+  , testGroup "Table" [+          "Table with Header" =:+          T.unlines [ "|= Foo |= Bar |= Baz  |"+                    , "| One  | Two  | Three |"+                    , "| 1    | 2    | 3     |"+                    , "| A    | B    | C     |"+                    ]+          =?> simpleTable+            [plain "Foo", plain "Bar" , plain "Baz"]+            [[plain "One", plain "Two" , plain "Three"]+            ,[plain "1", plain "2" , plain "3"]+            ,[plain "A", plain "B" , plain "C"]]+        , "Table without Header" =:+          T.unlines [ "| One  | Two  | Three |"+                    , "| 1    | 2    | 3     |"+                    , "| A    | B    | C     |"+                    ]+          =?> simpleTable [mempty]+            [[plain "One", plain "Two" , plain "Three"]+            ,[plain "1", plain "2" , plain "3"]+            ,[plain "A", plain "B" , plain "C"]]+        , "Table without Header, no markers at line ends" =:+          T.unlines [ "| One  | Two  | Three"+                    , "| 1    | 2    | 3"+                    , "| A    | B    | C  "+                    ]+          =?> simpleTable [mempty]+            [[plain "One", plain "Two" , plain "Three"]+            ,[plain "1", plain "2" , plain "3"]+            ,[plain "A", plain "B" , plain "C"]]+        , "Table with Header, with formatting" =:+          T.unlines [ "|= **Foo**        |= **Bar** |= **Baz**  |"+                    , "|//one// element  |//second// elt|Three  |"+                    , "| {{{1}}}    | {{{{}}}}    | [[link]]    |"+                    ]+          =?> simpleTable+            [plain $ strong "Foo", plain $ strong "Bar" , plain $ strong "Baz"]+            [[plain (emph "one" <> " element"), plain (emph "second" <> " elt")+             ,plain "Three"]+            ,[plain $ code "1", plain $ code "{}"+             ,plain $ link "link" "" (str "link")]]+        ]+  ]
+ test/Tests/Readers/Docx.hs view
@@ -0,0 +1,347 @@+module Tests.Readers.Docx (tests) where++import Codec.Archive.Zip+import qualified Data.ByteString as BS+import qualified Data.ByteString.Lazy as B+import qualified Data.Map as M+import qualified Data.Text as T+import System.IO.Unsafe+import Test.Tasty+import Test.Tasty.HUnit+import Tests.Helpers+import Text.Pandoc+import qualified Text.Pandoc.Class as P+import Text.Pandoc.MediaBag (MediaBag, lookupMedia, mediaDirectory)+import Text.Pandoc.UTF8 as UTF8++-- We define a wrapper around pandoc that doesn't normalize in the+-- tests. Since we do our own normalization, we want to make sure+-- we're doing it right.++data NoNormPandoc = NoNormPandoc {unNoNorm :: Pandoc}+                 deriving Show++noNorm :: Pandoc -> NoNormPandoc+noNorm = NoNormPandoc++defopts :: ReaderOptions+defopts = def{ readerExtensions = getDefaultExtensions "docx" }++instance ToString NoNormPandoc where+  toString d = T.unpack $ purely (writeNative def{ writerTemplate = s }) $ toPandoc d+   where s = case d of+                  NoNormPandoc (Pandoc (Meta m) _)+                    | M.null m  -> Nothing+                    | otherwise -> Just "" -- need this to get meta output++instance ToPandoc NoNormPandoc where+  toPandoc = unNoNorm++compareOutput :: ReaderOptions+                 -> FilePath+                 -> FilePath+                 -> IO (NoNormPandoc, NoNormPandoc)+compareOutput opts docxFile nativeFile = do+  df <- B.readFile docxFile+  nf <- UTF8.toText <$> BS.readFile nativeFile+  p <- runIOorExplode $ readDocx opts df+  df' <- runIOorExplode $ readNative def nf+  return $ (noNorm p, noNorm df')++testCompareWithOptsIO :: ReaderOptions -> String -> FilePath -> FilePath -> IO TestTree+testCompareWithOptsIO opts name docxFile nativeFile = do+  (dp, np) <- compareOutput opts docxFile nativeFile+  return $ test id name (dp, np)++testCompareWithOpts :: ReaderOptions -> String -> FilePath -> FilePath -> TestTree+testCompareWithOpts opts name docxFile nativeFile =+  unsafePerformIO $ testCompareWithOptsIO opts name docxFile nativeFile++testCompare :: String -> FilePath -> FilePath -> TestTree+testCompare = testCompareWithOpts defopts++testForWarningsWithOptsIO :: ReaderOptions -> String -> FilePath -> [String] -> IO TestTree+testForWarningsWithOptsIO opts name docxFile expected = do+  df <- B.readFile docxFile+  logs <-  runIOorExplode $ setVerbosity ERROR >> readDocx opts df >> P.getLog+  let warns = [m | DocxParserWarning m <- logs]+  return $ test id name (unlines warns, unlines expected)++testForWarningsWithOpts :: ReaderOptions -> String -> FilePath -> [String] -> TestTree+testForWarningsWithOpts opts name docxFile expected =+  unsafePerformIO $ testForWarningsWithOptsIO opts name docxFile expected++-- testForWarnings :: String -> FilePath -> [String] -> TestTree+-- testForWarnings = testForWarningsWithOpts defopts++getMedia :: FilePath -> FilePath -> IO (Maybe B.ByteString)+getMedia archivePath mediaPath = do+  zf <- B.readFile archivePath >>= return . toArchive+  return $ findEntryByPath ("word/" ++ mediaPath) zf >>= (Just . fromEntry)++compareMediaPathIO :: FilePath -> MediaBag -> FilePath -> IO Bool+compareMediaPathIO mediaPath mediaBag docxPath = do+  docxMedia <- getMedia docxPath mediaPath+  let mbBS   = case lookupMedia mediaPath mediaBag of+                 Just (_, bs) -> bs+                 Nothing      -> error ("couldn't find " +++                                        mediaPath +++                                        " in media bag")+      docxBS = case docxMedia of+                 Just bs -> bs+                 Nothing -> error ("couldn't find " +++                                   mediaPath +++                                   " in media bag")+  return $ mbBS == docxBS++compareMediaBagIO :: FilePath -> IO Bool+compareMediaBagIO docxFile = do+    df <- B.readFile docxFile+    mb <- runIOorExplode $ readDocx defopts df >> P.getMediaBag+    bools <- mapM+             (\(fp, _, _) -> compareMediaPathIO fp mb docxFile)+             (mediaDirectory mb)+    return $ and bools++testMediaBagIO :: String -> FilePath -> IO TestTree+testMediaBagIO name docxFile = do+  outcome <- compareMediaBagIO docxFile+  return $ testCase name (assertBool+                          ("Media didn't match media bag in file " ++ docxFile)+                          outcome)++testMediaBag :: String -> FilePath -> TestTree+testMediaBag name docxFile = unsafePerformIO $ testMediaBagIO name docxFile++tests :: [TestTree]+tests = [ testGroup "inlines"+          [ testCompare+            "font formatting"+            "docx/inline_formatting.docx"+            "docx/inline_formatting.native"+          , testCompare+            "font formatting with character styles"+            "docx/char_styles.docx"+            "docx/char_styles.native"+          , testCompare+            "hyperlinks"+            "docx/links.docx"+            "docx/links.native"+          , testCompare+            "inline image"+            "docx/image.docx"+            "docx/image_no_embed.native"+          , testCompare+            "VML image"+            "docx/image_vml.docx"+            "docx/image_vml.native"+          , testCompare+            "inline image in links"+            "docx/inline_images.docx"+            "docx/inline_images.native"+          , testCompare+            "handling unicode input"+            "docx/unicode.docx"+            "docx/unicode.native"+          , testCompare+            "literal tabs"+            "docx/tabs.docx"+            "docx/tabs.native"+          , testCompare+            "special punctuation"+            "docx/special_punctuation.docx"+            "docx/special_punctuation.native"+          , testCompare+            "normalizing inlines"+            "docx/normalize.docx"+            "docx/normalize.native"+          , testCompare+            "normalizing inlines deep inside blocks"+            "docx/deep_normalize.docx"+            "docx/deep_normalize.native"+          , testCompare+            "move trailing spaces outside of formatting"+            "docx/trailing_spaces_in_formatting.docx"+            "docx/trailing_spaces_in_formatting.native"+          , testCompare+            "inline code (with VerbatimChar style)"+            "docx/inline_code.docx"+            "docx/inline_code.native"+          , testCompare+            "inline code in subscript and superscript"+            "docx/verbatim_subsuper.docx"+            "docx/verbatim_subsuper.native"+          ]+        , testGroup "blocks"+          [ testCompare+            "headers"+            "docx/headers.docx"+            "docx/headers.native"+          , testCompare+            "headers already having auto identifiers"+            "docx/already_auto_ident.docx"+            "docx/already_auto_ident.native"+          , testCompare+            "avoid zero-level headers"+            "docx/0_level_headers.docx"+            "docx/0_level_headers.native"+          , testCompare+            "nested anchor spans in header"+            "docx/nested_anchors_in_header.docx"+            "docx/nested_anchors_in_header.native"+          , testCompare+            "single numbered item not made into list"+            "docx/numbered_header.docx"+            "docx/numbered_header.native"+          , testCompare+            "enumerated headers not made into numbered list"+            "docx/enumerated_headings.docx"+            "docx/enumerated_headings.native"+          , testCompare+            "i18n blocks (headers and blockquotes)"+            "docx/i18n_blocks.docx"+            "docx/i18n_blocks.native"+          , testCompare+            "lists"+            "docx/lists.docx"+            "docx/lists.native"+          , testCompare+            "definition lists"+            "docx/definition_list.docx"+            "docx/definition_list.native"+          , testCompare+            "custom defined lists in styles"+            "docx/german_styled_lists.docx"+            "docx/german_styled_lists.native"+          , testCompare+            "user deletes bullet after list item (=> part of item par)"+            "docx/dummy_item_after_list_item.docx"+            "docx/dummy_item_after_list_item.native"+          , testCompare+            "user deletes bullet after par (=> new par)"+            "docx/dummy_item_after_paragraph.docx"+            "docx/dummy_item_after_paragraph.native"+          , testCompare+            "footnotes and endnotes"+            "docx/notes.docx"+            "docx/notes.native"+          , testCompare+            "links in footnotes and endnotes"+            "docx/link_in_notes.docx"+            "docx/link_in_notes.native"+          , testCompare+            "blockquotes (parsing indent as blockquote)"+            "docx/block_quotes.docx"+            "docx/block_quotes_parse_indent.native"+          , testCompare+            "hanging indents"+            "docx/hanging_indent.docx"+            "docx/hanging_indent.native"+          , testCompare+            "tables"+            "docx/tables.docx"+            "docx/tables.native"+          , testCompare+            "tables with lists in cells"+            "docx/table_with_list_cell.docx"+            "docx/table_with_list_cell.native"+          , testCompare+            "tables with one row"+            "docx/table_one_row.docx"+            "docx/table_one_row.native"+          , testCompare+            "code block"+            "docx/codeblock.docx"+            "docx/codeblock.native"+          , testCompare+            "dropcap paragraphs"+            "docx/drop_cap.docx"+            "docx/drop_cap.native"+          ]+        , testGroup "track changes"+          [ testCompare+            "insertion (default)"+            "docx/track_changes_insertion.docx"+            "docx/track_changes_insertion_accept.native"+          , testCompareWithOpts def{readerTrackChanges=AcceptChanges}+            "insert insertion (accept)"+            "docx/track_changes_insertion.docx"+            "docx/track_changes_insertion_accept.native"+          , testCompareWithOpts def{readerTrackChanges=RejectChanges}+            "remove insertion (reject)"+            "docx/track_changes_insertion.docx"+            "docx/track_changes_insertion_reject.native"+          , testCompare+            "deletion (default)"+            "docx/track_changes_deletion.docx"+            "docx/track_changes_deletion_accept.native"+          , testCompareWithOpts def{readerTrackChanges=AcceptChanges}+            "remove deletion (accept)"+            "docx/track_changes_deletion.docx"+            "docx/track_changes_deletion_accept.native"+          , testCompareWithOpts def{readerTrackChanges=RejectChanges}+            "insert deletion (reject)"+            "docx/track_changes_deletion.docx"+            "docx/track_changes_deletion_reject.native"+          , testCompareWithOpts def{readerTrackChanges=AllChanges}+            "keep insertion (all)"+            "docx/track_changes_deletion.docx"+            "docx/track_changes_deletion_all.native"+          , testCompareWithOpts def{readerTrackChanges=AllChanges}+            "keep deletion (all)"+            "docx/track_changes_deletion.docx"+            "docx/track_changes_deletion_all.native"+          , testCompareWithOpts def{readerTrackChanges=AcceptChanges}+            "move text (accept)"+            "docx/track_changes_move.docx"+            "docx/track_changes_move_accept.native"+          , testCompareWithOpts def{readerTrackChanges=RejectChanges}+            "move text (reject)"+            "docx/track_changes_move.docx"+            "docx/track_changes_move_reject.native"+          , testCompareWithOpts def{readerTrackChanges=AllChanges}+            "move text (all)"+            "docx/track_changes_move.docx"+            "docx/track_changes_move_all.native"+          , testCompareWithOpts def{readerTrackChanges=AcceptChanges}+            "comments (accept -- no comments)"+            "docx/comments.docx"+            "docx/comments_no_comments.native"+          , testCompareWithOpts def{readerTrackChanges=RejectChanges}+            "comments (reject -- comments)"+            "docx/comments.docx"+            "docx/comments_no_comments.native"+          , testCompareWithOpts def{readerTrackChanges=AllChanges}+            "comments (all comments)"+            "docx/comments.docx"+            "docx/comments.native"+          , testForWarningsWithOpts def{readerTrackChanges=AcceptChanges}+            "comment warnings (accept -- no warnings)"+            "docx/comments_warning.docx"+            []+          , testForWarningsWithOpts def{readerTrackChanges=RejectChanges}+            "comment warnings (reject -- no warnings)"+            "docx/comments_warning.docx"+            []+          , testForWarningsWithOpts def{readerTrackChanges=AllChanges}+            "comment warnings (all)"+            "docx/comments_warning.docx"+            ["Docx comment 1 will not retain formatting"]+          ]+        , testGroup "media"+          [ testMediaBag+            "image extraction"+            "docx/image.docx"+          ]+        , testGroup "metadata"+          [ testCompareWithOpts def{readerStandalone=True}+            "metadata fields"+            "docx/metadata.docx"+            "docx/metadata.native"+          , testCompareWithOpts def{readerStandalone=True}+            "stop recording metadata with normal text"+            "docx/metadata_after_normal.docx"+            "docx/metadata_after_normal.native"+          ]++        ]
+ test/Tests/Readers/EPUB.hs view
@@ -0,0 +1,40 @@+module Tests.Readers.EPUB (tests) where++import qualified Data.ByteString.Lazy as BL+import Test.Tasty+import Test.Tasty.HUnit+import qualified Text.Pandoc.Class as P+import Text.Pandoc.MediaBag (MediaBag, mediaDirectory)+import Text.Pandoc.Options+import Text.Pandoc.Readers.EPUB++getMediaBag :: FilePath -> IO MediaBag+getMediaBag fp = do+  bs <- BL.readFile fp+  P.runIOorExplode $ do+    readEPUB def bs+    P.getMediaBag++testMediaBag :: FilePath -> [(String, String, Int)] -> IO ()+testMediaBag fp bag = do+  actBag <- (mediaDirectory <$> getMediaBag fp)+  assertBool (show "MediaBag did not match:\nExpected: "+             ++ show bag+             ++ "\nActual: "+             ++ show actBag)+             (actBag == bag)++featuresBag :: [(String, String, Int)]+featuresBag = [("img/check.gif","image/gif",1340)+              ,("img/check.jpg","image/jpeg",2661)+              ,("img/check.png","image/png",2815)+              ,("img/multiscripts_and_greek_alphabet.png","image/png",10060)+              ]++tests :: [TestTree]+tests =+  [ testGroup "EPUB Mediabag"+    [ testCase "features bag"+      (testMediaBag "epub/img.epub" featuresBag)+    ]+  ]
+ test/Tests/Readers/HTML.hs view
@@ -0,0 +1,54 @@+{-# LANGUAGE OverloadedStrings #-}+module Tests.Readers.HTML (tests) where++import Data.Text (Text)+import Test.Tasty+import Tests.Helpers+import Text.Pandoc+import Text.Pandoc.Arbitrary ()+import Text.Pandoc.Builder++html :: Text -> Pandoc+html = purely $ readHtml def++htmlNativeDivs :: Text -> Pandoc+htmlNativeDivs = purely $ readHtml def { readerExtensions = enableExtension Ext_native_divs $ readerExtensions def }++tests :: [TestTree]+tests = [ testGroup "base tag"+          [ test html "simple" $+            "<head><base href=\"http://www.w3schools.com/images/foo\" ></head><body><img src=\"stickman.gif\" alt=\"Stickman\"></head>" =?>+            plain (image "http://www.w3schools.com/images/stickman.gif" "" (text "Stickman"))+          , test html "slash at end of base" $+            "<head><base href=\"http://www.w3schools.com/images/\" ></head><body><img src=\"stickman.gif\" alt=\"Stickman\"></head>" =?>+            plain (image "http://www.w3schools.com/images/stickman.gif" "" (text "Stickman"))+          , test html "slash at beginning of href" $+            "<head><base href=\"http://www.w3schools.com/images/\" ></head><body><img src=\"/stickman.gif\" alt=\"Stickman\"></head>" =?>+            plain (image "http://www.w3schools.com/stickman.gif" "" (text "Stickman"))+          , test html "absolute URL" $+            "<head><base href=\"http://www.w3schools.com/images/\" ></head><body><img src=\"http://example.com/stickman.gif\" alt=\"Stickman\"></head>" =?>+            plain (image "http://example.com/stickman.gif" "" (text "Stickman"))+          ]+        , testGroup "anchors"+          [ test html "anchor without href" $ "<a name=\"anchor\"/>" =?>+            plain (spanWith ("anchor",[],[]) mempty)+          ]+        , testGroup "lang"+          [ test html "lang on <html>" $ "<html lang=\"es\">hola" =?>+            setMeta "lang" (text "es") (doc (plain (text "hola")))+          , test html "xml:lang on <html>" $ "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"es\"><head></head><body>hola</body></html>" =?>+            setMeta "lang" (text "es") (doc (plain (text "hola")))+          ]+        , testGroup "main"+          [ test htmlNativeDivs "<main> becomes <div role=main>" $ "<main>hello</main>" =?>+            doc (divWith ("", [], [("role", "main")]) (plain (text "hello")))+          , test htmlNativeDivs "<main role=X> becomes <div role=X>" $ "<main role=foobar>hello</main>" =?>+            doc (divWith ("", [], [("role", "foobar")]) (plain (text "hello")))+          , test htmlNativeDivs "<main> has attributes preserved" $ "<main id=foo class=bar data-baz=qux>hello</main>" =?>+            doc (divWith ("foo", ["bar"], [("role", "main"), ("data-baz", "qux")]) (plain (text "hello")))+          , test htmlNativeDivs "<main> closes <p>" $ "<p>hello<main>main content</main>" =?>+            doc (para (text "hello") <> divWith ("", [], [("role", "main")]) (plain (text "main content")))+          , test htmlNativeDivs "<main> followed by text" $ "<main>main content</main>non-main content" =?>+            doc (divWith ("", [], [("role", "main")]) (plain (text "main content")) <> plain (text "non-main content"))+          ]+        ]
+ test/Tests/Readers/LaTeX.hs view
@@ -0,0 +1,324 @@+{-# LANGUAGE OverloadedStrings #-}+module Tests.Readers.LaTeX (tests) where++import Data.Text (Text)+import qualified Data.Text as T+import Test.Tasty+import Tests.Helpers+import Text.Pandoc+import Text.Pandoc.Arbitrary ()+import Text.Pandoc.Builder++latex :: Text -> Pandoc+latex = purely $ readLaTeX def{+                   readerExtensions = getDefaultExtensions "latex" }++infix 4 =:+(=:) :: ToString c+     => String -> (Text, c) -> TestTree+(=:) = test latex++simpleTable' :: [Alignment] -> [[Blocks]] -> Blocks+simpleTable' aligns = table "" (zip aligns (repeat 0.0))+                      (map (const mempty) aligns)++tests :: [TestTree]+tests = [ testGroup "basic"+          [ "simple" =:+            "word" =?> para "word"+          , "space" =:+            "some text" =?> para "some text"+          , "emphasized" =:+            "\\emph{emphasized}" =?> para (emph "emphasized")+          ]++        , testGroup "headers"+          [ "level 1" =:+            "\\section{header}" =?> headerWith ("header",[],[]) 1 "header"+          , "level 2" =:+            "\\subsection{header}" =?> headerWith ("header",[],[]) 2 "header"+          , "level 3" =:+            "\\subsubsection{header}" =?> headerWith ("header",[],[]) 3 "header"+          , "emph" =:+            "\\section{text \\emph{emph}}" =?>+             headerWith ("text-emph",[],[]) 1 ("text" <> space <> emph "emph")+          , "link" =:+            "\\section{text \\href{/url}{link}}" =?>+              headerWith ("text-link",[],[]) 1 ("text" <> space <> link "/url" "" "link")+          ]++        , testGroup "math"+          [ "escaped $" =:+            "$x=\\$4$" =?> para (math "x=\\$4")+          ]++        , testGroup "space and comments"+          [ "blank lines + space at beginning" =:+            "\n  \n  hi" =?> para "hi"+          , "blank lines + space + comments" =:+            "% my comment\n\n  \n  % another\n\nhi" =?> para "hi"+          , "comment in paragraph" =:+            "hi % this is a comment\nthere\n" =?>+                para ("hi" <> softbreak <> "there")+          ]++        , testGroup "code blocks"+          [ "identifier" =:+            "\\begin{lstlisting}[label=test]\\end{lstlisting}" =?> codeBlockWith ("test", [], [("label","test")]) ""+          , "no identifier" =:+            "\\begin{lstlisting}\\end{lstlisting}" =?> codeBlock ""+          ]++        , testGroup "tables"+          [ "Single cell table" =:+            "\\begin{tabular}{|l|}Test\\\\\\end{tabular}" =?>+            simpleTable' [AlignLeft] [[plain "Test"]]+          , "Multi cell table" =:+            "\\begin{tabular}{|rl|}One & Two\\\\ \\end{tabular}" =?>+            simpleTable' [AlignRight,AlignLeft] [[plain "One", plain "Two"]]+          , "Multi line table" =:+            T.unlines [ "\\begin{tabular}{|c|}"+                    , "One\\\\"+                    , "Two\\\\"+                    , "Three\\\\"+                    , "\\end{tabular}" ] =?>+            simpleTable' [AlignCenter]+                         [[plain "One"], [plain "Two"], [plain "Three"]]+          , "Empty table" =:+            "\\begin{tabular}{}\\end{tabular}" =?>+            simpleTable' [] []+          , "Table with fixed column width" =:+            "\\begin{tabular}{|p{5cm}r|}One & Two\\\\ \\end{tabular}" =?>+            simpleTable' [AlignLeft,AlignRight] [[plain "One", plain "Two"]]+          , "Table with empty column separators" =:+            "\\begin{tabular}{@{}r@{}l}One & Two\\\\ \\end{tabular}" =?>+            simpleTable' [AlignRight,AlignLeft] [[plain "One", plain "Two"]]+          , "Table with custom column separators" =:+            T.unlines [ "\\begin{tabular}{@{($\\to$)}r@{\\hspace{2cm}}l}"+                    , "One&Two\\\\"+                    , "\\end{tabular}" ] =?>+            simpleTable' [AlignRight,AlignLeft] [[plain "One", plain "Two"]]+          , "Table with vertical alignment argument" =:+            "\\begin{tabular}[t]{r|r}One & Two\\\\ \\end{tabular}" =?>+            simpleTable' [AlignRight,AlignRight] [[plain "One", plain "Two"]]+          ]++        , testGroup "citations"+          [ natbibCitations+          , biblatexCitations+          ]++        , testGroup "images"+          [ "Basic image" =:+            "\\includegraphics{foo.png}" =?>+            para (image "foo.png" "" (text "image"))+          , "Basic image with blank options" =:+            "\\includegraphics[]{foo.png}" =?>+            para (image "foo.png" "" (text "image"))+          , "Image with both width and height" =:+            "\\includegraphics[width=17cm,height=5cm]{foo.png}" =?>+            para (imageWith ("", [], [("width", "17cm"), ("height", "5cm")]) "foo.png" "" "image")+          , "Image with width and height and a bunch of other options" =:+            "\\includegraphics[width=17cm,height=5cm,clip,keepaspectratio]{foo.png}" =?>+            para (imageWith ("", [], [("width", "17cm"), ("height", "5cm")]) "foo.png" "" "image")+          , "Image with just width" =:+            "\\includegraphics[width=17cm]{foo.png}" =?>+            para (imageWith ("", [], [("width", "17cm")]) "foo.png" "" "image")+          , "Image with just height" =:+            "\\includegraphics[height=17cm]{foo.png}" =?>+            para (imageWith ("", [], [("height", "17cm")]) "foo.png" "" "image")+          , "Image width relative to textsize" =:+            "\\includegraphics[width=0.6\\textwidth]{foo.png}" =?>+            para (imageWith ("", [], [("width", "60%")]) "foo.png" "" "image")+          , "Image with options with spaces" =:+            "\\includegraphics[width=12cm, height = 5cm]{foo.png}" =?>+            para (imageWith ("", [], [("width", "12cm"), ("height", "5cm")]) "foo.png" "" "image")+          ]++        , let hex = ['0'..'9']++['a'..'f'] in+          testGroup "Character Escapes"+          [ "Two-character escapes" =:+            mconcat ["^^" <> T.pack [i,j] | i <- hex, j <- hex] =?>+            para (str ['\0'..'\255'])+          , "One-character escapes" =:+            mconcat ["^^" <> T.pack [i] | i <- hex] =?>+            para (str $ ['p'..'y']++['!'..'&'])+          ]+        , testGroup "memoir scene breaks"+          [ "plainbreak" =:+            "hello\\plainbreak{2}goodbye" =?>+            para (str "hello") <> horizontalRule <> para (str "goodbye")+          , "plainbreak*" =:+            "hello\\plainbreak*{2}goodbye" =?>+            para (str "hello") <> horizontalRule <> para (str "goodbye")+          , "fancybreak" =:+            "hello\\fancybreak{b r e a k}goodbye" =?>+            para (str "hello") <> horizontalRule <> para (str "goodbye")+          , "fancybreak*" =:+            "hello\\fancybreak*{b r e a k}goodbye" =?>+            para (str "hello") <> horizontalRule <> para (str "goodbye")+          , "plainfancybreak" =:+            "hello\\plainfancybreak{4}{2}{b r e a k}goodbye" =?>+            para (str "hello") <> horizontalRule <> para (str "goodbye")+          , "plainfancybreak*" =:+            "hello\\plainfancybreak*{4}{2}{b r e a k}goodbye" =?>+            para (str "hello") <> horizontalRule <> para (str "goodbye")+          , "pfbreak" =:+            "hello\\pfbreak{}goodbye" =?>+            para (str "hello") <> horizontalRule <> para (str "goodbye")+          , "pfbreak*" =:+            "hello\\pfbreak*{}goodbye" =?>+            para (str "hello") <> horizontalRule <> para (str "goodbye")+          ]+        , testGroup "biblatex roman numerals"+          [ "upper" =:+            "number \\RN{12}" =?>+            para (str "number" <> space <> str "XII")+          , "lower" =:+            "number \\Rn{29}" =?>+            para (str "number" <> space <> str "xxix")+          , "leading zero" =:+            "\\Rn{014}" =?>+            para (str "xiv")+          , "surrounding spaces" =:+            "number \\Rn{ 41 }" =?>+            para (str "number" <> space <> str "xli")+          , "zero" =:+            "\\RN{0}" =?>+            para (str "")+          , "space then unbraced argument" =:+            "\\RN 7 ok" =?>+            para (str "VII" <> space <> str "ok")+          , "space before braced argument" =:+            "\\Rn {13}ok" =?>+            para (str "xiiiok")+          ]+        , testGroup "polyglossia language spans"+          [ "french" =:+            "hello \\textfrench{bonjour}" =?>+            para (str "hello" <> space <> spanWith ("", [], [("lang", "fr")]) (str "bonjour"))+          , "nested" =:+            "\\textfrench{quelle c'est \\textlatin{primus}?}" =?>+            para (spanWith ("", [], [("lang", "fr")]) $+                    str "quelle" <> space <> str "c\8217est" <> space <>+                    spanWith ("", [], [("lang", "la")]) (str "primus") <> str "?")+          , "with formatting" =:+            "\\textgerman{wie \\emph{spaet} ist es?}" =?>+            para (spanWith ("", [], [("lang", "de")]) $+                    str "wie" <> space <> emph (str "spaet") <> space <> str "ist" <> space <> str "es?")+          , "language options" =:+            "\\textgerman[variant=swiss]{hoechdeutsche}" =?>+            para (spanWith ("", [], [("lang", "de-CH")]) $ str "hoechdeutsche")+          , "unknown option fallback" =:+            "\\textgerman[variant=moon]{ueberhoechdeutsche}" =?>+            para (spanWith ("", [], [("lang", "de")]) $ str "ueberhoechdeutsche")+          ]+        ]++baseCitation :: Citation+baseCitation = Citation{ citationId      = "item1"+                       , citationPrefix  = []+                       , citationSuffix  = []+                       , citationMode    = AuthorInText+                       , citationNoteNum = 0+                       , citationHash    = 0+                       }++rt :: String -> Inlines+rt = rawInline "latex"++natbibCitations :: TestTree+natbibCitations = testGroup "natbib"+  [ "citet" =: "\\citet{item1}"+    =?> para (cite [baseCitation] (rt "\\citet{item1}"))+  , "suffix" =: "\\citet[p.~30]{item1}"+    =?> para+        (cite [baseCitation{ citationSuffix = toList $ text "p.\160\&30" }] (rt "\\citet[p.~30]{item1}"))+  , "suffix long" =: "\\citet[p.~30, with suffix]{item1}"+    =?> para (cite [baseCitation{ citationSuffix =+                       toList $ text "p.\160\&30, with suffix" }] (rt "\\citet[p.~30, with suffix]{item1}"))+  , "multiple" =: "\\citeauthor{item1} \\citetext{\\citeyear{item1}; \\citeyear[p.~30]{item2}; \\citealp[see also][]{item3}}"+    =?> para (cite [baseCitation{ citationMode = AuthorInText }+                   ,baseCitation{ citationMode = SuppressAuthor+                                , citationSuffix = [Str "p.\160\&30"]+                                , citationId = "item2" }+                   ,baseCitation{ citationId = "item3"+                                , citationPrefix = [Str "see",Space,Str "also"]+                                , citationMode = NormalCitation }+                   ] (rt "\\citetext{\\citeyear{item1}; \\citeyear[p.~30]{item2}; \\citealp[see also][]{item3}}"))+  , "group" =: "\\citetext{\\citealp[see][p.~34--35]{item1}; \\citealp[also][chap. 3]{item3}}"+    =?> para (cite [baseCitation{ citationMode = NormalCitation+                                , citationPrefix = [Str "see"]+                                , citationSuffix = [Str "p.\160\&34\8211\&35"] }+                   ,baseCitation{ citationMode = NormalCitation+                                , citationId = "item3"+                                , citationPrefix = [Str "also"]+                                , citationSuffix = [Str "chap.",Space,Str "3"] }+                   ] (rt "\\citetext{\\citealp[see][p.~34--35]{item1}; \\citealp[also][chap. 3]{item3}}"))+  , "suffix and locator" =: "\\citep[pp.~33, 35--37, and nowhere else]{item1}"+    =?> para (cite [baseCitation{ citationMode = NormalCitation+                                , citationSuffix = [Str "pp.\160\&33,",Space,Str "35\8211\&37,",Space,Str "and",Space,Str "nowhere",Space, Str "else"] }] (rt "\\citep[pp.~33, 35--37, and nowhere else]{item1}"))+  , "suffix only" =: "\\citep[and nowhere else]{item1}"+    =?> para (cite [baseCitation{ citationMode = NormalCitation+                                , citationSuffix = toList $ text "and nowhere else" }] (rt "\\citep[and nowhere else]{item1}"))+  , "no author" =: "\\citeyearpar{item1}, and now Doe with a locator \\citeyearpar[p.~44]{item2}"+    =?> para (cite [baseCitation{ citationMode = SuppressAuthor }] (rt "\\citeyearpar{item1}") <>+              text ", and now Doe with a locator " <>+              cite [baseCitation{ citationMode = SuppressAuthor+                                , citationSuffix = [Str "p.\160\&44"]+                                , citationId = "item2" }] (rt "\\citeyearpar[p.~44]{item2}"))+  , "markup" =: "\\citep[\\emph{see}][p. \\textbf{32}]{item1}"+    =?> para (cite [baseCitation{ citationMode = NormalCitation+                                , citationPrefix = [Emph [Str "see"]]+                                , citationSuffix = [Str "p.",Space,+                                    Strong [Str "32"]] }] (rt "\\citep[\\emph{see}][p. \\textbf{32}]{item1}"))+  ]++biblatexCitations :: TestTree+biblatexCitations = testGroup "biblatex"+  [ "textcite" =: "\\textcite{item1}"+    =?> para (cite [baseCitation] (rt "\\textcite{item1}"))+  , "suffix" =: "\\textcite[p.~30]{item1}"+    =?> para+        (cite [baseCitation{ citationSuffix = toList $ text "p.\160\&30" }] (rt "\\textcite[p.~30]{item1}"))+  , "suffix long" =: "\\textcite[p.~30, with suffix]{item1}"+    =?> para (cite [baseCitation{ citationSuffix =+                       toList $ text "p.\160\&30, with suffix" }] (rt "\\textcite[p.~30, with suffix]{item1}"))+  , "multiple" =: "\\textcites{item1}[p.~30]{item2}[see also][]{item3}"+    =?> para (cite [baseCitation{ citationMode = AuthorInText }+                   ,baseCitation{ citationMode = NormalCitation+                                , citationSuffix = [Str "p.\160\&30"]+                                , citationId = "item2" }+                   ,baseCitation{ citationId = "item3"+                                , citationPrefix = [Str "see",Space,Str "also"]+                                , citationMode = NormalCitation }+                   ] (rt "\\textcites{item1}[p.~30]{item2}[see also][]{item3}"))+  , "group" =: "\\autocites[see][p.~34--35]{item1}[also][chap. 3]{item3}"+    =?> para (cite [baseCitation{ citationMode = NormalCitation+                                , citationPrefix = [Str "see"]+                                , citationSuffix = [Str "p.\160\&34\8211\&35"] }+                   ,baseCitation{ citationMode = NormalCitation+                                , citationId = "item3"+                                , citationPrefix = [Str "also"]+                                , citationSuffix = [Str "chap.",Space,Str "3"] }+                   ] (rt "\\autocites[see][p.~34--35]{item1}[also][chap. 3]{item3}"))+  , "suffix and locator" =: "\\autocite[pp.~33, 35--37, and nowhere else]{item1}"+    =?> para (cite [baseCitation{ citationMode = NormalCitation+                                , citationSuffix = [Str "pp.\160\&33,",Space,Str "35\8211\&37,",Space,Str "and",Space,Str "nowhere",Space, Str "else"] }] (rt "\\autocite[pp.~33, 35--37, and nowhere else]{item1}"))+  , "suffix only" =: "\\autocite[and nowhere else]{item1}"+    =?> para (cite [baseCitation{ citationMode = NormalCitation+                                , citationSuffix = toList $ text "and nowhere else" }] (rt "\\autocite[and nowhere else]{item1}"))+  , "no author" =: "\\autocite*{item1}, and now Doe with a locator \\autocite*[p.~44]{item2}"+    =?> para (cite [baseCitation{ citationMode = SuppressAuthor }] (rt "\\autocite*{item1}") <>+              text ", and now Doe with a locator " <>+              cite [baseCitation{ citationMode = SuppressAuthor+                                , citationSuffix = [Str "p.\160\&44"]+                                , citationId = "item2" }] (rt "\\autocite*[p.~44]{item2}"))+  , "markup" =: "\\autocite[\\emph{see}][p. \\textbf{32}]{item1}"+    =?> para (cite [baseCitation{ citationMode = NormalCitation+                                , citationPrefix = [Emph [Str "see"]]+                                , citationSuffix = [Str "p.",Space,+                                    Strong [Str "32"]] }] (rt "\\autocite[\\emph{see}][p. \\textbf{32}]{item1}"))+  , "parencite" =: "\\parencite{item1}"+    =?> para (cite [baseCitation{ citationMode = NormalCitation }] (rt "\\parencite{item1}"))+  ]
+ test/Tests/Readers/Markdown.hs view
@@ -0,0 +1,462 @@+{-# LANGUAGE OverloadedStrings #-}+module Tests.Readers.Markdown (tests) where++import Data.Text (Text, unpack)+import qualified Data.Text as T+import Test.Tasty+import Tests.Helpers+import Text.Pandoc+import Text.Pandoc.Arbitrary ()+import Text.Pandoc.Builder++markdown :: Text -> Pandoc+markdown = purely $ readMarkdown def { readerExtensions =+                            disableExtension Ext_smart pandocExtensions }++markdownSmart :: Text -> Pandoc+markdownSmart = purely $  readMarkdown def { readerExtensions =+                             enableExtension Ext_smart pandocExtensions }++markdownCDL :: Text -> Pandoc+markdownCDL = purely $ readMarkdown def { readerExtensions = enableExtension+                 Ext_compact_definition_lists pandocExtensions }++markdownGH :: Text -> Pandoc+markdownGH = purely $ readMarkdown def {+                readerExtensions = githubMarkdownExtensions }++infix 4 =:+(=:) :: ToString c+     => String -> (Text, c) -> TestTree+(=:) = test markdown++testBareLink :: (Text, Inlines) -> TestTree+testBareLink (inp, ils) =+  test (purely $ readMarkdown def{ readerExtensions =+             extensionsFromList [Ext_autolink_bare_uris, Ext_raw_html] })+       (unpack inp) (inp, doc $ para ils)++autolink :: String -> Inlines+autolink = autolinkWith nullAttr++autolinkWith :: Attr -> String -> Inlines+autolinkWith attr s = linkWith attr s "" (str s)++bareLinkTests :: [(Text, Inlines)]+bareLinkTests =+  [ ("http://google.com is a search engine.",+     autolink "http://google.com" <> " is a search engine.")+  , ("<a href=\"http://foo.bar.baz\">http://foo.bar.baz</a>",+     rawInline "html" "<a href=\"http://foo.bar.baz\">" <>+     "http://foo.bar.baz" <> rawInline "html" "</a>")+  , ("Try this query: http://google.com?search=fish&time=hour.",+     "Try this query: " <> autolink "http://google.com?search=fish&time=hour" <> ".")+  , ("HTTPS://GOOGLE.COM,",+      autolink "HTTPS://GOOGLE.COM" <> ",")+  , ("http://el.wikipedia.org/wiki/Τεχνολογία,",+      autolink "http://el.wikipedia.org/wiki/Τεχνολογία" <> ",")+  , ("doi:10.1000/182,",+      autolink "doi:10.1000/182" <> ",")+  , ("git://github.com/foo/bar.git,",+      autolink "git://github.com/foo/bar.git" <> ",")+  , ("file:///Users/joe/joe.txt, and",+      autolink "file:///Users/joe/joe.txt" <> ", and")+  , ("mailto:someone@somedomain.com.",+      autolink "mailto:someone@somedomain.com" <> ".")+  , ("Use http: this is not a link!",+      "Use http: this is not a link!")+  , ("(http://google.com).",+      "(" <> autolink "http://google.com" <> ").")+  , ("http://en.wikipedia.org/wiki/Sprite_(computer_graphics)",+      autolink "http://en.wikipedia.org/wiki/Sprite_(computer_graphics)")+  , ("http://en.wikipedia.org/wiki/Sprite_[computer_graphics]",+      link "http://en.wikipedia.org/wiki/Sprite_%5Bcomputer_graphics%5D" ""+        (str "http://en.wikipedia.org/wiki/Sprite_[computer_graphics]"))+  , ("http://en.wikipedia.org/wiki/Sprite_{computer_graphics}",+      link "http://en.wikipedia.org/wiki/Sprite_%7Bcomputer_graphics%7D" ""+        (str "http://en.wikipedia.org/wiki/Sprite_{computer_graphics}"))+  , ("http://example.com/Notification_Center-GitHub-20101108-140050.jpg",+      autolink "http://example.com/Notification_Center-GitHub-20101108-140050.jpg")+  , ("https://github.com/github/hubot/blob/master/scripts/cream.js#L20-20",+      autolink "https://github.com/github/hubot/blob/master/scripts/cream.js#L20-20")+  , ("http://www.rubyonrails.com",+      autolink "http://www.rubyonrails.com")+  , ("http://www.rubyonrails.com:80",+      autolink "http://www.rubyonrails.com:80")+  , ("http://www.rubyonrails.com/~minam",+      autolink "http://www.rubyonrails.com/~minam")+  , ("https://www.rubyonrails.com/~minam",+      autolink "https://www.rubyonrails.com/~minam")+  , ("http://www.rubyonrails.com/~minam/url%20with%20spaces",+      autolink "http://www.rubyonrails.com/~minam/url%20with%20spaces")+  , ("http://www.rubyonrails.com/foo.cgi?something=here",+      autolink "http://www.rubyonrails.com/foo.cgi?something=here")+  , ("http://www.rubyonrails.com/foo.cgi?something=here&and=here",+      autolink "http://www.rubyonrails.com/foo.cgi?something=here&and=here")+  , ("http://www.rubyonrails.com/contact;new",+      autolink "http://www.rubyonrails.com/contact;new")+  , ("http://www.rubyonrails.com/contact;new%20with%20spaces",+      autolink "http://www.rubyonrails.com/contact;new%20with%20spaces")+  , ("http://www.rubyonrails.com/contact;new?with=query&string=params",+      autolink "http://www.rubyonrails.com/contact;new?with=query&string=params")+  , ("http://www.rubyonrails.com/~minam/contact;new?with=query&string=params",+      autolink "http://www.rubyonrails.com/~minam/contact;new?with=query&string=params")+  , ("http://en.wikipedia.org/wiki/Wikipedia:Today%27s_featured_picture_%28animation%29/January_20%2C_2007",+      autolink "http://en.wikipedia.org/wiki/Wikipedia:Today%27s_featured_picture_%28animation%29/January_20%2C_2007")+  , ("http://www.mail-archive.com/rails@lists.rubyonrails.org/",+      autolink "http://www.mail-archive.com/rails@lists.rubyonrails.org/")+  , ("http://www.amazon.com/Testing-Equal-Sign-In-Path/ref=pd_bbs_sr_1?ie=UTF8&s=books&qid=1198861734&sr=8-1",+      autolink "http://www.amazon.com/Testing-Equal-Sign-In-Path/ref=pd_bbs_sr_1?ie=UTF8&s=books&qid=1198861734&sr=8-1")+  , ("http://en.wikipedia.org/wiki/Texas_hold%27em",+      autolink "http://en.wikipedia.org/wiki/Texas_hold%27em")+  , ("https://www.google.com/doku.php?id=gps:resource:scs:start",+      autolink "https://www.google.com/doku.php?id=gps:resource:scs:start")+  , ("http://www.rubyonrails.com",+      autolink "http://www.rubyonrails.com")+  , ("http://manuals.ruby-on-rails.com/read/chapter.need_a-period/103#page281",+      autolink "http://manuals.ruby-on-rails.com/read/chapter.need_a-period/103#page281")+  , ("http://foo.example.com/controller/action?parm=value&p2=v2#anchor123",+      autolink "http://foo.example.com/controller/action?parm=value&p2=v2#anchor123")+  , ("http://foo.example.com:3000/controller/action",+      autolink "http://foo.example.com:3000/controller/action")+  , ("http://foo.example.com:3000/controller/action+pack",+      autolink "http://foo.example.com:3000/controller/action+pack")+  , ("http://business.timesonline.co.uk/article/0,,9065-2473189,00.html",+      autolink "http://business.timesonline.co.uk/article/0,,9065-2473189,00.html")+  , ("http://www.mail-archive.com/ruby-talk@ruby-lang.org/",+      autolink "http://www.mail-archive.com/ruby-talk@ruby-lang.org/")+  , ("https://example.org/?anchor=lala-",+      autolink "https://example.org/?anchor=lala-")+  , ("https://example.org/?anchor=-lala",+      autolink "https://example.org/?anchor=-lala")+  ]++{-+p_markdown_round_trip :: Block -> Bool+p_markdown_round_trip b = matches d' d''+  where d'  = normalize $ Pandoc (Meta [] [] []) [b]+        d'' = normalize+              $ readMarkdown def { readerSmart = True }+              $ writeMarkdown def d'+        matches (Pandoc _ [Plain []]) (Pandoc _ []) = True+        matches (Pandoc _ [Para []]) (Pandoc _ []) = True+        matches (Pandoc _ [Plain xs]) (Pandoc _ [Para xs']) = xs == xs'+        matches x y = x == y+-}++tests :: [TestTree]+tests = [ testGroup "inline code"+          [ "with attribute" =:+            "`document.write(\"Hello\");`{.javascript}"+            =?> para+                (codeWith ("",["javascript"],[]) "document.write(\"Hello\");")+          , "with attribute space" =:+            "`*` {.haskell .special x=\"7\"}"+            =?> para (code "*" <> space <> str "{.haskell" <> space <>+                      str ".special" <> space <> str "x=\"7\"}")+          ]+        , testGroup "emph and strong"+          [ "two strongs in emph" =:+             "***a**b **c**d*" =?> para (emph (strong (str "a") <> str "b" <> space+                                         <> strong (str "c") <> str "d"))+          , "emph and strong emph alternating" =:+            "*xxx* ***xxx*** xxx\n*xxx* ***xxx*** xxx"+            =?> para (emph "xxx" <> space <> strong (emph "xxx") <>+                      space <> "xxx" <> softbreak <>+                      emph "xxx" <> space <> strong (emph "xxx") <>+                      space <> "xxx")+          , "emph with spaced strong" =:+            "*x **xx** x*"+            =?> para (emph ("x" <> space <> strong "xx" <> space <> "x"))+          , "intraword underscore with opening underscore (#1121)" =:+            "_foot_ball_" =?> para (emph (text "foot_ball"))+          ]+        , testGroup "raw LaTeX"+          [ "in URL" =:+            "\\begin\n" =?> para (text "\\begin")+          ]+        , testGroup "raw HTML"+          [ "nesting (issue #1330)" =:+            "<del>test</del>" =?>+            rawBlock "html" "<del>" <> plain (str "test") <>+            rawBlock "html" "</del>"+          , "invalid tag (issue #1820" =:+            "</ div></.div>" =?>+            para (text "</ div></.div>")+          , "technically invalid comment" =:+            "<!-- pandoc --help -->" =?>+            rawBlock "html" "<!-- pandoc --help -->"+          , test markdownGH "issue 2469" $+            "<\n\na>" =?>+            para (text "<") <> para (text "a>")+          ]+        , testGroup "raw email addresses"+          [ test markdownGH "issue 2940" $+            "**@user**" =?>+            para (strong (text "@user"))+          ]+        , testGroup "emoji"+          [ test markdownGH "emoji symbols" $+            ":smile: and :+1:" =?> para (text "😄 and 👍")+          ]+        , "unbalanced brackets" =:+            "[[[[[[[[[[[[hi" =?> para (text "[[[[[[[[[[[[hi")+        , testGroup "backslash escapes"+          [ "in URL" =:+            "[hi](/there\\))"+            =?> para (link "/there)" "" "hi")+          , "in title" =:+            "[hi](/there \"a\\\"a\")"+            =?> para (link "/there" "a\"a" "hi")+          , "in reference link title" =:+            "[hi]\n\n[hi]: /there (a\\)a)"+            =?> para (link "/there" "a)a" "hi")+          , "in reference link URL" =:+            "[hi]\n\n[hi]: /there\\.0"+            =?> para (link "/there.0" "" "hi")+          ]+        , testGroup "bare URIs"+             (map testBareLink bareLinkTests)+        , testGroup "autolinks"+          [ "with unicode dash following" =:+            "<http://foo.bar>\8212" =?> para (autolink "http://foo.bar" <>+                                         str "\8212")+          , "a partial URL (#2277)" =:+            "<www.boe.es/buscar/act.php?id=BOE-A-1996-8930#a66>" =?>+            para (text "<www.boe.es/buscar/act.php?id=BOE-A-1996-8930#a66>")+          , "with some attributes" =:+            "<http://foo.bar>{#i .j .z k=v}" =?>+            para (autolinkWith ("i", ["j", "z"], [("k", "v")]) "http://foo.bar")+          , "with some attributes and spaces" =:+            "<http://foo.bar> {#i .j .z k=v}" =?>+            para (autolink "http://foo.bar" <> space <> text "{#i .j .z k=v}")+          ]+        , testGroup "links"+          [ "no autolink inside link" =:+            "[<https://example.org>](url)" =?>+            para (link "url" "" (text "<https://example.org>"))+          , "no inline link inside link" =:+            "[[a](url2)](url)" =?>+            para (link "url" "" (text "[a](url2)"))+          , "no bare URI inside link" =:+            "[https://example.org(](url)" =?>+            para (link "url" "" (text "https://example.org("))+          ]+        , testGroup "Headers"+          [ "blank line before header" =:+            "\n# Header\n"+            =?> headerWith ("header",[],[]) 1 "Header"+          , "bracketed text (#2062)" =:+            "# [hi]\n"+            =?> headerWith ("hi",[],[]) 1 "[hi]"+          , "ATX header without trailing #s" =:+            "# Foo bar\n\n" =?>+            headerWith ("foo-bar",[],[]) 1 "Foo bar"+          , "ATX header without trailing #s" =:+            "# Foo bar with # #" =?>+            headerWith ("foo-bar-with",[],[]) 1 "Foo bar with #"+          , "setext header" =:+            "Foo bar\n=\n\n Foo bar 2 \n=" =?>+            headerWith ("foo-bar",[],[]) 1 "Foo bar"+            <> headerWith ("foo-bar-2",[],[]) 1 "Foo bar 2"+          ]+        , testGroup "Implicit header references"+          [ "ATX header without trailing #s" =:+            "# Header\n[header]\n\n[header ]\n\n[ header]" =?>+            headerWith ("header",[],[]) 1 "Header"+            <> para (link "#header" "" (text "header"))+            <> para (link "#header" "" (text "header"))+            <> para (link "#header" "" (text "header"))+          , "ATX header with trailing #s" =:+            "# Foo bar #\n[foo bar]\n\n[foo bar ]\n\n[ foo bar]" =?>+            headerWith ("foo-bar",[],[]) 1 "Foo bar"+            <> para (link "#foo-bar" "" (text "foo bar"))+            <> para (link "#foo-bar" "" (text "foo bar"))+            <> para (link "#foo-bar" "" (text "foo bar"))+          , "setext header" =:+            " Header \n=\n\n[header]\n\n[header ]\n\n[ header]" =?>+            headerWith ("header",[],[]) 1 "Header"+            <> para (link "#header" "" (text "header"))+            <> para (link "#header" "" (text "header"))+            <> para (link "#header" "" (text "header"))+          ]+        , testGroup "smart punctuation"+          [ test markdownSmart "quote before ellipses"+            ("'...hi'"+            =?> para (singleQuoted "…hi"))+          , test markdownSmart "apostrophe before emph"+            ("D'oh! A l'*aide*!"+            =?> para ("D’oh! A l’" <> emph "aide" <> "!"))+          , test markdownSmart "apostrophe in French"+            ("À l'arrivée de la guerre, le thème de l'«impossibilité du socialisme»"+            =?> para "À l’arrivée de la guerre, le thème de l’«impossibilité du socialisme»")+          , test markdownSmart "apostrophe after math" $ -- issue #1909+              "The value of the $x$'s and the systems' condition." =?>+              para (text "The value of the " <> math "x" <> text "\8217s and the systems\8217 condition.")+          ]+        , testGroup "footnotes"+          [ "indent followed by newline and flush-left text" =:+            "[^1]\n\n[^1]: my note\n\n     \nnot in note\n"+            =?> para (note (para "my note")) <> para "not in note"+          , "indent followed by newline and indented text" =:+            "[^1]\n\n[^1]: my note\n     \n    in note\n"+            =?> para (note (para "my note" <> para "in note"))+          , "recursive note" =:+            "[^1]\n\n[^1]: See [^1]\n"+            =?> para (note (para "See [^1]"))+          ]+        , testGroup "lhs"+          [ test (purely $ readMarkdown def{ readerExtensions = enableExtension+                       Ext_literate_haskell pandocExtensions })+              "inverse bird tracks and html" $+              "> a\n\n< b\n\n<div>\n"+              =?> codeBlockWith ("",["sourceCode","literate","haskell"],[]) "a"+                  <>+                  codeBlockWith ("",["sourceCode","haskell"],[]) "b"+                  <>+                  rawBlock "html" "<div>\n\n"+          ]+-- the round-trip properties frequently fail+--        , testGroup "round trip"+--          [ property "p_markdown_round_trip" p_markdown_round_trip+--          ]+        , testGroup "definition lists"+          [ "no blank space" =:+            "foo1\n  :  bar\n\nfoo2\n  : bar2\n  : bar3\n" =?>+            definitionList [ (text "foo1", [plain (text "bar")])+                           , (text "foo2", [plain (text "bar2"),+                                            plain (text "bar3")])+                           ]+          , "blank space before first def" =:+            "foo1\n\n  :  bar\n\nfoo2\n\n  : bar2\n  : bar3\n" =?>+            definitionList [ (text "foo1", [para (text "bar")])+                           , (text "foo2", [para (text "bar2"),+                                            plain (text "bar3")])+                           ]+          , "blank space before second def" =:+            "foo1\n  :  bar\n\nfoo2\n  : bar2\n\n  : bar3\n" =?>+            definitionList [ (text "foo1", [plain (text "bar")])+                           , (text "foo2", [plain (text "bar2"),+                                            para (text "bar3")])+                           ]+          , "laziness" =:+            "foo1\n  :  bar\nbaz\n  : bar2\n" =?>+            definitionList [ (text "foo1", [plain (text "bar" <>+                                                 softbreak <> text "baz"),+                                            plain (text "bar2")])+                           ]+          , "no blank space before first of two paragraphs" =:+            "foo1\n  : bar\n\n    baz\n" =?>+            definitionList [ (text "foo1", [para (text "bar") <>+                                            para (text "baz")])+                           ]+          , "first line not indented" =:+            "foo\n: bar\n" =?>+            definitionList [ (text "foo", [plain (text "bar")]) ]+          , "list in definition" =:+            "foo\n:   - bar\n" =?>+            definitionList [ (text "foo", [bulletList [plain (text "bar")]]) ]+          , "in div" =:+            "<div>foo\n:   - bar\n</div>" =?>+            divWith nullAttr (definitionList+              [ (text "foo", [bulletList [plain (text "bar")]]) ])+          ]+        , testGroup "+compact_definition_lists"+          [ test markdownCDL "basic compact list" $+            "foo1\n:   bar\n    baz\nfoo2\n:   bar2\n" =?>+            definitionList [ (text "foo1", [plain (text "bar" <> softbreak <>+                                                     text "baz")])+                           , (text "foo2", [plain (text "bar2")])+                           ]+          ]+        , testGroup "lists"+          [ "issue #1154" =:+              " -  <div>\n    first div breaks\n    </div>\n\n    <button>if this button exists</button>\n\n    <div>\n    with this div too.\n    </div>\n"+              =?> bulletList [divWith nullAttr (para $ text "first div breaks") <>+                              rawBlock "html" "<button>" <>+                              plain (text "if this button exists") <>+                              rawBlock "html" "</button>" <>+                              divWith nullAttr (para $ text "with this div too.")]+          , test markdownGH "issue #1636" $+              T.unlines [ "* a"+                        , "* b"+                        , "* c"+                        , "    * d" ]+              =?>+              bulletList [ plain "a"+                         , plain "b"+                         , plain "c" <> bulletList [plain "d"] ]+          ]+        , testGroup "entities"+          [ "character references" =:+            "&lang; &ouml;" =?> para (text "\10216 ö")+          , "numeric" =:+            "&#44;&#x44;&#X44;" =?> para (text ",DD")+          , "in link title" =:+            "[link](/url \"title &lang; &ouml; &#44;\")" =?>+               para (link "/url" "title \10216 ö ," (text "link"))+          ]+        , testGroup "citations"+          [ "simple" =:+            "@item1" =?> para (cite [+                Citation{ citationId      = "item1"+                        , citationPrefix  = []+                        , citationSuffix  = []+                        , citationMode    = AuthorInText+                        , citationNoteNum = 0+                        , citationHash    = 0+                        }+                ] "@item1")+          , "key starts with digit" =:+            "@1657:huyghens" =?> para (cite [+                Citation{ citationId      = "1657:huyghens"+                        , citationPrefix  = []+                        , citationSuffix  = []+                        , citationMode    = AuthorInText+                        , citationNoteNum = 0+                        , citationHash    = 0+                        }+                ] "@1657:huyghens")+          ]+        , let citation = cite [Citation "cita" [] [] AuthorInText 0 0] (str "@cita")+          in testGroup "footnote/link following citation" -- issue #2083+          [ "footnote" =:+              T.unlines [ "@cita[^note]"+                        , ""+                        , "[^note]: note" ] =?>+              para (+                citation <> note (para $ str "note")+              )+          , "normal link" =:+              "@cita [link](http://www.com)" =?>+              para (+                citation <> space <> link "http://www.com" "" (str "link")+              )+          , "reference link" =:+              T.unlines [ "@cita [link][link]"+                        , ""+                        , "[link]: http://www.com" ] =?>+              para (+                citation <> space <> link "http://www.com" "" (str "link")+              )+          , "short reference link" =:+              T.unlines [ "@cita [link]"+                        , ""+                        , "[link]: http://www.com" ] =?>+              para (+                citation <> space <> link "http://www.com" "" (str "link")+              )+          , "implicit header link" =:+              T.unlines [ "# Header"+                        , "@cita [Header]" ] =?>+              headerWith ("header",[],[]) 1 (str "Header") <> para (+                citation <> space <> link "#header" "" (str "Header")+              )+          , "regular citation" =:+              "@cita [foo]" =?>+              para (+                cite [Citation "cita" [] [Str "foo"] AuthorInText 0 0]+                  (str "@cita" <> space <> str "[foo]")+              )+          ]+        ]
+ test/Tests/Readers/Muse.hs view
@@ -0,0 +1,716 @@+{-# LANGUAGE OverloadedStrings #-}+module Tests.Readers.Muse (tests) where++import Data.List (intersperse)+import Data.Text (Text)+import qualified Data.Text as T+import Test.Tasty+import Tests.Helpers+import Text.Pandoc+import Text.Pandoc.Arbitrary ()+import Text.Pandoc.Builder++muse :: Text -> Pandoc+muse = purely $ \s -> do+  setInputFiles ["in"]+  setOutputFile (Just "out")+  readMuse def s++infix 4 =:+(=:) :: ToString c+     => String -> (Text, c) -> TestTree+(=:) = test muse++spcSep :: [Inlines] -> Inlines+spcSep = mconcat . intersperse space++tests :: [TestTree]+tests =+  [ testGroup "Inlines"+      [ "Plain String" =:+          "Hello, World" =?>+          para "Hello, World"++      , "Emphasis" =:+        "*Foo bar*" =?>+        para (emph . spcSep $ ["Foo", "bar"])++      , "Comma after closing *" =:+        "Foo *bar*, baz" =?>+        para ("Foo " <> emph "bar" <> ", baz")++      , "Letter after closing *" =:+        "Foo *bar*x baz" =?>+        para "Foo *bar*x baz"++      , "Emphasis tag" =:+        "<em>Foo bar</em>" =?>+        para (emph . spcSep $ ["Foo", "bar"])++      , "Strong" =:+          "**Cider**" =?>+          para (strong "Cider")++      , "Strong tag" =: "<strong>Strong</strong>" =?> para (strong "Strong")++      , "Strong Emphasis" =:+          "***strength***" =?>+          para (strong . emph $ "strength")++      , "Superscript tag" =: "<sup>Superscript</sup>" =?> para (superscript "Superscript")++      , "Subscript tag" =: "<sub>Subscript</sub>" =?> para (subscript "Subscript")++      , "Strikeout tag" =: "<del>Strikeout</del>" =?> para (strikeout "Strikeout")++      , "Opening inline tags" =: "foo <em> bar <strong>baz" =?> para "foo <em> bar <strong>baz"++      , "Closing inline tags" =: "foo </em> bar </strong>baz" =?> para "foo </em> bar </strong>baz"++      , "Tag soup" =: "foo <em> bar </strong>baz" =?> para "foo <em> bar </strong>baz"++      -- Both inline tags must be within the same paragraph+      , "No multiparagraph inline tags" =:+        T.unlines [ "First line"+                  , "<em>Second line"+                  , ""+                  , "Fourth line</em>"+                  ] =?>+        para "First line <em>Second line" <>+        para "Fourth line</em>"++      , "Linebreak" =: "Line <br>  break" =?> para ("Line" <> linebreak <> "break")++      , testGroup "Code markup"+        [ "Code" =: "=foo(bar)=" =?> para (code "foo(bar)")++        , "Not code" =: "a=b= =c=d" =?> para (text "a=b= =c=d")++        -- Emacs Muse 3.20 parses this as code, we follow Amusewiki+        , "Not code if closing = is detached" =: "=this is not a code =" =?> para "=this is not a code ="++        , "Not code if opening = is detached" =: "= this is not a code=" =?> para "= this is not a code="++        , "Code if followed by comma" =:+          "Foo =bar=, baz" =?>+          para (text "Foo " <> code "bar" <> text ", baz")++        , "One character code" =: "=c=" =?> para (code "c")++        , "Three = characters is not a code" =: "===" =?> para "==="++        , "Multiline code markup" =:+          "foo =bar\nbaz= end of code" =?>+          para (text "foo " <> code "bar\nbaz" <> text " end of code")++{- Emacs Muse 3.20 has a bug: it publishes+ - <p>foo <code>bar+ -+ - baz</code> foo</p>+ - which is displayed as one paragraph by browsers.+ - We follow Amusewiki here and avoid joining paragraphs.+ -}+        , "No multiparagraph code" =:+          T.unlines [ "foo =bar"+                    , ""+                    , "baz= foo"+                    ] =?>+          para "foo =bar" <>+          para "baz= foo"+        ]++      , "Code tag" =: "<code>foo(bar)</code>" =?> para (code "foo(bar)")++      , "Verbatim tag" =: "*<verbatim>*</verbatim>*" =?> para (emph "*")++      , testGroup "Links"+        [ "Link without description" =:+          "[[https://amusewiki.org/]]" =?>+          para (link "https://amusewiki.org/" "" (str "https://amusewiki.org/"))+        , "Link with description" =:+          "[[https://amusewiki.org/][A Muse Wiki]]" =?>+          para (link "https://amusewiki.org/" "" (text "A Muse Wiki"))+        , "Image" =:+          "[[image.jpg]]" =?>+          para (image "image.jpg" "" mempty)+        , "Image with description" =:+          "[[image.jpg][Image]]" =?>+          para (image "image.jpg" "" (text "Image"))+        , "Image link" =:+          "[[URL:image.jpg]]" =?>+          para (link "image.jpg" "" (str "image.jpg"))+        , "Image link with description" =:+          "[[URL:image.jpg][Image]]" =?>+          para (link "image.jpg" "" (text "Image"))+        -- Implicit links are supported in Emacs Muse, but not in Amusewiki:+        -- https://github.com/melmothx/text-amuse/issues/18+        --+        -- This test also makes sure '=' without whitespace is not treated as code markup+        , "No implicit links" =: "http://example.org/index.php?action=view&id=1"+               =?> para "http://example.org/index.php?action=view&id=1"+        ]+      ]++  , testGroup "Blocks"+      [ "Block elements end paragraphs" =:+        T.unlines [ "First paragraph"+                  , "----"+                  , "Second paragraph"+                  ] =?> para (text "First paragraph") <> horizontalRule <> para (text "Second paragraph")+      , testGroup "Horizontal rule"+        [ "Less than 4 dashes is not a horizontal rule" =: "---" =?> para (text "---")+        , "4 dashes is a horizontal rule" =: "----" =?> horizontalRule+        , "5 dashes is a horizontal rule" =: "-----" =?> horizontalRule+        , "4 dashes with spaces is a horizontal rule" =: "----  " =?> horizontalRule+        ]+      , testGroup "Paragraphs"+        [ "Simple paragraph" =:+          T.unlines [ "First line"+                    , "second line."+                    ] =?>+          para "First line second line."+        , "Indented paragraph" =:+          T.unlines [ " First line"+                    , "second line."+                    ] =?>+          para "First line second line."+        -- Emacs Muse starts a blockquote on the second line.+        -- We copy Amusewiki behavior and require a blank line to start a blockquote.+        , "Indentation in the middle of paragraph" =:+           T.unlines [ "First line"+                     , "  second line"+                     , "third line"+                     ] =?>+           para "First line second line third line"+        , "Quote" =:+          "  This is a quotation\n" =?>+          blockQuote (para "This is a quotation")+        , "Multiline quote" =:+          T.unlines [ "  This is a quotation"+                    , "  with a continuation"+                    ] =?>+          blockQuote (para "This is a quotation with a continuation")+        , testGroup "Div"+          [ "Div without id" =:+            "<div>Foo bar</div>" =?>+            divWith nullAttr (para "Foo bar")+          , "Div with id" =:+            "<div id=\"foo\">Foo bar</div>" =?>+            divWith ("foo", [], []) (para "Foo bar")+          ]+        , "Verse" =:+          T.unlines [ "> This is"+                    , "> First stanza"+                    , ">" -- Emacs produces verbatim ">" here, we follow Amusewiki+                    , "> And this is"+                    , ">   Second stanza"+                    , ">"+                    , ""+                    , ">"+                    , ""+                    , "> Another verse"+                    , ">    is here"+                    ] =?>+          lineBlock [ "This is"+                    , "First stanza"+                    , ""+                    , "And this is"+                    , "\160\160Second stanza"+                    , ""+                    ] <>+          lineBlock [ "" ] <>+          lineBlock [ "Another verse"+                    , "\160\160\160is here"+                    ]+        ]+      , "Quote tag" =: "<quote>Hello, world</quote>" =?> blockQuote (para $ text "Hello, world")+      , "Verse tag" =:+        T.unlines [ "<verse>"+                  , ""+                  , "Foo bar baz"+                  , "  One two three"+                  , ""+                  , "</verse>"+                  , "<verse>Foo bar</verse>"+                  , "<verse>"+                  , "Foo bar</verse>"+                  , "<verse>"+                  , "   Foo</verse>"+                  ] =?>+        lineBlock [ ""+                  , text "Foo bar baz"+                  , text "\160\160One two three"+                  , ""+                  ] <>+        lineBlock [ "Foo bar" ] <>+        lineBlock [ "Foo bar" ] <>+        lineBlock [ "\160\160\160Foo" ]+      , testGroup "Example"+        [ "Braces on separate lines" =:+          T.unlines [ "{{{"+                    , "Example line"+                    , "}}}"+                    ] =?>+          codeBlock "Example line"+        , "Spaces after opening braces" =:+          T.unlines [ "{{{  "+                    , "Example line"+                    , "}}}"+                    ] =?>+          codeBlock "Example line"+        , "One blank line in the beginning" =:+          T.unlines [ "{{{"+                    , ""+                    , "Example line"+                    , "}}}"+                    ] =?>+          codeBlock "\nExample line"+        , "One blank line in the end" =:+          T.unlines [ "{{{"+                    , "Example line"+                    , ""+                    , "}}}"+                    ] =?>+          codeBlock "Example line\n"+        -- Amusewiki requires braces to be on separate line,+        -- this is an extension.+        , "One line" =:+          "{{{Example line}}}" =?>+          codeBlock "Example line"+        ]+      , testGroup "Example tag"+        [ "Tags on separate lines" =:+          T.unlines [ "<example>"+                    , "Example line"+                    , "</example>"+                    ] =?>+          codeBlock "Example line"+        , "One line" =:+          "<example>Example line</example>" =?>+          codeBlock "Example line"+        , "One blank line in the beginning" =:+          T.unlines [ "<example>"+                    , ""+                    , "Example line"+                    , "</example>"+                    ] =?>+          codeBlock "\nExample line"+        , "One blank line in the end" =:+          T.unlines [ "<example>"+                    , "Example line"+                    , ""+                    , "</example>"+                    ] =?>+          codeBlock "Example line\n"+        ]+      , "Center" =: "<center>Hello, world</center>" =?> para (text "Hello, world")+      , "Right" =: "<right>Hello, world</right>" =?> para (text "Hello, world")+      , testGroup "Comments"+        [ "Comment tag" =: "<comment>\nThis is a comment\n</comment>" =?> (mempty::Blocks)+        , "Line comment" =: "; Comment" =?> (mempty::Blocks)+        , "Not a comment (does not start with a semicolon)" =: " ; Not a comment" =?> para (text "; Not a comment")+        , "Not a comment (has no space after semicolon)" =: ";Not a comment" =?> para (text ";Not a comment")+        ]+      , testGroup "Headers"+        [ "Part" =:+          "* First level" =?>+          header 1 "First level"+        , "Chapter" =:+          "** Second level" =?>+          header 2 "Second level"+        , "Section" =:+          "*** Third level" =?>+          header 3 "Third level"+        , "Subsection" =:+          "**** Fourth level" =?>+          header 4 "Fourth level"+        , "Subsubsection" =:+          "***** Fifth level" =?>+          header 5 "Fifth level"+        , "Whitespace is required after *" =: "**Not a header" =?> para "**Not a header"+        , "No headers in footnotes" =:+          T.unlines [ "Foo[1]"+                    , "[1] * Bar"+                    ] =?>+          para (text "Foo" <>+                note (para "* Bar"))+        , "No headers in quotes" =:+          T.unlines [ "<quote>"+                    , "* Hi"+                    , "</quote>"+                    ] =?>+          blockQuote (para "* Hi")+        ]+      , testGroup "Anchors"+        [ "Anchor" =:+          T.unlines [ "; A comment to make sure anchor is not parsed as a directive"+                    , "#anchor Target"+                    ] =?>+          para (spanWith ("anchor", [], []) mempty <> "Target")+        , "Anchor cannot start with a number" =:+          T.unlines [ "; A comment to make sure anchor is not parsed as a directive"+                    , "#0notanchor Target"+                    ] =?>+          para "#0notanchor Target"+        , "Not anchor if starts with a space" =:+          " #notanchor Target" =?>+          para "#notanchor Target"+        , "Anchor inside a paragraph" =:+          T.unlines [ "Paragraph starts here"+                    , "#anchor and ends here."+                    ] =?>+          para ("Paragraph starts here " <> spanWith ("anchor", [], []) mempty <> "and ends here.")+        ]+      , testGroup "Footnotes"+        [ "Simple footnote" =:+          T.unlines [ "Here is a footnote[1]."+                    , ""+                    , "[1] Footnote contents"+                    ] =?>+          para (text "Here is a footnote" <>+                note (para "Footnote contents") <>+                str ".")+        , "Recursive footnote" =:+          T.unlines [ "Start recursion here[1]"+                    , ""+                    , "[1] Recursion continues here[1]"+                    ] =?>+          para (text "Start recursion here" <>+                note (para "Recursion continues here[1]"))+        ]+      ]+    , testGroup "Tables"+        [ "Two cell table" =:+          "One | Two" =?>+          table mempty [(AlignDefault, 0.0), (AlignDefault, 0.0)]+                       []+                       [[plain "One", plain "Two"]]+        , "Table with multiple words" =:+          "One two | three four" =?>+          table mempty [(AlignDefault, 0.0), (AlignDefault, 0.0)]+                       []+                       [[plain "One two", plain "three four"]]+        , "Not a table" =:+          "One| Two" =?>+          para (text "One| Two")+        , "Not a table again" =:+          "One |Two" =?>+          para (text "One |Two")+        , "Two line table" =:+          T.unlines+            [ "One |  Two"+            , "Three  | Four"+            ] =?>+          table mempty [(AlignDefault, 0.0), (AlignDefault, 0.0)]+                       []+                       [[plain "One", plain "Two"],+                       [plain "Three", plain "Four"]]+        , "Table with one header" =:+          T.unlines+            [ "First || Second"+            , "Third | Fourth"+            ] =?>+          table mempty [(AlignDefault, 0.0), (AlignDefault, 0.0)]+            [plain "First", plain "Second"]+            [[plain "Third", plain "Fourth"]]+        , "Table with two headers" =:+          T.unlines+            [ "First || header"+            , "Second || header"+            , "Foo | bar"+            ] =?>+          table mempty [(AlignDefault, 0.0), (AlignDefault, 0.0)]+            [plain "First", plain "header"]+            [[plain "Second", plain "header"],+             [plain "Foo", plain "bar"]]+        , "Header and footer reordering" =:+          T.unlines+            [ "Foo ||| bar"+            , "Baz || foo"+            , "Bar | baz"+            ] =?>+          table mempty [(AlignDefault, 0.0), (AlignDefault, 0.0)]+            [plain "Baz", plain "foo"]+            [[plain "Bar", plain "baz"],+             [plain "Foo", plain "bar"]]+        , "Table with caption" =:+          T.unlines+            [ "Foo || bar || baz"+            , "First | row | here"+            , "Second | row | there"+            , "|+ Table caption +|"+            ] =?>+          table (text "Table caption") (replicate 3 (AlignDefault, 0.0))+            [plain "Foo", plain "bar", plain "baz"]+            [[plain "First", plain "row", plain "here"],+             [plain "Second", plain "row", plain "there"]]+        , "Caption without table" =:+          "|+ Foo bar baz +|" =?>+          table (text "Foo bar baz") [] [] []+        , "Table indented with space" =:+          T.unlines+            [ " Foo | bar"+            , " Baz | foo"+            , " Bar | baz"+            ] =?>+          table mempty [(AlignDefault, 0.0), (AlignDefault, 0.0)]+            []+            [[plain "Foo", plain "bar"],+             [plain "Baz", plain "foo"],+             [plain "Bar", plain "baz"]]+        , "Empty cells" =:+          T.unlines+            [ " | Foo"+            , " |"+            , " bar |"+            , " || baz"+            ] =?>+          table mempty [(AlignDefault, 0.0), (AlignDefault, 0.0)]+            [plain "", plain "baz"]+            [[plain "", plain "Foo"],+             [plain "", plain ""],+             [plain "bar", plain ""]]+        ]+    , testGroup "Lists"+      [ "Bullet list" =:+         T.unlines+           [ " - Item1"+           , ""+           , " - Item2"+           ] =?>+         bulletList [ para "Item1"+                    , para "Item2"+                    ]+      , "Ordered list" =:+         T.unlines+           [ " 1. Item1"+           , ""+           , " 2. Item2"+           ] =?>+         orderedListWith (1, Decimal, Period) [ para "Item1"+                                              , para "Item2"+                                              ]+      , "Nested list" =:+         T.unlines+           [ " - Item1"+           , "   - Item2"+           , "   - Item3"+           , " - Item4"+           , "   1. Nested"+           , "   2. Ordered"+           , "   3. List"+           ] =?>+         bulletList [ mconcat [ para "Item1"+                              , bulletList [ para "Item2"+                                           , para "Item3"+                                           ]+                              ]+                    , mconcat [ para "Item4"+                              , orderedListWith (1, Decimal, Period) [ para "Nested"+                                                                     , para "Ordered"+                                                                     , para "List"+                                                                     ]+                              ]+                    ]+      , "List continuation" =:+         T.unlines+           [ " - a"+           , ""+           , "   b"+           , ""+           , "   c"+           ] =?>+         bulletList [ mconcat [ para "a"+                              , para "b"+                              , para "c"+                              ]+                    ]+      -- Emacs Muse allows to separate lists with two or more blank lines.+      -- Text::Amuse (Amusewiki engine) always creates a single list as of version 0.82.+      -- pandoc follows Emacs Muse behavior+      , testGroup "Blank lines"+        [ "Blank lines between list items are not required" =:+          T.unlines+            [ " - Foo"+            , " - Bar"+            ] =?>+          bulletList [ para "Foo"+                     , para "Bar"+                     ]+        , "One blank line between list items is allowed" =:+          T.unlines+            [ " - Foo"+            , ""+            , " - Bar"+            ] =?>+          bulletList [ para "Foo"+                     , para "Bar"+                     ]+        , "Two blank lines separate lists" =:+          T.unlines+            [ " - Foo"+            , ""+            , ""+            , " - Bar"+            ] =?>+          bulletList [ para "Foo" ] <> bulletList [ para "Bar" ]+        , "No blank line after multiline first item" =:+          T.unlines+            [ " - Foo"+            , "   bar"+            , " - Baz"+            ] =?>+          bulletList [ para "Foo bar"+                     , para "Baz"+                     ]+        , "One blank line after multiline first item" =:+          T.unlines+            [ " - Foo"+            , "   bar"+            , ""+            , " - Baz"+            ] =?>+          bulletList [ para "Foo bar"+                     , para "Baz"+                     ]+        , "Two blank lines after multiline first item" =:+          T.unlines+            [ " - Foo"+            , "   bar"+            , ""+            , ""+            , " - Baz"+            ] =?>+          bulletList [ para "Foo bar" ] <> bulletList [ para "Baz" ]+        , "No blank line after list continuation" =:+          T.unlines+            [ " - Foo"+            , ""+            , "   bar"+            , " - Baz"+            ] =?>+          bulletList [ para "Foo" <> para "bar"+                     , para "Baz"+                     ]+        , "One blank line after list continuation" =:+          T.unlines+            [ " - Foo"+            , ""+            , "   bar"+            , ""+            , " - Baz"+            ] =?>+          bulletList [ para "Foo" <> para "bar"+                     , para "Baz"+                     ]+        , "Two blank lines after list continuation" =:+          T.unlines+            [ " - Foo"+            , ""+            , "   bar"+            , ""+            , ""+            , " - Baz"+            ] =?>+          bulletList [ para "Foo" <> para "bar" ] <> bulletList [ para "Baz" ]+        ]+      -- Test that definition list requires a leading space.+      -- Emacs Muse does not require a space, we follow Amusewiki here.+      , "Not a definition list" =:+        T.unlines+          [ "First :: second"+          , "Foo :: bar"+          ] =?>+        para "First :: second Foo :: bar"+      , "Definition list" =:+        T.unlines+          [ " First :: second"+          , " Foo :: bar"+          ] =?>+        definitionList [ ("First", [ para "second" ])+                       , ("Foo", [ para "bar" ])+                       ]+      , "Definition list term cannot include newline" =:+        T.unlines+          [ " Foo" -- "Foo" is not a part of the definition list term+          , " Bar :: baz"+          ] =?>+        para "Foo" <>+        definitionList [ ("Bar", [ para "baz" ]) ]+      , "Multi-line definition lists" =:+        T.unlines+          [ " First term :: Definition of first term"+          , "and its continuation."+          , " Second term :: Definition of second term."+          ] =?>+        definitionList [ ("First term", [ para "Definition of first term and its continuation." ])+                       , ("Second term", [ para "Definition of second term." ])+                       ]+      -- Emacs Muse creates two separate lists when indentation of items is different.+      -- We follow Amusewiki and allow different indentation within one list.+      , "Changing indentation" =:+        T.unlines+          [ " First term :: Definition of first term"+          , "and its continuation."+          , "   Second term :: Definition of second term."+          ] =?>+        definitionList [ ("First term", [ para "Definition of first term and its continuation." ])+                       , ("Second term", [ para "Definition of second term." ])+                       ]+      , "Two blank lines separate definition lists" =:+        T.unlines+          [ " First :: list"+          , ""+          , ""+          , " Second :: list"+          ] =?>+        definitionList [ ("First", [ para "list" ]) ] <>+        definitionList [ ("Second", [ para "list" ]) ]+      -- Headers in first column of list continuation are not allowed+      , "No headers in list continuation" =:+        T.unlines+          [ " - Foo"+          , ""+          , "   * Bar"+          ] =?>+        bulletList [ mconcat [ para "Foo"+                             , para "* Bar"+                             ]+                   ]+      , "List inside a tag" =:+        T.unlines+          [ "<quote>"+          , " 1. First"+          , ""+          , " 2. Second"+          , ""+          , " 3. Third"+          , "</quote>"+          ] =?>+        blockQuote (orderedListWith (1, Decimal, Period) [ para "First"+                                                         , para "Second"+                                                         , para "Third"+                                                         ])+      -- Amusewiki requires block tags to be on separate lines,+      -- but Emacs Muse allows them to be on the same line as contents.+      , "List inside an inline tag" =:+        T.unlines+          [ "<quote> 1. First"+          , ""+          , " 2. Second"+          , ""+          , " 3. Third</quote>"+          ] =?>+        blockQuote (orderedListWith (1, Decimal, Period) [ para "First"+                                                         , para "Second"+                                                         , para "Third"+                                                         ])+      ]+  , testGroup "Meta"+      [ "Title" =:+        "#title Document title" =?>+        let titleInline = toList $ "Document title"+            meta = setMeta "title" (MetaInlines titleInline) $ nullMeta+        in Pandoc meta mempty+      ]+  ]
+ test/Tests/Readers/Odt.hs view
@@ -0,0 +1,170 @@+module Tests.Readers.Odt (tests) where++import Control.Monad (liftM)+import qualified Data.ByteString as BS+import qualified Data.ByteString.Lazy as B+import qualified Data.Map as M+import Data.Text (unpack)+import System.IO.Unsafe (unsafePerformIO)+import Test.Tasty+import Tests.Helpers+import Text.Pandoc+import qualified Text.Pandoc.UTF8 as UTF8++defopts :: ReaderOptions+defopts = def{ readerExtensions = getDefaultExtensions "odt" }++tests :: [TestTree]+tests = testsComparingToMarkdown ++ testsComparingToNative++testsComparingToMarkdown :: [TestTree]+testsComparingToMarkdown    = map nameToTest namesOfTestsComparingToMarkdown+  where nameToTest     name = createTest+                                compareOdtToMarkdown+                                name+                                (toOdtPath      name)+                                (toMarkdownPath name)+        toOdtPath      name = "odt/odt/"      ++ name ++ ".odt"+        toMarkdownPath name = "odt/markdown/" ++ name ++ ".md"++testsComparingToNative   :: [TestTree]+testsComparingToNative      = map nameToTest namesOfTestsComparingToNative+  where nameToTest     name = createTest+                                compareOdtToNative+                                name+                                (toOdtPath      name)+                                (toNativePath   name)+        toOdtPath      name = "odt/odt/"      ++ name ++ ".odt"+        toNativePath   name = "odt/native/"   ++ name ++ ".native"+++newtype NoNormPandoc = NoNormPandoc {unNoNorm :: Pandoc}+  deriving ( Show )++instance ToString NoNormPandoc where+  toString d = unpack $+               purely (writeNative def{ writerTemplate = s }) $ toPandoc d+   where s = case d of+                  NoNormPandoc (Pandoc (Meta m) _)+                    | M.null m  -> Nothing+                    | otherwise -> Just "" -- need this for Meta output++instance ToPandoc NoNormPandoc where+  toPandoc = unNoNorm++getNoNormVia :: (a -> Pandoc) -> String -> Either PandocError a -> NoNormPandoc+getNoNormVia _ readerName (Left  _) = error (readerName ++ " reader failed")+getNoNormVia f _          (Right a) = NoNormPandoc (f a)++type TestCreator =  ReaderOptions+                 -> FilePath -> FilePath+                 -> IO (NoNormPandoc, NoNormPandoc)++compareOdtToNative   :: TestCreator+compareOdtToNative opts odtPath nativePath = do+   nativeFile   <- UTF8.toText <$> BS.readFile nativePath+   odtFile      <- B.readFile       odtPath+   native       <- getNoNormVia id  "native" <$> runIO (readNative def nativeFile)+   odt          <- getNoNormVia id  "odt"    <$> runIO (readOdt  opts odtFile)+   return (odt,native)++compareOdtToMarkdown :: TestCreator+compareOdtToMarkdown opts odtPath markdownPath = do+   markdownFile <- UTF8.toText <$> BS.readFile markdownPath+   odtFile      <- B.readFile       odtPath+   markdown     <- getNoNormVia id "markdown" <$>+                      runIO (readMarkdown def{ readerExtensions = pandocExtensions }+                              markdownFile)+   odt          <- getNoNormVia id "odt"      <$> runIO (readOdt      opts odtFile)+   return (odt,markdown)+++createTest :: TestCreator+           -> TestName+           -> FilePath -> FilePath+           -> TestTree+createTest   creator name path1 path2 =+  unsafePerformIO $ liftM (test id name) (creator defopts path1 path2)++{-+--++getMedia :: FilePath -> FilePath -> IO (Maybe B.ByteString)+getMedia archivePath mediaPath = do+  zf <- B.readFile archivePath >>= return . toArchive+  return $ findEntryByPath ("Pictures/" ++ mediaPath) zf >>= (Just . fromEntry)++compareMediaPathIO :: FilePath -> MediaBag -> FilePath -> IO Bool+compareMediaPathIO mediaPath mediaBag odtPath = do+  odtMedia <- getMedia odtPath mediaPath+  let mbBS   = case lookupMedia mediaPath mediaBag of+                 Just (_, bs) -> bs+                 Nothing      -> error ("couldn't find " +++                                        mediaPath +++                                        " in media bag")+      odtBS = case odtMedia of+                 Just bs -> bs+                 Nothing -> error ("couldn't find " +++                                   mediaPath +++                                   " in media bag")+  return $ mbBS == odtBS++compareMediaBagIO :: FilePath -> IO Bool+compareMediaBagIO odtFile = do+    df <- B.readFile odtFile+    let (_, mb) = readOdt def df+    bools <- mapM+             (\(fp, _, _) -> compareMediaPathIO fp mb odtFile)+             (mediaDirectory mb)+    return $ and bools++testMediaBagIO :: String -> FilePath -> IO TestTree+testMediaBagIO name odtFile = do+  outcome <- compareMediaBagIO odtFile+  return $ testCase name (assertBool+                          ("Media didn't match media bag in file " ++ odtFile)+                          outcome)++testMediaBag :: String -> FilePath -> TestTree+testMediaBag name odtFile = buildTest $ testMediaBagIO name odtFile+-}+--++++namesOfTestsComparingToMarkdown :: [ String ]+namesOfTestsComparingToMarkdown  = [ "bold"+--                                 , "citation"+                                   , "endnote"+                                   , "externalLink"+                                   , "footnote"+                                   , "headers"+--                                 , "horizontalRule"+                                   , "italic"+--                                 , "listBlocks"+                                   , "paragraph"+                                   , "strikeout"+--                                 , "trackedChanges"+                                   , "underlined"+                                   ]++namesOfTestsComparingToNative  :: [ String ]+namesOfTestsComparingToNative   = [ "blockquote"+                                  , "image"+                                  , "imageIndex"+                                  , "imageWithCaption"+                                  , "inlinedCode"+                                  , "orderedListMixed"+                                  , "orderedListRoman"+                                  , "orderedListSimple"+                                  , "referenceToChapter"+                                  , "referenceToListItem"+                                  , "referenceToText"+                                  , "simpleTable"+                                  , "simpleTableWithCaption"+--                                , "table"+                                  , "textMixedStyles"+                                  , "tableWithContents"+                                  , "unicode"+                                  , "unorderedList"+                                  ]
+ test/Tests/Readers/Org.hs view
@@ -0,0 +1,1859 @@+{-# LANGUAGE OverloadedStrings #-}+module Tests.Readers.Org (tests) where++import Data.List (intersperse)+import Data.Text (Text)+import qualified Data.Text as T+import Test.Tasty+import Tests.Helpers+import Text.Pandoc+import Text.Pandoc.Builder+import Text.Pandoc.Shared (underlineSpan)++org :: Text -> Pandoc+org = purely $ readOrg def{ readerExtensions = getDefaultExtensions "org" }++orgSmart :: Text -> Pandoc+orgSmart = purely $ readOrg def { readerExtensions =+                     enableExtension Ext_smart $ getDefaultExtensions "org" }++infix 4 =:+(=:) :: ToString c+     => String -> (Text, c) -> TestTree+(=:) = test org++spcSep :: [Inlines] -> Inlines+spcSep = mconcat . intersperse space++simpleTable' :: Int+             -> [Blocks]+             -> [[Blocks]]+             -> Blocks+simpleTable' n = table "" (replicate n (AlignDefault, 0.0))++-- | Create a span for the given tag.+tagSpan :: String -> Inlines+tagSpan t = spanWith ("", ["tag"], [("tag-name", t)]) . smallcaps $ str t++tests :: [TestTree]+tests =+  [ testGroup "Inlines" $+      [ "Plain String" =:+          "Hello, World" =?>+          para (spcSep [ "Hello,", "World" ])++      , "Emphasis" =:+          "/Planet Punk/" =?>+          para (emph . spcSep $ ["Planet", "Punk"])++      , "Strong" =:+          "*Cider*" =?>+          para (strong "Cider")++      , "Strong Emphasis" =:+          "/*strength*/" =?>+          para (emph . strong $ "strength")++      , "Emphasized Strong preceded by space" =:+          " */super/*" =?>+          para (strong . emph $ "super")++      , "Underline" =:+          "_underline_" =?>+          para (underlineSpan $ "underline")++      , "Strikeout" =:+          "+Kill Bill+" =?>+          para (strikeout . spcSep $ [ "Kill", "Bill" ])++      , "Verbatim" =:+          "=Robot.rock()=" =?>+          para (code "Robot.rock()")++      , "Code" =:+          "~word for word~" =?>+          para (code "word for word")++      , "Math $..$" =:+          "$E=mc^2$" =?>+           para (math "E=mc^2")++      , "Math $$..$$" =:+          "$$E=mc^2$$" =?>+          para (displayMath "E=mc^2")++      , "Math \\[..\\]" =:+          "\\[E=ℎν\\]" =?>+          para (displayMath "E=ℎν")++      , "Math \\(..\\)" =:+          "\\(σ_x σ_p ≥ \\frac{ℏ}{2}\\)" =?>+          para (math "σ_x σ_p ≥ \\frac{ℏ}{2}")++      , "Symbol" =:+          "A * symbol" =?>+          para (str "A" <> space <> str "*" <> space <> "symbol")++      , "Superscript simple expression" =:+          "2^-λ" =?>+          para (str "2" <> superscript "-λ")++      , "Superscript multi char" =:+          "2^{n-1}" =?>+          para (str "2" <> superscript "n-1")++      , "Subscript simple expression" =:+          "a_n" =?>+          para (str "a" <> subscript "n")++      , "Subscript multi char" =:+          "a_{n+1}" =?>+          para (str "a" <> subscript "n+1")++      , "Linebreak" =:+          "line \\\\ \nbreak" =?>+          para ("line" <> linebreak <> "break")++      , "Inline note" =:+          "[fn::Schreib mir eine E-Mail]" =?>+          para (note $ para "Schreib mir eine E-Mail")++      , "Markup-chars not occuring on word break are symbols" =:+          T.unlines [ "this+that+ +so+on"+                    , "seven*eight* nine*"+                    , "+not+funny+"+                    ] =?>+          para ("this+that+ +so+on" <> softbreak <>+                "seven*eight* nine*" <> softbreak <>+                strikeout "not+funny")++      , "No empty markup" =:+          "// ** __ <> == ~~ $$" =?>+          para (spcSep [ "//", "**", "__", "<>", "==", "~~", "$$" ])++      , "Adherence to Org's rules for markup borders" =:+          "/t/& a/ / ./r/ (*l*) /e/! /b/." =?>+          para (spcSep [ emph $ "t/&" <> space <> "a"+                       , "/"+                       , "./r/"+                       , "(" <> strong "l" <> ")"+                       , emph "e" <> "!"+                       , emph "b" <> "."+                       ])++      , "Quotes are allowed border chars" =:+          "/'yep/ *sure\"*" =?>+          para (emph "'yep" <> space <> strong "sure\"")++      , "Spaces are forbidden border chars" =:+          "/nada /" =?>+          para "/nada /"++      , "Markup should work properly after a blank line" =:+        T.unlines ["foo", "", "/bar/"] =?>+        (para $ text "foo") <> (para $ emph $ text "bar")++      , "Inline math must stay within three lines" =:+          T.unlines [ "$a", "b", "c$", "$d", "e", "f", "g$" ] =?>+          para ((math "a\nb\nc") <> softbreak <>+                "$d" <> softbreak <> "e" <> softbreak <>+                "f" <> softbreak <> "g$")++      , "Single-character math" =:+          "$a$ $b$! $c$?" =?>+          para (spcSep [ math "a"+                       , "$b$!"+                       , (math "c") <> "?"+                       ])++      , "Markup may not span more than two lines" =:+          "/this *is +totally\nnice+ not*\nemph/" =?>+          para ("/this" <> space <>+                  strong ("is" <> space <>+                          strikeout ("totally" <>+                            softbreak <> "nice") <>+                          space <> "not") <>+                  softbreak <> "emph/")++      , "Sub- and superscript expressions" =:+         T.unlines [ "a_(a(b)(c)d)"+                   , "e^(f(g)h)"+                   , "i_(jk)l)"+                   , "m^()n"+                   , "o_{p{q{}r}}"+                   , "s^{t{u}v}"+                   , "w_{xy}z}"+                   , "1^{}2"+                   , "3_{{}}"+                   , "4^(a(*b(c*)d))"+                   ] =?>+         para (mconcat $ intersperse softbreak+                      [ "a" <> subscript "(a(b)(c)d)"+                      , "e" <> superscript "(f(g)h)"+                      , "i" <> (subscript "(jk)") <> "l)"+                      , "m" <> (superscript "()") <> "n"+                      , "o" <> subscript "p{q{}r}"+                      , "s" <> superscript "t{u}v"+                      , "w" <> (subscript "xy") <> "z}"+                      , "1" <> (superscript "") <> "2"+                      , "3" <> subscript "{}"+                      , "4" <> superscript ("(a(" <> strong "b(c" <> ")d))")+                      ])+      , "Verbatim text can contain equal signes (=)" =:+          "=is_subst = True=" =?>+          para (code "is_subst = True")++      , testGroup "Images"+        [ "Image" =:+            "[[./sunset.jpg]]" =?>+            (para $ image "./sunset.jpg" "" "")++        , "Image with explicit file: prefix" =:+            "[[file:sunrise.jpg]]" =?>+            (para $ image "sunrise.jpg" "" "")++        , "Multiple images within a paragraph" =:+            T.unlines [ "[[file:sunrise.jpg]]"+                      , "[[file:sunset.jpg]]"+                      ] =?>+            (para $ (image "sunrise.jpg" "" "")+                 <> softbreak+                 <> (image "sunset.jpg" "" ""))++        , "Image with html attributes" =:+            T.unlines [ "#+ATTR_HTML: :width 50%"+                      , "[[file:guinea-pig.gif]]"+                      ] =?>+            (para $ imageWith ("", [], [("width", "50%")]) "guinea-pig.gif" "" "")+        ]++      , "Explicit link" =:+          "[[http://zeitlens.com/][pseudo-random /nonsense/]]" =?>+          (para $ link "http://zeitlens.com/" ""+                       ("pseudo-random" <> space <> emph "nonsense"))++      , "Self-link" =:+          "[[http://zeitlens.com/]]" =?>+          (para $ link "http://zeitlens.com/" "" "http://zeitlens.com/")++      , "Absolute file link" =:+          "[[/url][hi]]" =?>+          (para $ link "file:///url" "" "hi")++      , "Link to file in parent directory" =:+          "[[../file.txt][moin]]" =?>+          (para $ link "../file.txt" "" "moin")++      , "Empty link (for gitit interop)" =:+          "[[][New Link]]" =?>+          (para $ link "" "" "New Link")++      , "Image link" =:+          "[[sunset.png][file:dusk.svg]]" =?>+          (para $ link "sunset.png" "" (image "dusk.svg" "" ""))++      , "Image link with non-image target" =:+          "[[http://example.com][./logo.png]]" =?>+          (para $ link "http://example.com" "" (image "./logo.png" "" ""))++      , "Plain link" =:+          "Posts on http://zeitlens.com/ can be funny at times." =?>+          (para $ spcSep [ "Posts", "on"+                         , link "http://zeitlens.com/" "" "http://zeitlens.com/"+                         , "can", "be", "funny", "at", "times."+                         ])++      , "Angle link" =:+          "Look at <http://moltkeplatz.de> for fnords." =?>+          (para $ spcSep [ "Look", "at"+                         , link "http://moltkeplatz.de" "" "http://moltkeplatz.de"+                         , "for", "fnords."+                         ])++      , "Absolute file link" =:+          "[[file:///etc/passwd][passwd]]" =?>+          (para $ link "file:///etc/passwd" "" "passwd")++      , "File link" =:+          "[[file:target][title]]" =?>+          (para $ link "target" "" "title")++      , "Anchor" =:+          "<<anchor>> Link here later." =?>+          (para $ spanWith ("anchor", [], []) mempty <>+                  "Link" <> space <> "here" <> space <> "later.")++      , "Inline code block" =:+          "src_emacs-lisp{(message \"Hello\")}" =?>+          (para $ codeWith ( ""+                           , [ "commonlisp" ]+                           , [ ("org-language", "emacs-lisp") ])+                           "(message \"Hello\")")++      , "Inline code block with arguments" =:+          "src_sh[:export both :results output]{echo 'Hello, World'}" =?>+          (para $ codeWith ( ""+                           , [ "bash" ]+                           , [ ("org-language", "sh")+                             , ("export", "both")+                             , ("results", "output")+                             ]+                           )+                           "echo 'Hello, World'")++      , "Inline code block with toggle" =:+          "src_sh[:toggle]{echo $HOME}" =?>+          (para $ codeWith ( ""+                           , [ "bash" ]+                           , [ ("org-language", "sh")+                             , ("toggle", "yes")+                             ]+                           )+                           "echo $HOME")++      , "Citation" =:+          "[@nonexistent]" =?>+          let citation = Citation+                         { citationId = "nonexistent"+                         , citationPrefix = []+                         , citationSuffix = []+                         , citationMode = NormalCitation+                         , citationNoteNum = 0+                         , citationHash = 0}+          in (para $ cite [citation] "[@nonexistent]")++      , "Citation containing text" =:+          "[see @item1 p. 34-35]" =?>+          let citation = Citation+                         { citationId = "item1"+                         , citationPrefix = [Str "see"]+                         , citationSuffix = [Space ,Str "p.",Space,Str "34-35"]+                         , citationMode = NormalCitation+                         , citationNoteNum = 0+                         , citationHash = 0}+          in (para $ cite [citation] "[see @item1 p. 34-35]")++      , "Org-ref simple citation" =:+        "cite:pandoc" =?>+        let citation = Citation+                       { citationId = "pandoc"+                       , citationPrefix = mempty+                       , citationSuffix = mempty+                       , citationMode = AuthorInText+                       , citationNoteNum = 0+                       , citationHash = 0+                       }+        in (para $ cite [citation] "cite:pandoc")++      , "Org-ref simple citation with underscores" =:+        "cite:pandoc_org_ref" =?>+        let citation = Citation+                       { citationId = "pandoc_org_ref"+                       , citationPrefix = mempty+                       , citationSuffix = mempty+                       , citationMode = AuthorInText+                       , citationNoteNum = 0+                       , citationHash = 0+                       }+        in (para $ cite [citation] "cite:pandoc_org_ref")++      , "Org-ref simple citation succeeded by comma" =:+        "cite:pandoc," =?>+        let citation = Citation+                       { citationId = "pandoc"+                       , citationPrefix = mempty+                       , citationSuffix = mempty+                       , citationMode = AuthorInText+                       , citationNoteNum = 0+                       , citationHash = 0+                       }+        in (para $ cite [citation] "cite:pandoc" <> str ",")++      , "Org-ref simple citation succeeded by dot" =:+        "cite:pandoc." =?>+        let citation = Citation+                       { citationId = "pandoc"+                       , citationPrefix = mempty+                       , citationSuffix = mempty+                       , citationMode = AuthorInText+                       , citationNoteNum = 0+                       , citationHash = 0+                       }+        in (para $ cite [citation] "cite:pandoc" <> str ".")++      , "Org-ref simple citation succeeded by colon" =:+        "cite:pandoc:" =?>+        let citation = Citation+                       { citationId = "pandoc"+                       , citationPrefix = mempty+                       , citationSuffix = mempty+                       , citationMode = AuthorInText+                       , citationNoteNum = 0+                       , citationHash = 0+                       }+        in (para $ cite [citation] "cite:pandoc" <> str ":")++      , "Org-ref simple citep citation" =:+        "citep:pandoc" =?>+        let citation = Citation+                       { citationId = "pandoc"+                       , citationPrefix = mempty+                       , citationSuffix = mempty+                       , citationMode = NormalCitation+                       , citationNoteNum = 0+                       , citationHash = 0+                       }+        in (para $ cite [citation] "citep:pandoc")++      , "Org-ref extended citation" =:+        "[[citep:Dominik201408][See page 20::, for example]]" =?>+        let citation = Citation+                       { citationId = "Dominik201408"+                       , citationPrefix = toList "See page 20"+                       , citationSuffix = toList ", for example"+                       , citationMode = NormalCitation+                       , citationNoteNum = 0+                       , citationHash = 0+                       }+        in (para $ cite [citation] "[[citep:Dominik201408][See page 20::, for example]]")++      , testGroup "Berkeley-style citations" $+        let pandocCite = Citation+              { citationId = "Pandoc"+              , citationPrefix = mempty+              , citationSuffix = mempty+              , citationMode = NormalCitation+              , citationNoteNum = 0+              , citationHash = 0+              }+            pandocInText = pandocCite { citationMode = AuthorInText }+            dominikCite = Citation+              { citationId = "Dominik201408"+              , citationPrefix = mempty+              , citationSuffix = mempty+              , citationMode = NormalCitation+              , citationNoteNum = 0+              , citationHash = 0+              }+            dominikInText = dominikCite { citationMode = AuthorInText }+        in [+            "Berkeley-style in-text citation" =:+              "See @Dominik201408." =?>+                (para $ "See "+                      <> cite [dominikInText] "@Dominik201408"+                      <> ".")++          , "Berkeley-style parenthetical citation list" =:+              "[(cite): see; @Dominik201408;also @Pandoc; and others]" =?>+              let pandocCite'  = pandocCite {+                                   citationPrefix = toList "also"+                                 , citationSuffix = toList "and others"+                                 }+                  dominikCite' = dominikCite {+                                   citationPrefix = toList "see"+                                 }+              in (para $ cite [dominikCite', pandocCite'] "")++          , "Berkeley-style plain citation list" =:+              "[cite: See; @Dominik201408; and @Pandoc; and others]" =?>+              let pandocCite' = pandocInText {+                                  citationPrefix = toList "and"+                                }+              in (para $ "See "+                      <> cite [dominikInText] ""+                      <> "," <> space+                      <> cite [pandocCite'] ""+                      <> "," <> space <> "and others")+        ]++      , "Inline LaTeX symbol" =:+          "\\dots" =?>+          para "…"++      , "Inline LaTeX command" =:+          "\\textit{Emphasised}" =?>+          para (emph "Emphasised")++      , "Inline LaTeX command with spaces" =:+          "\\emph{Emphasis mine}" =?>+          para (emph "Emphasis mine")++      , "Inline LaTeX math symbol" =:+          "\\tau" =?>+          para (emph "τ")++      , "Unknown inline LaTeX command" =:+          "\\notacommand{foo}" =?>+          para (rawInline "latex" "\\notacommand{foo}")++      , "Export snippet" =:+          "@@html:<kbd>M-x org-agenda</kbd>@@" =?>+          para (rawInline "html" "<kbd>M-x org-agenda</kbd>")++      , "MathML symbol in LaTeX-style" =:+          "There is a hackerspace in Lübeck, Germany, called nbsp (unicode symbol: '\\nbsp')." =?>+          para ("There is a hackerspace in Lübeck, Germany, called nbsp (unicode symbol: ' ').")++      , "MathML symbol in LaTeX-style, including braces" =:+          "\\Aacute{}stor" =?>+          para "Ástor"++      , "MathML copy sign" =:+          "\\copy" =?>+          para "©"++      , "MathML symbols, space separated" =:+          "\\ForAll \\Auml" =?>+          para "∀ Ä"++      , "LaTeX citation" =:+          "\\cite{Coffee}" =?>+          let citation = Citation+                         { citationId = "Coffee"+                         , citationPrefix = []+                         , citationSuffix = []+                         , citationMode = NormalCitation+                         , citationNoteNum = 0+                         , citationHash = 0}+          in (para . cite [citation] $ rawInline "latex" "\\cite{Coffee}")++      , "Macro" =:+          T.unlines [ "#+MACRO: HELLO /Hello, $1/"+                    , "{{{HELLO(World)}}}"+                    ] =?>+          para (emph "Hello, World")++      , "Macro repeting its argument" =:+          T.unlines [ "#+MACRO: HELLO $1$1"+                    , "{{{HELLO(moin)}}}"+                    ] =?>+          para "moinmoin"++      , "Macro called with too few arguments" =:+          T.unlines [ "#+MACRO: HELLO Foo $1 $2 Bar"+                    , "{{{HELLO()}}}"+                    ] =?>+          para "Foo Bar"+      ]++  , testGroup "Meta Information" $+      [ "Comment" =:+          "# Nothing to see here" =?>+          (mempty::Blocks)++      , "Not a comment" =:+          "#-tag" =?>+          para "#-tag"++      , "Comment surrounded by Text" =:+          T.unlines [ "Before"+                    , "# Comment"+                    , "After"+                    ] =?>+          mconcat [ para "Before"+                  , para "After"+                  ]++      , "Title" =:+        "#+TITLE: Hello, World" =?>+        let titleInline = toList $ "Hello," <> space <> "World"+            meta = setMeta "title" (MetaInlines titleInline) $ nullMeta+        in Pandoc meta mempty++      , "Author" =:+        "#+author: Albert /Emacs-Fanboy/ Krewinkel" =?>+        let author = toList . spcSep $ [ "Albert", emph "Emacs-Fanboy", "Krewinkel" ]+            meta = setMeta "author" (MetaList [MetaInlines author]) $ nullMeta+        in Pandoc meta mempty++      , "Multiple authors" =:+        "#+author: James Dewey Watson, Francis Harry Compton Crick " =?>+        let watson = MetaInlines $ toList "James Dewey Watson"+            crick = MetaInlines $ toList "Francis Harry Compton Crick"+            meta = setMeta "author" (MetaList [watson, crick]) $ nullMeta+        in Pandoc meta mempty++      , "Date" =:+        "#+Date: Feb. *28*, 2014" =?>+        let date = toList . spcSep $ [ "Feb.", (strong "28") <> ",", "2014" ]+            meta = setMeta "date" (MetaInlines date) $ nullMeta+        in Pandoc meta mempty++      , "Description" =:+        "#+DESCRIPTION: Explanatory text" =?>+        let description = "Explanatory text"+            meta = setMeta "description" (MetaString description) $ nullMeta+        in Pandoc meta mempty++      , "Properties drawer" =:+          T.unlines [ "  :PROPERTIES:"+                    , "  :setting: foo"+                    , "  :END:"+                    ] =?>+          (mempty::Blocks)++      , "LaTeX_headers options are translated to header-includes" =:+          "#+LaTeX_header: \\usepackage{tikz}" =?>+          let latexInlines = rawInline "latex" "\\usepackage{tikz}"+              inclList = MetaList [MetaInlines (toList latexInlines)]+              meta = setMeta "header-includes" inclList nullMeta+          in Pandoc meta mempty++      , "LaTeX_class option is translated to documentclass" =:+          "#+LATEX_CLASS: article" =?>+          let meta = setMeta "documentclass" (MetaString "article") nullMeta+          in Pandoc meta mempty++      , "LaTeX_class_options is translated to classoption" =:+          "#+LATEX_CLASS_OPTIONS: [a4paper]" =?>+          let meta = setMeta "classoption" (MetaString "a4paper") nullMeta+          in Pandoc meta mempty++      , "LaTeX_class_options is translated to classoption" =:+          "#+html_head: <meta/>" =?>+          let html = rawInline "html" "<meta/>"+              inclList = MetaList [MetaInlines (toList html)]+              meta = setMeta "header-includes" inclList nullMeta+          in Pandoc meta mempty++      , "later meta definitions take precedence" =:+          T.unlines [ "#+AUTHOR: this will not be used"+                    , "#+author: Max"+                    ] =?>+          let author = MetaInlines [Str "Max"]+              meta = setMeta "author" (MetaList [author]) $ nullMeta+          in Pandoc meta mempty++      , "Logbook drawer" =:+          T.unlines [ "  :LogBook:"+                    , "  - State \"DONE\"       from \"TODO\"       [2014-03-03 Mon 11:00]"+                    , "  :END:"+                    ] =?>+          (mempty::Blocks)++      , "Drawer surrounded by text" =:+          T.unlines [ "Before"+                    , ":PROPERTIES:"+                    , ":END:"+                    , "After"+                    ] =?>+          para "Before" <> para "After"++      , "Drawer markers must be the only text in the line" =:+          T.unlines [ "  :LOGBOOK: foo"+                    , "  :END: bar"+                    ] =?>+          para (":LOGBOOK: foo" <> softbreak <> ":END: bar")++      , "Drawers can be arbitrary" =:+          T.unlines [ ":FOO:"+                    , "/bar/"+                    , ":END:"+                    ] =?>+          divWith (mempty, ["FOO", "drawer"], mempty) (para $ emph "bar")++      , "Anchor reference" =:+          T.unlines [ "<<link-here>> Target."+                    , ""+                    , "[[link-here][See here!]]"+                    ] =?>+          (para (spanWith ("link-here", [], []) mempty <> "Target.") <>+           para (link "#link-here" "" ("See" <> space <> "here!")))++      , "Search links are read as emph" =:+          "[[Wally][Where's Wally?]]" =?>+          (para (emph $ "Where's" <> space <> "Wally?"))++      , "Link to nonexistent anchor" =:+          T.unlines [ "<<link-here>> Target."+                    , ""+                    , "[[link$here][See here!]]"+                    ] =?>+          (para (spanWith ("link-here", [], []) mempty <> "Target.") <>+           para (emph ("See" <> space <> "here!")))++      , "Link abbreviation" =:+          T.unlines [ "#+LINK: wp https://en.wikipedia.org/wiki/%s"+                    , "[[wp:Org_mode][Wikipedia on Org-mode]]"+                    ] =?>+          (para (link "https://en.wikipedia.org/wiki/Org_mode" ""+                      ("Wikipedia" <> space <> "on" <> space <> "Org-mode")))++      , "Link abbreviation, defined after first use" =:+          T.unlines [ "[[zl:non-sense][Non-sense articles]]"+                    , "#+LINK: zl http://zeitlens.com/tags/%s.html"+                    ] =?>+          (para (link "http://zeitlens.com/tags/non-sense.html" ""+                      ("Non-sense" <> space <> "articles")))++      , "Link abbreviation, URL encoded arguments" =:+          T.unlines [ "#+link: expl http://example.com/%h/foo"+                    , "[[expl:Hello, World!][Moin!]]"+                    ] =?>+          (para (link "http://example.com/Hello%2C%20World%21/foo" "" "Moin!"))++      , "Link abbreviation, append arguments" =:+          T.unlines [ "#+link: expl http://example.com/"+                    , "[[expl:foo][bar]]"+                    ] =?>+          (para (link "http://example.com/foo" "" "bar"))+++      , testGroup "export options"++          [ "disable simple sub/superscript syntax" =:+              T.unlines [ "#+OPTIONS: ^:nil"+                        , "a^b"+                        ] =?>+              para "a^b"++          , "directly select drawers to be exported" =:+              T.unlines [ "#+OPTIONS: d:(\"IMPORTANT\")"+                        , ":IMPORTANT:"+                        , "23"+                        , ":END:"+                        , ":BORING:"+                        , "very boring"+                        , ":END:"+                        ] =?>+              divWith (mempty, ["IMPORTANT", "drawer"], mempty) (para "23")++          , "exclude drawers from being exported" =:+              T.unlines [ "#+OPTIONS: d:(not \"BORING\")"+                        , ":IMPORTANT:"+                        , "5"+                        , ":END:"+                        , ":BORING:"+                        , "very boring"+                        , ":END:"+                        ] =?>+              divWith (mempty, ["IMPORTANT", "drawer"], mempty) (para "5")++          , "don't include archive trees" =:+              T.unlines [ "#+OPTIONS: arch:nil"+                        , "* old  :ARCHIVE:"+                        ] =?>+              (mempty ::Blocks)++          , "include complete archive trees" =:+              T.unlines [ "#+OPTIONS: arch:t"+                        , "* old  :ARCHIVE:"+                        , "  boring"+                        ] =?>+              mconcat [ headerWith ("old", [], mempty) 1+                                   ("old" <> space <> tagSpan "ARCHIVE")+                      , para "boring"+                      ]++          , "include archive tree header only" =:+              T.unlines [ "#+OPTIONS: arch:headline"+                        , "* old  :ARCHIVE:"+                        , "  boring"+                        ] =?>+              headerWith ("old", [], mempty) 1 ("old" <> space <> tagSpan "ARCHIVE")++          , "limit headline depth" =:+              T.unlines [ "#+OPTIONS: H:2"+                        , "* top-level section"+                        , "** subsection"+                        , "*** list item 1"+                        , "*** list item 2"+                        ] =?>+              mconcat [ headerWith ("top-level-section", [], [])    1 "top-level section"+                      , headerWith ("subsection", [], []) 2 "subsection"+                      , orderedList [ para "list item 1", para "list item 2" ]+                      ]++          , "turn all headlines into lists" =:+              T.unlines [ "#+OPTIONS: H:0"+                        , "first block"+                        , "* top-level section 1"+                        , "** subsection"+                        , "* top-level section 2"+                        ] =?>+              mconcat [ para "first block"+                      , orderedList+                        [ (para "top-level section 1" <>+                           orderedList [ para "subsection" ])+                        , para "top-level section 2" ]+                      ]++          , "preserve linebreaks as hard breaks" =:+              T.unlines [ "#+OPTIONS: \\n:t"+                        , "first"+                        , "second"+                        ] =?>+              para ("first" <> linebreak <> "second")++          , "disable author export" =:+              T.unlines [ "#+OPTIONS: author:nil"+                        , "#+AUTHOR: ShyGuy"+                        ] =?>+              Pandoc nullMeta mempty++          , "disable creator export" =:+              T.unlines [ "#+OPTIONS: creator:nil"+                        , "#+creator: The Architect"+                        ] =?>+              Pandoc nullMeta mempty++          , "disable email export" =:+              T.unlines [ "#+OPTIONS: email:nil"+                        , "#+email: no-mail-please@example.com"+                        ] =?>+              Pandoc nullMeta mempty++          , "disable inclusion of todo keywords" =:+              T.unlines [ "#+OPTIONS: todo:nil"+                        , "** DONE todo export"+                        ] =?>+              headerWith ("todo-export", [], []) 2 "todo export"++          , "remove tags from headlines" =:+              T.unlines [ "#+OPTIONS: tags:nil"+                        , "* Headline :hello:world:"+                        ] =?>+              headerWith ("headline", [], mempty) 1 "Headline"+          ]+      ]++  , testGroup "Basic Blocks" $+      [ "Paragraph" =:+          "Paragraph\n" =?>+          para "Paragraph"++      , testGroup "headers" $+        [ "First Level Header" =:+            "* Headline\n" =?>+            headerWith ("headline", [], []) 1 "Headline"++        , "Third Level Header" =:+            "*** Third Level Headline\n" =?>+            headerWith ("third-level-headline", [], [])+                       3+                       ("Third" <> space <> "Level" <> space <> "Headline")++        , "Compact Headers with Paragraph" =:+            T.unlines [ "* First Level"+                      , "** Second Level"+                      , "   Text"+                      ] =?>+            mconcat [ headerWith ("first-level", [], [])+                                 1+                                 ("First" <> space <> "Level")+                    , headerWith ("second-level", [], [])+                                 2+                                 ("Second" <> space <> "Level")+                    , para "Text"+                    ]++        , "Separated Headers with Paragraph" =:+            T.unlines [ "* First Level"+                      , ""+                      , "** Second Level"+                      , ""+                      , "   Text"+                      ] =?>+            mconcat [ headerWith ("first-level", [], [])+                                 1+                                 ("First" <> space <> "Level")+                    , headerWith ("second-level", [], [])+                                 2+                                 ("Second" <> space <> "Level")+                    , para "Text"+                    ]++        , "Headers not preceded by a blank line" =:+            T.unlines [ "** eat dinner"+                      , "Spaghetti and meatballs tonight."+                      , "** walk dog"+                      ] =?>+            mconcat [ headerWith ("eat-dinner", [], [])+                                 2+                                 ("eat" <> space <> "dinner")+                    , para $ spcSep [ "Spaghetti", "and", "meatballs", "tonight." ]+                    , headerWith ("walk-dog", [], [])+                                 2+                                 ("walk" <> space <> "dog")+                    ]++        , testGroup "Todo keywords"+          [ "Header with known todo keyword" =:+              "* TODO header" =?>+              let todoSpan = spanWith ("", ["todo", "TODO"], []) "TODO"+              in headerWith ("header", [], []) 1 (todoSpan <> space <> "header")++          , "Header marked as done" =:+              "* DONE header" =?>+              let todoSpan = spanWith ("", ["done", "DONE"], []) "DONE"+              in headerWith ("header", [], []) 1 (todoSpan <> space <> "header")++          , "Header with unknown todo keyword" =:+              "* WAITING header" =?>+              headerWith ("waiting-header", [], []) 1 "WAITING header"++          , "Custom todo keywords" =:+              T.unlines [ "#+TODO: WAITING CANCELLED"+                        , "* WAITING compile"+                        , "* CANCELLED lunch"+                        ] =?>+              let todoSpan = spanWith ("", ["todo", "WAITING"], []) "WAITING"+                  doneSpan = spanWith ("", ["done", "CANCELLED"], []) "CANCELLED"+              in headerWith ("compile", [], []) 1 (todoSpan <> space <> "compile")+              <> headerWith ("lunch", [], []) 1 (doneSpan <> space <> "lunch")++          , "Custom todo keywords with multiple done-states" =:+              T.unlines [ "#+TODO: WAITING | DONE CANCELLED "+                        , "* WAITING compile"+                        , "* CANCELLED lunch"+                        , "* DONE todo-feature"+                        ] =?>+              let waiting = spanWith ("", ["todo", "WAITING"], []) "WAITING"+                  cancelled = spanWith ("", ["done", "CANCELLED"], []) "CANCELLED"+                  done = spanWith ("", ["done", "DONE"], []) "DONE"+              in headerWith ("compile", [], []) 1 (waiting <> space <> "compile")+              <> headerWith ("lunch", [], []) 1 (cancelled <> space <> "lunch")+              <> headerWith ("todo-feature", [], []) 1 (done <> space <> "todo-feature")+          ]++        , "Tagged headers" =:+            T.unlines [ "* Personal       :PERSONAL:"+                      , "** Call Mom      :@PHONE:"+                      , "** Call John     :@PHONE:JOHN: "+                      ] =?>+            mconcat [ headerWith ("personal", [], [])+                                 1+                                 ("Personal " <> tagSpan "PERSONAL")+                    , headerWith ("call-mom", [], [])+                                 2+                                 ("Call Mom " <> tagSpan "@PHONE")+                    , headerWith ("call-john", [], [])+                                 2+                                 ("Call John " <> tagSpan "@PHONE" <> "\160" <> tagSpan "JOHN")+                    ]++        , "Untagged header containing colons" =:+            "* This: is not: tagged" =?>+            headerWith ("this-is-not-tagged", [], []) 1 "This: is not: tagged"++        , "Header starting with strokeout text" =:+            T.unlines [ "foo"+                      , ""+                      , "* +thing+ other thing"+                      ] =?>+            mconcat [ para "foo"+                    , headerWith ("thing-other-thing", [], [])+                                 1+                                 ((strikeout "thing") <> " other thing")+                    ]++        , "Comment Trees" =:+            T.unlines [ "* COMMENT A comment tree"+                      , "  Not much going on here"+                      , "** This will be dropped"+                      , "* Comment tree above"+                      ] =?>+            headerWith ("comment-tree-above", [], []) 1 "Comment tree above"++        , "Nothing but a COMMENT header" =:+            "* COMMENT Test" =?>+            (mempty::Blocks)++        , "Tree with :noexport:" =:+            T.unlines [ "* Should be ignored :archive:noexport:old:"+                      , "** Old stuff"+                      , "   This is not going to be exported"+                      ] =?>+            (mempty::Blocks)++        , "Subtree with :noexport:" =:+            T.unlines [ "* Exported"+                      , "** This isn't exported :noexport:"+                      , "*** This neither"+                      , "** But this is"+                      ] =?>+            mconcat [ headerWith ("exported", [], []) 1 "Exported"+                    , headerWith ("but-this-is", [], []) 2 "But this is"+                    ]++        , "Preferences are treated as header attributes" =:+            T.unlines [ "* foo"+                      , "  :PROPERTIES:"+                      , "  :custom_id: fubar"+                      , "  :bar: baz"+                      , "  :END:"+                      ] =?>+            headerWith ("fubar", [], [("bar", "baz")]) 1 "foo"+++        , "Headers marked with a unnumbered property get a class of the same name" =:+            T.unlines [ "* Not numbered"+                      , "  :PROPERTIES:"+                      , "  :UNNUMBERED: t"+                      , "  :END:"+                      ] =?>+            headerWith ("not-numbered", ["unnumbered"], []) 1 "Not numbered"+      ]+      , "Paragraph starting with an asterisk" =:+          "*five" =?>+          para "*five"++      , "Paragraph containing asterisk at beginning of line" =:+          T.unlines [ "lucky"+                    , "*star"+                    ] =?>+          para ("lucky" <> softbreak <> "*star")++      , "Example block" =:+          T.unlines [ ": echo hello"+                    , ": echo dear tester"+                    ] =?>+          codeBlockWith ("", ["example"], []) "echo hello\necho dear tester\n"++      , "Example block surrounded by text" =:+          T.unlines [ "Greetings"+                    , ": echo hello"+                    , ": echo dear tester"+                    , "Bye"+                    ] =?>+          mconcat [ para "Greetings"+                  , codeBlockWith ("", ["example"], [])+                                  "echo hello\necho dear tester\n"+                  , para "Bye"+                  ]++      , "Horizontal Rule" =:+          T.unlines [ "before"+                    , "-----"+                    , "after"+                    ] =?>+          mconcat [ para "before"+                  , horizontalRule+                  , para "after"+                  ]++      , "Not a Horizontal Rule" =:+          "----- em and en dash" =?>+          para "\8212\8211 em and en dash"++      , "Comment Block" =:+          T.unlines [ "#+BEGIN_COMMENT"+                    , "stuff"+                    , "bla"+                    , "#+END_COMMENT"] =?>+          (mempty::Blocks)++      , testGroup "Figures" $+        [ "Figure" =:+            T.unlines [ "#+caption: A very courageous man."+                      , "#+name: goodguy"+                      , "[[file:edward.jpg]]"+                      ] =?>+            para (image "edward.jpg" "fig:goodguy" "A very courageous man.")++        , "Figure with no name" =:+            T.unlines [ "#+caption: I've been through the desert on this"+                      , "[[file:horse.png]]"+                      ] =?>+            para (image "horse.png" "fig:" "I've been through the desert on this")++        , "Figure with `fig:` prefix in name" =:+            T.unlines [ "#+caption: Used as a metapher in evolutionary biology."+                      , "#+name: fig:redqueen"+                      , "[[./the-red-queen.jpg]]"+                      ] =?>+            para (image "./the-red-queen.jpg" "fig:redqueen"+                        "Used as a metapher in evolutionary biology.")++        , "Figure with HTML attributes" =:+            T.unlines [ "#+CAPTION: mah brain just explodid"+                      , "#+NAME: lambdacat"+                      , "#+ATTR_HTML: :style color: blue :role button"+                      , "[[file:lambdacat.jpg]]"+                      ] =?>+            let kv = [("style", "color: blue"), ("role", "button")]+                name = "fig:lambdacat"+                caption = "mah brain just explodid"+            in para (imageWith (mempty, mempty, kv) "lambdacat.jpg" name caption)++        , "Labelled figure" =:+            T.unlines [ "#+CAPTION: My figure"+                      , "#+LABEL: fig:myfig"+                      , "[[file:blub.png]]"+                      ] =?>+            let attr = ("fig:myfig", mempty, mempty)+            in para (imageWith attr "blub.png" "fig:" "My figure")++        , "Figure with empty caption" =:+            T.unlines [ "#+CAPTION:"+                      , "[[file:guess.jpg]]"+                      ] =?>+            para (image "guess.jpg" "fig:" "")+        ]++      , testGroup "Footnotes"+        [ "Footnote" =:+            T.unlines [ "A footnote[1]"+                      , ""+                      , "[1] First paragraph"+                      , ""+                      , "second paragraph"+                      ] =?>+            para (mconcat+                  [ "A", space, "footnote"+                  , note $ mconcat [ para ("First" <> space <> "paragraph")+                                   , para ("second" <> space <> "paragraph")+                                   ]+                  ])++        , "Two footnotes" =:+            T.unlines [ "Footnotes[fn:1][fn:2]"+                      , ""+                      , "[fn:1] First note."+                      , ""+                      , "[fn:2] Second note."+                      ] =?>+            para (mconcat+                  [ "Footnotes"+                  , note $ para ("First" <> space <> "note.")+                  , note $ para ("Second" <> space <> "note.")+                  ])++        , "Emphasized text before footnote" =:+            T.unlines [ "/text/[fn:1]"+                      , ""+                      , "[fn:1] unicorn"+                      ] =?>+            para (mconcat+                 [ emph "text"+                 , note . para $ "unicorn"+                 ])++        , "Footnote that starts with emphasized text" =:+            T.unlines [ "text[fn:1]"+                      , ""+                      , "[fn:1] /emphasized/"+                      ] =?>+            para (mconcat+                 [ "text"+                 , note . para $ emph "emphasized"+                 ])++        , "Footnote followed by header" =:+            T.unlines [ "Another note[fn:yay]"+                      , ""+                      , "[fn:yay] This is great!"+                      , ""+                      , "** Headline"+                      ] =?>+            mconcat+            [ para (mconcat+                    [ "Another", space, "note"+                    , note $ para ("This" <> space <> "is" <> space <> "great!")+                    ])+            , headerWith ("headline", [], []) 2 "Headline"+            ]++        , "Footnote followed by two blank lines" =:+            T.unlines [ "footnote[fn:blanklines]"+                      , ""+                      , "[fn:blanklines] followed by blank lines"+                      , ""+                      , ""+                      , "next"+                      ] =?>+            mconcat+            [ para ("footnote" <> note (para "followed by blank lines"))+            , para "next"+            ]+        ]+      ]++  , testGroup "Lists" $+      [ "Simple Bullet Lists" =:+          ("- Item1\n" <>+           "- Item2\n") =?>+          bulletList [ plain "Item1"+                     , plain "Item2"+                     ]++      , "Indented Bullet Lists" =:+          ("   - Item1\n" <>+           "   - Item2\n") =?>+          bulletList [ plain "Item1"+                     , plain "Item2"+                     ]++      , "Unindented *" =:+          ("- Item1\n" <>+           "* Item2\n") =?>+          bulletList [ plain "Item1"+                     ] <>+          headerWith ("item2", [], []) 1 "Item2"++      , "Multi-line Bullet Lists" =:+          ("- *Fat\n" <>+           "  Tony*\n" <>+           "- /Sideshow\n" <>+           " Bob/") =?>+          bulletList [ plain $ strong ("Fat" <> softbreak <> "Tony")+                     , plain $ emph ("Sideshow" <> softbreak <> "Bob")+                     ]++      , "Nested Bullet Lists" =:+          ("- Discovery\n" <>+           "  + One More Time\n" <>+           "  + Harder, Better, Faster, Stronger\n" <>+           "- Homework\n" <>+           "  + Around the World\n"<>+           "- Human After All\n" <>+           "  + Technologic\n" <>+           "  + Robot Rock\n") =?>+          bulletList [ mconcat+                       [ plain "Discovery"+                       , bulletList [ plain ("One" <> space <>+                                             "More" <> space <>+                                             "Time")+                                    , plain ("Harder," <> space <>+                                             "Better," <> space <>+                                             "Faster," <> space <>+                                             "Stronger")+                                    ]+                       ]+                     , mconcat+                       [ plain "Homework"+                       , bulletList [ plain ("Around" <> space <>+                                             "the" <> space <>+                                             "World")+                                    ]+                       ]+                     , mconcat+                       [ plain ("Human" <> space <> "After" <> space <> "All")+                       , bulletList [ plain "Technologic"+                                    , plain ("Robot" <> space <> "Rock")+                                    ]+                       ]+                     ]++      , "Bullet List with Decreasing Indent" =:+           ("  - Discovery\n\+            \ - Human After All\n") =?>+           mconcat [ bulletList [ plain "Discovery" ]+                   , bulletList [ plain ("Human" <> space <> "After" <> space <> "All")]+                   ]++      , "Header follows Bullet List" =:+          ("  - Discovery\n\+           \  - Human After All\n\+           \* Homework") =?>+          mconcat [ bulletList [ plain "Discovery"+                               , plain ("Human" <> space <> "After" <> space <> "All")+                               ]+                  , headerWith ("homework", [], []) 1 "Homework"+                  ]++      , "Bullet List Unindented with trailing Header" =:+          ("- Discovery\n\+           \- Homework\n\+           \* NotValidListItem") =?>+          mconcat [ bulletList [ plain "Discovery"+                               , plain "Homework"+                               ]+                  , headerWith ("notvalidlistitem", [], []) 1 "NotValidListItem"+                  ]++      , "Simple Ordered List" =:+          ("1. Item1\n" <>+           "2. Item2\n") =?>+          let listStyle = (1, DefaultStyle, DefaultDelim)+              listStructure = [ plain "Item1"+                              , plain "Item2"+                              ]+          in orderedListWith listStyle listStructure++      , "Simple Ordered List with Parens" =:+          ("1) Item1\n" <>+           "2) Item2\n") =?>+          let listStyle = (1, DefaultStyle, DefaultDelim)+              listStructure = [ plain "Item1"+                              , plain "Item2"+                              ]+          in orderedListWith listStyle listStructure++      , "Indented Ordered List" =:+          (" 1. Item1\n" <>+           " 2. Item2\n") =?>+          let listStyle = (1, DefaultStyle, DefaultDelim)+              listStructure = [ plain "Item1"+                              , plain "Item2"+                              ]+          in orderedListWith listStyle listStructure++      , "Nested Ordered Lists" =:+          ("1. One\n" <>+           "   1. One-One\n" <>+           "   2. One-Two\n" <>+           "2. Two\n" <>+           "   1. Two-One\n"<>+           "   2. Two-Two\n") =?>+          let listStyle = (1, DefaultStyle, DefaultDelim)+              listStructure = [ mconcat+                                [ plain "One"+                                , orderedList [ plain "One-One"+                                              , plain "One-Two"+                                              ]+                                ]+                              , mconcat+                                [ plain "Two"+                                , orderedList [ plain "Two-One"+                                              , plain "Two-Two"+                                              ]+                                ]+                              ]+          in orderedListWith listStyle listStructure++      , "Ordered List in Bullet List" =:+          ("- Emacs\n" <>+           "  1. Org\n") =?>+          bulletList [ (plain "Emacs") <>+                       (orderedList [ plain "Org"])+                     ]++      , "Bullet List in Ordered List" =:+          ("1. GNU\n" <>+           "   - Freedom\n") =?>+          orderedList [ (plain "GNU") <> bulletList [ (plain "Freedom") ] ]++      , "Definition List" =:+          T.unlines [ "- PLL :: phase-locked loop"+                    , "- TTL ::"+                    , "  transistor-transistor logic"+                    , "- PSK :: phase-shift keying"+                    , ""+                    , "  a digital modulation scheme"+                    ] =?>+          definitionList [ ("PLL", [ plain $ "phase-locked" <> space <> "loop" ])+                         , ("TTL", [ plain $ "transistor-transistor" <> space <>+                                               "logic" ])+                         , ("PSK", [ mconcat+                                     [ para $ "phase-shift" <> space <> "keying"+                                     , para $ spcSep [ "a", "digital"+                                                     , "modulation", "scheme" ]+                                     ]+                                   ])+                         ]+      , "Definition list with multi-word term" =:+        " - Elijah Wood :: He plays Frodo" =?>+         definitionList [ ("Elijah" <> space <> "Wood", [plain $ "He" <> space <> "plays" <> space <> "Frodo"])]+      , "Compact definition list" =:+           T.unlines [ "- ATP :: adenosine 5' triphosphate"+                     , "- DNA :: deoxyribonucleic acid"+                     , "- PCR :: polymerase chain reaction"+                     , ""+                     ] =?>+          definitionList+          [ ("ATP", [ plain $ spcSep [ "adenosine", "5'", "triphosphate" ] ])+          , ("DNA", [ plain $ spcSep [ "deoxyribonucleic", "acid" ] ])+          , ("PCR", [ plain $ spcSep [ "polymerase", "chain", "reaction" ] ])+          ]++      , "Definition List With Trailing Header" =:+          "- definition :: list\n\+          \- cool :: defs\n\+          \* header" =?>+          mconcat [ definitionList [ ("definition", [plain "list"])+                                   , ("cool", [plain "defs"])+                                   ]+                  , headerWith ("header", [], []) 1 "header"+                  ]++      , "Definition lists double-colon markers must be surrounded by whitespace" =:+          "- std::cout" =?>+          bulletList [ plain "std::cout" ]++      , "Loose bullet list" =:+         T.unlines [ "- apple"+                   , ""+                   , "- orange"+                   , ""+                   , "- peach"+                   ] =?>+          bulletList [ para "apple"+                     , para "orange"+                     , para "peach"+                     ]++      , "Recognize preceding paragraphs in non-list contexts" =:+          T.unlines [ "CLOSED: [2015-10-19 Mon 15:03]"+                    , "- Note taken on [2015-10-19 Mon 13:24]"+                    ] =?>+          mconcat [ para "CLOSED: [2015-10-19 Mon 15:03]"+                  , bulletList [ plain "Note taken on [2015-10-19 Mon 13:24]" ]+                  ]+      ]++  , testGroup "Tables"+      [ "Single cell table" =:+          "|Test|" =?>+          simpleTable' 1 mempty [[plain "Test"]]++      , "Multi cell table" =:+          "| One | Two |" =?>+           simpleTable' 2 mempty [ [ plain "One", plain "Two" ] ]++      , "Multi line table" =:+          T.unlines [ "| One   |"+                    , "| Two   |"+                    , "| Three |"+                    ] =?>+           simpleTable' 1 mempty+                        [ [ plain "One" ]+                        , [ plain "Two" ]+                        , [ plain "Three" ]+                        ]++      , "Empty table" =:+          "||" =?>+          simpleTable' 1 mempty [[mempty]]++      , "Glider Table" =:+          T.unlines [ "| 1 | 0 | 0 |"+                    , "| 0 | 1 | 1 |"+                    , "| 1 | 1 | 0 |"+                    ] =?>+          simpleTable' 3 mempty+                       [ [ plain "1", plain "0", plain "0" ]+                       , [ plain "0", plain "1", plain "1" ]+                       , [ plain "1", plain "1", plain "0" ]+                       ]++      , "Table between Paragraphs" =:+          T.unlines [ "Before"+                    , "| One | Two |"+                    , "After"+                    ] =?>+          mconcat [ para "Before"+                  , simpleTable' 2 mempty [ [ plain "One", plain "Two" ] ]+                  , para "After"+                  ]++      , "Table with Header" =:+          T.unlines [ "| Species      | Status       |"+                    , "|--------------+--------------|"+                    , "| cervisiae    | domesticated |"+                    , "| paradoxus    | wild         |"+                    ] =?>+          simpleTable [ plain "Species", plain "Status" ]+                      [ [ plain "cervisiae", plain "domesticated" ]+                      , [ plain "paradoxus", plain "wild" ]+                      ]++      , "Table with final hline" =:+          T.unlines [ "| cervisiae    | domesticated |"+                    , "| paradoxus    | wild         |"+                    , "|--------------+--------------|"+                    ] =?>+          simpleTable' 2 mempty+                [ [ plain "cervisiae", plain "domesticated" ]+                 , [ plain "paradoxus", plain "wild" ]+                ]++      , "Table in a box" =:+          T.unlines [ "|---------|---------|"+                    , "| static  | Haskell |"+                    , "| dynamic | Lisp    |"+                    , "|---------+---------|"+                    ] =?>+          simpleTable' 2 mempty+                [ [ plain "static", plain "Haskell" ]+                , [ plain "dynamic", plain "Lisp" ]+                ]++      , "Table with empty cells" =:+          "|||c|" =?>+          simpleTable' 3 mempty [[mempty, mempty, plain "c"]]++      , "Table with empty rows" =:+          T.unlines [ "| first  |"+                    , "|        |"+                    , "| third  |"+                    ] =?>+          simpleTable' 1 mempty [[plain "first"], [mempty], [plain "third"]]++      , "Table with alignment row" =:+          T.unlines [ "| Numbers | Text | More |"+                    , "| <c>     | <r>  |      |"+                    , "| 1       | One  | foo  |"+                    , "| 2       | Two  | bar  |"+                    ] =?>+          table "" (zip [AlignCenter, AlignRight, AlignDefault] [0, 0, 0])+                []+                [ [ plain "Numbers", plain "Text", plain "More" ]+                , [ plain "1"      , plain "One" , plain "foo"  ]+                , [ plain "2"      , plain "Two" , plain "bar"  ]+                ]++      , "Pipe within text doesn't start a table" =:+          "Ceci n'est pas une | pipe " =?>+          para (spcSep [ "Ceci", "n'est", "pas", "une", "|", "pipe" ])++      , "Missing pipe at end of row" =:+          "|incomplete-but-valid" =?>+          simpleTable' 1 mempty [ [ plain "incomplete-but-valid" ] ]++      , "Table with differing row lengths" =:+          T.unlines [ "| Numbers | Text "+                    , "|-"+                    , "| <c>     | <r>  |"+                    , "| 1       | One  | foo  |"+                    , "| 2"+                    ] =?>+          table "" (zip [AlignCenter, AlignRight] [0, 0])+                [ plain "Numbers", plain "Text" ]+                [ [ plain "1" , plain "One" , plain "foo" ]+                , [ plain "2" ]+                ]++      , "Table with caption" =:+          T.unlines [ "#+CAPTION: Hitchhiker's Multiplication Table"+                    , "| x |  6 |"+                    , "| 9 | 42 |"+                    ] =?>+          table "Hitchhiker's Multiplication Table"+                [(AlignDefault, 0), (AlignDefault, 0)]+                []+                [ [ plain "x", plain "6" ]+                , [ plain "9", plain "42" ]+                ]+      ]++    , testGroup "Blocks and fragments"+      [ "Source block" =:+           T.unlines [ "  #+BEGIN_SRC haskell"+                     , "  main = putStrLn greeting"+                     , "    where greeting = \"moin\""+                     , "  #+END_SRC" ] =?>+           let attr' = ("", ["haskell"], [])+               code' = "main = putStrLn greeting\n" <>+                       "  where greeting = \"moin\"\n"+           in codeBlockWith attr' code'++      , "Source block with indented code" =:+           T.unlines [ "  #+BEGIN_SRC haskell"+                     , "    main = putStrLn greeting"+                     , "      where greeting = \"moin\""+                     , "  #+END_SRC" ] =?>+           let attr' = ("", ["haskell"], [])+               code' = "main = putStrLn greeting\n" <>+                       "  where greeting = \"moin\"\n"+           in codeBlockWith attr' code'++      , "Source block with tab-indented code" =:+           T.unlines [ "\t#+BEGIN_SRC haskell"+                     , "\tmain = putStrLn greeting"+                     , "\t  where greeting = \"moin\""+                     , "\t#+END_SRC" ] =?>+           let attr' = ("", ["haskell"], [])+               code' = "main = putStrLn greeting\n" <>+                       "  where greeting = \"moin\"\n"+           in codeBlockWith attr' code'++      , "Empty source block" =:+           T.unlines [ "  #+BEGIN_SRC haskell"+                     , "  #+END_SRC" ] =?>+           let attr' = ("", ["haskell"], [])+               code' = ""+           in codeBlockWith attr' code'++      , "Source block between paragraphs" =:+           T.unlines [ "Low German greeting"+                     , "  #+BEGIN_SRC haskell"+                     , "  main = putStrLn greeting"+                     , "    where greeting = \"Moin!\""+                     , "  #+END_SRC" ] =?>+           let attr' = ("", ["haskell"], [])+               code' = "main = putStrLn greeting\n" <>+                        "  where greeting = \"Moin!\"\n"+           in mconcat [ para $ spcSep [ "Low", "German", "greeting"  ]+                      , codeBlockWith attr' code'+                      ]+      , "Source block with babel arguments" =:+           T.unlines [ "#+BEGIN_SRC emacs-lisp :exports both"+                     , "(progn (message \"Hello, World!\")"+                     , "       (+ 23 42))"+                     , "#+END_SRC" ] =?>+           let classes = [ "commonlisp" ] -- as kate doesn't know emacs-lisp syntax+               params = [ ("org-language", "emacs-lisp")+                        , ("exports", "both")+                        ]+               code' = unlines [ "(progn (message \"Hello, World!\")"+                               , "       (+ 23 42))" ]+           in codeBlockWith ("", classes, params) code'++      , "Source block with results and :exports both" =:+           T.unlines [ "#+BEGIN_SRC emacs-lisp :exports both"+                     , "(progn (message \"Hello, World!\")"+                     , "       (+ 23 42))"+                     , "#+END_SRC"+                     , ""+                     , "#+RESULTS:"+                     , ": 65"] =?>+           let classes = [ "commonlisp" ]+               params = [ ("org-language", "emacs-lisp")+                        , ("exports", "both")+                        ]+               code' = unlines [ "(progn (message \"Hello, World!\")"+                               , "       (+ 23 42))" ]+               results' = "65\n"+           in codeBlockWith ("", classes, params) code'+              <>+              codeBlockWith ("", ["example"], []) results'++      , "Source block with results and :exports code" =:+           T.unlines [ "#+BEGIN_SRC emacs-lisp :exports code"+                     , "(progn (message \"Hello, World!\")"+                     , "       (+ 23 42))"+                     , "#+END_SRC"+                     , ""+                     , "#+RESULTS:"+                     , ": 65" ] =?>+           let classes = [ "commonlisp" ]+               params = [ ("org-language", "emacs-lisp")+                        , ("exports", "code")+                        ]+               code' = unlines [ "(progn (message \"Hello, World!\")"+                               , "       (+ 23 42))" ]+           in codeBlockWith ("", classes, params) code'++      , "Source block with results and :exports results" =:+           T.unlines [ "#+BEGIN_SRC emacs-lisp :exports results"+                     , "(progn (message \"Hello, World!\")"+                     , "       (+ 23 42))"+                     , "#+END_SRC"+                     , ""+                     , "#+RESULTS:"+                     , ": 65" ] =?>+           let results' = "65\n"+           in codeBlockWith ("", ["example"], []) results'++      , "Source block with results and :exports none" =:+           T.unlines [ "#+BEGIN_SRC emacs-lisp :exports none"+                     , "(progn (message \"Hello, World!\")"+                     , "       (+ 23 42))"+                     , "#+END_SRC"+                     , ""+                     , "#+RESULTS:"+                     , ": 65" ] =?>+           (mempty :: Blocks)++      , "Source block with toggling header arguments" =:+        T.unlines [ "#+BEGIN_SRC sh :noeval"+                  , "echo $HOME"+                  , "#+END_SRC"+                  ] =?>+        let classes = [ "bash" ]+            params = [ ("org-language", "sh"), ("noeval", "yes") ]+        in codeBlockWith ("", classes, params) "echo $HOME\n"++      , "Source block with line number switch" =:+        T.unlines [ "#+BEGIN_SRC sh -n 10"+                  , ":() { :|:& };:"+                  , "#+END_SRC"+                  ] =?>+        let classes = [ "bash", "numberLines" ]+            params = [ ("org-language", "sh"), ("startFrom", "10") ]+        in codeBlockWith ("", classes, params) ":() { :|:& };:\n"++      , "Source block with multi-word parameter values" =:+        T.unlines [ "#+BEGIN_SRC dot :cmdline -Kdot -Tpng "+                  , "digraph { id [label=\"ID\"] }"+                  , "#+END_SRC"+                  ] =?>+        let classes = [ "dot" ]+            params = [ ("cmdline", "-Kdot -Tpng") ]+        in codeBlockWith ("", classes, params) "digraph { id [label=\"ID\"] }\n"++      , "Example block" =:+           T.unlines [ "#+begin_example"+                     , "A chosen representation of"+                     , "a rule."+                     , "#+eND_exAMPle"+                     ] =?>+           codeBlockWith ("", ["example"], [])+                         "A chosen representation of\na rule.\n"++      , "HTML block" =:+           T.unlines [ "#+BEGIN_HTML"+                     , "<aside>HTML5 is pretty nice.</aside>"+                     , "#+END_HTML"+                     ] =?>+           rawBlock "html" "<aside>HTML5 is pretty nice.</aside>\n"++      , "Quote block" =:+           T.unlines [ "#+BEGIN_QUOTE"+                     , "/Niemand/ hat die Absicht, eine Mauer zu errichten!"+                     , "#+END_QUOTE"+                     ] =?>+           blockQuote (para (spcSep [ emph "Niemand", "hat", "die", "Absicht,"+                                    , "eine", "Mauer", "zu", "errichten!"+                                    ]))++      , "Verse block" =:+          T.unlines [ "The first lines of Goethe's /Faust/:"+                    , "#+begin_verse"+                    , "Habe nun, ach! Philosophie,"+                    , "Juristerei und Medizin,"+                    , "Und leider auch Theologie!"+                    , "Durchaus studiert, mit heißem Bemühn."+                    , "#+end_verse"+                    ] =?>+          mconcat+          [ para $ spcSep [ "The", "first", "lines", "of"+                          , "Goethe's", emph "Faust" <> ":"]+          , lineBlock+              [ "Habe nun, ach! Philosophie,"+              , "Juristerei und Medizin,"+              , "Und leider auch Theologie!"+              , "Durchaus studiert, mit heißem Bemühn."+              ]+          ]++      , "Verse block with blank lines" =:+          T.unlines [ "#+BEGIN_VERSE"+                    , "foo"+                    , ""+                    , "bar"+                    , "#+END_VERSE"+                    ] =?>+          lineBlock [ "foo", mempty, "bar" ]++      , "Verse block with varying indentation" =:+          T.unlines [ "#+BEGIN_VERSE"+                    , "  hello darkness"+                    , "my old friend"+                    , "#+END_VERSE"+                    ] =?>+          lineBlock [ "\160\160hello darkness", "my old friend" ]++      , "Raw block LaTeX" =:+          T.unlines [ "#+BEGIN_LaTeX"+                    , "The category $\\cat{Set}$ is adhesive."+                    , "#+END_LaTeX"+                    ] =?>+          rawBlock "latex" "The category $\\cat{Set}$ is adhesive.\n"++      , "Raw LaTeX line" =:+          "#+LATEX: \\let\\foo\\bar" =?>+          rawBlock "latex" "\\let\\foo\\bar"++      , "Raw Beamer line" =:+          "#+beamer: \\pause" =?>+          rawBlock "beamer" "\\pause"++      , "Raw HTML line" =:+          "#+HTML: <aside>not important</aside>" =?>+          rawBlock "html" "<aside>not important</aside>"++      , "Export block HTML" =:+          T.unlines [ "#+BEGIN_export html"+                    , "<samp>Hello, World!</samp>"+                    , "#+END_export"+                    ] =?>+          rawBlock "html" "<samp>Hello, World!</samp>\n"++      , "LaTeX fragment" =:+          T.unlines [ "\\begin{equation}"+                    , "X_i = \\begin{cases}"+                    , "      G_{\\alpha(i)} & \\text{if }\\alpha(i-1) = \\alpha(i)\\\\"+                    , "      C_{\\alpha(i)} & \\text{otherwise}"+                    , "      \\end{cases}"+                    , "\\end{equation}"+                    ] =?>+          rawBlock "latex"+                   (unlines [ "\\begin{equation}"+                            , "X_i = \\begin{cases}"+                            , "      G_{\\alpha(i)} & \\text{if }\\alpha(i-1) =" <>+                              " \\alpha(i)\\\\"+                            , "      C_{\\alpha(i)} & \\text{otherwise}"+                            , "      \\end{cases}"+                            , "\\end{equation}"+                            ])++      , "Code block with caption" =:+          T.unlines [ "#+CAPTION: Functor laws in Haskell"+                    , "#+NAME: functor-laws"+                    , "#+BEGIN_SRC haskell"+                    , "fmap id = id"+                    , "fmap (p . q) = (fmap p) . (fmap q)"+                    , "#+END_SRC"+                    ] =?>+          divWith+             nullAttr+             (mappend+              (plain $ spanWith ("", ["label"], [])+                                (spcSep [ "Functor", "laws", "in", "Haskell" ]))+              (codeBlockWith ("functor-laws", ["haskell"], [])+                             (unlines [ "fmap id = id"+                                      , "fmap (p . q) = (fmap p) . (fmap q)"+                                      ])))++      , "Convert blank lines in blocks to single newlines" =:+          T.unlines [ "#+begin_html"+                    , ""+                    , "<span>boring</span>"+                    , ""+                    , "#+end_html"+                    ] =?>+          rawBlock "html" "\n<span>boring</span>\n\n"++      , "Accept `ATTR_HTML` attributes for generic block" =:+          T.unlines [ "#+ATTR_HTML: :title hello, world :id test :class fun code"+                    , "#+BEGIN_TEST"+                    , "nonsense"+                    , "#+END_TEST"+                    ] =?>+          let attr = ("test", ["fun", "code", "TEST"], [("title", "hello, world")])+          in divWith attr (para "nonsense")++      , "Non-letter chars in source block parameters" =:+          T.unlines [ "#+BEGIN_SRC C :tangle xxxx.c :city Zürich"+                    , "code body"+                    , "#+END_SRC"+                    ] =?>+          let params  = [ ("org-language", "C")+                        , ("tangle", "xxxx.c")+                        , ("city", "Zürich")+                        ]+          in codeBlockWith ( "", ["c"], params) "code body\n"+      ]++    , testGroup "Smart punctuation"+      [ test orgSmart "quote before ellipses"+        ("'...hi'"+         =?> para (singleQuoted "…hi"))++      , test orgSmart "apostrophe before emph"+        ("D'oh! A l'/aide/!"+         =?> para ("D’oh! A l’" <> emph "aide" <> "!"))++      , test orgSmart "apostrophe in French"+        ("À l'arrivée de la guerre, le thème de l'«impossibilité du socialisme»"+         =?> para "À l’arrivée de la guerre, le thème de l’«impossibilité du socialisme»")++      , test orgSmart "Quotes cannot occur at the end of emphasized text"+        ("/say \"yes\"/" =?>+         para ("/say" <> space <> doubleQuoted "yes" <> "/"))++      , test orgSmart "Dashes are allowed at the borders of emphasis'"+        ("/foo---/" =?>+         para (emph "foo—"))++      , test orgSmart "Single quotes can be followed by emphasized text"+        ("Singles on the '/meat market/'" =?>+         para ("Singles on the " <> (singleQuoted $ emph "meat market")))++      , test orgSmart "Double quotes can be followed by emphasized text"+        ("Double income, no kids: \"/DINK/\"" =?>+         para ("Double income, no kids: " <> (doubleQuoted $ emph "DINK")))+      ]+  ]
+ test/Tests/Readers/RST.hs view
@@ -0,0 +1,190 @@+{-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE ScopedTypeVariables #-}+module Tests.Readers.RST (tests) where++import Data.Text (Text)+import qualified Data.Text as T+import Test.Tasty+import Tests.Helpers+import Text.Pandoc+import Text.Pandoc.Arbitrary ()+import Text.Pandoc.Builder++rst :: Text -> Pandoc+rst = purely $ readRST def{ readerStandalone = True }++infix 4 =:+(=:) :: ToString c+     => String -> (Text, c) -> TestTree+(=:) = test rst++tests :: [TestTree]+tests = [ "line block with blank line" =:+          "| a\n|\n|  b" =?> lineBlock [ "a", mempty, "\160b" ]+        , testGroup "field list"+          [ "general" =: T.unlines+             [ "para"+             , ""+             , ":Hostname: media08"+             , ":IP address: 10.0.0.19"+             , ":Size: 3ru"+             , ":Version: 1"+             , ":Indentation: Since the field marker may be quite long, the second"+             , "   and subsequent lines of the field body do not have to line up"+             , "   with the first line, but they must be indented relative to the"+             , "   field name marker, and they must line up with each other."+             , ":Parameter i: integer"+             , ":Final: item"+             , "  on two lines" ]+             =?> ( doc+                 $ para "para" <>+                   definitionList [ (str "Hostname", [para "media08"])+                                  , (text "IP address", [para "10.0.0.19"])+                                  , (str "Size", [para "3ru"])+                                  , (str "Version", [para "1"])+                                  , (str "Indentation", [para "Since the field marker may be quite long, the second\nand subsequent lines of the field body do not have to line up\nwith the first line, but they must be indented relative to the\nfield name marker, and they must line up with each other."])+                                  , (text "Parameter i", [para "integer"])+                                  , (str "Final", [para "item\non two lines"])+                                  ])+          , "metadata" =: T.unlines+             [ "====="+             , "Title"+             , "====="+             , "--------"+             , "Subtitle"+             , "--------"+             , ""+             , ":Version: 1"+             ]+             =?> ( setMeta "version" (para "1")+                 $ setMeta "title" ("Title" :: Inlines)+                 $ setMeta "subtitle" ("Subtitle" :: Inlines)+                 $ doc mempty )+          , "with inline markup" =: T.unlines+             [ ":*Date*: today"+             , ""+             , ".."+             , ""+             , ":*one*: emphasis"+             , ":two_: reference"+             , ":`three`_: another one"+             , ":``four``: literal"+             , ""+             , ".. _two: http://example.com"+             , ".. _three: http://example.org"+             ]+             =?> ( setMeta "date" (str "today")+                 $ doc+                 $ definitionList [ (emph "one", [para "emphasis"])+                                  , (link "http://example.com" "" "two", [para "reference"])+                                  , (link "http://example.org" "" "three", [para "another one"])+                                  , (code "four", [para "literal"])+                                  ])+          ]+        , "URLs with following punctuation" =:+          ("http://google.com, http://yahoo.com; http://foo.bar.baz.\n" <>+           "http://foo.bar/baz_(bam) (http://foo.bar)") =?>+          para (link "http://google.com" "" "http://google.com" <> ", " <>+                link "http://yahoo.com" "" "http://yahoo.com" <> "; " <>+                link "http://foo.bar.baz" "" "http://foo.bar.baz" <> ". " <>+                softbreak <>+                link "http://foo.bar/baz_(bam)" "" "http://foo.bar/baz_(bam)"+                <> " (" <> link "http://foo.bar" "" "http://foo.bar" <> ")")+        , "Reference names with special characters" =:+                   ("A-1-B_2_C:3:D+4+E.5.F_\n\n" <>+                   ".. _A-1-B_2_C:3:D+4+E.5.F: https://example.com\n") =?>+                   para (link "https://example.com" "" "A-1-B_2_C:3:D+4+E.5.F")+        , "Code directive with class and number-lines" =: T.unlines+            [ ".. code::python"+            , "   :number-lines: 34"+            , "   :class: class1 class2 class3"+            , ""+            , "  def func(x):"+            , "    return y"+            ]  =?>+              ( doc $ codeBlockWith+                  ( ""+                  , ["sourceCode", "python", "numberLines", "class1", "class2", "class3"]+                  , [ ("startFrom", "34") ]+                  )+                  "def func(x):\n  return y"+              )+        , "Code directive with number-lines, no line specified" =: T.unlines+            [ ".. code::python"+            , "   :number-lines: "+            , ""+            , "  def func(x):"+            , "    return y"+            ]  =?>+              ( doc $ codeBlockWith+                  ( ""+                  , ["sourceCode", "python", "numberLines"]+                  , [ ("startFrom", "") ]+                  )+                  "def func(x):\n  return y"+              )+        , testGroup "literal / line / code blocks"+          [ "indented literal block" =: T.unlines+            [ "::"+            , ""+            , "  block quotes"+            , ""+            , "  can go on for many lines"+            , "but must stop here"]+            =?> (doc $+                 codeBlock "block quotes\n\ncan go on for many lines" <>+                 para "but must stop here")+          , "line block with 3 lines" =: "| a\n| b\n| c"+            =?> lineBlock ["a", "b", "c"]+          , "line blocks with blank lines" =: T.unlines+            [ "|"+            , ""+            , "|"+            , "| a"+            , "| b"+            , "|"+            , ""+            , "|"+            ] =?>+            lineBlock [""] <>+            lineBlock ["", "a", "b", ""] <>+            lineBlock [""]+          , "quoted literal block using >" =: "::\n\n> quoted\n> block\n\nOrdinary paragraph"+            =?> codeBlock "> quoted\n> block" <> para "Ordinary paragraph"+          , "quoted literal block using | (not  a line block)" =: "::\n\n| quoted\n| block\n\nOrdinary paragraph"+            =?> codeBlock "| quoted\n| block" <> para "Ordinary paragraph"+          , "class directive with single paragraph" =: ".. class:: special\n\nThis is a \"special\" paragraph."+            =?> divWith ("", ["special"], []) (para "This is a \"special\" paragraph.")+          , "class directive with two paragraphs" =: ".. class:: exceptional remarkable\n\n    First paragraph.\n\n    Second paragraph."+            =?> divWith ("", ["exceptional", "remarkable"], []) (para "First paragraph." <> para "Second paragraph.")+          , "class directive around literal block" =: ".. class:: classy\n\n::\n\n    a\n    b"+            =?> divWith ("", ["classy"], []) (codeBlock "a\nb")]+        , testGroup "interpreted text roles"+          [ "literal role prefix" =: ":literal:`a`" =?> para (code "a")+          , "literal role postfix" =: "`a`:literal:" =?> para (code "a")+          , "literal text" =: "``text``" =?> para (code "text")+          , "code role" =: ":code:`a`" =?> para (codeWith ("", ["sourceCode"], []) "a")+          , "inherited code role" =: ".. role:: codeLike(code)\n\n:codeLike:`a`"+            =?> para (codeWith ("", ["codeLike", "sourceCode"], []) "a")+          , "custom code role with language field"+            =: ".. role:: lhs(code)\n    :language: haskell\n\n:lhs:`a`"+            =?> para (codeWith ("", ["lhs", "haskell","sourceCode"], []) "a")+          , "custom role with unspecified parent role"+            =: ".. role:: classy\n\n:classy:`text`"+            =?> para (spanWith ("", ["classy"], []) "text")+          , "role with recursive inheritance"+            =: ".. role:: haskell(code)\n.. role:: lhs(haskell)\n\n:lhs:`text`"+            =?> para (codeWith ("", ["lhs", "haskell", "sourceCode"], []) "text")+          , "unknown role" =: ":unknown:`text`" =?>+              para (spanWith ("",[],[("role","unknown")]) (str "text"))+          ]+        , testGroup "footnotes"+          [ "remove space before note" =: T.unlines+            [ "foo [1]_"+            , ""+            , ".. [1]"+            , "   bar"+            ] =?>+            (para $ "foo" <> (note $ para "bar"))+          ]+        ]
+ test/Tests/Readers/Txt2Tags.hs view
@@ -0,0 +1,434 @@+{-# LANGUAGE OverloadedStrings #-}+module Tests.Readers.Txt2Tags (tests) where++import Data.List (intersperse)+import Data.Text (Text)+import qualified Data.Text as T+import Test.Tasty+import Tests.Helpers+import Text.Pandoc+import Text.Pandoc.Arbitrary ()+import Text.Pandoc.Builder+import Text.Pandoc.Shared (underlineSpan)++t2t :: Text -> Pandoc+-- t2t = handleError . readTxt2Tags (T2TMeta "date" "mtime" "in" "out") def+t2t = purely $ \s -> do+  setInputFiles ["in"]+  setOutputFile (Just "out")+  readTxt2Tags def s++infix 4 =:+(=:) :: ToString c+     => String -> (Text, c) -> TestTree+(=:) = test t2t++spcSep :: [Inlines] -> Inlines+spcSep = mconcat . intersperse space++simpleTable' :: Int+             -> [Blocks]+             -> [[Blocks]]+             -> Blocks+simpleTable' n = table "" (take n $ repeat (AlignCenter, 0.0))++tests :: [TestTree]+tests =+  [ testGroup "Inlines" $+      [ "Plain String" =:+          "Hello, World" =?>+          para (spcSep [ "Hello,", "World" ])++      , "Emphasis" =:+          "//Planet Punk//" =?>+          para (emph . spcSep $ ["Planet", "Punk"])++      , "Strong" =:+          "**Cider**" =?>+          para (strong "Cider")++      , "Strong Emphasis" =:+          "//**strength**//" =?>+          para (emph . strong $ "strength")++      , "Strikeout" =:+          "--Kill Bill--" =?>+          para (strikeout . spcSep $ [ "Kill", "Bill" ])++      , "Verbatim" =:+          "``Robot.rock()``" =?>+          para (code "Robot.rock()")++      , "Symbol" =:+          "A * symbol" =?>+          para (str "A" <> space <> str "*" <> space <> "symbol")++      , "No empty markup" =:+          "//// **** ____ ---- ```` \"\"\"\" ''''" =?>+          para (spcSep [ "////", "****", "____", "----", "````", "\"\"\"\"", "''''" ])++      , "Inline markup is greedy" =:+          "***** ///// _____ ----- ````` \"\"\"\"\" '''''" =?>+          para (spcSep [strong "*", emph "/", underlineSpan "_"+                       , strikeout "-", code "`", text "\""+                       , rawInline "html" "'"])+      , "Markup must be greedy" =:+          "**********    //////////    __________    ----------    ``````````   \"\"\"\"\"\"\"\"\"\"   ''''''''''" =?>+                      para (spcSep [strong "******", emph "//////", underlineSpan "______"+                       , strikeout "------", code "``````", text "\"\"\"\"\"\""+                       , rawInline "html" "''''''"])+      , "Inlines must be glued" =:+          "** a** **a ** ** a **" =?>+          para (text "** a** **a ** ** a **")++      , "Macros: Date" =:+          "%%date" =?>+            para "1970-01-01"+      , "Macros: Mod Time" =:+          "%%mtime" =?>+            para (str "")+      , "Macros: Infile" =:+          "%%infile" =?>+            para "in"+      , "Macros: Outfile" =:+          "%%outfile" =?>+            para "out"+      , "Autolink" =:+          "http://www.google.com" =?>+            para (link "http://www.google.com" "" (str "http://www.google.com"))+      , "Image" =:+          "[image.jpg]" =?>+            para (image "image.jpg" "" mempty)++      , "Link" =:+          "[title http://google.com]" =?>+            para (link "http://google.com" "" (str "title"))++      , "Image link" =:+          "[[image.jpg] abc]" =?>+            para (link "abc" "" (image "image.jpg" "" mempty))+      , "Invalid link: No trailing space" =:+          "[title invalid ]" =?>+            para (text "[title invalid ]")+++      ]++  , testGroup "Basic Blocks" $+      ["Paragraph, lines grouped together" =:+          "A paragraph\n A blank line ends the \n current paragraph\n"+            =?> para "A paragraph\n A blank line ends the\n current paragraph"+      , "Paragraph, ignore leading and trailing spaces" =:+          "   Leading and trailing spaces are ignored.   \n" =?>+            para "Leading and trailing spaces are ignored."+      , "Comment line in paragraph" =:+          "A comment line can be placed inside a paragraph.\n% this comment will be ignored \nIt will not affect it.\n"+          =?> para "A comment line can be placed inside a paragraph.\nIt will not affect it."+      , "Paragraph" =:+          "Paragraph\n" =?>+          para "Paragraph"++      , "First Level Header" =:+          "+ Headline +\n" =?>+          header 1 "Headline"++      , "Third Level Header" =:+          "=== Third Level Headline ===\n" =?>+          header 3 ("Third" <> space <>+                    "Level" <> space <>+                    "Headline")++      , "Header with label" =:+          "= header =[label]" =?>+            headerWith ("label", [], []) 1 ("header")++      , "Invalid header, mismatched delimiters" =:+          "== header =" =?>+            para (text "== header =")++      , "Invalid header, spaces in label" =:+          "== header ==[ haha ]" =?>+            para (text "== header ==[ haha ]")++      , "Invalid header, invalid label character" =:+          "== header ==[lab/el]" =?>+            para (text "== header ==[lab/el]")+      , "Headers not preceded by a blank line" =:+          T.unlines [ "++ eat dinner ++"+                  , "Spaghetti and meatballs tonight."+                  , "== walk dog =="+                  ] =?>+          mconcat [ header 2 ("eat" <> space <> "dinner")+                  , para $ spcSep [ "Spaghetti", "and", "meatballs", "tonight." ]+                  , header 2 ("walk" <> space <> "dog")+                  ]++      , "Paragraph starting with an equals" =:+          "=five" =?>+          para "=five"++      , "Paragraph containing asterisk at beginning of line" =:+          T.unlines [ "lucky"+                  , "*star"+                  ] =?>+          para ("lucky" <> softbreak <> "*star")++      , "Horizontal Rule" =:+          T.unlines [ "before"+                  , T.replicate 20 "-"+                  , T.replicate 20 "="+                  , T.replicate 20 "_"+                  , "after"+                  ] =?>+          mconcat [ para "before"+                  , horizontalRule+                  , horizontalRule+                  , horizontalRule+                  , para "after"+                  ]++      , "Comment Block" =:+          T.unlines [ "%%%"+                  , "stuff"+                  , "bla"+                  , "%%%"] =?>+          (mempty::Blocks)+++    ]++  , testGroup "Lists" $+      [ "Simple Bullet Lists" =:+          ("- Item1\n" <>+           "- Item2\n") =?>+          bulletList [ plain "Item1"+                     , plain "Item2"+                     ]++      , "Indented Bullet Lists" =:+          ("   - Item1\n" <>+           "   - Item2\n") =?>+          bulletList [ plain "Item1"+                     , plain "Item2"+                     ]++++      , "Nested Bullet Lists" =:+          ("- Discovery\n" <>+           "  + One More Time\n" <>+           "  + Harder, Better, Faster, Stronger\n" <>+           "- Homework\n" <>+           "  + Around the World\n"<>+           "- Human After All\n" <>+           "  + Technologic\n" <>+           "  + Robot Rock\n") =?>+          bulletList [ mconcat+                       [ plain "Discovery"+                       , orderedList [ plain ("One" <> space <>+                                             "More" <> space <>+                                             "Time")+                                    , plain ("Harder," <> space <>+                                             "Better," <> space <>+                                             "Faster," <> space <>+                                             "Stronger")+                                    ]+                       ]+                     , mconcat+                       [ plain "Homework"+                       , orderedList [ plain ("Around" <> space <>+                                             "the" <> space <>+                                             "World")+                                    ]+                       ]+                     , mconcat+                       [ plain ("Human" <> space <> "After" <> space <> "All")+                       , orderedList [ plain "Technologic"+                                    , plain ("Robot" <> space <> "Rock")+                                    ]+                       ]+                     ]++      , "Simple Ordered List" =:+          ("+ Item1\n" <>+           "+ Item2\n") =?>+          let listStyle = (1, DefaultStyle, DefaultDelim)+              listStructure = [ plain "Item1"+                              , plain "Item2"+                              ]+          in orderedListWith listStyle listStructure+++      , "Indented Ordered List" =:+          (" + Item1\n" <>+           " + Item2\n") =?>+          let listStyle = (1, DefaultStyle, DefaultDelim)+              listStructure = [ plain "Item1"+                              , plain "Item2"+                              ]+          in orderedListWith listStyle listStructure++      , "Nested Ordered Lists" =:+          ("+ One\n" <>+           "   + One-One\n" <>+           "   + One-Two\n" <>+           "+ Two\n" <>+           "   + Two-One\n"<>+           "   + Two-Two\n") =?>+          let listStyle = (1, DefaultStyle, DefaultDelim)+              listStructure = [ mconcat+                                [ plain "One"+                                , orderedList [ plain "One-One"+                                              , plain "One-Two"+                                              ]+                                ]+                              , mconcat+                                [ plain "Two"+                                , orderedList [ plain "Two-One"+                                              , plain "Two-Two"+                                              ]+                                ]+                              ]+          in orderedListWith listStyle listStructure++      , "Ordered List in Bullet List" =:+          ("- Emacs\n" <>+           "  + Org\n") =?>+          bulletList [ (plain "Emacs") <>+                       (orderedList [ plain "Org"])+                     ]++      , "Bullet List in Ordered List" =:+          ("+ GNU\n" <>+           "   - Freedom\n") =?>+          orderedList [ (plain "GNU") <> bulletList [ (plain "Freedom") ] ]++      , "Definition List" =:+          T.unlines [ ": PLL"+                  , "  phase-locked loop"+                  , ": TTL"+                  , "  transistor-transistor logic"+                  , ": PSK"+                  , "  a digital"+                  ] =?>+          definitionList [ ("PLL", [ plain $ "phase-locked" <> space <> "loop" ])+                         , ("TTL", [ plain $ "transistor-transistor" <> space <> "logic" ])+                         , ("PSK", [ plain $ "a" <> space <> "digital" ])+                         ]+++      , "Loose bullet list" =:+          T.unlines [ "- apple"+                  , ""+                  , "- orange"+                  , ""+                  , "- peach"+                  ] =?>+          bulletList [ para "apple"+                     , para "orange"+                     , para "peach"+                     ]+      ]++  , testGroup "Tables"+      [ "Single cell table" =:+          "| Test " =?>+          simpleTable' 1 mempty [[plain "Test"]]++      , "Multi cell table" =:+          "| One | Two |" =?>+           simpleTable' 2 mempty [ [ plain "One", plain "Two" ] ]++      , "Multi line table" =:+          T.unlines [ "| One |"+                  , "| Two |"+                  , "| Three |"+                  ] =?>+           simpleTable' 1 mempty+                        [ [ plain "One" ]+                        , [ plain "Two" ]+                        , [ plain "Three" ]+                        ]++      , "Empty table" =:+          "| |" =?>+          simpleTable' 1 mempty [[mempty]]++      , "Glider Table" =:+          T.unlines [ "| 1 | 0 | 0 |"+                  , "| 0 | 1 | 1 |"+                  , "| 1 | 1 | 0 |"+                  ] =?>+          simpleTable' 3 mempty+                       [ [ plain "1", plain "0", plain "0" ]+                       , [ plain "0", plain "1", plain "1" ]+                       , [ plain "1", plain "1", plain "0" ]+                       ]+++      , "Table with Header" =:+          T.unlines [ "|| Species     | Status       |"+                  , "| cervisiae    | domesticated |"+                  , "| paradoxus | wild         |"+                  ] =?>+          simpleTable [ plain "Species", plain "Status" ]+                      [ [ plain "cervisiae", plain "domesticated" ]+                      , [ plain "paradoxus", plain "wild" ]+                      ]++      , "Table alignment determined by spacing" =:+          T.unlines [ "| Numbers |     Text | More    |"+                  , "| 1 |    One  |    foo  |"+                  , "| 2 |    Two  | bar  |"+                  ] =?>+          table "" (zip [AlignCenter, AlignRight, AlignDefault] [0, 0, 0])+                []+                [ [ plain "Numbers", plain "Text", plain "More" ]+                , [ plain "1"      , plain "One" , plain "foo"  ]+                , [ plain "2"      , plain "Two" , plain "bar"  ]+                ]++      , "Pipe within text doesn't start a table" =:+          "Ceci n'est pas une | pipe " =?>+          para (spcSep [ "Ceci", "n'est", "pas", "une", "|", "pipe" ])+++      , "Table with differing row lengths" =:+          T.unlines [ "|| Numbers | Text "+                  , "| 1 | One  | foo  |"+                  , "| 2 "+                  ] =?>+          table "" (zip [AlignCenter, AlignLeft, AlignLeft] [0, 0, 0])+                [ plain "Numbers", plain "Text" , plain mempty ]+                [ [ plain "1"      , plain "One"  , plain "foo"  ]+                , [ plain "2"      , plain mempty , plain mempty  ]+                ]++      ]++    , testGroup "Blocks and fragments"+      [ "Source block" =:+           T.unlines [ "```"+                   , "main = putStrLn greeting"+                   , "  where greeting = \"moin\""+                   , "```" ] =?>+           let code' = "main = putStrLn greeting\n" <>+                       "  where greeting = \"moin\"\n"+           in codeBlock code'++      , "tagged block" =:+           T.unlines [ "'''"+                   , "<aside>HTML5 is pretty nice.</aside>"+                   , "'''"+                   ] =?>+           rawBlock "html" "<aside>HTML5 is pretty nice.</aside>\n"++      , "Quote block" =:+           T.unlines ["\t//Niemand// hat die Absicht, eine Mauer zu errichten!"+                   ] =?>+           blockQuote (para (spcSep [ emph "Niemand", "hat", "die", "Absicht,"+                                    , "eine", "Mauer", "zu", "errichten!"+                                    ]))++      ]+  ]
+ test/Tests/Shared.hs view
@@ -0,0 +1,39 @@+module Tests.Shared (tests) where++import System.FilePath.Posix (joinPath)+import Test.Tasty+import Test.Tasty.HUnit (assertBool, testCase, (@?=))+import Text.Pandoc.Arbitrary ()+import Text.Pandoc.Builder+import Text.Pandoc.Shared++tests :: [TestTree]+tests = [ testGroup "compactifyDL"+          [ testCase "compactifyDL with empty def" $+              assertBool "compactifyDL"+              (let x = [(str "word", [para (str "def"), mempty])]+               in  compactifyDL x == x)+          ]+        , testGroup "collapseFilePath" testCollapse+        ]++testCollapse :: [TestTree]+testCollapse = map (testCase "collapse")+ [  (collapseFilePath (joinPath [ ""]) @?= (joinPath [ ""]))+ ,  (collapseFilePath (joinPath [ ".","foo"]) @?= (joinPath [ "foo"]))+ ,  (collapseFilePath (joinPath [ ".",".","..","foo"]) @?= (joinPath [ joinPath ["..", "foo"]]))+ ,  (collapseFilePath (joinPath [ "..","foo"]) @?= (joinPath [ "..","foo"]))+ ,  (collapseFilePath (joinPath [ "","bar","..","baz"]) @?= (joinPath [ "","baz"]))+ ,  (collapseFilePath (joinPath [ "","..","baz"]) @?= (joinPath [ "","..","baz"]))+ ,  (collapseFilePath (joinPath [ ".","foo","..",".","bar","..",".",".","baz"]) @?= (joinPath [ "baz"]))+ ,  (collapseFilePath (joinPath [ ".",""]) @?= (joinPath [ ""]))+ ,  (collapseFilePath (joinPath [ ".",".",""]) @?= (joinPath [ ""]))+ ,  (collapseFilePath (joinPath [ "..",""]) @?= (joinPath [ ".."]))+ ,  (collapseFilePath (joinPath [ "..",".",""]) @?= (joinPath [ ".."]))+ ,  (collapseFilePath (joinPath [ ".","..",""]) @?= (joinPath [ ".."]))+ ,  (collapseFilePath (joinPath [ "..","..",""]) @?= (joinPath [ "..",".."]))+ ,  (collapseFilePath (joinPath [ "parent","foo","baz","..","bar"]) @?= (joinPath [ "parent","foo","bar"]))+ ,  (collapseFilePath (joinPath [ "parent","foo","baz","..","..","bar"]) @?= (joinPath [ "parent","bar"]))+ ,  (collapseFilePath (joinPath [ "parent","foo",".."]) @?= (joinPath [ "parent"]))+ ,  (collapseFilePath (joinPath [ "","parent","foo","..","..","bar"]) @?= (joinPath [ "","bar"]))+ ,  (collapseFilePath (joinPath [ "",".","parent","foo"]) @?= (joinPath [ "","parent","foo"]))]
+ test/Tests/Writers/AsciiDoc.hs view
@@ -0,0 +1,56 @@+module Tests.Writers.AsciiDoc (tests) where++import Data.Text (unpack)+import Test.Tasty+import Tests.Helpers+import Text.Pandoc+import Text.Pandoc.Arbitrary ()+import Text.Pandoc.Builder++asciidoc :: (ToPandoc a) => a -> String+asciidoc = unpack . purely (writeAsciiDoc def{ writerWrapText = WrapNone }) . toPandoc++tests :: [TestTree]+tests = [ testGroup "emphasis"+          [ test asciidoc "emph word before" $+               para (text "foo" <> emph (text "bar")) =?>+                 "foo__bar__"+          , test asciidoc "emph word after" $+               para (emph (text "foo") <> text "bar") =?>+                 "__foo__bar"+          , test asciidoc "emph quoted" $+               para (doubleQuoted (emph (text "foo"))) =?>+                 "``__foo__''"+          , test asciidoc "strong word before" $+               para (text "foo" <> strong (text "bar")) =?>+                 "foo**bar**"+          , test asciidoc "strong word after" $+               para (strong (text "foo") <> text "bar") =?>+                 "**foo**bar"+          , test asciidoc "strong quoted" $+               para (singleQuoted (strong (text "foo"))) =?>+                 "`**foo**'"+          ]+        , testGroup "tables"+          [ test asciidoc "empty cells" $+               simpleTable [] [[mempty],[mempty]] =?> unlines+                                           [ "[cols=\"\",]"+                                           , "|===="+                                           , "|"+                                           , "|"+                                           , "|===="+                                           ]+          , test asciidoc "multiblock cells" $+               simpleTable [] [[para (text "Para 1") <> para (text "Para 2")]]+                                           =?> unlines+                                           [ "[cols=\"\",]"+                                           , "|====="+                                           , "a|"+                                           , "Para 1"+                                           , ""+                                           , "Para 2"+                                           , ""+                                           , "|====="+                                           ]+          ]+        ]
+ test/Tests/Writers/ConTeXt.hs view
@@ -0,0 +1,72 @@+{-# LANGUAGE OverloadedStrings #-}+module Tests.Writers.ConTeXt (tests) where++import Data.Text (unpack)+import Test.Tasty+import Test.Tasty.QuickCheck+import Tests.Helpers+import Text.Pandoc+import Text.Pandoc.Arbitrary ()+import Text.Pandoc.Builder++context :: (ToPandoc a) => a -> String+context = unpack . purely (writeConTeXt def) . toPandoc++context' :: (ToPandoc a) => a -> String+context' = unpack . purely (writeConTeXt def{ writerWrapText = WrapNone }) . toPandoc++{-+  "my test" =: X =?> Y++is shorthand for++  test context "my test" $ X =?> Y++which is in turn shorthand for++  test context "my test" (X,Y)+-}++infix 4 =:+(=:) :: (ToString a, ToPandoc a)+     => String -> (a, String) -> TestTree+(=:) = test context++tests :: [TestTree]+tests = [ testGroup "inline code"+          [ "with '}'" =: code "}" =?> "\\mono{\\}}"+          , "without '}'" =: code "]" =?> "\\type{]}"+          , testProperty "code property" $ \s -> null s ||+                if '{' `elem` s || '}' `elem` s+                   then (context' $ code s) == "\\mono{" +++                             (context' $ str s) ++ "}"+                   else (context' $ code s) == "\\type{" ++ s ++ "}"+          ]+        , testGroup "headers"+          [ "level 1" =:+            headerWith ("my-header",[],[]) 1 "My header" =?> "\\section[my-header]{My header}"+          ]+        , testGroup "bullet lists"+          [ "nested" =:+            bulletList [+               plain (text "top")+                 <> bulletList [+                   plain (text "next")+                    <> bulletList [plain (text "bot")]+                 ]+            ] =?> unlines+                [ "\\startitemize[packed]"+                , "\\item"+                , "  top"+                , "  \\startitemize[packed]"+                , "  \\item"+                , "    next"+                , "    \\startitemize[packed]"+                , "    \\item"+                , "      bot"+                , "    \\stopitemize"+                , "  \\stopitemize"+                , "\\stopitemize" ]+          ]+        ]+
+ test/Tests/Writers/Docbook.hs view
@@ -0,0 +1,303 @@+{-# LANGUAGE OverloadedStrings #-}+module Tests.Writers.Docbook (tests) where++import Data.Text (unpack)+import Test.Tasty+import Tests.Helpers+import Text.Pandoc+import Text.Pandoc.Arbitrary ()+import Text.Pandoc.Builder++docbook :: (ToPandoc a) => a -> String+docbook = docbookWithOpts def{ writerWrapText = WrapNone }++docbookWithOpts :: ToPandoc a => WriterOptions -> a -> String+docbookWithOpts opts = unpack . purely (writeDocbook4 opts) . toPandoc++{-+  "my test" =: X =?> Y++is shorthand for++  test docbook "my test" $ X =?> Y++which is in turn shorthand for++  test docbook "my test" (X,Y)+-}++infix 4 =:+(=:) :: (ToString a, ToPandoc a)+     => String -> (a, String) -> TestTree+(=:) = test docbook++lineblock :: Blocks+lineblock = para ("some text" <> linebreak <>+                  "and more lines" <> linebreak <>+                  "and again")+lineblock_out :: [String]+lineblock_out = [ "<literallayout>some text"+                , "and more lines"+                , "and again</literallayout>"+                ]++tests :: [TestTree]+tests = [ testGroup "line blocks"+          [ "none"       =: para "This is a test"+                              =?> unlines+                                    [ "<para>"+                                    , "  This is a test"+                                    , "</para>"+                                    ]+          , "basic"      =: lineblock+                              =?> unlines lineblock_out+          , "blockquote" =: blockQuote lineblock+                              =?> unlines+                                    ( [ "<blockquote>" ] +++                                      lineblock_out +++                                      [ "</blockquote>" ]+                                    )+          , "footnote"   =: para ("This is a test" <>+                                  note lineblock <>+                                  " of footnotes")+                              =?> unlines+                                    ( [ "<para>"+                                      , "  This is a test<footnote>" ] +++                                      lineblock_out +++                                      [ "  </footnote> of footnotes"+                                      , "</para>" ]+                                    )+          ]+        , testGroup "compact lists"+          [ testGroup "bullet"+            [ "compact"    =: bulletList [plain "a", plain "b", plain "c"]+                                =?> unlines+                                      [ "<itemizedlist spacing=\"compact\">"+                                      , "  <listitem>"+                                      , "    <para>"+                                      , "      a"+                                      , "    </para>"+                                      , "  </listitem>"+                                      , "  <listitem>"+                                      , "    <para>"+                                      , "      b"+                                      , "    </para>"+                                      , "  </listitem>"+                                      , "  <listitem>"+                                      , "    <para>"+                                      , "      c"+                                      , "    </para>"+                                      , "  </listitem>"+                                      , "</itemizedlist>"+                                      ]+            , "loose"      =: bulletList [para "a", para "b", para "c"]+                                =?> unlines+                                      [ "<itemizedlist>"+                                      , "  <listitem>"+                                      , "    <para>"+                                      , "      a"+                                      , "    </para>"+                                      , "  </listitem>"+                                      , "  <listitem>"+                                      , "    <para>"+                                      , "      b"+                                      , "    </para>"+                                      , "  </listitem>"+                                      , "  <listitem>"+                                      , "    <para>"+                                      , "      c"+                                      , "    </para>"+                                      , "  </listitem>"+                                      , "</itemizedlist>"+                                      ]+            ]+          , testGroup "ordered"+            [ "compact"    =: orderedList [plain "a", plain "b", plain "c"]+                                =?> unlines+                                      [ "<orderedlist spacing=\"compact\">"+                                      , "  <listitem>"+                                      , "    <para>"+                                      , "      a"+                                      , "    </para>"+                                      , "  </listitem>"+                                      , "  <listitem>"+                                      , "    <para>"+                                      , "      b"+                                      , "    </para>"+                                      , "  </listitem>"+                                      , "  <listitem>"+                                      , "    <para>"+                                      , "      c"+                                      , "    </para>"+                                      , "  </listitem>"+                                      , "</orderedlist>"+                                      ]+            , "loose"      =: orderedList [para "a", para "b", para "c"]+                                =?> unlines+                                      [ "<orderedlist>"+                                      , "  <listitem>"+                                      , "    <para>"+                                      , "      a"+                                      , "    </para>"+                                      , "  </listitem>"+                                      , "  <listitem>"+                                      , "    <para>"+                                      , "      b"+                                      , "    </para>"+                                      , "  </listitem>"+                                      , "  <listitem>"+                                      , "    <para>"+                                      , "      c"+                                      , "    </para>"+                                      , "  </listitem>"+                                      , "</orderedlist>"+                                      ]+            ]+          , testGroup "definition"+            [ "compact"    =: definitionList [ ("an", [plain "apple" ])+                                             , ("a",  [plain "banana"])+                                             , ("an", [plain "orange"])]+                                =?> unlines+                                      [ "<variablelist spacing=\"compact\">"+                                      , "  <varlistentry>"+                                      , "    <term>"+                                      , "      an"+                                      , "    </term>"+                                      , "    <listitem>"+                                      , "      <para>"+                                      , "        apple"+                                      , "      </para>"+                                      , "    </listitem>"+                                      , "  </varlistentry>"+                                      , "  <varlistentry>"+                                      , "    <term>"+                                      , "      a"+                                      , "    </term>"+                                      , "    <listitem>"+                                      , "      <para>"+                                      , "        banana"+                                      , "      </para>"+                                      , "    </listitem>"+                                      , "  </varlistentry>"+                                      , "  <varlistentry>"+                                      , "    <term>"+                                      , "      an"+                                      , "    </term>"+                                      , "    <listitem>"+                                      , "      <para>"+                                      , "        orange"+                                      , "      </para>"+                                      , "    </listitem>"+                                      , "  </varlistentry>"+                                      , "</variablelist>"+                                      ]+            , "loose"      =: definitionList [ ("an", [para "apple" ])+                                             , ("a",  [para "banana"])+                                             , ("an", [para "orange"])]+                                =?> unlines+                                      [ "<variablelist>"+                                      , "  <varlistentry>"+                                      , "    <term>"+                                      , "      an"+                                      , "    </term>"+                                      , "    <listitem>"+                                      , "      <para>"+                                      , "        apple"+                                      , "      </para>"+                                      , "    </listitem>"+                                      , "  </varlistentry>"+                                      , "  <varlistentry>"+                                      , "    <term>"+                                      , "      a"+                                      , "    </term>"+                                      , "    <listitem>"+                                      , "      <para>"+                                      , "        banana"+                                      , "      </para>"+                                      , "    </listitem>"+                                      , "  </varlistentry>"+                                      , "  <varlistentry>"+                                      , "    <term>"+                                      , "      an"+                                      , "    </term>"+                                      , "    <listitem>"+                                      , "      <para>"+                                      , "        orange"+                                      , "      </para>"+                                      , "    </listitem>"+                                      , "  </varlistentry>"+                                      , "</variablelist>"+                                      ]+            ]+          ]+        , testGroup "writer options" $+          [ testGroup "top-level division" $+            let+              headers =  header 1 (text "header1")+                      <> header 2 (text "header2")+                      <> header 3 (text "header3")++              docbookTopLevelDiv :: (ToPandoc a)+                                 => TopLevelDivision -> a -> String+              docbookTopLevelDiv division =+                docbookWithOpts def{ writerTopLevelDivision = division }+            in+            [ test (docbookTopLevelDiv TopLevelSection) "sections as top-level" $+              headers =?>+              unlines [ "<sect1>"+                      , "  <title>header1</title>"+                      , "  <sect2>"+                      , "    <title>header2</title>"+                      , "    <sect3>"+                      , "      <title>header3</title>"+                      , "      <para>"+                      , "      </para>"+                      , "    </sect3>"+                      , "  </sect2>"+                      , "</sect1>"+                      ]+            , test (docbookTopLevelDiv TopLevelChapter) "chapters as top-level" $+              headers =?>+              unlines [ "<chapter>"+                      , "  <title>header1</title>"+                      , "  <sect1>"+                      , "    <title>header2</title>"+                      , "    <sect2>"+                      , "      <title>header3</title>"+                      , "      <para>"+                      , "      </para>"+                      , "    </sect2>"+                      , "  </sect1>"+                      , "</chapter>"+                      ]+            , test (docbookTopLevelDiv TopLevelPart) "parts as top-level" $+              headers =?>+              unlines [ "<part>"+                      , "  <title>header1</title>"+                      , "  <chapter>"+                      , "    <title>header2</title>"+                      , "    <sect1>"+                      , "      <title>header3</title>"+                      , "      <para>"+                      , "      </para>"+                      , "    </sect1>"+                      , "  </chapter>"+                      , "</part>"+                      ]+            , test (docbookTopLevelDiv TopLevelDefault) "default top-level" $+              headers =?>+              unlines [ "<sect1>"+                      , "  <title>header1</title>"+                      , "  <sect2>"+                      , "    <title>header2</title>"+                      , "    <sect3>"+                      , "      <title>header3</title>"+                      , "      <para>"+                      , "      </para>"+                      , "    </sect3>"+                      , "  </sect2>"+                      , "</sect1>"+                      ]+            ]+          ]+        ]
+ test/Tests/Writers/Docx.hs view
@@ -0,0 +1,161 @@+module Tests.Writers.Docx (tests) where++import qualified Data.ByteString as BS+import System.FilePath ((</>))+import System.IO.Unsafe (unsafePerformIO)+import Test.Tasty+import Tests.Helpers+import Text.Pandoc.Class (runIOorExplode, setUserDataDir)+import Text.Pandoc.Definition+import Text.Pandoc.Options+import Text.Pandoc.Readers.Docx+import Text.Pandoc.Readers.Native+import qualified Text.Pandoc.UTF8 as UTF8+import Text.Pandoc.Walk+import Text.Pandoc.Writers.Docx++type Options = (WriterOptions, ReaderOptions)++compareOutput :: Options+              -> FilePath+              -> FilePath+              -> IO (Pandoc, Pandoc)+compareOutput (wopts, ropts) nativeFileIn nativeFileOut = do+  nf <- UTF8.toText <$> BS.readFile nativeFileIn+  nf' <- UTF8.toText <$> BS.readFile nativeFileOut+  runIOorExplode $ do+    setUserDataDir $ Just (".." </> "data")+    roundtripped <- readNative def nf >>=+            writeDocx wopts >>= readDocx ropts+    orig <- readNative def nf'+    return (walk fixImages roundtripped, walk fixImages orig)++-- make all image filenames "image", since otherwise round-trip+-- tests fail because of different behavior of Data.Unique in+-- different ghc versions...+fixImages :: Inline -> Inline+fixImages (Image attr alt (_,tit)) = Image attr alt ("image",tit)+fixImages x                        = x++testCompareWithOptsIO :: Options -> String -> FilePath -> FilePath -> IO TestTree+testCompareWithOptsIO opts name nativeFileIn nativeFileOut = do+  (dp, np) <- compareOutput opts nativeFileIn nativeFileOut+  return $ test id name (dp, np)++testCompareWithOpts :: Options -> String -> FilePath -> FilePath -> TestTree+testCompareWithOpts opts name nativeFileIn nativeFileOut =+  unsafePerformIO $ testCompareWithOptsIO opts name nativeFileIn nativeFileOut++roundTripCompareWithOpts :: Options -> String -> FilePath -> TestTree+roundTripCompareWithOpts opts name nativeFile =+  testCompareWithOpts opts name nativeFile nativeFile++-- testCompare :: String -> FilePath -> FilePath -> TestTree+-- testCompare = testCompareWithOpts def++roundTripCompare :: String -> FilePath -> TestTree+roundTripCompare = roundTripCompareWithOpts def++tests :: [TestTree]+tests = [ testGroup "inlines"+          [ roundTripCompare+            "font formatting"+            "docx/inline_formatting_writer.native"+          , roundTripCompare+            "font formatting with character styles"+            "docx/char_styles.native"+          , roundTripCompare+            "hyperlinks"+            "docx/links_writer.native"+          , roundTripCompare+            "inline image"+            "docx/image_no_embed_writer.native"+          , roundTripCompare+            "inline image in links"+            "docx/inline_images_writer.native"+          , roundTripCompare+            "handling unicode input"+            "docx/unicode.native"+          , roundTripCompare+            "literal tabs"+            "docx/tabs.native"+          , roundTripCompare+            "normalizing inlines"+            "docx/normalize.native"+          , roundTripCompare+            "normalizing inlines deep inside blocks"+            "docx/deep_normalize.native"+          , roundTripCompare+            "move trailing spaces outside of formatting"+            "docx/trailing_spaces_in_formatting.native"+          , roundTripCompare+            "inline code (with VerbatimChar style)"+            "docx/inline_code.native"+          , roundTripCompare+            "inline code in subscript and superscript"+            "docx/verbatim_subsuper.native"+          ]+        , testGroup "blocks"+          [ roundTripCompare+            "headers"+            "docx/headers.native"+          , roundTripCompare+            "headers already having auto identifiers"+            "docx/already_auto_ident.native"+          , roundTripCompare+            "numbered headers automatically made into list"+            "docx/numbered_header.native"+          , roundTripCompare+            "i18n blocks (headers and blockquotes)"+            "docx/i18n_blocks.native"+          -- Continuation does not survive round-trip+          , roundTripCompare+            "lists"+            "docx/lists_writer.native"+          , roundTripCompare+            "definition lists"+            "docx/definition_list.native"+          , roundTripCompare+            "custom defined lists in styles"+            "docx/german_styled_lists.native"+          , roundTripCompare+            "footnotes and endnotes"+            "docx/notes.native"+          , roundTripCompare+            "blockquotes (parsing indent as blockquote)"+            "docx/block_quotes_parse_indent.native"+          , roundTripCompare+            "hanging indents"+            "docx/hanging_indent.native"+          -- tables headers do not survive round-trip, should look into that+          , roundTripCompare+            "tables"+            "docx/tables.native"+          , roundTripCompare+            "tables with lists in cells"+            "docx/table_with_list_cell.native"+          , roundTripCompare+            "code block"+            "docx/codeblock.native"+          , roundTripCompare+            "dropcap paragraphs"+            "docx/drop_cap.native"+          ]+        , testGroup "metadata"+          [ roundTripCompareWithOpts (def,def{readerStandalone=True})+            "metadata fields"+            "docx/metadata.native"+          , roundTripCompareWithOpts (def,def{readerStandalone=True})+            "stop recording metadata with normal text"+            "docx/metadata_after_normal.native"+          ]+        , testGroup "customized styles"+          [ testCompareWithOpts+            ( def{writerReferenceDoc=Just "docx/custom-style-reference.docx"}+            , def)+            "simple customized blocks and inlines"+            "docx/custom-style-roundtrip-start.native"+            "docx/custom-style-roundtrip-end.native"+          ]++        ]
+ test/Tests/Writers/HTML.hs view
@@ -0,0 +1,44 @@+{-# LANGUAGE OverloadedStrings #-}+module Tests.Writers.HTML (tests) where++import Data.Text (unpack)+import Test.Tasty+import Tests.Helpers+import Text.Pandoc+import Text.Pandoc.Arbitrary ()+import Text.Pandoc.Builder++html :: (ToPandoc a) => a -> String+html = unpack . purely (writeHtml4String def{ writerWrapText = WrapNone }) . toPandoc++{-+  "my test" =: X =?> Y++is shorthand for++  test html "my test" $ X =?> Y++which is in turn shorthand for++  test html "my test" (X,Y)+-}++infix 4 =:+(=:) :: (ToString a, ToPandoc a)+     => String -> (a, String) -> TestTree+(=:) = test html++tests :: [TestTree]+tests = [ testGroup "inline code"+          [ "basic" =: code "@&" =?> "<code>@&amp;</code>"+          , "haskell" =: codeWith ("",["haskell"],[]) ">>="+            =?> "<code class=\"sourceCode haskell\"><span class=\"fu\">&gt;&gt;=</span></code>"+          , "nolanguage" =: codeWith ("",["nolanguage"],[]) ">>="+            =?> "<code class=\"nolanguage\">&gt;&gt;=</code>"+          ]+        , testGroup "images"+          [ "alt with formatting" =:+            image "/url" "title" ("my " <> emph "image")+            =?> "<img src=\"/url\" title=\"title\" alt=\"my image\" />"+          ]+        ]
+ test/Tests/Writers/LaTeX.hs view
@@ -0,0 +1,176 @@+{-# LANGUAGE OverloadedStrings #-}+module Tests.Writers.LaTeX (tests) where++import Data.Text (unpack)+import Test.Tasty+import Tests.Helpers+import Text.Pandoc+import Text.Pandoc.Arbitrary ()+import Text.Pandoc.Builder++latex :: (ToPandoc a) => a -> String+latex = latexWithOpts def++latexListing :: (ToPandoc a) => a -> String+latexListing = latexWithOpts def{ writerListings = True }++latexWithOpts :: (ToPandoc a) => WriterOptions -> a -> String+latexWithOpts opts = unpack . purely (writeLaTeX opts) . toPandoc++beamerWithOpts :: (ToPandoc a) => WriterOptions -> a -> String+beamerWithOpts opts = unpack . purely (writeBeamer opts) . toPandoc++{-+  "my test" =: X =?> Y++is shorthand for++  test latex "my test" $ X =?> Y++which is in turn shorthand for++  test latex "my test" (X,Y)+-}++infix 4 =:+(=:) :: (ToString a, ToPandoc a)+     => String -> (a, String) -> TestTree+(=:) = test latex++tests :: [TestTree]+tests = [ testGroup "code blocks"+          [ "in footnotes" =: note (para "hi" <> codeBlock "hi") =?>+            "\\footnote{hi\n\n\\begin{Verbatim}\nhi\n\\end{Verbatim}\n}"+          , test latexListing "identifier" $ codeBlockWith ("id",[],[]) "hi" =?>+            ("\\begin{lstlisting}[label=id]\nhi\n\\end{lstlisting}" :: String)+          , test latexListing "no identifier" $ codeBlock "hi" =?>+            ("\\begin{lstlisting}\nhi\n\\end{lstlisting}" :: String)+          ]+        , testGroup "definition lists"+          [ "with internal link" =: definitionList [(link "#go" "" (str "testing"),+             [plain (text "hi there")])] =?>+            "\\begin{description}\n\\tightlist\n\\item[{\\protect\\hyperlink{go}{testing}}]\nhi there\n\\end{description}"+          ]+        , testGroup "math"+          [ "escape |" =: para (math "\\sigma|_{\\{x\\}}") =?>+            "\\(\\sigma|_{\\{x\\}}\\)"+          ]+        , testGroup "headers"+          [ "unnumbered header" =:+            headerWith ("foo",["unnumbered"],[]) 1+              (text "Header 1" <> note (plain $ text "note")) =?>+            "\\hypertarget{foo}{%\n\\section*{\\texorpdfstring{Header 1\\footnote{note}}{Header 1}}\\label{foo}}\n\\addcontentsline{toc}{section}{Header 1}\n"+          , "in list item" =:+            bulletList [header 2 (text "foo")] =?>+            "\\begin{itemize}\n\\item ~\n  \\subsection{foo}\n\\end{itemize}"+          , "in definition list item" =:+            definitionList [(text "foo", [header 2 (text "bar"),+                                          para $ text "baz"])] =?>+            "\\begin{description}\n\\item[foo] ~ \n\\subsection{bar}\n\nbaz\n\\end{description}"+          , "containing image" =:+            header 1 (image "imgs/foo.jpg" "" (text "Alt text")) =?>+            "\\section{\\texorpdfstring{\\protect\\includegraphics{imgs/foo.jpg}}{Alt text}}"+          ]+        , testGroup "inline code"+          [ "struck out and highlighted" =:+            strikeout (codeWith ("",["haskell"],[]) "foo" <> space+              <> str "bar") =?>+            "\\sout{\\mbox{\\VERB|\\NormalTok{foo}|} bar}"+          , "struck out and not highlighted" =:+            strikeout (code "foo" <> space+              <> str "bar") =?>+            "\\sout{\\texttt{foo} bar}"+          , "single quotes" =:+              code "dog's" =?> "\\texttt{dog\\textquotesingle{}s}"+          , "backtick" =:+              code "`nu?`" =?> "\\texttt{\\textasciigrave{}nu?\\textasciigrave{}}"+          ]+        , testGroup "writer options"+          [ testGroup "top-level division" $+            let+              headers =  header 1 (text "header1")+                      <> header 2 (text "header2")+                      <> header 3 (text "header3")++              latexTopLevelDiv :: (ToPandoc a) => TopLevelDivision -> a -> String+              latexTopLevelDiv division =+                latexWithOpts def{ writerTopLevelDivision = division }++              beamerTopLevelDiv :: (ToPandoc a)+                                => TopLevelDivision -> a -> String+              beamerTopLevelDiv division =+                beamerWithOpts def { writerTopLevelDivision = division }+            in+            [ test (latexTopLevelDiv TopLevelSection)+                   "sections as top-level" $ headers =?>+              unlines [ "\\section{header1}\n"+                      , "\\subsection{header2}\n"+                      , "\\subsubsection{header3}"+                      ]+            , test (latexTopLevelDiv TopLevelChapter)+                   "chapters as top-level" $ headers =?>+              unlines [ "\\chapter{header1}\n"+                      , "\\section{header2}\n"+                      , "\\subsection{header3}"+                      ]+            , test (latexTopLevelDiv TopLevelPart)+                   "parts as top-level" $ headers =?>+              unlines [ "\\part{header1}\n"+                      , "\\chapter{header2}\n"+                      , "\\section{header3}"+                      ]+            , test (latexTopLevelDiv TopLevelDefault)+                   "default top-level" $ headers =?>+              unlines [ "\\section{header1}\n"+                      , "\\subsection{header2}\n"+                      , "\\subsubsection{header3}"+                      ]+            , test (beamerTopLevelDiv TopLevelSection)+                   "sections as top-level in beamer" $ headers =?>+              unlines [ "\\section{header1}\n"+                      , "\\subsection{header2}\n"+                      , "\\subsubsection{header3}"+                      ]+            , test (beamerTopLevelDiv TopLevelChapter)+                   "chapters are as part in beamer" $ headers =?>+              unlines [ "\\part{header1}\n"+                      , "\\section{header2}\n"+                      , "\\subsection{header3}"+                      ]+            , test (beamerTopLevelDiv TopLevelPart)+                   "parts as top-level in beamer" $ headers =?>+              unlines [ "\\part{header1}\n"+                      , "\\section{header2}\n"+                      , "\\subsection{header3}"+                      ]+            , test (beamerTopLevelDiv TopLevelDefault)+                   "default top-level in beamer" $ headers =?>+              unlines [ "\\section{header1}\n"+                      , "\\subsection{header2}\n"+                      , "\\subsubsection{header3}"+                      ]+            , test (latexTopLevelDiv TopLevelPart)+                   "part top-level, section not in toc" $+                   (   headerWith ("", ["unnumbered"], []) 1 (text "header1")+                    <> headerWith ("", ["unnumbered"], []) 2 (text "header2")+                    <> headerWith ("", ["unnumbered"], []) 3 (text "header3")+                    <> headerWith ("", ["unnumbered"], []) 4 (text "header4")+                    <> headerWith ("", ["unnumbered"], []) 5 (text "header5")+                    <> headerWith ("", ["unnumbered"], []) 6 (text "header6"))+                   =?>+              unlines [ "\\part*{header1}"+                      , "\\addcontentsline{toc}{part}{header1}\n"+                      , "\\chapter*{header2}"+                      , "\\addcontentsline{toc}{chapter}{header2}\n"+                      , "\\section*{header3}"+                      , "\\addcontentsline{toc}{section}{header3}\n"+                      , "\\subsection*{header4}"+                      , "\\addcontentsline{toc}{subsection}{header4}\n"+                      , "\\subsubsection*{header5}"+                      , "\\addcontentsline{toc}{subsubsection}{header5}\n"+                      , "\\paragraph{header6}"+                      , "\\addcontentsline{toc}{paragraph}{header6}"+                      ]+            ]+          ]+        ]
+ test/Tests/Writers/Markdown.hs view
@@ -0,0 +1,267 @@+{-# LANGUAGE OverloadedStrings #-}+{-# OPTIONS_GHC -fno-warn-name-shadowing #-}+module Tests.Writers.Markdown (tests) where++import Data.Text (unpack)+import Test.Tasty+import Tests.Helpers+import Text.Pandoc+import Text.Pandoc.Arbitrary ()+import Text.Pandoc.Builder++defopts :: WriterOptions+defopts = def{ writerExtensions = pandocExtensions }++markdown :: (ToPandoc a) => a -> String+markdown = unpack . purely (writeMarkdown defopts) . toPandoc++markdownWithOpts :: (ToPandoc a) => WriterOptions -> a -> String+markdownWithOpts opts x = unpack . purely (writeMarkdown opts) $ toPandoc x++{-+  "my test" =: X =?> Y++is shorthand for++  test markdown "my test" $ X =?> Y++which is in turn shorthand for++  test markdown "my test" (X,Y)+-}++infix 4 =:+(=:) :: (ToString a, ToPandoc a)+     => String -> (a, String) -> TestTree+(=:) = test markdown++tests :: [TestTree]+tests = [ "indented code after list"+             =: (orderedList [ para "one" <> para "two" ] <> codeBlock "test")+             =?> "1.  one\n\n    two\n\n<!-- -->\n\n    test"+        , "list with tight sublist"+             =: bulletList [ plain "foo" <> bulletList [ plain "bar" ],+                             plain "baz" ]+             =?> "-   foo\n    -   bar\n-   baz\n"+        ] ++ [noteTests] ++ [shortcutLinkRefsTests]++{-++Testing with the following text:++First Header+============++This is a footnote.[^1] And this is a [link](https://www.google.com).++> A note inside a block quote.[^2]+>+> A second paragraph.++Second Header+=============++Some more text.+++[^1]: Down here.++[^2]: The second note.++-}++noteTestDoc :: Blocks+noteTestDoc =+  header 1 "First Header" <>+  para ("This is a footnote." <>+        note (para "Down here.") <>+        " And this is a " <>+        link "https://www.google.com" "" "link" <>+        ".") <>+  blockQuote (para ("A note inside a block quote." <>+                    note (para "The second note.")) <>+              para ("A second paragraph.")) <>+  header 1 "Second Header" <>+  para "Some more text."++++noteTests :: TestTree+noteTests = testGroup "note and reference location"+  [ test (markdownWithOpts defopts)+    "footnotes at the end of a document" $+    noteTestDoc =?>+    (unlines $ [ "First Header"+               , "============"+               , ""+               , "This is a footnote.[^1] And this is a [link](https://www.google.com)."+               , ""+               , "> A note inside a block quote.[^2]"+               , ">"+               , "> A second paragraph."+               , ""+               , "Second Header"+               , "============="+               , ""+               , "Some more text."+               , ""+               , "[^1]: Down here."+               , ""+               , "[^2]: The second note."+               ])+  , test (markdownWithOpts defopts{writerReferenceLocation=EndOfBlock})+    "footnotes at the end of blocks" $+    noteTestDoc =?>+    (unlines $ [ "First Header"+               , "============"+               , ""+               , "This is a footnote.[^1] And this is a [link](https://www.google.com)."+               , ""+               , "[^1]: Down here."+               , ""+               , "> A note inside a block quote.[^2]"+               , ">"+               , "> A second paragraph."+               , ""+               , "[^2]: The second note."+               , ""+               , "Second Header"+               , "============="+               , ""+               , "Some more text."+               ])+  , test (markdownWithOpts defopts{writerReferenceLocation=EndOfBlock, writerReferenceLinks=True})+    "footnotes and reference links at the end of blocks" $+    noteTestDoc =?>+    (unlines $ [ "First Header"+               , "============"+               , ""+               , "This is a footnote.[^1] And this is a [link]."+               , ""+               , "[^1]: Down here."+               , ""+               , "  [link]: https://www.google.com"+               , ""+               , "> A note inside a block quote.[^2]"+               , ">"+               , "> A second paragraph."+               , ""+               , "[^2]: The second note."+               , ""+               , "Second Header"+               , "============="+               , ""+               , "Some more text."+               ])+  , test (markdownWithOpts defopts{writerReferenceLocation=EndOfSection})+    "footnotes at the end of section" $+    noteTestDoc =?>+    (unlines $ [ "First Header"+               , "============"+               , ""+               , "This is a footnote.[^1] And this is a [link](https://www.google.com)."+               , ""+               , "> A note inside a block quote.[^2]"+               , ">"+               , "> A second paragraph."+               , ""+               , "[^1]: Down here."+               , ""+               , "[^2]: The second note."+               , ""+               , "Second Header"+               , "============="+               , ""+               , "Some more text."+               ])++  ]++shortcutLinkRefsTests :: TestTree+shortcutLinkRefsTests =+  let infix 4 =:+      (=:) :: (ToString a, ToPandoc a)++        => String -> (a, String) -> TestTree+      (=:) = test (purely (writeMarkdown defopts{writerReferenceLinks = True}) . toPandoc)+  in testGroup "Shortcut reference links"+     [ "Simple link (shortcutable)"+           =: (para (link "/url" "title" "foo"))+           =?> "[foo]\n\n  [foo]: /url \"title\""+     , "Followed by another link (unshortcutable)"+           =: (para ((link "/url1" "title1" "first")+                  <> (link "/url2" "title2" "second")))+           =?> unlines [ "[first][][second]"+                       , ""+                       , "  [first]: /url1 \"title1\""+                       , "  [second]: /url2 \"title2\""+                       ]+     , "Followed by space and another link (unshortcutable)"+           =: (para ((link "/url1" "title1" "first") <> " "+                  <> (link "/url2" "title2" "second")))+           =?> unlines [ "[first][] [second]"+                       , ""+                       , "  [first]: /url1 \"title1\""+                       , "  [second]: /url2 \"title2\""+                       ]+     , "Reference link is used multiple times (unshortcutable)"+           =: (para ((link "/url1" "" "foo") <> (link "/url2" "" "foo")+                                             <> (link "/url3" "" "foo")))+           =?> unlines [ "[foo][][foo][1][foo][2]"+                       , ""+                       , "  [foo]: /url1"+                       , "  [1]: /url2"+                       , "  [2]: /url3"+                       ]+     , "Reference link is used multiple times (unshortcutable)"+           =: (para ((link "/url1" "" "foo") <> " " <> (link "/url2" "" "foo")+                                             <> " " <> (link "/url3" "" "foo")))+           =?> unlines [ "[foo][] [foo][1] [foo][2]"+                       , ""+                       , "  [foo]: /url1"+                       , "  [1]: /url2"+                       , "  [2]: /url3"+                       ]+     , "Reference link is followed by text in brackets"+          =:  (para ((link "/url" "" "link") <> "[text in brackets]"))+          =?> unlines [ "[link][]\\[text in brackets\\]"+                      , ""+                      , "  [link]: /url"+                      ]+     , "Reference link is followed by space and text in brackets"+          =:  (para ((link "/url" "" "link") <> " [text in brackets]"))+          =?> unlines [ "[link][] \\[text in brackets\\]"+                      , ""+                      , "  [link]: /url"+                      ]+     , "Reference link is followed by RawInline"+          =: (para ((link "/url" "" "link") <> rawInline "markdown" "[rawText]"))+          =?> unlines [ "[link][][rawText]"+                      , ""+                      , "  [link]: /url"+                      ]+     , "Reference link is followed by space and RawInline"+          =: (para ((link "/url" "" "link") <> space <> rawInline "markdown" "[rawText]"))+          =?> unlines [ "[link][] [rawText]"+                      , ""+                      , "  [link]: /url"+                      ]+     , "Reference link is followed by RawInline with space"+          =: (para ((link "/url" "" "link") <> rawInline "markdown" " [rawText]"))+          =?> unlines [ "[link][] [rawText]"+                      , ""+                      , "  [link]: /url"+                      ]+     , "Reference link is followed by citation"+          =: (para ((link "/url" "" "link") <> cite [Citation "author" [] [] NormalCitation 0 0] (str "[@author]")))+          =?> unlines [ "[link][][@author]"+                      , ""+                      , "  [link]: /url"+                      ]+     , "Reference link is followed by space and citation"+          =: (para ((link "/url" "" "link") <> space <> cite [Citation "author" [] [] NormalCitation 0 0] (str "[@author]")))+          =?> unlines [ "[link][] [@author]"+                      , ""+                      , "  [link]: /url"+                      ]+     ]
+ test/Tests/Writers/Muse.hs view
@@ -0,0 +1,358 @@+module Tests.Writers.Muse (tests) where++import Data.Text (unpack)+import Test.Tasty+import Tests.Helpers+import Text.Pandoc+import Text.Pandoc.Arbitrary ()+import Text.Pandoc.Builder++muse :: (ToPandoc a) => a -> String+muse = museWithOpts def{ writerWrapText = WrapNone }++museWithOpts :: (ToPandoc a) => WriterOptions -> a -> String+museWithOpts opts = unpack . purely (writeMuse opts) . toPandoc++infix 4 =:+(=:) :: (ToString a, ToPandoc a)+     => String -> (a, String) -> TestTree+(=:) = test muse++tests :: [TestTree]+tests = [ testGroup "block elements"+          [ "plain" =: plain (text "Foo bar.") =?> "Foo bar."+          , testGroup "paragraphs"+            [ "single paragraph" =: para (text "Sample paragraph.")+                                 =?> "Sample paragraph."+            , "two paragraphs" =: para (text "First paragraph.") <>+                                  para (text "Second paragraph.")+                               =?> unlines [ "First paragraph."+                                           , ""+                                           , "Second paragraph."+                                           ]+            ]+          , "line block" =: lineBlock [text "Foo", text "bar", text "baz"]+                         =?> unlines [ "<verse>"+                                     , "Foo"+                                     , "bar"+                                     , "baz"+                                     , "</verse>"+                                     ]+          , "code block" =: codeBlock "int main(void) {\n\treturn 0;\n}"+                         =?> unlines [ "<example>"+                                     , "int main(void) {"+                                     , "\treturn 0;"+                                     , "}"+                                     , "</example>"+                                     ]+          , "html raw block" =: rawBlock "html" "<hr>"+                             =?> unlines [ "<literal style=\"html\">"+                                         , "<hr>"+                                         , "</literal>"+                                         ]+          , "block quote" =: blockQuote (para (text "Foo"))+                          =?> unlines [ "<quote>"+                                      , "Foo"+                                      , "</quote>"+                                      ]+          , testGroup "lists"+            [ testGroup "simple lists"+              [+                "ordered list" =: orderedList [ plain $ text "first"+                                              , plain $ text "second"+                                              , plain $ text "third"+                                              ]+                               =?> unlines [ " 1. first"+                                           , " 2. second"+                                           , " 3. third"+                                           ]+              , "ordered list with Roman numerals"+                =: orderedListWith (1, UpperRoman, DefaultDelim)+                   [ plain $ text "first"+                   , plain $ text "second"+                   , plain $ text "third"+                   ]+                =?> unlines [ " I.   first"+                            , " II.  second"+                            , " III. third"+                            ]+              , "bullet list" =: bulletList [ plain $ text "first"+                                            , plain $ text "second"+                                            , plain $ text "third"+                                            ]+                              =?> unlines [ " - first"+                                          , " - second"+                                          , " - third"+                                          ]+              , "definition list" =: definitionList [ (text "first definition", [plain $ text "first description"])+                                                    , (text "second definition", [plain $ text "second description"])+                                                    , (text "third definition", [plain $ text "third description"])+                                                    ]+                                  =?> unlines [ " first definition :: first description"+                                              , " second definition :: second description"+                                              , " third definition :: third description"+                                              ]+              ]+            -- Test that lists of the same type and style are separated with two blanklines+            , testGroup "sequential lists"+              [ "bullet lists" =:+                bulletList [ para $ text "First"+                           , para $ text "Second"+                           , para $ text "Third"+                           ] <>+                bulletList [ para $ text "Fourth"+                           , para $ text "Fifth"+                           ] =?>+                unlines [ " - First"+                        , " - Second"+                        , " - Third"+                        , ""+                        , ""+                        , " - Fourth"+                        , " - Fifth"+                        ]+              , "ordered lists of the same style" =:+                orderedListWith (1, UpperRoman, DefaultDelim) [ para $ text "First"+                                                              , para $ text "Second"+                                                              ] <>+                orderedListWith (1, UpperRoman, DefaultDelim) [ para $ text "Third"+                                                              , para $ text "Fourth"+                                                              ] =?>+                unlines [ " I.  First"+                        , " II. Second"+                        , ""+                        , ""+                        , " I.  Third"+                        , " II. Fourth"+                        ]+              , "ordered lists with equal styles" =:+                orderedList [ para $ text "First"+                            , para $ text "Second"+                            ] <>+                orderedListWith (1, Decimal, DefaultDelim) [ para $ text "Third"+                                                           , para $ text "Fourth"+                                                           ] =?>+                unlines [ " 1. First"+                        , " 2. Second"+                        , ""+                        , ""+                        , " 1. Third"+                        , " 2. Fourth"+                        ]+              , "bullet and ordered lists" =:+                bulletList [ para $ text "First"+                           , para $ text "Second"+                           ] <>+                orderedListWith (1, UpperRoman, DefaultDelim) [ para $ text "Third"+                                                              , para $ text "Fourth"+                                                              ] =?>+                unlines [ " - First"+                        , " - Second"+                        , ""+                        , " I.  Third"+                        , " II. Fourth"+                        ]+              , "different style ordered lists" =:+                orderedListWith (1, UpperRoman, DefaultDelim) [ para $ text "First"+                                                              , para $ text "Second"+                                                              ] <>+                orderedListWith (1, Decimal, DefaultDelim) [ para $ text "Third"+                                                           , para $ text "Fourth"+                                                           ] =?>+                unlines [ " I.  First"+                        , " II. Second"+                        , ""+                        , " 1. Third"+                        , " 2. Fourth"+                        ]+              ]+            , testGroup "nested lists"+              [ "nested ordered list" =: orderedList [ plain $ text "First outer"+                                                     , plain (text "Second outer:") <>+                                                       orderedList [ plain $ text "first"+                                                                   , plain $ text "second"+                                                                   ]+                                                     , plain $ text "Third outer"+                                                     ]+                                      =?> unlines [ " 1. First outer"+                                                  , " 2. Second outer:"+                                                  , "    1. first"+                                                  , "    2. second"+                                                  , " 3. Third outer"+                                                  ]+              , "nested bullet lists" =: bulletList [ plain $ text "First outer"+                                                    , plain (text "Second outer:") <>+                                                      bulletList [ plain $ text "first"+                                                                 , plain $ text "second"+                                                                 ]+                                                    , plain $ text "Third outer"+                                                    ]+                                      =?> unlines [ " - First outer"+                                                  , " - Second outer:"+                                                  , "   - first"+                                                  , "   - second"+                                                  , " - Third outer"+                                                  ]+              , "nested definition lists" =: definitionList [ (text "first definition", [plain $ text "first description"])+                                                            , (text "second definition",+                                                               [ plain (text "second description")+                                                               , definitionList [ ( text "first inner definition"+                                                                                  , [plain $ text "first inner description"])+                                                                                , ( text "second inner definition"+                                                                                  , [plain $ text "second inner description"])+                                                                                ]+                                                               ]+                                                              )+                                                            ]+                                          =?> unlines [ " first definition :: first description"+                                                      , " second definition :: second description"+                                                      , "                       first inner definition :: first inner description"+                                                      , "                       second inner definition :: second inner description"+                                                      ]+              ]+            -- Check that list is intended with one space even inside a quote+            , "List inside block quote" =: blockQuote (orderedList [ plain $ text "first"+                                                                   , plain $ text "second"+                                                                   , plain $ text "third"+                                                                   ])+                                        =?> unlines [ "<quote>"+                                                    , " 1. first"+                                                    , " 2. second"+                                                    , " 3. third"+                                                    , "</quote>"+                                                    ]+            ]+          , testGroup "headings"+            [ "normal heading" =:+              header 1 (text "foo") =?> "* foo"+            , "heading levels" =:+              header 1 (text "First level") <>+              header 3 (text "Third level") =?>+              unlines [ "* First level"+                      , ""+                      , "*** Third level"+                      ]+            ]+          , "horizontal rule" =: horizontalRule =?> "----"+          , testGroup "tables"+            [ "table without header" =:+              let rows = [[para $ text "Para 1.1", para $ text "Para 1.2"]+                         ,[para $ text "Para 2.1", para $ text "Para 2.2"]]+              in simpleTable [] rows+              =?>+              unlines [ " Para 1.1 | Para 1.2"+                      , " Para 2.1 | Para 2.2"+                      ]+            , "table with header" =:+              let headers = [plain $ text "header 1", plain $ text "header 2"]+                  rows = [[para $ text "Para 1.1", para $ text "Para 1.2"]+                         ,[para $ text "Para 2.1", para $ text "Para 2.2"]]+              in simpleTable headers rows+              =?>+              unlines [ " header 1 || header 2"+                      , " Para 1.1 |  Para 1.2"+                      , " Para 2.1 |  Para 2.2"+                      ]+            , "table with header and caption" =:+              let caption = text "Table 1"+                  headers = [plain $ text "header 1", plain $ text "header 2"]+                  rows = [[para $ text "Para 1.1", para $ text "Para 1.2"]+                         ,[para $ text "Para 2.1", para $ text "Para 2.2"]]+              in table caption mempty headers rows+              =?> unlines [ " header 1 || header 2"+                          , " Para 1.1 |  Para 1.2"+                          , " Para 2.1 |  Para 2.2"+                          , " |+ Table 1 +|"+                          ]+            ]+          -- Div is trivial+          -- Null is trivial+          ]+        , testGroup "inline elements"+          [ testGroup "string"+            [ "string" =: str "foo" =?> "foo"+            , "escape footnote" =: str "[1]" =?> "<verbatim>[1]</verbatim>"+            , "escape verbatim close tag" =: str "foo</verbatim>bar"+               =?> "<verbatim>foo<</verbatim><verbatim>/verbatim>bar</verbatim>"+            , "escape pipe to avoid accidental tables" =: str "foo | bar"+               =?> "<verbatim>foo | bar</verbatim>"+            , "escape definition list markers" =: str "::" =?> "<verbatim>::</verbatim>"+            -- We don't want colons to be escaped if they can't be confused+            -- with definition list item markers.+            , "do not escape colon" =: str ":" =?> ":"+            ]+          , testGroup "emphasis"+            [ "emph" =: emph (text "foo") =?> "<em>foo</em>"+            , "strong" =: strong (text "foo") =?> "<strong>foo</strong>"+            , "strikeout" =: strikeout (text "foo") =?> "<del>foo</del>"+            ]+          , "superscript" =: superscript (text "foo") =?> "<sup>foo</sup>"+          , "subscript" =: subscript (text "foo") =?> "<sub>foo</sub>"+          , "smallcaps" =: smallcaps (text "foo") =?> "foo"+          , "single quoted" =: singleQuoted (text "foo") =?> "'foo'"+          , "double quoted" =: doubleQuoted (text "foo") =?> "\"foo\""+          -- Cite is trivial+          , testGroup "code"+            [ "simple" =: code "foo" =?> "<code>foo</code>"+            , "escape lightweight markup" =: code "foo = bar" =?> "<code><verbatim>foo = bar</verbatim></code>"+            , "escape tag" =: code "<code>foo = bar</code> baz" =?> "<code><verbatim><code>foo = bar</code> baz</verbatim></code>"+            ]+          , testGroup "spaces"+            [ "space" =: text "a" <> space <> text "b" =?> "a b"+            , "soft break" =: text "a" <> softbreak <> text "b" =?> "a b"+            , test (museWithOpts def{ writerWrapText = WrapPreserve })+                   "preserve soft break" $ text "a" <> softbreak <> text "b"+                   =?> "a\nb"+            , "line break" =: text "a" <> linebreak <> text "b" =?> "a<br>\nb"+            ]+          , testGroup "math"+            [ "inline math" =: math "2^3" =?> "2<sup>3</sup>"+            , "display math" =: displayMath "2^3" =?> "<verse>2<sup>3</sup></verse>"+            ]+          , "raw inline"+            =: rawInline "html" "<mark>marked text</mark>"+            =?> "<literal style=\"html\"><mark>marked text</mark></literal>"+          , testGroup "links"+            [ "link with description" =: link "https://example.com" "" (str "Link 1")+                                      =?> "[[https://example.com][Link 1]]"+            , "link without description" =: link "https://example.com" "" (str "https://example.com")+                                         =?> "[[https://example.com]]"+            -- Internal links in Muse include '#'+            , "link to anchor" =: link "#intro" "" (str "Introduction")+                               =?> "[[#intro][Introduction]]"+            -- According to Emacs Muse manual, links to images should be prefixed with "URL:"+            , "link to image with description" =: link "1.png" "" (str "Link to image")+                                               =?> "[[URL:1.png][Link to image]]"+            , "link to image without description" =: link "1.png" "" (str "1.png")+                                                  =?> "[[URL:1.png]]"+            ]+          , "image" =: image "image.png" "Image 1" (str "") =?> "[[image.png][Image 1]]"+          , "note" =: note (plain (text "Foo"))+                   =?> unlines [ "[1]"+                               , ""+                               , "[1] Foo"+                               ]+          , "span" =: spanWith ("",["foobar"],[]) (str "Some text")+                   =?> "<class name=\"foobar\">Some text</class>"+          , testGroup "combined"+            [ "emph word before" =:+                para (text "foo" <> emph (text "bar")) =?>+                    "foo<em>bar</em>"+            , "emph word after" =:+                para (emph (text "foo") <> text "bar") =?>+                    "<em>foo</em>bar"+            , "emph quoted" =:+                para (doubleQuoted (emph (text "foo"))) =?>+                    "\"<em>foo</em>\""+            , "strong word before" =:+                para (text "foo" <> strong (text "bar")) =?>+                    "foo<strong>bar</strong>"+            , "strong word after" =:+                para (strong (text "foo") <> text "bar") =?>+                    "<strong>foo</strong>bar"+            , "strong quoted" =:+                para (singleQuoted (strong (text "foo"))) =?>+                    "'<strong>foo</strong>'"+            ]+         ]+       ]
+ test/Tests/Writers/Native.hs view
@@ -0,0 +1,22 @@+module Tests.Writers.Native (tests) where++import Data.Text (unpack)+import Test.Tasty+import Test.Tasty.QuickCheck+import Tests.Helpers+import Text.Pandoc+import Text.Pandoc.Arbitrary ()++p_write_rt :: Pandoc -> Bool+p_write_rt d =+  read (unpack $ purely (writeNative def{ writerTemplate = Just "" }) d) == d++p_write_blocks_rt :: [Block] -> Bool+p_write_blocks_rt bs =+  read (unpack $ purely (writeNative def) (Pandoc nullMeta bs)) == bs++tests :: [TestTree]+tests = [ testProperty "p_write_rt" p_write_rt+        , testProperty "p_write_blocks_rt" $ mapSize+             (\x -> if x > 3 then 3 else x) $ p_write_blocks_rt+        ]
+ test/Tests/Writers/Org.hs view
@@ -0,0 +1,25 @@+{-# LANGUAGE OverloadedStrings #-}+module Tests.Writers.Org (tests) where++import Test.Tasty+import Tests.Helpers+import Text.Pandoc+import Text.Pandoc.Arbitrary ()+import Text.Pandoc.Builder++infix 4 =:+(=:) :: (ToString a, ToPandoc a)+     => String -> (a, String) -> TestTree+(=:) = test (purely (writeOrg def . toPandoc))++tests :: [TestTree]+tests = [ testGroup "links"+          -- See http://orgmode.org/manual/Internal-links.html#Internal-links+          [ "simple link"+              =: link "/url" "" "foo"+              =?> "[[/url][foo]]"+          , "internal link to anchor"+              =: link "#my-custom-id" "" "#my-custom-id"+              =?> "[[#my-custom-id]]"+          ]+        ]
+ test/Tests/Writers/Plain.hs view
@@ -0,0 +1,21 @@+{-# LANGUAGE OverloadedStrings #-}+module Tests.Writers.Plain (tests) where++import Test.Tasty+import Tests.Helpers+import Text.Pandoc+import Text.Pandoc.Arbitrary ()+import Text.Pandoc.Builder+++infix 4 =:+(=:) :: (ToString a, ToPandoc a)+     => String -> (a, String) -> TestTree+(=:) = test (purely (writePlain def) . toPandoc)+++tests :: [TestTree]+tests = [ "strongly emphasized text to uppercase"+             =: strong "Straße"+             =?> "STRASSE"+        ]
+ test/Tests/Writers/RST.hs view
@@ -0,0 +1,107 @@+{-# LANGUAGE OverloadedStrings #-}+module Tests.Writers.RST (tests) where++import Test.Tasty+import Tests.Helpers+import Text.Pandoc+import Text.Pandoc.Arbitrary ()+import Text.Pandoc.Builder++infix 4 =:+(=:) :: (ToString a, ToPandoc a)+     => String -> (a, String) -> TestTree+(=:) = test (purely (writeRST def . toPandoc))++tests :: [TestTree]+tests = [ testGroup "rubrics"+          [ "in list item" =:+              bulletList [header 2 (text "foo")] =?>+              "-  .. rubric:: foo"+          , "in definition list item" =:+              definitionList [(text "foo", [header 2 (text "bar"),+                                            para $ text "baz"])] =?>+              unlines+              [ "foo"+              , "    .. rubric:: bar"+              , ""+              , "    baz"]+          , "in block quote" =:+              blockQuote (header 1 (text "bar")) =?>+              "    .. rubric:: bar"+          , "with id" =:+              blockQuote (headerWith ("foo",[],[]) 1 (text "bar")) =?>+              unlines+              [ "    .. rubric:: bar"+              , "       :name: foo"]+          , "with id class" =:+              blockQuote (headerWith ("foo",["baz"],[]) 1 (text "bar")) =?>+              unlines+              [ "    .. rubric:: bar"+              , "       :name: foo"+              , "       :class: baz"]+          ]+        , testGroup "headings"+          [ "normal heading" =:+              header 1 (text "foo") =?>+              unlines+              [ "foo"+              , "==="]+          -- note: heading normalization is only done in standalone mode+          , test (purely (writeRST def{ writerTemplate = Just "$body$\n" }) . toPandoc)+            "heading levels" $+              header 1 (text "Header 1") <>+              header 3 (text "Header 2") <>+              header 2 (text "Header 2") <>+              header 1 (text "Header 1") <>+              header 4 (text "Header 2") <>+              header 5 (text "Header 3") <>+              header 3 (text "Header 2") =?>+              unlines+              [ "Header 1"+              , "========"+              , ""+              , "Header 2"+              , "--------"+              , ""+              , "Header 2"+              , "--------"+              , ""+              , "Header 1"+              , "========"+              , ""+              , "Header 2"+              , "--------"+              , ""+              , "Header 3"+              , "~~~~~~~~"+              , ""+              , "Header 2"+              , "--------"]+          , test (purely (writeRST def{ writerTemplate = Just "$body$\n" }) . toPandoc)+            "minimal heading levels" $+              header 2 (text "Header 1") <>+              header 3 (text "Header 2") <>+              header 2 (text "Header 1") <>+              header 4 (text "Header 2") <>+              header 5 (text "Header 3") <>+              header 3 (text "Header 2") =?>+              unlines+              [ "Header 1"+              , "========"+              , ""+              , "Header 2"+              , "--------"+              , ""+              , "Header 1"+              , "========"+              , ""+              , "Header 2"+              , "--------"+              , ""+              , "Header 3"+              , "~~~~~~~~"+              , ""+              , "Header 2"+              , "--------"]+          ]+        ]
+ test/Tests/Writers/TEI.hs view
@@ -0,0 +1,43 @@+{-# LANGUAGE OverloadedStrings #-}+module Tests.Writers.TEI (tests) where++import Test.Tasty+import Tests.Helpers+import Text.Pandoc+import Text.Pandoc.Arbitrary ()+import Text.Pandoc.Builder++{-+  "my test" =: X =?> Y++is shorthand for++  test html "my test" $ X =?> Y++which is in turn shorthand for++  test html "my test" (X,Y)+-}++infix 4 =:+(=:) :: (ToString a, ToPandoc a)+     => String -> (a, String) -> TestTree+(=:) = test (purely (writeTEI def) . toPandoc)++tests :: [TestTree]+tests = [ testGroup "block elements"+          ["para"          =: para "Lorem ipsum cetera."+                           =?> "<p>Lorem ipsum cetera.</p>"+          ]+        , testGroup "inlines"+          [+            "Emphasis"      =:  emph ("emphasized")+                            =?> "<p><hi rendition=\"simple:italic\">emphasized</hi></p>"+           ,"SingleQuoted"  =:  singleQuoted (text "quoted material")+                            =?> "<p><quote>quoted material</quote></p>"+           ,"DoubleQuoted"  =:  doubleQuoted (text "quoted material")+                            =?> "<p><quote>quoted material</quote></p>"+           ,"NestedQuoted"  =:  doubleQuoted (singleQuoted (text "quoted material"))+                            =?> "<p><quote><quote>quoted material</quote></quote></p>"+          ]+         ]
+ test/bodybg.gif view

binary file changed (absent → 10119 bytes)

+ test/command/1166.md view
@@ -0,0 +1,48 @@+See #1166 and <http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html#simple-tables>.++```+% pandoc -f rst -t html5+=====  =====+col 1  col 2+=====  =====+1      Second column of row 1.+2      Second column of row 2.+       Second line of paragraph.+3      - Second column of row 3.++       - Second item in bullet+         list (row 3, column 2).+\      Row 4; column 1 will be empty.+=====  =====+^D+<table>+<thead>+<tr class="header">+<th>col 1</th>+<th>col 2</th>+</tr>+</thead>+<tbody>+<tr class="odd">+<td>1</td>+<td>Second column of row 1.</td>+</tr>+<tr class="even">+<td><p>2</p></td>+<td><p>Second column of row 2. Second line of paragraph.</p></td>+</tr>+<tr class="odd">+<td><p>3</p></td>+<td><ul>+<li>Second column of row 3.</li>+<li>Second item in bullet list (row 3, column 2).</li>+</ul></td>+</tr>+<tr class="even">+<td></td>+<td>Row 4; column 1 will be empty.</td>+</tr>+</tbody>+</table>+```+
+ test/command/1279.md view
@@ -0,0 +1,19 @@+```+pandoc -s -t markdown+---+author: 'John Doe[^1]'+date: 2014+title: My Article+---++[^1]: Dept. of This and That+^D+---+author: 'John Doe[^1]'+date: 2014+title: My Article+---++[^1]: Dept. of This and That+```+
+ test/command/1390.md view
@@ -0,0 +1,20 @@+```+% pandoc -f latex -t native+\newcommand\foo{+}+Testing: $\mu\foo\eta$.+^D+[Para [Str "Testing:",Space,Math InlineMath "\\mu+\\eta",Str "."]]+```++<!-- It would be nice to handle this case, but I don't+know how:++```+% pandoc -f latex -t native+\newcommand{\vecx}{a + b}+$\hat\vecx$+^D+[Para [Math InlineMath "\\hat{a+b}"]]+```+-->+
+ test/command/1592.md view
@@ -0,0 +1,49 @@+```+% pandoc -t native+[hi]{.smallcaps}+^D+[Para [SmallCaps [Str "hi"]]]+```++```+% pandoc -t native+[hi]{style="font-variant: small-caps;"}+^D+[Para [SmallCaps [Str "hi"]]]+```++```+% pandoc -t native+<span class="smallcaps">hi</span>+^D+[Para [SmallCaps [Str "hi"]]]+```++```+% pandoc -f html -t native+<p><span class="smallcaps">hi</span></p>+^D+[Para [SmallCaps [Str "hi"]]]+```++```+% pandoc -f html -t native+<p><span style="font-variant:small-caps">hi</span></p>+^D+[Para [SmallCaps [Str "hi"]]]+```++```+% pandoc -f native -t html+[Para [SmallCaps [Str "hi"]]]+^D+<p><span class="smallcaps">hi</span></p>+```++```+pandoc -f native -t markdown+[Para [SmallCaps [Str "hi"]]]+^D+[hi]{.smallcaps}+```+
+ test/command/1629.md view
@@ -0,0 +1,10 @@+```+% pandoc -t latex --listings+bla bla `a % b`++*bla bla `a % b`*+^D+bla bla \passthrough{\lstinline!a \% b!}++\emph{bla bla \passthrough{\lstinline!a \% b!}}+```
+ test/command/168.md view
@@ -0,0 +1,43 @@+```+% pandoc -t native+:::::::::: warning ::::::::::::+This is the warning!++1. list+2. another++::: {#myid .class key=val}+nested div+:::+:::::::::::::::::::::::::::::::+^D+[Div ("",["warning"],[])+ [Para [Str "This",Space,Str "is",Space,Str "the",Space,Str "warning!"]+ ,OrderedList (1,Decimal,Period)+  [[Plain [Str "list"]]+  ,[Plain [Str "another"]]]+ ,Div ("myid",["class"],[("key","val")])+  [Para [Str "nested",Space,Str "div"]]]]+```++```+% pandoc -t native+foo+:::+bar+^D+[Para [Str "foo",SoftBreak,Str ":::",SoftBreak,Str "bar"]]+```++```+% pandoc -t native+::::: Warning+Here is a paragraph.++And another.+:::::+^D+[Div ("",["Warning"],[])+ [Para [Str "Here",Space,Str "is",Space,Str "a",Space,Str "paragraph."]+ ,Para [Str "And",Space,Str "another."]]]+```
+ test/command/1710.md view
@@ -0,0 +1,91 @@+```+% pandoc -t revealjs+# Slide one++<div class="columns">+<div class="column" width="40%">+- a+- b+</div>+<div class="column" width="40%">+- c+- d+</div>+<div class="column" width="10%">+ok+</div>+</div>+^D+<section id="slide-one" class="slide level1">+<h1>Slide one</h1>+<div class="columns">+<div class="column" width="40%" style="width:40%;min-width:40%;vertical-align:top;">+<ul>+<li>a</li>+<li>b</li>+</ul>+</div>+<div class="column" width="40%" style="width:40%;min-width:40%;vertical-align:top;">+<ul>+<li>c</li>+<li>d</li>+</ul>+</div>+<div class="column" width="10%" style="width:10%;min-width:10%;vertical-align:top;">+<p>ok</p>+</div>+</div>+</section>+```++```+% pandoc -t beamer+# Slide one++<div class="columns">+<div class="column" width="40%">+- a+- b+</div>+<div class="column" width="40%">+- c+- d+</div>+<div class="column" width="10%">+ok+</div>+</div>+^D+\begin{frame}{%+\protect\hypertarget{slide-one}{%+Slide one}}++\begin{columns}[T]+\begin{column}{0.40\textwidth}+\begin{itemize}+\tightlist+\item+  a+\item+  b+\end{itemize}+\end{column}++\begin{column}{0.40\textwidth}+\begin{itemize}+\tightlist+\item+  c+\item+  d+\end{itemize}+\end{column}++\begin{column}{0.10\textwidth}+ok+\end{column}+\end{columns}++\end{frame}+```+
+ test/command/1718.md view
@@ -0,0 +1,11 @@+```+% pandoc -t native+Note[^1].++[^1]: the first note.++[^2]: the second, unused, note.+^D+[WARNING] Note with key '2' defined at line 5 column 1 but not used.+[Para [Str "Note",Note [Para [Str "the",Space,Str "first",Space,Str "note."]],Str "."]]+```
+ test/command/1745.md view
@@ -0,0 +1,13 @@+```+% pandoc -f latex+auto_identifiers -t html+\section{Six favourite beers}+\subsection{Jovaru Alus}\label{jovaru-alus}+\section{Farmhouse brewers}+\subsection{Jovaru Alus}+^D+<h1 id="six-favourite-beers">Six favourite beers</h1>+<h2 id="jovaru-alus">Jovaru Alus</h2>+<h1 id="farmhouse-brewers">Farmhouse brewers</h1>+<h2 id="jovaru-alus-1">Jovaru Alus</h2>+```+
+ test/command/1773.md view
@@ -0,0 +1,6 @@+```+% pandoc -f latex+raw_tex -t native+\noindent hi+^D+[Para [RawInline (Format "latex") "\\noindent ",Str "hi"]]+```
+ test/command/1841.md view
@@ -0,0 +1,42 @@+```+% pandoc+<table>+<tr>+<td>    *one*</td>+<td>    [a link](http://google.com)</td>+</tr>+</table>+^D+<table>+<tr>+<td>+<em>one</em>+</td>+<td>+<a href="http://google.com">a link</a>+</td>+</tr>+</table>+```++```+% pandoc+<table>+    <tr>+        <td>*one*</td>+        <td>[a link](http://google.com)</td>+    </tr>+</table>+^D+<table>+<tr>+<td>+<em>one</em>+</td>+<td>+<a href="http://google.com">a link</a>+</td>+</tr>+</table>+```+
+ test/command/1881.md view
@@ -0,0 +1,55 @@+```+% pandoc -f html -t native+<table>+<caption>Demonstration of simple table syntax.</caption>+<thead>+<tr class="header">+<th align="right">Right</th>+<th align="left">Left</th>+<th align="center">Center</th>+<th>Default</th>+</tr>+</thead>+<tbody>+<tr class="odd">+<td align="right">12</td>+<td align="left">12</td>+<td align="center">12</td>+<td>12</td>+</tr>+</tbody>+</table>+^D+[Table [Str "Demonstration",Space,Str "of",Space,Str "simple",Space,Str "table",Space,Str "syntax."] [AlignRight,AlignLeft,AlignCenter,AlignDefault] [0.0,0.0,0.0,0.0]+ [[Plain [Str "Right"]]+ ,[Plain [Str "Left"]]+ ,[Plain [Str "Center"]]+ ,[Plain [Str "Default"]]]+ [[[Plain [Str "12"]]+  ,[Plain [Str "12"]]+  ,[Plain [Str "12"]]+  ,[Plain [Str "12"]]]]]+```++```+% pandoc -f html -t native+<table>+<tr class="odd">+<td style="text-align: right;">12</td>+<td style="text-align:left;">12</td>+<td style="text-align:  center">12</td>+<td style="text-align: right;">12</td>+</tr>+</table>+^D+[Table [] [AlignRight,AlignLeft,AlignCenter,AlignRight] [0.0,0.0,0.0,0.0]+ [[]+ ,[]+ ,[]+ ,[]]+ [[[Plain [Str "12"]]+  ,[Plain [Str "12"]]+  ,[Plain [Str "12"]]+  ,[Plain [Str "12"]]]]]+```+
+ test/command/1905.md view
@@ -0,0 +1,30 @@+```+% pandoc -f latex-auto_identifiers -t html+\chapter{chapone}+\part{partone}+\chapter{chaptwo}+\section{secone}+^D+<h2>chapone</h2>+<h1>partone</h1>+<h2>chaptwo</h2>+<h3>secone</h3>+```++```+% pandoc -f latex-auto_identifiers -t html+\chapter{chapone}+\chapter{chaptwo}+\section{secone}+^D+<h1>chapone</h1>+<h1>chaptwo</h1>+<h2>secone</h2>+```++```+% pandoc -f latex-auto_identifiers -t html+\section{secone}+^D+<h1>secone</h1>+```
+ test/command/2118.md view
@@ -0,0 +1,11 @@+```+% pandoc -f latex -t native+\newcommand{\inclgraph}{\includegraphics[width=0.8\textwidth]}+\begin{figure}[ht]+  \inclgraph{setminus.png}+  \caption{Set subtraction}+  \label{fig:setminus}+\end{figure}+^D+[Para [Image ("",[],[("width","80%")]) [Str "Set",Space,Str "subtraction",Span ("",[],[("label","fig:setminus")]) []] ("setminus.png","fig:")]]+```
+ test/command/2228.md view
@@ -0,0 +1,6 @@+```+% pandoc -f markdown+smart -t latex+smart+*foo*'s 'foo'+^D+\emph{foo}'s `foo'+```
+ test/command/2378.md view
@@ -0,0 +1,27 @@+Ensure that we don't get duplicated footnotes when+a note occurs in a header cell and `\endfirsthead`+is used.++```+% pandoc -t latex+| x | y[^fn] |+|-|-|+|1|2|+: a table++[^fn]: a footnote+^D+\begin{longtable}[]{@{}ll@{}}+\caption{a table}\tabularnewline+\toprule+x & y\footnote{a footnote}\tabularnewline+\midrule+\endfirsthead+\toprule+x & y{}\tabularnewline+\midrule+\endhead+1 & 2\tabularnewline+\bottomrule+\end{longtable}+```
+ test/command/2397.md view
@@ -0,0 +1,9 @@+```+% pandoc -f markdown_mmd+# Chapter 1: A long name of chapter [Chapter 1]++See [Chapter 1].+^D+<h1 id="chapter1">Chapter 1: A long name of chapter</h1>+<p>See <a href="#chapter1">Chapter 1</a>.</p>+```
+ test/command/2434.md view
@@ -0,0 +1,59 @@+```+% pandoc -t opendocument+1. a+2. b+    1. alpha+    2. beta+    * gamma+^D+<text:list text:style-name="L1">+  <text:list-item>+    <text:p text:style-name="P1">a</text:p>+  </text:list-item>+  <text:list-item>+    <text:p text:style-name="P1">b</text:p>+    <text:list>+      <text:list-item>+        <text:p text:style-name="P1">alpha</text:p>+      </text:list-item>+      <text:list-item>+        <text:p text:style-name="P1">beta</text:p>+      </text:list-item>+    </text:list>+    <text:list text:style-name="L2">+      <text:list-item>+        <text:p text:style-name="P2">gamma</text:p>+      </text:list-item>+    </text:list>+  </text:list-item>+</text:list>+```++```+% pandoc -t opendocument+(@) text++    some text++    a) sub item 1+    b) sub item 2++    more text -- this line is missing in the odt output+^D+<text:list text:style-name="L1">+  <text:list-item>+    <text:p text:style-name="P1">text</text:p>+    <text:p text:style-name="P1">some text</text:p>+    <text:list>+      <text:list-item>+        <text:p text:style-name="P1">sub item 1</text:p>+      </text:list-item>+      <text:list-item>+        <text:p text:style-name="P1">sub item 2</text:p>+      </text:list-item>+    </text:list>+    <text:p text:style-name="P1">more text – this line is missing in the+    odt output</text:p>+  </text:list-item>+</text:list>+```
+ test/command/2549.md view
@@ -0,0 +1,38 @@+```+% pandoc -f latex -t native+\hypertarget{foo}{%+\section{A section}\label{foo}+}+^D+[Header 1 ("foo",[],[]) [Str "A",Space,Str "section"]]+```++```+% pandoc -f latex -t native+\hypertarget{bar}{%+\section{A section}\label{foo}+}+^D+[Div ("bar",[],[])+ [Header 1 ("foo",[],[]) [Str "A",Space,Str "section"]]]+```++```+% pandoc -f latex -t native+Bar \hypertarget{foo}{Foo}+^D+[Para [Str "Bar",Space,Span ("foo",[],[]) [Str "Foo"]]]+```++```+% pandoc -f latex -t native+\hypertarget{foo}{%+\begin{verbatim}+bar+\end{verbatim}+}+^D+[Div ("foo",[],[])+ [CodeBlock ("",[],[]) "bar"]]+```+
+ test/command/2552.md view
@@ -0,0 +1,14 @@+```+% pandoc --strip-comments+Foo++bar++<!-- comment -->++baz<!-- bim -->boop+^D+<p>Foo</p>+<p>bar</p>+<p>bazboop</p>+```
+ test/command/256.md view
@@ -0,0 +1,12 @@+```+% pandoc --abbreviations=command/abbrevs -t native+Foo. bar baz h.k. and e.g. and Mr. Brown.+^D+[Para [Str "Foo.\160bar",Space,Str "baz",Space,Str "h.k.\160and",Space,Str "e.g.",Space,Str "and",Space,Str "Mr.",Space,Str "Brown."]]+```+```+% pandoc -t native+Foo. bar baz h.k. and e.g. and Mr. Brown.+^D+[Para [Str "Foo.",Space,Str "bar",Space,Str "baz",Space,Str "h.k.",Space,Str "and",Space,Str "e.g.\160and",Space,Str "Mr.\160Brown."]]+```
+ test/command/2602.md view
@@ -0,0 +1,18 @@+```+% pandoc+[a] [b]++[b]: url+^D+<p>[a] <a href="url">b</a></p>+```++```+% pandoc -f markdown+spaced_reference_links+[a] [b]++[b]: url+^D+<p><a href="url">a</a></p>+```+
+ test/command/2606.md view
@@ -0,0 +1,58 @@+```+% pandoc -f mediawiki -t html5+{|+| * hello+|}+^D+<table>+<tbody>+<tr class="odd">+<td><p>* hello</p></td>+</tr>+</tbody>+</table>+```++```+% pandoc -f mediawiki -t html5+{|+|+* hello+|}+^D+<table>+<tbody>+<tr class="odd">+<td><ul>+<li>hello</li>+</ul></td>+</tr>+</tbody>+</table>+```++```+% pandoc -f mediawiki -t html5+{|+|+ * hello+|}+^D+<table>+<tbody>+<tr class="odd">+<td><p><code>* hello</code></p></td>+</tr>+</tbody>+</table>+```++```+% pandoc -f mediawiki -t html5+* * hi+^D+<ul>+<li>* hi</li>+</ul>+```+
+ test/command/262.md view
@@ -0,0 +1,26 @@+```+% pandoc -f rst+`hello`_ and `goodbye`_++.. _hello:+.. _goodbye: example.com+^D+<p><a href="example.com">hello</a> and <a href="example.com">goodbye</a></p>+```++```+% pandoc -f rst+`hello`_ `goodbye`_++.. _hello:+.. _goodbye:++paragraph+^D+<p><a href="#hello">hello</a> <a href="#goodbye">goodbye</a></p>+<div id="hello">+<div id="goodbye">+<p>paragraph</p>+</div>+</div>+```
+ test/command/2649.md view
@@ -0,0 +1,109 @@+```+% pandoc -f mediawiki -t html5+{| class="wikitable" style="line-height: 1.0"++|- bgcolor="#efefef"+|}+^D+<table>+<tbody>+<tr class="odd">+</tr>+</tbody>+</table>+```++```+% pandoc -f mediawiki -t html5+{| border="4" cellspacing="2" cellpadding="0" WIDTH="100%"+|-----+| peildatum Simbase || november 2005 || '''uitslagen Flohrgambiet''' ||+|-----+| totaal aantal partijen Simbase || 7.316.773+| wit wint || 53%+|-----+| percentage (en partijen) Flohrgambiet+| 0.023 % (1.699) || zwart wint || 27%+|-----+| percentage Flohrgambiet in aug 2003+| 0.035 % || remise || 20%+|}+^D+<table>+<tbody>+<tr class="odd">+<td><p>peildatum Simbase</p></td>+<td><p>november 2005</p></td>+<td><p><strong>uitslagen Flohrgambiet</strong></p></td>+<td></td>+</tr>+<tr class="even">+<td><p>totaal aantal partijen Simbase</p></td>+<td><p>7.316.773</p></td>+<td><p>wit wint</p></td>+<td><p>53%</p></td>+</tr>+<tr class="odd">+<td><p>percentage (en partijen) Flohrgambiet</p></td>+<td><p>0.023 % (1.699)</p></td>+<td><p>zwart wint</p></td>+<td><p>27%</p></td>+</tr>+<tr class="even">+<td><p>percentage Flohrgambiet in aug 2003</p></td>+<td><p>0.035 %</p></td>+<td><p>remise</p></td>+<td><p>20%</p></td>+</tr>+</tbody>+</table>+```++```+% pandoc -f mediawiki -t html5+{| class="wikitable" style="text-align:center; font-size:95%" valign="top" |+! Plaats+! Rijder+! Aantal+|-+| 1+|align=left| {{FR-VLAG}} [[Sébastien Loeb]] | 78+|-+| 2+|align=left| {{FR-VLAG}} '''[[Sébastien Ogier]]'''+| 38+|-+| 10+|align=left| {{FI-VLAG}} [[Hannu Mikkola]]+| 18+|}+^D+<table>+<tbody>+<tr class="odd">+<td></td>+<td><p>Plaats</p></td>+<td><p>Rijder</p></td>+<td><p>Aantal</p></td>+</tr>+<tr class="even">+<td><p>1</p></td>+<td>+<p><a href="Sébastien_Loeb" title="wikilink">Sébastien Loeb</a></p></td>+<td><p>78</p></td>+</tr>+<tr class="odd">+<td><p>2</p></td>+<td>+<p><strong><a href="Sébastien_Ogier" title="wikilink">Sébastien Ogier</a></strong></p></td>+<td><p>38</p></td>+</tr>+<tr class="even">+<td><p>10</p></td>+<td>+<p><a href="Hannu_Mikkola" title="wikilink">Hannu Mikkola</a></p></td>+<td><p>18</p></td>+</tr>+</tbody>+</table>+```
+ test/command/2662.md view
@@ -0,0 +1,11 @@+```+% pandoc -t html -f rst --wrap=none+.. image:: http://url.to.image/foo.png+   :align: left+   :height: 100px+   :width: 200 px+   :scale: 300 %+   :alt: alternate text+^D+<p><img src="http://url.to.image/foo.png" alt="alternate text" class="align-left" width="600" height="300" /></p>+```
+ test/command/2834.md view
@@ -0,0 +1,29 @@+Nested grid tables.+```+% pandoc -f html -t markdown --columns=72+<table>+  <tr>+    <td>+      <table>+        <tr>+          <td>+            <table>+              <tr>+                <td>some text</td>+              </tr>+            </table>+          </td>+        </tr>+      </table>+    </td>+  </tr>+</table>+^D++-----------------------------------------------------------------------++| +------------------------------------------------------------------+  |+| |   -----------                                                    |  |+| |   some text                                                      |  |+| |   -----------                                                    |  |+| +------------------------------------------------------------------+  |++-----------------------------------------------------------------------++```
+ test/command/2874.md view
@@ -0,0 +1,14 @@+```+% pandoc -f html -t latex+<a></a>+<br/>+^D+{}~\\+```++```+% pandoc -f html -t latex+<a name="foo"></a><br/>+^D+\protect\hypertarget{foo}{}{}~\\+```
+ test/command/2994.md view
@@ -0,0 +1,10 @@+```+% pandoc -f markdown -t docx -o - | pandoc -f docx -t markdown --track-changes=all+I want [I left a comment.]{.comment-start id="0"+author="Jesse Rosenthal" date="2016-05-09T16:13:00Z"}some text to have a+comment []{.comment-end id="0"}on it.+^D+I want [I left a comment.]{.comment-start id="0"+author="Jesse Rosenthal" date="2016-05-09T16:13:00Z"}some text to have a+comment []{.comment-end id="0"}on it.+```
+ test/command/3113.md view
@@ -0,0 +1,13 @@+```+% pandoc -f latex -t native+\begin{eqnarray}+A&=&B,\\+C&=&D,\\+%\end{eqnarray}+%\begin{eqnarray}+E&=&F+\end{eqnarray}+^D+[Para [Math DisplayMath "\\begin{aligned}\nA&=&B,\\\\\nC&=&D,\\\\\n%\\end{eqnarray}\n%\\begin{eqnarray}\nE&=&F\\end{aligned}"]]+```+
+ test/command/3236.md view
@@ -0,0 +1,9 @@+```+pandoc -f latex -t native+\newcommand{\mycolor}{red}++\includegraphics[width=17cm]{\mycolor /header}+Magnificent \mycolor{} header.+^D+[Para [Image ("",[],[("width","17cm")]) [Str "image"] ("red/header",""),SoftBreak,Str "Magnificent",Space,Str "red",Space,Str "header."]]+```
+ test/command/3257.md view
@@ -0,0 +1,13 @@+```+% pandoc -t native+(i<j)+^D+[Para [Str "(i<j)"]]+```++```+% pandoc -t native+i<j-1, j>k+^D+[Para [Str "i<j-1,",Space,Str "j>k"]]+```
+ test/command/3309.md view
@@ -0,0 +1,52 @@+Certain environments should be treated as inline unless they+are surrounded by blank lines:++```+% pandoc -t latex --wrap=preserve+Lorem ipsum dolor sit amet,++\begin{equation}+E = mc^2,+\end{equation}++consectetur adipiscing elit.+^D+Lorem ipsum dolor sit amet,++\begin{equation}+E = mc^2,+\end{equation}++consectetur adipiscing elit.+```++```+% pandoc -t latex --wrap=preserve+Lorem ipsum dolor sit amet,+\begin{equation}+E = mc^2,+\end{equation}+consectetur adipiscing elit.+^D+Lorem ipsum dolor sit amet,+\begin{equation}+E = mc^2,+\end{equation}+consectetur adipiscing elit.+```++```+% pandoc -t latex --wrap=preserve+The formula+\begin{math}+x = y+\end{math}+should be inline.+^D+The formula+\begin{math}+x = y+\end{math}+should be inline.+```+
+ test/command/3314.md view
@@ -0,0 +1,34 @@+See #3315 and <http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html#simple-tables>.++```+% pandoc -f org -t html5++-----------+-------+----------++| First     | 12.0  | Example  |+|           |       | row      |+|           |       | spanning |+|           |       | lines    |++-----------+-------+----------++| Second    | 5.0   | Another  |++-----------+-------+----------++^D+<table style="width:43%;">+<colgroup>+<col style="width: 16%" />+<col style="width: 11%" />+<col style="width: 15%" />+</colgroup>+<tbody>+<tr class="odd">+<td>First</td>+<td>12.0</td>+<td>Example row spanning lines</td>+</tr>+<tr class="even">+<td>Second</td>+<td>5.0</td>+<td>Another</td>+</tr>+</tbody>+</table>+```+
+ test/command/3337.md view
@@ -0,0 +1,13 @@+```+% pandoc -f html -t markdown+<table>+<tr><td>a</td></tr>+<tr><td>1</td><td>2</td></tr>+</table>+^D+  --- ---+  a   +  1   2+  --- ---+```+
+ test/command/3348.md view
@@ -0,0 +1,17 @@+```+% pandoc -t native --columns=72+  ----- ------------------------------------------------+    foo bar++    foo this is a long+        line of text+  ----- ------------------------------------------------+^D+[Table [] [AlignRight,AlignLeft] [8.333333333333333e-2,0.6666666666666666]+ [[]+ ,[]]+ [[[Plain [Str "foo"]]+  ,[Plain [Str "bar"]]]+ ,[[Plain [Str "foo"]]+  ,[Plain [Str "this",Space,Str "is",Space,Str "a",Space,Str "long",SoftBreak,Str "line",Space,Str "of",Space,Str "text"]]]]]+```
+ test/command/3401.md view
@@ -0,0 +1,19 @@+See #3401 and <http://orgmode.org/manual/Macro-replacement.html>++```+% pandoc -f org -t native+#+MACRO: HELLO /Hello, $1/+{{{HELLO(World)}}}+^D+[Para [Emph [Str "Hello,",Space,Str "World"]]]+```++Inverted argument order++```+% pandoc -f org -t native+#+MACRO: A $2,$1+{{{A(1,2)}}}+^D+[Para [Str "2,1"]]+```
+ test/command/3407.md view
@@ -0,0 +1,13 @@+```+% pandoc -f native -t rst+[Para [Span ("",[],[("role","foo")]) [Str "text"]]]+^D+:foo:`text`+```++```+% pandoc -f rst -t native+:foo:`text`+^D+[Para [Span ("",[],[("role","foo")]) [Str "text"]]]+```
+ test/command/3422.md view
@@ -0,0 +1,9 @@+See #3422++```+% pandoc -t latex --listings+`int main(int argc, const char *argv[]);`{.c}+^D+\passthrough{\lstinline[language=C]!int main(int argc, const char *argv[]);!}+```+
+ test/command/3432.md view
@@ -0,0 +1,289 @@+List-table with header-rows and widths options. ++```+% pandoc -f rst+.. list-table:: Frozen Delights!+   :widths: 15 10 30+   :header-rows: 1++   * - Treat+     - Quantity+     - Description+   * - Albatross+     - 2.99+     - On a stick!+   * - Crunchy Frog+     - 1.49+     - If we took the bones out, it wouldn't be+       crunchy, now would it?+   * - Gannet Ripple+     - 1.99+     - On a stick!+^D+<table>+<caption>Frozen Delights!</caption>+<colgroup>+<col style="width: 27%" />+<col style="width: 18%" />+<col style="width: 54%" />+</colgroup>+<thead>+<tr class="header">+<th>Treat</th>+<th>Quantity</th>+<th>Description</th>+</tr>+</thead>+<tbody>+<tr class="odd">+<td>Albatross</td>+<td>2.99</td>+<td>On a stick!</td>+</tr>+<tr class="even">+<td>Crunchy Frog</td>+<td>1.49</td>+<td>If we took the bones out, it wouldn't be crunchy, now would it?</td>+</tr>+<tr class="odd">+<td>Gannet Ripple</td>+<td>1.99</td>+<td>On a stick!</td>+</tr>+</tbody>+</table>+```++List-table whose widths is "auto". ++```+% pandoc -f rst+.. list-table:: Frozen Delights!+   :header-rows: 1+   :widths: auto++   * - Treat+     - Quantity+     - Description+   * - Albatross+     - 2.99+     - On a stick!+   * - Crunchy Frog+     - 1.49+     - If we took the bones out, it wouldn't be+       crunchy, now would it?+   * - Gannet Ripple+     - 1.99+     - On a stick!+^D+<table>+<caption>Frozen Delights!</caption>+<thead>+<tr class="header">+<th>Treat</th>+<th>Quantity</th>+<th>Description</th>+</tr>+</thead>+<tbody>+<tr class="odd">+<td>Albatross</td>+<td>2.99</td>+<td>On a stick!</td>+</tr>+<tr class="even">+<td>Crunchy Frog</td>+<td>1.49</td>+<td>If we took the bones out, it wouldn't be crunchy, now would it?</td>+</tr>+<tr class="odd">+<td>Gannet Ripple</td>+<td>1.99</td>+<td>On a stick!</td>+</tr>+</tbody>+</table>+```+++List-table with header-rows which is bigger than 1. Only the first row is treated as a header. ++```+% pandoc -f rst+.. list-table:: Frozen Delights!+   :header-rows: 2++   * - Treat+     - Quantity+     - Description+   * - Albatross+     - 2.99+     - On a stick!+   * - Crunchy Frog+     - 1.49+     - If we took the bones out, it wouldn't be+       crunchy, now would it?+   * - Gannet Ripple+     - 1.99+     - On a stick!+^D+<table>+<caption>Frozen Delights!</caption>+<thead>+<tr class="header">+<th>Treat</th>+<th>Quantity</th>+<th>Description</th>+</tr>+</thead>+<tbody>+<tr class="odd">+<td>Albatross</td>+<td>2.99</td>+<td>On a stick!</td>+</tr>+<tr class="even">+<td>Crunchy Frog</td>+<td>1.49</td>+<td>If we took the bones out, it wouldn't be crunchy, now would it?</td>+</tr>+<tr class="odd">+<td>Gannet Ripple</td>+<td>1.99</td>+<td>On a stick!</td>+</tr>+</tbody>+</table>+```++List-table without header-rows.++```+% pandoc -f rst+.. list-table:: Frozen Delights!++   * - Albatross+     - 2.99+     - On a stick!+   * - Crunchy Frog+     - 1.49+     - If we took the bones out, it wouldn't be+       crunchy, now would it?+   * - Gannet Ripple+     - 1.99+     - On a stick!+^D+<table>+<caption>Frozen Delights!</caption>+<tbody>+<tr class="odd">+<td>Albatross</td>+<td>2.99</td>+<td>On a stick!</td>+</tr>+<tr class="even">+<td>Crunchy Frog</td>+<td>1.49</td>+<td>If we took the bones out, it wouldn't be crunchy, now would it?</td>+</tr>+<tr class="odd">+<td>Gannet Ripple</td>+<td>1.99</td>+<td>On a stick!</td>+</tr>+</tbody>+</table>+```++List-table with empty cells. You need a space after '-', otherwise the row will disapear. Parser for Bulletlists causes this ristriction. ++```+% pandoc -f rst+.. list-table:: Frozen Delights!+   :header-rows: 2++   * - Treat+     - Quantity+     - Description+   * - Albatross+     - 2.99+     - +   * - Crunchy Frog+     - +     - If we took the bones out, it wouldn't be+       crunchy, now would it?+   * - Gannet Ripple+     - 1.99+     - On a stick!+^D+<table>+<caption>Frozen Delights!</caption>+<thead>+<tr class="header">+<th>Treat</th>+<th>Quantity</th>+<th>Description</th>+</tr>+</thead>+<tbody>+<tr class="odd">+<td>Albatross</td>+<td>2.99</td>+<td></td>+</tr>+<tr class="even">+<td>Crunchy Frog</td>+<td></td>+<td>If we took the bones out, it wouldn't be crunchy, now would it?</td>+</tr>+<tr class="odd">+<td>Gannet Ripple</td>+<td>1.99</td>+<td>On a stick!</td>+</tr>+</tbody>+</table>+```++List-table with a cell having a bulletlist++```+% pandoc -f rst+.. list-table:: Frozen Delights!++   * - Albatross+     - 2.99+     - + On a stick!+       + In a cup!+   * - Crunchy Frog+     - 1.49+     - If we took the bones out, it wouldn't be+       crunchy, now would it?+   * - Gannet Ripple+     - 1.99+     - On a stick!+^D+<table>+<caption>Frozen Delights!</caption>+<tbody>+<tr class="odd">+<td>Albatross</td>+<td>2.99</td>+<td><ul>+<li>On a stick!</li>+<li>In a cup!</li>+</ul></td>+</tr>+<tr class="even">+<td>Crunchy Frog</td>+<td>1.49</td>+<td>If we took the bones out, it wouldn't be crunchy, now would it?</td>+</tr>+<tr class="odd">+<td>Gannet Ripple</td>+<td>1.99</td>+<td>On a stick!</td>+</tr>+</tbody>+</table>+```
+ test/command/3432a.md view
@@ -0,0 +1,19 @@+```+% pandoc -f rst+* - a+  - b+* - c+  - d+^D+<ul>+<li><ul>+<li>a</li>+<li>b</li>+</ul></li>+<li><ul>+<li>c</li>+<li>d</li>+</ul></li>+</ul>+```+
+ test/command/3450.md view
@@ -0,0 +1,12 @@+```+% pandoc -fmarkdown-implicit_figures+![image](lalune.jpg){height=2em}+^D+<p><img src="lalune.jpg" alt="image" style="height:2em" /></p>+```+```+% pandoc -fmarkdown-implicit_figures -t latex+![image](lalune.jpg){height=2em}+^D+\includegraphics[height=2em]{lalune.jpg}+```
+ test/command/3475.md view
@@ -0,0 +1,45 @@+RST implicit internal links to headers:++```+pandoc -f rst+Years+-----++Years_+^D+<h1 id="years">Years</h1>+<p><a href="#years">Years</a></p>+```++```+pandoc -f rst+Years_++Years+-----+^D+<p><a href="#years">Years</a></p>+<h1 id="years">Years</h1>+```++```+pandoc -f rst+Years and years+---------------++`Years and years`_+^D+<h1 id="years-and-years">Years and years</h1>+<p><a href="#years-and-years">Years and years</a></p>+```++```+pandoc -f rst+Years and *years*+-----------------++`Years and years`_+^D+<h1 id="years-and-years">Years and <em>years</em></h1>+<p><a href="#years-and-years">Years and years</a></p>+```
+ test/command/3487.md view
@@ -0,0 +1,11 @@+```+% pandoc -f html -t markdown+Some text+<ul>+<li>element</li>+</ul>+^D+Some text++-   element+```
+ test/command/3494.md view
@@ -0,0 +1,41 @@+```+% pandoc -f latex --quiet+\begin{table}[h!]+\begin{tabular}{r|l|l}++  {\large \textbf{ﺍ}} && \\+  \textbf{ﺄﺤﺴﻨﺘـ(ﻭﺍ) IV} & \em{ʾaḥsant(ū)} & thank you \\+  \newpage+  \emph{blah} & \emph{blah} & \emph{blah} \\+  blah & blah & blah \\++\end{tabular}+\end{table}+^D+<table>+<tbody>+<tr class="odd">+<td style="text-align: right;"><span><strong>ﺍ</strong></span></td>+<td style="text-align: left;"></td>+<td style="text-align: left;"></td>+</tr>+<tr class="even">+<td style="text-align: right;"><strong>ﺄﺤﺴﻨﺘـ(ﻭﺍ) IV</strong></td>+<td style="text-align: left;"><em><span>ʾaḥsant(ū)</span></em></td>+<td style="text-align: left;">thank you</td>+</tr>+<tr class="odd">+<td style="text-align: right;">+<p><em>blah</em></p></td>+<td style="text-align: left;"><em>blah</em></td>+<td style="text-align: left;"><em>blah</em></td>+</tr>+<tr class="even">+<td style="text-align: right;">blah</td>+<td style="text-align: left;">blah</td>+<td style="text-align: left;">blah</td>+</tr>+</tbody>+</table>+```+
+ test/command/3497.md view
@@ -0,0 +1,51 @@+Escape list markers at beginning of paragraph:++```+% pandoc -t markdown+\* ok++\+ ok++\- ok++1\. ok++a\. ok+^D+\* ok++\+ ok++\- ok++1\. ok++a\. ok+```++Here we don't need to escape because there's no space:++```+% pandoc -t markdown+\+ok++\-ok++1.ok+^D++ok++-ok++1.ok+```++Also escape things that might become line blocks or tables:++```+% pandoc -t markdown+\| hi \|+^D+\| hi \|+```+
+ test/command/3499.md view
@@ -0,0 +1,18 @@+Org-mode tables can't be on the same line as list markers:+```+% pandoc -f org+- |something|+- +  |else|+^D+<ul>+<li>|something|</li>+<li><table>+<tbody>+<tr class="odd">+<td>else</td>+</tr>+</tbody>+</table></li>+</ul>+```
+ test/command/3510-export.latex view
@@ -0,0 +1,1 @@+\emph{Hello}
+ test/command/3510-src.hs view
@@ -0,0 +1,1 @@+putStrLn outString
+ test/command/3510-subdoc.org view
@@ -0,0 +1,5 @@+* Subsection++Included text++Lorem ipsum.
+ test/command/3510.md view
@@ -0,0 +1,20 @@+See <http://orgmode.org/manual/Include-files.html>+```+% pandoc -f org -t native+Text++#+include: "command/3510-subdoc.org"++#+INCLUDE: "command/3510-src.hs" src haskell+#+INCLUDE: "command/3510-export.latex" export latex++More text+^D+[Para [Str "Text"]+,Header 1 ("subsection",[],[]) [Str "Subsection"]+,Para [Str "Included",Space,Str "text"]+,Plain [Str "Lorem",Space,Str "ipsum."]+,CodeBlock ("",["haskell"],[]) "putStrLn outString\n"+,RawBlock (Format "latex") "\\emph{Hello}"+,Para [Str "More",Space,Str "text"]]+```
+ test/command/3511.md view
@@ -0,0 +1,46 @@+```+% pandoc -t native+- a+  - b+    - c++-     code++1000. one++    not continuation+^D+[BulletList+ [[Plain [Str "a"]+  ,BulletList+   [[Plain [Str "b"]+    ,BulletList+     [[Plain [Str "c"]]]]]]+ ,[CodeBlock ("",[],[]) "code"]]+,OrderedList (1000,Decimal,Period)+ [[Plain [Str "one"]]]+,CodeBlock ("",[],[]) "not continuation"]+```++```+% pandoc -t native -f markdown+four_space_rule+- a+  - b+    - c++-     not code++1000. one++    continuation+^D+[BulletList+ [[Plain [Str "a"]]+ ,[Plain [Str "b"]+  ,BulletList+   [[Plain [Str "c"]]]]+ ,[CodeBlock ("",[],[]) "not code"]]+,OrderedList (1000,Decimal,Period)+ [[Para [Str "one"]+  ,Para [Str "continuation"]]]]+```
+ test/command/3512.md view
@@ -0,0 +1,13 @@+```+% pandoc -f markdown-auto_identifiers+#hi+^D+<p>#hi</p>+```++```+% pandoc -f markdown-auto_identifiers-space_in_atx_header+#hi+^D+<h1>hi</h1>+```
+ test/command/3516.md view
@@ -0,0 +1,51 @@+Correctly handle empty row:+```+% pandoc -f markdown -t rst++---+---++| 1 | 2 |++---+---++|   |   |++---+---++^D++---+---++| 1 | 2 |++---+---++|   |   |++---+---++```++Temporarily added these to figure out what is happening+on Windows builds.+```+% pandoc -f markdown -t native++---+---++| 1 | 2 |++---+---++|   |   |++---+---++^D+[Table [] [AlignDefault,AlignDefault] [5.555555555555555e-2,5.555555555555555e-2]+ [[]+ ,[]]+ [[[Plain [Str "1"]]+  ,[Plain [Str "2"]]]+ ,[[]+  ,[]]]]+```++```+% pandoc -f native -t rst+[Table [] [AlignDefault,AlignDefault] [5.555555555555555e-2,5.555555555555555e-2]+ [[]+ ,[]]+ [[[Para [Str "1"]]+  ,[Para [Str "2"]]]+ ,[[]+  ,[]]]]+^D++---+---++| 1 | 2 |++---+---++|   |   |++---+---++```
+ test/command/3518.md view
@@ -0,0 +1,6 @@+```+pandoc -f latex -t plain+$\alpha^2 \cdot \alpha^{2+3} \equiv \alpha^7$+^D+α² ⋅ α² ⁺ ³ ≡ α⁷+```
+ test/command/3526.md view
@@ -0,0 +1,14 @@+```+% pandoc -t rst++--+---++|  |   |++--+---++|  |   |++--+---++^D++---+---++|   |   |++---+---++|   |   |++---+---++```
+ test/command/3529.md view
@@ -0,0 +1,15 @@+```+% pandoc -t markdown-simple_tables-pipe_tables-grid_tables+multiline_tables+A  B+-- --+7  8+9  10+^D+  --------+  A   B+  --- ----+  7   8++  9   10+  --------+```
+ test/command/3530.md view
@@ -0,0 +1,22 @@+```+% pandoc -f latex -t native+\subfile{command/sub-file-chapter-1}+\subfile{command/sub-file-chapter-2}+^D+[Header 1 ("chapter-1",[],[]) [Str "Chapter",Space,Str "1"]+,Para [Str "This",Space,Str "is",Space,Str "Chapter",Space,Str "1,",Space,Str "provided",Space,Str "in",Space,Str "a",Space,Str "sub",Space,Str "file."]+,Header 1 ("chapter-2",[],[]) [Str "Chapter",Space,Str "2"]+,Para [Str "This",Space,Str "is",Space,Str "Chapter",Space,Str "2,",Space,Str "provided",Space,Str "in",Space,Str "a",Space,Str "second",Space,Str "sub",Space,Str "file."]]+```++```+% pandoc -flatex+raw_tex -t native+\subfile{command/sub-file-chapter-1}+\subfile{command/sub-file-chapter-2}+^D+[Header 1 ("chapter-1",[],[]) [Str "Chapter",Space,Str "1"]+,Para [Str "This",Space,Str "is",Space,Str "Chapter",Space,Str "1,",Space,Str "provided",Space,Str "in",Space,Str "a",Space,Str "sub",Space,Str "file."]+,Header 1 ("chapter-2",[],[]) [Str "Chapter",Space,Str "2"]+,Para [Str "This",Space,Str "is",Space,Str "Chapter",Space,Str "2,",Space,Str "provided",Space,Str "in",Space,Str "a",Space,Str "second",Space,Str "sub",Space,Str "file."]]++```
+ test/command/3531.md view
@@ -0,0 +1,21 @@+```+% pandoc -t mediawiki --wrap=preserve+* This is a list item.+* This is a list item in Markdown. It is+  continued in the next line.+    * It has a sub-item.+* This is the next list item.++A paragraph can span multiple lines+without being broken into pieces.+^D+* This is a list item.+* This is a list item in Markdown. It is continued in the next line.+** It has a sub-item.+* This is the next list item.++A paragraph can span multiple lines+without being broken into pieces.+++```
+ test/command/3533-rst-csv-tables.csv view
@@ -0,0 +1,4 @@+"Albatross", 2.99, "On a stick!"+"Crunchy Frog", 1.49, "If we took the bones out, it wouldn't be+crunchy, now would it?"+
+ test/command/3533-rst-csv-tables.md view
@@ -0,0 +1,56 @@+```+% pandoc -f rst -t native+.. csv-table:: Test+   :widths: 10, 5, 10+   :header: Flavor,Price,Slogan+   :file: command/3533-rst-csv-tables.csv+^D+[Table [Str "Test"] [AlignDefault,AlignDefault,AlignDefault] [0.4,0.2,0.4]+ [[Plain [Str "Flavor"]]+ ,[Plain [Str "Price"]]+ ,[Plain [Str "Slogan"]]]+ [[[Plain [Str "Albatross"]]+  ,[Plain [Str "2.99"]]+  ,[Plain [Str "On",Space,Str "a",Space,Str "stick!"]]]+ ,[[Plain [Str "Crunchy",Space,Str "Frog"]]+  ,[Plain [Str "1.49"]]+  ,[Plain [Str "If",Space,Str "we",Space,Str "took",Space,Str "the",Space,Str "bones",Space,Str "out,",Space,Str "it",Space,Str "wouldn't",Space,Str "be",SoftBreak,Str "crunchy,",Space,Str "now",Space,Str "would",Space,Str "it?"]]]]]+```++```+% pandoc -f rst -t native+.. csv-table:: Test+   :header-rows: 1+   :quote: '+   :delim: space++   '' 'a' 'b'+   'cat''s' 3 4+   'dog''s' 2 3+^D+[Table [Str "Test"] [AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0]+ [[]+ ,[Plain [Str "a"]]+ ,[Plain [Str "b"]]]+ [[[Plain [Str "cat's"]]+  ,[Plain [Str "3"]]+  ,[Plain [Str "4"]]]+ ,[[Plain [Str "dog's"]]+  ,[Plain [Str "2"]]+  ,[Plain [Str "3"]]]]]+```++```+% pandoc -f rst -t native+.. csv-table:: Test+   :escape: \++   "1","\""+^D+[Table [Str "Test"] [AlignDefault,AlignDefault] [0.0,0.0]+ [[]+ ,[]]+ [[[Plain [Str "1"]]+  ,[Plain [Str "\""]]]]]+```+
+ test/command/3534.md view
@@ -0,0 +1,23 @@+```+% pandoc -f latex -t html+I want to explain the interface of \lstinline[language=Java]{public class MyClass}.+^D+<p>I want to explain the interface of <code class="sourceCode java"><span class="kw">public</span> <span class="kw">class</span> MyClass</code>.</p>++```++```+% pandoc -f latex -t html+I want to explain the interface of \lstinline{public class MyClass}.+^D+<p>I want to explain the interface of <code>public class MyClass</code>.</p>++```++```+% pandoc -f latex -t native+I want to explain the interface of \lstinline[language=Java]{public class MyClass}.+^D+[Para [Str "I",Space,Str "want",Space,Str "to",Space,Str "explain",Space,Str "the",Space,Str "interface",Space,Str "of",Space,Code ("",["java"],[]) "public class MyClass",Str "."]]+```+
+ test/command/3537.md view
@@ -0,0 +1,28 @@+Generalized raw attributes.++````+% pandoc -t native+```{=ms}+.MACRO+foo bar+```+^D+[RawBlock (Format "ms") ".MACRO\nfoo bar"]+````++````+% pandoc -t native+Hi `there`{=ms}.+^D+[Para [Str "Hi",Space,RawInline (Format "ms") "there",Str "."]]+````++````+% pandoc -t native+~~~ {=ms}+.MACRO+foo bar+~~~+^D+[RawBlock (Format "ms") ".MACRO\nfoo bar"]+````
+ test/command/3539.md view
@@ -0,0 +1,45 @@+# Commands of [glossaries package](ftp://ftp.tu-chemnitz.de/pub/tex/macros/latex/contrib/glossaries/glossaries-code.pdf)++```+% pandoc -f latex -t native+Many programming languages provide \glspl{API}. Each \gls{API} should provide a documentation.+^D+[Para [Str "Many",Space,Str "programming",Space,Str "languages",Space,Str "provide",Space,Span ("",[],[("acronym-label","API"),("acronym-form","plural+short")]) [Str "APIs"],Str ".",Space,Str "Each",Space,Span ("",[],[("acronym-label","API"),("acronym-form","singular+short")]) [Str "API"],Space,Str "should",Space,Str "provide",Space,Str "a",Space,Str "documentation."]]+```++```+% pandoc -f latex -t native+\Glsdesc{API} XYZ ist not as performant as \glsdesc{API} ZXY.+^D+[Para [Span ("",[],[("acronym-label","API"),("acronym-form","singular+long")]) [Str "API"],Space,Str "XYZ",Space,Str "ist",Space,Str "not",Space,Str "as",Space,Str "performant",Space,Str "as",Space,Span ("",[],[("acronym-label","API"),("acronym-form","singular+long")]) [Str "API"],Space,Str "ZXY."]]+```++```+% pandoc -f latex -t native+\Acrlong{API} XYZ ist not as performant as \acrlong{API} ZXY.+^D+[Para [Span ("",[],[("acronym-label","API"),("acronym-form","singular+long")]) [Str "API"],Space,Str "XYZ",Space,Str "ist",Space,Str "not",Space,Str "as",Space,Str "performant",Space,Str "as",Space,Span ("",[],[("acronym-label","API"),("acronym-form","singular+long")]) [Str "API"],Space,Str "ZXY."]]+```++```+% pandoc -f latex -t native+\Acrfull{API} XYZ ist not as performant as \acrfull{API} ZXY.+^D+[Para [Span ("",[],[("acronym-label","API"),("acronym-form","singular+full")]) [Str "API"],Space,Str "XYZ",Space,Str "ist",Space,Str "not",Space,Str "as",Space,Str "performant",Space,Str "as",Space,Span ("",[],[("acronym-label","API"),("acronym-form","singular+full")]) [Str "API"],Space,Str "ZXY."]]+```++```+% pandoc -f latex -t native+\Acrshort{API} XYZ ist not as performant as \acrshort{API} ZXY.+^D+[Para [Span ("",[],[("acronym-label","API"),("acronym-form","singular+abbrv")]) [Str "API"],Space,Str "XYZ",Space,Str "ist",Space,Str "not",Space,Str "as",Space,Str "performant",Space,Str "as",Space,Span ("",[],[("acronym-label","API"),("acronym-form","singular+abbrv")]) [Str "API"],Space,Str "ZXY."]]+```++# Commands of [acronym package](ftp://ftp.mpi-sb.mpg.de/pub/tex/mirror/ftp.dante.de/pub/tex/macros/latex/contrib/acronym/acronym.pdf)++```+% pandoc -f latex -t native+Many programming languages provide \acp{API}. Each \ac{API} should provide a documentation.+^D+[Para [Str "Many",Space,Str "programming",Space,Str "languages",Space,Str "provide",Space,Span ("",[],[("acronym-label","API"),("acronym-form","plural+short")]) [Str "APIs"],Str ".",Space,Str "Each",Space,Span ("",[],[("acronym-label","API"),("acronym-form","singular+short")]) [Str "API"],Space,Str "should",Space,Str "provide",Space,Str "a",Space,Str "documentation."]]+```
+ test/command/3558.md view
@@ -0,0 +1,12 @@+```+% pandoc -t native+\multi++hello++\endmulti+^D+[RawBlock (Format "latex") "\\multi"+,Para [Str "hello"]+,RawBlock (Format "latex") "\\endmulti"]+```
+ test/command/3568.md view
@@ -0,0 +1,15 @@+```+% pandoc -t man+normal *italic **bold in the middle** only italic* normal.++normal **bold `code` more bold** normal.++normal `code` normal.+^D+.PP+normal \f[I]italic \f[BI]bold in the middle\f[I] only italic\f[] normal.+.PP+normal \f[B]bold \f[BC]code\f[B] more bold\f[] normal.+.PP+normal \f[C]code\f[] normal.+```
+ test/command/3570.md view
@@ -0,0 +1,6 @@+```+% pandoc -f markdown+autolink_bare_uris+**Notes:**+^D+<p><strong>Notes:</strong></p>+```
+ test/command/3577.md view
@@ -0,0 +1,37 @@+```+% pandoc -f latex -t html5 --quiet+\begin{figure}[ht]+    \begin{subfigure}{0.45\textwidth}+        \centering+        \includegraphics{img1.jpg}+        \caption{Caption 1}+    \end{subfigure}++    \begin{subfigure}{0.45\textwidth}+        \centering+        \includegraphics{img2.jpg}+        \caption{Caption 2}+    \end{subfigure}+    \caption{Subfigure with Subfloat}+\end{figure}+^D++<figure>+<img src="img1.jpg" alt="Caption 1" /><figcaption>Caption 1</figcaption>+</figure>++<figure>+<img src="img2.jpg" alt="Caption 2" /><figcaption>Caption 2</figcaption>+</figure>+```+```+% pandoc -f latex -t html5+\begin{figure}[ht]+    \includegraphics{img1.jpg}+    \caption{Caption 3}+\end{figure}+^D+<figure>+<img src="img1.jpg" alt="Caption 3" /><figcaption>Caption 3</figcaption>+</figure>+```
+ test/command/3585.md view
@@ -0,0 +1,16 @@+```+% pandoc -f mediawiki+smart -t native+"Hello"++Same but bzip2 it and nice it <tt>zfs send tank/storage/data/svn@daily-2014-03-20_00.00.00--2w | nice -15 bzip2 | ssh user@hyper.somewhere.org "> /storage/c-3po/tank-storage-data-svn.dmp.bz2"</tt>+^D+[Para [Quoted DoubleQuote [Str "Hello"]]+,Para [Str "Same",Space,Str "but",Space,Str "bzip2",Space,Str "it",Space,Str "and",Space,Str "nice",Space,Str "it",Space,Code ("",[],[]) "zfs send tank/storage/data/svn@daily-2014-03-20_00.00.00--2w | nice -15 bzip2 | ssh user@hyper.somewhere.org \"> /storage/c-3po/tank-storage-data-svn.dmp.bz2\""]]+```++```+% pandoc -f mediawiki -t native+"Hello"+^D+[Para [Str "\"Hello\""]]+```
+ test/command/3587.md view
@@ -0,0 +1,21 @@+```+% pandoc -f latex -t native+\SI[round-precision=2]{1}{m} is equal to \SI{1000}{mm}+^D+[Para [Str "1\160m",Space,Str "is",Space,Str "equal",Space,Str "to",Space,Str "1000\160mm"]]+```++```+% pandoc -f latex -t native+\SI[round-precision=2]{1}[\$]{} is equal to \SI{0.938094}{\euro}+^D+[Para [Str "$\160\&1",Space,Str "is",Space,Str "equal",Space,Str "to",Space,Str "0.938094\160\8364"]]+```+++```+% pandoc -f latex -t native+\SI[round-precision=2]{\{\}}[\{\}]{\{\}}+^D+[Para [Str "{}\160{}\160{}"]]+```
+ test/command/3596.md view
@@ -0,0 +1,61 @@+```+% pandoc -f html -t markdown-raw_html-bracketed_spans-native_spans+<ul>+<li>foo</li>+<li id="id">bar</li>+<li>baz</li>+</ul>+^D+-   foo+-   bar+-   baz+```++```+% pandoc -f html -t markdown-raw_html-bracketed_spans-native_spans+<ul>+<li>foo</li>+<li id="id">bar<ul><li>subbar</li></ul></li>+<li>baz</li>+</ul>+^D+-   foo+-   bar+    -   subbar+-   baz+```+++```+% pandoc -f html -t markdown+<ul>+<li>foo</li>+<li id="id">bar</li>+<li>baz</li>+</ul>+^D+-   foo+-   [bar]{#id}+-   baz+```+++```+% pandoc -f html -t markdown+<ul>+<li><p>foo</p></li>+<li id="id"><p>bar</p></li>+<li><p>baz</p></li>+</ul>+^D+-   foo++-   <div id="id">++    bar++    </div>++-   baz++```
+ test/command/3615.md view
@@ -0,0 +1,18 @@+```+% pandoc -f html -t markdown --reference-links+<a href="a">foo</a> <a href="b">Foo</a>+^D+[foo][] [Foo][1]++  [foo]: a+  [1]: b+```++```+% pandoc -f html -t markdown --reference-links+<a href="a">foo</a> <a href="a">Foo</a>+^D+[foo][] [Foo]++  [foo]: a+```
+ test/command/3619.md view
@@ -0,0 +1,28 @@+```+% pandoc -f html -t markdown --reference-links+<a href="foo">bar</a>: baz+^D+[bar][]: baz++  [bar]: foo+```++```+% pandoc -f html -t markdown --reference-links+<a href="foo">bar</a>(baz)+^D+[bar][](baz)++  [bar]: foo+```++```+% pandoc -f html -t markdown_strict --reference-links+<a href="a">foo</a><br/><a href="b">bar</a>+^D+[foo][]  +[bar]++  [foo]: a+  [bar]: b+```
+ test/command/3630.md view
@@ -0,0 +1,8 @@+```+% pandoc -f markdown -t markdown --reference-links+![foo](bar.png){#myId}+^D+![foo]++  [foo]: bar.png {#myId}+```
+ test/command/3667.md view
@@ -0,0 +1,13 @@+```+% pandoc -f textile+| "link text":http://example.com/ |+^D+<table>+<tbody>+<tr class="odd">+<td><a href="http://example.com/">link text</a></td>+</tr>+</tbody>+</table>+```+
+ test/command/3674.md view
@@ -0,0 +1,39 @@+Make sure we don't get duplicate reference links, even with+`--reference-location=section`.++```+% pandoc --reference-links -t markdown --reference-location=section --atx-headers+# a++![](a)++# b++![](b)++^D+# a++![][1]++  [1]: a++# b++![][2]++  [2]: b+```++Subsidiary issue:  allow line break between reference link+url/title and attributes:++```+% pandoc+[a]++[a]: url+{.class}+^D+<p><a href="url" class="class">a</a></p>+```
+ test/command/3675.md view
@@ -0,0 +1,15 @@+````+% pandoc -t rst+```python+print("hello")+```+> block quote+^D+.. code:: python++    print("hello")++..++    block quote+````
+ test/command/3681.md view
@@ -0,0 +1,27 @@+```+% pandoc -f latex -t native+\newcommand{\cicd}{CI/CD\xspace}++Software developers create \cicd pipelines to… Following issue can be resolved by \cicd:+^D+[Para [Str "Software",Space,Str "developers",Space,Str "create",Space,Str "CI/CD",Space,Str "pipelines",Space,Str "to\8230",Space,Str "Following",Space,Str "issue",Space,Str "can",Space,Str "be",Space,Str "resolved",Space,Str "by",Space,Str "CI/CD:"]]+```++```+% pandoc -f latex -t native+\newcommand{\cicd}{CI/CD\xspace}++\cicd\footnote{\url{https://en.wikipedia.org/wiki/CI/CD}} is awesome.+^D+[Para [Str "CI/CD",Note [Para [Link ("",[],[]) [Str "https://en.wikipedia.org/wiki/CI/CD"] ("https://en.wikipedia.org/wiki/CI/CD","")]],Space,Str "is",Space,Str "awesome."]]+```++```+% pandoc -f latex -t native+\newcommand{\cicd}{CI/CD\xspace}+\newcommand{\pipeline}{pipeline\xspace}++\cicd\pipeline.+^D+[Para [Str "CI/CD",Space,Str "pipeline."]]+```
+ test/command/3690.md view
@@ -0,0 +1,8 @@+```+% pandoc+- [o] _hi_+^D+<ul>+<li>[o] <em>hi</em></li>+</ul>+```
+ test/command/3701.md view
@@ -0,0 +1,60 @@+```+% pandoc --reference-location=block -t markdown --reference-links --wrap=preserve+[a](u)++[a](u)++[a](u2)+[A](u)+[a](u){.foo}++[a](u3)+^D+[a]++  [a]: u++[a]++  [a]: u++[a][1]+[A][]+[a][2]++  [1]: u2+  [A]: u+  [2]: u {.foo}++[a][3]++  [3]: u3+```++```+% pandoc+[a]++  [a]: u++[a]++  [a]: u++[a][1]+[A][]+[a][2]++  [1]: u2+  [A]: u+  [2]: u {.foo}++[a][3]++  [3]: u3+^D+<p><a href="u">a</a></p>+<p><a href="u">a</a></p>+<p><a href="u2">a</a> <a href="u">A</a> <a href="u" class="foo">a</a></p>+<p><a href="u3">a</a></p>+```
+ test/command/3706.md view
@@ -0,0 +1,44 @@+Results marker can be hidden in block attributes (#3706)++```+pandoc -f org -t native+#+BEGIN_SRC R :exports results :colnames yes+   data.frame(Id = 1:3, Desc = rep("La",3))+#+END_SRC++#+CAPTION: Lalelu.+#+LABEL: tab+#+RESULTS:+| Id | Desc |+|----+------|+|  1 | La   |+|  2 | La   |+|  3 | La   |+^D+[Table [Str "Lalelu."] [AlignDefault,AlignDefault] [0.0,0.0]+ [[Plain [Str "Id"]]+ ,[Plain [Str "Desc"]]]+ [[[Plain [Str "1"]]+  ,[Plain [Str "La"]]]+ ,[[Plain [Str "2"]]+  ,[Plain [Str "La"]]]+ ,[[Plain [Str "3"]]+  ,[Plain [Str "La"]]]]]+```++```+pandoc -f org -t native+#+BEGIN_SRC R :exports none :colnames yes+   data.frame(Id = 1:2, Desc = rep("La",2))+#+END_SRC++#+CAPTION: Lalelu.+#+LABEL: tab+#+RESULTS:+| Id | Desc |+|----+------|+|  1 | La   |+|  2 | La   |+^D+[]+```
+ test/command/3708.md view
@@ -0,0 +1,15 @@+```+% pandoc -f latex -t native+\begin{tabular}{cc}+    A & B\&1 \\+    C & D+\end{tabular}+^D+[Table [] [AlignCenter,AlignCenter] [0.0,0.0]+ [[]+ ,[]]+ [[[Plain [Str "A"]]+  ,[Plain [Str "B&1"]]]+ ,[[Plain [Str "C"]]+  ,[Plain [Str "D"]]]]]+```
+ test/command/3715.md view
@@ -0,0 +1,15 @@+```+% pandoc -t markdown -f html --wrap=preserve+x<em></em>x+y<strong></strong>y+z<sup></sup>z+w<sub></sub>w+q<s></s>q+^D+xx+yy+zz+ww+qq+```+
+ test/command/3716.md view
@@ -0,0 +1,6 @@+```+% pandoc+<http://example.com>{.foo}+^D+<p><a href="http://example.com" class="uri foo">http://example.com</a></p>+```
+ test/command/3730.md view
@@ -0,0 +1,21 @@+````+% pandoc+nice line\+```+code+```+^D+<p>nice line<br />+</p>+<pre><code>code</code></pre>+````++```+% pandoc+# hi\+there+^D+<h1 id="hi">hi<br />+</h1>+<p>there</p>+```
+ test/command/3733.md view
@@ -0,0 +1,13 @@+````+% pandoc -t native+- Item1+- Item2+```yaml+some: code+```+^D+[BulletList+ [[Plain [Str "Item1"]]+ ,[Plain [Str "Item2"]]]+,CodeBlock ("",["yaml"],[]) "some: code"]+````
+ test/command/3734.md view
@@ -0,0 +1,50 @@+```+% pandoc -t markdown_strict+pipe_tables+| aaaaaaaaaaaa | bbbbb | ccccccccccc                                                              |+|--------------|-------|--------------------------------------------------------------------------|+| aaaaaaaaaaaa |       | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc |+^D+<table>+<colgroup>+<col style="width: 15%" />+<col style="width: 8%" />+<col style="width: 76%" />+</colgroup>+<thead>+<tr class="header">+<th>aaaaaaaaaaaa</th>+<th>bbbbb</th>+<th>ccccccccccc</th>+</tr>+</thead>+<tbody>+<tr class="odd">+<td>aaaaaaaaaaaa</td>+<td></td>+<td>cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc</td>+</tr>+</tbody>+</table>+```++```+% pandoc -t markdown_strict+pipe_tables-raw_html+| aaaaaaaaaaaa | bbbbb | ccccccccccc                                                              |+|--------------|-------|--------------------------------------------------------------------------|+| aaaaaaaaaaaa |       | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc |+^D+| aaaaaaaaaaaa | bbbbb | ccccccccccc                                                              |+|--------------|-------|--------------------------------------------------------------------------|+| aaaaaaaaaaaa |       | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc |+```++```+% pandoc -t gfm+| aaaaaaaaaaaa | bbbbb | ccccccccccc                                                              |+|--------------|-------|--------------------------------------------------------------------------|+| aaaaaaaaaaaa |       | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc |+^D+| aaaaaaaaaaaa | bbbbb | ccccccccccc                                                              |+| ------------ | ----- | ------------------------------------------------------------------------ |+| aaaaaaaaaaaa |       | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc |+```
+ test/command/3736.md view
@@ -0,0 +1,25 @@+```+% pandoc --wrap=preserve -f html -t markdown+<h2>hi+there</h2>+^D+hi there+--------+```++```+% pandoc --wrap=preserve -f html -t markdown+<h2>hi <em>there+again</em></h2>+^D+hi *there again*+----------------+```++```+% pandoc --wrap=preserve -f html -t markdown+<h2>hi<br>there</h2>+^D+hi there+--------+```
+ test/command/3755.md view
@@ -0,0 +1,23 @@+```+% pandoc -t native -s+---+title: 'Titel'+date: '22. Juni 2017'+---+^D+Pandoc (Meta {unMeta = fromList [("date",MetaInlines [Str "22.",Space,Str "Juni",Space,Str "2017"]),("title",MetaInlines [Str "Titel"])]})+[]+```++```+% pandoc -t native -s+---+title: '<div>foo</div>'+date: |+  22. Juni 2017+---+^D+Pandoc (Meta {unMeta = fromList [("date",MetaBlocks [OrderedList (22,Decimal,Period) [[Plain [Str "Juni",Space,Str "2017"]]]]),("title",MetaBlocks [Div ("",[],[]) [Plain [Str "foo"]]])]})+[]+```+
+ test/command/3771.md view
@@ -0,0 +1,14 @@+```+% pandoc -f html -t org+<div class="Section1">+  Today is a nice day.+</div>+<div id="forecast">+  Tomorrow will be rainy.+</div>+^D+Today is a nice day.++<<forecast>>+Tomorrow will be rainy.+```
+ test/command/3773.md view
@@ -0,0 +1,14 @@+```+% pandoc -t markdown+A.  \#+B.  \++C.  \*+D.  o+E.  o or \*+^D+A.  \#+B.  \++C.  \*+D.  o+E.  o or \*+```
+ test/command/3779.md view
@@ -0,0 +1,28 @@+```+% pandoc -f latex -t native+\newcommand{\fakeitemize}[1]{+    \begin{itemize}+        #1+    \end{itemize}+}+\newcommand{\testcmd}[1]{+    #1+}+\fakeitemize{+    \item Pandoc is 100\% awesome.+}++\begin{itemize}+    \item Pandoc is 200\% awesome.+\end{itemize}++\testcmd{+    Pandoc is 300\% awesome.+}+^D+[BulletList+ [[Para [Str "Pandoc",Space,Str "is",Space,Str "100%",Space,Str "awesome."]]]+,BulletList+ [[Para [Str "Pandoc",Space,Str "is",Space,Str "200%",Space,Str "awesome."]]]+,Para [Str "Pandoc",Space,Str "is",Space,Str "300%",Space,Str "awesome."]]+```
+ test/command/3792.md view
@@ -0,0 +1,13 @@+Make sure metadata values are treated as strings,+and properly escaped.++```+% pandoc -t markdown -s -M title="<this> *that*"+ok+^D+---+title: '\<this\> \*that\*'+---++ok+```
+ test/command/3794.md view
@@ -0,0 +1,7 @@+```+% pandoc -f html -t native+<div><p>hello</div>+^D+[Div ("",[],[])+ [Para [Str "hello"]]]+```
+ test/command/3803.md view
@@ -0,0 +1,10 @@+```+% pandoc -f markdown+raw_tex -t latex+\begin{blah*}+*ok*+\end{blah*}+^D+\begin{blah*}+*ok*+\end{blah*}+```
+ test/command/3804.md view
@@ -0,0 +1,6 @@+```+% pandoc -t native+\titleformat{\chapter}[display]{\normalfont\large\bfseries}{第\thechapter{}章}{20pt}{\Huge}+^D+[RawBlock (Format "latex") "\\titleformat{\\chapter}[display]{\\normalfont\\large\\bfseries}{\31532\\thechapter{}\31456}{20pt}{\\Huge}"]+```
+ test/command/3816.md view
@@ -0,0 +1,32 @@+```+% pandoc --mathjax -t html5 --wrap=preserve+This is an equation:+\begin{equation}+y+2 = 3+\end{equation}++This is a system of equations:+\begin{align*}+x^2+y^2 & = 2 \\+\sin(y) & = 0.5+\end{align*}++This is Euler's formula:+\begin{eqnarray*}+e^{i\pi} + 1 & = & 0.+\end{eqnarray*}+^D+<p>This is an equation:+<span class="math display">\[\begin{equation}+y+2 = 3+\end{equation}\]</span></p>+<p>This is a system of equations:+<span class="math display">\[\begin{align*}+x^2+y^2 &amp; = 2 \\+\sin(y) &amp; = 0.5+\end{align*}\]</span></p>+<p>This is Euler’s formula:+<span class="math display">\[\begin{eqnarray*}+e^{i\pi} + 1 &amp; = &amp; 0.+\end{eqnarray*}\]</span></p>+```
+ test/command/3824.md view
@@ -0,0 +1,14 @@+```+% pandoc -f native -t dokuwiki+[BulletList+ [[Para [Str "hi"]+  ,CodeBlock ("",[],[]) " there"]+ ,[Para [Str "ok"]]]]+^D+  * hi<code>+ there+</code>+  * ok+++```
+ test/command/3840.md view
@@ -0,0 +1,15 @@+```+% pandoc+[@Alhazen1572-qk, V.9]: "competentius est"+^D+<p><span class="citation" data-cites="Alhazen1572-qk">[@Alhazen1572-qk, V.9]</span>: “competentius est”</p>+```++```+% pandoc -f markdown-citations+[@Alhazen1572-qk, V.9]: "competentius est"++[@Alhazen1572-qk, V.9]+^D+<p><a href="" title="competentius est">@Alhazen1572-qk, V.9</a></p>+```
+ test/command/3853.md view
@@ -0,0 +1,26 @@+```+% pandoc -f latex -t native+\newtoggle{ebook}+\toggletrue{ebook}+\iftoggle{ebook}{+ebook+}%+{+not ebook+}%+more++\togglefalse{ebook}+\iftoggle{ebook}{%+ebook+}{+not ebook+}%+more++hello \iftoggle{ebook}{ebook}{noebook}+^D+[Para [Str "ebook",SoftBreak,Str "more"]+,Para [Str "not",Space,Str "ebook",SoftBreak,Str "more"]+,Para [Str "hello",Space,Str "noebook"]]+```
+ test/command/3880.md view
@@ -0,0 +1,6 @@+```+pandoc -f rst -t native+.. include:: command/3880.txt+^D+[Para [Str "hi"]]+```
+ test/command/3880.txt view
@@ -0,0 +1,1 @@+hi
+ test/command/3916.md view
@@ -0,0 +1,11 @@+```+% pandoc -f textile -t native+# text text+<pre>blabla</pre>+# more+^D+[OrderedList (1,DefaultStyle,DefaultDelim)+ [[Plain [Str "text",Space,Str "text"]+  ,CodeBlock ("",[],[]) "blabla"]+ ,[Plain [Str "more"]]]]+```
+ test/command/3937.md view
@@ -0,0 +1,13 @@+```+% pandoc -t rst+# My Great Section {#mysection}+# Other section+^D+.. mysection:++My Great Section+================++Other section+=============+```
+ test/command/3947.md view
@@ -0,0 +1,11 @@+```+% pandoc -t native+\newpage++	Code block++	Another Code block+^D+[RawBlock (Format "latex") "\\newpage"+,CodeBlock ("",[],[]) "Code block\n\nAnother Code block"]+```
+ test/command/3958.md view
@@ -0,0 +1,20 @@+```+% pandoc -f latex -t native+\texttt{"hi"}+^D+[Para [Code ("",[],[]) "\"hi\""]]+```++```+% pandoc -f latex -t native+\texttt{``hi''}+^D+[Para [Code ("",[],[]) "\8220hi\8221"]]+```++```+% pandoc -f latex -t native+\texttt{`hi'}+^D+[Para [Code ("",[],[]) "\8216hi\8217"]]+```
+ test/command/3968.md view
@@ -0,0 +1,9 @@+```+% pandoc --top-level-division=chapter -t context+# Chapter++## Section+^D+\chapter[chapter]{Chapter}+\section[section]{Section}+```
+ test/command/3971.md view
@@ -0,0 +1,9 @@+```+% pandoc -f latex -t native+\documentclass{article}+\include{command/3971b}+\code{f}+\end{document}+^D+[Para [Code ("",[],[]) "f"]]+```
+ test/command/3971b.tex view
@@ -0,0 +1,2 @@+\newcommand{\code}[1]{\texttt{#1}}+\begin{document}
+ test/command/3974.md view
@@ -0,0 +1,6 @@+```+% pandoc -f native -t rst+[Code ("",[],[]) "``"]+^D+:literal:`\`\``+```
+ test/command/3978.md view
@@ -0,0 +1,6 @@+```+% pandoc -t rst+foo_bar*baz+^D+foo_bar*baz+```
+ test/command/3983.md view
@@ -0,0 +1,29 @@+```+pandoc -f latex -t native+\def\filename@area{foo:bar:baz}+\makeatletter+\graphicspath\expandafter{\expandafter{\filename@area}}%+\makeatother+^D+[RawBlock (Format "latex") "\\makeatletter"+,RawBlock (Format "latex") "\\makeatother"]+```++```+pandoc -f latex -t native+\makeatletter+  \newcommand\urlfootnote@[1]{\footnote{\url@{#1}}}+  \DeclareRobustCommand{\urlfootnote}{\hyper@normalise\urlfootnote@}+\makeatother+^D+[RawBlock (Format "latex") "\\makeatletter"+,RawBlock (Format "latex") "\\makeatother"]+```++```+pandoc -f latex -t native+\def\foo{bar}+\expandafter\bam\foo+^D+[RawBlock (Format "latex") "\\bambar"]+```
+ test/command/3989.md view
@@ -0,0 +1,9 @@+```+pandoc -f markdown -t native+<span data-toggle="tooltip" data-placement="right" data-html="true"+title="1st line of text <br> 2nd line of text">+Hover over me+</span>+^D+[Para [Span ("",[],[("data-toggle","tooltip"),("data-placement","right"),("data-html","true"),("title","1st line of text <br> 2nd line of text")]) [SoftBreak,Str "Hover",Space,Str "over",Space,Str "me",SoftBreak]]]+```
+ test/command/512.md view
@@ -0,0 +1,42 @@+```+% pandoc -f rst+`click here`__ or `click here`__++.. _link1: http://www.example.com/+.. _link2: http://johnmacfarlane.net/pandoc/++__ link1_+__ link2_+^D+<p><a href="http://www.example.com/">click here</a> or <a href="http://johnmacfarlane.net/pandoc/">click here</a></p>+```++Multiple indirection:++```+% pandoc -f rst+`click here`__++.. _link1: link2_+.. _link2: http://johnmacfarlane.net/pandoc/++__ link1_+^D+<p><a href="http://johnmacfarlane.net/pandoc/">click here</a></p>+```++Loop detection:++```+% pandoc -f rst+`click here`__++.. _link1: link2_+.. _link2: link1_++__ link1_+^D+[WARNING] Circular reference 'link1' at line 1 column 15+<p><a href="">click here</a></p>+```+
+ test/command/645.md view
@@ -0,0 +1,12 @@+Don't use listings commands in \item[..] context:+```+% pandoc -t latex+`--foo` **BAR**++:   Enables the foo feature with **BAR** as its flavour.+^D+\begin{description}+\item[\texttt{-\/-foo} \textbf{BAR}]+Enables the foo feature with \textbf{BAR} as its flavour.+\end{description}+```
+ test/command/853.md view
@@ -0,0 +1,18 @@+reStructuredText citations.++```+% pandoc -f rst+Here is a citation reference: [CIT2002]_.++.. [CIT2002] This is the citation.  It's just like a footnote,+   except the label is textual.+^D+<p>Here is a citation reference: <a href="#CIT2002" class="citation">[CIT2002]</a>.</p>+<div id="citations">+<dl>+<dt><span id="CIT2002" class="citation-label">CIT2002</span></dt>+<dd><p>This is the citation. It's just like a footnote, except the label is textual.</p>+</dd>+</dl>+</div>+```
+ test/command/934.md view
@@ -0,0 +1,12 @@+```+% pandoc -f latex -t native+\newcommand{\ddb}[2]{+  \textit{``#1''}++  \textbf{#2}+}+\ddb{This should be italic and in quotes}{And this is the attribution}+^D+[Para [Emph [Quoted DoubleQuote [Str "This",Space,Str "should",Space,Str "be",Space,Str "italic",Space,Str "and",Space,Str "in",Space,Str "quotes"]]]+,Para [Strong [Str "And",Space,Str "this",Space,Str "is",Space,Str "the",Space,Str "attribution"]]]+```
+ test/command/982.md view
@@ -0,0 +1,11 @@+```+% pandoc -f latex -t native+\newcommand{\BEQ}{\begin{equation}}+\newcommand{\EEQ}{\end{equation}}++\BEQ+y=x^2+\EEQ+^D+[Para [Math DisplayMath "y=x^2"]]+```
+ test/command/987.md view
@@ -0,0 +1,12 @@+```+pandoc -f latex -t markdown+\documentclass{article}+\newenvironment{flubble}{FOO}{BAR}+\begin{document}+   \begin{flubble}+   grr+   \end{flubble}+\end{document}+^D+FOO grr BAR+```
+ test/command/SVG_logo-without-xml-declaration.svg view
@@ -0,0 +1,32 @@+<svg viewBox="-50 -50 100 100" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">+<title>SVG Logo</title>+<rect id="background" x="-50" y="-50" width="100" height="100" rx="4" fill="#f90"/>+<rect id="top-left" x="-50" y="-50" width="50" height="50" rx="4" fill="#ffb13b"/>+<rect id="bottom-right" width="50" height="50" rx="4" fill="#de8500"/>+<use stroke="#f90" stroke-width="22.6" xlink:href="#a"/>+<circle r="26"/>+<use stroke="#000" stroke-width="12" xlink:href="#a"/>+<g id="a">+	<g id="b">+		<g id="c">+			<circle id="n" cy="-31.6" r="7.1" fill="#fff"/>+			<path d="m0 31.6v-63.2" stroke="#fff" stroke-width="10"/>+			<use y="63.2" xlink:href="#n"/>+		</g>+		<use transform="rotate(90)" xlink:href="#c"/>+	</g>+	<use transform="rotate(45)" xlink:href="#b"/>+</g>+<path id="text-backdrop" d="m44.68 0v40c0 3.333-1.667 5-5 5h-79.38c-3.333 0-5-1.667-5-5v-40"/>+<path id="shine" d="m36 4.21c2.9 0 5.3 2.4 5.3 5.3v18c-27.6-3.4-54.9-8-82-7.7v-10.2c0-2.93 2.4-5.3 5.3-5.3z" fill="#3f3f3f"/>+<use stroke="#000" stroke-width="7.4" xlink:href="#s"/>+<g id="svg-text" stroke="#fff" stroke-width="6.4">+	<g id="s">+		<path fill="none" d="m-31.74 31.17a8.26 8.26 0 1 0 8.26 -8.26 8.26 8.26 0 1 1 8.26 -8.26M23.23 23h8.288v 8.26a8.26 8.26 0 0 1 -16.52 0v-16.52a8.26 8.26 0 0 1 16.52 0"/>+		<g stroke-width=".5" stroke="#000">+			<path d="m4.76 3h6.83l-8.24 39.8h-6.85l-8.26-39.8h6.85l4.84 23.3z" fill="#fff"/>+			<path d="m23.23 19.55v6.9m4.838-11.71h6.9m-70.16 16.43h6.9m9.62-16.52h6.9" stroke-linecap="square"/>+		</g>+	</g>+</g>+</svg>
+ test/command/SVG_logo.svg view
@@ -0,0 +1,33 @@+<?xml version="1.0"?>+<svg viewBox="-50 -50 100 100" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">+<title>SVG Logo</title>+<rect id="background" x="-50" y="-50" width="100" height="100" rx="4" fill="#f90"/>+<rect id="top-left" x="-50" y="-50" width="50" height="50" rx="4" fill="#ffb13b"/>+<rect id="bottom-right" width="50" height="50" rx="4" fill="#de8500"/>+<use stroke="#f90" stroke-width="22.6" xlink:href="#a"/>+<circle r="26"/>+<use stroke="#000" stroke-width="12" xlink:href="#a"/>+<g id="a">+	<g id="b">+		<g id="c">+			<circle id="n" cy="-31.6" r="7.1" fill="#fff"/>+			<path d="m0 31.6v-63.2" stroke="#fff" stroke-width="10"/>+			<use y="63.2" xlink:href="#n"/>+		</g>+		<use transform="rotate(90)" xlink:href="#c"/>+	</g>+	<use transform="rotate(45)" xlink:href="#b"/>+</g>+<path id="text-backdrop" d="m44.68 0v40c0 3.333-1.667 5-5 5h-79.38c-3.333 0-5-1.667-5-5v-40"/>+<path id="shine" d="m36 4.21c2.9 0 5.3 2.4 5.3 5.3v18c-27.6-3.4-54.9-8-82-7.7v-10.2c0-2.93 2.4-5.3 5.3-5.3z" fill="#3f3f3f"/>+<use stroke="#000" stroke-width="7.4" xlink:href="#s"/>+<g id="svg-text" stroke="#fff" stroke-width="6.4">+	<g id="s">
+		<path fill="none" d="m-31.74 31.17a8.26 8.26 0 1 0 8.26 -8.26 8.26 8.26 0 1 1 8.26 -8.26M23.23 23h8.288v 8.26a8.26 8.26 0 0 1 -16.52 0v-16.52a8.26 8.26 0 0 1 16.52 0"/>
+		<g stroke-width=".5" stroke="#000">+			<path d="m4.76 3h6.83l-8.24 39.8h-6.85l-8.26-39.8h6.85l4.84 23.3z" fill="#fff"/>
+			<path d="m23.23 19.55v6.9m4.838-11.71h6.9m-70.16 16.43h6.9m9.62-16.52h6.9" stroke-linecap="square"/>
+		</g>+	</g>+</g>+</svg>
+ test/command/abbrevs view
@@ -0,0 +1,2 @@+Foo.+h.k.
+ test/command/corrupt.svg view
@@ -0,0 +1,5 @@+Lorem ipsum dolor sit amet etiam. A pede dolor neque pretium luctus pharetra vel rutrum. Orci nonummy ac. At eu est tempor +proin wisi. Nunc tincidunt proin. Suspendisse lorem commodo. Integer diam diam semper commodo dictum et tellus eu ultrices +nec erat pulvinar porttitor nulla nulla mauris orci libero eros elementum et possimus voluptate. Velit morbi et. Luctus diam +in. Lorem tincidunt sem dolor rerum mauris. Dis taciti posuere pellentesque sed rutrum. Lectus donec fusce in dictum pede. +In etiam congue. Aliquam aliquet elit arcu mauris enim. Risus at enim.
+ test/command/dots.md view
@@ -0,0 +1,12 @@+```+% pandoc -f latex -t native+\dots++\ldots++\vdots+^D+[Para [Str "\8230"]+,Para [Str "\8230"]+,Para [Str "\8942"]]+```
+ test/command/gfm.md view
@@ -0,0 +1,103 @@+gfm tests:++```+% pandoc -f gfm -t native+| Fruit | Price |+| ----- | ----: |+| apple | 0.13  |+| orange|1.12|+^D+[Table [] [AlignDefault,AlignRight] [0.0,0.0]+ [[Plain [Str "Fruit"]]+ ,[Plain [Str "Price"]]]+ [[[Plain [Str "apple"]]+  ,[Plain [Str "0.13"]]]+ ,[[Plain [Str "orange"]]+  ,[Plain [Str "1.12"]]]]]+```++```+% pandoc -f gfm -t native+~~stricken out~~+^D+[Para [Strikeout [Str "stricken",Space,Str "out"]]]+```++```+% pandoc -f gfm -t native+# Header+## Header+# -foo-bar_baz+^D+[Header 1 ("header",[],[]) [Str "Header"]+,Header 2 ("header-1",[],[]) [Str "Header"]+,Header 1 ("-foo-bar_baz",[],[]) [Str "-foo-bar_baz"]]+```++```+% pandoc -f gfm -t native+My:thumbsup:emoji:heart:+^D+[Para [Str "My\128077emoji\10084\65039"]]+```++```+% pandoc -f gfm -t native+"hi"+^D+[Para [Str "\"hi\""]]+```++```+% pandoc -f gfm+smart -t native+"hi"+^D+[Para [Str "\8220hi\8221"]]+```++```+% pandoc -t gfm -f native+[Table [Str "The",Space,Str "caption."] [AlignDefault,AlignRight] [0.0,0.0]+ [[Plain [Str "Fruit"]]+ ,[Plain [Str "Price"]]]+ [[[Plain [Str "apple"]]+  ,[Plain [Str "0.13"]]]+ ,[[Plain [Str "orange"]]+  ,[Plain [Str "1.12"]]]]]+^D+| Fruit  | Price |+| ------ | ----: |+| apple  |  0.13 |+| orange |  1.12 |++The caption.+```++```+% pandoc -f gfm-smart -t gfm+smart+“hi”+^D+"hi"+```++```+% pandoc -f gfm+smart -t gfm-smart+"hi"+^D+“hi”+```++```+% pandoc -f gfm+smart -t gfm+smart+"hi"+^D+"hi"+```++```+% pandoc -f gfm+hard_line_breaks -t native+hi+hi+^D+[Para [Str "hi",LineBreak,Str "hi"]]+```
+ test/command/hspace.md view
@@ -0,0 +1,56 @@+`\hspace` and `\vspace` should count as both block and inline.++Here they need to be inline:+```+% pandoc -f markdown+raw_tex -t native+\begin{figure}+\includegraphics{lalune.jpg}+\caption{lalune \hspace{2em} \vspace{1em} bloo}+\end{figure}+^D+[RawBlock (Format "latex") "\\begin{figure}\n\\includegraphics{lalune.jpg}\n\\caption{lalune \\hspace{2em} \\vspace{1em} bloo}\n\\end{figure}"]+```++Here block:+```+% pandoc -f markdown+raw_tex -t native+\begin{tabular}[t]{cc|c}+\(P\) & \(Q\) & \(P\wedge Q\)\\+\hline+T & T &\\+T & F &\\+F & T &\\+F & F &\\+\end{tabular}+\hspace{1em}+\begin{tabular}[t]{cc|c}+\(P\) & \(Q\) & \(P\vee Q\)\\+\hline+T & T &\\+T & F &\\+F & T &\\+F & F &\\+\end{tabular}+^D+[RawBlock (Format "latex") "\\begin{tabular}[t]{cc|c}\n\\(P\\) & \\(Q\\) & \\(P\\wedge Q\\)\\\\\n\\hline\nT & T &\\\\\nT & F &\\\\\nF & T &\\\\\nF & F &\\\\\n\\end{tabular}\\hspace{1em}\\begin{tabular}[t]{cc|c}\n\\(P\\) & \\(Q\\) & \\(P\\vee Q\\)\\\\\n\\hline\nT & T &\\\\\nT & F &\\\\\nF & T &\\\\\nF & F &\\\\\n\\end{tabular}"]+```++```+% pandoc -f markdown+raw_tex -t native+hi\hspace{1em}there+^D+[Para [Str "hi",RawInline (Format "tex") "\\hspace{1em}",Str "there"]]+```++```+% pandoc -f markdown+raw_tex -t native+hi++\hspace{1em}++there+^D+[Para [Str "hi"]+,RawBlock (Format "latex") "\\hspace{1em}"+,Para [Str "there"]]+```
+ test/command/html-read-figure.md view
@@ -0,0 +1,45 @@+```+% pandoc -f html -t native+<figure>+  <img src="foo.png" title="voyage">+  <figcaption>bar</figcaption>+</figure>+^D+[Para [Image ("",[],[]) [Str "bar"] ("foo.png","fig:voyage")]]+```++```+% pandoc -f html -t native+<figure>+  <figcaption>bar</figcaption>+  <img src="foo.png" title="voyage">+</figure>+^D+[Para [Image ("",[],[]) [Str "bar"] ("foo.png","fig:voyage")]]+```++```+% pandoc -f html -t native+<figure>+  <img src="foo.png" title="voyage">+</figure>+^D+[Para [Image ("",[],[]) [] ("foo.png","fig:voyage")]]+```++```+% pandoc -f html -t native+<figure>+  <p><img src="foo.png" title="voyage"></p>+  <figcaption>bar</figcaption>+</figure>+^D+[Para [Image ("",[],[]) [Str "bar"] ("foo.png","fig:voyage")]]+```++```+% pandoc -f html -t native+<figure><img src="foo.png" title="voyage" alt="this is ignored"><figcaption>bar <strong>baz</strong></figcaption></figure>+^D+[Para [Image ("",[],[]) [Str "bar",Space,Strong [Str "baz"]] ("foo.png","fig:voyage")]]+```
+ test/command/hyphenat.md view
@@ -0,0 +1,49 @@+```+% pandoc -f latex -t native+electromagnetic\hyp{}endioscopy+^D+[Para [Str "electromagnetic-endioscopy"]]+```++```+% pandoc -f latex -t native+C\colonhyp\bshyp{}Windows\bshyp+^D+[Para [Str "C:\173\\\173Windows\\\173"]]+```++```+% pandoc -f latex -t native+\fshyp{}usr\fshyp{}share\fshyp+^D+[Para [Str "/\173usr/\173share/\173"]]+```++```+% pandoc -f latex -t native+\fshyp{}home\fshyp{}schrieveslaach\fshyp\dothyp{}m2+^D+[Para [Str "/\173home/\173schrieveslaach/\173.\173m2"]]+```++```+% pandoc -f latex -t native+\nohyphens{Pneumonoultramicroscopicsilicovolcanoconiosis}+^D+[Para [Str "Pneumonoultramicroscopicsilicovolcanoconiosis"]]+```++```+% pandoc -f latex -t native+\textnhtt{Pneumonoultramicroscopicsilicovolcanoconiosis}+^D+[Para [Code ("",[],[]) "Pneumonoultramicroscopicsilicovolcanoconiosis"]]+```++```+% pandoc -f latex -t native+\nhttfamily{Pneumonoultramicroscopicsilicovolcanoconiosis}+^D+[Para [Code ("",[],[]) "Pneumonoultramicroscopicsilicovolcanoconiosis"]]+```+
+ test/command/ifstrequal.md view
@@ -0,0 +1,10 @@+```+% pandoc -f latex -t native+\ifstrequal{a}{b}{yes}{\emph{no}}+\newcommand{\h}[1]{\ifstrequal{#1}{a}{\'a}{#1}}+\h{a}+\h{b}+^D+[Para [Emph [Str "no"]]+,Para [Str "\225",SoftBreak,Str "b"]]+```
+ test/command/inkscape-cube.svg view
@@ -0,0 +1,119 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+   xmlns:dc="http://purl.org/dc/elements/1.1/"+   xmlns:cc="http://creativecommons.org/ns#"+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+   xmlns:svg="http://www.w3.org/2000/svg"+   xmlns="http://www.w3.org/2000/svg"+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+   width="38.772217mm"+   height="46.163891mm"+   viewBox="0 0 38.772217 46.163891"+   version="1.1"+   id="svg8"+   inkscape:version="0.92.1 r"+   sodipodi:docname="cube.svg">+  <defs+     id="defs2">+    <inkscape:perspective+       sodipodi:type="inkscape:persp3d"+       inkscape:vp_x="-48.380952 : -45.023815 : 1"+       inkscape:vp_y="0 : 1000 : 0"+       inkscape:vp_z="161.61905 : -45.023817 : 1"+       inkscape:persp3d-origin="56.619048 : -94.523816 : 1"+       id="perspective4485" />+  </defs>+  <sodipodi:namedview+     id="base"+     pagecolor="#ffffff"+     bordercolor="#666666"+     borderopacity="1.0"+     inkscape:pageopacity="0.0"+     inkscape:pageshadow="2"+     inkscape:zoom="0.98994949"+     inkscape:cx="-63.181251"+     inkscape:cy="-116.38602"+     inkscape:document-units="mm"+     inkscape:current-layer="layer1"+     showgrid="false"+     fit-margin-top="0"+     fit-margin-left="0"+     fit-margin-right="0"+     fit-margin-bottom="0"+     inkscape:window-width="1920"+     inkscape:window-height="1136"+     inkscape:window-x="1920"+     inkscape:window-y="30"+     inkscape:window-maximized="1" />+  <metadata+     id="metadata5">+    <rdf:RDF>+      <cc:Work+         rdf:about="">+        <dc:format>image/svg+xml</dc:format>+        <dc:type+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+        <dc:title></dc:title>+      </cc:Work>+    </rdf:RDF>+  </metadata>+  <g+     inkscape:label="Ebene 1"+     inkscape:groupmode="layer"+     id="layer1"+     transform="translate(-149.67857,78.746839)">+    <g+       sodipodi:type="inkscape:box3d"+       id="g4487"+       style="opacity:0.2;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.53100002;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"+       inkscape:perspectiveID="#perspective4485"+       inkscape:corner0="1.1045097 : 0.18860662 : 0 : 1"+       inkscape:corner7="0.52634769 : 0.15538942 : 0.25 : 1">+      <path+         sodipodi:type="inkscape:box3dside"+         id="path4489"+         style="fill:#353564;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"+         inkscape:box3dsidetype="6"+         d="m 151.19047,-53.658435 v 15.783818 l 17.00006,5.342459 v -14.107905 z"+         points="151.19047,-37.874617 168.19053,-32.532158 168.19053,-46.640063 151.19047,-53.658435 " />+      <path+         sodipodi:type="inkscape:box3dside"+         id="path4499"+         style="fill:#e9e9ff;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"+         inkscape:box3dsidetype="11"+         d="m 168.19053,-46.640063 21.77216,-19.229539 v 18.699717 l -21.77216,14.637727 z"+         points="189.96269,-65.869602 189.96269,-47.169885 168.19053,-32.532158 168.19053,-46.640063 " />+      <path+         sodipodi:type="inkscape:box3dside"+         id="path4491"+         style="fill:#4d4d9f;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"+         inkscape:box3dsidetype="5"+         d="m 151.19047,-53.658435 18.89881,-25.037614 19.87341,12.826447 -21.77216,19.229539 z"+         points="170.08928,-78.696049 189.96269,-65.869602 168.19053,-46.640063 151.19047,-53.658435 " />+      <path+         sodipodi:type="inkscape:box3dside"+         id="path4497"+         style="fill:#afafde;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"+         inkscape:box3dsidetype="13"+         d="m 151.19047,-37.874617 18.89881,-19.058894 19.87341,9.763626 -21.77216,14.637727 z"+         points="170.08928,-56.933511 189.96269,-47.169885 168.19053,-32.532158 151.19047,-37.874617 " />+      <path+         sodipodi:type="inkscape:box3dside"+         id="path4495"+         style="fill:#d7d7ff;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"+         inkscape:box3dsidetype="14"+         d="m 170.08928,-78.696049 v 21.762538 l 19.87341,9.763626 v -18.699717 z"+         points="170.08928,-56.933511 189.96269,-47.169885 189.96269,-65.869602 170.08928,-78.696049 " />+      <path+         sodipodi:type="inkscape:box3dside"+         id="path4493"+         style="fill:#8686bf;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"+         inkscape:box3dsidetype="3"+         d="m 151.19047,-53.658435 18.89881,-25.037614 v 21.762538 l -18.89881,19.058894 z"+         points="170.08928,-78.696049 170.08928,-56.933511 151.19047,-37.874617 151.19047,-53.658435 " />+    </g>+  </g>+</svg>
+ test/command/latex-color.md view
@@ -0,0 +1,127 @@+# `\textcolor{}{}`++```+% pandoc -f latex -t native+Hello \textcolor{red}{World}+^D+[Para [Str "Hello",Space,Span ("",[],[("style","color: red")]) [Str "World"]]]+```++```+% pandoc -f latex -t native+\textcolor{red}{Hello} World+^D+[Para [Span ("",[],[("style","color: red")]) [Str "Hello"],Space,Str "World"]]+```++```+% pandoc -f latex -t native+Hello \textcolor{blue}{\textbf{World}}+^D+[Para [Str "Hello",Space,Span ("",[],[("style","color: blue")]) [Strong [Str "World"]]]]+```+++```+% pandoc -f latex -t native+Hello \textcolor{blue}{\textbf{World}}.+^D+[Para [Str "Hello",Space,Span ("",[],[("style","color: blue")]) [Strong [Str "World"]],Str "."]]+```++```+% pandoc -f latex -t native+\textcolor{orange}{+\begin{itemize}	+    \item Item 1+    \item Item 2+\end{itemize}+}+^D+[Div ("",[],[("style","color: orange")])+ [BulletList+  [[Para [Str "Item",Space,Str "1"]]+  ,[Para [Str "Item",Space,Str "2"]]]]]+```++```+% pandoc -f latex -t native+\textcolor{blue}{+\begin{itemize}+    \item Item 1+    \item Item 2+\end{itemize}+} some more text+^D+[Div ("",[],[("style","color: blue")])+ [BulletList+  [[Para [Str "Item",Space,Str "1"]]+  ,[Para [Str "Item",Space,Str "2"]]]]+,Para [Str "some",Space,Str "more",Space,Str "text"]]+```++# `\colorbox{}{}`+++```+% pandoc -f latex -t native+Hello \colorbox{red}{World}+^D+[Para [Str "Hello",Space,Span ("",[],[("style","background-color: red")]) [Str "World"]]]+```++```+% pandoc -f latex -t native+\colorbox{red}{Hello} World+^D+[Para [Span ("",[],[("style","background-color: red")]) [Str "Hello"],Space,Str "World"]]+```++```+% pandoc -f latex -t native+Hello \colorbox{blue}{\textbf{World}}+^D+[Para [Str "Hello",Space,Span ("",[],[("style","background-color: blue")]) [Strong [Str "World"]]]]+```++```+% pandoc -f latex -t native+Hello \colorbox{blue}{\textbf{World}}.+^D+[Para [Str "Hello",Space,Span ("",[],[("style","background-color: blue")]) [Strong [Str "World"]],Str "."]]+```++```+% pandoc -f latex -t native+\colorbox{orange}{+\begin{minipage}{\textwidth}+\begin{itemize}	+    \item Item 1+    \item Item 2+\end{itemize}+\end{minipage}+}+^D+[Div ("",[],[("style","background-color: orange")])+ [BulletList+  [[Para [Str "Item",Space,Str "1"]]+  ,[Para [Str "Item",Space,Str "2"]]]]]+```++```+% pandoc -f latex -t native+\colorbox{blue}{+\begin{minipage}{\textwidth}+\begin{itemize}+    \item Item 1+    \item Item 2+\end{itemize}+\end{minipage}+} some more text+^D+[Div ("",[],[("style","background-color: blue")])+ [BulletList+  [[Para [Str "Item",Space,Str "1"]]+  ,[Para [Str "Item",Space,Str "2"]]]]+,Para [Str "some",Space,Str "more",Space,Str "text"]]+```
+ test/command/latex-fontawesome.md view
@@ -0,0 +1,13 @@+```+% pandoc -f latex -t native+Check: \faCheck+^D+[Para [Str "Check:",Space,Str "\10003"]]+```++```+% pandoc -f latex -t native+Close: \faClose+^D+[Para [Str "Close:",Space,Str "\10007"]]+```
+ test/command/latex-tabular-column-specs.md view
@@ -0,0 +1,24 @@+See https://groups.google.com/forum/#!topic/pandoc-discuss/_VXtqihCyDU.++```+% pandoc -f latex -t native+\begin{tabular}{>{$}l<{$}>{$}l<{$} >{$}l<{$}}+\toprule+& f1 & f2 \\+\midrule+e      & 0.5    &  4   \\+f      & 0.5    & 5,5  \\+\bottomrule+\end{tabular}+^D+[Table [] [AlignLeft,AlignLeft,AlignLeft] [0.0,0.0,0.0]+ [[Plain [Math InlineMath ""]]+ ,[Plain [Math InlineMath "f1"]]+ ,[Plain [Math InlineMath "f2"]]]+ [[[Plain [Math InlineMath "e"]]+  ,[Plain [Math InlineMath "0.5"]]+  ,[Plain [Math InlineMath "4"]]]+ ,[[Plain [Math InlineMath "f"]]+  ,[Plain [Math InlineMath "0.5"]]+  ,[Plain [Math InlineMath "5,5"]]]]]+```
+ test/command/lettrine.md view
@@ -0,0 +1,9 @@+```+% pandoc -f latex -t native+\lettrine{A}{category} is++\lettrine[lhang=0.17]{A}{category} is+^D+[Para [Span ("",["lettrine"],[]) [Str "A"],Span ("",[],[]) [Str "category"],Space,Str "is"]+,Para [Span ("",["lettrine"],[]) [Str "A"],Span ("",[],[]) [Str "category"],Space,Str "is"]]+```
+ test/command/lstlisting.md view
@@ -0,0 +1,25 @@+```+% pandoc -f latex -t native+\begin{lstlisting}[language=Java, caption={Java Example}, label=lst:Hello-World]+public class World {+    public static void main(String[] args) {+        System.out.println("Hello World");+    }+}+\end{lstlisting}+^D+[CodeBlock ("lst:Hello-World",["java"],[("language","Java"),("caption","Java Example"),("label","lst:Hello-World")]) "public class World {\n    public static void main(String[] args) {\n        System.out.println(\"Hello World\");\n    }\n}"]+```++```+% pandoc -f latex -t native+\begin{lstlisting}[language=Java, escapechar=|, caption={Java Example}, label=lst:Hello-World]+public class World {+    public static void main(String[] args) {+        System.out.println("Hello World");+    }+}+\end{lstlisting}+^D+[CodeBlock ("lst:Hello-World",["java"],[("language","Java"),("escapechar","|"),("caption","Java Example"),("label","lst:Hello-World")]) "public class World {\n    public static void main(String[] args) {\n        System.out.println(\"Hello World\");\n    }\n}"]+```
+ test/command/macros.md view
@@ -0,0 +1,68 @@+```+% pandoc -f markdown+latex_macros -t markdown+\newcommand{\my}{\phi}+$\my+\my$+^D+\newcommand{\my}{\phi}+$\phi+\phi$+```++```+% pandoc -f markdown-latex_macros -t markdown+\newcommand{\my}{\phi}+$\my+\my$+^D+\newcommand{\my}{\phi}+$\my+\my$+```++`\let` macros should be expanded at point of+definition, while `\newcommand` macros should be+expanded at point of use:++```+% pandoc -f latex -t latex+\let\a\b+\newcommand{\b}{\emph{ouk}}+\a+^D+\b+```++```+% pandoc -f latex -t latex+\newcommand{\a}{\b}+\newcommand{\b}{\emph{ouk}}+\a+^D+\emph{ouk}+```++```+% pandoc -f latex -t latex+\def\BDpos{}+\def\BDneg{-}+\def\beq{\begin{align}}+\def\eeq{\end{align}}+\def\e#1{\emph{#1}}+\def\f#1#2{\emph{#1--#2}}++$5\BDneg 6\BDpos 7$++\beq+x &= y\\+\eeq++\e{hi}++\f{hi}{ok}+^D+\(5-67\)++\[\begin{aligned}+x &= y\\\end{aligned}\]++\emph{hi}++\emph{hi--ok}+```
+ test/command/md-abbrevs.md view
@@ -0,0 +1,31 @@+Pandoc recognizes an abbreviation and inserts a nonbreaking+space (among other things, this prevents a sentence-ending+space from being inserted in LaTeX output).++```+% pandoc -t native+Mr. Bob+^D+[Para [Str "Mr.\160Bob"]]+```++Here pandoc readjusts the softbreak so that the nonbreaking+space can be inserted:++```+% pandoc -t native+Hi Mr.+Bob+^D+[Para [Str "Hi",SoftBreak,Str "Mr.\160Bob"]]+```++If you don't want this to happen you can escape the period:++```+% pandoc -t native+Hi Mr\. Bob+^D+[Para [Str "Hi",Space,Str "Mr.",Space,Str "Bob"]]+```+
+ test/command/multiple-metadata-blocks.md view
@@ -0,0 +1,15 @@+If multiple blocks define a field, the first is used.++```+% pandoc -s -t native+---+foo: bar+...++---+foo: bim+...+^D+Pandoc (Meta {unMeta = fromList [("foo",MetaInlines [Str "bar"])]})+[]+```
+ test/command/parse-raw.md view
@@ -0,0 +1,27 @@+```+% pandoc -f latex+raw_tex -t markdown+\emph{Hi \foo{there}}+^D+*Hi \foo{there}*+```++```+% pandoc -f latex -t markdown+\emph{Hi \foo{there}}+^D+*Hi*+```++```+% pandoc -f html+raw_html -t markdown+<em>Hi <blink>there</blink></em>+^D+*Hi <blink>there</blink>*+```++```+% pandoc -f html -t markdown+<em>Hi <blink>there</blink></em>+^D+*Hi there*+```
+ test/command/refs.md view
@@ -0,0 +1,54 @@+```+% pandoc -f latex -t native+Figure \ref{fig:1}+^D+[Para [Str "Figure",Space,Link ("",[],[("reference-type","ref"),("reference","fig:1")]) [Str "[fig:1]"] ("#fig:1","")]]+```++```+% pandoc -f latex -t native+Figure \cref{fig:1}+^D+[Para [Str "Figure",Space,Link ("",[],[("reference-type","ref"),("reference","fig:1")]) [Str "[fig:1]"] ("#fig:1","")]]+```++```+% pandoc -f latex -t native+Figure \vref{fig:1}+^D+[Para [Str "Figure",Space,Link ("",[],[("reference-type","ref+page"),("reference","fig:1")]) [Str "[fig:1]"] ("#fig:1","")]]+```++```+% pandoc -f latex -t native+Accuracy~\eqref{eq:Accuracy} is the proportion, measuring true results among all results.++\begin{equation}+  \label{eq:Accuracy}+  Accuracy = \frac{t_p + t_n}{t_p + f_p + f_n + t_n}+\end{equation}+^D+[Para [Str "Accuracy\160",Link ("",[],[("reference-type","eqref"),("reference","eq:Accuracy")]) [Str "[eq:Accuracy]"] ("#eq:Accuracy",""),Space,Str "is",Space,Str "the",Space,Str "proportion,",Space,Str "measuring",Space,Str "true",Space,Str "results",Space,Str "among",Space,Str "all",Space,Str "results."]+,Para [Math DisplayMath "\\label{eq:Accuracy}\n  Accuracy = \\frac{t_p + t_n}{t_p + f_p + f_n + t_n}"]]+```++```+% pandoc -f latex -t native+\begin{figure}+  \includegraphics{command/SVG_logo.svg}+  \caption{Logo}+  \label{fig:Logo}+\end{figure}++Figure \ref{fig:Logo} illustrated the SVG logo+^D+[Para [Image ("",[],[]) [Str "Logo",Span ("",[],[("label","fig:Logo")]) []] ("command/SVG_logo.svg","fig:")]+,Para [Str "Figure",Space,Link ("",[],[("reference-type","ref"),("reference","fig:Logo")]) [Str "[fig:Logo]"] ("#fig:Logo",""),Space,Str "illustrated",Space,Str "the",Space,Str "SVG",Space,Str "logo"]]+```++```+% pandoc -f latex -t native+\label{section} Section \ref{section}+^D+[Para [Span ("section",[],[("label","section")]) [Str "[section]"],Space,Str "Section",Space,Link ("",[],[("reference-type","ref"),("reference","section")]) [Str "[section]"] ("#section","")]]+```
+ test/command/smart.md view
@@ -0,0 +1,45 @@+```+% pandoc -f markdown+smart -t markdown-smart+"hi"...dog's breath---cat 5--6+^D+“hi”…dog’s breath—cat 5–6+```++```+% pandoc -f markdown+smart -t markdown+smart+"hi"...dog's breath---cat 5--6+^D+"hi"...dog's breath---cat 5--6+```++When we render literal quotes without smart, we need to escape:++```+% pandoc -f markdown-smart \+  -t markdown+smart+"hi"...dog's breath---cat 5--6+^D+\"hi\"\...dog\'s breath\-\--cat 5\--6+```++```+% pandoc -f markdown+smart -t rst-smart+"hi"...dog's breath---cat 5--6+^D+“hi”…dog’s breath—cat 5–6+```++```+% pandoc -f markdown+smart -t rst+smart+"hi"...dog's breath---cat 5--6+^D+"hi"...dog's breath---cat 5--6+```++```+% pandoc -f markdown-smart -t rst+smart+"hi"...dog's breath---cat 5--6+^D+\"hi\"\...dog\'s breath\-\--cat 5\--6+```+
+ test/command/sub-file-chapter-1.tex view
@@ -0,0 +1,8 @@+\documentclass[main.tex]{subfiles}+\begin{document}++\section{Chapter 1}++This is Chapter 1, provided in a sub file. ++\end{document}
+ test/command/sub-file-chapter-2.tex view
@@ -0,0 +1,8 @@+\documentclass[main.tex]{subfiles}+\begin{document}++\section{Chapter 2}++This is Chapter 2, provided in a second sub file. ++\end{document}
+ test/command/svg.md view
@@ -0,0 +1,132 @@+```+% pandoc -f latex -t icml+\includegraphics{command/corrupt.svg}+^D+[WARNING] Could not determine image size for 'command/corrupt.svg': could not determine image type+<ParagraphStyleRange AppliedParagraphStyle="ParagraphStyle/Paragraph">+  <CharacterStyleRange AppliedCharacterStyle="$ID/NormalCharacterStyle">+    <Rectangle Self="uec" StrokeWeight="0" ItemTransform="1 0 0 1 150 -100">+      <Properties>+        <PathGeometry>+          <GeometryPathType PathOpen="false">+            <PathPointArray>+              <PathPointType Anchor="-150 -100" LeftDirection="-150 -100" RightDirection="-150 -100" />+              <PathPointType Anchor="-150 100" LeftDirection="-150 100" RightDirection="-150 100" />+              <PathPointType Anchor="150 100" LeftDirection="150 100" RightDirection="150 100" />+              <PathPointType Anchor="150 -100" LeftDirection="150 -100" RightDirection="150 -100" />+            </PathPointArray>+          </GeometryPathType>+        </PathGeometry>+      </Properties>+      <Image Self="ue6" ItemTransform="1 0 0 1 -150 -100">+        <Properties>+          <Profile type="string">+            $ID/Embedded+          </Profile>+        </Properties>+        <Link Self="ueb" LinkResourceURI="file:command/corrupt.svg" />+      </Image>+    </Rectangle>+  </CharacterStyleRange>+</ParagraphStyleRange>+```++```+% pandoc -f latex -t icml+\includegraphics{command/SVG_logo.svg}+^D+[WARNING] Could not determine image size for 'command/SVG_logo.svg': could not determine SVG size+<ParagraphStyleRange AppliedParagraphStyle="ParagraphStyle/Paragraph">+  <CharacterStyleRange AppliedCharacterStyle="$ID/NormalCharacterStyle">+    <Rectangle Self="uec" StrokeWeight="0" ItemTransform="1 0 0 1 150 -100">+      <Properties>+        <PathGeometry>+          <GeometryPathType PathOpen="false">+            <PathPointArray>+              <PathPointType Anchor="-150 -100" LeftDirection="-150 -100" RightDirection="-150 -100" />+              <PathPointType Anchor="-150 100" LeftDirection="-150 100" RightDirection="-150 100" />+              <PathPointType Anchor="150 100" LeftDirection="150 100" RightDirection="150 100" />+              <PathPointType Anchor="150 -100" LeftDirection="150 -100" RightDirection="150 -100" />+            </PathPointArray>+          </GeometryPathType>+        </PathGeometry>+      </Properties>+      <Image Self="ue6" ItemTransform="1 0 0 1 -150 -100">+        <Properties>+          <Profile type="string">+            $ID/Embedded+          </Profile>+        </Properties>+        <Link Self="ueb" LinkResourceURI="file:command/SVG_logo.svg" />+      </Image>+    </Rectangle>+  </CharacterStyleRange>+</ParagraphStyleRange>+```++```+% pandoc -f latex -t icml+\includegraphics{command/SVG_logo-without-xml-declaration.svg}+^D+[WARNING] Could not determine image size for 'command/SVG_logo-without-xml-declaration.svg': could not determine SVG size+<ParagraphStyleRange AppliedParagraphStyle="ParagraphStyle/Paragraph">+  <CharacterStyleRange AppliedCharacterStyle="$ID/NormalCharacterStyle">+    <Rectangle Self="uec" StrokeWeight="0" ItemTransform="1 0 0 1 150 -100">+      <Properties>+        <PathGeometry>+          <GeometryPathType PathOpen="false">+            <PathPointArray>+              <PathPointType Anchor="-150 -100" LeftDirection="-150 -100" RightDirection="-150 -100" />+              <PathPointType Anchor="-150 100" LeftDirection="-150 100" RightDirection="-150 100" />+              <PathPointType Anchor="150 100" LeftDirection="150 100" RightDirection="150 100" />+              <PathPointType Anchor="150 -100" LeftDirection="150 -100" RightDirection="150 -100" />+            </PathPointArray>+          </GeometryPathType>+        </PathGeometry>+      </Properties>+      <Image Self="ue6" ItemTransform="1 0 0 1 -150 -100">+        <Properties>+          <Profile type="string">+            $ID/Embedded+          </Profile>+        </Properties>+        <Link Self="ueb" LinkResourceURI="file:command/SVG_logo-without-xml-declaration.svg" />+      </Image>+    </Rectangle>+  </CharacterStyleRange>+</ParagraphStyleRange>+```+++```+% pandoc -f latex -t icml+\includegraphics{command/inkscape-cube.svg}+^D+<ParagraphStyleRange AppliedParagraphStyle="ParagraphStyle/Paragraph">+  <CharacterStyleRange AppliedCharacterStyle="$ID/NormalCharacterStyle">+    <Rectangle Self="uec" StrokeWeight="0" ItemTransform="1 0 0 1 54.75 -65.25">+      <Properties>+        <PathGeometry>+          <GeometryPathType PathOpen="false">+            <PathPointArray>+              <PathPointType Anchor="-54.75 -65.25" LeftDirection="-54.75 -65.25" RightDirection="-54.75 -65.25" />+              <PathPointType Anchor="-54.75 65.25" LeftDirection="-54.75 65.25" RightDirection="-54.75 65.25" />+              <PathPointType Anchor="54.75 65.25" LeftDirection="54.75 65.25" RightDirection="54.75 65.25" />+              <PathPointType Anchor="54.75 -65.25" LeftDirection="54.75 -65.25" RightDirection="54.75 -65.25" />+            </PathPointArray>+          </GeometryPathType>+        </PathGeometry>+      </Properties>+      <Image Self="ue6" ItemTransform="1 0 0 1 -54.75 -65.25">+        <Properties>+          <Profile type="string">+            $ID/Embedded+          </Profile>+        </Properties>+        <Link Self="ueb" LinkResourceURI="file:command/inkscape-cube.svg" />+      </Image>+    </Rectangle>+  </CharacterStyleRange>+</ParagraphStyleRange>+```+
+ test/command/tabularx.md view
@@ -0,0 +1,110 @@+```+% pandoc -f latex -t native --quiet+\begin{tabularx}{\linewidth}{|c|c|c|}+\hline+  Column Heading 1+  & Column Heading 2+  & Column Heading 3 \\+\hline+  Cell 1.1 +  & Cell 1.2+  & Cell 1.3 \\+\hline+  Cell 2.1 +  & Cell 2.2+  & Cell 2.3 \\+\hline+  Cell 3.1 +  & Cell 3.2+  & Cell 3.3 \\+\hline+\end{tabularx}+^D+[Table [] [AlignCenter,AlignCenter,AlignCenter] [0.0,0.0,0.0]+ [[Plain [Str "Column",Space,Str "Heading",Space,Str "1"]]+ ,[Plain [Str "Column",Space,Str "Heading",Space,Str "2"]]+ ,[Plain [Str "Column",Space,Str "Heading",Space,Str "3"]]]+ [[[Plain [Str "Cell",Space,Str "1.1"]]+  ,[Plain [Str "Cell",Space,Str "1.2"]]+  ,[Plain [Str "Cell",Space,Str "1.3"]]]+ ,[[Plain [Str "Cell",Space,Str "2.1"]]+  ,[Plain [Str "Cell",Space,Str "2.2"]]+  ,[Plain [Str "Cell",Space,Str "2.3"]]]+ ,[[Plain [Str "Cell",Space,Str "3.1"]]+  ,[Plain [Str "Cell",Space,Str "3.2"]]+  ,[Plain [Str "Cell",Space,Str "3.3"]]]]]+```++```+% pandoc -f latex -t native --quiet+\begin{tabularx}{\linewidth}{|X|c|p{0.25\linewidth}|}+\hline+  Column Heading 1+  & Column Heading 2+  & Column Heading 3 \\+\hline+  Cell 1.1 +  & Cell 1.2+  & Cell 1.3 \\+\hline+  Cell 2.1 +  & Cell 2.2+  & Cell 2.3 \\+\hline+  Cell 3.1 +  & Cell 3.2+  & Cell 3.3 \\+\hline+\end{tabularx}+^D+[Table [] [AlignLeft,AlignCenter,AlignLeft] [0.0,0.0,0.25]+ [[Plain [Str "Column",Space,Str "Heading",Space,Str "1"]]+ ,[Plain [Str "Column",Space,Str "Heading",Space,Str "2"]]+ ,[Plain [Str "Column",Space,Str "Heading",Space,Str "3"]]]+ [[[Plain [Str "Cell",Space,Str "1.1"]]+  ,[Plain [Str "Cell",Space,Str "1.2"]]+  ,[Plain [Str "Cell",Space,Str "1.3"]]]+ ,[[Plain [Str "Cell",Space,Str "2.1"]]+  ,[Plain [Str "Cell",Space,Str "2.2"]]+  ,[Plain [Str "Cell",Space,Str "2.3"]]]+ ,[[Plain [Str "Cell",Space,Str "3.1"]]+  ,[Plain [Str "Cell",Space,Str "3.2"]]+  ,[Plain [Str "Cell",Space,Str "3.3"]]]]]+```++```+% pandoc -f latex -t native --quiet+\begin{tabularx}{\linewidth}{|b{0.25\linewidth}|c|m{0.25\linewidth}|}+\hline+  Column Heading 1+  & Column Heading 2+  & Column Heading 3 \\+\hline+  Cell 1.1 +  & Cell 1.2+  & Cell 1.3 \\+\hline+  Cell 2.1 +  & Cell 2.2+  & Cell 2.3 \\+\hline+  Cell 3.1 +  & Cell 3.2+  & Cell 3.3 \\+\hline+\end{tabularx}+^D+[Table [] [AlignLeft,AlignCenter,AlignLeft] [0.25,0.0,0.25]+ [[Plain [Str "Column",Space,Str "Heading",Space,Str "1"]]+ ,[Plain [Str "Column",Space,Str "Heading",Space,Str "2"]]+ ,[Plain [Str "Column",Space,Str "Heading",Space,Str "3"]]]+ [[[Plain [Str "Cell",Space,Str "1.1"]]+  ,[Plain [Str "Cell",Space,Str "1.2"]]+  ,[Plain [Str "Cell",Space,Str "1.3"]]]+ ,[[Plain [Str "Cell",Space,Str "2.1"]]+  ,[Plain [Str "Cell",Space,Str "2.2"]]+  ,[Plain [Str "Cell",Space,Str "2.3"]]]+ ,[[Plain [Str "Cell",Space,Str "3.1"]]+  ,[Plain [Str "Cell",Space,Str "3.2"]]+  ,[Plain [Str "Cell",Space,Str "3.3"]]]]]+```
+ test/command/translations.md view
@@ -0,0 +1,29 @@+```+% pandoc -f latex -t native -M lang=en+\figurename\ 2+^D+[Para [Str "Figure\160\&2"]]+```++```+% pandoc -f latex -t native -M lang=de-DE+\figurename\ 2+^D+[Para [Str "Abbildung\160\&2"]]+```++```+% pandoc -f latex -t native -M lang=en+\setmainlanguage{german}+\figurename 2+^D+[Para [Str "Abbildung2"]]+```++```+% pandoc -f latex -t native -M lang=sr+\figurename~2+\figurename.+^D+[Para [Str "Slika\160\&2",SoftBreak,Str "Slika."]]+```
+ test/command/vars-and-metadata.md view
@@ -0,0 +1,15 @@+Variables should not leak into metadata in the Markdown writer:++```+% pandoc -t markdown -Vfoo=1 -Vbar=2 -s+---+foo: x+...+zib+^D+---+foo: x+---++zib+```
+ test/command/write18.md view
@@ -0,0 +1,14 @@+Handle \write18{..} as raw tex:+```+% pandoc -t native+\write18{git --version}+^D+[RawBlock (Format "latex") "\\write18{git --version}"]+```++```+% pandoc -f latex+raw_tex -t native+\write18{git --version}+^D+[RawBlock (Format "latex") "\\write18{git --version}"]+```
+ test/creole-reader.native view
@@ -0,0 +1,95 @@+Pandoc (Meta {unMeta = fromList []})+[Header 1 ("",[],[]) [Str "Top-level heading (1)"]+,Header 2 ("",[],[]) [Str "This a test for creole 0.1 (2)"]+,Header 3 ("",[],[]) [Str "This is a Subheading (3)"]+,Header 4 ("",[],[]) [Str "Subsub (4)"]+,Header 5 ("",[],[]) [Str "Subsubsub (5)"]+,Para [Str "The",Space,Str "ending",Space,Str "equal",Space,Str "signs",Space,Str "should",Space,Str "not",Space,Str "be",Space,Str "displayed:"]+,Header 1 ("",[],[]) [Str "Top-level heading (1)"]+,Header 2 ("",[],[]) [Str "This a test for creole 0.1 (2)"]+,Header 3 ("",[],[]) [Str "This is a Subheading (3)"]+,Header 4 ("",[],[]) [Str "Subsub (4)"]+,Header 5 ("",[],[]) [Str "Subsubsub (5)"]+,Para [Str "You",Space,Str "can",Space,Str "make",Space,Str "things",Space,Strong [Str "bold"],Space,Str "or",Space,Emph [Str "italic"],Space,Str "or",Space,Strong [Emph [Str "both"]],Space,Str "or",Space,Emph [Strong [Str "both"]],Str "."]+,Para [Str "Character",Space,Str "formatting",Space,Str "extends",Space,Str "across",Space,Str "line",Space,Str "breaks:",Space,Strong [Str "bold,",Space,Str "this",Space,Str "is",Space,Str "still",Space,Str "bold.",Space,Str "This",Space,Str "line",Space,Str "deliberately",Space,Str "does",Space,Str "not",Space,Str "end",Space,Str "in",Space,Str "star-star."]]+,Para [Str "Not",Space,Str "bold.",Space,Str "Character",Space,Str "formatting",Space,Str "does",Space,Str "not",Space,Str "cross",Space,Str "paragraph",Space,Str "boundaries."]+,Para [Str "You",Space,Str "can",Space,Str "use",Space,Link ("",[],[]) [Str "internal links"] ("internal links",""),Space,Str "or",Space,Link ("",[],[]) [Str "external links"] ("http://www.wikicreole.org",""),Str ",",Space,Str "give",Space,Str "the",Space,Str "link",Space,Str "a",Space,Link ("",[],[]) [Str "different"] ("internal links",""),Space,Str "name."]+,Para [Str "Here's",Space,Str "another",Space,Str "sentence:",Space,Str "This",Space,Str "wisdom",Space,Str "is",Space,Str "taken",Space,Str "from",Space,Link ("",[],[]) [Str "Ward Cunningham's"] ("Ward Cunningham's",""),Space,Link ("",[],[]) [Str "Presentation at the Wikisym 06"] ("http://www.c2.com/doc/wikisym/WikiSym2006.pdf",""),Str "."]+,Para [Str "Here's",Space,Str "a",Space,Str "external",Space,Str "link",Space,Str "without",Space,Str "a",Space,Str "description:",Space,Link ("",[],[]) [Str "http://www.wikicreole.org"] ("http://www.wikicreole.org","")]+,Para [Str "Be",Space,Str "careful",Space,Str "that",Space,Str "italic",Space,Str "links",Space,Str "are",Space,Str "rendered",Space,Str "properly:",Space,Emph [Link ("",[],[]) [Str "My Book Title"] ("http://my.book.example/","")]]+,Para [Str "Free",Space,Str "links",Space,Str "without",Space,Str "braces",Space,Str "should",Space,Str "be",Space,Str "rendered",Space,Str "as",Space,Str "well,",Space,Str "like",Space,Link ("",[],[]) [Str "http://www.wikicreole.org/"] ("http://www.wikicreole.org/",""),Space,Str "and",Space,Link ("",[],[]) [Str "http://www.wikicreole.org/users/~example"] ("http://www.wikicreole.org/users/~example",""),Str "."]+,Para [Str "Creole1.0",Space,Str "specifies",Space,Str "that",Space,Link ("",[],[]) [Str "http://bar"] ("http://bar",""),Space,Str "and",Space,Link ("",[],[]) [Str "ftp://bar"] ("ftp://bar",""),Space,Str "should",Space,Str "not",Space,Str "render",Space,Str "italic,",Space,Str "something",Space,Str "like",Space,Str "foo:",Emph [Str "bar",Space,Str "should",Space,Str "render",Space,Str "as",Space,Str "italic."]]+,Para [Str "You",Space,Str "can",Space,Str "use",Space,Str "this",Space,Str "to",Space,Str "draw",Space,Str "a",Space,Str "line",Space,Str "to",Space,Str "separate",Space,Str "the",Space,Str "page:"]+,HorizontalRule+,Para [Str "You",Space,Str "can",Space,Str "use",Space,Str "lists,",Space,Str "start",Space,Str "it",Space,Str "at",Space,Str "the",Space,Str "first",Space,Str "column",Space,Str "for",Space,Str "now,",Space,Str "please..."]+,Para [Str "unnumbered",Space,Str "lists",Space,Str "are",Space,Str "like"]+,BulletList+ [[Plain [Str "item",Space,Str "a"]]+ ,[Plain [Str "item",Space,Str "b"]]+ ,[Plain [Strong [Str "bold",Space,Str "item",Space,Str "c"]]]]+,Para [Str "blank",Space,Str "space",Space,Str "is",Space,Str "also",Space,Str "permitted",Space,Str "before",Space,Str "lists",Space,Str "like:"]+,BulletList+ [[Plain [Str "item",Space,Str "a"]]+ ,[Plain [Str "item",Space,Str "b"]]+ ,[Plain [Str "item",Space,Str "c"]+  ,BulletList+   [[Plain [Str "item",Space,Str "c.a"]]]]]+,Para [Str "or",Space,Str "you",Space,Str "can",Space,Str "number",Space,Str "them"]+,OrderedList (1,DefaultStyle,DefaultDelim)+ [[Plain [Link ("",[],[]) [Str "item 1"] ("item 1","")]]+ ,[Plain [Str "item",Space,Str "2"]]+ ,[Plain [Emph [Space,Str "italic",Space,Str "item",Space,Str "3",Space]]+  ,OrderedList (1,DefaultStyle,DefaultDelim)+   [[Plain [Str "item",Space,Str "3.1"]]+   ,[Plain [Str "item",Space,Str "3.2"]]]]]+,Para [Str "up",Space,Str "to",Space,Str "five",Space,Str "levels"]+,BulletList+ [[Plain [Str "1"]+  ,BulletList+   [[Plain [Str "2"]+    ,BulletList+     [[Plain [Str "3"]+      ,BulletList+       [[Plain [Str "4"]+        ,BulletList+         [[Plain [Str "5"]]]]]]]]]]]+,BulletList+ [[Plain [Str "You",Space,Str "can",Space,Str "have",Space,Str "multiline",Space,Str "list",Space,Str "items"]]+ ,[Plain [Str "this",Space,Str "is",Space,Str "a",Space,Str "second",Space,Str "multiline",Space,Str "list",Space,Str "item"]]]+,Para [Str "You",Space,Str "can",Space,Str "use",Space,Str "nowiki",Space,Str "syntax",Space,Str "if",Space,Str "you",Space,Str "would",Space,Str "like",Space,Str "do",Space,Str "stuff",Space,Str "like",Space,Str "this:"]+,CodeBlock ("",[],[]) "Guitar Chord C:\n\n||---|---|---|\n||-0-|---|---|\n||---|---|---|\n||---|-0-|---|\n||---|---|-0-|\n||---|---|---|"+,Para [Str "You",Space,Str "can",Space,Str "also",Space,Str "use",Space,Str "it",Space,Str "inline",Space,Str "nowiki",Space,Code ("",[],[]) " in a sentence ",Space,Str "like",Space,Str "this."]+,Header 1 ("",[],[]) [Str "Escapes"]+,Para [Str "Normal",Space,Str "Link:",Space,Link ("",[],[]) [Str "http://wikicreole.org/"] ("http://wikicreole.org/",""),Space,Str "-",Space,Str "now",Space,Str "same",Space,Str "link,",Space,Str "but",Space,Str "escaped:",Space,Str "http://wikicreole.org/"]+,Para [Str "Normal",Space,Str "asterisks:",Space,Str "**not",Space,Str "bold**"]+,Para [Str "a",Space,Str "tilde",Space,Str "alone:",Space,Str "~"]+,Para [Str "a",Space,Str "tilde",Space,Str "escapes",Space,Str "itself:",Space,Str "~xxx"]+,Header 3 ("",[],[]) [Str "Creole 0.2"]+,Para [Str "This",Space,Str "should",Space,Str "be",Space,Str "a",Space,Str "flower",Space,Str "with",Space,Str "the",Space,Str "ALT",Space,Str "text",Space,Str "\"this",Space,Str "is",Space,Str "a",Space,Str "flower\"",Space,Str "if",Space,Str "your",Space,Str "wiki",Space,Str "supports",Space,Str "ALT",Space,Str "text",Space,Str "on",Space,Str "images:"]+,Para [Image ("",[],[]) [Str "here is a red flower"] ("Red-Flower.jpg","")]+,Header 3 ("",[],[]) [Str "Creole 0.4"]+,Para [Str "Tables",Space,Str "are",Space,Str "done",Space,Str "like",Space,Str "this:"]+,Table [] [AlignDefault,AlignDefault] [0.0,0.0]+ [[Plain [Str "header",Space,Str "col1"]]+ ,[Plain [Str "header",Space,Str "col2"]]]+ [[[Plain [Str "col1"]]+  ,[Plain [Str "col2"]]]+ ,[[Plain [Str "you"]]+  ,[Plain [Str "can"]]]+ ,[[Plain [Str "also"]]+  ,[Plain [Str "align",LineBreak,Str "it."]]]]+,Para [Str "You",Space,Str "can",Space,Str "format",Space,Str "an",Space,Str "address",Space,Str "by",Space,Str "simply",Space,Str "forcing",Space,Str "linebreaks:"]+,Para [Str "My",Space,Str "contact",Space,Str "dates:",LineBreak,Str "Pone:",Space,Str "xyz",LineBreak,Str "Fax:",Space,Str "+45",LineBreak,Str "Mobile:",Space,Str "abc"]+,Header 3 ("",[],[]) [Str "Creole 0.5"]+,Table [] [AlignDefault,AlignDefault] [0.0,0.0]+ [[Plain [Str "Header",Space,Str "title"]]+ ,[Plain [Str "Another",Space,Str "header",Space,Str "title"]]]+ [[[Plain [Code ("",[],[]) " //not italic text// "]]+  ,[Plain [Code ("",[],[]) " **not bold text** "]]]+ ,[[Plain [Emph [Str "italic",Space,Str "text"]]]+  ,[Plain [Strong [Space,Str "bold",Space,Str "text",Space]]]]]+,Header 3 ("",[],[]) [Str "Creole 1.0"]+,Para [Str "If",Space,Str "interwiki",Space,Str "links",Space,Str "are",Space,Str "setup",Space,Str "in",Space,Str "your",Space,Str "wiki,",Space,Str "this",Space,Str "links",Space,Str "to",Space,Str "the",Space,Str "WikiCreole",Space,Str "page",Space,Str "about",Space,Str "Creole",Space,Str "1.0",Space,Str "test",Space,Str "cases:",Space,Link ("",[],[]) [Str "WikiCreole:Creole1.0TestCases"] ("WikiCreole:Creole1.0TestCases",""),Str "."]+,HorizontalRule+,Para [Str "The",Space,Str "above",Space,Str "test",Space,Str "document",Space,Str "was",Space,Str "found",Space,Str "on",Space,Link ("",[],[]) [Str "http://www.wikicreole.org/wiki/Creole1.0TestCases"] ("http://www.wikicreole.org/wiki/Creole1.0TestCases",""),Space,Str "and",Space,Str "downloaded",Space,Str "from",Space,Link ("",[],[]) [Str "http://www.wikicreole.org/attach/Creole1.0TestCases/creole1.0test.txt"] ("http://www.wikicreole.org/attach/Creole1.0TestCases/creole1.0test.txt",""),Str "."]+,Para [Str "The",Space,Str "Creole",Space,Str "Wiki",Space,Str "is",Space,Str "licensed:",Space,Str "Copyright",Space,Str "(C)",Space,Str "by",Space,Str "the",Space,Str "contributors.",Space,Str "Some",Space,Str "rights",Space,Str "reserved,",Space,Str "license",Space,Link ("",[],[]) [Str "https://creativecommons.org/licenses/by-sa/1.0/"] ("BY-SA",""),Str "."]]
+ test/creole-reader.txt view
@@ -0,0 +1,137 @@+= Top-level heading (1)+== This a test for creole 0.1 (2)+=== This is a Subheading (3)+==== Subsub (4)+===== Subsubsub (5)++The ending equal signs should not be displayed:++= Top-level heading (1) =+== This a test for creole 0.1 (2) ==+=== This is a Subheading (3) ===+==== Subsub (4) ====+===== Subsubsub (5) =====+++You can make things **bold** or //italic// or **//both//** or //**both**//.++Character formatting extends across line breaks: **bold,+this is still bold. This line deliberately does not end in star-star.++Not bold. Character formatting does not cross paragraph boundaries.++You can use [[internal links]] or [[http://www.wikicreole.org|external links]],+give the link a [[internal links|different]] name.++Here's another sentence: This wisdom is taken from [[Ward Cunningham's]]+[[http://www.c2.com/doc/wikisym/WikiSym2006.pdf|Presentation at the Wikisym 06]].++Here's a external link without a description: [[http://www.wikicreole.org]]++Be careful that italic links are rendered properly:  //[[http://my.book.example/|My Book Title]]// ++Free links without braces should be rendered as well, like http://www.wikicreole.org/ and http://www.wikicreole.org/users/~example. ++Creole1.0 specifies that http://bar and ftp://bar should not render italic,+something like foo://bar should render as italic.++You can use this to draw a line to separate the page:+----++You can use lists, start it at the first column for now, please...++unnumbered lists are like+* item a+* item b+* **bold item c**++blank space is also permitted before lists like:+  *   item a+ * item b+* item c+ ** item c.a++or you can number them+# [[item 1]]+# item 2+# // italic item 3 //+    ## item 3.1+  ## item 3.2++up to five levels+* 1+** 2+*** 3+**** 4+***** 5++* You can have+multiline list items+* this is a second multiline+list item++You can use nowiki syntax if you would like do stuff like this:++{{{+Guitar Chord C:++||---|---|---|+||-0-|---|---|+||---|---|---|+||---|-0-|---|+||---|---|-0-|+||---|---|---|+}}}++You can also use it inline nowiki {{{ in a sentence }}} like this.++= Escapes =+Normal Link: http://wikicreole.org/ - now same link, but escaped: ~http://wikicreole.org/ ++Normal asterisks: ~**not bold~**++a tilde alone: ~++a tilde escapes itself: ~~xxx++=== Creole 0.2 ===++This should be a flower with the ALT text "this is a flower" if your wiki supports ALT text on images:++{{Red-Flower.jpg|here is a red flower}}++=== Creole 0.4 ===++Tables are done like this:++|=header col1|=header col2| +|col1|col2| +|you         |can         | +|also        |align\\ it. | ++You can format an address by simply forcing linebreaks:++My contact dates:\\+Pone: xyz\\+Fax: +45\\+Mobile: abc++=== Creole 0.5 ===++|= Header title               |= Another header title     |+| {{{ //not italic text// }}} | {{{ **not bold text** }}} |+| //italic text//             | **  bold text **          |++=== Creole 1.0 ===++If interwiki links are setup in your wiki, this links to the WikiCreole page about Creole 1.0 test cases: [[WikiCreole:Creole1.0TestCases]].++  ----++The above test document was found on+http://www.wikicreole.org/wiki/Creole1.0TestCases and downloaded from+http://www.wikicreole.org/attach/Creole1.0TestCases/creole1.0test.txt.++The Creole Wiki is licensed: Copyright (C) by the contributors. Some+rights reserved, license+[[BY-SA|https://creativecommons.org/licenses/by-sa/1.0/]].
+ test/docbook-reader.docbook view
@@ -0,0 +1,1561 @@+<?xml version="1.0" encoding="utf-8" ?>+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"+                  "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">+<article>+  <articleinfo>+    <title>Pandoc Test Suite</title>+    <authorgroup>+      <author>+        <firstname>John</firstname>+        <surname>MacFarlane</surname>+      </author>+      <author>+        <firstname></firstname>+        <surname>Anonymous</surname>+      </author>+    </authorgroup>+    <date>July 17, 2006</date>+  </articleinfo>+<para>+  This is a set of tests for pandoc. Most of them are adapted from John+  Gruber’s markdown test suite.+</para>+<sect1 id="headers">+  <title>Headers</title>+  <sect2 id="level-2-with-an-embedded-link">+    <title>Level 2 with an <ulink url="/url">embedded link</ulink></title>+    <sect3 id="level-3-with-emphasis">+      <title>Level 3 with <emphasis>emphasis</emphasis></title>+      <sect4 id="level-4">+        <title>Level 4</title>+        <sect5 id="level-5">+          <title>Level 5</title>+          <para>+            Hi.+          </para>+        </sect5>+      </sect4>+    </sect3>+  </sect2>+</sect1>+<sect1 id="level-1">+  <title>Level 1</title>+  <sect2 id="level-2-with-emphasis">+    <title>Level 2 with <emphasis>emphasis</emphasis></title>+    <sect3 id="level-3">+      <title>Level 3</title>+      <para>+        with no blank line+      </para>+    </sect3>+  </sect2>+  <sect2 id="level-2">+    <title>Level 2</title>+    <para>+      with no blank line+    </para>+  </sect2>+</sect1>+<sect1 id="paragraphs">+  <title>Paragraphs</title>+  <para>+    Here’s a regular paragraph.+  </para>+  <para>+    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.+  </para>+  <para>+    Here’s one with a bullet. * criminey.+  </para>+</sect1>+<sect1 id="block-quotes">+  <title>Block Quotes</title>+  <para>+    E-mail style:+  </para>+  <blockquote>+    <para>+      This is a block quote. It is pretty short.+    </para>+  </blockquote>+  <blockquote>+    <para>+      Code in a block quote:+    </para>+    <programlisting>+sub status {+    print &quot;working&quot;;+}+</programlisting>+    <screen>+% <command>ls</command>+</screen>+    <para>+      A list:+    </para>+    <orderedlist numeration="arabic">+      <listitem>+        <para>+          item one+        </para>+      </listitem>+      <listitem>+        <para>+          item two+        </para>+      </listitem>+    </orderedlist>+    <para>+      Nested block quotes:+    </para>+    <blockquote>+      <para>+        nested+      </para>+    </blockquote>+    <blockquote>+      <para>+        nested+      </para>+    </blockquote>+  </blockquote>+  <para>+    This should not be a block quote: 2 &gt; 1.+  </para>+  <para>+    And a following paragraph.+  </para>+</sect1>+<sect1 id="code-blocks">+  <title>Code Blocks</title>+  <para>+    Code:+  </para>+  <programlisting>+---- (should be four hyphens)++sub status {+    print &quot;working&quot;;+}++this code block is indented by one tab+</programlisting>+  <para>+    And:+  </para>+  <programlisting>+    this code block is indented by two tabs++These should not be escaped:  \$ \\ \&gt; \[ \{+</programlisting>+</sect1>+<sect1 id="lists">+  <title>Lists</title>+  <sect2 id="unordered">+    <title>Unordered</title>+    <para>+      Asterisks loose:+    </para>+    <itemizedlist>+      <listitem>+        <para>+          asterisk 1+        </para>+      </listitem>+      <listitem>+        <para>+          asterisk 2+        </para>+      </listitem>+      <listitem>+        <para>+          asterisk 3+        </para>+      </listitem>+    </itemizedlist>+    <para>+      Pluses loose:+    </para>+    <itemizedlist>+      <listitem>+        <para>+          Plus 1+        </para>+      </listitem>+      <listitem>+        <para>+          Plus 2+        </para>+      </listitem>+      <listitem>+        <para>+          Plus 3+        </para>+      </listitem>+    </itemizedlist>+    <para>+      Minuses loose:+    </para>+    <itemizedlist>+      <listitem>+        <para>+          Minus 1+        </para>+      </listitem>+      <listitem>+        <para>+          Minus 2+        </para>+      </listitem>+      <listitem>+        <para>+          Minus 3+        </para>+      </listitem>+    </itemizedlist>+  </sect2>+  <sect2 id="ordered">+    <title>Ordered</title>+    <orderedlist numeration="arabic">+      <listitem>+        <para>+          First+        </para>+      </listitem>+      <listitem>+        <para>+          Second+        </para>+      </listitem>+      <listitem>+        <para>+          Third+        </para>+      </listitem>+    </orderedlist>+    <para>+      and using spaces:+    </para>+    <orderedlist numeration="arabic">+      <listitem>+        <para>+          One+        </para>+      </listitem>+      <listitem>+        <para>+          Two+        </para>+      </listitem>+      <listitem>+        <para>+          Three+        </para>+      </listitem>+    </orderedlist>+    <para>+      Multiple paragraphs:+    </para>+    <orderedlist numeration="arabic">+      <listitem>+        <para>+          Item 1, graf one.+        </para>+        <para>+          Item 1. graf two. The quick brown fox jumped over the lazy dog’s+          back.+        </para>+      </listitem>+      <listitem>+        <para>+          Item 2.+        </para>+      </listitem>+      <listitem>+        <para>+          Item 3.+        </para>+      </listitem>+    </orderedlist>+  </sect2>+  <sect2 id="nested">+    <title>Nested</title>+    <itemizedlist>+      <listitem>+        <para>+          Tab+        </para>+        <itemizedlist>+          <listitem>+            <para>+              Tab+            </para>+            <itemizedlist>+              <listitem>+                <para>+                  Tab+                </para>+              </listitem>+            </itemizedlist>+          </listitem>+        </itemizedlist>+      </listitem>+    </itemizedlist>+    <para>+      Here’s another:+    </para>+    <orderedlist numeration="arabic">+      <listitem>+        <para>+          First+        </para>+      </listitem>+      <listitem>+        <para>+          Second:+        </para>+        <itemizedlist>+          <listitem>+            <para>+              Fee+            </para>+          </listitem>+          <listitem>+            <para>+              Fie+            </para>+          </listitem>+          <listitem>+            <para>+              Foe+            </para>+          </listitem>+        </itemizedlist>+      </listitem>+      <listitem>+        <para>+          Third+        </para>+      </listitem>+    </orderedlist>+    <para>+      Same thing but with paragraphs:+    </para>+    <orderedlist numeration="arabic">+      <listitem>+        <para>+          First+        </para>+      </listitem>+      <listitem>+        <para>+          Second:+        </para>+        <itemizedlist>+          <listitem>+            <para>+              Fee+            </para>+          </listitem>+          <listitem>+            <para>+              Fie+            </para>+          </listitem>+          <listitem>+            <para>+              Foe+            </para>+          </listitem>+        </itemizedlist>+      </listitem>+      <listitem>+        <para>+          Third+        </para>+      </listitem>+    </orderedlist>+  </sect2>+  <sect2 id="tabs-and-spaces">+    <title>Tabs and spaces</title>+    <itemizedlist>+      <listitem>+        <para>+          this is a list item indented with tabs+        </para>+      </listitem>+      <listitem>+        <para>+          this is a list item indented with spaces+        </para>+        <itemizedlist>+          <listitem>+            <para>+              this is an example list item indented with tabs+            </para>+          </listitem>+          <listitem>+            <para>+              this is an example list item indented with spaces+            </para>+          </listitem>+        </itemizedlist>+      </listitem>+    </itemizedlist>+  </sect2>+  <sect2 id="fancy-list-markers">+    <title>Fancy list markers</title>+    <orderedlist numeration="arabic">+      <listitem override="2">+        <para>+          begins with 2+        </para>+      </listitem>+      <listitem>+        <para>+          and now 3+        </para>+        <para>+          with a continuation+        </para>+        <orderedlist numeration="lowerroman">+          <listitem override="4">+            <para>+              sublist with roman numerals, starting with 4+            </para>+          </listitem>+          <listitem>+            <para>+              more items+            </para>+            <orderedlist numeration="upperalpha">+              <listitem>+                <para>+                  a subsublist+                </para>+              </listitem>+              <listitem>+                <para>+                  a subsublist+                </para>+              </listitem>+            </orderedlist>+          </listitem>+        </orderedlist>+      </listitem>+    </orderedlist>+    <para>+      Nesting:+    </para>+    <orderedlist numeration="upperalpha">+      <listitem>+        <para>+          Upper Alpha+        </para>+        <orderedlist numeration="upperroman">+          <listitem>+            <para>+              Upper Roman.+            </para>+            <orderedlist numeration="arabic">+              <listitem override="6">+                <para>+                  Decimal start with 6+                </para>+                <orderedlist numeration="loweralpha">+                  <listitem override="3">+                    <para>+                      Lower alpha with paren+                    </para>+                  </listitem>+                </orderedlist>+              </listitem>+            </orderedlist>+          </listitem>+        </orderedlist>+      </listitem>+    </orderedlist>+    <para>+      Autonumbering:+    </para>+    <orderedlist>+      <listitem>+        <para>+          Autonumber.+        </para>+      </listitem>+      <listitem>+        <para>+          More.+        </para>+        <orderedlist>+          <listitem>+            <para>+              Nested.+            </para>+          </listitem>+        </orderedlist>+      </listitem>+    </orderedlist>+    <para>+      Should not be a list item:+    </para>+    <para>+      M.A. 2007+    </para>+    <para>+      B. Williams+    </para>+  </sect2>+  <sect2 id="callout">+    <title>Callout</title>+    <para>Simple.</para>+      <calloutlist>+	<callout arearefs="loop1-letrec-co" id="loop1-letrec">+	  <para id="x_QA1">A <code>__letrec</code> is equivalent to a normal+	    Haskell &let;.</para>+	</callout>+	<callout arearefs="loop1-def-co" id="loop1-def">+	  <para id="x_RA1">&GHC; compiled the body of our list comprehension into+	    a loop named <function>go_s1YC</function>.</para>+	</callout>+	<callout arearefs="loop1-pat-empty-co" id="loop1-pat-empty">+	  <para id="x_SA1">If our &case; expression matches the empty list, we+	    return the empty list.  This is reassuringly+	    familiar.</para>+	</callout>+      </calloutlist>+  </sect2>+</sect1>+<sect1 id="definition-lists">+  <title>Definition Lists</title>+  <variablelist>+    <varlistentry>+      <term>+        apple+      </term>+      <listitem>+        <para>+          red fruit+        </para>+      </listitem>+    </varlistentry>+    <varlistentry>+      <term>+        orange+      </term>+      <listitem>+        <para>+          orange fruit+        </para>+      </listitem>+    </varlistentry>+    <varlistentry>+      <term>+        banana+      </term>+      <listitem>+        <para>+          yellow fruit+        </para>+      </listitem>+    </varlistentry>+  </variablelist>+  <para>+    Multiple blocks with italics:+  </para>+  <variablelist>+    <varlistentry>+      <term>+        <emphasis>apple</emphasis>+      </term>+      <listitem>+        <para>+          red fruit+        </para>+        <para>+          contains seeds, crisp, pleasant to taste+        </para>+      </listitem>+    </varlistentry>+    <varlistentry>+      <term>+        <emphasis>orange</emphasis>+      </term>+      <listitem>+        <para>+          orange fruit+        </para>+        <programlisting>+{ orange code block }+</programlisting>+        <blockquote>+          <para>+            orange block quote+          </para>+        </blockquote>+      </listitem>+    </varlistentry>+  </variablelist>+  <para>+    Multiple definitions, loose:+  </para>+  <variablelist>+    <varlistentry>+      <term>+        apple+      </term>+      <listitem>+        <para>+          red fruit+        </para>+      </listitem>+      <listitem>+        <para>+          computer+        </para>+      </listitem>+    </varlistentry>+    <varlistentry>+      <term>+        orange+      </term>+      <listitem>+        <para>+          orange fruit+        </para>+      </listitem>+      <listitem>+        <para>+          bank+        </para>+      </listitem>+    </varlistentry>+  </variablelist>+  <para>+    Blank line after term, indented marker, alternate markers:+  </para>+  <variablelist>+    <varlistentry>+      <term>+        apple+      </term>+      <listitem>+        <para>+          red fruit+        </para>+      </listitem>+      <listitem>+        <para>+          computer+        </para>+      </listitem>+    </varlistentry>+    <varlistentry>+      <term>+        orange+      </term>+      <listitem>+        <para>+          orange fruit+        </para>+        <orderedlist numeration="arabic">+          <listitem>+            <para>+              sublist+            </para>+          </listitem>+          <listitem>+            <para>+              sublist+            </para>+          </listitem>+        </orderedlist>+      </listitem>+    </varlistentry>+  </variablelist>+</sect1>+<sect1 id="inline-markup">+  <title>Inline Markup</title>+  <para>+    This is <emphasis>emphasized</emphasis>, and so <emphasis>is+    this</emphasis>.+  </para>+  <para>+    This is <emphasis role="strong">strong</emphasis>, and so+    <emphasis role="strong">is this</emphasis>.+  </para>+  <para>+    An <emphasis><ulink url="/url">emphasized link</ulink></emphasis>.+  </para>+  <para>+    <emphasis role="strong"><emphasis>This is strong and+    em.</emphasis></emphasis>+  </para>+  <para>+    So is <emphasis role="strong"><emphasis>this</emphasis></emphasis> word.+  </para>+  <para>+    <emphasis role="strong"><emphasis>This is strong and+    em.</emphasis></emphasis>+  </para>+  <para>+    So is <emphasis role="strong"><emphasis>this</emphasis></emphasis> word.+  </para>+  <para>+    This is code: <literal>&gt;</literal>, <literal>$</literal>,+    <literal>\</literal>, <literal>\$</literal>,+    <literal>&lt;html&gt;</literal>.+  </para>+  <para>+    More code: <classname>Class</classname> and <type>Type</type>+  </para>+  <para>+    <emphasis role="strikethrough">This is+    <emphasis>strikeout</emphasis>.</emphasis>+  </para>+  <para>+    Superscripts: a<superscript>bc</superscript>d+    a<superscript><emphasis>hello</emphasis></superscript>+    a<superscript>hello there</superscript>.+  </para>+  <para>+    Subscripts: H<subscript>2</subscript>O, H<subscript>23</subscript>O,+    H<subscript>many of them</subscript>O.+  </para>+  <para>+    These should not be superscripts or subscripts, because of the unescaped+    spaces: a^b c^d, a~b c~d.+  </para>+</sect1>+<sect1 id="smart-quotes-ellipses-dashes">+  <title>Smart quotes, ellipses, dashes</title>+  <para>+    <quote>Hello,</quote> said the spider. <quote><quote>Shelob</quote> is my+    name.</quote>+  </para>+  <para>+    <quote>A</quote>, <quote>B</quote>, and <quote>C</quote> are letters.+  </para>+  <para>+    <quote>He said, <quote>I want to go.</quote></quote> Were you alive in the+    70’s?+  </para>+  <para>+    Some dashes: one—two — three—four — five.+  </para>+  <para>+    Dashes between numbers: 5–7, 255–66, 1987–1999.+  </para>+  <para>+    Ellipses…and…and….+  </para>+</sect1>+<sect1 id="math">+  <para>+    <equation>+      <mml:math>+        <mml:mrow>+          <mml:mi>e</mml:mi>+          <mml:mo>=</mml:mo>+          <mml:mi>m</mml:mi>+          <mml:msup>+            <mml:mi>c</mml:mi>+            <mml:mn>2</mml:mn>+          </mml:msup>+        </mml:mrow>+      </mml:math>+      <mml:math>+        <mrow>+          <mn>1</mn>+        </mrow>+      </mml:math>+    </equation>+    <inlineequation>+      <mml:math>+        <mml:mrow>+          <mml:mi>e</mml:mi>+          <mml:mo>=</mml:mo>+          <mml:mi>m</mml:mi>+          <mml:msup>+            <mml:mi>c</mml:mi>+            <mml:mn>2</mml:mn>+          </mml:msup>+        </mml:mrow>+      </mml:math>+    </inlineequation>+    <informalequation>+      <mml:math>+        <mml:mrow>+          <mml:mi>e</mml:mi>+          <mml:mo>=</mml:mo>+          <mml:mi>m</mml:mi>+          <mml:msup>+            <mml:mi>c</mml:mi>+            <mml:mn>2</mml:mn>+          </mml:msup>+        </mml:mrow>+      </mml:math>+    </informalequation>+  </para>+</sect1>+<sect1 id="special-characters">+  <title>Special Characters</title>+  <para>+    Here is some unicode:+  </para>+  <itemizedlist>+    <listitem>+      <para>+        I hat: Î+      </para>+    </listitem>+    <listitem>+      <para>+        o umlaut: ö+      </para>+    </listitem>+    <listitem>+      <para>+        section: §+      </para>+    </listitem>+    <listitem>+      <para>+        set membership: ∈+      </para>+    </listitem>+    <listitem>+      <para>+        copyright: ©+      </para>+    </listitem>+  </itemizedlist>+  <para>+    AT&amp;T has an ampersand in their name.+  </para>+  <para>+    AT&amp;T is another way to write it.+  </para>+  <para>+    This &amp; that.+  </para>+  <para>+    4 &lt; 5.+  </para>+  <para>+    6 &gt; 5.+  </para>+  <para>+    Backslash: \+  </para>+  <para>+    Backtick: `+  </para>+  <para>+    Asterisk: *+  </para>+  <para>+    Underscore: _+  </para>+  <para>+    Left brace: {+  </para>+  <para>+    Right brace: }+  </para>+  <para>+    Left bracket: [+  </para>+  <para>+    Right bracket: ]+  </para>+  <para>+    Left paren: (+  </para>+  <para>+    Right paren: )+  </para>+  <para>+    Greater-than: &gt;+  </para>+  <para>+    Hash: #+  </para>+  <para>+    Period: .+  </para>+  <para>+    Bang: !+  </para>+  <para>+    Plus: ++  </para>+  <para>+    Minus: -+  </para>+</sect1>+<sect1 id="links">+  <title>Links</title>+  <sect2 id="explicit">+    <title>Explicit</title>+    <para>+      Just a <ulink url="/url/">URL</ulink>.+    </para>+    <para>+      <ulink url="/url/">URL and title</ulink>.+    </para>+    <para>+      <ulink url="/url/">URL and title</ulink>.+    </para>+    <para>+      <ulink url="/url/">URL and title</ulink>.+    </para>+    <para>+      <ulink url="/url/">URL and title</ulink>+    </para>+    <para>+      <ulink url="/url/">URL and title</ulink>+    </para>+    <para>+      <ulink url="/url/with_underscore">with_underscore</ulink>+    </para>+    <para>+      <email>nobody@nowhere.net</email>+    </para>+    <para>+      <ulink url="">Empty</ulink>.+    </para>+  </sect2>+  <sect2 id="reference">+    <title>Reference</title>+    <para>+      Foo <ulink url="/url/">bar</ulink>.+    </para>+    <para>+      Foo <ulink url="/url/">bar</ulink>.+    </para>+    <para>+      Foo <ulink url="/url/">bar</ulink>.+    </para>+    <para>+      With <ulink url="/url/">embedded [brackets]</ulink>.+    </para>+    <para>+      <ulink url="/url/">b</ulink> by itself should be a link.+    </para>+    <para>+      Indented <ulink url="/url">once</ulink>.+    </para>+    <para>+      Indented <ulink url="/url">twice</ulink>.+    </para>+    <para>+      Indented <ulink url="/url">thrice</ulink>.+    </para>+    <para>+      This should [not][] be a link.+    </para>+    <programlisting>+[not]: /url+</programlisting>+    <para>+      Foo <ulink url="/url/">bar</ulink>.+    </para>+    <para>+      Foo <ulink url="/url/">biz</ulink>.+    </para>+  </sect2>+  <sect2 id="with-ampersands">+    <title>With ampersands</title>+    <para>+      Here’s a <ulink url="http://example.com/?foo=1&amp;bar=2">link with an+      ampersand in the URL</ulink>.+    </para>+    <para>+      Here’s a link with an amersand in the link text:+      <ulink url="http://att.com/">AT&amp;T</ulink>.+    </para>+    <para>+      Here’s an <ulink url="/script?foo=1&amp;bar=2">inline link</ulink>.+    </para>+    <para>+      Here’s an <ulink url="/script?foo=1&amp;bar=2">inline link in pointy+      braces</ulink>.+    </para>+  </sect2>+  <sect2 id="autolinks">+    <title>Autolinks</title>+    <para>+      With an ampersand:+      <ulink url="http://example.com/?foo=1&amp;bar=2">http://example.com/?foo=1&amp;bar=2</ulink>+    </para>+    <itemizedlist>+      <listitem>+        <para>+          In a list?+        </para>+      </listitem>+      <listitem>+        <para>+          <ulink url="http://example.com/">http://example.com/</ulink>+        </para>+      </listitem>+      <listitem>+        <para>+          It should.+        </para>+      </listitem>+    </itemizedlist>+    <para>+      An e-mail address: <email>nobody@nowhere.net</email>+    </para>+    <blockquote>+      <para>+        Blockquoted:+        <ulink url="http://example.com/">http://example.com/</ulink>+      </para>+    </blockquote>+    <para>+      Auto-links should not occur here:+      <literal>&lt;http://example.com/&gt;</literal>+    </para>+    <programlisting>+or here: &lt;http://example.com/&gt;+</programlisting>+  </sect2>+</sect1>+<sect1 id="images">+  <title>Images</title>+  <para>+    From <quote>Voyage dans la Lune</quote> by Georges Melies (1902):+  </para>+  <figure>+    <title>lalune fig caption</title>+    <mediaobject>+      <imageobject>+        <imagedata fileref="lalune.jpg" />+      </imageobject>+      <textobject><phrase>lalune alt text shadowed by fig caption</phrase></textobject>+    </mediaobject>+  </figure>+  <para>+    Here is a movie <inlinemediaobject>+      <imageobject>+        <imagedata fileref="movie.jpg" />+      </imageobject>+    </inlinemediaobject> icon.+    And here a second movie <inlinemediaobject>+      <alt>alt text</alt>+      <imageobject>+        <imagedata fileref="movie.jpg" />+      </imageobject>+    </inlinemediaobject> icon.+    And here a third movie <inlinemediaobject>+      <textobject><phrase>alt text</phrase></textobject>+      <imageobject>+        <imagedata fileref="movie.jpg" />+      </imageobject>+    </inlinemediaobject> icon.+  </para>+  <mediaobject>+    <imageobject>+      <imagedata fileref="lalune.jpg" />+    </imageobject>+    <textobject><phrase>lalune no figure alt text</phrase></textobject>+  </mediaobject>+</sect1>+<sect1 id="footnotes">+  <title>Footnotes</title>+  <para>+    Here is a footnote reference,<footnote>+      <para>+        Here is the footnote. It can go anywhere after the footnote reference.+        It need not be placed at the end of the document.+      </para>+    </footnote> and another.<footnote>+      <para>+        Here’s the long note. This one contains multiple blocks.+      </para>+      <para>+        Subsequent blocks are indented to show that they belong to the+        footnote (as with list items).+      </para>+      <programlisting>+  { &lt;code&gt; }+</programlisting>+      <para>+        If you want, you can indent every line, but you can also be lazy and+        just indent the first line of each block.+      </para>+    </footnote> This should <emphasis>not</emphasis> be a footnote reference,+    because it contains a space.[^my note] Here is an inline note.<footnote>+      <para>+        This is <emphasis>easier</emphasis> to type. Inline notes may contain+        <ulink url="http://google.com">links</ulink> and <literal>]</literal>+        verbatim characters, as well as [bracketed text].+      </para>+    </footnote>+  </para>+  <blockquote>+    <para>+      Notes can go in quotes.<footnote>+        <para>+          In quote.+        </para>+      </footnote>+    </para>+  </blockquote>+  <orderedlist numeration="arabic">+    <listitem>+      <para>+        And in list items.<footnote>+          <para>+            In list.+          </para>+        </footnote>+      </para>+    </listitem>+  </orderedlist>+  <para>+    This paragraph should not be part of the note, as it is not indented.+  </para>+</sect1>+<sect1 id="tables">+  <title>Tables</title>+  <para>+    Simple table with caption:+  </para>+  <table>+    <title>+      Demonstration of simple table syntax.+    </title>+    <tgroup cols="4">+      <colspec align="right" />+      <colspec align="left" />+      <colspec align="center" />+      <colspec align="left" />+      <thead>+        <row>+          <entry>+            Right+          </entry>+          <entry>+            Left+          </entry>+          <entry>+            Center+          </entry>+          <entry>+            Default+          </entry>+        </row>+      </thead>+      <tbody>+        <row>+          <entry>+            12+          </entry>+          <entry>+            12+          </entry>+          <entry>+            12+          </entry>+          <entry>+            12+          </entry>+        </row>+        <row>+          <entry>+            123+          </entry>+          <entry>+            123+          </entry>+          <entry>+            123+          </entry>+          <entry>+            123+          </entry>+        </row>+        <row>+          <entry>+            1+          </entry>+          <entry>+            1+          </entry>+          <entry>+            1+          </entry>+          <entry>+            1+          </entry>+        </row>+      </tbody>+    </tgroup>+  </table>+  <para>+    Simple table without caption:+  </para>+  <informaltable>+    <tgroup cols="4">+      <colspec align="right" />+      <colspec align="left" />+      <colspec align="center" />+      <colspec align="left" />+      <thead>+        <row>+          <entry>+            Right+          </entry>+          <entry>+            Left+          </entry>+          <entry>+            Center+          </entry>+          <entry>+            Default+          </entry>+        </row>+      </thead>+      <tbody>+        <row>+          <entry>+            12+          </entry>+          <entry>+            12+          </entry>+          <entry>+            12+          </entry>+          <entry>+            12+          </entry>+        </row>+        <row>+          <entry>+            123+          </entry>+          <entry>+            123+          </entry>+          <entry>+            123+          </entry>+          <entry>+            123+          </entry>+        </row>+        <row>+          <entry>+            1+          </entry>+          <entry>+            1+          </entry>+          <entry>+            1+          </entry>+          <entry>+            1+          </entry>+        </row>+      </tbody>+    </tgroup>+  </informaltable>+  <para>+    Simple table indented two spaces:+  </para>+  <table>+    <title>+      Demonstration of simple table syntax.+    </title>+    <tgroup cols="4">+      <colspec align="right" />+      <colspec align="left" />+      <colspec align="center" />+      <colspec align="left" />+      <thead>+        <row>+          <entry>+            Right+          </entry>+          <entry>+            Left+          </entry>+          <entry>+            Center+          </entry>+          <entry>+            Default+          </entry>+        </row>+      </thead>+      <tbody>+        <row>+          <entry>+            12+          </entry>+          <entry>+            12+          </entry>+          <entry>+            12+          </entry>+          <entry>+            12+          </entry>+        </row>+        <row>+          <entry>+            123+          </entry>+          <entry>+            123+          </entry>+          <entry>+            123+          </entry>+          <entry>+            123+          </entry>+        </row>+        <row>+          <entry>+            1+          </entry>+          <entry>+            1+          </entry>+          <entry>+            1+          </entry>+          <entry>+            1+          </entry>+        </row>+      </tbody>+    </tgroup>+  </table>+  <para>+    Multiline table with caption:+  </para>+  <table>+    <title>+      Here's the caption. It may span multiple lines.+    </title>+    <tgroup cols="4">+      <colspec colwidth="2*" align="center" />+      <colspec colwidth="2*" align="left" />+      <colspec colwidth="3*" align="right" />+      <colspec colwidth="3*" align="left" />+      <thead>+        <row>+          <entry>+            Centered Header+          </entry>+          <entry>+            Left Aligned+          </entry>+          <entry>+            Right Aligned+          </entry>+          <entry>+            Default aligned+          </entry>+        </row>+      </thead>+      <tbody>+        <row>+          <entry>+            First+          </entry>+          <entry>+            row+          </entry>+          <entry>+            12.0+          </entry>+          <entry>+            Example of a row that spans multiple lines.+          </entry>+        </row>+        <row>+          <entry>+            Second+          </entry>+          <entry>+            row+          </entry>+          <entry>+            5.0+          </entry>+          <entry>+            Here's another one. Note the blank line between rows.+          </entry>+        </row>+      </tbody>+    </tgroup>+  </table>+  <para>+    Multiline table without caption:+  </para>+  <informaltable>+    <tgroup cols="4">+      <colspec colwidth="1*" align="center" />+      <colspec colwidth="2*" align="left" />+      <colspec colwidth="3*" align="right" />+      <colspec colwidth="4*" align="left" />+      <thead>+        <row>+          <entry>+            Centered Header+          </entry>+          <entry>+            Left Aligned+          </entry>+          <entry>+            Right Aligned+          </entry>+          <entry>+            Default aligned+          </entry>+        </row>+      </thead>+      <tbody>+        <row>+          <entry>+            First+          </entry>+          <entry>+            row+          </entry>+          <entry>+            12.0+          </entry>+          <entry>+            Example of a row that spans multiple lines.+          </entry>+        </row>+        <row>+          <entry>+            Second+          </entry>+          <entry>+            row+          </entry>+          <entry>+            5.0+          </entry>+          <entry>+            Here's another one. Note the blank line between rows.+          </entry>+        </row>+      </tbody>+    </tgroup>+  </informaltable>+  <para>+    Table without column headers:+  </para>+  <informaltable>+    <tgroup cols="4">+      <colspec align="right" />+      <colspec align="left" />+      <colspec align="center" />+      <colspec align="right" />+      <tbody>+        <row>+          <entry>+            12+          </entry>+          <entry>+            12+          </entry>+          <entry>+            12+          </entry>+          <entry>+            12+          </entry>+        </row>+        <row>+          <entry>+            123+          </entry>+          <entry>+            123+          </entry>+          <entry>+            123+          </entry>+          <entry>+            123+          </entry>+        </row>+        <row>+          <entry>+            1+          </entry>+          <entry>+            1+          </entry>+          <entry>+            1+          </entry>+          <entry>+            1+          </entry>+        </row>+      </tbody>+    </tgroup>+  </informaltable>+  <para>+    Multiline table without column headers:+  </para>+  <informaltable>+    <tgroup cols="4">+      <colspec colwidth="10*" align="center" />+      <colspec colwidth="10*" align="left" />+      <colspec colwidth="10*" align="right" />+      <colspec colwidth="10*" align="left" />+      <tbody>+        <row>+          <entry>+            First+          </entry>+          <entry>+            row+          </entry>+          <entry>+            12.0+          </entry>+          <entry>+            Example of a row that spans multiple lines.+          </entry>+        </row>+        <row>+          <entry>+            Second+          </entry>+          <entry>+            row+          </entry>+          <entry>+            5.0+          </entry>+          <entry>+            Here's another one. Note the blank line between rows.+          </entry>+        </row>+      </tbody>+    </tgroup>+  </informaltable>+</sect1>+</article>
+ test/docbook-reader.native view
@@ -0,0 +1,397 @@+Pandoc (Meta {unMeta = fromList [("author",MetaList [MetaInlines [Str "John",SoftBreak,Str "MacFarlane"],MetaInlines [Str "Anonymous"]]),("date",MetaInlines [Str "July",Space,Str "17,",Space,Str "2006"]),("title",MetaInlines [Str "Pandoc",Space,Str "Test",Space,Str "Suite"])]})+[Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "set",Space,Str "of",Space,Str "tests",Space,Str "for",Space,Str "pandoc.",Space,Str "Most",Space,Str "of",Space,Str "them",Space,Str "are",Space,Str "adapted",Space,Str "from",Space,Str "John",SoftBreak,Str "Gruber\8217s",Space,Str "markdown",Space,Str "test",Space,Str "suite."]+,Header 1 ("headers",[],[]) [Str "Headers"]+,Header 2 ("level-2-with-an-embedded-link",[],[]) [Str "Level",Space,Str "2",Space,Str "with",Space,Str "an",Space,Link ("",[],[]) [Str "embedded",Space,Str "link"] ("/url","")]+,Header 3 ("level-3-with-emphasis",[],[]) [Str "Level",Space,Str "3",Space,Str "with",Space,Emph [Str "emphasis"]]+,Header 4 ("level-4",[],[]) [Str "Level",Space,Str "4"]+,Header 5 ("level-5",[],[]) [Str "Level",Space,Str "5"]+,Para [Str "Hi."]+,Header 1 ("level-1",[],[]) [Str "Level",Space,Str "1"]+,Header 2 ("level-2-with-emphasis",[],[]) [Str "Level",Space,Str "2",Space,Str "with",Space,Emph [Str "emphasis"]]+,Header 3 ("level-3",[],[]) [Str "Level",Space,Str "3"]+,Para [Str "with",Space,Str "no",Space,Str "blank",Space,Str "line"]+,Header 2 ("level-2",[],[]) [Str "Level",Space,Str "2"]+,Para [Str "with",Space,Str "no",Space,Str "blank",Space,Str "line"]+,Header 1 ("paragraphs",[],[]) [Str "Paragraphs"]+,Para [Str "Here\8217s",Space,Str "a",Space,Str "regular",Space,Str "paragraph."]+,Para [Str "In",Space,Str "Markdown",Space,Str "1.0.0",Space,Str "and",Space,Str "earlier.",Space,Str "Version",Space,Str "8.",Space,Str "This",Space,Str "line",Space,Str "turns",Space,Str "into",Space,Str "a",Space,Str "list",SoftBreak,Str "item.",Space,Str "Because",Space,Str "a",Space,Str "hard-wrapped",Space,Str "line",Space,Str "in",Space,Str "the",Space,Str "middle",Space,Str "of",Space,Str "a",Space,Str "paragraph",Space,Str "looked",Space,Str "like",SoftBreak,Str "a",Space,Str "list",Space,Str "item."]+,Para [Str "Here\8217s",Space,Str "one",Space,Str "with",Space,Str "a",Space,Str "bullet.",Space,Str "*",Space,Str "criminey."]+,Header 1 ("block-quotes",[],[]) [Str "Block",Space,Str "Quotes"]+,Para [Str "E-mail",Space,Str "style:"]+,BlockQuote+ [Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "block",Space,Str "quote.",Space,Str "It",Space,Str "is",Space,Str "pretty",Space,Str "short."]]+,BlockQuote+ [Para [Str "Code",Space,Str "in",Space,Str "a",Space,Str "block",Space,Str "quote:"]+ ,CodeBlock ("",[],[]) "sub status {\n    print \"working\";\n}"+ ,CodeBlock ("",[],[]) "% ls"+ ,Para [Str "A",Space,Str "list:"]+ ,OrderedList (1,Decimal,DefaultDelim)+  [[Para [Str "item",Space,Str "one"]]+  ,[Para [Str "item",Space,Str "two"]]]+ ,Para [Str "Nested",Space,Str "block",Space,Str "quotes:"]+ ,BlockQuote+  [Para [Str "nested"]]+ ,BlockQuote+  [Para [Str "nested"]]]+,Para [Str "This",Space,Str "should",Space,Str "not",Space,Str "be",Space,Str "a",Space,Str "block",Space,Str "quote:",Space,Str "2",Space,Str ">",Space,Str "1."]+,Para [Str "And",Space,Str "a",Space,Str "following",Space,Str "paragraph."]+,Header 1 ("code-blocks",[],[]) [Str "Code",Space,Str "Blocks"]+,Para [Str "Code:"]+,CodeBlock ("",[],[]) "---- (should be four hyphens)\n\nsub status {\n    print \"working\";\n}\n\nthis code block is indented by one tab"+,Para [Str "And:"]+,CodeBlock ("",[],[]) "    this code block is indented by two tabs\n\nThese should not be escaped:  \\$ \\\\ \\> \\[ \\{"+,Header 1 ("lists",[],[]) [Str "Lists"]+,Header 2 ("unordered",[],[]) [Str "Unordered"]+,Para [Str "Asterisks",Space,Str "loose:"]+,BulletList+ [[Para [Str "asterisk",Space,Str "1"]]+ ,[Para [Str "asterisk",Space,Str "2"]]+ ,[Para [Str "asterisk",Space,Str "3"]]]+,Para [Str "Pluses",Space,Str "loose:"]+,BulletList+ [[Para [Str "Plus",Space,Str "1"]]+ ,[Para [Str "Plus",Space,Str "2"]]+ ,[Para [Str "Plus",Space,Str "3"]]]+,Para [Str "Minuses",Space,Str "loose:"]+,BulletList+ [[Para [Str "Minus",Space,Str "1"]]+ ,[Para [Str "Minus",Space,Str "2"]]+ ,[Para [Str "Minus",Space,Str "3"]]]+,Header 2 ("ordered",[],[]) [Str "Ordered"]+,OrderedList (1,Decimal,DefaultDelim)+ [[Para [Str "First"]]+ ,[Para [Str "Second"]]+ ,[Para [Str "Third"]]]+,Para [Str "and",Space,Str "using",Space,Str "spaces:"]+,OrderedList (1,Decimal,DefaultDelim)+ [[Para [Str "One"]]+ ,[Para [Str "Two"]]+ ,[Para [Str "Three"]]]+,Para [Str "Multiple",Space,Str "paragraphs:"]+,OrderedList (1,Decimal,DefaultDelim)+ [[Para [Str "Item",Space,Str "1,",Space,Str "graf",Space,Str "one."]+  ,Para [Str "Item",Space,Str "1.",Space,Str "graf",Space,Str "two.",Space,Str "The",Space,Str "quick",Space,Str "brown",Space,Str "fox",Space,Str "jumped",Space,Str "over",Space,Str "the",Space,Str "lazy",Space,Str "dog\8217s",SoftBreak,Str "back."]]+ ,[Para [Str "Item",Space,Str "2."]]+ ,[Para [Str "Item",Space,Str "3."]]]+,Header 2 ("nested",[],[]) [Str "Nested"]+,BulletList+ [[Para [Str "Tab"]+  ,BulletList+   [[Para [Str "Tab"]+    ,BulletList+     [[Para [Str "Tab"]]]]]]]+,Para [Str "Here\8217s",Space,Str "another:"]+,OrderedList (1,Decimal,DefaultDelim)+ [[Para [Str "First"]]+ ,[Para [Str "Second:"]+  ,BulletList+   [[Para [Str "Fee"]]+   ,[Para [Str "Fie"]]+   ,[Para [Str "Foe"]]]]+ ,[Para [Str "Third"]]]+,Para [Str "Same",Space,Str "thing",Space,Str "but",Space,Str "with",Space,Str "paragraphs:"]+,OrderedList (1,Decimal,DefaultDelim)+ [[Para [Str "First"]]+ ,[Para [Str "Second:"]+  ,BulletList+   [[Para [Str "Fee"]]+   ,[Para [Str "Fie"]]+   ,[Para [Str "Foe"]]]]+ ,[Para [Str "Third"]]]+,Header 2 ("tabs-and-spaces",[],[]) [Str "Tabs",Space,Str "and",Space,Str "spaces"]+,BulletList+ [[Para [Str "this",Space,Str "is",Space,Str "a",Space,Str "list",Space,Str "item",Space,Str "indented",Space,Str "with",Space,Str "tabs"]]+ ,[Para [Str "this",Space,Str "is",Space,Str "a",Space,Str "list",Space,Str "item",Space,Str "indented",Space,Str "with",Space,Str "spaces"]+  ,BulletList+   [[Para [Str "this",Space,Str "is",Space,Str "an",Space,Str "example",Space,Str "list",Space,Str "item",Space,Str "indented",Space,Str "with",Space,Str "tabs"]]+   ,[Para [Str "this",Space,Str "is",Space,Str "an",Space,Str "example",Space,Str "list",Space,Str "item",Space,Str "indented",Space,Str "with",Space,Str "spaces"]]]]]+,Header 2 ("fancy-list-markers",[],[]) [Str "Fancy",Space,Str "list",Space,Str "markers"]+,OrderedList (2,Decimal,DefaultDelim)+ [[Para [Str "begins",Space,Str "with",Space,Str "2"]]+ ,[Para [Str "and",Space,Str "now",Space,Str "3"]+  ,Para [Str "with",Space,Str "a",Space,Str "continuation"]+  ,OrderedList (4,LowerRoman,DefaultDelim)+   [[Para [Str "sublist",Space,Str "with",Space,Str "roman",Space,Str "numerals,",Space,Str "starting",Space,Str "with",Space,Str "4"]]+   ,[Para [Str "more",Space,Str "items"]+    ,OrderedList (1,UpperAlpha,DefaultDelim)+     [[Para [Str "a",Space,Str "subsublist"]]+     ,[Para [Str "a",Space,Str "subsublist"]]]]]]]+,Para [Str "Nesting:"]+,OrderedList (1,UpperAlpha,DefaultDelim)+ [[Para [Str "Upper",Space,Str "Alpha"]+  ,OrderedList (1,UpperRoman,DefaultDelim)+   [[Para [Str "Upper",Space,Str "Roman."]+    ,OrderedList (6,Decimal,DefaultDelim)+     [[Para [Str "Decimal",Space,Str "start",Space,Str "with",Space,Str "6"]+      ,OrderedList (3,LowerAlpha,DefaultDelim)+       [[Para [Str "Lower",Space,Str "alpha",Space,Str "with",Space,Str "paren"]]]]]]]]]+,Para [Str "Autonumbering:"]+,OrderedList (1,Decimal,DefaultDelim)+ [[Para [Str "Autonumber."]]+ ,[Para [Str "More."]+  ,OrderedList (1,Decimal,DefaultDelim)+   [[Para [Str "Nested."]]]]]+,Para [Str "Should",Space,Str "not",Space,Str "be",Space,Str "a",Space,Str "list",Space,Str "item:"]+,Para [Str "M.A.\160\&2007"]+,Para [Str "B.",Space,Str "Williams"]+,Header 2 ("callout",[],[]) [Str "Callout"]+,Para [Str "Simple."]+,BulletList+ [[Para [Str "A",Space,Code ("",[],[]) "__letrec",Space,Str "is",Space,Str "equivalent",Space,Str "to",Space,Str "a",Space,Str "normal",SoftBreak,Str "Haskell",Space,Str "LET."]]+ ,[Para [Str "GHC",Space,Str "compiled",Space,Str "the",Space,Str "body",Space,Str "of",Space,Str "our",Space,Str "list",Space,Str "comprehension",Space,Str "into",SoftBreak,Str "a",Space,Str "loop",Space,Str "named",Space,Code ("",[],[]) "go_s1YC",Str "."]]+ ,[Para [Str "If",Space,Str "our",Space,Str "CASE",Space,Str "expression",Space,Str "matches",Space,Str "the",Space,Str "empty",Space,Str "list,",Space,Str "we",SoftBreak,Str "return",Space,Str "the",Space,Str "empty",Space,Str "list.",Space,Str "This",Space,Str "is",Space,Str "reassuringly",SoftBreak,Str "familiar."]]]+,Header 1 ("definition-lists",[],[]) [Str "Definition",Space,Str "Lists"]+,DefinitionList+ [([Str "apple"],+   [[Para [Str "red",Space,Str "fruit"]]])+ ,([Str "orange"],+   [[Para [Str "orange",Space,Str "fruit"]]])+ ,([Str "banana"],+   [[Para [Str "yellow",Space,Str "fruit"]]])]+,Para [Str "Multiple",Space,Str "blocks",Space,Str "with",Space,Str "italics:"]+,DefinitionList+ [([Emph [Str "apple"]],+   [[Para [Str "red",Space,Str "fruit"]+    ,Para [Str "contains",Space,Str "seeds,",Space,Str "crisp,",Space,Str "pleasant",Space,Str "to",Space,Str "taste"]]])+ ,([Emph [Str "orange"]],+   [[Para [Str "orange",Space,Str "fruit"]+    ,CodeBlock ("",[],[]) "{ orange code block }"+    ,BlockQuote+     [Para [Str "orange",Space,Str "block",Space,Str "quote"]]]])]+,Para [Str "Multiple",Space,Str "definitions,",Space,Str "loose:"]+,DefinitionList+ [([Str "apple"],+   [[Para [Str "red",Space,Str "fruit"]]+   ,[Para [Str "computer"]]])+ ,([Str "orange"],+   [[Para [Str "orange",Space,Str "fruit"]]+   ,[Para [Str "bank"]]])]+,Para [Str "Blank",Space,Str "line",Space,Str "after",Space,Str "term,",Space,Str "indented",Space,Str "marker,",Space,Str "alternate",Space,Str "markers:"]+,DefinitionList+ [([Str "apple"],+   [[Para [Str "red",Space,Str "fruit"]]+   ,[Para [Str "computer"]]])+ ,([Str "orange"],+   [[Para [Str "orange",Space,Str "fruit"]+    ,OrderedList (1,Decimal,DefaultDelim)+     [[Para [Str "sublist"]]+     ,[Para [Str "sublist"]]]]])]+,Header 1 ("inline-markup",[],[]) [Str "Inline",Space,Str "Markup"]+,Para [Str "This",Space,Str "is",Space,Emph [Str "emphasized"],Str ",",Space,Str "and",Space,Str "so",Space,Emph [Str "is",SoftBreak,Str "this"],Str "."]+,Para [Str "This",Space,Str "is",Space,Strong [Str "strong"],Str ",",Space,Str "and",Space,Str "so",SoftBreak,Strong [Str "is",Space,Str "this"],Str "."]+,Para [Str "An",Space,Emph [Link ("",[],[]) [Str "emphasized",Space,Str "link"] ("/url","")],Str "."]+,Para [Strong [Emph [Str "This",Space,Str "is",Space,Str "strong",Space,Str "and",SoftBreak,Str "em."]]]+,Para [Str "So",Space,Str "is",Space,Strong [Emph [Str "this"]],Space,Str "word."]+,Para [Strong [Emph [Str "This",Space,Str "is",Space,Str "strong",Space,Str "and",SoftBreak,Str "em."]]]+,Para [Str "So",Space,Str "is",Space,Strong [Emph [Str "this"]],Space,Str "word."]+,Para [Str "This",Space,Str "is",Space,Str "code:",Space,Code ("",[],[]) ">",Str ",",Space,Code ("",[],[]) "$",Str ",",SoftBreak,Code ("",[],[]) "\\",Str ",",Space,Code ("",[],[]) "\\$",Str ",",SoftBreak,Code ("",[],[]) "<html>",Str "."]+,Para [Str "More",Space,Str "code:",Space,Code ("",[],[]) "Class",Space,Str "and",Space,Code ("",[],[]) "Type"]+,Para [Strikeout [Str "This",Space,Str "is",SoftBreak,Emph [Str "strikeout"],Str "."]]+,Para [Str "Superscripts:",Space,Str "a",Superscript [Str "bc"],Str "d",SoftBreak,Str "a",Superscript [Emph [Str "hello"]],SoftBreak,Str "a",Superscript [Str "hello\160there"],Str "."]+,Para [Str "Subscripts:",Space,Str "H",Subscript [Str "2"],Str "O,",Space,Str "H",Subscript [Str "23"],Str "O,",SoftBreak,Str "H",Subscript [Str "many\160of\160them"],Str "O."]+,Para [Str "These",Space,Str "should",Space,Str "not",Space,Str "be",Space,Str "superscripts",Space,Str "or",Space,Str "subscripts,",Space,Str "because",Space,Str "of",Space,Str "the",Space,Str "unescaped",SoftBreak,Str "spaces:",Space,Str "a^b",Space,Str "c^d,",Space,Str "a~b",Space,Str "c~d."]+,Header 1 ("smart-quotes-ellipses-dashes",[],[]) [Str "Smart",Space,Str "quotes,",Space,Str "ellipses,",Space,Str "dashes"]+,Para [Quoted DoubleQuote [Str "Hello,"],Space,Str "said",Space,Str "the",Space,Str "spider.",Space,Quoted DoubleQuote [Quoted SingleQuote [Str "Shelob"],Space,Str "is",Space,Str "my",SoftBreak,Str "name."]]+,Para [Quoted DoubleQuote [Str "A"],Str ",",Space,Quoted DoubleQuote [Str "B"],Str ",",Space,Str "and",Space,Quoted DoubleQuote [Str "C"],Space,Str "are",Space,Str "letters."]+,Para [Quoted DoubleQuote [Str "He",Space,Str "said,",Space,Quoted SingleQuote [Str "I",Space,Str "want",Space,Str "to",Space,Str "go."]],Space,Str "Were",Space,Str "you",Space,Str "alive",Space,Str "in",Space,Str "the",SoftBreak,Str "70\8217s?"]+,Para [Str "Some",Space,Str "dashes:",Space,Str "one\8212two",Space,Str "\8212",Space,Str "three\8212four",Space,Str "\8212",Space,Str "five."]+,Para [Str "Dashes",Space,Str "between",Space,Str "numbers:",Space,Str "5\8211\&7,",Space,Str "255\8211\&66,",Space,Str "1987\8211\&1999."]+,Para [Str "Ellipses\8230and\8230and\8230."]+,Header 1 ("math",[],[]) []+,Para [Math DisplayMath "e = mc^{2}",Math DisplayMath "1",SoftBreak,Math InlineMath "e = mc^{2}",SoftBreak,Math DisplayMath "e = mc^{2}"]+,Header 1 ("special-characters",[],[]) [Str "Special",Space,Str "Characters"]+,Para [Str "Here",Space,Str "is",Space,Str "some",Space,Str "unicode:"]+,BulletList+ [[Para [Str "I",Space,Str "hat:",Space,Str "\206"]]+ ,[Para [Str "o",Space,Str "umlaut:",Space,Str "\246"]]+ ,[Para [Str "section:",Space,Str "\167"]]+ ,[Para [Str "set",Space,Str "membership:",Space,Str "\8712"]]+ ,[Para [Str "copyright:",Space,Str "\169"]]]+,Para [Str "AT&T",Space,Str "has",Space,Str "an",Space,Str "ampersand",Space,Str "in",Space,Str "their",Space,Str "name."]+,Para [Str "AT&T",Space,Str "is",Space,Str "another",Space,Str "way",Space,Str "to",Space,Str "write",Space,Str "it."]+,Para [Str "This",Space,Str "&",Space,Str "that."]+,Para [Str "4",Space,Str "<",Space,Str "5."]+,Para [Str "6",Space,Str ">",Space,Str "5."]+,Para [Str "Backslash:",Space,Str "\\"]+,Para [Str "Backtick:",Space,Str "`"]+,Para [Str "Asterisk:",Space,Str "*"]+,Para [Str "Underscore:",Space,Str "_"]+,Para [Str "Left",Space,Str "brace:",Space,Str "{"]+,Para [Str "Right",Space,Str "brace:",Space,Str "}"]+,Para [Str "Left",Space,Str "bracket:",Space,Str "["]+,Para [Str "Right",Space,Str "bracket:",Space,Str "]"]+,Para [Str "Left",Space,Str "paren:",Space,Str "("]+,Para [Str "Right",Space,Str "paren:",Space,Str ")"]+,Para [Str "Greater-than:",Space,Str ">"]+,Para [Str "Hash:",Space,Str "#"]+,Para [Str "Period:",Space,Str "."]+,Para [Str "Bang:",Space,Str "!"]+,Para [Str "Plus:",Space,Str "+"]+,Para [Str "Minus:",Space,Str "-"]+,Header 1 ("links",[],[]) [Str "Links"]+,Header 2 ("explicit",[],[]) [Str "Explicit"]+,Para [Str "Just",Space,Str "a",Space,Link ("",[],[]) [Str "URL"] ("/url/",""),Str "."]+,Para [Link ("",[],[]) [Str "URL",Space,Str "and",Space,Str "title"] ("/url/",""),Str "."]+,Para [Link ("",[],[]) [Str "URL",Space,Str "and",Space,Str "title"] ("/url/",""),Str "."]+,Para [Link ("",[],[]) [Str "URL",Space,Str "and",Space,Str "title"] ("/url/",""),Str "."]+,Para [Link ("",[],[]) [Str "URL",Space,Str "and",Space,Str "title"] ("/url/","")]+,Para [Link ("",[],[]) [Str "URL",Space,Str "and",Space,Str "title"] ("/url/","")]+,Para [Link ("",[],[]) [Str "with_underscore"] ("/url/with_underscore","")]+,Para [Link ("",[],[]) [Str "nobody@nowhere.net"] ("mailto:nobody@nowhere.net","")]+,Para [Link ("",[],[]) [Str "Empty"] ("",""),Str "."]+,Header 2 ("reference",[],[]) [Str "Reference"]+,Para [Str "Foo",Space,Link ("",[],[]) [Str "bar"] ("/url/",""),Str "."]+,Para [Str "Foo",Space,Link ("",[],[]) [Str "bar"] ("/url/",""),Str "."]+,Para [Str "Foo",Space,Link ("",[],[]) [Str "bar"] ("/url/",""),Str "."]+,Para [Str "With",Space,Link ("",[],[]) [Str "embedded",Space,Str "[brackets]"] ("/url/",""),Str "."]+,Para [Link ("",[],[]) [Str "b"] ("/url/",""),Space,Str "by",Space,Str "itself",Space,Str "should",Space,Str "be",Space,Str "a",Space,Str "link."]+,Para [Str "Indented",Space,Link ("",[],[]) [Str "once"] ("/url",""),Str "."]+,Para [Str "Indented",Space,Link ("",[],[]) [Str "twice"] ("/url",""),Str "."]+,Para [Str "Indented",Space,Link ("",[],[]) [Str "thrice"] ("/url",""),Str "."]+,Para [Str "This",Space,Str "should",Space,Str "[not][]",Space,Str "be",Space,Str "a",Space,Str "link."]+,CodeBlock ("",[],[]) "[not]: /url"+,Para [Str "Foo",Space,Link ("",[],[]) [Str "bar"] ("/url/",""),Str "."]+,Para [Str "Foo",Space,Link ("",[],[]) [Str "biz"] ("/url/",""),Str "."]+,Header 2 ("with-ampersands",[],[]) [Str "With",Space,Str "ampersands"]+,Para [Str "Here\8217s",Space,Str "a",Space,Link ("",[],[]) [Str "link",Space,Str "with",Space,Str "an",SoftBreak,Str "ampersand",Space,Str "in",Space,Str "the",Space,Str "URL"] ("http://example.com/?foo=1&bar=2",""),Str "."]+,Para [Str "Here\8217s",Space,Str "a",Space,Str "link",Space,Str "with",Space,Str "an",Space,Str "amersand",Space,Str "in",Space,Str "the",Space,Str "link",Space,Str "text:",SoftBreak,Link ("",[],[]) [Str "AT&T"] ("http://att.com/",""),Str "."]+,Para [Str "Here\8217s",Space,Str "an",Space,Link ("",[],[]) [Str "inline",Space,Str "link"] ("/script?foo=1&bar=2",""),Str "."]+,Para [Str "Here\8217s",Space,Str "an",Space,Link ("",[],[]) [Str "inline",Space,Str "link",Space,Str "in",Space,Str "pointy",SoftBreak,Str "braces"] ("/script?foo=1&bar=2",""),Str "."]+,Header 2 ("autolinks",[],[]) [Str "Autolinks"]+,Para [Str "With",Space,Str "an",Space,Str "ampersand:",SoftBreak,Link ("",[],[]) [Str "http://example.com/?foo=1&bar=2"] ("http://example.com/?foo=1&bar=2","")]+,BulletList+ [[Para [Str "In",Space,Str "a",Space,Str "list?"]]+ ,[Para [Link ("",[],[]) [Str "http://example.com/"] ("http://example.com/","")]]+ ,[Para [Str "It",Space,Str "should."]]]+,Para [Str "An",Space,Str "e-mail",Space,Str "address:",Space,Link ("",[],[]) [Str "nobody@nowhere.net"] ("mailto:nobody@nowhere.net","")]+,BlockQuote+ [Para [Str "Blockquoted:",SoftBreak,Link ("",[],[]) [Str "http://example.com/"] ("http://example.com/","")]]+,Para [Str "Auto-links",Space,Str "should",Space,Str "not",Space,Str "occur",Space,Str "here:",SoftBreak,Code ("",[],[]) "<http://example.com/>"]+,CodeBlock ("",[],[]) "or here: <http://example.com/>"+,Header 1 ("images",[],[]) [Str "Images"]+,Para [Str "From",Space,Quoted DoubleQuote [Str "Voyage",Space,Str "dans",Space,Str "la",Space,Str "Lune"],Space,Str "by",Space,Str "Georges",Space,Str "Melies",Space,Str "(1902):"]+,Para [Image ("",[],[]) [Str "lalune",Space,Str "fig",Space,Str "caption"] ("lalune.jpg","fig:")]+,Para [Str "Here",Space,Str "is",Space,Str "a",Space,Str "movie",Space,Image ("",[],[]) [] ("movie.jpg",""),Space,Str "icon.",SoftBreak,Str "And",Space,Str "here",Space,Str "a",Space,Str "second",Space,Str "movie",Space,Image ("",[],[]) [Str "alt",Space,Str "text"] ("movie.jpg",""),Space,Str "icon.",SoftBreak,Str "And",Space,Str "here",Space,Str "a",Space,Str "third",Space,Str "movie",Space,Image ("",[],[]) [Str "alt",Space,Str "text"] ("movie.jpg",""),Space,Str "icon."]+,Para [Image ("",[],[]) [Str "lalune",Space,Str "no",Space,Str "figure",Space,Str "alt",Space,Str "text"] ("lalune.jpg","")]+,Header 1 ("footnotes",[],[]) [Str "Footnotes"]+,Para [Str "Here",Space,Str "is",Space,Str "a",Space,Str "footnote",Space,Str "reference,",Note [Para [Str "Here",Space,Str "is",Space,Str "the",Space,Str "footnote.",Space,Str "It",Space,Str "can",Space,Str "go",Space,Str "anywhere",Space,Str "after",Space,Str "the",Space,Str "footnote",Space,Str "reference.",SoftBreak,Str "It",Space,Str "need",Space,Str "not",Space,Str "be",Space,Str "placed",Space,Str "at",Space,Str "the",Space,Str "end",Space,Str "of",Space,Str "the",Space,Str "document."]],Space,Str "and",Space,Str "another.",Note [Para [Str "Here\8217s",Space,Str "the",Space,Str "long",Space,Str "note.",Space,Str "This",Space,Str "one",Space,Str "contains",Space,Str "multiple",Space,Str "blocks."],Para [Str "Subsequent",Space,Str "blocks",Space,Str "are",Space,Str "indented",Space,Str "to",Space,Str "show",Space,Str "that",Space,Str "they",Space,Str "belong",Space,Str "to",Space,Str "the",SoftBreak,Str "footnote",Space,Str "(as",Space,Str "with",Space,Str "list",Space,Str "items)."],CodeBlock ("",[],[]) "  { <code> }",Para [Str "If",Space,Str "you",Space,Str "want,",Space,Str "you",Space,Str "can",Space,Str "indent",Space,Str "every",Space,Str "line,",Space,Str "but",Space,Str "you",Space,Str "can",Space,Str "also",Space,Str "be",Space,Str "lazy",Space,Str "and",SoftBreak,Str "just",Space,Str "indent",Space,Str "the",Space,Str "first",Space,Str "line",Space,Str "of",Space,Str "each",Space,Str "block."]],Space,Str "This",Space,Str "should",Space,Emph [Str "not"],Space,Str "be",Space,Str "a",Space,Str "footnote",Space,Str "reference,",SoftBreak,Str "because",Space,Str "it",Space,Str "contains",Space,Str "a",Space,Str "space.[^my",Space,Str "note]",Space,Str "Here",Space,Str "is",Space,Str "an",Space,Str "inline",Space,Str "note.",Note [Para [Str "This",Space,Str "is",Space,Emph [Str "easier"],Space,Str "to",Space,Str "type.",Space,Str "Inline",Space,Str "notes",Space,Str "may",Space,Str "contain",SoftBreak,Link ("",[],[]) [Str "links"] ("http://google.com",""),Space,Str "and",Space,Code ("",[],[]) "]",SoftBreak,Str "verbatim",Space,Str "characters,",Space,Str "as",Space,Str "well",Space,Str "as",Space,Str "[bracketed",Space,Str "text]."]]]+,BlockQuote+ [Para [Str "Notes",Space,Str "can",Space,Str "go",Space,Str "in",Space,Str "quotes.",Note [Para [Str "In",Space,Str "quote."]]]]+,OrderedList (1,Decimal,DefaultDelim)+ [[Para [Str "And",Space,Str "in",Space,Str "list",Space,Str "items.",Note [Para [Str "In",Space,Str "list."]]]]]+,Para [Str "This",Space,Str "paragraph",Space,Str "should",Space,Str "not",Space,Str "be",Space,Str "part",Space,Str "of",Space,Str "the",Space,Str "note,",Space,Str "as",Space,Str "it",Space,Str "is",Space,Str "not",Space,Str "indented."]+,Header 1 ("tables",[],[]) [Str "Tables"]+,Para [Str "Simple",Space,Str "table",Space,Str "with",Space,Str "caption:"]+,Table [Str "Demonstration",Space,Str "of",Space,Str "simple",Space,Str "table",Space,Str "syntax."] [AlignRight,AlignLeft,AlignCenter,AlignLeft] [0.0,0.0,0.0,0.0]+ [[Plain [Str "Right"]]+ ,[Plain [Str "Left"]]+ ,[Plain [Str "Center"]]+ ,[Plain [Str "Default"]]]+ [[[Plain [Str "12"]]+  ,[Plain [Str "12"]]+  ,[Plain [Str "12"]]+  ,[Plain [Str "12"]]]+ ,[[Plain [Str "123"]]+  ,[Plain [Str "123"]]+  ,[Plain [Str "123"]]+  ,[Plain [Str "123"]]]+ ,[[Plain [Str "1"]]+  ,[Plain [Str "1"]]+  ,[Plain [Str "1"]]+  ,[Plain [Str "1"]]]]+,Para [Str "Simple",Space,Str "table",Space,Str "without",Space,Str "caption:"]+,Table [] [AlignRight,AlignLeft,AlignCenter,AlignLeft] [0.0,0.0,0.0,0.0]+ [[Plain [Str "Right"]]+ ,[Plain [Str "Left"]]+ ,[Plain [Str "Center"]]+ ,[Plain [Str "Default"]]]+ [[[Plain [Str "12"]]+  ,[Plain [Str "12"]]+  ,[Plain [Str "12"]]+  ,[Plain [Str "12"]]]+ ,[[Plain [Str "123"]]+  ,[Plain [Str "123"]]+  ,[Plain [Str "123"]]+  ,[Plain [Str "123"]]]+ ,[[Plain [Str "1"]]+  ,[Plain [Str "1"]]+  ,[Plain [Str "1"]]+  ,[Plain [Str "1"]]]]+,Para [Str "Simple",Space,Str "table",Space,Str "indented",Space,Str "two",Space,Str "spaces:"]+,Table [Str "Demonstration",Space,Str "of",Space,Str "simple",Space,Str "table",Space,Str "syntax."] [AlignRight,AlignLeft,AlignCenter,AlignLeft] [0.0,0.0,0.0,0.0]+ [[Plain [Str "Right"]]+ ,[Plain [Str "Left"]]+ ,[Plain [Str "Center"]]+ ,[Plain [Str "Default"]]]+ [[[Plain [Str "12"]]+  ,[Plain [Str "12"]]+  ,[Plain [Str "12"]]+  ,[Plain [Str "12"]]]+ ,[[Plain [Str "123"]]+  ,[Plain [Str "123"]]+  ,[Plain [Str "123"]]+  ,[Plain [Str "123"]]]+ ,[[Plain [Str "1"]]+  ,[Plain [Str "1"]]+  ,[Plain [Str "1"]]+  ,[Plain [Str "1"]]]]+,Para [Str "Multiline",Space,Str "table",Space,Str "with",Space,Str "caption:"]+,Table [Str "Here's",Space,Str "the",Space,Str "caption.",Space,Str "It",Space,Str "may",Space,Str "span",Space,Str "multiple",Space,Str "lines."] [AlignCenter,AlignLeft,AlignRight,AlignLeft] [0.2,0.2,0.3,0.3]+ [[Plain [Str "Centered",Space,Str "Header"]]+ ,[Plain [Str "Left",Space,Str "Aligned"]]+ ,[Plain [Str "Right",Space,Str "Aligned"]]+ ,[Plain [Str "Default",Space,Str "aligned"]]]+ [[[Plain [Str "First"]]+  ,[Plain [Str "row"]]+  ,[Plain [Str "12.0"]]+  ,[Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",Space,Str "spans",Space,Str "multiple",Space,Str "lines."]]]+ ,[[Plain [Str "Second"]]+  ,[Plain [Str "row"]]+  ,[Plain [Str "5.0"]]+  ,[Plain [Str "Here's",Space,Str "another",Space,Str "one.",Space,Str "Note",Space,Str "the",Space,Str "blank",Space,Str "line",Space,Str "between",Space,Str "rows."]]]]+,Para [Str "Multiline",Space,Str "table",Space,Str "without",Space,Str "caption:"]+,Table [] [AlignCenter,AlignLeft,AlignRight,AlignLeft] [0.1,0.2,0.3,0.4]+ [[Plain [Str "Centered",Space,Str "Header"]]+ ,[Plain [Str "Left",Space,Str "Aligned"]]+ ,[Plain [Str "Right",Space,Str "Aligned"]]+ ,[Plain [Str "Default",Space,Str "aligned"]]]+ [[[Plain [Str "First"]]+  ,[Plain [Str "row"]]+  ,[Plain [Str "12.0"]]+  ,[Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",Space,Str "spans",Space,Str "multiple",Space,Str "lines."]]]+ ,[[Plain [Str "Second"]]+  ,[Plain [Str "row"]]+  ,[Plain [Str "5.0"]]+  ,[Plain [Str "Here's",Space,Str "another",Space,Str "one.",Space,Str "Note",Space,Str "the",Space,Str "blank",Space,Str "line",Space,Str "between",Space,Str "rows."]]]]+,Para [Str "Table",Space,Str "without",Space,Str "column",Space,Str "headers:"]+,Table [] [AlignRight,AlignLeft,AlignCenter,AlignRight] [0.0,0.0,0.0,0.0]+ [[]+ ,[]+ ,[]+ ,[]]+ [[[Plain [Str "12"]]+  ,[Plain [Str "12"]]+  ,[Plain [Str "12"]]+  ,[Plain [Str "12"]]]+ ,[[Plain [Str "123"]]+  ,[Plain [Str "123"]]+  ,[Plain [Str "123"]]+  ,[Plain [Str "123"]]]+ ,[[Plain [Str "1"]]+  ,[Plain [Str "1"]]+  ,[Plain [Str "1"]]+  ,[Plain [Str "1"]]]]+,Para [Str "Multiline",Space,Str "table",Space,Str "without",Space,Str "column",Space,Str "headers:"]+,Table [] [AlignCenter,AlignLeft,AlignRight,AlignLeft] [0.25,0.25,0.25,0.25]+ [[]+ ,[]+ ,[]+ ,[]]+ [[[Plain [Str "First"]]+  ,[Plain [Str "row"]]+  ,[Plain [Str "12.0"]]+  ,[Plain [Str "Example",Space,Str "of",Space,Str "a",Space,Str "row",Space,Str "that",Space,Str "spans",Space,Str "multiple",Space,Str "lines."]]]+ ,[[Plain [Str "Second"]]+  ,[Plain [Str "row"]]+  ,[Plain [Str "5.0"]]+  ,[Plain [Str "Here's",Space,Str "another",Space,Str "one.",Space,Str "Note",Space,Str "the",Space,Str "blank",Space,Str "line",Space,Str "between",Space,Str "rows."]]]]]
+ test/docbook-xref.docbook view
@@ -0,0 +1,70 @@+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"+          "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">+<book><title>An Example Book</title>+<chapter id="ch01"><title>XRef Samples</title>+<para>+This paragraph demonstrates several features of+<sgmltag>XRef</sgmltag>.+</para>+<itemizedlist>+<listitem><para>A straight link generates the+cross-reference text: <xref linkend="ch02"/>.+</para></listitem>+<listitem><para>A link to an element with an+<sgmltag class="attribute">XRefLabel</sgmltag>:+<xref linkend="ch03"/>.+</para></listitem>+<listitem><para>A link with an+<sgmltag class="attribute">EndTerm</sgmltag>:+<xref linkend="ch04" endterm="ch04short"/>.+</para></listitem>+<listitem><para>A link to an+<sgmltag>cmdsynopsis</sgmltag> element: <xref linkend="cmd01"/>.+</para></listitem>+<listitem><para>A link to an+<sgmltag>funcsynopsis</sgmltag> element: <xref linkend="func01"/>.+</para></listitem>+</itemizedlist>+</chapter>++<chapter id="ch02">+  <title>The Second Chapter</title>+  <para>Some content here</para>+</chapter>++<chapter id="ch03" xreflabel="Chapter the Third">+  <title>The Third Chapter</title>+  <para>Some content here</para>+</chapter>++<chapter id="ch04">+  <title>The Fourth Chapter</title>+  <titleabbrev id="ch04short">Chapter 4</titleabbrev>+  <para>Some content here</para>++<cmdsynopsis id="cmd01">+  <command>chgrp</command>+  <arg>-R+    <group>+      <arg>-H</arg>+      <arg>-L</arg>+      <arg>-P</arg>+    </group>+  </arg>+  <arg>-f</arg>+  <arg choice='plain'><replaceable>group</replaceable></arg>+  <arg rep='repeat' choice='plain'><replaceable>file</replaceable></arg>+</cmdsynopsis>+++<funcsynopsis id="func01">+<funcprototype>+<funcdef>int <function>max</function></funcdef>+<paramdef>int <parameter>int1</parameter></paramdef>+<paramdef>int <parameter>int2</parameter></paramdef>+</funcprototype>+</funcsynopsis>++</chapter>+</book>+
+ test/docbook-xref.native view
@@ -0,0 +1,29 @@+Pandoc (Meta {unMeta = fromList []})+[Header 1 ("ch01",[],[]) [Str "XRef",Space,Str "Samples"]+,Para [Str "This",Space,Str "paragraph",Space,Str "demonstrates",Space,Str "several",Space,Str "features",Space,Str "of",SoftBreak,Str "XRef."]+,BulletList+ [[Para [Str "A",Space,Str "straight",Space,Str "link",Space,Str "generates",Space,Str "the",SoftBreak,Str "cross-reference",Space,Str "text:",Space,Link ("",[],[]) [Str "The",Space,Str "Second",Space,Str "Chapter"] ("#ch02",""),Str "."]]+ ,[Para [Str "A",Space,Str "link",Space,Str "to",Space,Str "an",Space,Str "element",Space,Str "with",Space,Str "an",SoftBreak,Str "XRefLabel:",SoftBreak,Link ("",[],[]) [Str "Chapter",Space,Str "the",Space,Str "Third"] ("#ch03",""),Str "."]]+ ,[Para [Str "A",Space,Str "link",Space,Str "with",Space,Str "an",SoftBreak,Str "EndTerm:",SoftBreak,Link ("",[],[]) [Str "Chapter",Space,Str "4"] ("#ch04",""),Str "."]]+ ,[Para [Str "A",Space,Str "link",Space,Str "to",Space,Str "an",SoftBreak,Str "cmdsynopsis",Space,Str "element:",Space,Link ("",[],[]) [Str "chgrp"] ("#cmd01",""),Str "."]]+ ,[Para [Str "A",Space,Str "link",Space,Str "to",Space,Str "an",SoftBreak,Str "funcsynopsis",Space,Str "element:",Space,Link ("",[],[]) [Str "max"] ("#func01",""),Str "."]]]+,Header 1 ("ch02",[],[]) [Str "The",Space,Str "Second",Space,Str "Chapter"]+,Para [Str "Some",Space,Str "content",Space,Str "here"]+,Header 1 ("ch03",[],[]) [Str "The",Space,Str "Third",Space,Str "Chapter"]+,Para [Str "Some",Space,Str "content",Space,Str "here"]+,Header 1 ("ch04",[],[]) [Str "The",Space,Str "Fourth",Space,Str "Chapter"]+,Para [Str "Some",Space,Str "content",Space,Str "here"]+,Plain [Str "chgrp"]+,Plain [Str "-R"]+,Plain [Str "-H"]+,Plain [Str "-L"]+,Plain [Str "-P"]+,Plain [Str "-f"]+,Plain [Str "group"]+,Plain [Str "file"]+,Plain [Str "int"]+,Plain [Str "max"]+,Plain [Str "int"]+,Plain [Str "int1"]+,Plain [Str "int"]+,Plain [Str "int2"]]
+ test/docx/0_level_headers.docx view

binary file changed (absent → 35146 bytes)

+ test/docx/0_level_headers.native view
@@ -0,0 +1,25 @@+[Table [] [AlignDefault] [0.0]+ [[]]+ [[[]]+ ,[[Plain [Str "User\8217s",Space,Str "Guide"]]]+ ,[[]]+ ,[[]]+ ,[[]]+ ,[[Plain [Str "11",Space,Str "August",Space,Str "2017"]]]+ ,[[]]+ ,[[]]+ ,[[]]+ ,[[]]]+,Para [Str "CONTENTS"]+,Para [Strong [Str "Section",Space,Str "Page"]]+,Para [Str "FIGURES",Space,Str "iv"]+,Para [Str "TABLES",Space,Str "v"]+,Para [Str "SECTION",Space,Str "1",Space,Str "Introduction",Space,Str "2"]+,Header 1 ("figures",["Heading0"],[]) [Str "FIGURES"]+,Para [Strong [Str "Figure",Space,Str "Page"]]+,Para [Strong [Str "No",Space,Str "table",Space,Str "of",Space,Str "figures",Space,Str "entries",Space,Str "found."]]+,Header 1 ("tables",["Heading0"],[]) [Str "TABLES"]+,Para [Strong [Str "Table",Space,Str "Page"]]+,Para [Strong [Str "No",Space,Str "table",Space,Str "of",Space,Str "figures",Space,Str "entries",Space,Str "found."]]+,Header 1 ("introduction",[],[]) [Str "Introduction"]+,Para [Str "Nothing",Space,Str "to",Space,Str "introduce,",Space,Str "yet."]]
+ test/docx/already_auto_ident.docx view

binary file changed (absent → 8463 bytes)

+ test/docx/already_auto_ident.native view
@@ -0,0 +1,2 @@+[Header 1 ("anchor-header",[],[]) [Str "Anchor",Space,Str "Header"]+,Para [Str "A",Space,Link ("",[],[]) [Str "link"] ("#anchor-header","")]]
+ test/docx/block_quotes.docx view

binary file changed (absent → 41855 bytes)

+ test/docx/block_quotes_parse_indent.native view
@@ -0,0 +1,8 @@+[Header 2 ("some-block-quotes-in-different-ways",[],[]) [Str "Some",Space,Str "block",Space,Str "quotes,",Space,Str "in",Space,Str "different",Space,Str "ways"]+,Para [Str "This",Space,Str "is",Space,Str "the",Space,Str "proper",Space,Str "way,",Space,Str "with",Space,Str "a",Space,Str "style"]+,BlockQuote+ [Para [Str "I",Space,Str "don\8217t",Space,Str "know",Space,Str "why",Space,Str "this",Space,Str "would",Space,Str "be",Space,Str "in",Space,Str "italics,",Space,Str "but",Space,Str "so",Space,Str "it",Space,Str "appears",Space,Str "to",Space,Str "be",Space,Str "on",Space,Str "my",Space,Str "screen."]]+,Para [Str "And",Space,Str "this",Space,Str "is",Space,Str "the",Space,Str "way",Space,Str "that",Space,Str "most",Space,Str "people",Space,Str "do",Space,Str "it:"]+,BlockQuote+ [Para [Str "I",Space,Str "just",Space,Str "indented",Space,Str "this,",Space,Str "so",Space,Str "it",Space,Str "looks",Space,Str "like",Space,Str "a",Space,Str "block",Space,Str "quote.",Space,Str "I",Space,Str "think",Space,Str "this",Space,Str "is",Space,Str "how",Space,Str "most",Space,Str "people",Space,Str "do",Space,Str "block",Space,Str "quotes",Space,Str "in",Space,Str "their",Space,Str "documents."]]+,Para [Str "And",Space,Str "back",Space,Str "to",Space,Str "the",Space,Str "normal",Space,Str "style."]]
+ test/docx/char_styles.docx view

binary file changed (absent → 30134 bytes)

+ test/docx/char_styles.native view
@@ -0,0 +1,4 @@+[Para [Emph [Str "This",Space,Str "is",Space,Str "all",Space,Str "in",Space,Str "an"],Space,Emph [Strong [Str "italic",Space,Str "style"],Str "."]]+,Para [Emph [Str "This",Space,Str "is",Space,Str "an",Space,Str "italic"],Space,Str "style",Space,Emph [Str "with",Space,Str "some"],Space,Str "words",Space,Emph [Str "unitalicized."]]+,Para [Strong [Str "This",Space,Str "is",Space,Str "all",Space,Str "in",Space,Str "a",Space,Emph [Str "strong",Space,Str "style"],Str "."]]+,Para [Strong [Str "This",Space,Str "is",Space,Str "a",Space,Str "strong"],Space,Str "style",Space,Strong [Str "with",Space,Str "some"],Space,Str "words",Space,Strong [Str "ubolded."]]]
+ test/docx/codeblock.docx view

binary file changed (absent → 8465 bytes)

+ test/docx/codeblock.native view
@@ -0,0 +1,3 @@+[Para [Str "This",Space,Str "is",Space,Str "some",Space,Str "code:"]+,CodeBlock ("",[],[]) "readDocx :: ReaderOptions\n         -> B.ByteString\n         -> Pandoc"+,Para [Str "from",Space,Str "the",Space,Str "beginning",Space,Str "of",Space,Str "the",Space,Str "docx",Space,Str "reader."]]
+ test/docx/comments.docx view

file too large to diff

+ test/docx/comments.native view

file too large to diff

+ test/docx/comments_no_comments.native view

file too large to diff

+ test/docx/comments_warning.docx view

file too large to diff

+ test/docx/custom-style-reference.docx view

file too large to diff

+ test/docx/custom-style-roundtrip-end.native view

file too large to diff

+ test/docx/custom-style-roundtrip-start.native view

file too large to diff

+ test/docx/deep_normalize.docx view

file too large to diff

+ test/docx/deep_normalize.native view

file too large to diff

+ test/docx/definition_list.docx view

file too large to diff

+ test/docx/definition_list.native view

file too large to diff

+ test/docx/drop_cap.docx view

file too large to diff

+ test/docx/drop_cap.native view

file too large to diff

+ test/docx/dummy_item_after_list_item.docx view

file too large to diff

+ test/docx/dummy_item_after_list_item.native view

file too large to diff

+ test/docx/dummy_item_after_paragraph.docx view

file too large to diff

+ test/docx/dummy_item_after_paragraph.native view

file too large to diff

+ test/docx/enumerated_headings.docx view

file too large to diff

+ test/docx/enumerated_headings.native view

file too large to diff

+ test/docx/german_styled_lists.docx view

file too large to diff

+ test/docx/german_styled_lists.native view

file too large to diff

+ test/docx/hanging_indent.docx view

file too large to diff

+ test/docx/hanging_indent.native view

file too large to diff

+ test/docx/headers.docx view

file too large to diff

+ test/docx/headers.native view

file too large to diff

+ test/docx/i18n_blocks.docx view

file too large to diff

+ test/docx/i18n_blocks.native view

file too large to diff

+ test/docx/image.docx view

file too large to diff

+ test/docx/image_no_embed.native view

file too large to diff

+ test/docx/image_no_embed_writer.native view

file too large to diff

+ test/docx/image_vml.docx view

file too large to diff

+ test/docx/image_vml.native view

file too large to diff

+ test/docx/inline_code.docx view

file too large to diff

+ test/docx/inline_code.native view

file too large to diff

+ test/docx/inline_formatting.docx view

file too large to diff

+ test/docx/inline_formatting.native view

file too large to diff

+ test/docx/inline_formatting_writer.native view

file too large to diff

+ test/docx/inline_images.docx view

file too large to diff

+ test/docx/inline_images.native view

file too large to diff

+ test/docx/inline_images_writer.native view

file too large to diff

file too large to diff

file too large to diff

+ test/docx/links.docx view

file too large to diff

+ test/docx/links.native view

file too large to diff

file too large to diff

+ test/docx/lists.docx view

file too large to diff

+ test/docx/lists.native view

file too large to diff

+ test/docx/lists_writer.native view

file too large to diff

+ test/docx/metadata.docx view

file too large to diff

+ test/docx/metadata.native view

file too large to diff

+ test/docx/metadata_after_normal.docx view

file too large to diff

+ test/docx/metadata_after_normal.native view

file too large to diff

+ test/docx/nested_anchors_in_header.docx view

file too large to diff

+ test/docx/nested_anchors_in_header.native view

file too large to diff

+ test/docx/normalize.docx view

file too large to diff

+ test/docx/normalize.native view

file too large to diff

+ test/docx/notes.docx view

file too large to diff

+ test/docx/notes.native view

file too large to diff

+ test/docx/numbered_header.docx view

file too large to diff

+ test/docx/numbered_header.native view

file too large to diff

+ test/docx/special_punctuation.docx view

file too large to diff

+ test/docx/special_punctuation.native view

file too large to diff

+ test/docx/table_one_row.docx view

file too large to diff

+ test/docx/table_one_row.native view

file too large to diff

+ test/docx/table_with_list_cell.docx view

file too large to diff

+ test/docx/table_with_list_cell.native view

file too large to diff

+ test/docx/tables.docx view

file too large to diff

+ test/docx/tables.native view

file too large to diff

+ test/docx/tabs.docx view

file too large to diff

+ test/docx/tabs.native view

file too large to diff

+ test/docx/track_changes_deletion.docx view

file too large to diff

+ test/docx/track_changes_deletion_accept.native view

file too large to diff

+ test/docx/track_changes_deletion_all.native view

file too large to diff

+ test/docx/track_changes_deletion_reject.native view

file too large to diff

+ test/docx/track_changes_insertion.docx view

file too large to diff

+ test/docx/track_changes_insertion_accept.native view

file too large to diff

+ test/docx/track_changes_insertion_all.native view

file too large to diff

+ test/docx/track_changes_insertion_reject.native view

file too large to diff

+ test/docx/track_changes_move.docx view

file too large to diff

+ test/docx/track_changes_move_accept.native view

file too large to diff

+ test/docx/track_changes_move_all.native view

file too large to diff

+ test/docx/track_changes_move_reject.native view

file too large to diff

+ test/docx/trailing_spaces_in_formatting.docx view

file too large to diff

+ test/docx/trailing_spaces_in_formatting.native view

file too large to diff

+ test/docx/unicode.docx view

file too large to diff

+ test/docx/unicode.native view

file too large to diff

+ test/docx/verbatim_subsuper.docx view

file too large to diff

+ test/docx/verbatim_subsuper.native view

file too large to diff

+ test/dokuwiki_external_images.dokuwiki view

file too large to diff

+ test/dokuwiki_external_images.native view

file too large to diff

+ test/dokuwiki_inline_formatting.dokuwiki view

file too large to diff

+ test/dokuwiki_inline_formatting.native view

file too large to diff

+ test/dokuwiki_multiblock_table.dokuwiki view

file too large to diff

+ test/dokuwiki_multiblock_table.native view

file too large to diff

+ test/epub/features.epub view

file too large to diff

+ test/epub/features.native view

file too large to diff

+ test/epub/formatting.epub view

file too large to diff

+ test/epub/formatting.native view

file too large to diff

+ test/epub/img.epub view

file too large to diff

+ test/epub/wasteland.epub view

file too large to diff

+ test/epub/wasteland.native view

file too large to diff

+ test/fb2/basic.fb2 view

file too large to diff

+ test/fb2/basic.markdown view

file too large to diff

+ test/fb2/images-embedded.fb2 view

file too large to diff

+ test/fb2/images-embedded.html view

file too large to diff

+ test/fb2/images.fb2 view

file too large to diff

+ test/fb2/images.markdown view

file too large to diff

+ test/fb2/math.fb2 view

file too large to diff

+ test/fb2/math.markdown view

file too large to diff

+ test/fb2/test-small.png view

file too large to diff

+ test/fb2/test.jpg view

file too large to diff

+ test/fb2/titles.fb2 view

file too large to diff

+ test/fb2/titles.markdown view

file too large to diff

+ test/haddock-reader.haddock view

file too large to diff

+ test/haddock-reader.native view

file too large to diff

+ test/html-reader.html view

file too large to diff

+ test/html-reader.native view

file too large to diff

+ test/insert view

file too large to diff

+ test/lalune.jpg view

file too large to diff

+ test/latex-reader.latex view

file too large to diff

+ test/latex-reader.native view

file too large to diff

+ test/lhs-test-markdown.native view

file too large to diff

+ test/lhs-test.fragment.html+lhs view

file too large to diff

+ test/lhs-test.html view

file too large to diff

+ test/lhs-test.html+lhs view

file too large to diff

+ test/lhs-test.latex view

file too large to diff

+ test/lhs-test.latex+lhs view

file too large to diff

+ test/lhs-test.markdown view

file too large to diff

+ test/lhs-test.markdown+lhs view

file too large to diff

+ test/lhs-test.native view

file too large to diff

+ test/lhs-test.rst view

file too large to diff

+ test/lhs-test.rst+lhs view

file too large to diff

+ test/lua/block-count.lua view

file too large to diff

+ test/lua/hello-world-doc.lua view

file too large to diff

+ test/lua/implicit-doc-filter.lua view

file too large to diff

+ test/lua/markdown-reader.lua view

file too large to diff

+ test/lua/metatable-catch-all.lua view

file too large to diff

+ test/lua/plain-to-para.lua view

file too large to diff

+ test/lua/single-to-double-quoted.lua view

file too large to diff

+ test/lua/smallcaps-title.lua view

file too large to diff

+ test/lua/strmacro.lua view

file too large to diff

+ test/lua/undiv.lua view

file too large to diff

+ test/markdown-citations.native view

file too large to diff

+ test/markdown-citations.txt view

file too large to diff

+ test/markdown-reader-more.native view

file too large to diff

+ test/markdown-reader-more.txt view

file too large to diff

+ test/media/rId25.jpg view

file too large to diff

+ test/media/rId26.jpg view

file too large to diff

+ test/media/rId27.jpg view

file too large to diff

+ test/mediawiki-reader.native view

file too large to diff

+ test/mediawiki-reader.wiki view

file too large to diff

+ test/movie.jpg view

file too large to diff

+ test/odt/markdown/bold.md view

file too large to diff

+ test/odt/markdown/citation.md view

file too large to diff

+ test/odt/markdown/endnote.md view

file too large to diff

+ test/odt/markdown/externalLink.md view

file too large to diff

+ test/odt/markdown/footnote.md view

file too large to diff

+ test/odt/markdown/headers.md view

file too large to diff

+ test/odt/markdown/horizontalRule.md view

file too large to diff

+ test/odt/markdown/image.md view

file too large to diff

+ test/odt/markdown/imageIndex.md view

file too large to diff

+ test/odt/markdown/imageWithCaption.md view

file too large to diff

+ test/odt/markdown/italic.md view

file too large to diff

+ test/odt/markdown/listBlocks.md view

file too large to diff

+ test/odt/markdown/paragraph.md view

file too large to diff

+ test/odt/markdown/strikeout.md view

file too large to diff

+ test/odt/markdown/trackedChanges.md view

file too large to diff

+ test/odt/markdown/underlined.md view

file too large to diff

+ test/odt/native/blockquote.native view

file too large to diff

+ test/odt/native/image.native view

file too large to diff

+ test/odt/native/imageIndex.native view

file too large to diff

+ test/odt/native/imageWithCaption.native view

file too large to diff

+ test/odt/native/inlinedCode.native view

file too large to diff

+ test/odt/native/orderedListMixed.native view

file too large to diff

+ test/odt/native/orderedListRoman.native view

file too large to diff

+ test/odt/native/orderedListSimple.native view

file too large to diff

+ test/odt/native/referenceToChapter.native view

file too large to diff

+ test/odt/native/referenceToListItem.native view

file too large to diff

+ test/odt/native/referenceToText.native view

file too large to diff

+ test/odt/native/simpleTable.native view

file too large to diff

+ test/odt/native/simpleTableWithCaption.native view

file too large to diff

+ test/odt/native/tableWithContents.native view

file too large to diff

+ test/odt/native/textMixedStyles.native view

file too large to diff

+ test/odt/native/unicode.native view

file too large to diff

+ test/odt/native/unorderedList.native view

file too large to diff

+ test/odt/odt/blockquote.odt view

file too large to diff

+ test/odt/odt/bold.odt view

file too large to diff

+ test/odt/odt/citation.odt view

file too large to diff

+ test/odt/odt/endnote.odt view

file too large to diff

+ test/odt/odt/expression.odt view

file too large to diff

+ test/odt/odt/expressionUnevaluated.odt view

file too large to diff

+ test/odt/odt/externalLink.odt view

file too large to diff

+ test/odt/odt/footnote.odt view

file too large to diff

+ test/odt/odt/formula.odt view

file too large to diff

+ test/odt/odt/headers.odt view

file too large to diff

+ test/odt/odt/hiddenTextByStyle.odt view

file too large to diff

+ test/odt/odt/hiddenTextByVariable.odt view

file too large to diff

+ test/odt/odt/horizontalRule.odt view

file too large to diff

+ test/odt/odt/image.odt view

file too large to diff

+ test/odt/odt/imageIndex.odt view

file too large to diff

+ test/odt/odt/imageWithCaption.odt view

file too large to diff

+ test/odt/odt/inlinedCode.odt view

file too large to diff

+ test/odt/odt/italic.odt view

file too large to diff

+ test/odt/odt/listBlocks.odt view

file too large to diff

+ test/odt/odt/orderedListMixed.odt view

file too large to diff

+ test/odt/odt/orderedListRoman.odt view

file too large to diff

+ test/odt/odt/orderedListSimple.odt view

file too large to diff

+ test/odt/odt/paragraph.odt view

file too large to diff

+ test/odt/odt/referenceAllInOne.odt view

file too large to diff

+ test/odt/odt/referenceToChapter.odt view

file too large to diff

+ test/odt/odt/referenceToListItem.odt view

file too large to diff

+ test/odt/odt/referenceToText.odt view

file too large to diff

+ test/odt/odt/simpleTable.odt view

file too large to diff

+ test/odt/odt/simpleTableWithCaption.odt view

file too large to diff

+ test/odt/odt/strikeout.odt view

file too large to diff

+ test/odt/odt/table.odt view

file too large to diff

+ test/odt/odt/tableWithCaption.odt view

file too large to diff

+ test/odt/odt/tableWithContents.odt view

file too large to diff

+ test/odt/odt/textMixedStyles.odt view

file too large to diff

+ test/odt/odt/trackedChanges.odt view

file too large to diff

+ test/odt/odt/underlined.odt view

file too large to diff

+ test/odt/odt/unicode.odt view

file too large to diff

+ test/odt/odt/unorderedList.odt view

file too large to diff

+ test/odt/odt/variable.odt view

file too large to diff

+ test/opml-reader.native view

file too large to diff

+ test/opml-reader.opml view

file too large to diff

+ test/pipe-tables.native view

file too large to diff

+ test/pipe-tables.txt view

file too large to diff

+ test/rst-reader.native view

file too large to diff

+ test/rst-reader.rst view

file too large to diff

+ test/s5-basic.html view

file too large to diff

+ test/s5-fancy.html view

file too large to diff

+ test/s5-fragment.html view

file too large to diff

+ test/s5-inserts.html view

file too large to diff

+ test/s5.native view

file too large to diff

+ test/tables-rstsubset.native view

file too large to diff

+ test/tables.asciidoc view

file too large to diff

+ test/tables.context view

file too large to diff

+ test/tables.docbook4 view

file too large to diff

+ test/tables.docbook5 view

file too large to diff

+ test/tables.dokuwiki view

file too large to diff

+ test/tables.fb2 view

file too large to diff

+ test/tables.haddock view

file too large to diff

+ test/tables.html4 view

file too large to diff

+ test/tables.html5 view

file too large to diff

+ test/tables.icml view

file too large to diff

+ test/tables.jats view

file too large to diff

+ test/tables.latex view

file too large to diff

+ test/tables.man view

file too large to diff

+ test/tables.markdown view

file too large to diff

+ test/tables.mediawiki view

file too large to diff

+ test/tables.ms view

file too large to diff

+ test/tables.muse view

file too large to diff

+ test/tables.native view

file too large to diff

+ test/tables.opendocument view

file too large to diff

+ test/tables.org view

file too large to diff

+ test/tables.plain view

file too large to diff

+ test/tables.rst view

file too large to diff

+ test/tables.rtf view

file too large to diff

+ test/tables.tei view

file too large to diff

+ test/tables.texinfo view

file too large to diff

+ test/tables.textile view

file too large to diff

+ test/tables.txt view

file too large to diff

+ test/tables.zimwiki view

file too large to diff

+ test/test-pandoc.hs view

file too large to diff

+ test/testsuite.native view

file too large to diff

+ test/testsuite.txt view

file too large to diff

+ test/textile-reader.native view

file too large to diff

+ test/textile-reader.textile view

file too large to diff

+ test/tikiwiki-reader.native view

file too large to diff

+ test/tikiwiki-reader.tikiwiki view

file too large to diff

+ test/twiki-reader.native view

file too large to diff

+ test/twiki-reader.twiki view

file too large to diff

+ test/txt2tags.native view

file too large to diff

+ test/txt2tags.t2t view

file too large to diff

+ test/vimwiki-reader.native view

file too large to diff

+ test/vimwiki-reader.wiki view

file too large to diff

+ test/writer.asciidoc view

file too large to diff

+ test/writer.context view

file too large to diff

+ test/writer.docbook4 view

file too large to diff

+ test/writer.docbook5 view

file too large to diff

+ test/writer.dokuwiki view

file too large to diff

+ test/writer.fb2 view

file too large to diff

+ test/writer.haddock view

file too large to diff

+ test/writer.html4 view

file too large to diff

+ test/writer.html5 view

file too large to diff

+ test/writer.icml view

file too large to diff

+ test/writer.jats view

file too large to diff

+ test/writer.latex view

file too large to diff

+ test/writer.man view

file too large to diff

+ test/writer.markdown view

file too large to diff

+ test/writer.mediawiki view

file too large to diff

+ test/writer.ms view

file too large to diff

+ test/writer.muse view

file too large to diff

+ test/writer.native view

file too large to diff

+ test/writer.opendocument view

file too large to diff

+ test/writer.opml view

file too large to diff

+ test/writer.org view

file too large to diff

+ test/writer.plain view

file too large to diff

+ test/writer.rst view

file too large to diff

+ test/writer.rtf view

file too large to diff

+ test/writer.tei view

file too large to diff

+ test/writer.texinfo view

file too large to diff

+ test/writer.textile view

file too large to diff

+ test/writer.zimwiki view

file too large to diff

+ test/writers-lang-and-dir.context view

file too large to diff

+ test/writers-lang-and-dir.latex view

file too large to diff

+ test/writers-lang-and-dir.native view

file too large to diff

− tests/Tests/Helpers.hs

file too large to diff

− tests/Tests/Old.hs

file too large to diff

− tests/Tests/Readers/Docx.hs

file too large to diff

− tests/Tests/Readers/EPUB.hs

file too large to diff

− tests/Tests/Readers/HTML.hs

file too large to diff

− tests/Tests/Readers/LaTeX.hs

file too large to diff

− tests/Tests/Readers/Markdown.hs

file too large to diff

− tests/Tests/Readers/Odt.hs

file too large to diff

− tests/Tests/Readers/Org.hs

file too large to diff

− tests/Tests/Readers/RST.hs

file too large to diff

− tests/Tests/Readers/Txt2Tags.hs

file too large to diff

− tests/Tests/Shared.hs

file too large to diff

− tests/Tests/Walk.hs

file too large to diff

− tests/Tests/Writers/AsciiDoc.hs

file too large to diff

− tests/Tests/Writers/ConTeXt.hs

file too large to diff

− tests/Tests/Writers/Docbook.hs

file too large to diff

− tests/Tests/Writers/Docx.hs

file too large to diff

− tests/Tests/Writers/HTML.hs

file too large to diff

− tests/Tests/Writers/LaTeX.hs

file too large to diff

− tests/Tests/Writers/Markdown.hs

file too large to diff

− tests/Tests/Writers/Native.hs

file too large to diff

− tests/Tests/Writers/Plain.hs

file too large to diff

− tests/Tests/Writers/RST.hs

file too large to diff

− tests/Tests/Writers/TEI.hs

file too large to diff

− tests/bodybg.gif

file too large to diff

− tests/docbook-reader.docbook

file too large to diff

− tests/docbook-reader.native

file too large to diff

− tests/docbook-xref.docbook

file too large to diff

− tests/docbook-xref.native

file too large to diff

− tests/docx/adjacent_links.docx

file too large to diff

− tests/docx/adjacent_links.native

file too large to diff

− tests/docx/already_auto_ident.docx

file too large to diff

− tests/docx/already_auto_ident.native

file too large to diff

− tests/docx/block_quotes.docx

file too large to diff

− tests/docx/block_quotes_parse_indent.native

file too large to diff

− tests/docx/char_styles.docx

file too large to diff

− tests/docx/char_styles.native

file too large to diff

− tests/docx/codeblock.docx

file too large to diff

− tests/docx/codeblock.native

file too large to diff

− tests/docx/comments.docx

file too large to diff

− tests/docx/comments.native

file too large to diff

− tests/docx/comments_no_comments.native

file too large to diff

− tests/docx/comments_warning.docx

file too large to diff

− tests/docx/custom-style-reference.docx

file too large to diff

− tests/docx/custom-style-roundtrip-end.native

file too large to diff

− tests/docx/custom-style-roundtrip-start.native

file too large to diff

− tests/docx/deep_normalize.docx

file too large to diff

− tests/docx/deep_normalize.native

file too large to diff

− tests/docx/definition_list.docx

file too large to diff

− tests/docx/definition_list.native

file too large to diff

− tests/docx/drop_cap.docx

file too large to diff

− tests/docx/drop_cap.native

file too large to diff

− tests/docx/dummy_item_after_list_item.docx

file too large to diff

− tests/docx/dummy_item_after_list_item.native

file too large to diff

− tests/docx/dummy_item_after_paragraph.docx

file too large to diff

− tests/docx/dummy_item_after_paragraph.native

file too large to diff

− tests/docx/enumerated_headings.docx

file too large to diff

− tests/docx/enumerated_headings.native

file too large to diff

− tests/docx/german_styled_lists.docx

file too large to diff

− tests/docx/german_styled_lists.native

file too large to diff

− tests/docx/hanging_indent.docx

file too large to diff

− tests/docx/hanging_indent.native

file too large to diff

− tests/docx/headers.docx

file too large to diff

− tests/docx/headers.native

file too large to diff

− tests/docx/i18n_blocks.docx

file too large to diff

− tests/docx/i18n_blocks.native

file too large to diff

− tests/docx/image.docx

file too large to diff

− tests/docx/image_no_embed.native

file too large to diff

− tests/docx/image_no_embed_writer.native

file too large to diff

− tests/docx/image_vml.docx

file too large to diff

− tests/docx/image_vml.native

file too large to diff

− tests/docx/inline_code.docx

file too large to diff

− tests/docx/inline_code.native

file too large to diff

− tests/docx/inline_formatting.docx

file too large to diff

− tests/docx/inline_formatting.native

file too large to diff

− tests/docx/inline_formatting_writer.native

file too large to diff

− tests/docx/inline_images.docx

file too large to diff

− tests/docx/inline_images.native

file too large to diff

− tests/docx/inline_images_writer.native

file too large to diff

file too large to diff

file too large to diff

− tests/docx/links.docx

file too large to diff

− tests/docx/links.native

file too large to diff

file too large to diff

− tests/docx/lists.docx

file too large to diff

− tests/docx/lists.native

file too large to diff

− tests/docx/lists_writer.native

file too large to diff

− tests/docx/metadata.docx

file too large to diff

− tests/docx/metadata.native

file too large to diff

− tests/docx/metadata_after_normal.docx

file too large to diff

− tests/docx/metadata_after_normal.native

file too large to diff

− tests/docx/nested_anchors_in_header.docx

file too large to diff

− tests/docx/nested_anchors_in_header.native

file too large to diff

− tests/docx/normalize.docx

file too large to diff

− tests/docx/normalize.native

file too large to diff

− tests/docx/notes.docx

file too large to diff

− tests/docx/notes.native

file too large to diff

− tests/docx/numbered_header.docx

file too large to diff

− tests/docx/numbered_header.native

file too large to diff

− tests/docx/special_punctuation.docx

file too large to diff

− tests/docx/special_punctuation.native

file too large to diff

− tests/docx/table_one_row.docx

file too large to diff

− tests/docx/table_one_row.native

file too large to diff

− tests/docx/table_with_list_cell.docx

file too large to diff

− tests/docx/table_with_list_cell.native

file too large to diff

− tests/docx/tables.docx

file too large to diff

− tests/docx/tables.native

file too large to diff

− tests/docx/tabs.docx

file too large to diff

− tests/docx/tabs.native

file too large to diff

− tests/docx/track_changes_deletion.docx

file too large to diff

− tests/docx/track_changes_deletion_accept.native

file too large to diff

− tests/docx/track_changes_deletion_all.native

file too large to diff

− tests/docx/track_changes_deletion_reject.native

file too large to diff

− tests/docx/track_changes_insertion.docx

file too large to diff

− tests/docx/track_changes_insertion_accept.native

file too large to diff

− tests/docx/track_changes_insertion_all.native

file too large to diff

− tests/docx/track_changes_insertion_reject.native

file too large to diff

− tests/docx/track_changes_move.docx

file too large to diff

− tests/docx/track_changes_move_accept.native

file too large to diff

− tests/docx/track_changes_move_all.native

file too large to diff

− tests/docx/track_changes_move_reject.native

file too large to diff

− tests/docx/trailing_spaces_in_formatting.docx

file too large to diff

− tests/docx/trailing_spaces_in_formatting.native

file too large to diff

− tests/docx/unicode.docx

file too large to diff

− tests/docx/unicode.native

file too large to diff

− tests/docx/verbatim_subsuper.docx

file too large to diff

− tests/docx/verbatim_subsuper.native

file too large to diff

− tests/dokuwiki_external_images.dokuwiki

file too large to diff

− tests/dokuwiki_external_images.native

file too large to diff

− tests/dokuwiki_inline_formatting.dokuwiki

file too large to diff

− tests/dokuwiki_inline_formatting.native

file too large to diff

− tests/dokuwiki_multiblock_table.dokuwiki

file too large to diff

− tests/dokuwiki_multiblock_table.native

file too large to diff

− tests/epub/features.epub

file too large to diff

− tests/epub/features.native

file too large to diff

− tests/epub/formatting.epub

file too large to diff

− tests/epub/formatting.native

file too large to diff

− tests/epub/img.epub

file too large to diff

− tests/epub/wasteland.epub

file too large to diff

− tests/epub/wasteland.native

file too large to diff

− tests/fb2/basic.fb2

file too large to diff

− tests/fb2/basic.markdown

file too large to diff

− tests/fb2/images-embedded.fb2

file too large to diff

− tests/fb2/images-embedded.html

file too large to diff

− tests/fb2/images.fb2

file too large to diff

− tests/fb2/images.markdown

file too large to diff

− tests/fb2/math.fb2

file too large to diff

− tests/fb2/math.markdown

file too large to diff

− tests/fb2/test-small.png

file too large to diff

− tests/fb2/test.jpg

file too large to diff

− tests/fb2/titles.fb2

file too large to diff

− tests/fb2/titles.markdown

file too large to diff

− tests/haddock-reader.haddock

file too large to diff

− tests/haddock-reader.native

file too large to diff

− tests/html-reader.html

file too large to diff

− tests/html-reader.native

file too large to diff

− tests/insert

file too large to diff

− tests/lalune.jpg

file too large to diff

− tests/latex-reader.latex

file too large to diff

− tests/latex-reader.native

file too large to diff

− tests/lhs-test-markdown.native

file too large to diff

− tests/lhs-test.fragment.html+lhs

file too large to diff

− tests/lhs-test.html

file too large to diff

− tests/lhs-test.html+lhs

file too large to diff

− tests/lhs-test.latex

file too large to diff

− tests/lhs-test.latex+lhs

file too large to diff

− tests/lhs-test.markdown

file too large to diff

− tests/lhs-test.markdown+lhs

file too large to diff

− tests/lhs-test.native

file too large to diff

− tests/lhs-test.rst

file too large to diff

− tests/lhs-test.rst+lhs

file too large to diff

− tests/markdown-citations.native

file too large to diff

− tests/markdown-citations.txt

file too large to diff

− tests/markdown-reader-more.native

file too large to diff

− tests/markdown-reader-more.txt

file too large to diff

− tests/media/rId25.jpg

file too large to diff

− tests/media/rId26.jpg

file too large to diff

− tests/media/rId27.jpg

file too large to diff

− tests/mediawiki-reader.native

file too large to diff

− tests/mediawiki-reader.wiki

file too large to diff

− tests/movie.jpg

file too large to diff

− tests/odt/markdown/bold.md

file too large to diff

− tests/odt/markdown/citation.md

file too large to diff

− tests/odt/markdown/endnote.md

file too large to diff

− tests/odt/markdown/externalLink.md

file too large to diff

− tests/odt/markdown/footnote.md

file too large to diff

− tests/odt/markdown/headers.md

file too large to diff

− tests/odt/markdown/horizontalRule.md

file too large to diff

− tests/odt/markdown/image.md

file too large to diff

− tests/odt/markdown/imageIndex.md

file too large to diff

− tests/odt/markdown/imageWithCaption.md

file too large to diff

− tests/odt/markdown/italic.md

file too large to diff

− tests/odt/markdown/listBlocks.md

file too large to diff

− tests/odt/markdown/paragraph.md

file too large to diff

− tests/odt/markdown/strikeout.md

file too large to diff

− tests/odt/markdown/trackedChanges.md

file too large to diff

− tests/odt/markdown/underlined.md

file too large to diff

− tests/odt/native/blockquote.native

file too large to diff

− tests/odt/native/image.native

file too large to diff

− tests/odt/native/imageIndex.native

file too large to diff

− tests/odt/native/imageWithCaption.native

file too large to diff

− tests/odt/native/inlinedCode.native

file too large to diff

− tests/odt/native/orderedListMixed.native

file too large to diff

− tests/odt/native/orderedListRoman.native

file too large to diff

− tests/odt/native/orderedListSimple.native

file too large to diff

− tests/odt/native/referenceToChapter.native

file too large to diff

− tests/odt/native/referenceToListItem.native

file too large to diff

− tests/odt/native/referenceToText.native

file too large to diff

− tests/odt/native/simpleTable.native

file too large to diff

− tests/odt/native/simpleTableWithCaption.native

file too large to diff

− tests/odt/native/tableWithContents.native

file too large to diff

− tests/odt/native/textMixedStyles.native

file too large to diff

− tests/odt/native/unicode.native

file too large to diff

− tests/odt/native/unorderedList.native

file too large to diff

− tests/odt/odt/blockquote.odt

file too large to diff

− tests/odt/odt/bold.odt

file too large to diff

− tests/odt/odt/citation.odt

file too large to diff

− tests/odt/odt/endnote.odt

file too large to diff

− tests/odt/odt/expression.odt

file too large to diff

− tests/odt/odt/expressionUnevaluated.odt

file too large to diff

− tests/odt/odt/externalLink.odt

file too large to diff

− tests/odt/odt/footnote.odt

file too large to diff

− tests/odt/odt/formula.odt

file too large to diff

− tests/odt/odt/headers.odt

file too large to diff

− tests/odt/odt/hiddenTextByStyle.odt

file too large to diff

− tests/odt/odt/hiddenTextByVariable.odt

file too large to diff

− tests/odt/odt/horizontalRule.odt

file too large to diff

− tests/odt/odt/image.odt

file too large to diff

− tests/odt/odt/imageIndex.odt

file too large to diff

− tests/odt/odt/imageWithCaption.odt

file too large to diff

− tests/odt/odt/inlinedCode.odt

file too large to diff

− tests/odt/odt/italic.odt

file too large to diff

− tests/odt/odt/listBlocks.odt

file too large to diff

− tests/odt/odt/orderedListMixed.odt

file too large to diff

− tests/odt/odt/orderedListRoman.odt

file too large to diff

− tests/odt/odt/orderedListSimple.odt

file too large to diff

− tests/odt/odt/paragraph.odt

file too large to diff

− tests/odt/odt/referenceAllInOne.odt

file too large to diff

− tests/odt/odt/referenceToChapter.odt

file too large to diff

− tests/odt/odt/referenceToListItem.odt

file too large to diff

− tests/odt/odt/referenceToText.odt

file too large to diff

− tests/odt/odt/simpleTable.odt

file too large to diff

− tests/odt/odt/simpleTableWithCaption.odt

file too large to diff

− tests/odt/odt/strikeout.odt

file too large to diff

− tests/odt/odt/table.odt

file too large to diff

− tests/odt/odt/tableWithCaption.odt

file too large to diff

− tests/odt/odt/tableWithContents.odt

file too large to diff

− tests/odt/odt/textMixedStyles.odt

file too large to diff

− tests/odt/odt/trackedChanges.odt

file too large to diff

− tests/odt/odt/underlined.odt

file too large to diff

− tests/odt/odt/unicode.odt

file too large to diff

− tests/odt/odt/unorderedList.odt

file too large to diff

− tests/odt/odt/variable.odt

file too large to diff

− tests/opml-reader.native

file too large to diff

− tests/opml-reader.opml

file too large to diff

− tests/pipe-tables.native

file too large to diff

− tests/pipe-tables.txt

file too large to diff

− tests/rst-reader.native

file too large to diff

− tests/rst-reader.rst

file too large to diff

− tests/s5-basic.html

file too large to diff

− tests/s5-fancy.html

file too large to diff

− tests/s5-fragment.html

file too large to diff

− tests/s5-inserts.html

file too large to diff

− tests/s5.native

file too large to diff

− tests/tables-rstsubset.native

file too large to diff

− tests/tables.asciidoc

file too large to diff

− tests/tables.context

file too large to diff

− tests/tables.docbook

file too large to diff

− tests/tables.docbook5

file too large to diff

− tests/tables.dokuwiki

file too large to diff

− tests/tables.fb2

file too large to diff

− tests/tables.haddock

file too large to diff

− tests/tables.html

file too large to diff

− tests/tables.icml

file too large to diff

− tests/tables.latex

file too large to diff

− tests/tables.man

file too large to diff

− tests/tables.markdown

file too large to diff

− tests/tables.mediawiki

file too large to diff

− tests/tables.native

file too large to diff

− tests/tables.opendocument

file too large to diff

− tests/tables.org

file too large to diff

− tests/tables.plain

file too large to diff

− tests/tables.rst

file too large to diff

− tests/tables.rtf

file too large to diff

− tests/tables.tei

file too large to diff

− tests/tables.texinfo

file too large to diff

− tests/tables.textile

file too large to diff

− tests/tables.txt

file too large to diff

− tests/tables.zimwiki

file too large to diff

− tests/test-pandoc.hs

file too large to diff

− tests/testsuite.native

file too large to diff

− tests/testsuite.txt

file too large to diff

− tests/textile-reader.native

file too large to diff

− tests/textile-reader.textile

file too large to diff

− tests/twiki-reader.native

file too large to diff

− tests/twiki-reader.twiki

file too large to diff

− tests/txt2tags.native

file too large to diff

− tests/txt2tags.t2t

file too large to diff

− tests/writer.asciidoc

file too large to diff

− tests/writer.context

file too large to diff

− tests/writer.docbook

file too large to diff

− tests/writer.docbook5

file too large to diff

− tests/writer.dokuwiki

file too large to diff

− tests/writer.fb2

file too large to diff

− tests/writer.haddock

file too large to diff

− tests/writer.html

file too large to diff

− tests/writer.icml

file too large to diff

− tests/writer.latex

file too large to diff

− tests/writer.man

file too large to diff

− tests/writer.markdown

file too large to diff

− tests/writer.mediawiki

file too large to diff

− tests/writer.native

file too large to diff

− tests/writer.opendocument

file too large to diff

− tests/writer.opml

file too large to diff

− tests/writer.org

file too large to diff

− tests/writer.plain

file too large to diff

− tests/writer.rst

file too large to diff

− tests/writer.rtf

file too large to diff

− tests/writer.tei

file too large to diff

− tests/writer.texinfo

file too large to diff

− tests/writer.textile

file too large to diff

− tests/writer.zimwiki

file too large to diff

− tests/writers-lang-and-dir.context

file too large to diff

− tests/writers-lang-and-dir.latex

file too large to diff

− tests/writers-lang-and-dir.native

file too large to diff

trypandoc/Makefile view

file too large to diff

trypandoc/index.html view

file too large to diff

trypandoc/trypandoc.hs view

file too large to diff