-----------------------------------------------------------------------------
-- |
-- Module      :  Text.BlogLiterately.LaTeX
-- Copyright   :  (c) 2012 Brent Yorgey
-- License     :  GPL (see LICENSE)
-- Maintainer  :  Brent Yorgey <byorgey@gmail.com>
--
-- Utilities for working with embedded LaTeX.
--
-----------------------------------------------------------------------------

{-# LANGUAGE OverloadedStrings #-}

module Text.BlogLiterately.LaTeX
    (
      rawTeXify
    , wpTeXify
    ) where

import           Data.Text   (Text)
import qualified Data.Text   as T
import           Text.Pandoc

bracket :: Text -> Text -> Text -> Text
bracket :: Text -> Text -> Text -> Text
bracket l :: Text
l r :: Text
r t :: Text
t = Text -> Text -> Text
T.append Text
l (Text -> Text -> Text
T.append Text
t Text
r)

-- | Pass LaTeX through unchanged.
rawTeXify :: Pandoc -> Pandoc
rawTeXify :: Pandoc -> Pandoc
rawTeXify = ([Block] -> [Block]) -> Pandoc -> Pandoc
forall a b. (Data a, Data b) => (a -> a) -> b -> b
bottomUp [Block] -> [Block]
formatDisplayTex (Pandoc -> Pandoc) -> (Pandoc -> Pandoc) -> Pandoc -> Pandoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Inline] -> [Inline]) -> Pandoc -> Pandoc
forall a b. (Data a, Data b) => (a -> a) -> b -> b
bottomUp [Inline] -> [Inline]
formatInlineTex
  where formatInlineTex :: [Inline] -> [Inline]
        formatInlineTex :: [Inline] -> [Inline]
formatInlineTex (Math InlineMath tex :: Text
tex : is :: [Inline]
is)
          = (Format -> Text -> Inline
RawInline (Text -> Format
Format "html") (Text -> Text -> Text -> Text
bracket "$" "$" Text
tex)) Inline -> [Inline] -> [Inline]
forall a. a -> [a] -> [a]
: [Inline]
is
        formatInlineTex is :: [Inline]
is = [Inline]
is

        formatDisplayTex :: [Block] -> [Block]
        formatDisplayTex :: [Block] -> [Block]
formatDisplayTex (Para [Math DisplayMath tex :: Text
tex] : bs :: [Block]
bs)
          = Format -> Text -> Block
RawBlock (Text -> Format
Format "html") (Text -> Text -> Text -> Text
bracket "\n\\[" "\\]\n" Text
tex)
          Block -> [Block] -> [Block]
forall a. a -> [a] -> [a]
: [Block]
bs
        formatDisplayTex bs :: [Block]
bs = [Block]
bs

-- | WordPress can render LaTeX, but expects it in a special non-standard
--   format (@\$latex foo\$@).  The @wpTeXify@ function formats LaTeX code
--   using this format so that it can be processed by WordPress.
wpTeXify :: Pandoc -> Pandoc
wpTeXify :: Pandoc -> Pandoc
wpTeXify = ([Block] -> [Block]) -> Pandoc -> Pandoc
forall a b. (Data a, Data b) => (a -> a) -> b -> b
bottomUp [Block] -> [Block]
formatDisplayTex (Pandoc -> Pandoc) -> (Pandoc -> Pandoc) -> Pandoc -> Pandoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Inline] -> [Inline]) -> Pandoc -> Pandoc
forall a b. (Data a, Data b) => (a -> a) -> b -> b
bottomUp [Inline] -> [Inline]
formatInlineTex
  where formatInlineTex :: [Inline] -> [Inline]
        formatInlineTex :: [Inline] -> [Inline]
formatInlineTex (Math InlineMath tex :: Text
tex : is :: [Inline]
is)
          = (Text -> Inline
Str (Text -> Inline) -> Text -> Inline
forall a b. (a -> b) -> a -> b
$ Text -> Text -> Text -> Text
bracket "$latex " "$" (Text -> Text -> Text
unPrefix "latex" Text
tex)) Inline -> [Inline] -> [Inline]
forall a. a -> [a] -> [a]
: [Inline]
is
        formatInlineTex is :: [Inline]
is = [Inline]
is

        formatDisplayTex :: [Block] -> [Block]
        formatDisplayTex :: [Block] -> [Block]
formatDisplayTex (Para [Math DisplayMath tex :: Text
tex] : bs :: [Block]
bs)
          = Format -> Text -> Block
RawBlock (Text -> Format
Format "html") "<p><div style=\"text-align: center\">"
          Block -> [Block] -> [Block]
forall a. a -> [a] -> [a]
: [Inline] -> Block
Plain [Text -> Inline
Str (Text -> Inline) -> Text -> Inline
forall a b. (a -> b) -> a -> b
$ Text -> Text -> Text -> Text
bracket "$latex \\displaystyle " "$" (Text -> Text -> Text
unPrefix "latex" Text
tex)]
          Block -> [Block] -> [Block]
forall a. a -> [a] -> [a]
: Format -> Text -> Block
RawBlock (Text -> Format
Format "html") "</div></p>"
          Block -> [Block] -> [Block]
forall a. a -> [a] -> [a]
: [Block]
bs
        formatDisplayTex bs :: [Block]
bs = [Block]
bs

        unPrefix :: Text -> Text -> Text
unPrefix pre :: Text
pre s :: Text
s
          | Text
pre Text -> Text -> Bool
`T.isPrefixOf` Text
s = Int -> Text -> Text
T.drop (Text -> Int
T.length Text
pre) Text
s
          | Bool
otherwise            = Text
s