{-# OPTIONS_GHC -Wno-missing-export-lists #-} module Burrito.Internal.Render where import qualified Burrito.Internal.Type.Case as Case import qualified Burrito.Internal.Type.Character as Character import qualified Burrito.Internal.Type.Digit as Digit import qualified Burrito.Internal.Type.Expression as Expression import qualified Burrito.Internal.Type.Field as Field import qualified Burrito.Internal.Type.Literal as Literal import qualified Burrito.Internal.Type.MaxLength as MaxLength import qualified Burrito.Internal.Type.Modifier as Modifier import qualified Burrito.Internal.Type.Name as Name import qualified Burrito.Internal.Type.Operator as Operator import qualified Burrito.Internal.Type.Template as Template import qualified Burrito.Internal.Type.Token as Token import qualified Burrito.Internal.Type.Variable as Variable import qualified Data.List as List import qualified Data.List.NonEmpty as NonEmpty import qualified Data.Text.Lazy as LazyText import qualified Data.Text.Lazy.Builder as Builder -- | Renders a template back into a string. This is essentially the opposite of -- @parse@. Usually you'll want to use @expand@ to actually substitute -- variables in the template, but this can be useful for printing out the -- template itself -- -- >>> render <$> parse "valid-template" -- Just "valid-template" -- >>> render <$> parse "{var}" -- Just "{var}" render :: Template.Template -> String render = builderToString . template builderToString :: Builder.Builder -> String builderToString = LazyText.unpack . Builder.toLazyText template :: Template.Template -> Builder.Builder template = foldMap token . Template.tokens token :: Token.Token -> Builder.Builder token x = case x of Token.Expression y -> expression y Token.Literal y -> literal y expression :: Expression.Expression -> Builder.Builder expression x = Builder.singleton '{' <> operator (Expression.operator x) <> sepBy1 variable (Builder.singleton ',') (Expression.variables x) <> Builder.singleton '}' operator :: Operator.Operator -> Builder.Builder operator x = case x of Operator.Ampersand -> Builder.singleton '&' Operator.FullStop -> Builder.singleton '.' Operator.None -> mempty Operator.NumberSign -> Builder.singleton '#' Operator.PlusSign -> Builder.singleton '+' Operator.QuestionMark -> Builder.singleton '?' Operator.Semicolon -> Builder.singleton ';' Operator.Solidus -> Builder.singleton '/' sepBy1 :: (a -> Builder.Builder) -> Builder.Builder -> NonEmpty.NonEmpty a -> Builder.Builder sepBy1 f x = mconcat . List.intersperse x . fmap f . NonEmpty.toList variable :: Variable.Variable -> Builder.Builder variable x = name (Variable.name x) <> modifier (Variable.modifier x) name :: Name.Name -> Builder.Builder name = sepBy1 field (Builder.singleton '.') . Name.fields field :: Field.Field -> Builder.Builder field = foldMap character . Field.characters character :: Character.Character tag -> Builder.Builder character x = case x of Character.Encoded y z -> encodedCharacter y z Character.Unencoded y -> Builder.singleton y encodedCharacter :: Digit.Digit -> Digit.Digit -> Builder.Builder encodedCharacter x y = Builder.singleton '%' <> digit x <> digit y digit :: Digit.Digit -> Builder.Builder digit x = Builder.singleton $ case x of Digit.Ox0 -> '0' Digit.Ox1 -> '1' Digit.Ox2 -> '2' Digit.Ox3 -> '3' Digit.Ox4 -> '4' Digit.Ox5 -> '5' Digit.Ox6 -> '6' Digit.Ox7 -> '7' Digit.Ox8 -> '8' Digit.Ox9 -> '9' Digit.OxA Case.Upper -> 'A' Digit.OxB Case.Upper -> 'B' Digit.OxC Case.Upper -> 'C' Digit.OxD Case.Upper -> 'D' Digit.OxE Case.Upper -> 'E' Digit.OxF Case.Upper -> 'F' Digit.OxA Case.Lower -> 'a' Digit.OxB Case.Lower -> 'b' Digit.OxC Case.Lower -> 'c' Digit.OxD Case.Lower -> 'd' Digit.OxE Case.Lower -> 'e' Digit.OxF Case.Lower -> 'f' modifier :: Modifier.Modifier -> Builder.Builder modifier x = case x of Modifier.Asterisk -> Builder.singleton '*' Modifier.Colon y -> Builder.singleton ':' <> maxLength y Modifier.None -> mempty maxLength :: MaxLength.MaxLength -> Builder.Builder maxLength = Builder.fromString . show . MaxLength.count literal :: Literal.Literal -> Builder.Builder literal = foldMap character . Literal.characters