Dynamic route and handler creation for Markdown posts
This commit is contained in:
parent
81e01e242c
commit
7f97da838f
@ -19,6 +19,8 @@ executable sampu
|
|||||||
, commonmark >= 0.2.4
|
, commonmark >= 0.2.4
|
||||||
, directory >= 1.3.7.0
|
, directory >= 1.3.7.0
|
||||||
, dotenv >= 0.11.0.0
|
, dotenv >= 0.11.0.0
|
||||||
|
, filemanip >= 0.3.6.1
|
||||||
|
, filepath >= 1.4.2.2
|
||||||
, lucid >= 2.11.0
|
, lucid >= 2.11.0
|
||||||
, text >= 2.0
|
, text >= 2.0
|
||||||
, twain >= 2.1.0.0
|
, twain >= 2.1.0.0
|
||||||
|
@ -1,20 +1,30 @@
|
|||||||
module Core.HTTP where
|
module Core.HTTP where
|
||||||
|
|
||||||
import qualified Core.Configuration as Conf
|
import qualified Core.Configuration as Conf
|
||||||
import qualified Core.Handlers as Handle
|
import qualified Core.Handlers as Handle
|
||||||
|
|
||||||
import Network.Wai.Handler.Warp (Port, run)
|
import Control.Monad ( mapM_ )
|
||||||
import Network.Wai.Middleware.RequestLogger (logStdoutDev)
|
import Data.String ( fromString )
|
||||||
import Network.Wai.Middleware.Static
|
import Network.Wai.Handler.Warp ( Port, run )
|
||||||
|
import Network.Wai.Middleware.RequestLogger ( logStdoutDev )
|
||||||
|
import Network.Wai.Middleware.Static
|
||||||
|
import System.FilePath ( takeFileName )
|
||||||
|
|
||||||
import Web.Twain
|
|
||||||
|
import Web.Twain
|
||||||
|
|
||||||
-- Get the port to listen on from the ENV and start the webserver
|
-- Get the port to listen on from the ENV and start the webserver
|
||||||
main :: IO ()
|
main :: [FilePath] -> IO ()
|
||||||
main = do
|
main mdFiles = do
|
||||||
port <- Conf.appPort
|
port <- Conf.appPort
|
||||||
run (read port :: Int) $
|
run (read port :: Int) $
|
||||||
foldr ($) (notFound Handle.missing) app
|
foldr ($) (notFound Handle.missing) (app mdFiles)
|
||||||
|
where
|
||||||
|
app mdFiles = preProcessors
|
||||||
|
++ routes
|
||||||
|
++ (map mdFileToRoute mdFiles)
|
||||||
|
++ postProcessors
|
||||||
|
|
||||||
|
|
||||||
-- These Middlewares are executed before any routes are reached
|
-- These Middlewares are executed before any routes are reached
|
||||||
preProcessors :: [Middleware]
|
preProcessors :: [Middleware]
|
||||||
@ -22,11 +32,14 @@ preProcessors = [ logStdoutDev
|
|||||||
, staticPolicy $ noDots >-> addBase "data/assets/public"
|
, staticPolicy $ noDots >-> addBase "data/assets/public"
|
||||||
]
|
]
|
||||||
|
|
||||||
-- The application's routes expressed as a list of WAI Middlewares
|
-- These Middlewares are executed after all other routes are exhausted
|
||||||
|
postProcessors :: [Middleware]
|
||||||
|
postProcessors = []
|
||||||
|
|
||||||
|
-- The application's core routes expressed as a list of WAI Middlewares
|
||||||
routes :: [Middleware]
|
routes :: [Middleware]
|
||||||
routes =
|
routes =
|
||||||
[ get "/" Handle.index ]
|
[ get "/" Handle.index ]
|
||||||
|
|
||||||
-- Combine our Preprocessor Middlewares and Routes to create an App to run
|
mdFileToRoute :: FilePath -> Middleware
|
||||||
app :: [Middleware]
|
mdFileToRoute fp = get (fromString $ "/posts/" ++ fp) (Handle.posts fp)
|
||||||
app = preProcessors ++ routes
|
|
||||||
|
@ -20,6 +20,16 @@ index = do
|
|||||||
$ baseNav
|
$ baseNav
|
||||||
<> baseHome homeMd
|
<> baseHome homeMd
|
||||||
|
|
||||||
|
posts :: FilePath -> ResponderM a
|
||||||
|
posts fp = do
|
||||||
|
title <- liftIO Conf.appTitle
|
||||||
|
postMd <- liftIO $ mdFileToLucid
|
||||||
|
$ "./data/posts/" ++ fp ++ ".md"
|
||||||
|
sendLucidFragment
|
||||||
|
$ baseDoc title
|
||||||
|
$ baseNav
|
||||||
|
<> postMd
|
||||||
|
|
||||||
missing :: ResponderM a
|
missing :: ResponderM a
|
||||||
missing = sendLucidFragment pageNotFound
|
missing = sendLucidFragment pageNotFound
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ baseDoc :: String -> Html () -> Html ()
|
|||||||
baseDoc title bodyContent = doctypehtml_ $ do
|
baseDoc title bodyContent = doctypehtml_ $ do
|
||||||
head_ $ do
|
head_ $ do
|
||||||
title_ $ fromString title
|
title_ $ fromString title
|
||||||
link_ [rel_ "stylesheet", type_ "text/css", href_ "style.css"]
|
link_ [rel_ "stylesheet", type_ "text/css", href_ "/style.css"]
|
||||||
script_ [src_ "/htmx.min.js"] none
|
script_ [src_ "/htmx.min.js"] none
|
||||||
body_ bodyContent
|
body_ bodyContent
|
||||||
|
|
||||||
|
22
src/Main.hs
22
src/Main.hs
@ -1,7 +1,23 @@
|
|||||||
module Main where
|
module Main where
|
||||||
|
|
||||||
import qualified Core.HTTP as Core
|
import qualified Core.HTTP as HTTP
|
||||||
import qualified Core.Configuration as Conf
|
import qualified Core.Configuration as Conf
|
||||||
|
|
||||||
|
import Control.Monad ( mapM_ )
|
||||||
|
import System.FilePath.Find ( always, extension, fileName, find, (&&?)
|
||||||
|
, (/~?), (==?) )
|
||||||
|
import System.FilePath ( dropExtension, takeFileName )
|
||||||
|
|
||||||
|
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
main = Conf.main >>= (\_ -> Core.main)
|
main = do
|
||||||
|
Conf.main
|
||||||
|
mdFilePaths <- getMdFilePaths "./data/posts/"
|
||||||
|
let mdFiles = map (dropExtension . takeFileName) mdFilePaths
|
||||||
|
HTTP.main mdFiles
|
||||||
|
|
||||||
|
getMdFilePaths :: FilePath -> IO [FilePath]
|
||||||
|
getMdFilePaths fp = find isVisible (isMdFile &&? isVisible) fp
|
||||||
|
where
|
||||||
|
isMdFile = extension ==? ".md"
|
||||||
|
isVisible = fileName /~? ".?*"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user