virtual-dom: clone Html library into virtual-dom

This commit is contained in:
Brian Carroll 2022-10-21 07:39:14 +01:00
parent e589dc88a3
commit 0732395be8
No known key found for this signature in database
GPG Key ID: 5C7B2EC4101703C0
2 changed files with 630 additions and 0 deletions

View File

@ -0,0 +1,353 @@
interface Html
exposes [
Node,
Attribute,
render,
renderWithoutDocType,
element,
text,
attribute,
html,
base,
head,
link,
meta,
style,
title,
body,
address,
article,
aside,
footer,
header,
h1,
h2,
h3,
h4,
h5,
h6,
main,
nav,
section,
blockquote,
dd,
div,
dl,
dt,
figcaption,
figure,
hr,
li,
menu,
ol,
p,
pre,
ul,
a,
abbr,
b,
bdi,
bdo,
br,
cite,
code,
data,
dfn,
em,
i,
kbd,
mark,
q,
rp,
rt,
ruby,
s,
samp,
small,
span,
strong,
sub,
sup,
time,
u,
var,
wbr,
area,
audio,
img,
map,
track,
video,
embed,
iframe,
object,
picture,
portal,
source,
svg,
math,
canvas,
noscript,
script,
del,
ins,
caption,
col,
colgroup,
table,
tbody,
td,
tfoot,
th,
thead,
tr,
button,
datalist,
fieldset,
form,
input,
label,
legend,
meter,
optgroup,
option,
output,
progress,
select,
textarea,
details,
dialog,
summary,
slot,
template,
]
imports [Html.Attributes]
Node : [Text Str, Element Str Nat (List Attribute) (List Node)]
Attribute : Html.Attributes.Attribute
attribute : Str -> (Str -> Attribute)
attribute = Html.Attributes.attribute
text : Str -> Node
text = Text
## Define a non-standard HTML Element
##
## You can use this to add elements that are not already supported.
## For example, you could bring back the obsolete <blink> element,
## and add some 90's nostalgia to your web page!
##
## blink : List Attribute, List Node -> Node
## blink = element "blink"
##
## html = blink [] [ text "This text is blinking!" ]
##
element : Str -> (List Attribute, List Node -> Node)
element = \tagName ->
\attrs, children ->
# While building the node tree, calculate the size of Str it will render to
withTag = 2 * (3 + Str.countUtf8Bytes tagName)
withAttrs = List.walk attrs withTag \acc, Attribute name val ->
acc + Str.countUtf8Bytes name + Str.countUtf8Bytes val + 4
totalSize = List.walk children withAttrs \acc, child ->
acc + nodeSize child
Element tagName totalSize attrs children
# internal helper
nodeSize : Node -> Nat
nodeSize = \node ->
when node is
Text content ->
Str.countUtf8Bytes content
Element _ size _ _ ->
size
## Render a Node to an HTML string
##
## The output has no whitespace between nodes, to make it small.
## This is intended for generating full HTML documents, so it
## automatically adds `<!DOCTYPE html>` to the start of the string.
## See also `renderWithoutDocType`.
render : Node -> Str
render = \node ->
buffer = Str.reserve "<!DOCTYPE html>" (nodeSize node)
renderHelp buffer node
## Render a Node to a string, without a DOCTYPE tag
renderWithoutDocType : Node -> Str
renderWithoutDocType = \node ->
buffer = Str.reserve "" (nodeSize node)
renderHelp buffer node
# internal helper
renderHelp : Str, Node -> Str
renderHelp = \buffer, node ->
when node is
Text content ->
Str.concat buffer content
Element tagName _ attrs children ->
withTagName = "\(buffer)<\(tagName)"
withAttrs =
if List.isEmpty attrs then
withTagName
else
List.walk attrs "\(withTagName) " renderAttr
withTag = Str.concat withAttrs ">"
withChildren = List.walk children withTag renderHelp
"\(withChildren)</\(tagName)>"
# internal helper
renderAttr : Str, Attribute -> Str
renderAttr = \buffer, Attribute key val ->
"\(buffer) \(key)=\"\(val)\""
# Main root
html = element "html"
# Document metadata
base = element "base"
head = element "head"
link = element "link"
meta = element "meta"
style = element "style"
title = element "title"
# Sectioning root
body = element "body"
# Content sectioning
address = element "address"
article = element "article"
aside = element "aside"
footer = element "footer"
header = element "header"
h1 = element "h1"
h2 = element "h2"
h3 = element "h3"
h4 = element "h4"
h5 = element "h5"
h6 = element "h6"
main = element "main"
nav = element "nav"
section = element "section"
# Text content
blockquote = element "blockquote"
dd = element "dd"
div = element "div"
dl = element "dl"
dt = element "dt"
figcaption = element "figcaption"
figure = element "figure"
hr = element "hr"
li = element "li"
menu = element "menu"
ol = element "ol"
p = element "p"
pre = element "pre"
ul = element "ul"
# Inline text semantics
a = element "a"
abbr = element "abbr"
b = element "b"
bdi = element "bdi"
bdo = element "bdo"
br = element "br"
cite = element "cite"
code = element "code"
data = element "data"
dfn = element "dfn"
em = element "em"
i = element "i"
kbd = element "kbd"
mark = element "mark"
q = element "q"
rp = element "rp"
rt = element "rt"
ruby = element "ruby"
s = element "s"
samp = element "samp"
small = element "small"
span = element "span"
strong = element "strong"
sub = element "sub"
sup = element "sup"
time = element "time"
u = element "u"
var = element "var"
wbr = element "wbr"
# Image and multimedia
area = element "area"
audio = element "audio"
img = element "img"
map = element "map"
track = element "track"
video = element "video"
# Embedded content
embed = element "embed"
iframe = element "iframe"
object = element "object"
picture = element "picture"
portal = element "portal"
source = element "source"
# SVG and MathML
svg = element "svg"
math = element "math"
# Scripting
canvas = element "canvas"
noscript = element "noscript"
script = element "script"
# Demarcating edits
del = element "del"
ins = element "ins"
# Table content
caption = element "caption"
col = element "col"
colgroup = element "colgroup"
table = element "table"
tbody = element "tbody"
td = element "td"
tfoot = element "tfoot"
th = element "th"
thead = element "thead"
tr = element "tr"
# Forms
button = element "button"
datalist = element "datalist"
fieldset = element "fieldset"
form = element "form"
input = element "input"
label = element "label"
legend = element "legend"
meter = element "meter"
optgroup = element "optgroup"
option = element "option"
output = element "output"
progress = element "progress"
select = element "select"
textarea = element "textarea"
# Interactive elements
details = element "details"
dialog = element "dialog"
summary = element "summary"
# Web Components
slot = element "slot"
template = element "template"

