jails-js 5.9.0 → 6.0.1-beta.1
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 +1125 -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 +6 -6
- package/readme.md +1 -1
- package/src/component.ts +127 -99
- package/src/element.ts +21 -55
- package/src/index.ts +15 -30
- package/src/template-system.ts +161 -43
- package/src/utils/index.ts +11 -5
- package/src/utils/pubsub.ts +1 -1
- 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,110 +1,136 @@
|
|
1
|
-
import {
|
1
|
+
import { safe, rAF, g } 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
|
-
const
|
11
|
-
const
|
12
|
-
const
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
const
|
17
|
-
const
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
const base
|
22
|
-
|
23
|
-
|
5
|
+
export const Component = ({ name, module, dependencies, node, templates, signal }) => {
|
6
|
+
const _model = module.model || {}
|
7
|
+
const initialState = (new Function( `return ${node.getAttribute('html-model') || '{}'}`))()
|
8
|
+
const tplid = node.getAttribute('tplid')
|
9
|
+
const scopeid = node.getAttribute('html-scope-id')
|
10
|
+
const tpl = templates[ tplid ]
|
11
|
+
const data = g.scope[ scopeid ]
|
12
|
+
const model = module?.model?.apply ? _model({ elm:node, initialState }) : _model
|
13
|
+
const state = Object.assign({}, data, model, initialState)
|
14
|
+
const view = module.view? module.view : (data) => data
|
15
|
+
|
16
|
+
let updates = []
|
17
|
+
|
18
|
+
const base = {
|
19
|
+
name,
|
20
|
+
model,
|
21
|
+
elm: node,
|
22
|
+
template: tpl.template,
|
24
23
|
dependencies,
|
25
24
|
publish,
|
26
25
|
subscribe,
|
27
26
|
|
28
27
|
main(fn) {
|
29
|
-
|
30
|
-
},
|
31
|
-
|
32
|
-
unmount(fn) {
|
33
|
-
options.unmount = fn
|
28
|
+
node.addEventListener(':mount', fn)
|
34
29
|
},
|
35
30
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
on(eventName, selectorOrCallback, callback) {
|
41
|
-
on(elm, eventName, selectorOrCallback, callback)
|
42
|
-
},
|
31
|
+
/**
|
32
|
+
* @State
|
33
|
+
*/
|
34
|
+
state : {
|
43
35
|
|
44
|
-
|
45
|
-
|
46
|
-
|
36
|
+
save(data) {
|
37
|
+
if( data.constructor === Function ) {
|
38
|
+
data( state )
|
39
|
+
} else {
|
40
|
+
Object.assign(state, data)
|
41
|
+
}
|
42
|
+
},
|
47
43
|
|
48
|
-
|
49
|
-
if (target.constructor === String) {
|
50
|
-
Array
|
51
|
-
.from(elm.querySelectorAll(target))
|
52
|
-
.forEach( children => trigger(children, eventName, { args: args }) )
|
53
|
-
}
|
54
|
-
else trigger(elm, eventName, { args: target })
|
55
|
-
},
|
44
|
+
set( data ) {
|
56
45
|
|
57
|
-
|
58
|
-
|
59
|
-
|
46
|
+
if (!document.body.contains(node)) {
|
47
|
+
return
|
48
|
+
}
|
60
49
|
|
61
|
-
|
62
|
-
|
63
|
-
if (data.constructor === Function) {
|
64
|
-
const newstate = dup(state.data)
|
65
|
-
data(newstate)
|
66
|
-
base.render(newstate)
|
67
|
-
} else {
|
68
|
-
base.render(data)
|
50
|
+
if( data.constructor === Function ) {
|
51
|
+
data( state )
|
69
52
|
}
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
53
|
+
const newstate = Object.assign({}, state)
|
54
|
+
render( newstate )
|
55
|
+
|
56
|
+
updates.push(data)
|
57
|
+
|
58
|
+
return new Promise((resolve) => {
|
59
|
+
rAF(() => rAF(() => {
|
60
|
+
Object.assign.apply(null, [state, ...updates ])
|
61
|
+
if( updates.length ){
|
62
|
+
const newstate = Object.assign({}, state)
|
63
|
+
render(newstate)
|
64
|
+
resolve(newstate)
|
65
|
+
updates = []
|
66
|
+
}
|
67
|
+
}))
|
68
|
+
})
|
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
|
}
|
105
|
+
},
|
86
106
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
Idiomorph.morph(elm, newhtml, IdiomorphOptions(elm))
|
93
|
-
updateScope( elm )
|
107
|
+
off( ev, callback ) {
|
108
|
+
if( callback.handler ) {
|
109
|
+
node.removeEventListener(ev, callback.handler)
|
110
|
+
}
|
111
|
+
},
|
94
112
|
|
95
|
-
|
113
|
+
trigger(ev, selectorOrCallback, data) {
|
114
|
+
if( selectorOrCallback.constructor === String ) {
|
96
115
|
Array
|
97
|
-
.from(
|
98
|
-
.forEach(
|
99
|
-
|
100
|
-
child.options.onupdate(props)
|
101
|
-
child.base.render(props)
|
116
|
+
.from(node.querySelectorAll(selectorOrCallback))
|
117
|
+
.forEach( children => {
|
118
|
+
children.dispatchEvent(new CustomEvent(ev, { bubbles: true, detail: { args: data } }) )
|
102
119
|
})
|
103
|
-
}
|
120
|
+
} else {
|
121
|
+
node.dispatchEvent(new CustomEvent(ev, { bubbles: true, detail:{ args: data } }))
|
122
|
+
}
|
104
123
|
},
|
105
124
|
|
106
|
-
|
125
|
+
emit(ev, data) {
|
126
|
+
node.dispatchEvent(new CustomEvent(ev, { bubbles: true, detail: { args: data } }))
|
127
|
+
},
|
128
|
+
|
129
|
+
unmount( fn ) {
|
130
|
+
node.addEventListener(':unmount', fn)
|
131
|
+
},
|
107
132
|
|
133
|
+
innerHTML ( target, html_ ) {
|
108
134
|
const element = html_? target : elm
|
109
135
|
const clone = element.cloneNode()
|
110
136
|
const html = html_? html_ : target
|
@@ -114,32 +140,34 @@ export default function Component( elm, { module, dependencies, templates, compo
|
|
114
140
|
}
|
115
141
|
}
|
116
142
|
|
117
|
-
|
118
|
-
}
|
143
|
+
const render = ( data ) => {
|
119
144
|
|
120
|
-
const
|
121
|
-
|
122
|
-
unmount: (a) => a,
|
123
|
-
onupdate: (a) => a,
|
124
|
-
view: module.view ? module.view : (a) => a
|
125
|
-
})
|
145
|
+
const html = tpl.render.call( view(data), node, safe, g )
|
146
|
+
Idiomorph.morph( node, html, IdiomorphOptions(node) )
|
126
147
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
148
|
+
node.querySelectorAll('[tplid]').forEach((element) => {
|
149
|
+
if(!element.base) return
|
150
|
+
const base = element.base
|
151
|
+
const props = Object.keys(base.model).reduce((acc, key) => {
|
152
|
+
if( key in data ) {
|
153
|
+
if( !acc ) acc = {}
|
154
|
+
acc[key] = data[key]
|
155
|
+
}
|
156
|
+
return acc
|
157
|
+
}, null)
|
158
|
+
if( props ) {
|
159
|
+
base.state.set( props )
|
133
160
|
}
|
134
161
|
})
|
135
|
-
|
136
|
-
}
|
137
|
-
|
162
|
+
rAF(() => g.scope = {})
|
163
|
+
}
|
138
164
|
|
139
|
-
|
165
|
+
node.base = base
|
166
|
+
module.default( base )
|
167
|
+
}
|
140
168
|
|
169
|
+
const IdiomorphOptions = ( parent ) => ({
|
141
170
|
callbacks: {
|
142
|
-
|
143
171
|
beforeNodeMorphed( node ) {
|
144
172
|
if( node.nodeType === 1 ) {
|
145
173
|
if( 'html-static' in node.attributes ) {
|
package/src/element.ts
CHANGED
@@ -1,14 +1,11 @@
|
|
1
|
-
import Component from './component'
|
2
|
-
import { purge, rAF } from './utils'
|
1
|
+
import { Component } from './component'
|
3
2
|
|
4
|
-
export
|
3
|
+
export const Element = ({ component, templates, start }) => {
|
5
4
|
|
6
|
-
|
5
|
+
const { name, module, dependencies } = component
|
6
|
+
const abortController = new AbortController()
|
7
7
|
|
8
|
-
|
9
|
-
options: any
|
10
|
-
returns : any
|
11
|
-
__events: any
|
8
|
+
return class extends HTMLElement {
|
12
9
|
|
13
10
|
constructor() {
|
14
11
|
super()
|
@@ -16,59 +13,28 @@ export default function Element(module, dependencies, templates, components) {
|
|
16
13
|
|
17
14
|
connectedCallback() {
|
18
15
|
|
19
|
-
|
20
|
-
|
21
|
-
this.base = base
|
22
|
-
this.options = options
|
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
|
16
|
+
if( !this.getAttribute('tplid') ) {
|
17
|
+
start( this.parentNode )
|
36
18
|
}
|
37
19
|
|
38
|
-
|
39
|
-
this
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
20
|
+
Component({
|
21
|
+
node:this,
|
22
|
+
name,
|
23
|
+
module,
|
24
|
+
dependencies,
|
25
|
+
templates,
|
26
|
+
signal: abortController.signal
|
27
|
+
})
|
28
|
+
|
29
|
+
this.dispatchEvent( new CustomEvent(':mount') )
|
30
|
+
this.base.state.set({})
|
47
31
|
|
48
|
-
} else {
|
49
|
-
if( this.base && this.options.main ){
|
50
|
-
const array = this.options.main(this.base)
|
51
|
-
if( array && array.length ) {
|
52
|
-
array.forEach(f => f(this.base))
|
53
|
-
}
|
54
|
-
}
|
55
|
-
}
|
56
32
|
}
|
57
33
|
|
58
34
|
disconnectedCallback() {
|
59
|
-
this.
|
60
|
-
|
61
|
-
|
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
|
35
|
+
this.dispatchEvent( new CustomEvent(':unmount') )
|
36
|
+
abortController.abort()
|
37
|
+
delete this.base
|
72
38
|
}
|
73
39
|
}
|
74
40
|
}
|
package/src/index.ts
CHANGED
@@ -1,42 +1,27 @@
|
|
1
|
-
import {
|
2
|
-
import {
|
3
|
-
import { html, attributes } from '../html'
|
4
|
-
import Element from './element'
|
1
|
+
import { Element } from './element'
|
2
|
+
import { template, templateConfig as config } from './template-system'
|
5
3
|
|
6
|
-
const templates = {}
|
7
4
|
const components = {}
|
8
5
|
|
9
|
-
export {
|
6
|
+
export { publish, subscribe } from './utils/pubsub'
|
10
7
|
|
11
|
-
export
|
12
|
-
|
13
|
-
|
8
|
+
export const templateConfig = (options) => {
|
9
|
+
config( options )
|
10
|
+
}
|
14
11
|
|
15
|
-
|
16
|
-
|
12
|
+
export const register = ( name, module, dependencies ) => {
|
13
|
+
components[ name ] = { name, module, dependencies }
|
14
|
+
}
|
17
15
|
|
18
|
-
|
19
|
-
components[name] = { name, module, dependencies }
|
20
|
-
},
|
16
|
+
export const start = ( target = document.body ) => {
|
21
17
|
|
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
|
-
}
|
18
|
+
const templates = template( target, { components } )
|
31
19
|
|
32
|
-
const registerComponents = () => {
|
33
20
|
Object
|
34
21
|
.values( components )
|
35
|
-
.forEach(
|
36
|
-
|
37
|
-
|
38
|
-
const Base = Element(module, dependencies, templates, components)
|
39
|
-
customElements.define(name, Base)
|
22
|
+
.forEach(({ name, module, dependencies }) => {
|
23
|
+
if( !customElements.get(name) ) {
|
24
|
+
customElements.define( name, Element({ component: { name, module, dependencies }, templates, start }) )
|
40
25
|
}
|
41
|
-
|
26
|
+
})
|
42
27
|
}
|
package/src/template-system.ts
CHANGED
@@ -1,76 +1,194 @@
|
|
1
|
-
import Transpile from './transpile'
|
2
1
|
import { uuid, decodeHTML } from './utils'
|
3
2
|
|
3
|
+
const templates = {}
|
4
|
+
|
4
5
|
const config = {
|
5
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 ), '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 = ( outerHTML ) => {
|
26
|
+
|
27
|
+
const html = transformAttributes( outerHTML )
|
28
|
+
const parsedHtml = JSON.stringify( html )
|
29
|
+
|
30
|
+
return new Function('$element', 'safe', '$g',`
|
19
31
|
var $data = this;
|
20
32
|
with( $data ){
|
21
|
-
var output=${
|
33
|
+
var output=${parsedHtml
|
22
34
|
.replace(/%%_=(.+?)_%%/g, function(_, variable){
|
23
|
-
return '"+safe(function(){return '+
|
35
|
+
return '"+safe(function(){return '+ variable +';})+"'
|
24
36
|
})
|
25
37
|
.replace(/%%_(.+?)_%%/g, function(_, variable){
|
26
|
-
return '";' +
|
38
|
+
return '";' + variable +'\noutput+="'
|
27
39
|
})};return output;
|
28
40
|
}
|
29
41
|
`)
|
30
42
|
}
|
31
43
|
|
32
|
-
|
33
|
-
|
34
|
-
.
|
35
|
-
.
|
44
|
+
const tagElements = ( target, keys ) => {
|
45
|
+
target
|
46
|
+
.querySelectorAll( keys.toString() )
|
47
|
+
.forEach((node) => {
|
48
|
+
if( node.localName === 'template' ) {
|
49
|
+
return tagElements( node.content, keys )
|
50
|
+
}
|
51
|
+
node.setAttribute('tplid', uuid())
|
52
|
+
})
|
53
|
+
}
|
54
|
+
|
55
|
+
const transformAttributes = ( html ) => {
|
56
|
+
|
57
|
+
const regexTags = new RegExp(`\\${config.tags[0]}(.+?)\\${config.tags[1]}`, 'g')
|
58
|
+
|
59
|
+
return html
|
60
|
+
.replace(/jails___scope-id/g, '%%_=$scopeid_%%')
|
61
|
+
.replace(regexTags, '%%_=$1_%%')
|
62
|
+
// Booleans
|
63
|
+
// https://meiert.com/en/blog/boolean-attributes-of-html/
|
64
|
+
.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%%_}_%%`)
|
65
|
+
// The rest
|
66
|
+
.replace(/html-(.*?)=\"(.*?)\"/g, (all, key, value) => {
|
67
|
+
if (key === 'key' || key === 'model' || key === 'scope-id' ) {
|
68
|
+
return all
|
69
|
+
}
|
70
|
+
if (value) {
|
71
|
+
value = value.replace(/^{|}$/g, '')
|
72
|
+
return `${key}="%%_=safe(function(){ return ${value} })_%%"`
|
73
|
+
} else {
|
74
|
+
return all
|
75
|
+
}
|
76
|
+
})
|
77
|
+
}
|
78
|
+
|
79
|
+
const transformTemplate = ( clone ) => {
|
80
|
+
|
81
|
+
clone.querySelectorAll('template, [html-for], [html-if], [html-inner], [html-class]')
|
82
|
+
.forEach(( element ) => {
|
83
|
+
|
84
|
+
const htmlFor = element.getAttribute('html-for')
|
85
|
+
const htmlIf = element.getAttribute('html-if')
|
86
|
+
const htmlInner = element.getAttribute('html-inner')
|
87
|
+
const htmlClass = element.getAttribute('html-class')
|
88
|
+
|
89
|
+
if ( htmlFor ) {
|
90
|
+
|
91
|
+
element.removeAttribute('html-for')
|
92
|
+
|
93
|
+
const split = htmlFor.match(/(.*)\sin\s(.*)/) || ''
|
94
|
+
const varname = split[1]
|
95
|
+
const object = split[2]
|
96
|
+
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] = { ${varname} :${varname}, ${object}: ${object}, $index: $index, $key: $key }; _%%`)
|
97
|
+
const close = document.createTextNode(`%%_ $index++; } })() _%%`)
|
98
|
+
|
99
|
+
wrap(open, element, close)
|
100
|
+
}
|
101
|
+
|
102
|
+
if (htmlIf) {
|
103
|
+
element.removeAttribute('html-if')
|
104
|
+
const open = document.createTextNode(`%%_ if ( safe(function(){ return ${htmlIf} }) ){ _%%`)
|
105
|
+
const close = document.createTextNode(`%%_ } _%%`)
|
106
|
+
wrap(open, element, close)
|
107
|
+
}
|
108
|
+
|
109
|
+
if (htmlInner) {
|
110
|
+
element.removeAttribute('html-inner')
|
111
|
+
element.innerHTML = `%%_=${htmlInner}_%%`
|
112
|
+
}
|
113
|
+
|
114
|
+
if (htmlClass) {
|
115
|
+
element.removeAttribute('html-class')
|
116
|
+
element.className = (element.className + ` %%_=${htmlClass}_%%`).trim()
|
117
|
+
}
|
118
|
+
|
119
|
+
if( element.localName === 'template' ) {
|
120
|
+
transformTemplate(element.content)
|
121
|
+
}
|
122
|
+
})
|
123
|
+
}
|
124
|
+
|
125
|
+
const setTemplates = ( clone, components ) => {
|
126
|
+
|
127
|
+
Array.from(clone.querySelectorAll('[tplid]'))
|
36
128
|
.reverse()
|
37
|
-
.forEach(
|
38
|
-
|
39
|
-
|
129
|
+
.forEach((node) => {
|
130
|
+
|
131
|
+
const tplid = node.getAttribute('tplid')
|
132
|
+
const name = node.localName
|
133
|
+
node.setAttribute('html-scope-id', 'jails___scope-id')
|
134
|
+
|
135
|
+
if( name in components && components[name].module.template ) {
|
136
|
+
const children = node.innerHTML
|
137
|
+
const html = components[name].module.template({ elm:node, children })
|
138
|
+
|
139
|
+
if( html.constructor === Promise ) {
|
140
|
+
html.then( htmlstring => {
|
141
|
+
node.innerHTML = htmlstring
|
142
|
+
const html = node.outerHTML
|
143
|
+
templates[tplid] = {
|
144
|
+
template: html,
|
145
|
+
render: compile(html)
|
146
|
+
}
|
147
|
+
})
|
148
|
+
} else {
|
149
|
+
node.innerHTML = html
|
150
|
+
}
|
151
|
+
}
|
152
|
+
|
153
|
+
const html = node.outerHTML
|
154
|
+
|
155
|
+
templates[ tplid ] = {
|
156
|
+
template: html,
|
157
|
+
render : compile(html)
|
158
|
+
}
|
40
159
|
})
|
41
160
|
}
|
42
161
|
|
43
|
-
const
|
162
|
+
const removeTemplateTagsRecursively = (node) => {
|
44
163
|
|
45
|
-
|
164
|
+
// Get all <template> elements within the node
|
165
|
+
const templates = node.querySelectorAll('template')
|
46
166
|
|
47
|
-
|
48
|
-
const id = uuid()
|
49
|
-
element.setAttribute('tplid', id)
|
50
|
-
const name = element.localName
|
167
|
+
templates.forEach((template) => {
|
51
168
|
|
52
|
-
if(
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
169
|
+
if( template.getAttribute('html-if') || template.getAttribute('html-inner') ) {
|
170
|
+
return
|
171
|
+
}
|
172
|
+
|
173
|
+
// Process any nested <template> tags within this <template> first
|
174
|
+
removeTemplateTagsRecursively(template.content)
|
175
|
+
|
176
|
+
// Get the parent of the <template> tag
|
177
|
+
const parent = template.parentNode
|
178
|
+
|
179
|
+
if (parent) {
|
180
|
+
// Move all child nodes from the <template>'s content to its parent
|
181
|
+
const content = template.content
|
182
|
+
while (content.firstChild) {
|
183
|
+
parent.insertBefore(content.firstChild, template)
|
63
184
|
}
|
185
|
+
// Remove the <template> tag itself
|
186
|
+
parent.removeChild(template)
|
64
187
|
}
|
65
|
-
|
66
|
-
}
|
188
|
+
})
|
67
189
|
}
|
68
190
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
const _if = node.querySelectorAll('[html-if]')
|
73
|
-
_if.forEach( el => {
|
74
|
-
el.parentNode.insertBefore(document.createComment(''), el.nextSibling)
|
75
|
-
})
|
191
|
+
const wrap = (open, node, close) => {
|
192
|
+
node.parentNode?.insertBefore(open, node)
|
193
|
+
node.parentNode?.insertBefore(close, node.nextSibling)
|
76
194
|
}
|