@sitecore-feaas/clientside 0.1.45 → 0.1.46

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.
Files changed (60) hide show
  1. package/build/dom/html.js +287 -0
  2. package/build/dom/html.js.map +1 -0
  3. package/build/dom/rendering.js +4 -4
  4. package/build/dom/rendering.js.map +1 -1
  5. package/build/dom/scripts.js +2 -2
  6. package/build/dom/scripts.js.map +1 -1
  7. package/build/ui/FEAASContext.js +2 -2
  8. package/build/ui/FEAASContext.js.map +1 -1
  9. package/build/ui/react.js +3 -1
  10. package/build/ui/react.js.map +1 -1
  11. package/dist/browser/headless.cjs +5 -5
  12. package/dist/browser/headless.cjs.map +4 -4
  13. package/dist/browser/headless.esm.js +5 -5
  14. package/dist/browser/headless.esm.js.map +1 -1
  15. package/dist/browser/index.cjs +5 -5
  16. package/dist/browser/index.cjs.map +4 -4
  17. package/dist/browser/index.esm.js +5 -5
  18. package/dist/browser/index.esm.js.map +1 -1
  19. package/dist/browser/react.cjs +5 -5
  20. package/dist/browser/react.cjs.map +4 -4
  21. package/dist/browser/react.esm.js +5 -5
  22. package/dist/browser/react.esm.js.map +1 -1
  23. package/dist/node/headless.cjs +3 -3
  24. package/dist/node/headless.cjs.map +4 -4
  25. package/dist/node/headless.esm.js +3 -3
  26. package/dist/node/headless.esm.js.map +4 -4
  27. package/dist/node/index.cjs +3 -3
  28. package/dist/node/index.cjs.map +4 -4
  29. package/dist/node/index.esm.js +3 -3
  30. package/dist/node/index.esm.js.map +4 -4
  31. package/dist/node/react.cjs +3 -3
  32. package/dist/node/react.cjs.map +4 -4
  33. package/dist/node/react.esm.js +3 -3
  34. package/dist/node/react.esm.js.map +4 -4
  35. package/headless.cjs +3 -3
  36. package/headless.cjs.map +4 -4
  37. package/headless.js +3 -3
  38. package/headless.js.map +4 -4
  39. package/package.json +1 -4
  40. package/react.cjs +5 -5
  41. package/react.cjs.map +4 -4
  42. package/react.js +5 -5
  43. package/react.js.map +4 -4
  44. package/scripts/build.js +1 -9
  45. package/src/dom/html.ts +322 -0
  46. package/src/dom/rendering.ts +5 -5
  47. package/src/dom/scripts.ts +3 -3
  48. package/src/ui/FEAASContext.tsx +2 -2
  49. package/src/ui/react.tsx +4 -1
  50. package/test/FEAASComponent.react.test.tsx +109 -0
  51. package/test/FEAASContext.test.tsx +2 -2
  52. package/test/dom.test.ts +36 -25
  53. package/types/dom/html.d.ts +45 -0
  54. package/types/dom/html.d.ts.map +1 -0
  55. package/types/dom/rendering.d.ts +1 -1
  56. package/types/dom/rendering.d.ts.map +1 -1
  57. package/types/tsbuildinfo +1 -1
  58. package/types/tsbuildinfo_ui +1 -1
  59. package/types/ui/react.d.ts +2 -0
  60. package/types/ui/react.d.ts.map +1 -1
package/test/dom.test.ts CHANGED
@@ -1,22 +1,14 @@
1
1
  import { JSDOM } from 'jsdom'
2
2
  import * as FEAAS from '../src/headless.js'
3
- import * as FEAASServerSide from '../src/node.js'
3
+ import * as FEAASReact from '../src/ui/react.js'
4
4
  import { describe, it, assert, beforeAll } from 'vitest'
