use Mustache objects for rendering, allow lambdas and manual URL rooting
This commit is contained in:
		
							parent
							
								
									a50cb2eae6
								
							
						
					
					
						commit
						d4e1fdeaeb
					
				
							
								
								
									
										50
									
								
								reploy.hs
									
									
									
									
									
								
							
							
						
						
									
										50
									
								
								reploy.hs
									
									
									
									
									
								
							| 
						 | 
					@ -54,6 +54,7 @@ import System.FilePath
 | 
				
			||||||
  , takeFileName
 | 
					  , takeFileName
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
import qualified Text.Mustache as Mu
 | 
					import qualified Text.Mustache as Mu
 | 
				
			||||||
 | 
					import qualified Text.Mustache.Types as MT
 | 
				
			||||||
import Text.Pandoc.Class (runIOorExplode)
 | 
					import Text.Pandoc.Class (runIOorExplode)
 | 
				
			||||||
import qualified Text.Pandoc.Definition
 | 
					import qualified Text.Pandoc.Definition
 | 
				
			||||||
import Text.Pandoc.Readers.Markdown (readMarkdown)
 | 
					import Text.Pandoc.Readers.Markdown (readMarkdown)
 | 
				
			||||||
| 
						 | 
					@ -157,14 +158,21 @@ checkTarget fp = do
 | 
				
			||||||
    else targets %= S.insert fp
 | 
					    else targets %= S.insert fp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- | Prepend the root path to the given link
 | 
					-- | Prepend the root path to the given link
 | 
				
			||||||
rootUrl :: FilePath -> Site FilePath
 | 
					rootUrl' :: FilePath -> FilePath -> FilePath
 | 
				
			||||||
rootUrl fp = (</> unAbsolute fp) <$> use urlBase
 | 
					rootUrl' root = (root </>) . unAbsolute
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- | Like `rootUrl` but also appends @index.html@ for systems that don't have
 | 
					-- | Same as `rootUrl'` but conveniently in the monad
 | 
				
			||||||
 | 
					rootUrl :: FilePath -> Site FilePath
 | 
				
			||||||
 | 
					rootUrl fp = flip rootUrl' fp <$> use urlBase
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- | Like `rootUrl'` but also appends @index.html@ for systems that don't have
 | 
				
			||||||
-- working directory indexes.
 | 
					-- working directory indexes.
 | 
				
			||||||
 | 
					rootPageUrl' :: FilePath -> Bool -> FilePath -> FilePath
 | 
				
			||||||
 | 
					rootPageUrl' root index fp = bool id (</> "index.html") index $ rootUrl' root fp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- | Convenient version of `rootPageUrl'`
 | 
				
			||||||
rootPageUrl :: FilePath -> Site FilePath
 | 
					rootPageUrl :: FilePath -> Site FilePath
 | 
				
			||||||
rootPageUrl fp =
 | 
					rootPageUrl fp = rootPageUrl' <$> use urlBase <*> use appendUrlIndex <*> pure fp
 | 
				
			||||||
  bool id (</> "index.html") <$> use appendUrlIndex <*> rootUrl fp
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- | Process a single link pointing out from a page.
 | 
					-- | Process a single link pointing out from a page.
 | 
				
			||||||
processLink :: FilePath -> FilePath -> Site String
 | 
					processLink :: FilePath -> FilePath -> Site String
 | 
				
			||||||
| 
						 | 
					@ -182,7 +190,7 @@ pageFilename :: FilePath -> Site FilePath
 | 
				
			||||||
pageFilename = indexFilename
 | 
					pageFilename = indexFilename
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- | Like `Mu.substitute` but writes (and eventually should throw) stuff on errors
 | 
					-- | Like `Mu.substitute` but writes (and eventually should throw) stuff on errors
 | 
				
			||||||
checkedSubstitute :: Mu.Template -> Y.Value -> IO T.Text
 | 
					checkedSubstitute :: Mu.Template -> MT.Value -> IO T.Text
 | 
				
			||||||
checkedSubstitute t v = do
 | 
					checkedSubstitute t v = do
 | 
				
			||||||
  let (es, txt) = Mu.checkedSubstitute t v
 | 
					  let (es, txt) = Mu.checkedSubstitute t v
 | 
				
			||||||
  traverse_ (putStrLn . ("Error: " ++) . show) es
 | 
					  traverse_ (putStrLn . ("Error: " ++) . show) es
 | 
				
			||||||
| 
						 | 
					@ -190,10 +198,16 @@ checkedSubstitute t v = do
 | 
				
			||||||
  pure txt
 | 
					  pure txt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- | Add global information to page metadata for rendering (at this point just the url base)
 | 
					-- | Add global information to page metadata for rendering (at this point just the url base)
 | 
				
			||||||
