{-# LANGUAGE RebindableSyntax #-} module Functions.Atom ( generateAtom ) where import Prelude import Types (Token, Date(..), formatDateShort) import DependencyGenerator (DepGenM, TokenableTo(..), onTupleToken) import Data.Text (Text) import qualified Data.Text as T fromString :: String -> Text fromString = T.pack class IsStructure a where toStructure :: a -> Structure instance IsStructure Structure where toStructure = id instance IsStructure [Structure] where toStructure [s] = s toStructure (s1 : s2 : ss) = Merge (Merge s1 s2) (toStructure ss) toStructure [] = Empty instance IsStructure [Text] where toStructure = Line instance IsStructure Text where toStructure t = toStructure [t] data Structure = Line [Text] | Indent Structure | Merge Structure Structure | Empty structureToText :: Structure -> Text structureToText = T.concat . toText "" where toText :: Text -> Structure -> [Text] toText indent = \case Line ts -> indent : ts ++ ["\n"] Indent s -> toText (T.append indent " ") s Merge a b -> toText indent a ++ toText indent b Empty -> [] (>:) :: (IsStructure a, IsStructure b) => a -> b -> Structure a >: b = Merge (toStructure a) (toStructure b) (>>:) :: (IsStructure a, IsStructure b) => a -> b -> Structure a >>: b = Merge (toStructure a) (Indent (toStructure b)) type AtomEntry = ((Text, Date), String) urlRoot :: Text urlRoot = "https://mad.metanohi.name" generateAtomStructure :: Date -> [AtomEntry] -> Structure generateAtomStructure updated entries = "" >: "" >>: ("Niels' mad" >: [""] >: [""] >: ["", urlRoot, "/atom.xml"] >: "" >>: ("Niels G. W. Serup" >: "ngws@metanohi.name") >: "" >: ["", formatDateShort updated, "T00:00:00Z"]) >>: map makeEntry entries >: "" makeEntry :: AtomEntry -> Structure makeEntry ((title, updated), slug) = "" >>: (["", title, ""] >: (""]) >: ("" : slugUrl ++ [""]) >: ("" : updatedDate ++ [""]) >: ("" : updatedDate ++ [""])) >: "" where slugUrl = [urlRoot, "/", T.pack slug, ".html"] updatedDate = [formatDateShort updated, "T00:00:00Z"] generateAtom :: (TokenableTo Date a, TokenableTo [AtomEntry] b) => a -> b -> DepGenM (Token Text) generateAtom = onTupleToken (\updated entries -> structureToText $ generateAtomStructure updated entries)