atoms-element v5.0.0

#js

git clone https://git.pyrossh.dev/atoms-element

A simple web component library for defining your custom elements. It works on both client and server.


2124035Peter John 2026-08-08T12:04:26+05:30
fix arrays
Files changed (3) hide show
  1. index.js +9 -1
  2. index.test.js +10 -0
  3. index.test.js.snapshot +4 -0
index.js CHANGED
@@ -96,7 +96,15 @@ const parseTag = (tag) => {
96
96
 
97
97
  return res;
98
98
  };
99
+ // @lit-labs/ssr's escapeHtml (see its util/escape-html.js) unconditionally
100
+ // escapes &<>"' in attribute values, including the single quotes jsonAttr
101
+ // emits in place of JSON's double quotes — so a jsonAttr-bound object/array
102
+ // attr comes back through expandCustomElements's re-parsed HTML as literal
103
+ // "&#39;" sequences, not real quotes, and must be decoded before JSON.parse.
104
+ const htmlEntities = { amp: '&', lt: '<', gt: '>', quot: '"', '#39': "'" };
105
+ const unescapeHtml = (value) => value.replace(/&(amp|lt|gt|quot|#39);/g, (_, entity) => htmlEntities[entity]);
106
+ const parseAttrValue = (value) =>
99
- const parseAttrValue = (value) => (value && value.startsWith('{') ? JSON.parse(value.replace(/'/g, '"')) : value);
107
+ value && (value.startsWith('{') || value.startsWith('[')) ? JSON.parse(unescapeHtml(value).replace(/'/g, '"')) : value;
100
108
 
101
109
  // Used by createElement's attrs handling: unlike prop's sniffed
102
110
  // coercePropValue below, the type here is declared explicitly (as the
index.test.js CHANGED
@@ -127,6 +127,16 @@ test('watch resolves attribute values from preceding SSR markup via cheerio', (t
127
127
  t.assert.snapshot(res);
128
128
  });
129
129
 
130
+ test('jsonAttr round-trips array attrs through SSR expansion', (t) => {
131
+ const TagList = ({ tags }) => html`<ul>${tags.value.map((tag) => html`<li>${tag}</li>`)}</ul>`;
132
+ TagList.attrs = { tags: Array };
133
+ createElement({ url: '/tag-list.js' }, TagList);
134
+
135
+ const template = html`<tag-list tags=${jsonAttr(['rust', 'js'])}></tag-list>`;
136
+ const res = renderHtml(template);
137
+ t.assert.snapshot(res);
138
+ });
139
+
130
140
  test('createElement without attrs', (t) => {
131
141
  createElement({ url: '/base-element.js' }, () => {
132
142
  return html` <div></div> `;
index.test.js.snapshot CHANGED
@@ -18,6 +18,10 @@ exports[`css tagged template 1`] = `
18
18
  "\\n :scope {\\n display: flex;\\n }\\n button {\\n color: magenta;\\n }\\n "
19
19
  `;
20
20
 
21
+ exports[`jsonAttr round-trips array attrs through SSR expansion 1`] = `
22
+ "<!--lit-part BlC1BjVGRpM=--><!--lit-node 0--><tag-list tags=\\"[&#39;rust&#39;,&#39;js&#39;]\\"><!--lit-part om80B80ddXw=--><ul><!--lit-part--><!--lit-part PuAyB/F8cHw=--><li><!--lit-part-->rust<!--/lit-part--></li><!--/lit-part--><!--lit-part PuAyB/F8cHw=--><li><!--lit-part-->js<!--/lit-part--></li><!--/lit-part--><!--/lit-part--></ul><!--/lit-part--></tag-list><!--/lit-part-->"
23
+ `;
24
+
21
25
  exports[`render attribute keys 1`] = `
22
26
  "<!--lit-part Jm3yLdRDsSk=-->\\n <div>\\n <app-counter name=\\"123\\" perPage=\\"1\\"></app-counter>\\n </div>\\n <!--/lit-part-->"
23
27
  `;