jails-js 6.4.0 → 6.5.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/src/component.ts CHANGED
@@ -106,7 +106,7 @@ export const Component = ({ name, module, dependencies, node, templates, signal,
106
106
 
107
107
  if( attribute ) {
108
108
  observables.push({
109
- target: callback? node.querySelectorAll(selectorOrCallback) : [node],
109
+ target: callback? selectorOrCallback : null,
110
110
  callback: callback || selectorOrCallback
111
111
  })
112
112
 
@@ -117,7 +117,8 @@ export const Component = ({ name, module, dependencies, node, templates, signal,
117
117
  const attrname = mutation.attributeName
118
118
  if( attrname === attribute[1] ) {
119
119
  observables.forEach( item => {
120
- item.target.forEach( target => {
120
+ const target = item.target? node.querySelectorAll(item.target): [node]
121
+ target.forEach( target => {
121
122
  if( target == mutation.target ) {
122
123
  item.callback({
123
124
  target: mutation.target,
@@ -126,7 +127,6 @@ export const Component = ({ name, module, dependencies, node, templates, signal,
126
127
  })
127
128
  }
128
129
  })
129
-
130
130
  })
131
131
  }
132
132
  }
@@ -1,11 +1,14 @@
1
1
  import { uuid, decodeHTML } from './utils'
2
2
 
3
- const templates = {}
4
-
5
3
  const config = {
6
4
  tags: ['{{', '}}']
7
5
  }
8
6
 
7
+ const templates = {}
8
+ const booleanAttrs = /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
9
+ const htmlAttr = /html-([^\s]*?)="(.*?)"/g
10
+ const tagExpr = () => new RegExp(`\\${config.tags[0]}(.+?)\\${config.tags[1]}`, 'g')
11
+
9
12
  export const templateConfig = (newconfig) => {
10
13
  Object.assign( config, newconfig )
11
14
  }
@@ -40,44 +43,36 @@ export const compile = ( html ) => {
40
43
  `)
41
44
  }
42
45
 
43
- const tagElements = ( target, keys, components ) => {
44
- target
45
- .querySelectorAll( keys.toString() )
46
- .forEach((node) => {
47
- const name = node.localName
48
- if( name === 'template' ) {
49
- return tagElements( node.content, keys, components )
50
- }
51
- if( node.getAttribute('html-if') && !node.id ) {
52
- node.id = uuid()
53
- }
54
- if( name in components ) {
55
- node.setAttribute('tplid', uuid())
56
- }
57
- })
58
- }
46
+ const tagElements = (target, keys, components) => {
47
+ const isComponent = key => key in components
48
+ const selector = keys.join(',')
59
49
 
60
- const transformAttributes = ( html ) => {
61
-
62
- const regexTags = new RegExp(`\\${config.tags[0]}(.+?)\\${config.tags[1]}`, 'g')
50
+ target.querySelectorAll(selector).forEach(node => {
51
+ if (node.localName === 'template') {
52
+ tagElements(node.content, keys, components)
53
+ return
54
+ }
55
+ if (node.hasAttribute('html-if') && !node.id) {
56
+ node.id = uuid()
57
+ }
58
+ if (isComponent(node.localName)) {
59
+ node.setAttribute('tplid', uuid())
60
+ }
61
+ })
62
+ }
63
63
 
64
+ const transformAttributes = (html) => {
64
65
  return html
65
66
  .replace(/jails___scope-id/g, '%%_=$scopeid_%%')
66
- .replace(regexTags, '%%_=$1_%%')
67
- // Booleans
68
- // https://meiert.com/en/blog/boolean-attributes-of-html/
69
- .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%%_}_%%`)
70
- // The rest
71
- .replace(/html-([^\s]*?)=\"(.*?)\"/g, (all, key, value) => {
72
- if (key === 'key' || key === 'model' || key === 'scopeid' ) {
73
- return all
74
- }
67
+ .replace(tagExpr(), '%%_=$1_%%')
68
+ .replace(booleanAttrs, `%%_if(safe(function(){ return $2 })){_%%$1%%_}_%%`)
69
+ .replace(htmlAttr, (all, key, value) => {
70
+ if (['key', 'model', 'scopeid'].includes(key)) return all
75
71
  if (value) {
76
72
  value = value.replace(/^{|}$/g, '')
77
73
  return `${key}="%%_=safe(function(){ return ${value} })_%%"`
78
- } else {
79
- return all
80
74
  }
75
+ return all
81
76
  })
82
77
  }
83
78
 
@@ -156,32 +151,27 @@ const setTemplates = ( clone, components ) => {
156
151
  }
157
152
 
158
153
  const removeTemplateTagsRecursively = (node) => {
154
+ const walker = document.createTreeWalker(node, NodeFilter.SHOW_ELEMENT, {
155
+ acceptNode: el => el.tagName === 'TEMPLATE' ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP
156
+ })
159
157
 
160
- // Get all <template> elements within the node
161
- const templates = node.querySelectorAll('template')
162
-
163
- templates.forEach((template) => {
158
+ const templatesToRemove = []
164
159
 
165
- if( template.getAttribute('html-if') || template.getAttribute('html-inner') ) {
166
- return
160
+ while (walker.nextNode()) {
161
+ const tpl = walker.currentNode
162
+ if (!tpl.hasAttribute('html-if') && !tpl.hasAttribute('html-inner')) {
163
+ templatesToRemove.push(tpl)
167
164
  }
165
+ }
168
166
 
169
- // Process any nested <template> tags within this <template> first
170
- removeTemplateTagsRecursively(template.content)
171
-
172
- // Get the parent of the <template> tag
167
+ for (const template of templatesToRemove) {
173
168
  const parent = template.parentNode
169
+ if (!parent) continue
174
170
 
175
- if (parent) {
176
- // Move all child nodes from the <template>'s content to its parent
177
- const content = template.content
178
- while (content.firstChild) {
179
- parent.insertBefore(content.firstChild, template)
180
- }
181
- // Remove the <template> tag itself
182
- parent.removeChild(template)
183
- }
184
- })
171
+ const frag = document.createDocumentFragment()
172
+ frag.append(...template.content.childNodes)
173
+ parent.replaceChild(frag, template)
174
+ }
185
175
  }
186
176
 
187
177
  const wrap = (open, node, close) => {