deno.land / x / nano_jsx@v0.1.0 / components / helmet.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
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import { Component } from '../component.ts'import { appendChildren, h, isSSR } from '../core.ts'
class Attributes extends Map { toString() { let string = '' for (const [key, value] of this) string += ` ${key}="${value}"` return string.trim() }}
export class Helmet extends Component { static SSR(body: string) { const reg = /(<helmet\b[^>]*>)((.|\r|\n)*?)(<\/helmet>)/gm
// collect all elements const head: HTMLElement[] = [] const footer: HTMLElement[] = [] const attributes = { html: new Attributes(), body: new Attributes() }
// get what's in the head if (typeof document !== 'undefined' && document.head) { let children: HTMLElement[] = [] children = [].slice.call(document.head.children) for (let i = 0; i < children.length; i++) { // check if the same element already exists if (head.indexOf(children[i]) === -1) { head.push(children[i]) } } }
let result!: any while ((result = reg.exec(body)) !== null) { const first = result[1] let second = result[2]
const regHTML = /<html\s([^>]+)><\/html>/gm const regBody = /<body\s([^>]+)><\/body>/gm const regAttr = /(\w+)="([^"]+)"/gm let res = null
// extract html attributes body.match(regHTML)?.forEach(h => { second = second.replace(h, '') while ((res = regAttr.exec(h)) !== null) { attributes.html.set(res[1], res[2]) } }) // extract body attributes body.match(regBody)?.forEach(b => { second = second.replace(b, '') while ((res = regAttr.exec(b)) !== null) { attributes.body.set(res[1], res[2]) } })
const toHead = first.includes('data-placement="head"')
// do not add an element if it already exists if (toHead && !head.includes(second)) head.push(second) else if (!toHead && !footer.includes(second)) footer.push(second) }
// clean the body from all matches const cleanBody = body.replace(reg, '') return { body: cleanBody, head: head as unknown as string[], footer: footer as unknown as string[], attributes } }
didMount() { this.props.children.forEach((element: HTMLElement) => { // return if it is not an html element if (!(element instanceof HTMLElement)) return
const parent = this.props.footer ? document.body : document.head const tag = element.tagName let attrs: string[] = []
// get the inner text attrs.push(element.innerText as string)
// get all attributes for (let attr = 0; attr < element.attributes.length; attr++) { attrs.push(element.attributes.item(attr)?.name.toLowerCase() as string) attrs.push(element.attributes.item(attr)?.value.toLowerCase() as string) }
// handle special tags if (tag === 'HTML' || tag === 'BODY') { const htmlTag = document.getElementsByTagName(tag)[0] for (let attr = 1; attr < attrs.length; attr += 2) { htmlTag.setAttribute(attrs[attr], attrs[attr + 1]) } return } else if (tag === 'TITLE') { const titleTags = document.getElementsByTagName('TITLE') as HTMLCollectionOf<HTMLTitleElement> if (titleTags.length > 0) { const e = element as HTMLTitleElement titleTags[0].text = e.text } else { const titleTag = h('title', null, element.innerHTML) as HTMLTitleElement appendChildren(parent, [titleTag], false) } return }
// check if the element already exists let exists = false attrs = attrs.sort()
const el = document.getElementsByTagName(tag) as unknown as HTMLElement[]
for (let i = 0; i < el.length; i++) { let attrs2: string[] = []
// get the inner text attrs2.push(el[i].innerText as string)
for (let attr = 0; attr < el[i].attributes.length; attr++) { attrs2.push(el[i].attributes.item(attr)?.name.toLowerCase() as string) attrs2.push(el[i].attributes.item(attr)?.value.toLowerCase() as string) } attrs2 = attrs2.sort()
if (attrs.length > 0 && attrs2.length > 0 && JSON.stringify(attrs) === JSON.stringify(attrs2)) exists = true }
// add to dom if (!exists) appendChildren(parent, [element], false) }) }
render() { const placement = this.props.footer ? 'footer' : 'head'
if (isSSR()) return h('helmet', { 'data-ssr': true, 'data-placement': placement }, this.props.children) else return [] }}
nano_jsx

Version Info

Tagged at
8 months ago