This repository has been archived by the owner on Sep 19, 2023. It is now read-only.
/
elementToVNode.ts
67 lines (54 loc) · 1.68 KB
/
elementToVNode.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import { combine, Effects } from '@typed/effects'
import { map } from '@typed/list'
import { Just } from '@typed/maybe'
import {
comment,
ElementToVNode,
html,
HtmlTagName,
svg,
SvgTagName,
text,
VNode,
VNodeChildren,
} from '../domain'
import { SVG_NAMESPACE } from './constants'
const EMPTY: VNodeChildren = []
export const elementToVNode: ElementToVNode<unknown> = function* (
node: Text | Comment | HTMLElement | SVGElement,
): Effects<unknown, VNode> {
if (isTextNode(node)) {
const vNode = text(node.textContent ?? '')
vNode.node.current = Just.of(node)
return vNode
}
if (isCommentNode(node)) {
const vNode = comment(node.textContent ?? '')
vNode.node.current = Just.of(node)
return vNode
}
const props = { id: node.id, className: node.className }
const children: VNodeChildren =
node.childNodes.length === 0
? EMPTY
: yield* combine(
...map(
elementToVNode,
node.childNodes as NodeListOf<Text | Comment | HTMLElement | SVGElement>,
),
)
const vNode = isSvgElement(node)
? svg(node.tagName.toLowerCase() as SvgTagName, props, children)
: html(node.tagName.toLowerCase() as HtmlTagName, props, children)
vNode.node.current = Just.of(node as any)
return vNode
}
function isTextNode(node: Text | Comment | HTMLElement | SVGElement): node is Text {
return node.nodeType === Node.TEXT_NODE
}
function isCommentNode(node: Text | Comment | HTMLElement | SVGElement): node is Comment {
return node.nodeType === Node.COMMENT_NODE
}
function isSvgElement(node: Text | Comment | HTMLElement | SVGElement): node is SVGElement {
return node.namespaceURI === SVG_NAMESPACE
}