packages feed

clckwrks-0.13.0: Clckwrks/Page/PreProcess.hs

{-# 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(..))
import Clckwrks.URL   (ClckURL(ViewPageSlug))
import Clckwrks.Page.Types (PageId(..), slugify, toSlug)
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) =>
           (ClckURL -> [(Text, Maybe Text)] -> Text)
        -> TL.Text
        -> ClckT url m TL.Text
pageCmd clckShowURL txt =
    case parse (segments "page" parseCmd) txt of
      (Fail _ _ e) -> return (TL.pack e)
      (Done _ segments) ->
          do b <- transform (applyCmd clckShowURL) segments
             return $ B.toLazyText b

applyCmd clckShowURL l@(LinkPage pid mTitle) =
    do (ttl, slug) <-
           case mTitle of
             (Just t) -> return (t, Just $ slugify t)
             Nothing  -> do mttl <- query (GetPageTitle pid)
                            case mttl of
                              Nothing -> return $ (pack "Untitled", Nothing)
                              (Just ttlSlug) -> return ttlSlug
       html <- unXMLGenT $ <a href=(clckShowURL (ViewPageSlug pid (toSlug ttl slug)) [])><% ttl %></a>
       return $ B.fromString $ concat $ lines $ renderAsHTML html