@claspo/common 7.3.1-dev.2 → 7.3.1-dev.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/package.json +1 -1
- package/coverage/lcov-report/block-navigation.js +0 -87
- package/coverage/lcov-report/prettify.js +0 -2
- package/coverage/lcov-report/sorter.js +0 -196
- package/jest.config.ts +0 -204
- package/src/DefaultEventEmitter.test.ts +0 -84
- package/src/DefaultEventEmitter.ts +0 -96
- package/src/HttpAbortableLoader.ts +0 -35
- package/src/InAppLayoutType.ts +0 -6
- package/src/LayoutType.ts +0 -18
- package/src/PrizePool.interface.ts +0 -32
- package/src/RenderMode.ts +0 -10
- package/src/UuidGenerator.ts +0 -16
- package/src/WidgetInitConfig.interface.ts +0 -163
- package/src/WidgetType.ts +0 -18
- package/src/action/type.ts +0 -7
- package/src/async/createAsyncIterator.ts +0 -33
- package/src/async/debounce.ts +0 -28
- package/src/async/timeout.ts +0 -3
- package/src/component-manifest/ComponentManifest.interface.ts +0 -160
- package/src/component-manifest/ContextMenuManifest.interface.ts +0 -52
- package/src/component-manifest/DisplayCondition.interface.ts +0 -65
- package/src/component-manifest/FloatingControlManifest.interface.ts +0 -89
- package/src/component-manifest/PropPathCondition.interface.ts +0 -4
- package/src/component-manifest/PropertyPaneManifest.interface.ts +0 -614
- package/src/converter/time/TimeConverter.spec.ts +0 -11
- package/src/converter/time/TimeUnit.spec.ts +0 -12
- package/src/converter/time/TimeUnit.ts +0 -34
- package/src/converter/time/TimerConverter.ts +0 -29
- package/src/document/ComponentInsertType.ts +0 -6
- package/src/document/Document.interface.ts +0 -625
- package/src/document/DocumentCssVarsReplace.test.ts +0 -2947
- package/src/document/DocumentCssVarsReplace.ts +0 -31
- package/src/document/DocumentUtils.test.ts +0 -595
- package/src/document/DocumentUtils.ts +0 -194
- package/src/document/hidden-fields.interface.ts +0 -54
- package/src/dom/ViewportSize.ts +0 -61
- package/src/dom/copyToClipboard.ts +0 -17
- package/src/dom/getMostNestedNode.ts +0 -9
- package/src/dom/insertHtmlIntoElement.ts +0 -36
- package/src/dom/sanitizeHTML.test.ts +0 -59
- package/src/dom/sanitizeHTML.ts +0 -78
- package/src/element/BaseElementInViewportHandler.ts +0 -41
- package/src/element/CssVarsOperations.ts +0 -37
- package/src/element/ThemeCssVars.ts +0 -28
- package/src/element/recursiveFindParentNodeByAttribute.test.ts +0 -63
- package/src/element/recursiveFindParentNodeByAttribute.ts +0 -25
- package/src/flat.ts +0 -16
- package/src/handler/HandlerTypes.ts +0 -4
- package/src/math/RandomDistributor.test.ts +0 -35
- package/src/math/RandomDistributor.ts +0 -58
- package/src/math/sum.ts +0 -3
- package/src/network/HttpClient.ts +0 -28
- package/src/network/HttpStatus.ts +0 -4
- package/src/object/isDictionary.test.ts +0 -24
- package/src/object/isDictionary.ts +0 -13
- package/src/object/omitKeys.test.ts +0 -19
- package/src/object/omitKeys.ts +0 -20
- package/src/storage/BaseCachingStorage.test.ts +0 -70
- package/src/storage/BaseCachingStorage.ts +0 -37
- package/src/storage/CachingCookieStorage.test.ts +0 -75
- package/src/storage/CachingCookieStorage.ts +0 -36
- package/src/storage/CachingLocalStorage.test.ts +0 -59
- package/src/storage/CachingLocalStorage.ts +0 -34
- package/src/storage/getCookie.test.ts +0 -53
- package/src/storage/getCookie.ts +0 -10
- package/src/storage/setCookie.test.ts +0 -97
- package/src/storage/setCookie.ts +0 -49
- package/src/theme/theme.utils.ts +0 -50
- package/src/url/sanitizeUrl.test.ts +0 -62
- package/src/url/sanitizeUrl.ts +0 -51
- package/src/utils/CaseTransformer.test.ts +0 -16
- package/src/utils/CaseTransformer.ts +0 -10
- package/src/utils/NullishCoalescingOperator.ts +0 -3
- package/src/utils/NumericDecline.ts +0 -25
- package/src/utils/addEventListener.ts +0 -23
- package/src/utils/allSettled.ts +0 -6
- package/src/utils/checkTimeZone.spec.ts +0 -18
- package/src/utils/checkTimeZone.ts +0 -6
- package/src/utils/deviceUtils.ts +0 -12
- package/src/utils/flatMap.test.ts +0 -21
- package/src/utils/flatMap.ts +0 -3
- package/src/utils/fromEntries.ts +0 -6
- package/src/utils/generateRandomNumber.test.ts +0 -23
- package/src/utils/generateRandomNumber.ts +0 -3
- package/src/utils/objectSort.ts +0 -41
- package/src/utils/orientationUtils.ts +0 -18
- package/src/velocity/SysVelocityContext.spec.ts +0 -88
- package/src/velocity/SysVelocityContext.ts +0 -129
- package/src/velocity/SysVelocityRenderer.spec.ts +0 -36
- package/src/velocity/SysVelocityRenderer.ts +0 -11
- package/test/__mocks/jestGlobalMocks.js +0 -1887
- /package/{out/DefaultEventEmitter.d.ts → DefaultEventEmitter.d.ts} +0 -0
- /package/{out/DefaultEventEmitter.js → DefaultEventEmitter.js} +0 -0
- /package/{out/HttpAbortableLoader.d.ts → HttpAbortableLoader.d.ts} +0 -0
- /package/{out/HttpAbortableLoader.js → HttpAbortableLoader.js} +0 -0
- /package/{out/InAppLayoutType.d.ts → InAppLayoutType.d.ts} +0 -0
- /package/{out/InAppLayoutType.js → InAppLayoutType.js} +0 -0
- /package/{out/LayoutType.d.ts → LayoutType.d.ts} +0 -0
- /package/{out/LayoutType.js → LayoutType.js} +0 -0
- /package/{out/PrizePool.interface.d.ts → PrizePool.interface.d.ts} +0 -0
- /package/{out/PrizePool.interface.js → PrizePool.interface.js} +0 -0
- /package/{out/RenderMode.d.ts → RenderMode.d.ts} +0 -0
- /package/{out/RenderMode.js → RenderMode.js} +0 -0
- /package/{out/UuidGenerator.d.ts → UuidGenerator.d.ts} +0 -0
- /package/{out/UuidGenerator.js → UuidGenerator.js} +0 -0
- /package/{out/WidgetInitConfig.interface.d.ts → WidgetInitConfig.interface.d.ts} +0 -0
- /package/{out/WidgetInitConfig.interface.js → WidgetInitConfig.interface.js} +0 -0
- /package/{out/WidgetType.d.ts → WidgetType.d.ts} +0 -0
- /package/{out/WidgetType.js → WidgetType.js} +0 -0
- /package/{out/action → action}/type.d.ts +0 -0
- /package/{out/action → action}/type.js +0 -0
- /package/{out/async → async}/createAsyncIterator.d.ts +0 -0
- /package/{out/async → async}/createAsyncIterator.js +0 -0
- /package/{out/async → async}/debounce.d.ts +0 -0
- /package/{out/async → async}/debounce.js +0 -0
- /package/{out/async → async}/timeout.d.ts +0 -0
- /package/{out/async → async}/timeout.js +0 -0
- /package/{out/component-manifest → component-manifest}/ComponentManifest.interface.d.ts +0 -0
- /package/{out/component-manifest → component-manifest}/ComponentManifest.interface.js +0 -0
- /package/{out/component-manifest → component-manifest}/ContextMenuManifest.interface.d.ts +0 -0
- /package/{out/component-manifest → component-manifest}/ContextMenuManifest.interface.js +0 -0
- /package/{out/component-manifest → component-manifest}/DisplayCondition.interface.d.ts +0 -0
- /package/{out/component-manifest → component-manifest}/DisplayCondition.interface.js +0 -0
- /package/{out/component-manifest → component-manifest}/FloatingControlManifest.interface.d.ts +0 -0
- /package/{out/component-manifest → component-manifest}/FloatingControlManifest.interface.js +0 -0
- /package/{out/component-manifest → component-manifest}/PropPathCondition.interface.d.ts +0 -0
- /package/{out/component-manifest → component-manifest}/PropPathCondition.interface.js +0 -0
- /package/{out/component-manifest → component-manifest}/PropertyPaneManifest.interface.d.ts +0 -0
- /package/{out/component-manifest → component-manifest}/PropertyPaneManifest.interface.js +0 -0
- /package/{out/converter → converter}/time/TimeUnit.d.ts +0 -0
- /package/{out/converter → converter}/time/TimeUnit.js +0 -0
- /package/{out/converter → converter}/time/TimerConverter.d.ts +0 -0
- /package/{out/converter → converter}/time/TimerConverter.js +0 -0
- /package/{out/document → document}/ComponentInsertType.d.ts +0 -0
- /package/{out/document → document}/ComponentInsertType.js +0 -0
- /package/{out/document → document}/Document.interface.d.ts +0 -0
- /package/{out/document → document}/Document.interface.js +0 -0
- /package/{out/document → document}/DocumentCssVarsReplace.d.ts +0 -0
- /package/{out/document → document}/DocumentCssVarsReplace.js +0 -0
- /package/{out/document → document}/DocumentUtils.d.ts +0 -0
- /package/{out/document → document}/DocumentUtils.js +0 -0
- /package/{out/document → document}/hidden-fields.interface.d.ts +0 -0
- /package/{out/document → document}/hidden-fields.interface.js +0 -0
- /package/{out/dom → dom}/ViewportSize.d.ts +0 -0
- /package/{out/dom → dom}/ViewportSize.js +0 -0
- /package/{out/dom → dom}/copyToClipboard.d.ts +0 -0
- /package/{out/dom → dom}/copyToClipboard.js +0 -0
- /package/{out/dom → dom}/getMostNestedNode.d.ts +0 -0
- /package/{out/dom → dom}/getMostNestedNode.js +0 -0
- /package/{out/dom → dom}/insertHtmlIntoElement.d.ts +0 -0
- /package/{out/dom → dom}/insertHtmlIntoElement.js +0 -0
- /package/{out/dom → dom}/sanitizeHTML.d.ts +0 -0
- /package/{out/dom → dom}/sanitizeHTML.js +0 -0
- /package/{out/element → element}/BaseElementInViewportHandler.d.ts +0 -0
- /package/{out/element → element}/BaseElementInViewportHandler.js +0 -0
- /package/{out/element → element}/CssVarsOperations.d.ts +0 -0
- /package/{out/element → element}/CssVarsOperations.js +0 -0
- /package/{out/element → element}/ThemeCssVars.d.ts +0 -0
- /package/{out/element → element}/ThemeCssVars.js +0 -0
- /package/{out/element → element}/recursiveFindParentNodeByAttribute.d.ts +0 -0
- /package/{out/element → element}/recursiveFindParentNodeByAttribute.js +0 -0
- /package/{out/flat.d.ts → flat.d.ts} +0 -0
- /package/{out/flat.js → flat.js} +0 -0
- /package/{out/handler → handler}/HandlerTypes.d.ts +0 -0
- /package/{out/handler → handler}/HandlerTypes.js +0 -0
- /package/{out/math → math}/RandomDistributor.d.ts +0 -0
- /package/{out/math → math}/RandomDistributor.js +0 -0
- /package/{out/math → math}/sum.d.ts +0 -0
- /package/{out/math → math}/sum.js +0 -0
- /package/{out/network → network}/HttpClient.d.ts +0 -0
- /package/{out/network → network}/HttpClient.js +0 -0
- /package/{out/network → network}/HttpStatus.d.ts +0 -0
- /package/{out/network → network}/HttpStatus.js +0 -0
- /package/{out/object → object}/isDictionary.d.ts +0 -0
- /package/{out/object → object}/isDictionary.js +0 -0
- /package/{out/object → object}/omitKeys.d.ts +0 -0
- /package/{out/object → object}/omitKeys.js +0 -0
- /package/{out/storage → storage}/BaseCachingStorage.d.ts +0 -0
- /package/{out/storage → storage}/BaseCachingStorage.js +0 -0
- /package/{out/storage → storage}/CachingCookieStorage.d.ts +0 -0
- /package/{out/storage → storage}/CachingCookieStorage.js +0 -0
- /package/{out/storage → storage}/CachingLocalStorage.d.ts +0 -0
- /package/{out/storage → storage}/CachingLocalStorage.js +0 -0
- /package/{out/storage → storage}/getCookie.d.ts +0 -0
- /package/{out/storage → storage}/getCookie.js +0 -0
- /package/{out/storage → storage}/setCookie.d.ts +0 -0
- /package/{out/storage → storage}/setCookie.js +0 -0
- /package/{out/theme → theme}/theme.utils.d.ts +0 -0
- /package/{out/theme → theme}/theme.utils.js +0 -0
- /package/{out/url → url}/sanitizeUrl.d.ts +0 -0
- /package/{out/url → url}/sanitizeUrl.js +0 -0
- /package/{out/utils → utils}/CaseTransformer.d.ts +0 -0
- /package/{out/utils → utils}/CaseTransformer.js +0 -0
- /package/{out/utils → utils}/NullishCoalescingOperator.d.ts +0 -0
- /package/{out/utils → utils}/NullishCoalescingOperator.js +0 -0
- /package/{out/utils → utils}/NumericDecline.d.ts +0 -0
- /package/{out/utils → utils}/NumericDecline.js +0 -0
- /package/{out/utils → utils}/addEventListener.d.ts +0 -0
- /package/{out/utils → utils}/addEventListener.js +0 -0
- /package/{out/utils → utils}/allSettled.d.ts +0 -0
- /package/{out/utils → utils}/allSettled.js +0 -0
- /package/{out/utils → utils}/checkTimeZone.d.ts +0 -0
- /package/{out/utils → utils}/checkTimeZone.js +0 -0
- /package/{out/utils → utils}/deviceUtils.d.ts +0 -0
- /package/{out/utils → utils}/deviceUtils.js +0 -0
- /package/{out/utils → utils}/flatMap.d.ts +0 -0
- /package/{out/utils → utils}/flatMap.js +0 -0
- /package/{out/utils → utils}/fromEntries.d.ts +0 -0
- /package/{out/utils → utils}/fromEntries.js +0 -0
- /package/{out/utils → utils}/generateRandomNumber.d.ts +0 -0
- /package/{out/utils → utils}/generateRandomNumber.js +0 -0
- /package/{out/utils → utils}/objectSort.d.ts +0 -0
- /package/{out/utils → utils}/objectSort.js +0 -0
- /package/{out/utils → utils}/orientationUtils.d.ts +0 -0
- /package/{out/utils → utils}/orientationUtils.js +0 -0
- /package/{out/velocity → velocity}/SysVelocityContext.d.ts +0 -0
- /package/{out/velocity → velocity}/SysVelocityContext.js +0 -0
- /package/{out/velocity → velocity}/SysVelocityRenderer.d.ts +0 -0
- /package/{out/velocity → velocity}/SysVelocityRenderer.js +0 -0
|
@@ -1,194 +0,0 @@
|
|
|
1
|
-
import {ClBaseComponentI, ClDocumentActionI, ClDocumentHandlerI, ClDocumentHandlerType} from './Document.interface';
|
|
2
|
-
import {ComponentInsertType} from './ComponentInsertType';
|
|
3
|
-
|
|
4
|
-
export interface IterableNodeI {
|
|
5
|
-
children?: IterableNodeI[];
|
|
6
|
-
[key: string]: any;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export default class DocumentUtils {
|
|
10
|
-
|
|
11
|
-
static removeNode(views: ClBaseComponentI[], path: number[]): ClBaseComponentI {
|
|
12
|
-
const parentPath = this.getParentPath(path);
|
|
13
|
-
const nodeIndex = path[path.length - 1];
|
|
14
|
-
const parent = this.getNodeByPath(views, parentPath);
|
|
15
|
-
|
|
16
|
-
if (parent && parent.children && parent.path) {
|
|
17
|
-
const removedNode = parent.children.splice(nodeIndex, 1)[0];
|
|
18
|
-
(removedNode as any).prevPath = path;
|
|
19
|
-
(removedNode as any).path = null;
|
|
20
|
-
DocumentUtils.reIndex(parent, parent.path);
|
|
21
|
-
return removedNode;
|
|
22
|
-
} else {
|
|
23
|
-
const removedNode = views.splice(nodeIndex, 1)[0];
|
|
24
|
-
(removedNode as any).prevPath = path;
|
|
25
|
-
(removedNode as any).path = null;
|
|
26
|
-
views.forEach((view, index) => {
|
|
27
|
-
view.path = [index];
|
|
28
|
-
DocumentUtils.reIndex(view, view.path);
|
|
29
|
-
});
|
|
30
|
-
return removedNode;
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
static insertNode(node: ClBaseComponentI, targetPath: number[], views: ClBaseComponentI[], insertPosition: string): ClBaseComponentI {
|
|
36
|
-
const toPath = DocumentUtils.getPathToInsert(targetPath, insertPosition, views, node);
|
|
37
|
-
const parentPath = insertPosition === ComponentInsertType.INSIDE
|
|
38
|
-
? targetPath
|
|
39
|
-
: this.getParentPath(toPath);
|
|
40
|
-
const parentNode = this.getNodeByPath(views, parentPath);
|
|
41
|
-
|
|
42
|
-
const nodeIndex = toPath[toPath.length - 1];
|
|
43
|
-
|
|
44
|
-
if (parentNode && parentNode.children && parentNode.path) {
|
|
45
|
-
parentNode.children.splice(nodeIndex, 0, node);
|
|
46
|
-
DocumentUtils.reIndex(parentNode, parentNode.path);
|
|
47
|
-
return node;
|
|
48
|
-
} else {
|
|
49
|
-
views.splice(nodeIndex, 0, node);
|
|
50
|
-
views.forEach((view, index) => {
|
|
51
|
-
view.path = [index];
|
|
52
|
-
DocumentUtils.reIndex(view, view.path);
|
|
53
|
-
});
|
|
54
|
-
return node;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
static moveNode(views: ClBaseComponentI[], fromPath: number[], targetPath: number[], insertType: string): void {
|
|
60
|
-
const targetNode = DocumentUtils.getNodeByPath(views, targetPath);
|
|
61
|
-
|
|
62
|
-
if (!targetNode) {
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const removedComponent = DocumentUtils.removeNode(views, fromPath);
|
|
67
|
-
const foundNode = DocumentUtils.getNodeById(views, targetNode.id);
|
|
68
|
-
|
|
69
|
-
if (foundNode && foundNode.path) {
|
|
70
|
-
DocumentUtils.insertNode(removedComponent, foundNode.path, views, insertType);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
static iterateDepthFirst<T extends IterableNodeI>(node: T, callback: (node: T) => void): void {
|
|
75
|
-
return iterateDepthFirst(node, callback);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
static reIndex(node: ClBaseComponentI, nodePath: number[]): void {
|
|
79
|
-
node.path = nodePath;
|
|
80
|
-
if (node.children) {
|
|
81
|
-
node.children.forEach((n: ClBaseComponentI, i: number) => {
|
|
82
|
-
DocumentUtils.reIndex(n, nodePath.concat(i));
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
static getRelativePath(path: number[]): number[] {
|
|
88
|
-
return path.slice(1, path.length);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
static getParentPath(path: number[]): number[] {
|
|
92
|
-
return path.slice(0, -1);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
static getNodeByPath(components: ClBaseComponentI[], path: number[]): ClBaseComponentI | null {
|
|
96
|
-
let current: ClBaseComponentI[] = components;
|
|
97
|
-
for (let i = 0; i < path.length; i++) {
|
|
98
|
-
if (i === path.length - 1) {
|
|
99
|
-
return current[path[i]] || null;
|
|
100
|
-
} else {
|
|
101
|
-
if (current[path[i]] && current[path[i]].children) {
|
|
102
|
-
current = current[path[i]].children as ClBaseComponentI[];
|
|
103
|
-
} else {
|
|
104
|
-
return null;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
return null;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
static getNodeById(componentsTree: ClBaseComponentI[], id: string): ClBaseComponentI | null {
|
|
112
|
-
let targetComponent: ClBaseComponentI | null = null;
|
|
113
|
-
for (let i = 0; i < componentsTree.length; i++) {
|
|
114
|
-
const component = componentsTree[i];
|
|
115
|
-
if (targetComponent) {
|
|
116
|
-
break;
|
|
117
|
-
}
|
|
118
|
-
if (component.id === id) {
|
|
119
|
-
targetComponent = component;
|
|
120
|
-
break;
|
|
121
|
-
} else {
|
|
122
|
-
if (component.children && component.children.length) {
|
|
123
|
-
targetComponent = this.getNodeById(component.children, id);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
return targetComponent;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
static getPathToInsert(targetPath: number[], insertPosition: string, views: ClBaseComponentI[], node?: ClBaseComponentI): number[] {
|
|
132
|
-
let toPath: number[];
|
|
133
|
-
|
|
134
|
-
const targetIndex = targetPath[targetPath.length - 1];
|
|
135
|
-
switch (insertPosition) {
|
|
136
|
-
case ComponentInsertType.BEFORE:
|
|
137
|
-
toPath = targetPath;
|
|
138
|
-
break;
|
|
139
|
-
case ComponentInsertType.AFTER: {
|
|
140
|
-
toPath = targetPath.slice();
|
|
141
|
-
toPath[targetPath.length - 1] = targetIndex + 1;
|
|
142
|
-
break;
|
|
143
|
-
}
|
|
144
|
-
case ComponentInsertType.INSIDE: {
|
|
145
|
-
const targetNode = DocumentUtils.getNodeByPath(views, targetPath);
|
|
146
|
-
const childrenLength = targetNode?.children?.length ?? 0;
|
|
147
|
-
toPath = targetPath.concat([childrenLength]);
|
|
148
|
-
break;
|
|
149
|
-
}
|
|
150
|
-
case ComponentInsertType.INSTEAD: {
|
|
151
|
-
const prevPath = (node as any)?.prevPath;
|
|
152
|
-
const isBefore = prevPath?.at(-1) <= targetIndex;
|
|
153
|
-
toPath = isBefore
|
|
154
|
-
? [...targetPath.slice(0, -1), targetIndex + 1]
|
|
155
|
-
: targetPath;
|
|
156
|
-
break;
|
|
157
|
-
}
|
|
158
|
-
default:
|
|
159
|
-
toPath = targetPath;
|
|
160
|
-
break;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
return toPath;
|
|
164
|
-
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
static getNodeOnClickData(node: ClBaseComponentI): { actions: ClDocumentActionI[]; npsViewIds: string[] } {
|
|
168
|
-
let actions: ClDocumentActionI[] = [];
|
|
169
|
-
let npsViewIdsMap: Record<string, string> = {};
|
|
170
|
-
DocumentUtils.iterateDepthFirst(node, (model: ClBaseComponentI) => {
|
|
171
|
-
const clickActions = model.props?.handlers?.find((h: ClDocumentHandlerI) => h.type === ClDocumentHandlerType.CLICK)?.actions;
|
|
172
|
-
if (clickActions?.length) {
|
|
173
|
-
actions = [...actions, ...clickActions];
|
|
174
|
-
}
|
|
175
|
-
Object.keys(model.props?.content || {})
|
|
176
|
-
.filter(k => ['detractor', 'passive', 'promoter'].includes(k))
|
|
177
|
-
.map(k => (model.props?.content || {})[k] || null)
|
|
178
|
-
.filter(v => v)
|
|
179
|
-
.forEach(v => npsViewIdsMap[v] = v);
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
return {
|
|
183
|
-
actions,
|
|
184
|
-
npsViewIds: Object.keys(npsViewIdsMap),
|
|
185
|
-
};
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
export function iterateDepthFirst<T extends IterableNodeI>(node: T, callback: (node: T) => void): void {
|
|
190
|
-
if (node.children) {
|
|
191
|
-
node.children.forEach((ch) => iterateDepthFirst(ch as T, callback));
|
|
192
|
-
}
|
|
193
|
-
callback(node);
|
|
194
|
-
}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
export enum SourceType {
|
|
2
|
-
STATIC = 'STATIC',
|
|
3
|
-
DATA_LAYER = 'DATA_LAYER',
|
|
4
|
-
URL_QUERY_PARAMS = 'URL_QUERY_PARAMS',
|
|
5
|
-
JS_API_VARIABLE = 'JS_API_VARIABLE',
|
|
6
|
-
COOKIE = 'COOKIE',
|
|
7
|
-
LOCAL_STORAGE = 'LOCAL_STORAGE',
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export interface HiddenFieldSourceArgumentI {
|
|
11
|
-
name: string;
|
|
12
|
-
value: string;
|
|
13
|
-
type?: string;
|
|
14
|
-
placeholder?: string;
|
|
15
|
-
[key: string]: any;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface StaticSourceConfigI {
|
|
19
|
-
value: string;
|
|
20
|
-
[key: string]: any;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export interface HiddenFieldArgumentsConfigI {
|
|
24
|
-
arguments?: HiddenFieldSourceArgumentI[];
|
|
25
|
-
fallbackValue?: string;
|
|
26
|
-
[key: string]: any;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export interface HiddenFieldConfigBySource {
|
|
30
|
-
[SourceType.STATIC]: StaticSourceConfigI;
|
|
31
|
-
[SourceType.DATA_LAYER]: HiddenFieldArgumentsConfigI;
|
|
32
|
-
[SourceType.URL_QUERY_PARAMS]: HiddenFieldArgumentsConfigI;
|
|
33
|
-
[SourceType.JS_API_VARIABLE]: HiddenFieldArgumentsConfigI;
|
|
34
|
-
[SourceType.COOKIE]: HiddenFieldArgumentsConfigI;
|
|
35
|
-
[SourceType.LOCAL_STORAGE]: HiddenFieldArgumentsConfigI;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export interface HiddenFieldSharedBaseI {
|
|
39
|
-
id: string;
|
|
40
|
-
name: string;
|
|
41
|
-
label: string;
|
|
42
|
-
options: [];
|
|
43
|
-
type: 'HIDDEN';
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export type HiddenFieldSharedI<S extends SourceType = SourceType> =
|
|
47
|
-
HiddenFieldSharedBaseI & {
|
|
48
|
-
sourceType: S;
|
|
49
|
-
config: HiddenFieldConfigBySource[S];
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
export type AnyHiddenFieldSharedI = {
|
|
53
|
-
[S in SourceType]: HiddenFieldSharedI<S>;
|
|
54
|
-
}[SourceType];
|
package/src/dom/ViewportSize.ts
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Represents viewport dimensions.
|
|
3
|
-
*/
|
|
4
|
-
export interface ViewportSizeI {
|
|
5
|
-
/** Viewport width in pixels */
|
|
6
|
-
width: number;
|
|
7
|
-
/** Viewport height in pixels */
|
|
8
|
-
height: number;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Utility class for measuring viewport dimensions.
|
|
13
|
-
* Provides static methods to get viewport size, width, height, and scrollbar width.
|
|
14
|
-
*/
|
|
15
|
-
export default class ViewportSize {
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Returns the current viewport size (width and height).
|
|
19
|
-
* @param htmlDocumentObject - Optional document object (defaults to window.document)
|
|
20
|
-
* @returns Object containing viewport width and height
|
|
21
|
-
*/
|
|
22
|
-
static size(htmlDocumentObject?: Document): ViewportSizeI {
|
|
23
|
-
return {
|
|
24
|
-
width: this.width(htmlDocumentObject),
|
|
25
|
-
height: this.height(htmlDocumentObject),
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Returns the viewport width in pixels.
|
|
31
|
-
* Uses the maximum of clientWidth and innerWidth for cross-browser compatibility.
|
|
32
|
-
* @param htmlDocumentObject - Optional document object (defaults to window.document)
|
|
33
|
-
* @returns Viewport width in pixels
|
|
34
|
-
*/
|
|
35
|
-
static width(htmlDocumentObject?: Document): number {
|
|
36
|
-
const doc = htmlDocumentObject || document;
|
|
37
|
-
return Math.max(doc.documentElement.clientWidth, doc.defaultView?.innerWidth || 0);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Returns the viewport height in pixels.
|
|
42
|
-
* Uses the maximum of clientHeight and innerHeight for cross-browser compatibility.
|
|
43
|
-
* @param htmlDocumentObject - Optional document object (defaults to window.document)
|
|
44
|
-
* @returns Viewport height in pixels
|
|
45
|
-
*/
|
|
46
|
-
static height(htmlDocumentObject?: Document): number {
|
|
47
|
-
const doc = htmlDocumentObject || document;
|
|
48
|
-
return Math.max(doc.documentElement.clientHeight, doc.defaultView?.innerHeight || 0);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Returns the scrollbar width in pixels.
|
|
53
|
-
* Calculated as the difference between innerWidth and clientWidth.
|
|
54
|
-
* @param htmlDocumentObject - Optional document object (defaults to window.document)
|
|
55
|
-
* @returns Scrollbar width in pixels (0 if no scrollbar)
|
|
56
|
-
*/
|
|
57
|
-
static scrollbarWidth(htmlDocumentObject?: Document): number {
|
|
58
|
-
const doc = htmlDocumentObject || document;
|
|
59
|
-
return (doc.defaultView?.innerWidth || 0) - doc.documentElement.clientWidth;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copies text to the system clipboard using the Clipboard API.
|
|
3
|
-
* Trims whitespace and replaces `<br>` tags with spaces.
|
|
4
|
-
* @param textToCopy - The text to copy to the clipboard
|
|
5
|
-
* @returns A promise that resolves when the text is copied, or rejects if clipboard is unavailable
|
|
6
|
-
* @example
|
|
7
|
-
* copyToClipboard('Hello World').then(() => console.log('Copied!'));
|
|
8
|
-
*/
|
|
9
|
-
export default function copyToClipboard(textToCopy: string): Promise<void> {
|
|
10
|
-
if (!navigator.clipboard?.writeText) {
|
|
11
|
-
return Promise.reject();
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
return navigator.clipboard.writeText(
|
|
15
|
-
String(textToCopy).trim().replace('<br>', ' ')
|
|
16
|
-
);
|
|
17
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export default function getMostNestedNode(containerElement: Element): Element {
|
|
2
|
-
let mostNestedNode: Element = containerElement;
|
|
3
|
-
|
|
4
|
-
while (mostNestedNode.firstElementChild) {
|
|
5
|
-
mostNestedNode = mostNestedNode.firstElementChild;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
return mostNestedNode;
|
|
9
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import sanitizeHTML from './sanitizeHTML';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Parameters for inserting HTML into an element.
|
|
5
|
-
*/
|
|
6
|
-
export interface InsertHtmlIntoElementParamsI {
|
|
7
|
-
/** The target DOM element to insert HTML into */
|
|
8
|
-
element: Element;
|
|
9
|
-
/** The HTML string to insert */
|
|
10
|
-
html: string;
|
|
11
|
-
/** If true, appends HTML to existing content; otherwise replaces it */
|
|
12
|
-
appendHtml?: boolean;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Safely inserts HTML content into a DOM element after sanitizing it.
|
|
17
|
-
* Can either replace existing content or append to it.
|
|
18
|
-
* @param params - Configuration object with element, html, and optional appendHtml flag
|
|
19
|
-
* @example
|
|
20
|
-
* insertHtmlIntoElement({
|
|
21
|
-
* element: document.getElementById('container'),
|
|
22
|
-
* html: '<p>Hello</p>',
|
|
23
|
-
* appendHtml: true
|
|
24
|
-
* });
|
|
25
|
-
*/
|
|
26
|
-
export default function insertHtmlIntoElement(params: InsertHtmlIntoElementParamsI): void {
|
|
27
|
-
const {element, html, appendHtml} = params;
|
|
28
|
-
|
|
29
|
-
const sanitizedHTML = sanitizeHTML(html);
|
|
30
|
-
|
|
31
|
-
if (appendHtml) {
|
|
32
|
-
element.innerHTML += sanitizedHTML;
|
|
33
|
-
} else {
|
|
34
|
-
element.innerHTML = sanitizedHTML;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import sanitizeHTML from './sanitizeHTML';
|
|
2
|
-
import fs from 'fs';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Test cases array format: [input, expected_output]
|
|
7
|
-
* Each test case contains:
|
|
8
|
-
* - input: The HTML/text string to sanitize (or null/undefined/non-string values)
|
|
9
|
-
* - expected_output: The exact expected string result (strict equality check)
|
|
10
|
-
*
|
|
11
|
-
* Test cases are loaded from sanitizeHTML-test-cases.json for consistency with Java version
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
// Load test cases from JSON file
|
|
15
|
-
const jsonPath = path.join(__dirname, 'sanitizeHTML-test-cases.json');
|
|
16
|
-
const testData = JSON.parse(fs.readFileSync(jsonPath, 'utf-8'));
|
|
17
|
-
const testCases = testData.testCases;
|
|
18
|
-
|
|
19
|
-
describe('sanitizeHTML - Array-based tests from JSON', () => {
|
|
20
|
-
it('should sanitize all test cases correctly', () => {
|
|
21
|
-
const failedTests: { index: number; input: string; expected: any; actual: string }[] = [];
|
|
22
|
-
|
|
23
|
-
testCases.forEach(([input, expected], index) => {
|
|
24
|
-
const result = sanitizeHTML(input);
|
|
25
|
-
|
|
26
|
-
// Strict equality check
|
|
27
|
-
if (result !== expected) {
|
|
28
|
-
failedTests.push({
|
|
29
|
-
index,
|
|
30
|
-
input: input === null ? 'null' : input === undefined ? 'undefined' : String(input),
|
|
31
|
-
expected,
|
|
32
|
-
actual: result
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
// Report failed tests
|
|
38
|
-
if (failedTests.length > 0) {
|
|
39
|
-
console.log(`\n=== FAILED TEST CASES ${failedTests.length} ===\n`);
|
|
40
|
-
failedTests.forEach(test => {
|
|
41
|
-
console.log(`Test #${test.index}:`);
|
|
42
|
-
console.log(`Input:"${test.input}"`);
|
|
43
|
-
console.log(`Expected:"${test.expected}"`);
|
|
44
|
-
console.log(`Actual:"${test.actual}"\n`);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
console.log(`Total failed: ${failedTests.length} out of ${testCases.length} tests\n`);
|
|
48
|
-
|
|
49
|
-
// Fail the test with summary
|
|
50
|
-
expect(failedTests).toHaveLength(0);
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
// Keep one traditional test for better Jest output
|
|
55
|
-
it('should have all test cases loaded from JSON', () => {
|
|
56
|
-
expect(testCases.length).toBeGreaterThan(0);
|
|
57
|
-
console.log(`Loaded ${testCases.length} test cases from JSON`);
|
|
58
|
-
});
|
|
59
|
-
});
|
package/src/dom/sanitizeHTML.ts
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Sanitizes HTML content by removing potentially dangerous elements and attributes.
|
|
3
|
-
* Removes script tags, style tags, event handlers, and javascript: URLs.
|
|
4
|
-
* @param html - The HTML string to sanitize
|
|
5
|
-
* @returns The sanitized HTML string safe for insertion into the DOM
|
|
6
|
-
* @example
|
|
7
|
-
* const safe = sanitizeHTML('<div onclick="alert(1)">Hello</div>');
|
|
8
|
-
* // Returns: '<div>Hello</div>'
|
|
9
|
-
*/
|
|
10
|
-
export default function sanitizeHTML(html: string): string {
|
|
11
|
-
// Handle null and undefined specifically
|
|
12
|
-
if (html === null || html === undefined) {
|
|
13
|
-
return '';
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
if (typeof html !== 'string') {
|
|
17
|
-
// Convert non-string values to string, including boolean false
|
|
18
|
-
return String(html);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// Handle empty string
|
|
22
|
-
if (html === '') {
|
|
23
|
-
return '';
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// Improved HTML tag detection - must have valid tag name after <
|
|
27
|
-
// This avoids false positives on strings like "Price < 100" or "Banking &<>"
|
|
28
|
-
const htmlTagPattern = /<\/?([a-zA-Z][a-zA-Z0-9]*)\b[^>]*>/;
|
|
29
|
-
if (!htmlTagPattern.test(html)) {
|
|
30
|
-
return html;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const parser = new DOMParser();
|
|
34
|
-
const doc = parser.parseFromString(html, 'text/html');
|
|
35
|
-
|
|
36
|
-
const scriptsAndStyles = doc.querySelectorAll('script, style, link[rel="stylesheet"], meta[http-equiv]');
|
|
37
|
-
scriptsAndStyles.forEach(el => el.remove());
|
|
38
|
-
|
|
39
|
-
const elements = doc.querySelectorAll('*');
|
|
40
|
-
elements.forEach(element => {
|
|
41
|
-
const dangerousAttrs: string[] = [
|
|
42
|
-
'onclick', 'onload', 'onerror', 'onmouseover', 'onfocus', 'onblur',
|
|
43
|
-
'onkeyup', 'onkeydown', 'onchange', 'onsubmit', 'onmouseenter',
|
|
44
|
-
'onmouseleave', 'onmouseout', 'oncontextmenu', 'ondrag', 'ondrop'
|
|
45
|
-
];
|
|
46
|
-
|
|
47
|
-
dangerousAttrs.forEach(attr => element.removeAttribute(attr));
|
|
48
|
-
|
|
49
|
-
Array.from(element.attributes).forEach(attr => {
|
|
50
|
-
if (attr.name.startsWith('on')) {
|
|
51
|
-
element.removeAttribute(attr.name);
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
if (element.tagName === 'A' || element.tagName === 'AREA') {
|
|
56
|
-
const href = element.getAttribute('href');
|
|
57
|
-
if (href && (href.startsWith('javascript:') || href.startsWith('data:'))) {
|
|
58
|
-
element.removeAttribute('href');
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
if (element.tagName === 'IMG' || element.tagName === 'IFRAME') {
|
|
63
|
-
const src = element.getAttribute('src');
|
|
64
|
-
if (src && (src.startsWith('javascript:') || src.startsWith('data:text/html'))) {
|
|
65
|
-
element.removeAttribute('src');
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if (element.tagName === 'FORM') {
|
|
70
|
-
const action = element.getAttribute('action');
|
|
71
|
-
if (action && action.startsWith('javascript:')) {
|
|
72
|
-
element.removeAttribute('action');
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
return doc.body.innerHTML;
|
|
78
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
export default class BaseElementInViewportHandler {
|
|
2
|
-
observer: IntersectionObserver | null;
|
|
3
|
-
rootElement: Element;
|
|
4
|
-
oneTimeObserver: boolean;
|
|
5
|
-
|
|
6
|
-
constructor(rootElement: Element, oneTimeObserver: boolean) {
|
|
7
|
-
this.observer = null;
|
|
8
|
-
this.rootElement = rootElement;
|
|
9
|
-
this.oneTimeObserver = oneTimeObserver;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
handle(visibleCallback: () => void, notVisibleCallback?: () => void): void {
|
|
13
|
-
const options = {
|
|
14
|
-
root: null,
|
|
15
|
-
rootMargin: '0px',
|
|
16
|
-
threshold: 0.1
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
this.observer = new IntersectionObserver((intersectionEntries) => {
|
|
20
|
-
const isIntersecting = !!intersectionEntries.find(entry => entry.isIntersecting);
|
|
21
|
-
|
|
22
|
-
if (!isIntersecting) {
|
|
23
|
-
if (notVisibleCallback && typeof notVisibleCallback === 'function') {
|
|
24
|
-
notVisibleCallback();
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
visibleCallback();
|
|
31
|
-
if (this.oneTimeObserver) {
|
|
32
|
-
this.unsubscribe();
|
|
33
|
-
}
|
|
34
|
-
}, options);
|
|
35
|
-
this.observer.observe(this.rootElement);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
unsubscribe(): void {
|
|
39
|
-
this.observer?.disconnect();
|
|
40
|
-
}
|
|
41
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import {ClDocumentCssVarsI} from '../document/Document.interface';
|
|
2
|
-
|
|
3
|
-
function forEachCssVarKey(cssVarsMap: ClDocumentCssVarsI, cb: (key: string) => void): void {
|
|
4
|
-
if (cssVarsMap && Object.keys(cssVarsMap)) {
|
|
5
|
-
Object
|
|
6
|
-
.keys(cssVarsMap)
|
|
7
|
-
.forEach(cb);
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
export default class CssVarsOperations {
|
|
13
|
-
static get(varName: string, element: HTMLElement): string {
|
|
14
|
-
return element.style.getPropertyValue(`--${varName}`);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
static apply(cssVarsMap: ClDocumentCssVarsI = {}, element: HTMLElement): void {
|
|
18
|
-
forEachCssVarKey(cssVarsMap, (key: string) => {
|
|
19
|
-
const property = `--${key}`;
|
|
20
|
-
const value = cssVarsMap[key];
|
|
21
|
-
if (!element.style.getPropertyValue(property)) {
|
|
22
|
-
element.style.setProperty(property, value);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
static override(cssVarsMap: ClDocumentCssVarsI = {}, element: HTMLElement): void {
|
|
29
|
-
forEachCssVarKey(cssVarsMap, (key: string) => {
|
|
30
|
-
const property = `--${key}`;
|
|
31
|
-
const value = cssVarsMap[key];
|
|
32
|
-
element.style.setProperty(property, value);
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { toCssVarToken } from "../theme/theme.utils";
|
|
2
|
-
import CssVarsOperations from "./CssVarsOperations";
|
|
3
|
-
|
|
4
|
-
export function prepareKeys(schema) {
|
|
5
|
-
const originalKeys = Object.keys(schema).reduce((acc, key) => {
|
|
6
|
-
acc[toCssVarToken(key)] = schema[key];
|
|
7
|
-
return acc;
|
|
8
|
-
}, {});
|
|
9
|
-
|
|
10
|
-
return originalKeys;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export default class ThemeCssVars extends CssVarsOperations {
|
|
14
|
-
static override(schema = {}, element) {
|
|
15
|
-
const cssVars = prepareKeys(schema);
|
|
16
|
-
super.override(cssVars, element);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
static apply(schema = {}, element) {
|
|
20
|
-
const cssVars = prepareKeys(schema);
|
|
21
|
-
super.apply(cssVars, element);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
static get(varName, element) {
|
|
25
|
-
const cssVarToken = toCssVarToken(varName);
|
|
26
|
-
return super.get(cssVarToken, element);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import recursiveFindParentNodeByAttribute from "./recursiveFindParentNodeByAttribute";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
describe('recursiveFindParentNodeByAttribute function', () => {
|
|
5
|
-
test('returns null if reference node does not have the specified attribute', () => {
|
|
6
|
-
const parentNode = document.createElement('div');
|
|
7
|
-
|
|
8
|
-
const result = recursiveFindParentNodeByAttribute(parentNode, 'attribute', 'value');
|
|
9
|
-
|
|
10
|
-
expect(result).toBeNull();
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
test('returns null if reference node is null', () => {
|
|
14
|
-
const result = recursiveFindParentNodeByAttribute(null, 'attribute', 'value');
|
|
15
|
-
expect(result).toBeNull();
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
test('returns the reference node if it has the specified attribute', () => {
|
|
19
|
-
const parentNode = document.createElement('div');
|
|
20
|
-
parentNode.setAttribute('attribute', 'value');
|
|
21
|
-
|
|
22
|
-
const result = recursiveFindParentNodeByAttribute(parentNode, 'attribute', 'value');
|
|
23
|
-
|
|
24
|
-
expect(result).toEqual(parentNode);
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
test('returns the parent node with the specified attribute inside nested shadow DOM', () => {
|
|
28
|
-
// given
|
|
29
|
-
const parentNode = document.createElement('div');
|
|
30
|
-
const shadowChild1 = document.createElement('div');
|
|
31
|
-
const shadowChild2 = document.createElement('div');
|
|
32
|
-
|
|
33
|
-
parentNode.id = '0';
|
|
34
|
-
shadowChild1.id = '1';
|
|
35
|
-
shadowChild2.id = '2';
|
|
36
|
-
|
|
37
|
-
parentNode.setAttribute('attribute', 'value');
|
|
38
|
-
shadowChild1.setAttribute('attribute', 'value');
|
|
39
|
-
shadowChild2.setAttribute('attribute', 'value');
|
|
40
|
-
|
|
41
|
-
const shadowRoot1 = parentNode.attachShadow({ mode: 'open' });
|
|
42
|
-
const shadowRoot2 = shadowChild1.attachShadow({ mode: 'open' });
|
|
43
|
-
|
|
44
|
-
shadowRoot1.appendChild(shadowChild1);
|
|
45
|
-
shadowRoot2.appendChild(shadowChild2);
|
|
46
|
-
|
|
47
|
-
// when
|
|
48
|
-
const result = recursiveFindParentNodeByAttribute(shadowChild2, 'attribute', 'value');
|
|
49
|
-
|
|
50
|
-
// then
|
|
51
|
-
expect(result!.id).toEqual('2');
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
test('returns null if no parent node has the specified attribute', () => {
|
|
55
|
-
const parentNode = document.createElement('div');
|
|
56
|
-
const childNode = document.createElement('div');
|
|
57
|
-
parentNode.appendChild(childNode);
|
|
58
|
-
|
|
59
|
-
const result = recursiveFindParentNodeByAttribute(childNode, 'attribute', 'value');
|
|
60
|
-
|
|
61
|
-
expect(result).toBeNull();
|
|
62
|
-
});
|
|
63
|
-
});
|