-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathindex.js
109 lines (85 loc) · 2.5 KB
/
index.js
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import * as parse from 'parse5'
// eslint-disable-next-line
global.root = { toString () {} }
const registry = {}
global.document = {}
global.window = {
HTMLElement: class {
constructor () {
this.children = []
this.childNodes = []
this.attributes = []
this.id = this._id = 'ssr'
this.elementName = this.constructor.name
}
getRootNode () {
return this
}
disabledClientSideCallbacks () {
this.willConnect = () => {}
this.connected = () => {}
this.updated = () => {}
this.disconnected = () => {}
}
async visit (node) {
const Component = registry[node.tagName]
if (Component) {
const c = new Component()
c.node = node
c.disabledClientSideCallbacks()
c.attributes = node.attrs
c.connectedCallback()
if (c.stylesheet && !Tonic._stylesheetRegistry[node.tagName]) {
Tonic._stylesheetRegistry[node.tagName] = c.stylesheet()
}
const t = await c.render()
const frag = parse.parseFragment(t.rawText)
node.childNodes.push(...frag.childNodes)
}
for (const child of node.childNodes) {
if (child.childNodes) await this.visit(child)
}
}
querySelectorAll (s) {
const tags = s.split(',')
const elements = []
const find = (node, tagName) => {
for (const child of node.childNodes) {
if (child.tagName === tagName) elements.push(child)
if (child.childNodes) find(child, tagName)
}
}
for (const tagName of tags) {
find(this, tagName)
}
return elements
}
async preRender () {
const t = await this.render()
Object.assign(this, parse.parse(t.rawText))
this.disabledClientSideCallbacks()
this.connectedCallback()
const nodes = this.querySelectorAll(Tonic._tags)
for (const node of nodes) {
await this.visit(node)
}
const styles = Object.values(Tonic._stylesheetRegistry).join('\n')
const styleNode = parse.parseFragment(`<style>${styles}</style>`)
const head = this.querySelectorAll('head')[0]
if (head) {
head.childNodes.unshift(styleNode.childNodes[0])
}
return parse.serialize(this)
}
},
customElements: {
define: (id, c) => (registry[id] = c),
get: (id) => registry[id]
},
customEvent: () => {}
}
const { Tonic } = await import('@socketsupply/tonic')
Tonic.ssr = true
Tonic.cache = {}
export default Tonic
export { Tonic }