summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGregor Kleen <gkleen@yggdrasil.li>2015-11-07 19:24:34 +0000
committerGregor Kleen <gkleen@yggdrasil.li>2015-11-07 19:24:34 +0000
commitbb296bb319a1d9a0050577dfed96e30298390db7 (patch)
tree44b60ff682669c718e7431aef39f0fcbd1bd3b90 /src
parenta1068fbdeea74a12e4f33069cf091302f87e8d17 (diff)
downloaddirty-haskell.org-bb296bb319a1d9a0050577dfed96e30298390db7.tar
dirty-haskell.org-bb296bb319a1d9a0050577dfed96e30298390db7.tar.gz
dirty-haskell.org-bb296bb319a1d9a0050577dfed96e30298390db7.tar.bz2
dirty-haskell.org-bb296bb319a1d9a0050577dfed96e30298390db7.tar.xz
dirty-haskell.org-bb296bb319a1d9a0050577dfed96e30298390db7.zip
Working math support
Diffstat (limited to 'src')
-rw-r--r--src/Math.hs63
-rw-r--r--src/Site.hs53
2 files changed, 80 insertions, 36 deletions
diff --git a/src/Math.hs b/src/Math.hs
index e927fdd..db01f75 100644
--- a/src/Math.hs
+++ b/src/Math.hs
@@ -2,40 +2,61 @@ module Math
2 ( compileMath 2 ( compileMath
3 ) where 3 ) where
4 4
5import System.IO (stdout, stderr, hPutStrLn, writeFile, readFile)
5import System.IO.Temp (withSystemTempDirectory) 6import System.IO.Temp (withSystemTempDirectory)
6import System.Process (callProcess) 7import System.Process (callProcess, readProcessWithExitCode)
7import System.Directory (copyFile, getCurrentDirectory, setCurrentDirectory) 8import System.Directory (copyFile, getCurrentDirectory, setCurrentDirectory)
8import System.FilePath (takeFileName, FilePath(..), (</>)) 9import System.FilePath (takeFileName, FilePath(..), (</>))
10import System.Exit (ExitCode(..))
9 11
10import Control.Monad 12import Control.Monad (when)
11import Control.Exception (bracket) 13import Control.Exception (bracket, throwIO)
14import Data.Maybe (fromMaybe, listToMaybe)
15
16import Control.Monad.Writer.Strict (WriterT(..), execWriterT, tell)
17import Control.Monad.Trans (liftIO)
12 18
13import Control.DeepSeq (($!!)) 19import Control.DeepSeq (($!!))
14 20
15compileMath :: String -> IO String 21import Text.Regex.TDFA ((=~))
22
23instance Monoid ExitCode where
24 mempty = ExitSuccess
25 (ExitFailure a) `mappend` _ = ExitFailure a
26 ExitSuccess `mappend` x@(ExitFailure _) = x
27 ExitSuccess `mappend` ExitSuccess = ExitSuccess
28
29
30compileMath :: String -> IO (String, String)
16compileMath = withSystemTempDirectory "math" . compileMath' 31compileMath = withSystemTempDirectory "math" . compileMath'
17 32
18compileMath' :: String -> FilePath -> IO String 33compileMath' :: String -> FilePath -> IO (String, String)
19compileMath' input tmpDir = do 34compileMath' input tmpDir = do
20 mapM_ (copyToTmp . ("tex" </>)) [ "preamble.tex" 35 mapM_ (copyToTmp . ("tex" </>)) [ "preamble.tex"
21 , "preview.dtx" 36 , "preview.dtx"
22 , "preview.ins" 37 , "preview.ins"
23 ] 38 ]
24 withCurrentDirectory tmpDir $ do 39 (exitCode, out, err) <- withCurrentDirectory tmpDir $ execWriterT $ do
25 callProcess "latex" [ "-interaction=batchmode" 40 run "latex" [ "-interaction=batchmode"
26 , "preview.ins" 41 , "preview.ins"
27 ] 42 ] ""
28 writeFile (tmpDir </> "image.tex") input 43 liftIO $ writeFile (tmpDir </> "image.tex") input
29 callProcess "latex" [ "-interaction=batchmode" 44 run "latex" [ "-interaction=batchmode"
30 , "image.tex" 45 , "image.tex"
31 ] 46 ] ""
32 callProcess "dvisvgm" [ "--exact" 47 run "dvisvgm" [ "--exact"
33 , "--no-fonts" 48 , "--no-fonts"
34 , tmpDir </> "image.dvi" 49 , tmpDir </> "image.dvi"
35 ] 50 ] ""
36 (\x -> return $!! x) =<< (readFile $ tmpDir </> "image.svg") 51 when (exitCode /= ExitSuccess) $ do
52 hPutStrLn stdout out
53 hPutStrLn stderr err
54 throwIO exitCode
55 (\x -> return $!! (x, extractAlignment err)) =<< (readFile $ tmpDir </> "image.svg")
37 where 56 where
38 copyToTmp fp = copyFile fp (tmpDir </> takeFileName fp) 57 copyToTmp fp = copyFile fp (tmpDir </> takeFileName fp)
58 run :: String -> [String] -> String -> WriterT (ExitCode, String, String) IO ()
59 run bin args stdin = tell =<< liftIO (readProcessWithExitCode bin args stdin)
39 60
40withCurrentDirectory :: FilePath -- ^ Directory to execute in 61withCurrentDirectory :: FilePath -- ^ Directory to execute in
41 -> IO a -- ^ Action to be executed 62 -> IO a -- ^ Action to be executed
@@ -44,3 +65,9 @@ withCurrentDirectory dir action =
44 bracket getCurrentDirectory setCurrentDirectory $ \ _ -> do 65 bracket getCurrentDirectory setCurrentDirectory $ \ _ -> do
45 setCurrentDirectory dir 66 setCurrentDirectory dir
46 action 67 action
68
69extractAlignment :: String -> String
70extractAlignment = fromMaybe "0pt" . extract . (=~ "depth=([^\\s]+)")
71 where
72 extract :: (String, String, String, [String]) -> Maybe String
73 extract (_, _, _, xs) = listToMaybe xs
diff --git a/src/Site.hs b/src/Site.hs
index e821322..dcb9a7d 100644
--- a/src/Site.hs
+++ b/src/Site.hs
@@ -13,18 +13,19 @@ import Data.List (take, reverse, nub, groupBy, concatMap)
13import Data.Function (on) 13import Data.Function (on)
14import Data.Default 14import Data.Default
15import Text.Pandoc 15import Text.Pandoc
16import Text.Pandoc.Walk (query) 16import Text.Pandoc.Walk (query, walkM)
17import Text.Pandoc.Error 17import Text.Pandoc.Error
18import Control.Applicative (Alternative(..), Applicative(..)) 18import Control.Applicative (Alternative(..), Applicative(..))
19 19
20import System.FilePath (takeBaseName, (</>), (<.>))
21
20import qualified Crypto.Hash.SHA256 as SHA256 (hash) 22import qualified Crypto.Hash.SHA256 as SHA256 (hash)
21import qualified Data.ByteString.Char8 as CBS 23import qualified Data.ByteString.Char8 as CBS
22import Data.Hex 24import Data.Hex (hex)
23import Data.Char (toLower) 25import Data.Char (toLower)
24 26
25import System.FilePath (takeBaseName, (</>), (<.>))
26
27import Math (compileMath) 27import Math (compileMath)
28import Text.Printf (printf)
28 29
29main :: IO () 30main :: IO ()
30main = hakyllWith config $ do 31main = hakyllWith config $ do
@@ -34,24 +35,24 @@ main = hakyllWith config $ do
34 route idRoute 35 route idRoute
35 compile copyFileCompiler 36 compile copyFileCompiler
36 37
38 math <- getMath "posts/*" mathTranslation'
39 forM_ math $ \(_, mathStr) -> create [mathTranslation' mathStr] $ do
40 route idRoute
41 compile $ do
42 item <- makeItem mathStr
43 >>= loadAndApplyTemplate "templates/math.tex" defaultContext
44 >>= withItemBody (unsafeCompiler . compileMath)
45 saveSnapshot "alignment" $ fmap snd item
46 return $ fmap fst item
47
37 match "posts/*" $ do 48 match "posts/*" $ do
38 route $ setExtension ".html" 49 route $ setExtension ".html"
39 compile $ do 50 compile $ do
40 getResourceBody >>= saveSnapshot "content" 51 getResourceBody >>= saveSnapshot "content"
41 pandocCompiler 52 pandocCompilerWithTransformM defaultHakyllReaderOptions defaultHakyllWriterOptions mathTransform
42 >>= loadAndApplyTemplate "templates/default.html" defaultContext 53 >>= loadAndApplyTemplate "templates/default.html" defaultContext
43 >>= relativizeUrls 54 >>= relativizeUrls
44 55
45 math <- getMath "posts/*" mathTranslation'
46 forM_ math $ \(deps, mathStr) ->
47 rulesExtraDependencies (map IdentifierDependency deps) $
48 create [mathTranslation' mathStr] $ do
49 route idRoute
50 compile $ do
51 makeItem mathStr
52 >>= loadAndApplyTemplate "templates/math.tex" defaultContext
53 >>= withItemBody (unsafeCompiler . compileMath)
54
55 tags <- buildTags "posts/*" tagTranslation' >>= addTag "All Posts" "posts/*" 56 tags <- buildTags "posts/*" tagTranslation' >>= addTag "All Posts" "posts/*"
56 57
57 tagsRules tags $ \tag pattern -> do 58 tagsRules tags $ \tag pattern -> do
@@ -143,14 +144,14 @@ tagTranslation = mapMaybe charTrans
143 | isAlphaNum c = Just $ toLower c 144 | isAlphaNum c = Just $ toLower c
144 | otherwise = Nothing 145 | otherwise = Nothing
145 146
146mathTranslation' :: String -> Identifier
147mathTranslation' = fromCapture "math/*.svg" . map toLower . CBS.unpack . hex . SHA256.hash . CBS.pack
148
149addTag :: MonadMetadata m => String -> Pattern -> Tags -> m Tags 147addTag :: MonadMetadata m => String -> Pattern -> Tags -> m Tags
150addTag name pattern tags = do 148addTag name pattern tags = do
151 ids <- getMatches pattern 149 ids <- getMatches pattern
152 return $ tags { tagsMap = tagsMap tags ++ [(name, ids)] } 150 return $ tags { tagsMap = tagsMap tags ++ [(name, ids)] }
153 151
152mathTranslation' :: String -> Identifier
153mathTranslation' = fromCapture "math/*.svg" . map toLower . CBS.unpack . hex . SHA256.hash . CBS.pack
154
154getMath :: Pattern -> (String -> Identifier) -> Rules [([Identifier], String)] 155getMath :: Pattern -> (String -> Identifier) -> Rules [([Identifier], String)]
155getMath pattern makeId = do 156getMath pattern makeId = do
156 ids <- getMatches pattern 157 ids <- getMatches pattern
@@ -193,6 +194,22 @@ readPandoc' path = readFile path >>= either fail return . result'
193 194
194 addExt ro e = ro {readerExtensions = Set.insert e $ readerExtensions ro} 195 addExt ro e = ro {readerExtensions = Set.insert e $ readerExtensions ro}
195 196
197mathTransform :: Pandoc -> Compiler Pandoc
198mathTransform = walkM mathTransform'
199 where
200 mathTransform' :: Inline -> Compiler Inline
201 mathTransform' (Math mathType tex) = do
202 alignment <- loadSnapshotBody texId "alignment"
203 let
204 html = printf "<object data=\"/%s\" type=\"image/svg+xml\" style=\"vertical-align:-%s\">%s</object>"
205 (toFilePath texId) (alignment :: String) tex
206 return $ Span ("", [classOf mathType], []) [RawInline (Format "html") html]
207 where
208 texId = mathTranslation' tex
209 classOf DisplayMath = "display-math"
210 classOf InlineMath = "inline-math"
211 mathTransform' x = return x
212
196toFilePath' :: Identifier -> FilePath 213toFilePath' :: Identifier -> FilePath
197toFilePath' = (providerDirectory config </>) . toFilePath 214toFilePath' = (providerDirectory config </>) . toFilePath
198 215