summaryrefslogtreecommitdiff
path: root/src/Text/Pandoc/Shared.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Text/Pandoc/Shared.hs')
-rw-r--r--src/Text/Pandoc/Shared.hs77
1 files changed, 74 insertions, 3 deletions
diff --git a/src/Text/Pandoc/Shared.hs b/src/Text/Pandoc/Shared.hs
index c571c4143..9c62db86e 100644
--- a/src/Text/Pandoc/Shared.hs
+++ b/src/Text/Pandoc/Shared.hs
@@ -1,6 +1,6 @@
{-# LANGUAGE DeriveDataTypeable, CPP #-}
{-
-Copyright (C) 2006-2010 John MacFarlane <jgm@berkeley.edu>
+Copyright (C) 2006-2013 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 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
{- |
Module : Text.Pandoc.Shared
- Copyright : Copyright (C) 2006-2010 John MacFarlane
+ Copyright : Copyright (C) 2006-2013 John MacFarlane
License : GNU GPL, version 2 or above
Maintainer : John MacFarlane <jgm@berkeley.edu>
@@ -61,6 +61,10 @@ module Text.Pandoc.Shared (
isHeaderBlock,
headerShift,
isTightList,
+ addMetaField,
+ makeMeta,
+ metaToJSON,
+ setField,
-- * TagSoup HTML handling
renderTags',
-- * File handling
@@ -78,7 +82,7 @@ module Text.Pandoc.Shared (
import Text.Pandoc.Definition
import Text.Pandoc.Generic
-import Text.Pandoc.Builder (Blocks)
+import Text.Pandoc.Builder (Blocks, ToMetaValue(..))
import qualified Text.Pandoc.Builder as B
import qualified Text.Pandoc.UTF8 as UTF8
import System.Environment (getProgName)
@@ -86,6 +90,7 @@ import System.Exit (exitWith, ExitCode(..))
import Data.Char ( toLower, isLower, isUpper, isAlpha,
isLetter, isDigit, isSpace )
import Data.List ( find, isPrefixOf, intercalate )
+import qualified Data.Map as M
import Network.URI ( escapeURIString, isAbsoluteURI, parseURI, unEscapeString )
import System.Directory
import Text.Pandoc.MIME (getMimeType)
@@ -104,6 +109,11 @@ import qualified Data.ByteString.Char8 as B8
import Network.HTTP (findHeader, rspBody,
RequestMethod(..), HeaderName(..), mkRequest)
import Network.Browser (browse, setAllowRedirects, setOutHandler, request)
+import qualified Data.Traversable as Traversable
+import qualified Data.HashMap.Strict as H
+import qualified Data.Text as T
+import Data.Aeson (ToJSON (..), Value(Object), Result(..), fromJSON)
+
#ifdef EMBED_DATA_FILES
import Text.Pandoc.Data (dataFiles)
import System.FilePath ( joinPath, splitDirectories )
@@ -491,6 +501,67 @@ isTightList = and . map firstIsPlain
where firstIsPlain (Plain _ : _) = True
firstIsPlain _ = False
+-- | Set a field of a 'Meta' object. If the field already has a value,
+-- convert it into a list with the new value appended to the old value(s).
+addMetaField :: ToMetaValue a
+ => String
+ -> a
+ -> Meta
+ -> Meta
+addMetaField key val (Meta meta) =
+ Meta $ M.insertWith combine key (toMetaValue val) meta
+ where combine newval (MetaList xs) = MetaList (xs ++ [newval])
+ combine newval x = MetaList [x, newval]
+
+-- | Create 'Meta' from old-style title, authors, date. This is
+-- provided to ease the transition from the old API.
+makeMeta :: [Inline] -> [[Inline]] -> [Inline] -> Meta
+makeMeta title authors date =
+ addMetaField "title" (B.fromList title)
+ $ addMetaField "author" (map B.fromList authors)
+ $ addMetaField "date" (B.fromList date)
+ $ nullMeta
+
+-- | 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.
+metaToJSON :: (Monad m, Functor m)
+ => ([Block] -> m String) -- ^ Writer for output format
+ => ([Inline] -> m String) -- ^ Writer for output format
+ -> Meta -- ^ Metadata
+ -> m Value
+metaToJSON blockWriter inlineWriter (Meta metamap) = toJSON
+ `fmap` Traversable.mapM (metaValueToJSON blockWriter inlineWriter) metamap
+
+metaValueToJSON :: (Monad m, Functor m)
+ => ([Block] -> m String)
+ -> ([Inline] -> m String)
+ -> MetaValue
+ -> m Value
+metaValueToJSON blockWriter inlineWriter (MetaMap metamap) = toJSON
+ `fmap` Traversable.mapM (metaValueToJSON blockWriter inlineWriter) metamap
+metaValueToJSON blockWriter inlineWriter (MetaList xs) =
+ toJSON `fmap` Traversable.mapM (metaValueToJSON blockWriter inlineWriter) xs
+metaValueToJSON _ _ (MetaString s) = return $ toJSON s
+metaValueToJSON blockWriter _ (MetaBlocks bs) = toJSON `fmap` blockWriter bs
+metaValueToJSON _ inlineWriter (MetaInlines bs) = toJSON `fmap` inlineWriter bs
+
+setField :: ToJSON a
+ => String
+ -> a
+ -> Value
+ -> Value
+-- | Set a field of a JSON object. If the field already has a value,
+-- convert it into a list with the new value appended to the old value(s).
+-- This is a utility function to be used in preparing template contexts.
+setField field val (Object hashmap) =
+ 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]
+setField _ _ x = x
+
--
-- TagSoup HTML handling
--