@sitecore-feaas/clientside 0.1.45 → 0.1.47

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 +48 -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 () {
@@ -80,6 +91,13 @@ describe('DOM Clientside', function () {
80
91
  '<div><img data-path-src="image" src="a.jpg" /></div>'
81
92
  )
82
93
  })
94
+ it('should render mapped attribute', function () {
95
+ assertRenderedHTML(
96
+ `<div><img data-path-src="image" /></div>`,
97
+ { image: null },
98
+ '<div><img data-path-src="image" /></div>'
99
+ )
100
+ })
83
101
  it('should not render missing attribute', function () {
84
102
  assertRenderedHTML(
85
103
  `<div><img data-path-src="context.z" /></div>`,
@@ -145,6 +163,11 @@ describe('DOM Clientside', function () {
145
163
  { missing: 'a.jpg' },
146
164
  '<div data-path-custom-attribute="test"></div>'
147
165
  )
166
+ assertRenderedHTML(
167
+ `<div data-path-custom-attribute="test"></div>`,
168
+ { test: null },
169
+ '<div data-path-custom-attribute="test"></div>'
170
+ )
148
171
  })
149
172
  it('should render content hub docs as html', function () {
150
173
  assertRenderedHTML(
@@ -170,21 +193,21 @@ describe('DOM Clientside', function () {
170
193
  assertRenderedHTML(
171
194
  `<div><a><var data-path-href="image" data-path="image"></var></a></div>`,
172
195
  { image: 'a.jpg' },
173
- '<div><a href="a.jpg"><var data-path-href="image" data-path="image">a.jpg</a></div>'
196
+ '<div><a href="a.jpg"><var data-path-href="image" data-path="image">a.jpg</var></a></div>'
174
197
  )
175
198
  })
176
199
  it('should fill child element via attribute', function () {
177
200
  assertRenderedHTML(
178
201
  `<div data-path-href="image"><a><var data-path="image"></var></a></div>`,
179
202
  { image: 'a.jpg' },
180
- '<div data-path-href="image"><a href="a.jpg"><var data-path="image">a.jpg</a></div>'
203
+ '<div data-path-href="image"><a href="a.jpg"><var data-path="image">a.jpg</var></a></div>'
181
204
  )
182
205
  })
183
206
  it('should fill image element via attribute', function () {
184
207
  assertRenderedHTML(
185
208
  `<div data-path-href="image"><a><var data-path="image"></var></a></div>`,
186
209
  { image: 'a.jpg' },
187
- '<div data-path-href="image"><a href="a.jpg"><var data-path="image">a.jpg</a></div>'
210
+ '<div data-path-href="image"><a href="a.jpg"><var data-path="image">a.jpg</var></a></div>'
188
211
  )
189
212
  })
190
213
  })
@@ -845,7 +868,7 @@ describe('DOM Clientside', function () {
845
868
  describe('Various examples', () => {
846
869
  it('should render custom web components', () => {
847
870
  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">
871
+ `<bx-accordion class="-embed" data-embed-src="https://1.www.s81c.com/common/carbon/web-components/version/v1.21.0/accordion.min.js">
849
872
  <bx-accordion-item data-path-scope="dominatorData.items.*" data-path-attributes="dominatorData.items.*">
850
873
  </bx-accordion-item>
851
874
  </bx-accordion>`,
@@ -867,8 +890,8 @@ describe('DOM Clientside', function () {
867
890
  ]
868
891
  }
869
892
  },
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">
893
+ `<bx-accordion class="-embed" data-embed-src="https://1.www.s81c.com/common/carbon/web-components/version/v1.21.0/accordion.min.js">
894
+ <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
895
  Hola
873
896
  </bx-accordion-item>
874
897
  <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"}