jails-js 5.8.7 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1121 -0
- package/dist/index.js.map +1 -0
- package/dist/jails.js +1 -1
- package/dist/jails.js.map +1 -1
- package/{html.ts → html.js} +0 -1
- package/package.json +14 -7
- package/readme.md +6 -13
- package/src/component.ts +129 -104
- package/src/element.ts +25 -52
- package/src/index.ts +16 -30
- package/src/template-system.ts +152 -43
- package/src/utils/index.ts +11 -25
- package/src/utils/pubsub.ts +1 -1
- package/tsconfig.json +3 -0
- package/types.d.ts +47 -0
- package/vite.config.ts +4 -2
- package/index.d.ts +0 -65
- package/logo.svg +0 -29
- package/src/transpile.ts +0 -79
- package/src/utils/events.ts +0 -86
- package/src/utils/hmr-register.ts +0 -41
package/src/component.ts
CHANGED
@@ -1,151 +1,176 @@
|
|
1
|
-
import {
|
1
|
+
import { safe, g, dup } from './utils'
|
2
2
|
import { Idiomorph } from 'idiomorph/dist/idiomorph.esm'
|
3
|
-
import { rAF, dup, safe } from './utils'
|
4
|
-
import { buildtemplates } from './template-system'
|
5
|
-
import { on, off, trigger } from './utils/events'
|
6
3
|
import { publish, subscribe } from './utils/pubsub'
|
7
4
|
|
8
|
-
export
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
const
|
17
|
-
const
|
18
|
-
const
|
19
|
-
|
20
|
-
|
21
|
-
const
|
22
|
-
|
23
|
-
|
5
|
+
export const Component = ({ name, module, dependencies, node, templates, signal, register }) => {
|
6
|
+
|
7
|
+
let tick
|
8
|
+
let preserve = []
|
9
|
+
|
10
|
+
const _model = module.model || {}
|
11
|
+
const initialState = (new Function( `return ${node.getAttribute('html-model') || '{}'}`))()
|
12
|
+
const tplid = node.getAttribute('tplid')
|
13
|
+
const scopeid = node.getAttribute('html-scopeid')
|
14
|
+
const tpl = templates[ tplid ]
|
15
|
+
const scope = g.scope[ scopeid ]
|
16
|
+
const model = dup(module?.model?.apply ? _model({ elm:node, initialState }) : _model)
|
17
|
+
const state = Object.assign({}, scope, model, initialState)
|
18
|
+
const view = module.view? module.view : (data) => data
|
19
|
+
|
20
|
+
const base = {
|
21
|
+
name,
|
22
|
+
model,
|
23
|
+
elm: node,
|
24
|
+
template: tpl.template,
|
24
25
|
dependencies,
|
25
26
|
publish,
|
26
27
|
subscribe,
|
27
28
|
|
28
29
|
main(fn) {
|
29
|
-
|
30
|
-
},
|
31
|
-
|
32
|
-
unmount(fn) {
|
33
|
-
options.unmount = fn
|
34
|
-
},
|
35
|
-
|
36
|
-
onupdate(fn) {
|
37
|
-
options.onupdate = fn
|
38
|
-
},
|
39
|
-
|
40
|
-
on(eventName, selectorOrCallback, callback) {
|
41
|
-
on(elm, eventName, selectorOrCallback, callback)
|
30
|
+
node.addEventListener(':mount', fn)
|
42
31
|
},
|
43
32
|
|
44
|
-
|
45
|
-
|
46
|
-
|
33
|
+
/**
|
34
|
+
* @State
|
35
|
+
*/
|
36
|
+
state : {
|
47
37
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
},
|
38
|
+
protected( list ) {
|
39
|
+
if( list ) {
|
40
|
+
preserve = list
|
41
|
+
} else {
|
42
|
+
return preserve
|
43
|
+
}
|
44
|
+
},
|
56
45
|
|
57
|
-
|
58
|
-
|
59
|
-
|
46
|
+
save(data) {
|
47
|
+
if( data.constructor === Function ) {
|
48
|
+
data( state )
|
49
|
+
} else {
|
50
|
+
Object.assign(state, data)
|
51
|
+
}
|
52
|
+
},
|
60
53
|
|
61
|
-
state: {
|
62
54
|
set( data ) {
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
55
|
+
|
56
|
+
if (!document.body.contains(node)) {
|
57
|
+
return
|
58
|
+
}
|
59
|
+
if( data.constructor === Function ) {
|
60
|
+
data(state)
|
67
61
|
} else {
|
68
|
-
|
62
|
+
Object.assign(state, data)
|
69
63
|
}
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
64
|
+
|
65
|
+
const newstate = Object.assign({}, state, scope)
|
66
|
+
render(newstate)
|
67
|
+
|
68
|
+
return Promise.resolve(newstate)
|
74
69
|
},
|
75
70
|
|
76
|
-
|
77
|
-
return state
|
71
|
+
get() {
|
72
|
+
return Object.assign({}, state)
|
78
73
|
}
|
79
74
|
},
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
75
|
+
/**
|
76
|
+
* @Events
|
77
|
+
*/
|
78
|
+
on( ev, selectorOrCallback, callback ) {
|
79
|
+
|
80
|
+
if( callback ) {
|
81
|
+
callback.handler = (e) => {
|
82
|
+
const detail = e.detail || {}
|
83
|
+
let parent = e.target
|
84
|
+
while (parent) {
|
85
|
+
if (parent.matches(selectorOrCallback)) {
|
86
|
+
e.delegateTarget = parent
|
87
|
+
callback.apply(node, [e].concat(detail.args))
|
88
|
+
}
|
89
|
+
if (parent === node) break
|
90
|
+
parent = parent.parentNode
|
91
|
+
}
|
92
|
+
}
|
93
|
+
node.addEventListener(ev, callback.handler, {
|
94
|
+
signal,
|
95
|
+
capture: (ev == 'focus' || ev == 'blur' || ev == 'mouseenter' || ev == 'mouseleave')
|
96
|
+
})
|
97
|
+
|
98
|
+
} else {
|
99
|
+
selectorOrCallback.handler = (e) => {
|
100
|
+
e.delegateTarget = node
|
101
|
+
selectorOrCallback.apply(node, [e].concat(e.detail.args))
|
102
|
+
}
|
103
|
+
node.addEventListener(ev, selectorOrCallback.handler, { signal })
|
85
104
|
}
|
86
105
|
|
87
|
-
|
88
|
-
|
89
|
-
const newdata = dup(state.data)
|
90
|
-
const newhtml = templates[tplid].call(Object.assign(options.view(newdata), elm.___scope___), elm, safe)
|
106
|
+
},
|
91
107
|
|
92
|
-
|
93
|
-
|
108
|
+
off( ev, callback ) {
|
109
|
+
if( callback.handler ) {
|
110
|
+
node.removeEventListener(ev, callback.handler)
|
111
|
+
}
|
112
|
+
},
|
94
113
|
|
95
|
-
|
114
|
+
trigger(ev, selectorOrCallback, data) {
|
115
|
+
if( selectorOrCallback.constructor === String ) {
|
96
116
|
Array
|
97
|
-
.from(
|
98
|
-
.forEach(
|
99
|
-
|
100
|
-
child.options.onupdate(props)
|
101
|
-
child.base.render(props)
|
117
|
+
.from(node.querySelectorAll(selectorOrCallback))
|
118
|
+
.forEach( children => {
|
119
|
+
children.dispatchEvent(new CustomEvent(ev, { bubbles: true, detail: { args: data } }) )
|
102
120
|
})
|
103
|
-
}
|
121
|
+
} else {
|
122
|
+
node.dispatchEvent(new CustomEvent(ev, { bubbles: true, detail:{ args: data } }))
|
123
|
+
}
|
104
124
|
},
|
105
125
|
|
106
|
-
|
126
|
+
emit(ev, data) {
|
127
|
+
node.dispatchEvent(new CustomEvent(ev, { bubbles: true, detail: { args: data } }))
|
128
|
+
},
|
129
|
+
|
130
|
+
unmount( fn ) {
|
131
|
+
node.addEventListener(':unmount', fn)
|
132
|
+
},
|
107
133
|
|
108
|
-
|
134
|
+
innerHTML ( target, html_ ) {
|
135
|
+
const element = html_? target : node
|
109
136
|
const clone = element.cloneNode()
|
110
137
|
const html = html_? html_ : target
|
111
138
|
clone.innerHTML = html
|
112
|
-
|
113
|
-
rAF( _ => Idiomorph.morph(element, clone, IdiomorphOptions) )
|
139
|
+
Idiomorph.morph(element, clone)
|
114
140
|
}
|
115
141
|
}
|
116
142
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
const
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
cp.___scope___ = 'scope' in script.dataset? (new Function(`return ${script.text}`))() : {}
|
133
|
-
}
|
143
|
+
const render = ( data ) => {
|
144
|
+
clearTimeout( tick )
|
145
|
+
tick = setTimeout(() => {
|
146
|
+
const html = tpl.render.call( view(data), node, safe, g )
|
147
|
+
Idiomorph.morph( node, html, IdiomorphOptions(node, register) )
|
148
|
+
Promise.resolve().then(() => {
|
149
|
+
node.querySelectorAll('[tplid]')
|
150
|
+
.forEach((element) => {
|
151
|
+
const child = register.get(element)
|
152
|
+
if(!child) return
|
153
|
+
child.state.protected().forEach( key => delete data[key] )
|
154
|
+
child.state.set(data)
|
155
|
+
})
|
156
|
+
Promise.resolve().then(() => g.scope = {})
|
157
|
+
})
|
134
158
|
})
|
135
|
-
}
|
136
|
-
}
|
137
|
-
|
159
|
+
}
|
138
160
|
|
139
|
-
|
161
|
+
render( state )
|
162
|
+
register.set( node, base )
|
163
|
+
return module.default( base )
|
164
|
+
}
|
140
165
|
|
166
|
+
const IdiomorphOptions = ( parent, register ) => ({
|
141
167
|
callbacks: {
|
142
|
-
|
143
168
|
beforeNodeMorphed( node ) {
|
144
169
|
if( node.nodeType === 1 ) {
|
145
170
|
if( 'html-static' in node.attributes ) {
|
146
171
|
return false
|
147
172
|
}
|
148
|
-
if( node
|
173
|
+
if( register.get(node) && node !== parent ) {
|
149
174
|
return false
|
150
175
|
}
|
151
176
|
}
|
package/src/element.ts
CHANGED
@@ -1,14 +1,12 @@
|
|
1
|
-
import Component from './component'
|
2
|
-
import { purge, rAF } from './utils'
|
1
|
+
import { Component } from './component'
|
3
2
|
|
4
|
-
|
3
|
+
const register = new WeakMap()
|
5
4
|
|
6
|
-
|
5
|
+
export const Element = ({ component, templates, start }) => {
|
6
|
+
|
7
|
+
const { name, module, dependencies } = component
|
7
8
|
|
8
|
-
|
9
|
-
options: any
|
10
|
-
returns : any
|
11
|
-
__events: any
|
9
|
+
return class extends HTMLElement {
|
12
10
|
|
13
11
|
constructor() {
|
14
12
|
super()
|
@@ -16,59 +14,34 @@ export default function Element(module, dependencies, templates, components) {
|
|
16
14
|
|
17
15
|
connectedCallback() {
|
18
16
|
|
19
|
-
|
17
|
+
this.abortController = new AbortController()
|
20
18
|
|
21
|
-
this.
|
22
|
-
|
23
|
-
this.base.render()
|
24
|
-
this.returns = module.default(base)
|
25
|
-
|
26
|
-
if( this.__template && this.__template.constructor === Promise ) {
|
27
|
-
this.__template.then( _ => {
|
28
|
-
if( this.base && this.options.main) {
|
29
|
-
const array = this.options.main(this.base)
|
30
|
-
if( array && array.length ){
|
31
|
-
array.forEach(f => f(this.base))
|
32
|
-
}
|
33
|
-
}
|
34
|
-
})
|
35
|
-
return
|
19
|
+
if( !this.getAttribute('tplid') ) {
|
20
|
+
start( this.parentNode )
|
36
21
|
}
|
37
22
|
|
38
|
-
|
39
|
-
this
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
23
|
+
const rtrn = Component({
|
24
|
+
node:this,
|
25
|
+
name,
|
26
|
+
module,
|
27
|
+
dependencies,
|
28
|
+
templates,
|
29
|
+
signal: this.abortController.signal,
|
30
|
+
register
|
31
|
+
})
|
47
32
|
|
33
|
+
if ( rtrn && rtrn.constructor === Promise ) {
|
34
|
+
rtrn.then(() => {
|
35
|
+
this.dispatchEvent( new CustomEvent(':mount') )
|
36
|
+
})
|
48
37
|
} else {
|
49
|
-
|
50
|
-
const array = this.options.main(this.base)
|
51
|
-
if( array && array.length ) {
|
52
|
-
array.forEach(f => f(this.base))
|
53
|
-
}
|
54
|
-
}
|
38
|
+
this.dispatchEvent( new CustomEvent(':mount') )
|
55
39
|
}
|
56
40
|
}
|
57
41
|
|
58
42
|
disconnectedCallback() {
|
59
|
-
this.
|
60
|
-
|
61
|
-
if(!document.body.contains(this) ) {
|
62
|
-
this.__events? this.__events = null : null
|
63
|
-
this.base? this.base.elm = null : null
|
64
|
-
this.base? this.base = null : null
|
65
|
-
purge(this)
|
66
|
-
}
|
67
|
-
})
|
68
|
-
}
|
69
|
-
|
70
|
-
attributeChangedCallback() {
|
71
|
-
//TODO
|
43
|
+
this.dispatchEvent( new CustomEvent(':unmount') )
|
44
|
+
this.abortController.abort()
|
72
45
|
}
|
73
46
|
}
|
74
47
|
}
|
package/src/index.ts
CHANGED
@@ -1,42 +1,28 @@
|
|
1
|
-
import { templateConfig, buildtemplates } from './template-system'
|
2
|
-
import { publish, subscribe } from './utils/pubsub'
|
3
|
-
import { html, attributes } from '../html'
|
4
|
-
import Element from './element'
|
5
1
|
|
6
|
-
|
7
|
-
|
2
|
+
import { Element } from './element'
|
3
|
+
import { template, templateConfig as config } from './template-system'
|
8
4
|
|
9
|
-
|
5
|
+
const components = {}
|
10
6
|
|
11
|
-
export
|
7
|
+
export { publish, subscribe } from './utils/pubsub'
|
12
8
|
|
13
|
-
|
9
|
+
export const templateConfig = (options) => {
|
10
|
+
config( options )
|
11
|
+
}
|
14
12
|
|
15
|
-
|
16
|
-
|
13
|
+
export const register = ( name, module, dependencies ) => {
|
14
|
+
components[ name ] = { name, module, dependencies }
|
15
|
+
}
|
17
16
|
|
18
|
-
|
19
|
-
components[name] = { name, module, dependencies }
|
20
|
-
},
|
17
|
+
export const start = ( target = document.body ) => {
|
21
18
|
|
22
|
-
|
23
|
-
const keys = Object.keys(components)
|
24
|
-
const selector = keys.toString()
|
25
|
-
if( keys.length ) {
|
26
|
-
buildtemplates( target, selector, templates, components )
|
27
|
-
registerComponents()
|
28
|
-
}
|
29
|
-
}
|
30
|
-
}
|
19
|
+
const templates = template( target, { components } )
|
31
20
|
|
32
|
-
const registerComponents = () => {
|
33
21
|
Object
|
34
22
|
.values( components )
|
35
|
-
.forEach(
|
36
|
-
|
37
|
-
|
38
|
-
const Base = Element(module, dependencies, templates, components)
|
39
|
-
customElements.define(name, Base)
|
23
|
+
.forEach(({ name, module, dependencies }) => {
|
24
|
+
if( !customElements.get(name) ) {
|
25
|
+
customElements.define( name, Element({ component: { name, module, dependencies }, templates, start }))
|
40
26
|
}
|
41
|
-
|
27
|
+
})
|
42
28
|
}
|
package/src/template-system.ts
CHANGED
@@ -1,26 +1,37 @@
|
|
1
|
-
import Transpile from './transpile'
|
2
1
|
import { uuid, decodeHTML } from './utils'
|
3
2
|
|
3
|
+
const templates = {}
|
4
|
+
|
4
5
|
const config = {
|
5
|
-
tags: ['
|
6
|
+
tags: ['{{', '}}']
|
6
7
|
}
|
7
8
|
|
8
9
|
export const templateConfig = (newconfig) => {
|
9
|
-
Object.assign(config, newconfig)
|
10
|
+
Object.assign( config, newconfig )
|
10
11
|
}
|
11
12
|
|
12
|
-
export
|
13
|
+
export const template = ( target, { components }) => {
|
14
|
+
|
15
|
+
tagElements( target, [...Object.keys( components ), '[html-if]', 'template'] )
|
16
|
+
const clone = target.cloneNode( true )
|
13
17
|
|
14
|
-
|
15
|
-
|
16
|
-
|
18
|
+
transformTemplate( clone )
|
19
|
+
removeTemplateTagsRecursively( clone )
|
20
|
+
setTemplates( clone, components )
|
21
|
+
|
22
|
+
return templates
|
23
|
+
}
|
17
24
|
|
18
|
-
|
25
|
+
export const compile = ( html ) => {
|
26
|
+
|
27
|
+
const parsedHtml = JSON.stringify( html )
|
28
|
+
|
29
|
+
return new Function('$element', 'safe', '$g',`
|
19
30
|
var $data = this;
|
20
31
|
with( $data ){
|
21
|
-
var output=${
|
32
|
+
var output=${parsedHtml
|
22
33
|
.replace(/%%_=(.+?)_%%/g, function(_, variable){
|
23
|
-
return '"+safe(function(){return '+decodeHTML(variable)+';})+"'
|
34
|
+
return '"+safe(function(){return '+ decodeHTML(variable) +';})+"'
|
24
35
|
})
|
25
36
|
.replace(/%%_(.+?)_%%/g, function(_, variable){
|
26
37
|
return '";' + decodeHTML(variable) +'\noutput+="'
|
@@ -29,48 +40,146 @@ export default function Template(element) {
|
|
29
40
|
`)
|
30
41
|
}
|
31
42
|
|
32
|
-
|
33
|
-
|
34
|
-
.
|
35
|
-
.
|
43
|
+
const tagElements = ( target, keys ) => {
|
44
|
+
target
|
45
|
+
.querySelectorAll( keys.toString() )
|
46
|
+
.forEach((node) => {
|
47
|
+
if( node.localName === 'template' ) {
|
48
|
+
return tagElements( node.content, keys )
|
49
|
+
}
|
50
|
+
node.setAttribute('tplid', uuid())
|
51
|
+
if( node.getAttribute('html-if') && !node.id ) {
|
52
|
+
node.id = uuid()
|
53
|
+
}
|
54
|
+
})
|
55
|
+
}
|
56
|
+
|
57
|
+
const transformAttributes = ( html ) => {
|
58
|
+
|
59
|
+
const regexTags = new RegExp(`\\${config.tags[0]}(.+?)\\${config.tags[1]}`, 'g')
|
60
|
+
|
61
|
+
return html
|
62
|
+
.replace(/jails___scope-id/g, '%%_=$scopeid_%%')
|
63
|
+
.replace(regexTags, '%%_=$1_%%')
|
64
|
+
// Booleans
|
65
|
+
// https://meiert.com/en/blog/boolean-attributes-of-html/
|
66
|
+
.replace(/html-(allowfullscreen|async|autofocus|autoplay|checked|controls|default|defer|disabled|formnovalidate|inert|ismap|itemscope|loop|multiple|muted|nomodule|novalidate|open|playsinline|readonly|required|reversed|selected)=\"(.*?)\"/g, `%%_if(safe(function(){ return $2 })){_%%$1%%_}_%%`)
|
67
|
+
// The rest
|
68
|
+
.replace(/html-(.*?)=\"(.*?)\"/g, (all, key, value) => {
|
69
|
+
if (key === 'key' || key === 'model' || key === 'scopeid' ) {
|
70
|
+
return all
|
71
|
+
}
|
72
|
+
if (value) {
|
73
|
+
value = value.replace(/^{|}$/g, '')
|
74
|
+
return `${key}="%%_=safe(function(){ return ${value} })_%%"`
|
75
|
+
} else {
|
76
|
+
return all
|
77
|
+
}
|
78
|
+
})
|
79
|
+
}
|
80
|
+
|
81
|
+
const transformTemplate = ( clone ) => {
|
82
|
+
|
83
|
+
clone.querySelectorAll('template, [html-for], [html-if], [html-inner], [html-class]')
|
84
|
+
.forEach(( element ) => {
|
85
|
+
|
86
|
+
const htmlFor = element.getAttribute('html-for')
|
87
|
+
const htmlIf = element.getAttribute('html-if')
|
88
|
+
const htmlInner = element.getAttribute('html-inner')
|
89
|
+
const htmlClass = element.getAttribute('html-class')
|
90
|
+
|
91
|
+
if ( htmlFor ) {
|
92
|
+
|
93
|
+
element.removeAttribute('html-for')
|
94
|
+
|
95
|
+
const split = htmlFor.match(/(.*)\sin\s(.*)/) || ''
|
96
|
+
const varname = split[1]
|
97
|
+
const object = split[2]
|
98
|
+
const objectname = object.split(/\./).shift()
|
99
|
+
const open = document.createTextNode(`%%_ ;(function(){ var $index = 0; for(var $key in safe(function(){ return ${object} }) ){ var $scopeid = Math.random().toString(36).substring(2, 9); var ${varname} = ${object}[$key]; $g.scope[$scopeid] = Object.assign({}, { ${objectname}: ${objectname} }, { ${varname} :${varname}, $index: $index, $key: $key }); _%%`)
|
100
|
+
const close = document.createTextNode(`%%_ $index++; } })() _%%`)
|
101
|
+
|
102
|
+
wrap(open, element, close)
|
103
|
+
}
|
104
|
+
|
105
|
+
if (htmlIf) {
|
106
|
+
element.removeAttribute('html-if')
|
107
|
+
const open = document.createTextNode(`%%_ if ( safe(function(){ return ${htmlIf} }) ){ _%%`)
|
108
|
+
const close = document.createTextNode(`%%_ } _%%`)
|
109
|
+
wrap(open, element, close)
|
110
|
+
}
|
111
|
+
|
112
|
+
if (htmlInner) {
|
113
|
+
element.removeAttribute('html-inner')
|
114
|
+
element.innerHTML = `%%_=${htmlInner}_%%`
|
115
|
+
}
|
116
|
+
|
117
|
+
if (htmlClass) {
|
118
|
+
element.removeAttribute('html-class')
|
119
|
+
element.className = (element.className + ` %%_=${htmlClass}_%%`).trim()
|
120
|
+
}
|
121
|
+
|
122
|
+
if( element.localName === 'template' ) {
|
123
|
+
transformTemplate(element.content)
|
124
|
+
}
|
125
|
+
})
|
126
|
+
}
|
127
|
+
|
128
|
+
const setTemplates = ( clone, components ) => {
|
129
|
+
|
130
|
+
Array.from(clone.querySelectorAll('[tplid]'))
|
36
131
|
.reverse()
|
37
|
-
.forEach(
|
38
|
-
|
39
|
-
|
132
|
+
.forEach((node) => {
|
133
|
+
|
134
|
+
const tplid = node.getAttribute('tplid')
|
135
|
+
const name = node.localName
|
136
|
+
node.setAttribute('html-scopeid', 'jails___scope-id')
|
137
|
+
|
138
|
+
if( name in components && components[name].module.template ) {
|
139
|
+
const children = node.innerHTML
|
140
|
+
const html = components[name].module.template({ elm:node, children })
|
141
|
+
node.innerHTML = html
|
142
|
+
}
|
143
|
+
|
144
|
+
const html = transformAttributes(node.outerHTML)
|
145
|
+
|
146
|
+
templates[ tplid ] = {
|
147
|
+
template: html,
|
148
|
+
render : compile(html)
|
149
|
+
}
|
40
150
|
})
|
41
151
|
}
|
42
152
|
|
43
|
-
const
|
153
|
+
const removeTemplateTagsRecursively = (node) => {
|
44
154
|
|
45
|
-
|
155
|
+
// Get all <template> elements within the node
|
156
|
+
const templates = node.querySelectorAll('template')
|
46
157
|
|
47
|
-
|
48
|
-
const id = uuid()
|
49
|
-
element.setAttribute('tplid', id)
|
50
|
-
const name = element.localName
|
158
|
+
templates.forEach((template) => {
|
51
159
|
|
52
|
-
if(
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
160
|
+
if( template.getAttribute('html-if') || template.getAttribute('html-inner') ) {
|
161
|
+
return
|
162
|
+
}
|
163
|
+
|
164
|
+
// Process any nested <template> tags within this <template> first
|
165
|
+
removeTemplateTagsRecursively(template.content)
|
166
|
+
|
167
|
+
// Get the parent of the <template> tag
|
168
|
+
const parent = template.parentNode
|
169
|
+
|
170
|
+
if (parent) {
|
171
|
+
// Move all child nodes from the <template>'s content to its parent
|
172
|
+
const content = template.content
|
173
|
+
while (content.firstChild) {
|
174
|
+
parent.insertBefore(content.firstChild, template)
|
63
175
|
}
|
176
|
+
// Remove the <template> tag itself
|
177
|
+
parent.removeChild(template)
|
64
178
|
}
|
65
|
-
|
66
|
-
}
|
179
|
+
})
|
67
180
|
}
|
68
181
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
const _if = node.querySelectorAll('[html-if]')
|
73
|
-
_if.forEach( el => {
|
74
|
-
el.parentNode.insertBefore(document.createComment(''), el.nextSibling)
|
75
|
-
})
|
182
|
+
const wrap = (open, node, close) => {
|
183
|
+
node.parentNode?.insertBefore(open, node)
|
184
|
+
node.parentNode?.insertBefore(close, node.nextSibling)
|
76
185
|
}
|