{-# LANGUAGE FlexibleContexts, OverloadedStrings #-} {-# OPTIONS_GHC -F -pgmFtrhsx #-} module Clckwrks.Page.PreProcess where import Control.Monad.Trans (MonadIO(..)) import Control.Applicative ((<*>), (*>), (<$>), (<|>), optional) import Clckwrks.Monad (ClckT, ClckState, transform, query, segments) import Clckwrks.Page.Acid (GetPageTitle(..), PageState) import Clckwrks.Page.URL (PageURL(ViewPageSlug)) import Clckwrks.Page.Types (PageId(..), slugify, toSlug) import Data.Acid (AcidState(..)) import Data.Acid.Advanced (query') import Data.Attoparsec.Text.Lazy (Parser, Result(..), anyChar, char, choice, decimal, parse, skipMany, space, stringCI, skipMany, try) import Data.Attoparsec.Combinator (many1, manyTill, skipMany) import Data.String (fromString) import Data.Text (Text, pack) import qualified Data.Text.Lazy as TL import Data.Text.Lazy.Builder (Builder) import qualified Data.Text.Lazy.Builder as B import HSP import HSP.HTML (renderAsHTML) import Web.Routes (showURL) -- TODO: move to reusable module parseAttr :: Text -> Parser () parseAttr name = do skipMany space stringCI name skipMany space char '=' skipMany space qchar :: Parser Char qchar = (char '\\' *> anyChar) <|> anyChar text :: Parser Text text = pack <$> many1 qchar qtext :: Parser Text qtext = pack <$> (char '"' *> manyTill qchar (try $ char '"')) data PageCmd = LinkPage PageId (Maybe Text) deriving (Eq, Ord, Show) pageId :: Parser PageCmd pageId = LinkPage <$> (parseAttr (fromString "id") *> (PageId <$> decimal)) <*> (optional $ parseAttr (fromString "title") *> qtext) parseCmd :: Parser PageCmd parseCmd = pageId pageCmd :: (Functor m, MonadIO m) => AcidState PageState -> (PageURL -> [(Text, Maybe Text)] -> Text) -> TL.Text -> ClckT url m TL.Text pageCmd pageAcid clckShowURL txt = case parse (segments "page" parseCmd) txt of (Fail _ _ e) -> return (TL.pack e) (Done _ segments) -> do b <- transform (applyCmd pageAcid clckShowURL) segments return $ B.toLazyText b applyCmd pageAcid clckShowURL l@(LinkPage pid mTitle) = do (ttl, slug) <- case mTitle of (Just t) -> return (t, Just $ slugify t) Nothing -> do mttl <- query' pageAcid (GetPageTitle pid) case mttl of Nothing -> return $ (pack "Untitled", Nothing) (Just ttlSlug) -> return ttlSlug html <- unXMLGenT $ <% ttl %> return $ B.fromString $ concat $ lines $ renderAsHTML html