addGlobalMeta :: Y.Value -> Site Y.Value
 | 
					addGlobalMeta :: Y.Value -> Site MT.Value
 | 
				
			||||||
addGlobalMeta (Y.Object m) = do
 | 
					addGlobalMeta (Y.Object m) = do
 | 
				
			||||||
  r <- fromString <$> use urlBase
 | 
					  r <- use urlBase
 | 
				
			||||||
  pure . Y.Object $ KM.insert "root" r m
 | 
					  i <- use appendUrlIndex
 | 
				
			||||||
 | 
					  let l = map (\(k, v) -> (K.toText k, Mu.toMustache v)) $ KM.toList m
 | 
				
			||||||
 | 
					  pure . Mu.object $ l ++
 | 
				
			||||||
 | 
					    [ ("root", Mu.toMustache $ T.pack r)
 | 
				
			||||||
 | 
					    , ("rawRootUrl", Mu.overText $ T.pack . rootUrl' r . T.unpack)
 | 
				
			||||||
 | 
					    , ("pageLink", Mu.overText $ T.pack . rootPageUrl' r i . T.unpack)
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- | Get the expected timestamp file for a given filepath
 | 
					-- | Get the expected timestamp file for a given filepath
 | 
				
			||||||
timestampFile :: FilePath -> Site FilePath
 | 
					timestampFile :: FilePath -> Site FilePath
 | 
				
			||||||
| 
						 | 
					@ -257,7 +271,7 @@ installPage mount pi = do
 | 
				
			||||||
    addHeadingLinks "header-local-anchor" fixedUrlDoc
 | 
					    addHeadingLinks "header-local-anchor" fixedUrlDoc
 | 
				
			||||||
  let Y.Object meta' = pi ^. pageMeta
 | 
					  let Y.Object meta' = pi ^. pageMeta
 | 
				
			||||||
      meta = Y.Object $ KM.insert "body" (Y.String body) meta'
 | 
					      meta = Y.Object $ KM.insert "body" (Y.String body) meta'
 | 
				
			||||||
  meta <- addGlobalMeta meta >>= addTOC pi fixedUrlDoc >>= addPageMeta pi
 | 
					  meta <- addTOC pi fixedUrlDoc meta >>= addPageMeta pi >>= addGlobalMeta
 | 
				
			||||||
  io $ do
 | 
					  io $ do
 | 
				
			||||||
    putStrLn $ "P -> " ++ file
 | 
					    putStrLn $ "P -> " ++ file
 | 
				
			||||||
    makeDirectories file
 | 
					    makeDirectories file
 | 
				
			||||||
| 
						 | 
					@ -275,7 +289,8 @@ installRedirect target from = do
 | 
				
			||||||
    putStrLn $ "@ -> " ++ file ++ " -> " ++ target
 | 
					    putStrLn $ "@ -> " ++ file ++ " -> " ++ target
 | 
				
			||||||
    makeDirectories file
 | 
					    makeDirectories file
 | 
				
			||||||
    txt <-
 | 
					    txt <-
 | 
				
			||||||
      checkedSubstitute templ $ Y.object [("target", Y.String $ T.pack target)]
 | 
					      checkedSubstitute templ $
 | 
				
			||||||
 | 
					      Mu.object [("target", Mu.toMustache $ T.pack target)]
 | 
				
			||||||
    TIO.writeFile file txt
 | 
					    TIO.writeFile file txt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- | Install all redirects required by one page.
 | 
					-- | Install all redirects required by one page.
 | 
				
			||||||
| 
						 | 
					@ -435,20 +450,20 @@ makePageLinkMeta mount = do
 | 
				
			||||||
  pure $ Y.object [("href", fromString link), ("meta", meta)]
 | 
					  pure $ Y.object [("href", fromString link), ("meta", meta)]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- | Create the complete metadata structure for the template that renders a given categorical tag pages
 | 
					-- | Create the complete metadata structure for the template that renders a given categorical tag pages
 | 
				
			||||||
makeTagMeta :: [String] -> Site Y.Value
 | 
					makeTagMeta' :: [String] -> Site Y.Value
 | 
				
			||||||
makeTagMeta tag = do
 | 
					makeTagMeta' tag = do
 | 
				
			||||||
  taggedPages <- use $ htags . to (M.!? tag) . to (maybe [] id)
 | 
					  taggedPages <- use $ htags . to (M.!? tag) . to (maybe [] id)
 | 
				
			||||||
  subtags <-
 | 
					  subtags <-
 | 
				
			||||||
    gets
 | 
					    gets
 | 
				
			||||||
      (^.. ehtags . to M.keys . each . filtered (not . null) .
 | 
					      (^.. ehtags . to M.keys . each . filtered (not . null) .
 | 
				
			||||||
           filtered ((== tag) . init))
 | 
					           filtered ((== tag) . init))
 | 
				
			||||||
  htagMeta <- makeHTagMeta tagLink tag
 | 
					  htagMeta <- makeHTagMeta tagLink tag
 | 
				
			||||||
  subtagsMeta <- Y.array <$> traverse makeTagMeta subtags
 | 
					  subtagsMeta <- Y.array <$> traverse makeTagMeta' subtags
 | 
				
			||||||
  pagesMeta <- Y.array <$> traverse makePageLinkMeta taggedPages
 | 
					  pagesMeta <- Y.array <$> traverse makePageLinkMeta taggedPages
 | 
				
			||||||
  link <- tagLink tag
 | 
					  link <- tagLink tag
 | 
				
			||||||
  listlink <- listLink tag
 | 
					  listlink <- listLink tag
 | 
				
			||||||
  tags <- Y.array . map fromString <$> traverse getTagName tag
 | 
					  tags <- Y.array . map fromString <$> traverse getTagName tag
 | 
				
			||||||
  addGlobalMeta $
 | 
					  pure $
 | 
				
			||||||
    Y.object
 | 
					    Y.object
 | 
				
			||||||
      [ ("href", fromString link)
 | 
					      [ ("href", fromString link)
 | 
				
			||||||
      , ("tags", tags)
 | 
					      , ("tags", tags)
 | 
				
			||||||
| 
						 | 
					@ -458,6 +473,9 @@ makeTagMeta tag = do
 | 
				
			||||||
      , ("listhref", fromString listlink)
 | 
					      , ("listhref", fromString listlink)
 | 
				
			||||||
      ]
 | 
					      ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					makeTagMeta :: [String] -> Site MT.Value
 | 
				
			||||||
 | 
					makeTagMeta tag = makeTagMeta' tag >>= addGlobalMeta
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- | Make metadata for printing out a single tag as-is, without levels
 | 
					-- | Make metadata for printing out a single tag as-is, without levels
 | 
				
			||||||
makeHTagLinkMeta :: [String] -> Site Y.Value
 | 
					makeHTagLinkMeta :: [String] -> Site Y.Value
 | 
				
			||||||
makeHTagLinkMeta tag = do
 | 
					makeHTagLinkMeta tag = do
 | 
				
			||||||
| 
						 | 
					@ -466,7 +484,7 @@ makeHTagLinkMeta tag = do
 | 
				
			||||||
  pure $ Y.object [("href", fromString link), ("tags", tags)]
 | 
					  pure $ Y.object [("href", fromString link), ("tags", tags)]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- | Create the structure for rendering a complete listing of one hierarchical tag.
 | 
					-- | Create the structure for rendering a complete listing of one hierarchical tag.
 | 
				
			||||||
makeListMeta :: [String] -> Site Y.Value
 | 
					makeListMeta :: [String] -> Site MT.Value
 | 
				
			||||||
makeListMeta tag = do
 | 
					makeListMeta tag = do
 | 
				
			||||||
  taggedPages <- use $ ehtags . to (M.! tag)
 | 
					  taggedPages <- use $ ehtags . to (M.! tag)
 | 
				
			||||||
  subtags <-
 | 
					  subtags <-
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,9 +1,16 @@
 | 
				
			||||||
<header>
 | 
					<header>
 | 
				
			||||||
 | 
					  Navigation:
 | 
				
			||||||
 | 
					  <ul>
 | 
				
			||||||
 | 
					    <li><a href="{{#pageLink}}/tag{{/pageLink}}">Tags</a></li>
 | 
				
			||||||
 | 
					    <li><a href="{{#pageLink}}/list{{/pageLink}}">List</a></li>
 | 
				
			||||||
 | 
					    <li><a href="{{#pageLink}}/search{{/pageLink}}">Search</a></li>
 | 
				
			||||||
 | 
					  </ul>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  {{?htags}}
 | 
					  {{?htags}}
 | 
				
			||||||
  Categories:
 | 
					  Categories:
 | 
				
			||||||
  <ul>
 | 
					  <ul>
 | 
				
			||||||
    {{#htags}}
 | 
					    {{#htags}}
 | 
				
			||||||
    <li class="sidebox-tag">{{#.}}<a href="{{href}}">{{^tag}}all{{/tag}}{{?tag}} » {{tag}}{{/tag}}{{/.}}</a></li>
 | 
					    <li>{{#.}}<a href="{{href}}">{{^tag}}all{{/tag}}{{?tag}} » {{tag}}{{/tag}}{{/.}}</a></li>
 | 
				
			||||||
    {{/htags}}
 | 
					    {{/htags}}
 | 
				
			||||||
  </ul>
 | 
					  </ul>
 | 
				
			||||||
  {{/htags}}
 | 
					  {{/htags}}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue