mi-element 0.9.2 → 0.9.3

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
@@ -2,21 +2,26 @@ import { toJson } from './utils.js';
2
2
 
3
3
  const globalRenderCache = new class {
4
4
  cnt=0;
5
- map=new Map;
6
- cache=new WeakMap;
5
+ cache=new Map;
6
+ last=0;
7
+ get size() {
8
+ return this.cache.size;
9
+ }
7
10
  _inc() {
8
11
  return this.cnt = 268435455 & ++this.cnt, this.cnt;
9
12
  }
10
13
  clear() {
11
- this.cnt = 0, this.map.clear();
14
+ this.cnt = 0, this.cache.clear();
12
15
  }
13
16
  set(value) {
14
- const key = '__rc:' + this._inc().toString(36), ref = {};
15
- return this.map.set(key, ref), this.cache.set(ref, value), key;
17
+ const now = Date.now();
18
+ this.last < now && this.cache.clear(), this.last = now + 5e3;
19
+ const key = '__rc:' + this._inc().toString(36);
20
+ return this.cache.set(key, value), key;
16
21
  }
17
22
  get(key) {
18
- const ref = this.map.get(key);
19
- return this.map.delete(key), this.cache.get(ref);
23
+ const value = this.cache.get(key);
24
+ return this.cache.delete(key), value;
20
25
  }
21
26
  };
22
27
 
package/dist/index.js CHANGED
@@ -8,6 +8,6 @@ export { refsBySelector } from './refs.js';
8
8
 
9
9
  export { Store } from './store.js';
10
10
 
11
- export { addGlobalStyles, classNames, css, styleMap } from './styling.js';
11
+ export { addGlobalStyles, classNames, css, escCss, styleMap, unsafeCss } from './styling.js';
12
12
 
13
13
  export { default as Signal } from 'mi-signal';
package/dist/styling.js CHANGED
@@ -3,7 +3,7 @@ import { camelToKebabCase } from './case.js';
3
3
  const classNames = (...args) => {
4
4
  const classList = [];
5
5
  return args.forEach(arg => {
6
- arg && ('string' == typeof arg ? classList.push(arg) : Array.isArray(arg) ? classList.push(classNames(...arg)) : 'object' == typeof arg && Object.entries(arg).forEach(([key, value]) => {
6
+ arg && ('string' == typeof arg ? classList.push(arg) : 'object' == typeof arg && Object.entries(arg).forEach(([key, value]) => {
7
7
  value && classList.push(key);
8
8
  }));
9
9
  }), classList.join(' ');
@@ -26,8 +26,14 @@ function addGlobalStyles(renderRoot) {
26
26
  })), globalSheets));
27
27
  }
28
28
 
29
- const css = (strings, ...values) => String.raw({
29
+ class UnsafeCss extends String {}
30
+
31
+ const unsafeCss = str => new UnsafeCss(str), escMap = {
32
+ '&': '\\26 ',
33
+ '<': '\\3c ',
34
+ '>': '\\3e '
35
+ }, escCss = string => string instanceof UnsafeCss ? string : unsafeCss((string => string.replace(/[&<>]/g, tag => escMap[tag]))('' + string)), css = (strings, ...values) => String.raw({
30
36
  raw: strings
31
- }, ...values);
37
+ }, ...values.map(escCss));
32
38
 
33
- export { addGlobalStyles, classNames, css, styleMap };
39
+ export { addGlobalStyles, classNames, css, escCss, styleMap, unsafeCss };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mi-element",
3
- "version": "0.9.2",
3
+ "version": "0.9.3",
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
@@ -5,8 +5,12 @@ import { toJson } from './utils.js'
5
5
  */
