even more
This commit is contained in:
		
							parent
							
								
									903a308167
								
							
						
					
					
						commit
						3d34bd4a40
					
				
							
								
								
									
										121
									
								
								site.hs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								site.hs
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,121 @@
 | 
				
			||||||
 | 
					{-# LANGUAGE TemplateHaskell #-}
 | 
				
			||||||
 | 
					{-# LANGUAGE OverloadedStrings #-}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import Control.Monad (unless, when)
 | 
				
			||||||
 | 
					import Control.Monad.IO.Class
 | 
				
			||||||
 | 
					import Control.Monad.Trans.State.Lazy
 | 
				
			||||||
 | 
					import Data.Default (def)
 | 
				
			||||||
 | 
					import Data.Foldable (traverse_)
 | 
				
			||||||
 | 
					import Data.List.Extra (stripSuffix)
 | 
				
			||||||
 | 
					import qualified Data.Map as M
 | 
				
			||||||
 | 
					import Data.Maybe (isJust)
 | 
				
			||||||
 | 
					import qualified Data.Text as T
 | 
				
			||||||
 | 
					import qualified Data.Text.Encoding
 | 
				
			||||||
 | 
					import qualified Data.Text.IO as TIO
 | 
				
			||||||
 | 
					import qualified Data.Yaml as Y
 | 
				
			||||||
 | 
					import Hakyll.Core.Util.File (getRecursiveContents, makeDirectories)
 | 
				
			||||||
 | 
					import Lens.Micro
 | 
				
			||||||
 | 
					import Lens.Micro.Aeson
 | 
				
			||||||
 | 
					import Lens.Micro.Mtl
 | 
				
			||||||
 | 
					import Lens.Micro.TH
 | 
				
			||||||
 | 
					import System.Environment (getArgs)
 | 
				
			||||||
 | 
					import System.FilePath ((</>), splitPath)
 | 
				
			||||||
 | 
					import Text.Pandoc.Class (runIOorExplode)
 | 
				
			||||||
 | 
					import qualified Text.Pandoc.Definition
 | 
				
			||||||
 | 
					import qualified Text.Pandoc.Extensions
 | 
				
			||||||
 | 
					import Text.Pandoc.Options (ReaderOptions(..))
 | 
				
			||||||
 | 
					import Text.Pandoc.Readers.Markdown (readMarkdown)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import Debug.Trace
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					io :: MonadIO m => IO a -> m a
 | 
				
			||||||
 | 
					io = liftIO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					just _ (Just val) = val
 | 
				
			||||||
 | 
					just err Nothing = error ("Missing: " ++ err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					data SiteState =
 | 
				
			||||||
 | 
					  SiteState
 | 
				
			||||||
 | 
					    { _pages :: M.Map FilePath ( FilePath
 | 
				
			||||||
 | 
					                               , Y.Value
 | 
				
			||||||
 | 
					                               , Text.Pandoc.Definition.Pandoc -- loc -> (source, meta, markdown)
 | 
				
			||||||
 | 
					                                )
 | 
				
			||||||
 | 
					    , _redirects :: M.Map FilePath FilePath -- from -> to
 | 
				
			||||||
 | 
					    , _htags :: M.Map [String] [FilePath] -- tag sequence -> tagged locs
 | 
				
			||||||
 | 
					    , _installs :: M.Map FilePath FilePath -- file hash -> install location
 | 
				
			||||||
 | 
					    , _templates :: M.Map FilePath () -- TODO mustache templates
 | 
				
			||||||
 | 
					    , _outputDir :: FilePath
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  deriving (Show)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					makeLenses ''SiteState
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					emptySiteState out =
 | 
				
			||||||
 | 
					  SiteState
 | 
				
			||||||
 | 
					    { _pages = M.empty
 | 
				
			||||||
 | 
					    , _redirects = M.empty
 | 
				
			||||||
 | 
					    , _htags = M.empty
 | 
				
			||||||
 | 
					    , _installs = M.empty
 | 
				
			||||||
 | 
					    , _templates = M.empty
 | 
				
			||||||
 | 
					    , _outputDir = out
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Site a = StateT SiteState IO a
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					hasSuffix s = isJust . stripSuffix s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sourcePages :: FilePath -> Site ()
 | 
				
			||||||
 | 
					sourcePages fp = do
 | 
				
			||||||
 | 
					  links <-
 | 
				
			||||||
 | 
					    io $ filter (hasSuffix ".md" . last . splitPath) <$>
 | 
				
			||||||
 | 
					    getRecursiveContents (pure . const False) fp
 | 
				
			||||||
 | 
					  traverse_ loadPage (map (fp </>) links)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					markdownReadOpts =
 | 
				
			||||||
 | 
					  def
 | 
				
			||||||
 | 
					    { readerExtensions =
 | 
				
			||||||
 | 
					        Text.Pandoc.Extensions.enableExtension
 | 
				
			||||||
 | 
					          Text.Pandoc.Extensions.Ext_smart
 | 
				
			||||||
 | 
					          Text.Pandoc.Extensions.pandocExtensions
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					loadPage :: FilePath -> Site ()
 | 
				
			||||||
 | 
					loadPage fp = do
 | 
				
			||||||
 | 
					  txt <- io $ TIO.readFile fp
 | 
				
			||||||
 | 
					  (T.take 4 txt == "---\n") `unless`
 | 
				
			||||||
 | 
					    error ("metadata block start missing in " ++ fp)
 | 
				
			||||||
 | 
					  let (meta, markdown) = T.breakOn "\n---\n" (T.drop 4 txt)
 | 
				
			||||||
 | 
					  T.null meta `when` error ("metadata block bad in " ++ fp)
 | 
				
			||||||
 | 
					  yml <- Y.decodeThrow $ Data.Text.Encoding.encodeUtf8 meta
 | 
				
			||||||
 | 
					  md <- io $ runIOorExplode $ readMarkdown markdownReadOpts (T.drop 5 markdown)
 | 
				
			||||||
 | 
					  let mount =
 | 
				
			||||||
 | 
					        T.unpack . just ("mount point of " ++ fp) $ yml ^? key "title" . _String
 | 
				
			||||||
 | 
					  pages %= M.insert mount (fp, yml, md)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sourceTemplates :: FilePath -> Site ()
 | 
				
			||||||
 | 
					sourceTemplates _ = pure ()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					installPage :: FilePath -> Site ()
 | 
				
			||||||
 | 
					installPage = undefined
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					installFile :: FilePath -> Site FilePath
 | 
				
			||||||
 | 
					installFile = undefined
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					makeRedirect :: FilePath -> FilePath -> Site ()
 | 
				
			||||||
 | 
					makeRedirect = undefined
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					makeRedirects :: Site ()
 | 
				
			||||||
 | 
					makeRedirects = undefined
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					renderTag :: [String] -> Site ()
 | 
				
			||||||
 | 
					renderTag = undefined
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					renderTags :: Site ()
 | 
				
			||||||
 | 
					renderTags = undefined
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					main = do
 | 
				
			||||||
 | 
					  [targetDir] <- getArgs
 | 
				
			||||||
 | 
					  flip runStateT (emptySiteState targetDir) $ do
 | 
				
			||||||
 | 
					    traverse sourceTemplates ["templates"]
 | 
				
			||||||
 | 
					    traverse sourcePages ["external"]
 | 
				
			||||||
 | 
					    get >>= io . print
 | 
				
			||||||
		Loading…
	
		Reference in a new issue