mi-element 0.9.4 → 0.9.5

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/html.js CHANGED
@@ -33,9 +33,10 @@ const unsafeHtml = str => new UnsafeHtml(str), escMap = {
33
33
  '>': '>',
34
34
  '"': '"',
35
35
  "'": '''
36
- }, esc = string => string.replace(/[&<>"']/g, tag => escMap[tag]), escHtml = string => string instanceof UnsafeHtml ? string : unsafeHtml(esc('' + string)), OBJECT = 'object', FUNCTION = 'function', escValue = any => {
36
+ }, escRe = /[&<>"']/g, esc = string => string.replace(escRe, tag => escMap[tag]), escHtml = string => string instanceof UnsafeHtml ? string : unsafeHtml(esc('' + string)), escValue = any => {
37
37
  if (any instanceof UnsafeHtml) return any;
38
- if ([ OBJECT, FUNCTION ].includes(typeof any)) {
38
+ const t = typeof any;
39
+ if ("object" === t || "function" === t) {
39
40
  const key = globalRenderCache.set(any);
40
41
  return unsafeHtml(key);
41
42
  }
@@ -45,10 +46,9 @@ const unsafeHtml = str => new UnsafeHtml(str), escMap = {
45
46
  }, ...values.map(val => Array.isArray(val) ? val.map(escValue).join('') : escValue(val))));
46
47
 
47
48
  function render(node, template, handlers = {}) {
48
- const refs = {}, div = document.createElement('div');
49
- div.innerHTML = template.toString();
50
- for (let child of Array.from(div.children)) renderAttrs(child, handlers, refs),
51
- node.appendChild(child);
49
+ const refs = {};
50
+ node.innerHTML = template.toString();
51
+ for (let i = 0, l = node.children.length; i < l; i++) renderAttrs(node.children[i], handlers, refs);
52
52
  return refs;
53
53
  }
54
54
 
@@ -56,24 +56,24 @@ const REF = 'ref', REF_Q = '[ref]';
56
56
 
57
57
  function renderAttrs(node, handlers = {}, refs = {}) {
58
58
  if (node.nodeType === Node.ELEMENT_NODE) {
59
- const rmFns = [];
60
- for (let attr of node.attributes) {
61
- const startsWith = attr.name[0], name = attr.name.slice(1);
59
+ const rmAttrs = [], attrs = node.attributes;
60
+ for (let i = 0, l = attrs.length; i < l; i++) {
61
+ const attr = attrs[i], attrName = attr.name, code = attrName.charCodeAt(0), name = attrName.slice(1);
62
62
  let rm = 0;
63
- if ('?' === startsWith) toJson(attr.value) ? node.setAttribute(name, '') : node.removeAttribute(name),
63
+ if (63 === code) toJson(attr.value) ? node.setAttribute(name, '') : node.removeAttribute(name),
64
64
  rm = 1; else if ('...' === attr.name) {
65
65
  const obj = globalRenderCache.get(attr.value);
66
- if (obj && typeof obj === OBJECT) for (const [k, v] of Object.entries(obj)) node[k] = v;
66
+ if (obj && "object" == typeof obj) for (const [k, v] of Object.entries(obj)) node[k] = v;
67
67
  rm = 1;
68
- } else if ('.' === startsWith) node[name] = globalRenderCache.get(attr.value) ?? attr.value,
69
- rm = 1; else if ('@' === startsWith) {
68
+ } else if (46 === code) node[name] = globalRenderCache.get(attr.value) ?? attr.value,
69
+ rm = 1; else if (64 === code) {
70
70
  const handlerName = attr.value, fn = globalRenderCache.get(handlerName);
71
- fn ? node.addEventListener(name, e => fn(e)) : typeof handlers[handlerName] === FUNCTION && node.addEventListener(name, e => handlers[handlerName](e)),
71
+ fn ? node.addEventListener(name, fn) : "function" == typeof handlers[handlerName] && node.addEventListener(name, handlers[handlerName]),
72
72
  rm = 1;
73
73
  } else attr.name === REF && (refs[attr.value] = node, rm = 1);
74
- rm && rmFns.push([ node, attr.name ]);
74
+ rm && rmAttrs.push(attr.name);
75
75
  }
76
- rmFns.forEach(([node, name]) => node.removeAttribute(name));
76
+ for (let i = 0, l = rmAttrs.length; i < l; i++) node.removeAttribute(rmAttrs[i]);
77
77
  }
78
78
  if (customElements.get(node.localName)) {
79
79
  const q = node.querySelectorAll(REF_Q);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mi-element",
3
- "version": "0.9.4",
3
+ "version": "0.9.5",
4
4
  "description": "Build lightweight reactive micro web-components",
5
5
  "keywords": [],
6
6
  "homepage": "https://github.com/commenthol/mi-element/tree/main/packages/mi-element#readme",
package/src/html.js CHANGED
@@ -63,7 +63,9 @@ const escMap = {
63
63
  "'": '&#39;'
64
64
  }
65
65
 
66
- const esc = (string) => string.replace(/[&<>"']/g, (tag) => escMap[tag])
66
+ const escRe = /[&<>"']/g
67
+
68
+ const esc = (string) => string.replace(escRe, (tag) => escMap[tag])
67
69
 
68
70
  /**
69
71
  * escape HTML and prevent double escaping of '&'
@@ -90,7 +92,8 @@ const escValue = (any) => {
90
92
  // @ts-expect-error
91
93
  return any
92
94
  }
93
- if ([OBJECT, FUNCTION].includes(typeof any)) {
95
+ const t = typeof any
96
+ if (t === OBJECT || t === FUNCTION) {
94
97
  const key = globalRenderCache.set(any)
95
98
  return unsafeHtml(key)
96
99
  }
@@ -120,20 +123,18 @@ export const html = (strings, ...values) =>
120
123
  /**
121
124
  * render HTML template into given node with support for special attributes
122
125
  *
123
- * @param {Element} node to append rendered content
126
+ * @param {Element} node to render content
124
127
  * @param {string|UnsafeHtml} template HTML template string
125
128
  * @param {Record<string, Function>|HTMLElement} [handlers={}] event handlers or HTMLElement for method lookup
126
129
  * @returns {Record<string, Element>} references collected
127
130
  */
128
131
  export function render(node, template, handlers = {}) {
129
132
  const refs = {}
130
- const div = document.createElement('div')
131
- div.innerHTML = template.toString()
132
- // don't understand why `for (let child of div.children)` does not work here
133
- for (let child of Array.from(div.children)) {
133
+ node.innerHTML = template.toString()
134
+ for (let i = 0, l = node.children.length; i < l; i++) {
135
+ const child = node.children[i]
134
136
  // @ts-expect-error
135
137
  renderAttrs(child, handlers, refs)
136
- node.appendChild(child)
137
138
  }
138
139
  // @ts-expect-error
139
140
  return refs
@@ -162,12 +163,15 @@ const REF_Q = '[ref]'
162
163
  */
163
164
  export function renderAttrs(node, handlers = {}, refs = {}) {
164
165
  if (node.nodeType === Node.ELEMENT_NODE) {
165
- const rmFns = []
166
- for (let attr of node.attributes) {
167
- const startsWith = attr.name[0]
168
- const name = attr.name.slice(1)
166
+ const rmAttrs = []
167
+ const attrs = node.attributes
168
+ for (let i = 0, l = attrs.length; i < l; i++) {
169
+ const attr = attrs[i]
170
+ const attrName = attr.name
171
+ const code = attrName.charCodeAt(0)
172
+ const name = attrName.slice(1)
169
173
  let rm = 0
170
- if (startsWith === '?') {
174
+ if (code === 63 /* '?' */) {
171
175
  // boolean attributes
172
176
  if (toJson(attr.value)) {
173
177
  node.setAttribute(name, '')
@@ -184,32 +188,32 @@ export function renderAttrs(node, handlers = {}, refs = {}) {
184
188
  }
185
189
  }
186
190
  rm = 1
187
- } else if (startsWith === '.') {
191
+ } else if (code === 46 /* '.' */) {
188
192
  // property binding
189
193
  node[name] = globalRenderCache.get(attr.value) ?? attr.value
190
194
  rm = 1
191
- } else if (startsWith === '@') {
195
+ } else if (code === 64 /* '@' */) {
192
196
  // event listener
193
197
  const handlerName = attr.value
194
198
  const fn = globalRenderCache.get(handlerName)
195
199
  if (fn) {
196
- node.addEventListener(name, (e) => fn(e))
200
+ node.addEventListener(name, fn)
197
201
  } else if (typeof handlers[handlerName] === FUNCTION) {
198
- node.addEventListener(name, (e) => handlers[handlerName](e))
202
+ node.addEventListener(name, handlers[handlerName])
199
203
  }
200
204
  rm = 1
201
205
  } else if (attr.name === REF) {
202
206
  // element reference - remove as well to prevent collection by other processors
203
- const refName = attr.value
204
- refs[refName] = node
207
+ refs[attr.value] = node
205
208
  rm = 1
206
209
  }
207
210
  if (rm) {
208
- rmFns.push([node, attr.name])
211
+ rmAttrs.push(attr.name)
209
212
  }
210
213
  }
211
- // @ts-expect-error
212
- rmFns.forEach(([node, name]) => node.removeAttribute(name))
214
+ for (let i = 0, l = rmAttrs.length; i < l; i++) {
215
+ node.removeAttribute(rmAttrs[i])
216
+ }
213
217
  }
214
218
  // early abort if custom element but resolve slotted refs
215
219
  if (customElements.get(node.localName)) {
package/types/html.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * render HTML template into given node with support for special attributes
3
3
  *
4
- * @param {Element} node to append rendered content
4
+ * @param {Element} node to render content
5
5
  * @param {string|UnsafeHtml} template HTML template string
6
6
  * @param {Record<string, Function>|HTMLElement} [handlers={}] event handlers or HTMLElement for method lookup
7
7
  * @returns {Record<string, Element>} references collected