5
- import { parseHTML } from 'linkedom'
6
-
7
- export function renderHTMLContentFallback(
8
- template: string,
9
- data?: FEAAS.Datascopes,
10
- config?: FEAAS.FEAASCustomizations
11
- ) {
12
- const newTemplate = config?.processTemplate?.(null, template, data) || template
13
- const { document } = parseHTML(newTemplate)
14
- return FEAAS.renderDOMElement(document, data, config).toString()
15
- }
5
+ import { parseHTML, serializeHTML } from '../src/dom/html.js'
16
6
 
17
7
  function assertScriptLoaded(element: HTMLElement, src: string) {
18
8
  assert.equal(
19
- Array.prototype.find.call(element.querySelectorAll('script'), (s: HTMLScriptElement) => s.src == src)?.src,
9
+ Array.prototype.find
10
+ .call(element.querySelectorAll('script'), (s: HTMLScriptElement) => s.getAttribute('src') == src)
11
+ ?.getAttribute('src'),
20
12
  src
21
13
  )
22
14
  }
@@ -29,9 +21,10 @@ function normalize(str: string) {
29
21
  .replace(/\n+/g, '\n')
30
22
  .replace(/<\//g, '\n</')
31
23
  .replace(/<\/?body[^>]*>/g, '')
24
+ .replace(/<img([^>]*?) ?\/?>/gi, '<img$1 />')
32
25
  // sort attributes
33
- .replace(/<([a-z0-9-]+) ([^>]+?)(\s?\/?)>/g, (m, tag, attrs: string, closer = '') => {
34
- const matches = attrs.match(/(\S+)=["']((?:.(?!["']\s+(?:\S+)=|\s*\/?[>"']))+.)["']/g)
26
+ .replace(/<([a-z0-9-]+) ([^>]+?)(\s?\/?)>/g, (m, tag, attrs, closer = '') => {
27
+ const matches = attrs.match(/\b([\w-]+)(?:\s*=\s*("[^"]*"|'[^']*'|[^'">\s]+))?/g)
35
28
  if (!matches) return m
36
29
  matches.sort()
37
30
  return '<' + tag + ' ' + matches.join(' ') + closer + '>'
@@ -51,18 +44,36 @@ function assertRenderedHTML(
51
44
  ) {
52
45
  const element = doc.createElement('body')
53
46
  const rendered = FEAAS.renderDOMContent(element, input, data, customizations)
54
- const expectation = normalize(new JSDOM(expected).window.document.body.outerHTML)
55
- assert.equal(normalize(rendered?.outerHTML), expectation)
47
+ assert.equal(normalize(rendered?.outerHTML), normalize(expected))
56
48
  if (scripts) {
57
49
  scripts.map((s) => assertScriptLoaded(rendered, s))
58
50
  }
59
51
 
60
52
  if (!ignoreHTML) {
61
- assert.equal(normalize(FEAAS.renderHTMLContent('<body>' + input + '</body>', data, customizations)), expectation)
53
+ assert.equal(normalize(FEAAS.renderHTMLContent(input, data, customizations)), normalize(expected))
62
54
 
63
- assert.equal(normalize(renderHTMLContentFallback('<body>' + input + '</body>', data, customizations)), expectation)
55
+ assert.equal(
56
+ normalize(FEAASReact.renderHTMLContent('<body>' + input + '</body>', data, customizations)),
57
+ normalize('<body>' + expected + '</body>')
58
+ )
64
59
  }
65
60
  }
61
+ describe('HTML Parser', () => {
62
+ it('should handle basic parsing', function () {
63
+ const testCases = [
64
+ '<div id="container"><span>Hello</span> World</div>',
65
+ '<ul><li>Item 1</li><li>Item 2</li></ul>',
66
+ '<a href="https://example.com">Visit our site</a>',
67
+ '<p title="A &quot;quote&quot; inside an attribute">Text with "quote"</p>',
68
+ '<div onclick="alert(&#x27;Hello &amp; welcome!&#x27;)">Click me</div>',
69
+ '<input type="text" value="&amp;&quot;&#x27;" />',
70
+ 'Text &amp; <strong>HTML</strong> mixed'
71
+ ]
72
+ testCases.forEach((c: string) => {
73
+ assert.equal(serializeHTML(parseHTML(c)), c)
74
+ })
75
+ })
76
+ })
66
77
  describe('DOM Clientside', function () {
67
78
  describe('render without data', function () {
68
79
  it('should render element', function () {
@@ -170,21 +181,21 @@ describe('DOM Clientside', function () {
170
181
  assertRenderedHTML(
171
182
  `<div><a><var data-path-href="image" data-path="image"></var></a></div>`,
172
183
  { image: 'a.jpg' },
173
- '<div><a href="a.jpg"><var data-path-href="image" data-path="image">a.jpg</a></div>'
184
+ '<div><a href="a.jpg"><var data-path-href="image" data-path="image">a.jpg</var></a></div>'
174
185
  )
175
186
  })
176
187
  it('should fill child element via attribute', function () {
177
188
  assertRenderedHTML(
178
189
  `<div data-path-href="image"><a><var data-path="image"></var></a></div>`,
179
190
  { image: 'a.jpg' },
180
- '<div data-path-href="image"><a href="a.jpg"><var data-path="image">a.jpg</a></div>'
191
+ '<div data-path-href="image"><a href="a.jpg"><var data-path="image">a.jpg</var></a></div>'
181
192
  )
182
193
  })
183
194
  it('should fill image element via attribute', function () {
184
195
  assertRenderedHTML(
185
196
  `<div data-path-href="image"><a><var data-path="image"></var></a></div>`,
186
197
  { image: 'a.jpg' },
187
- '<div data-path-href="image"><a href="a.jpg"><var data-path="image">a.jpg</a></div>'
198
+ '<div data-path-href="image"><a href="a.jpg"><var data-path="image">a.jpg</var></a></div>'
188
199
  )
189
200
  })
190
201
  })
@@ -845,7 +856,7 @@ describe('DOM Clientside', function () {
845
856
  describe('Various examples', () => {
846
857
  it('should render custom web components', () => {
847
858
  assertRenderedHTML(
848
- `<bx-accordion class='-embed' data-embed-src="https://1.www.s81c.com/common/carbon/web-components/version/v1.21.0/accordion.min.js">
859
+ `<bx-accordion class="-embed" data-embed-src="https://1.www.s81c.com/common/carbon/web-components/version/v1.21.0/accordion.min.js">
849
860
  <bx-accordion-item data-path-scope="dominatorData.items.*" data-path-attributes="dominatorData.items.*">
850
861
  </bx-accordion-item>
851
862
  </bx-accordion>`,
@@ -867,8 +878,8 @@ describe('DOM Clientside', function () {
867
878
  ]
868
879
  }
869
880
  },
870
- `<bx-accordion class='-embed' data-embed-src="https://1.www.s81c.com/common/carbon/web-components/version/v1.21.0/accordion.min.js">
871
- <bx-accordion-item data-path-scope="dominatorData.items.*" data-path-attributes="dominatorData.items.*" title-text="Hello world" open data-attributes-keys="title-text,html,open">
881
+ `<bx-accordion class="-embed" data-embed-src="https://1.www.s81c.com/common/carbon/web-components/version/v1.21.0/accordion.min.js">
882
+ <bx-accordion-item data-path-scope="dominatorData.items.*" data-path-attributes="dominatorData.items.*" title-text="Hello world" open="" data-attributes-keys="title-text,html,open">
872
883
  Hola
873
884
  </bx-accordion-item>
874
885
  <bx-accordion-item data-path-scope="dominatorData.items.*" data-path-attributes="dominatorData.items.*" title-text="Bye world" data-attributes-keys="title-text,html">
@@ -0,0 +1,45 @@
1
+ /** Lightweight DOM parser and serializer to use in server environments */
2
+ import { Datascopes } from './data.js';
3
+ import { FEAASCustomizations } from './rendering.js';
4
+ type HTMLAttribute = {
5
+ name: string;
6
+ value: string;
7
+ };
8
+ declare class HTMLNode {
9
+ nodeName: string;
10
+ nodeType: number;
11
+ textContent?: string;
12
+ attributes: HTMLAttribute[];
13
+ childNodes: HTMLNode[];
14
+ parentNode?: HTMLNode;
15
+ constructor(nodeName: string, nodeType?: number, textContent?: string);
16
+ setAttribute(name: string, value: string): void;
17
+ getAttribute(name: string): string | undefined;
18
+ insertBefore(newNode: HTMLNode, referenceNode: HTMLNode | null): void;
19
+ removeAttribute(attrName: string): void;
20
+ appendChild(newNode: HTMLNode): void;
21
+ get tagName(): string;
22
+ get innerHTML(): string;
23
+ set innerHTML(html: string);
24
+ get outerHTML(): string;
25
+ closest(selector: string): HTMLNode | null;
26
+ querySelectorAll(selector: string): HTMLNode[];
27
+ querySelector(selector: string): HTMLNode;
28
+ private findSibling;
29
+ removeChild(child: HTMLNode): HTMLNode;
30
+ get previousSibling(): HTMLNode | null;
31
+ get nextSibling(): HTMLNode | null;
32
+ get previousElementSibling(): HTMLNode | null;
33
+ get nextElementSibling(): HTMLNode | null;
34
+ cloneNode(deep?: boolean): HTMLNode;
35
+ get parentElement(): HTMLNode;
36
+ ownerDocument: {
37
+ createElement(name: string): HTMLNode;
38
+ };
39
+ }
40
+ export declare function parseHTML(html: string): HTMLNode[];
41
+ export declare function escapeHTML(input: string): string;
42
+ export declare function serializeHTML(nodes: HTMLNode[]): string;
43
+ export declare function renderHTMLContent(template: string, data?: Datascopes, config?: FEAASCustomizations): string;
44
+ export {};
45
+ //# sourceMappingURL=html.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../../src/dom/html.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAE1E,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AACtC,OAAO,EAAE,mBAAmB,EAAoB,MAAM,gBAAgB,CAAA;AAEtE,KAAK,aAAa,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;AAEpD,cAAM,QAAQ;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,EAAE,aAAa,EAAE,CAAA;IAC3B,UAAU,EAAE,QAAQ,EAAE,CAAA;IACtB,UAAU,CAAC,EAAE,QAAQ,CAAA;gBAET,QAAQ,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAU,EAAE,WAAW,CAAC,EAAE,MAAM;IAQxE,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IASxC,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAK9C,YAAY,CAAC,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,QAAQ,GAAG,IAAI;IAY9D,eAAe,CAAC,QAAQ,EAAE,MAAM;IAOhC,WAAW,CAAC,OAAO,EAAE,QAAQ;IAK7B,IAAI,OAAO,WAEV;IACD,IAAI,SAAS,IAGO,MAAM,CADzB;IACD,IAAI,SAAS,CAAC,IAAI,EAAE,MAAM,EAEzB;IACD,IAAI,SAAS,WAEZ;IAED,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI;IAc1C,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,EAAE;IAwB9C,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ;IAIzC,OAAO,CAAC,WAAW;IAgBnB,WAAW,CAAC,KAAK,EAAE,QAAQ,GAAG,QAAQ;IAQtC,IAAI,eAAe,IAAI,QAAQ,GAAG,IAAI,CAErC;IAED,IAAI,WAAW,IAAI,QAAQ,GAAG,IAAI,CAEjC;IAED,IAAI,sBAAsB,IAAI,QAAQ,GAAG,IAAI,CAE5C;IAED,IAAI,kBAAkB,IAAI,QAAQ,GAAG,IAAI,CAExC;IACD,SAAS,CAAC,IAAI,GAAE,OAAe,GAAG,QAAQ;IAiB1C,IAAI,aAAa,aAEhB;IAED,aAAa;4BACS,MAAM,GAAG,QAAQ;MAGtC;CACF;AA+CD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,EAAE,CAgDlD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOhD;AAWD,wBAAgB,aAAa,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,MAAM,CAmBvD;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,mBAAmB,UAIlG"}
@@ -10,7 +10,7 @@ export interface FEAASCustomizations {
10
10
  export interface ExplicitTemplate {
11
11
  template: string;
12
12
  }
13
- export type FEAASComponentProps<T = Datascopes> = {
13
+ export type FEAASComponentProps<T = Datascopes> = Partial<ExplicitTemplate> & {
14
14
  data?: T;
15
15
  } & (ExplicitTemplate | FEAASCDNComponentProps) & FEAASCustomizations;
16
16
  export declare function setDOMAttribute(element: HTMLElement, attribute: string, value: any, config?: FEAASCustomizations): void;
@@ -1 +1 @@
1
- {"version":3,"file":"rendering.d.ts","sourceRoot":"","sources":["../../src/dom/rendering.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAA;AAClD,OAAO,EAAE,UAAU,EAA+D,MAAM,WAAW,CAAA;AAGnG,MAAM,WAAW,mBAAmB;IAClC,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,MAAM,CAAA;IAC/E,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,GAAG,KAAK,GAAG,CAAA;IACtD,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,GAAG,CAAA;IAC1E,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,GAAG,KAAK,OAAO,CAAA;IAC5D,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,GAAG,KAAK,IAAI,CAAA;CACrD;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,MAAM,mBAAmB,CAAC,CAAC,GAAG,UAAU,IAAI;IAChD,IAAI,CAAC,EAAE,CAAC,CAAA;CACT,GAAG,CAAC,gBAAgB,GAAG,sBAAsB,CAAC,GAC7C,mBAAmB,CAAA;AAsDrB,wBAAgB,eAAe,CAAC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,mBAAmB,QAgEhH;AAID,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,WAAW,GAAG,gBAAgB,EACrC,UAAU,CAAC,EAAE,GAAG,EAChB,MAAM,CAAC,EAAE,mBAAmB,EAC5B,QAAQ,CAAC,EAAE,OAAO,eA0CnB;AAKD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,mBAAmB,eAcpH;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,mBAAmB,EAAE,OAAO,UAAQ,UAYnH"}
1
+ {"version":3,"file":"rendering.d.ts","sourceRoot":"","sources":["../../src/dom/rendering.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAA;AAClD,OAAO,EAAE,UAAU,EAA+D,MAAM,WAAW,CAAA;AAInG,MAAM,WAAW,mBAAmB;IAClC,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,MAAM,CAAA;IAC/E,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,GAAG,KAAK,GAAG,CAAA;IACtD,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,GAAG,CAAA;IAC1E,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,GAAG,KAAK,OAAO,CAAA;IAC5D,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,GAAG,KAAK,IAAI,CAAA;CACrD;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,MAAM,mBAAmB,CAAC,CAAC,GAAG,UAAU,IAAI,OAAO,CAAC,gBAAgB,CAAC,GAAG;IAC5E,IAAI,CAAC,EAAE,CAAC,CAAA;CACT,GAAG,CAAC,gBAAgB,GAAG,sBAAsB,CAAC,GAC7C,mBAAmB,CAAA;AAsDrB,wBAAgB,eAAe,CAAC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,mBAAmB,QAgEhH;AAID,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,WAAW,GAAG,gBAAgB,EACrC,UAAU,CAAC,EAAE,GAAG,EAChB,MAAM,CAAC,EAAE,mBAAmB,EAC5B,QAAQ,CAAC,EAAE,OAAO,eA0CnB;AAKD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,mBAAmB,eAcpH;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,mBAAmB,EAAE,OAAO,UAAQ,UAWnH"}