pandoc-stylefrommeta 0.1.1.0 → 0.2.0.0
raw patch · 4 files changed
+175/−134 lines, 4 filesdep +bytestringdep +textdep −HaTeX
Dependencies added: bytestring, text
Dependencies removed: HaTeX
Files
- Changelog.md +9/−0
- README.md +63/−14
- pandoc-stylefrommeta.cabal +6/−5
- styleFromMeta.hs +97/−115
Changelog.md view
@@ -1,3 +1,12 @@+### 0.2.0.0++- Render substitutions using Pandoc's writers.+- Improved matching algorithms in metadata blocks.+- Implemented a new method of substitution using code blocks in metadata. This+ method must be preferred for all output formats.+- Added verbatim placeholders `$$SRC$$` and `$$TITLE$$`, and placeholder+ `$$ALT$$` in which all formatting is removed.+ ### 0.1.1.0 - Added support for Pandoc 2.0.
README.md view
@@ -1,44 +1,64 @@ styleFromMeta ============= -Pandoc filter to apply styles found in the metadata of the document for various+Pandoc filter to apply styles found in the metadata of the document to various objects. Styling is supported for following types of objects: -- Standalone images-- Inline images+- Standalone and inlined images - Links - Paragraphs (with restrictions, see below) Styles are read from the metadata of the document: they may reside inside the-document or in a separate YAML file. For example+document or in a separate YAML file. For example, ```yaml --- img_style : html : |+ ~~~~~ <div style="clear: both; text-align: center; margin-bottom: 16px"> <a href="$SRC$" style="margin-left: 10em;" alt="$ALT$"> <img border="0" src="$SRC$" /></a></div>+ ~~~~~ latex : |+ ~~~~~ \begin{center}- \includegraphics{$SRC$}+ \includegraphics{$$SRC$$} \end{center}+ ~~~~~+ rst: |+ ~~~~~+ .. image:: $$SRC$$+ :height: 100px+ :width: 200 px+ :scale: 50 %+ :alt: $$ALT$$+ :align: right+ ~~~~~+ haddock: |+ ~~~~~+ <<$$SRC$$ An image $ALT$>>+ ~~~~~ link_style : html : |+ ~~~~~ <a href="$SRC$" style="margin-left: 1em; margin-right: 1em;">$ALT$</a>+ ~~~~~ latex : |+ ~~~~~ \href{$SRC$}{\colorbox{green}{$ALT$}}+ ~~~~~ para_style : html : | <span style="display: block; margin-bottom: 16px;"></span> ... ``` -declares styles *img\_style*, *link\_style* and *para\_style*. Their names-(except for the last) are arbitrarily chosen and may be referred from the-document, for example+declares styles `img_style`, `link_style` and `para_style`. Their names (except+for the last) are arbitrarily chosen and may be referred from the document, for+example ```markdown @@ -46,13 +66,42 @@ ``` Placeholders `$ALT$`, `$SRC$` and `$TITLE$` from style declarations are to be-replaced by concrete data found in the object declaration. In the last example+replaced by corresponding data found in the object declaration. In this example `*here*` corresponds to `$ALT$`, and `http://example.com/` corresponds to-`$SRC$`.+`$SRC$`. Placeholders `$$SRC$$` and `$$TITLE$$` are replaced verbatim, in+`$$ALT$$` all formatting gets removed. In the example `$$SRC$$` is used to keep+underscores unescaped as they may reside in image names. +Notice that all metablocks contents, with the exclusion of `para_style`, are+wrapped inside code blocks. This let the contents be substituted verbatim for+any output format. However, raw HTML and TeX blocks are well supported by+Pandoc, so we could rewrite parts of the example like this:++```yaml+ ---+ img_style :+ html : |+ <div style="clear: both; text-align: center; margin-bottom: 16px">+ <a href="$SRC$" style="margin-left: 10em;" alt="$ALT$">+ <img border="0" src="$SRC$" /></a></div>+ latex : |+ \begin{center}+ \includegraphics{$$SRC$$}+ \end{center}++ # ...++ ...+```++The filter has support for raw HTML and TeX blocks, but this support is not+complete, and in some cases substitutions may fail. In addition, Pandoc may+re-format substitutions. That's why this method is not recommended to use.+ As soon as paragraphs do not have place where to put extra data, style-*para\_style* is applied to all paragraphs in the document. Currently only-transformation to a span block is supported. Any contents found between opening-and closing span tags are ignored: actual paragraph contents will be inserted-inside them.+`para_style` is applied to all paragraphs in the document. Currently, only+transformation to a span block is supported (which is probably useful only in+HTML). Any contents found between opening and closing span tags are ignored:+actual paragraph contents will be inserted inside them. Notice that wrapping+inside code blocks is not allowed in `para_style` block.
pandoc-stylefrommeta.cabal view
@@ -1,10 +1,10 @@ name: pandoc-stylefrommeta-version: 0.1.1.0+version: 0.2.0.0 synopsis: Pandoc filter to customize links, images and paragraphs description: Pandoc filter to customize links, images and paragraphs- (with restrictions). Styles are read from the metadata of the document:- they may reside inside the document or in a separate YAML file. See- details <http://github.com/lyokha/styleFromMeta#stylefrommeta here>.+ (with restrictions) in HTML and LaTeX formats. Styles are read from the+ metadata of the document: they may reside inside the document or in a+ separate YAML file. homepage: http://github.com/lyokha/styleFromMeta license: BSD3 license-file: LICENSE@@ -22,7 +22,8 @@ , pandoc-types >= 1.12 , containers >= 0.2 , MissingH >= 1.0.0- , HaTeX >= 3.3+ , text+ , bytestring extensions: CPP main-is: styleFromMeta.hs
styleFromMeta.hs view
@@ -1,21 +1,36 @@-{-# OPTIONS_HADDOCK prune, ignore-exports #-} {-# LANGUAGE ViewPatterns, PatternGuards, PatternSynonyms #-} import Text.Pandoc.JSON import Text.Pandoc.Walk (walk)+import Text.Pandoc.Options (def) import Text.Pandoc.Shared (stringify)-import Text.Pandoc.XML (escapeStringForXML) import qualified Data.Map as M import Data.String.Utils (replace)-import Text.LaTeX.Base.Syntax (protectString) #if MIN_VERSION_pandoc(2,0,0)+import Text.Pandoc.Writers (Writer (..), getWriter)+import Text.Pandoc.Class (runPure)+import qualified Data.ByteString.Lazy.Char8 as C8L+import qualified Data.Text as T+import Control.Exception (displayException)+ #define MBPLAIN Plain #else+import Text.Pandoc (Writer (..), getWriter)+ #define MBPLAIN Para #endif +pattern Style :: String -> Inline pattern Style x <- Math InlineMath x++pattern Subst :: String -> Inline+pattern Subst x = Math InlineMath x++pattern SubstVerbatim :: String -> Inline+pattern SubstVerbatim x <- Math DisplayMath x++pattern Alt :: [Inline] -> [Inline] pattern Alt x <- (dropWhile (== Space) -> x) type MMap = M.Map String MetaValue@@ -23,95 +38,47 @@ type InlineParams = (Inline, [Inline], Target) -- (style:alt, target) type InlineCons = [Inline] -> Target -> Inline -- Image or Link --- | Applies style found in the metadata of the document for various objects------ Styling is supported for following types of objects:------ * Standalone images------ * Inline images------ * Links------ * Paragraphs (with restrictions, see below)------ Styles are read from the metadata of the document: they may reside inside--- the document or in a separate YAML file. For example------ > ------ > img_style :--- > html : |--- > <div style="clear: both; text-align: center; margin-bottom: 16px">--- > <a href="$SRC$" style="margin-left: 10em;" alt="$ALT$">--- > <img border="0" src="$SRC$" /></a></div>--- > latex : |--- > \begin{center}--- > \includegraphics{$SRC$}--- > \end{center}--- > link_style :--- > html : |--- > <a href="$SRC$" style="margin-left: 1em; margin-right: 1em;">$ALT$</a>--- > latex : |--- > \href{$SRC$}{\colorbox{green}{$ALT$}}--- > para_style :--- > html : |--- > <span style="display: block; margin-bottom: 16px;"></span>--- > ...------ declares styles /img_style/, /link_style/ and /para_style/. Their names--- (except for the last) are arbitrarily chosen and may be referred from the--- document, for example------ > --- > [$link_style$ *here*](http://example.com/)------ Placeholders /$ALT$/, /$SRC$/ and /$TITLE$/ from style declarations are--- to be replaced by concrete data found in the object declaration. In the--- last example @*here*@ corresponds to /$ALT$/ and @http:\/\/example.com/@--- corresponds to /$SRC$/.------ As soon as paragraphs do not have place where to put extra data, style--- /para_style/ is applied to all paragraphs in the document. Currently only--- transformation to a span block is supported. Any contents found between--- opening and closing span tags are ignored: actual paragraph contents will--- be inserted inside them.--- styleFromMeta :: Maybe Format -> Pandoc -> IO Pandoc-styleFromMeta (Just fm) (Pandoc m bs) =- return $ Pandoc m $ walk (substStyle fm $ unMeta m) bs+styleFromMeta (Just fm) (Pandoc m bs) = do+ let b = unMeta m+ return $ Pandoc m $+ walk (substInlineStyle fm b) $ -- apply styles for links and images+ walk (substBlockStyle fm b) bs -- apply para_style to paragraphs styleFromMeta _ p = return p -substStyle :: Format -> MMap -> Block -> Block-substStyle fm@(Format fmt) m b@(Para [Image attr (Style style : Alt alt) tgt])- | Just (MetaMap mm) <- M.lookup style m =- let params = (alt, tgt)- substStyle' (Just (MetaBlocks [RawBlock f s])) =- RawBlock f $ substParams fm params s- substStyle' (Just (MetaBlocks [b])) = walk substParams' b- where substParams' (RawInline f s) =- RawInline f $ substParams fm params s- substParams' i = i- substStyle' Nothing = Para [Image attr alt tgt]- substStyle' _ = b- in substStyle' $ M.lookup fmt mm- | otherwise = b-substStyle fm@(Format fmt) m (Para cnt)+substBlockStyle :: Format -> MMap -> Block -> Block+substBlockStyle _ _ b@(Para is@(Image {} : _))+ | all isImage is = b -- do not apply para_style to standalone images+ where isImage Image {} = True+ isImage _ = False+substBlockStyle (Format fmt) m (Para cnt) | Just (MetaMap mm) <- M.lookup "para_style" m , Just (MetaBlocks [MBPLAIN [Span attr _]]) <- M.lookup fmt mm =- walk (substInlineStyle fm m) $ Plain [Span attr cnt]-substStyle fm m b = walk (substInlineStyle fm m) b+ Plain [Span attr cnt]+substBlockStyle _ _ b = b substInlineStyle :: Format -> MMap -> Inline -> Inline substInlineStyle fm@(Format fmt) m i@(toInlineParams -> Just ((Style style, alt, tgt), cons)) | Just (MetaMap mm) <- M.lookup style m =- let substInlineStyle' (Just (MetaBlocks- [MBPLAIN (RawInline f s : r)])) =- RawInline f $ substParams fm params $- s ++ stringify' fm (map subst r)- where params = (alt, tgt)- subst (Style "ALT") = RawInline f "$ALT$"- subst i = i+ let params = (alt, tgt)+ substPlainParams = Span nullAttr . map (substParams fm params)+ substInlineStyle' (Just (MetaBlocks [CodeBlock _ vb])) =+ RawInline fm $ substParamsInRawBlock fm params vb+ substInlineStyle' (Just (MetaBlocks mbs)) =+ RawInline fm $ renderInlines fm $ map substInlineStyle'' mbs+ where substInlineStyle'' mb =+ case mb of+ Plain is -> substPlainParams is+ Para is -> substPlainParams is+ d@Div {} ->+ RawInline fm $+ substParamsInRawBlock fm params $+ renderBlocks fm [d]+ RawBlock bfm b ->+ RawInline bfm $+ substParamsInRawBlock bfm params b+ _ -> i substInlineStyle' Nothing = cons alt tgt substInlineStyle' _ = i in substInlineStyle' $ M.lookup fmt mm@@ -124,41 +91,56 @@ Just ((style, alt, tgt), Link attr) toInlineParams _ = Nothing -substParams :: Format -> PureInlineParams -> String -> String-substParams fm (alt, (escape fm -> src, escape fm -> title)) s =- foldr (uncurry replace) s- [("$ALT$", stringify' fm alt), ("$SRC$", src), ("$TITLE$", title)]+substParams :: Format -> PureInlineParams -> Inline -> Inline+substParams _ (alt, _) (Subst "ALT") = Span nullAttr alt+substParams fm params (SubstVerbatim "ALT") = RawInline fm $+ stringify $ substParams fm params $ Subst "ALT"+substParams _ (_, (src, _)) (Subst "SRC") = Str src+substParams fm (_, (src, _)) (SubstVerbatim "SRC") = RawInline fm src+substParams _ (_, (_, title)) (Subst "TITLE") = Str title+substParams fm (_, (_, title)) (SubstVerbatim "TITLE") = RawInline fm title+substParams _ params (RawInline fm s) = RawInline fm $+ substParamsInRawBlock fm params s+substParams _ _ i = i -escape :: Format -> String -> String-escape (Format "latex") = protectString-escape (Format "html") = escapeStringForXML--- TODO: properly escape other formats-escape _ = id+substParamsInRawBlock :: Format -> PureInlineParams -> String -> String+substParamsInRawBlock fm (alt, (src, title)) s =+ foldr (\(p, is) -> replace p $ renderInlines fm is) s+ [("$ALT$", alt )+ ,("$SRC$", [Str src] )+ ,("$TITLE$", [Str title] )+ ,("$$ALT$$", [RawInline fm $ stringify $ Span nullAttr alt])+ ,("$$SRC$$", [RawInline fm src] )+ ,("$$TITLE$$", [RawInline fm title] )+ ] -stringify' :: Format -> [Inline] -> String-stringify' fm@(Format fmt@("latex")) =- foldr ((++) . subst) ""- where subst (Emph x) = "\\emph{" ++ stringify' fm x ++ "}"- subst (Strong x) = "\\textbf{" ++ stringify' fm x ++ "}"- subst (Strikeout x) = "\\sout{" ++ stringify' fm x ++ "}"- subst (Superscript x) = "\\textsuperscript{" ++ stringify' fm x ++ "}"- subst (Subscript x) = "\\textsubscript{" ++ stringify' fm x ++ "}"- subst (RawInline fmt x) = x- subst (Math _ x) = "$" ++ x ++ "$"- subst (Str x) = escape fm x- subst x = stringify x-stringify' fm@(Format fmt@("html")) =- foldr ((++) . subst) ""- where subst (Emph x) = "<em>" ++ stringify' fm x ++ "</em>"- subst (Strong x) = "<strong>" ++ stringify' fm x ++ "</strong>"- subst (Strikeout x) = "<del>" ++ stringify' fm x ++ "</del>"- subst (Superscript x) = "<sup>" ++ stringify' fm x ++ "</sup>"- subst (Subscript x) = "<sub>" ++ stringify' fm x ++ "</sub>"- subst (RawInline fmt x) = x- subst (Str x) = escape fm x- subst x = stringify x--- TODO: properly stringify' other formats-stringify' _ = stringify+renderBlocks :: Format -> [Block] -> String+renderBlocks fm p =+ let fmt = toWriterFormat fm+ writer = getWriter fmt+ doc = Pandoc (Meta M.empty) p+ in case writer of+ Left _ -> error $ "Unknown format " ++ fmt+#if MIN_VERSION_pandoc(2,0,0)+ Right (TextWriter w, _) ->+ case runPure $ w def doc of+ Left e -> displayException e+ Right r -> T.unpack r+ Right (ByteStringWriter w, _) ->+ case runPure $ w def doc of+ Left e -> displayException e+ Right r -> C8L.unpack r+#else+ Right (PureStringWriter w) -> w def doc+ _ -> error $ "Unsupported format " ++ fmt ++ ", try Pandoc 2.0!"+#endif++renderInlines :: Format -> [Inline] -> String+renderInlines fm p = renderBlocks fm [Plain p]++toWriterFormat :: Format -> String+toWriterFormat (Format "tex") = "latex"+toWriterFormat (Format fmt) = fmt main :: IO () main = toJSONFilter styleFromMeta