@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.
- package/build/dom/html.js +287 -0
- package/build/dom/html.js.map +1 -0
- package/build/dom/rendering.js +4 -4
- package/build/dom/rendering.js.map +1 -1
- package/build/dom/scripts.js +2 -2
- package/build/dom/scripts.js.map +1 -1
- package/build/ui/FEAASContext.js +2 -2
- package/build/ui/FEAASContext.js.map +1 -1
- package/build/ui/react.js +3 -1
- package/build/ui/react.js.map +1 -1
- package/dist/browser/headless.cjs +5 -5
- package/dist/browser/headless.cjs.map +4 -4
- package/dist/browser/headless.esm.js +5 -5
- package/dist/browser/headless.esm.js.map +1 -1
- package/dist/browser/index.cjs +5 -5
- package/dist/browser/index.cjs.map +4 -4
- package/dist/browser/index.esm.js +5 -5
- package/dist/browser/index.esm.js.map +1 -1
- package/dist/browser/react.cjs +5 -5
- package/dist/browser/react.cjs.map +4 -4
- package/dist/browser/react.esm.js +5 -5
- package/dist/browser/react.esm.js.map +1 -1
- package/dist/node/headless.cjs +3 -3
- package/dist/node/headless.cjs.map +4 -4
- package/dist/node/headless.esm.js +3 -3
- package/dist/node/headless.esm.js.map +4 -4
- package/dist/node/index.cjs +3 -3
- package/dist/node/index.cjs.map +4 -4
- package/dist/node/index.esm.js +3 -3
- package/dist/node/index.esm.js.map +4 -4
- package/dist/node/react.cjs +3 -3
- package/dist/node/react.cjs.map +4 -4
- package/dist/node/react.esm.js +3 -3
- package/dist/node/react.esm.js.map +4 -4
- package/headless.cjs +3 -3
- package/headless.cjs.map +4 -4
- package/headless.js +3 -3
- package/headless.js.map +4 -4
- package/package.json +1 -4
- package/react.cjs +5 -5
- package/react.cjs.map +4 -4
- package/react.js +5 -5
- package/react.js.map +4 -4
- package/scripts/build.js +1 -9
- package/src/dom/html.ts +322 -0
- package/src/dom/rendering.ts +5 -5
- package/src/dom/scripts.ts +3 -3
- package/src/ui/FEAASContext.tsx +2 -2
- package/src/ui/react.tsx +4 -1
- package/test/FEAASComponent.react.test.tsx +109 -0
- package/test/FEAASContext.test.tsx +2 -2
- package/test/dom.test.ts +48 -25
- package/types/dom/html.d.ts +45 -0
- package/types/dom/html.d.ts.map +1 -0
- package/types/dom/rendering.d.ts +1 -1
- package/types/dom/rendering.d.ts.map +1 -1
- package/types/tsbuildinfo +1 -1
- package/types/tsbuildinfo_ui +1 -1
- package/types/ui/react.d.ts +2 -0
- 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
|
|
3
|
+
import * as FEAASReact from '../src/ui/react.js'
|
|
4
4
|
import { describe, it, assert, beforeAll } from 'vitest'
|
|
5
|
-
import { parseHTML } from '
|
|
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
|
|
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
|
|
34
|
-
const matches = attrs.match(
|
|
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
|
-
|
|
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(
|
|
53
|
+
assert.equal(normalize(FEAAS.renderHTMLContent(input, data, customizations)), normalize(expected))
|
|
62
54
|
|
|
63
|
-
assert.equal(
|
|
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 "quote" inside an attribute">Text with "quote"</p>',
|
|
68
|
+
'<div onclick="alert('Hello & welcome!')">Click me</div>',
|
|
69
|
+
'<input type="text" value="&"'" />',
|
|
70
|
+
'Text & <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=
|
|
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=
|
|
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"}
|
package/types/dom/rendering.d.ts
CHANGED
|
@@ -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;
|
|
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"}
|