{-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE NoFieldSelectors #-} {-# LANGUAGE StrictData #-} {-# LANGUAGE TemplateHaskell #-} module Pages where import Control.Monad (forM) import Control.Monad.IO.Class (liftIO) import Data.List (find) import Data.Text (Text) import Data.Text.IO qualified as T import Language.Haskell.TH.Syntax (addDependentFile) import System.Directory (makeAbsolute, listDirectory) import Text.Mustache.Compile qualified as M import Text.Mustache.Types qualified as M import Pages.TH data IndexData = IndexData { networks :: [IndexNetworkData] } data IndexNetworkData = IndexNetworkData { name :: Text , channels :: [IndexChannelData] } data IndexChannelData = IndexChannelData { name :: Text , alias :: Text } data CalendarData = CalendarData { network :: Text , channel :: Text , alias :: Text , years :: [CalendarYearData] } data CalendarYearData = CalendarYearData { year :: Int , monrows :: [CalendarMonthRowData] } data CalendarMonthRowData = CalendarMonthRowData { months :: [CalendarMonthData] } data CalendarMonthData = CalendarMonthData { display :: Bool , month :: Int , month00 :: Text , monthname :: Text , weeks :: [CalendarWeekData] , phantomweek :: Bool } data CalendarWeekData = CalendarWeekData { days :: [CalendarDayData'] } data CalendarDayData' = CalendarDayData' { date :: Maybe Int , date00 :: Text } data LogData = LogData { network :: Text , channel :: Text , alias :: Text , totalevents :: Text , efAll :: Bool , efCompr :: Bool , picker :: PickerData , events :: [EventData () Text] } data CalendarDayData = CalendarDayData { network :: Text , channel :: Text , alias :: Text , efAll :: Bool , efCompr :: Bool , date :: Text , picker :: CalendarPickerData , events :: [EventData Text ()] } data PickerData = PickerData { prevpage :: Maybe Int , nextpage :: Maybe Int , firstpage :: Bool , leftdots :: Bool , rightdots :: Bool , lastpage :: Bool , leftnums :: [Int] , curnum :: Int , rightnums :: [Int] , npages :: Int } data CalendarPickerData = CalendarPickerData { prevpage :: Maybe Text , nextpage :: Maybe Text } data EventData tm dttm = EventData { classlist :: Maybe Text , time :: tm , datetime :: dttm , linkid :: Text , nickwrap1 :: Maybe Text , nick :: Text , nickwrap2 :: Maybe Text , message :: Text } $(do let dropSuffix suf str = let (actualSuf, rstr) = splitAt (length suf) (reverse str) in if actualSuf == reverse suf then reverse rstr else str let inlinePartials :: [M.Template] -> M.Template -> M.Template inlinePartials ps (M.Template topname ast _) = M.Template topname (concatMap go ast) mempty where go :: M.Node Text -> [M.Node Text] go n@M.TextBlock{} = [n] go (M.Section named nodes) = [M.Section named (concatMap go nodes)] go (M.InvertedSection named nodes) = [M.InvertedSection named (concatMap go nodes)] go n@M.Variable{} = [n] -- sorry for the lost indent go (M.Partial _indent partialname) = case find ((== partialname) . M.name) ps of Just (M.Template _ ast' _) -> concatMap go ast' Nothing -> error $ "Partial not found: " ++ partialname partialFiles <- liftIO $ listDirectory "pages/partials" partials <- forM partialFiles $ \fname -> do path <- liftIO $ makeAbsolute ("pages/partials/" ++ fname) tplSrc <- liftIO $ T.readFile path addDependentFile path let name = dropSuffix ".mustache" fname case M.compileTemplate name tplSrc of Right tpl -> return tpl Left err -> fail $ "Reading " ++ path ++ ": " ++ show err let makeDecs name dataname = do path <- liftIO $ makeAbsolute ("pages/" ++ name ++ ".mustache") tplSrc <- liftIO $ T.readFile path addDependentFile path tpl <- case M.compileTemplate name tplSrc of Right tpl -> return tpl Left err -> fail $ "Reading " ++ path ++ ": " ++ show err let tpl' = inlinePartials partials tpl makeRender tpl' dataname concat <$> mapM (uncurry makeDecs) [("log", ''LogData) ,("calendar-day", ''CalendarDayData) ,("index", ''IndexData) ,("calendar", ''CalendarData)])