packages feed

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 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     ![$img_style$](../images/an_image.png)@@ -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------ > ![$img_style$](../images/an_image.png)--- > [$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