module FF.HTML.Render where
open import Agda.Builtin.String using (String; primStringAppend)
open import Agda.Primitive using (Level; lzero; lsuc) renaming (Set to Type; _⊔_ to _lmax_)
open import Cubical.Foundations.Prelude using ()
open import Cubical.Data.List.Base using (List; []) renaming (_∷_ to _::_)
open import FF.HTML.Core
infixr 5 _++_
_++_ : String -> String -> String
_++_ = primStringAppend
private
levelOf : Level -> Level -> Level -> Level -> Level
levelOf tag key val atom = tag lmax key lmax val lmax atom
record Renderer
{tag key val atom : Level}
(S : Spec tag key val atom)
: Type (levelOf tag key val atom) where
field
renderTag : Tag S -> String
renderKey : {tagName : Tag S} -> AttrKey S tagName -> String
renderValue : {tagName : Tag S} -> (keyName : AttrKey S tagName) -> AttrValue S keyName -> String
renderAtom : Atom S -> String
open Renderer public
renderAttribute :
{tag key val atom : Level}
{S : Spec tag key val atom}
(renderer : Renderer S) ->
{tagName : Tag S} ->
Attribute S tagName ->
String
renderAttribute renderer (attr keyName value) =
Renderer.renderKey renderer keyName ++ "=\"" ++
Renderer.renderValue renderer keyName value ++ "\""
renderAttributes :
{tag key val atom : Level}
{S : Spec tag key val atom}
(renderer : Renderer S) ->
{tagName : Tag S} ->
List (Attribute S tagName) ->
String
renderAttributes renderer [] = ""
renderAttributes renderer (attribute :: rest) =
" " ++ renderAttribute renderer attribute ++ renderAttributes renderer rest
mutual
render :
{tag key val atom : Level}
{S : Spec tag key val atom} ->
Renderer S ->
Html S ->
String
render renderer (atomic content) =
Renderer.renderAtom renderer content
render renderer (node tagName attrs children) =
"<" ++ Renderer.renderTag renderer tagName ++ renderAttributes renderer attrs ++ ">" ++
renderChildren renderer children ++
"</" ++ Renderer.renderTag renderer tagName ++ ">"
renderChildren :
{tag key val atom : Level}
{S : Spec tag key val atom} ->
Renderer S ->
List (Html S) ->
String
renderChildren renderer [] = ""
renderChildren renderer (child :: rest) =
render renderer child ++ renderChildren renderer rest
pullRenderer :
{tag key val atom tag' key' val' atom' : Level}
{From : Spec tag key val atom}
{To : Spec tag' key' val' atom'} ->
Map From To ->
Renderer To ->
Renderer From
pullRenderer f renderer =
record
{ renderTag = \ tagName ->
Renderer.renderTag renderer (Map.mapTag f tagName)
; renderKey = \ keyName ->
Renderer.renderKey renderer (Map.mapKey f keyName)
; renderValue = \ keyName value ->
Renderer.renderValue renderer (Map.mapKey f keyName) (Map.mapValue f keyName value)
; renderAtom = \ content ->
Renderer.renderAtom renderer (Map.mapAtom f content)
}
renderVia :
{tag key val atom tag' key' val' atom' : Level}
{From : Spec tag key val atom}
{To : Spec tag' key' val' atom'} ->
Map From To ->
Renderer To ->
Html From ->
String
renderVia f renderer html = render renderer (mapHtml f html)