6
6
  class RenderCache {
7
7
  cnt = 0
8
- map = new Map()
9
- cache = new WeakMap()
8
+ cache = new Map()
9
+ last = 0
10
+
11
+ get size() {
12
+ return this.cache.size
13
+ }
10
14
 
11
15
  _inc() {
12
16
  this.cnt = ++this.cnt & 0xfffffff
@@ -15,21 +19,24 @@ class RenderCache {
15
19
 
16
20
  clear() {
17
21
  this.cnt = 0
18
- this.map.clear()
22
+ this.cache.clear()
19
23
  }
20
24
 
21
25
  set(value) {
26
+ const now = Date.now()
27
+ if (this.last < now) {
28
+ this.cache.clear()
29
+ }
30
+ this.last = now + 5e3
22
31
  const key = '__rc:' + this._inc().toString(36)
23
- const ref = {}
24
- this.map.set(key, ref)
25
- this.cache.set(ref, value)
32
+ this.cache.set(key, value)
26
33
  return key
27
34
  }
28
35
 
29
36
  get(key) {
30
- const ref = this.map.get(key)
31
- this.map.delete(key)
32
- return this.cache.get(ref)
37
+ const value = this.cache.get(key)
38
+ this.cache.delete(key)
39
+ return value
33
40
  }
34
41
  }
35
42
 
package/src/index.js CHANGED
@@ -10,11 +10,18 @@ export {
10
10
  * @typedef {import('./element.js').HostController} HostController
11
11
  */
12
12
  export { MiElement, convertType, define } from './element.js'
13
- export { unsafeHtml, html, escHtml, render, renderAttrs } from './html.js'
13
+ export { html, unsafeHtml, escHtml, render, renderAttrs } from './html.js'
14
14
  export { refsBySelector } from './refs.js'
15
15
  /**
16
16
  * @typedef {import('./store.js').Action} Action
17
17
  */
18
18
  export { Store } from './store.js'
19
- export { classNames, styleMap, addGlobalStyles, css } from './styling.js'
19
+ export {
20
+ classNames,
21
+ styleMap,
22
+ addGlobalStyles,
23
+ css,
24
+ unsafeCss,
25
+ escCss
26
+ } from './styling.js'
20
27
  export { default as Signal } from 'mi-signal'
package/src/styling.js CHANGED
@@ -11,8 +11,6 @@ export const classNames = (...args) => {
11
11
  if (!arg) return
12
12
  if (typeof arg === 'string') {
13
13
  classList.push(arg)
14
- } else if (Array.isArray(arg)) {
15
- classList.push(classNames(...arg))
16
14
  } else if (typeof arg === 'object') {
17
15
  Object.entries(arg).forEach(([key, value]) => {
18
16
  if (value) {
@@ -77,9 +75,41 @@ export function addGlobalStyles(renderRoot) {
77
75
  renderRoot.adoptedStyleSheets.push(...getGlobalStyleSheets())
78
76
  }
79
77
 
78
+ /**
79
+ * A helper class to avoid double escaping of HTML strings
80
+ */
81
+ class UnsafeCss extends String {}
82
+
83
+ /**
84
+ * tag a string as css for not to be escaped
85
+ * @param {string} str
86
+ * @returns {string}
87
+ */
88
+ // @ts-expect-error
89
+ export const unsafeCss = (str) => new UnsafeCss(str)
90
+
91
+ const escMap = {
92
+ '&': '\\26 ',
93
+ '<': '\\3c ',
94
+ '>': '\\3e '
95
+ }
96
+
97
+ const esc = (string) => string.replace(/[&<>]/g, (tag) => escMap[tag])
98
+
99
+ /**
100
+ * @see https://mathiasbynens.be/notes/css-escapes
101
+ * Escape a value interpolated into a css tagged template literal.
102
+ * Prevents injection of closing style tags or unexpected CSS constructs.
103
+ * @param {*} string
104
+ * @returns {string}
105
+ */
106
+ export const escCss = (string) =>
107
+ // @ts-expect-error
108
+ string instanceof UnsafeCss ? string : unsafeCss(esc('' + string))
109
+
80
110
  /**
81
111
  * Helper literal to show css styles in JS e.g. with
82
112
  * https://marketplace.visualstudio.com/items?itemName=Tobermory.es6-string-html
83
113
  */
84
114
  export const css = (strings, ...values) =>
85
- String.raw({ raw: strings }, ...values)
115
+ String.raw({ raw: strings }, ...values.map(escCss))
package/types/html.d.ts CHANGED
@@ -40,8 +40,9 @@ declare class UnsafeHtml extends String {
40
40
  */
41
41
  declare class RenderCache {
42
42
  cnt: number;
43
- map: Map<any, any>;
44
- cache: WeakMap<WeakKey, any>;
43
+ cache: Map<any, any>;
44
+ last: number;
45
+ get size(): number;
45
46
  _inc(): number;
46
47
  clear(): void;
47
48
  set(value: any): string;
package/types/index.d.ts CHANGED
@@ -6,5 +6,5 @@ export type HostController = import("./element.js").HostController;
6
6
  export type Action = import("./store.js").Action;
7
7
  export { ContextConsumer, ContextProvider, ContextRequestEvent } from "./context.js";
8
8
  export { MiElement, convertType, define } from "./element.js";
9
- export { unsafeHtml, html, escHtml, render, renderAttrs } from "./html.js";
10
- export { classNames, styleMap, addGlobalStyles, css } from "./styling.js";
9
+ export { html, unsafeHtml, escHtml, render, renderAttrs } from "./html.js";
10
+ export { classNames, styleMap, addGlobalStyles, css, unsafeCss, escCss } from "./styling.js";
@@ -15,4 +15,6 @@ export function styleMap(map: {
15
15
  }, options?: {
16
16
  unit?: string | undefined;
17
17
  }): string;
18
+ export function unsafeCss(str: string): string;
19
+ export function escCss(string: any): string;
18
20
  export function css(strings: any, ...values: any[]): string;