View File

@ -0,0 +1,277 @@
interface Html.Attributes
exposes [
Attribute,
attribute,
accept,
acceptCharset,
accesskey,
action,
align,
allow,
alt,
async,
autocapitalize,
autocomplete,
autofocus,
autoplay,
background,
bgcolor,
border,
buffered,
capture,
challenge,
charset,
checked,
cite,
class,
code,
codebase,
color,
cols,
colspan,
content,
contenteditable,
contextmenu,
controls,
coords,
crossorigin,
csp,
data,
dataAttr,
datetime,
decoding,
default,
defer,
dir,
dirname,
disabled,
download,
draggable,
enctype,
enterkeyhint,
for,
form,
formaction,
formenctype,
formmethod,
formnovalidate,
formtarget,
headers,
height,
hidden,
high,
href,
hreflang,
httpEquiv,
icon,
id,
importance,
integrity,
intrinsicsize,
inputmode,
ismap,
itemprop,
keytype,
kind,
label,
lang,
language,
loading,
list,
loop,
low,
manifest,
max,
maxlength,
minlength,
media,
method,
min,
multiple,
muted,
name,
novalidate,
open,
optimum,
pattern,
ping,
placeholder,
poster,
preload,
radiogroup,
readonly,
referrerpolicy,
rel,
required,
reversed,
role,
rows,
rowspan,
sandbox,
scope,
scoped,
selected,
shape,
size,
sizes,
slot,
span,
spellcheck,
src,
srcdoc,
srclang,
srcset,
start,
step,
style,
summary,
tabindex,
target,
title,
translate,
type,
usemap,
value,
width,
wrap,
]
imports []
Attribute : [Attribute Str Str]
attribute : Str -> (Str -> Attribute)
attribute = \attrName ->
\attrValue -> Attribute attrName attrValue
accept = attribute "accept"
acceptCharset = attribute "accept-charset"
accesskey = attribute "accesskey"
action = attribute "action"
align = attribute "align"
allow = attribute "allow"
alt = attribute "alt"
async = attribute "async"
autocapitalize = attribute "autocapitalize"
autocomplete = attribute "autocomplete"
autofocus = attribute "autofocus"
autoplay = attribute "autoplay"
background = attribute "background"
bgcolor = attribute "bgcolor"
border = attribute "border"
buffered = attribute "buffered"
capture = attribute "capture"
challenge = attribute "challenge"
charset = attribute "charset"
checked = attribute "checked"
cite = attribute "cite"
class = attribute "class"
code = attribute "code"
codebase = attribute "codebase"
color = attribute "color"
cols = attribute "cols"
colspan = attribute "colspan"
content = attribute "content"
contenteditable = attribute "contenteditable"
contextmenu = attribute "contextmenu"
controls = attribute "controls"
coords = attribute "coords"
crossorigin = attribute "crossorigin"
csp = attribute "csp"
data = attribute "data"
dataAttr = \dataName, dataVal -> Attribute "data-\(dataName)" dataVal
datetime = attribute "datetime"
decoding = attribute "decoding"
default = attribute "default"
defer = attribute "defer"
dir = attribute "dir"
dirname = attribute "dirname"
disabled = attribute "disabled"
download = attribute "download"
draggable = attribute "draggable"
enctype = attribute "enctype"
enterkeyhint = attribute "enterkeyhint"
for = attribute "for"
form = attribute "form"
formaction = attribute "formaction"
formenctype = attribute "formenctype"
formmethod = attribute "formmethod"
formnovalidate = attribute "formnovalidate"
formtarget = attribute "formtarget"
headers = attribute "headers"
height = attribute "height"
hidden = attribute "hidden"
high = attribute "high"
href = attribute "href"
hreflang = attribute "hreflang"
httpEquiv = attribute "http-equiv"
icon = attribute "icon"
id = attribute "id"
importance = attribute "importance"
integrity = attribute "integrity"
intrinsicsize = attribute "intrinsicsize"
inputmode = attribute "inputmode"
ismap = attribute "ismap"
itemprop = attribute "itemprop"
keytype = attribute "keytype"
kind = attribute "kind"
label = attribute "label"
lang = attribute "lang"
language = attribute "language"
loading = attribute "loading"
list = attribute "list"
loop = attribute "loop"
low = attribute "low"
manifest = attribute "manifest"
max = attribute "max"
maxlength = attribute "maxlength"
minlength = attribute "minlength"
media = attribute "media"
method = attribute "method"
min = attribute "min"
multiple = attribute "multiple"
muted = attribute "muted"
name = attribute "name"
novalidate = attribute "novalidate"
open = attribute "open"
optimum = attribute "optimum"
pattern = attribute "pattern"
ping = attribute "ping"
placeholder = attribute "placeholder"
poster = attribute "poster"
preload = attribute "preload"
radiogroup = attribute "radiogroup"
readonly = attribute "readonly"
referrerpolicy = attribute "referrerpolicy"
rel = attribute "rel"
required = attribute "required"
reversed = attribute "reversed"
role = attribute "role"
rows = attribute "rows"
rowspan = attribute "rowspan"
sandbox = attribute "sandbox"
scope = attribute "scope"
scoped = attribute "scoped"
selected = attribute "selected"
shape = attribute "shape"
size = attribute "size"
sizes = attribute "sizes"
slot = attribute "slot"
span = attribute "span"
spellcheck = attribute "spellcheck"
src = attribute "src"
srcdoc = attribute "srcdoc"
srclang = attribute "srclang"
srcset = attribute "srcset"
start = attribute "start"
step = attribute "step"
style = attribute "style"
summary = attribute "summary"
tabindex = attribute "tabindex"
target = attribute "target"
title = attribute "title"
translate = attribute "translate"
type = attribute "type"
usemap = attribute "usemap"
value = attribute "value"
width = attribute "width"
wrap = attribute "wrap"