@ubio/webvision 1.2.6 → 2.1.0

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 (47) hide show
  1. package/build/page.mjs +760 -355
  2. package/out/page/counter.d.ts +6 -0
  3. package/out/page/counter.js +13 -0
  4. package/out/page/counter.js.map +1 -0
  5. package/out/page/dom.d.ts +21 -0
  6. package/out/page/dom.js +172 -0
  7. package/out/page/dom.js.map +1 -0
  8. package/out/page/frame.d.ts +22 -0
  9. package/out/page/frame.js +69 -0
  10. package/out/page/frame.js.map +1 -0
  11. package/out/page/index.d.ts +9 -3
  12. package/out/page/index.js +9 -3
  13. package/out/page/index.js.map +1 -1
  14. package/out/page/overlay.d.ts +3 -0
  15. package/out/page/overlay.js +75 -0
  16. package/out/page/overlay.js.map +1 -0
  17. package/out/page/parser.d.ts +59 -0
  18. package/out/page/parser.js +249 -0
  19. package/out/page/parser.js.map +1 -0
  20. package/out/page/probe.d.ts +5 -0
  21. package/out/page/probe.js +36 -0
  22. package/out/page/probe.js.map +1 -0
  23. package/out/page/render.d.ts +12 -8
  24. package/out/page/render.js +73 -38
  25. package/out/page/render.js.map +1 -1
  26. package/out/page/snapshot.d.ts +9 -68
  27. package/out/page/snapshot.js +23 -183
  28. package/out/page/snapshot.js.map +1 -1
  29. package/out/page/traverse.d.ts +5 -0
  30. package/out/page/traverse.js +7 -0
  31. package/out/page/traverse.js.map +1 -0
  32. package/out/page/tree.d.ts +22 -0
  33. package/out/page/tree.js +59 -0
  34. package/out/page/tree.js.map +1 -0
  35. package/out/page/util.d.ts +3 -0
  36. package/out/page/util.js +9 -0
  37. package/out/page/util.js.map +1 -0
  38. package/package.json +6 -3
  39. package/out/page/highlight.d.ts +0 -5
  40. package/out/page/highlight.js +0 -72
  41. package/out/page/highlight.js.map +0 -1
  42. package/out/page/html.d.ts +0 -4
  43. package/out/page/html.js +0 -42
  44. package/out/page/html.js.map +0 -1
  45. package/out/page/utils.d.ts +0 -19
  46. package/out/page/utils.js +0 -68
  47. package/out/page/utils.js.map +0 -1
@@ -1,191 +1,31 @@
1
- import { containsSelector, deepIsHidden, isRecursiveInline, normalizeText } from './utils.js';
2
- export const DEFAULT_SKIP_TAGS = ['svg', 'script', 'noscript', 'style', 'link', 'meta'];
3
- export const DEFAULT_SEMANTIC_TAGS = [
4
- 'a', 'button', 'label', 'section',
5
- 'article', 'main', 'header', 'footer', 'nav', 'aside',
6
- 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
7
- 'ul', 'ol', 'li', 'dl', 'dt', 'dd',
8
- 'p', 'pre', 'code', 'blockquote', 'figure', 'figcaption',
9
- 'table', 'thead', 'tbody', 'tr', 'td', 'th',
10
- 'form', 'input', 'textarea', 'select', 'option', 'fieldset', 'legend',
11
- 'strong', 'em', 'sub', 'sup',
12
- ];
13
- export function createSnapshot(root, options = {}) {
14
- // Hack: hide all elements that may unintentionally contain visible text
15
- document.querySelectorAll('script, noscript, style').forEach(el => {
16
- el.style.display = 'none';
17
- });
18
- const opts = {
19
- startId: 0,
20
- skipHidden: true,
21
- skipEmptyText: true,
22
- skipImages: false,
23
- skipIframes: false,
24
- skipTags: DEFAULT_SKIP_TAGS,
25
- tagPreference: DEFAULT_SEMANTIC_TAGS,
26
- collapseInline: true,
27
- ...options,
28
- };
29
- const counter = new Counter(opts.startId);
30
- const refMap = new Map();
31
- const tree = new SnapshotTree(root, null, counter, opts);
32
- tree.fillMap(refMap);
1
+ import { VxTreeParser } from './parser.js';
2
+ import { VxTreeView } from './tree.js';
3
+ export const VX_DOM_SYMBOL = Symbol('vx:dom');
4
+ export const VX_TREE_SYMBOL = Symbol('vx:tree');
5
+ export function captureSnapshot(options = {}) {
6
+ const parser = new VxTreeParser(options);
7
+ const vxNodes = parser.getNodes();
8
+ const domMap = parser.getDomMap();
9
+ const vxTree = new VxTreeView(vxNodes);
10
+ globalThis[VX_DOM_SYMBOL] = domMap;
11
+ globalThis[VX_TREE_SYMBOL] = vxTree;
33
12
  return {
34
- refMap,
35
- snapshot: tree.toJson(),
36
- maxId: counter.value,
13
+ nodes: vxNodes,
14
+ refRange: parser.getRefRange(),
37
15
  };
38
16
  }
39
- export class SnapshotTree {
40
- constructor(node, parent, counter, options) {
41
- this.node = node;
42
- this.parent = parent;
43
- this.counter = counter;
44
- this.options = options;
45
- this.children = [];
46
- this.ref = this.counter.next();
47
- this.classList = [...(this.element?.classList ?? [])];
48
- if (this.element) {
49
- this.parseTree(this.element, this.getAcceptedChildren(this.element));
50
- }
51
- }
52
- get element() {
53
- return this.node instanceof Element ? this.node : null;
54
- }
55
- get depth() {
56
- return this.parent ? this.parent.depth + 1 : 0;
57
- }
58
- get leaf() {
59
- return this.children.length === 0;
60
- }
61
- get tagName() {
62
- return this.node instanceof Element ? this.node.tagName.toLowerCase() : undefined;
63
- }
64
- get href() {
65
- return this.node instanceof HTMLAnchorElement ? this.node.href : undefined;
66
- }
67
- get src() {
68
- return this.node.src ?? undefined;
69
- }
70
- get clientRect() {
71
- if (this.node instanceof Element) {
72
- return this.node.getBoundingClientRect();
73
- }
74
- const range = document.createRange();
75
- range.selectNodeContents(this.node);
76
- return range.getBoundingClientRect();
77
- }
78
- parseTree(el, childNodes) {
79
- this.children = [];
80
- if (childNodes.length === 1) {
81
- return this.collapseWrapper(el, childNodes[0]);
82
- }
83
- if (this.options.collapseInline && isRecursiveInline(el, this.options.tagPreference)) {
84
- // Do not process more children
85
- return;
86
- }
87
- for (const childNode of childNodes) {
88
- const snapshot = new SnapshotTree(childNode, this, this.counter, this.options);
89
- this.children.push(snapshot);
90
- }
91
- }
92
- /**
93
- * Collapses an element with only one visible child into one.
94
- *
95
- * Wrapper element is preferred if it's a link or a button,
96
- * in other cases child element is preferred.
97
- */
98
- collapseWrapper(el, child) {
99
- if (child instanceof Text) {
100
- this.textContent = normalizeText(child.textContent ?? '');
101
- return;
102
- }
103
- this.classList.push(...child.classList);
104
- const parentRank = this.options.tagPreference.indexOf(el.tagName.toLowerCase());
105
- const childRank = this.options.tagPreference.indexOf(child.tagName.toLowerCase());
106
- const preferParent = parentRank !== -1 && (parentRank < childRank || childRank === -1);
107
- if (!preferParent) {
108
- this.node = child;
109
- }
110
- // Continue parsing child element
111
- if (this.element) {
112
- this.parseTree(this.element, this.getAcceptedChildren(child));
113
- }
114
- }
115
- getAcceptedChildren(el) {
116
- const childNodes = [...el.childNodes];
117
- return childNodes.filter((node) => {
118
- // Ignore non-text and non-HTML nodes
119
- if (!(node instanceof Element || node instanceof Text)) {
120
- return false;
121
- }
122
- if (node instanceof Element) {
123
- // Skip hidden elements (opacity, display, visibility, etc)
124
- // TODO checkOpacity breaks PDF viewer
125
- if (this.options.skipHidden && deepIsHidden(node)) {
126
- return false;
127
- }
128
- // Always include inputs
129
- if (containsSelector(node, 'input')) {
130
- return true;
131
- }
132
- // Always include iframes, unless explicitly skipped
133
- if (!this.options.skipIframes && containsSelector(node, 'iframe')) {
134
- return true;
135
- }
136
- // Always include images, unless explicitly skipped
137
- if (!this.options.skipImages && containsSelector(node, 'img')) {
138
- return true;
139
- }
140
- // Skip listed tags
141
- if (this.options.skipTags.includes(node.tagName.toLowerCase())) {
142
- return false;
143
- }
144
- }
145
- // Skip nodes with empty text
146
- if (this.options.skipEmptyText) {
147
- const isEmptyText = normalizeText(node.textContent ?? '').length === 0;
148
- if (isEmptyText) {
149
- return false;
150
- }
151
- }
152
- return true;
153
- });
154
- }
155
- fillMap(map) {
156
- map.set(this.ref, this.node);
157
- for (const child of this.children) {
158
- child.fillMap(map);
159
- }
160
- }
161
- toJson() {
162
- const { top, left, width, height } = this.clientRect;
163
- return {
164
- ref: this.ref,
165
- nodeType: this.node instanceof Element ? 'element' : 'text',
166
- leaf: this.leaf,
167
- tagName: this.tagName,
168
- rect: {
169
- x: left,
170
- y: top,
171
- width,
172
- height,
173
- },
174
- classList: this.node instanceof Element ? this.classList : undefined,
175
- textContent: this.textContent,
176
- href: this.href,
177
- src: this.src,
178
- children: this.leaf ? undefined : this.children.map(child => child.toJson()),
179
- };
17
+ export function getSnapshot() {
18
+ const vxTree = globalThis[VX_TREE_SYMBOL];
19
+ if (!vxTree) {
20
+ throw new Error('[VX] Snapshot not found');
180
21
  }
22
+ return vxTree;
181
23
  }
182
- export class Counter {
183
- constructor(value = 0) {
184
- this.value = value;
185
- }
186
- next() {
187
- this.value += 1;
188
- return this.value;
24
+ export function resolveDomNode(ref) {
25
+ const domMap = globalThis[VX_DOM_SYMBOL];
26
+ if (!domMap) {
27
+ return null;
189
28
  }
29
+ return domMap.get(ref) ?? null;
190
30
  }
191
31
  //# sourceMappingURL=snapshot.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../../src/page/snapshot.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../../src/page/snapshot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,YAAY,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,MAAM,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;AAC9C,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;AAEhD,MAAM,UAAU,eAAe,CAAC,UAAyB,EAAE;IACvD,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,OAAO,CAAC,CAAC;IACzC,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;IAClC,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC;IAClC,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,OAAO,CAAC,CAAC;IACtC,UAAkB,CAAC,aAAa,CAAC,GAAG,MAAM,CAAC;IAC3C,UAAkB,CAAC,cAAc,CAAC,GAAG,MAAM,CAAC;IAC7C,OAAO;QACH,KAAK,EAAE,OAAO;QACd,QAAQ,EAAE,MAAM,CAAC,WAAW,EAAE;KACjC,CAAC;AACN,CAAC;AAED,MAAM,UAAU,WAAW;IACvB,MAAM,MAAM,GAAI,UAAkB,CAAC,cAAc,CAAe,CAAC;IACjE,IAAI,CAAC,MAAM,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC/C,CAAC;IACD,OAAO,MAAM,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,GAAW;IACtC,MAAM,MAAM,GAAI,UAAkB,CAAC,aAAa,CAAsB,CAAC;IACvE,IAAI,CAAC,MAAM,EAAE,CAAC;QACV,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,OAAO,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;AACnC,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { VxNode } from './parser.js';
2
+ export declare function traverseVxNode(vxNode: VxNode, depth?: number): IterableIterator<{
3
+ vxNode: VxNode;
4
+ depth: number;
5
+ }>;
@@ -0,0 +1,7 @@
1
+ export function* traverseVxNode(vxNode, depth = 0) {
2
+ yield { vxNode, depth };
3
+ for (const child of vxNode.children ?? []) {
4
+ yield* traverseVxNode(child, depth + 1);
5
+ }
6
+ }
7
+ //# sourceMappingURL=traverse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"traverse.js","sourceRoot":"","sources":["../../src/page/traverse.ts"],"names":[],"mappings":"AAEA,MAAM,SAAS,CAAC,CAAC,cAAc,CAAC,MAAc,EAAE,KAAK,GAAG,CAAC;IACrD,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IACxB,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;QACxC,KAAK,CAAC,CAAC,cAAc,CAAC,KAAK,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;IAC5C,CAAC;AACL,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { VxNode } from './parser.js';
2
+ import { VxRenderOptions } from './render.js';
3
+ export interface VxHighlightOptions {
4
+ highlight?: boolean;
5
+ clearOverlay?: boolean;
6
+ includeAll?: boolean;
7
+ filterRefs?: number[];
8
+ }
9
+ export declare class VxTreeView {
10
+ readonly nodes: VxNode[];
11
+ private refMap;
12
+ constructor(nodes: VxNode[]);
13
+ traverse(): IterableIterator<{
14
+ vxNode: VxNode;
15
+ depth: number;
16
+ }>;
17
+ private buildRefMap;
18
+ findNode(ref: number): VxNode | null;
19
+ render(options?: VxRenderOptions): string;
20
+ highlight(options?: VxHighlightOptions): number[];
21
+ collectRefs(leafOnly?: boolean, filterRefs?: number[]): number[];
22
+ }
@@ -0,0 +1,59 @@
1
+ import { clearOverlay, highlightEl } from './overlay.js';
2
+ import { renderVxNode } from './render.js';
3
+ import { resolveDomNode } from './snapshot.js';
4
+ import { traverseVxNode } from './traverse.js';
5
+ import { isContainerNode } from './util.js';
6
+ export class VxTreeView {
7
+ constructor(nodes) {
8
+ this.nodes = nodes;
9
+ this.refMap = new Map();
10
+ this.buildRefMap(nodes);
11
+ }
12
+ *traverse() {
13
+ for (const vxNode of this.nodes) {
14
+ yield* traverseVxNode(vxNode, 0);
15
+ }
16
+ }
17
+ buildRefMap(nodes) {
18
+ for (const node of nodes) {
19
+ this.refMap.set(node.ref, node);
20
+ this.buildRefMap(node.children ?? []);
21
+ }
22
+ }
23
+ findNode(ref) {
24
+ return this.refMap.get(ref) ?? null;
25
+ }
26
+ render(options = {}) {
27
+ return this.nodes.map(node => {
28
+ return renderVxNode(node, options);
29
+ }).join('\n');
30
+ }
31
+ highlight(options = {}) {
32
+ if (options.clearOverlay) {
33
+ clearOverlay();
34
+ }
35
+ const leafOnly = !options.includeAll;
36
+ const refs = this.collectRefs(leafOnly, options.filterRefs);
37
+ for (const ref of refs) {
38
+ const el = resolveDomNode(ref);
39
+ if (el instanceof Element) {
40
+ highlightEl(el);
41
+ }
42
+ }
43
+ return refs;
44
+ }
45
+ collectRefs(leafOnly = true, filterRefs) {
46
+ const refs = [];
47
+ for (const { vxNode } of this.traverse()) {
48
+ if (leafOnly && isContainerNode(vxNode)) {
49
+ continue;
50
+ }
51
+ if (filterRefs && !filterRefs.includes(vxNode.ref)) {
52
+ continue;
53
+ }
54
+ refs.push(vxNode.ref);
55
+ }
56
+ return refs;
57
+ }
58
+ }
59
+ //# sourceMappingURL=tree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree.js","sourceRoot":"","sources":["../../src/page/tree.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEzD,OAAO,EAAE,YAAY,EAAmB,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAS5C,MAAM,OAAO,UAAU;IAInB,YAAqB,KAAe;QAAf,UAAK,GAAL,KAAK,CAAU;QAF5B,WAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;QAGvC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;IAED,CAAC,QAAQ;QACL,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC9B,KAAK,CAAC,CAAC,cAAc,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACrC,CAAC;IACL,CAAC;IAEO,WAAW,CAAC,KAAe;QAC/B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACvB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YAChC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;QAC1C,CAAC;IACL,CAAC;IAED,QAAQ,CAAC,GAAW;QAChB,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;IACxC,CAAC;IAED,MAAM,CAAC,UAA2B,EAAE;QAChC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;YACzB,OAAO,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClB,CAAC;IAED,SAAS,CAAC,UAA8B,EAAE;QACtC,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;YACvB,YAAY,EAAE,CAAC;QACnB,CAAC;QACD,MAAM,QAAQ,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC;QACrC,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;QAC5D,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACrB,MAAM,EAAE,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;YAC/B,IAAI,EAAE,YAAY,OAAO,EAAE,CAAC;gBACxB,WAAW,CAAC,EAAE,CAAC,CAAC;YACpB,CAAC;QACL,CAAC;QACD,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,WAAW,CAAC,QAAQ,GAAG,IAAI,EAAE,UAAqB;QAC9C,MAAM,IAAI,GAAa,EAAE,CAAC;QAC1B,KAAK,MAAM,EAAE,MAAM,EAAE,IAAI,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC;YACvC,IAAI,QAAQ,IAAI,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC;gBACtC,SAAS;YACb,CAAC;YACD,IAAI,UAAU,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;gBACjD,SAAS;YACb,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC1B,CAAC;QACD,OAAO,IAAI,CAAC;IAChB,CAAC;CAEJ"}
@@ -0,0 +1,3 @@
1
+ import { VxNode } from './parser.js';
2
+ export declare function isContainerNode(vxNode: VxNode): boolean;
3
+ export declare function isObjectEmpty(obj: Record<string, any>): boolean;
@@ -0,0 +1,9 @@
1
+ export function isContainerNode(vxNode) {
2
+ const children = vxNode.children ?? [];
3
+ const hasTextChildren = children.some(child => !child.tagName);
4
+ return children.length > 0 && !hasTextChildren;
5
+ }
6
+ export function isObjectEmpty(obj) {
7
+ return !Object.values(obj).some(value => !!value);
8
+ }
9
+ //# sourceMappingURL=util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.js","sourceRoot":"","sources":["../../src/page/util.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,eAAe,CAAC,MAAc;IAC1C,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC;IACvC,MAAM,eAAe,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC/D,OAAO,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,eAAe,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,GAAwB;IAClD,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;AACtD,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ubio/webvision",
3
- "version": "1.2.6",
3
+ "version": "2.1.0",
4
4
  "main": "out/main/index.js",
5
5
  "type": "module",
6
6
  "exports": {
@@ -14,7 +14,9 @@
14
14
  ],
15
15
  "scripts": {
16
16
  "clean": "rm -rf out *.tsbuildinfo",
17
- "dev": "npm run clean && tsc -b -w",
17
+ "dev": "npm run clean && run-p dev:*",
18
+ "dev:ts": "tsc -b -w",
19
+ "dev:esbuild": "esbuild src/page/index.ts --bundle --outfile=build/page.mjs --target=es2022 --format=esm --watch",
18
20
  "compile": "npm run clean && tsc -b",
19
21
  "compile:page": "esbuild src/page/index.ts --bundle --outfile=build/page.mjs --target=es2022 --format=esm",
20
22
  "add:build": "git add ./build",
@@ -31,12 +33,13 @@
31
33
  ],
32
34
  "license": "ISC",
33
35
  "devDependencies": {
36
+ "@fastify/pre-commit": "^2.2.0",
34
37
  "@nodescript/eslint-config": "^2.1.0",
35
38
  "@types/node": "^22.13.1",
36
39
  "esbuild": "^0.25.0",
37
40
  "eslint": "^9.19.0",
41
+ "npm-run-all": "^4.1.5",
38
42
  "playwright": "^1.50.1",
39
- "pre-commit": "^1.2.2",
40
43
  "typescript": "^5.7.3"
41
44
  }
42
45
  }
@@ -1,5 +0,0 @@
1
- import { SnapshotItem, SnapshotNode } from './snapshot.js';
2
- export declare function highlightSnapshot(snapshot: SnapshotItem, refMap: Map<number, SnapshotNode>): void;
3
- export declare function highlightEl(snapshot: SnapshotItem, refMap: Map<number, SnapshotNode>, container: HTMLElement): void;
4
- export declare function removeHighlight(): void;
5
- export declare function getHighlightContainer(): HTMLElement;
@@ -1,72 +0,0 @@
1
- export function highlightSnapshot(snapshot, refMap) {
2
- removeHighlight();
3
- const container = getHighlightContainer();
4
- container.innerHTML = '';
5
- highlightRecursive(snapshot, refMap, container);
6
- }
7
- function highlightRecursive(snapshot, refMap, container) {
8
- highlightEl(snapshot, refMap, container);
9
- for (const child of snapshot.children ?? []) {
10
- highlightRecursive(child, refMap, container);
11
- }
12
- }
13
- export function highlightEl(snapshot, refMap, container) {
14
- const isContainerEl = !snapshot.leaf && snapshot.children?.every(child => child.nodeType === 'element');
15
- if (isContainerEl) {
16
- return;
17
- }
18
- const node = refMap.get(snapshot.ref);
19
- if (!(node instanceof Element)) {
20
- return;
21
- }
22
- const color = getColor(snapshot.ref);
23
- const rect = node.getBoundingClientRect();
24
- const overlay = document.createElement('div');
25
- container.appendChild(overlay);
26
- overlay.style.position = 'absolute';
27
- overlay.style.top = `${rect.top}px`;
28
- overlay.style.left = `${rect.left}px`;
29
- overlay.style.width = `${rect.width}px`;
30
- overlay.style.height = `${rect.height}px`;
31
- overlay.style.border = `2px solid ${color}`;
32
- const label = document.createElement('div');
33
- overlay.appendChild(label);
34
- label.style.position = 'absolute';
35
- label.style.bottom = `100%`;
36
- label.style.left = `0`;
37
- label.style.backgroundColor = color;
38
- label.style.color = 'white';
39
- label.style.fontSize = '10px';
40
- label.style.fontFamily = 'monospace';
41
- label.style.fontWeight = 'normal';
42
- label.style.fontStyle = 'normal';
43
- label.style.opacity = '0.8';
44
- label.style.padding = '0 2px';
45
- label.style.transform = 'translateY(50%)';
46
- label.textContent = String(snapshot.ref);
47
- }
48
- export function removeHighlight() {
49
- const container = getHighlightContainer();
50
- document.documentElement.removeChild(container);
51
- }
52
- export function getHighlightContainer() {
53
- let container = document.querySelector('#webvision-highlight');
54
- if (!container) {
55
- container = document.createElement('div');
56
- container.id = 'webvision-highlight';
57
- container.style.position = 'absolute';
58
- container.style.pointerEvents = 'none';
59
- container.style.top = '0';
60
- container.style.left = '0';
61
- container.style.width = '100%';
62
- container.style.height = '100%';
63
- container.style.zIndex = '2147483646'; // Maximum z-index value
64
- document.documentElement.appendChild(container);
65
- }
66
- return container;
67
- }
68
- function getColor(index) {
69
- const hue = (index * 120 * .382) % 360;
70
- return `hsl(${hue}, 85%, 50%)`;
71
- }
72
- //# sourceMappingURL=highlight.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"highlight.js","sourceRoot":"","sources":["../../src/page/highlight.ts"],"names":[],"mappings":"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"}
@@ -1,4 +0,0 @@
1
- import { SnapshotNode } from './snapshot.js';
2
- export declare function captureAncestorsHtml(el: SnapshotNode, includeText?: boolean): string[];
3
- export declare function captureHtmlLine(el: SnapshotNode): string | null;
4
- export declare function captureHtml(el: SnapshotNode): string | null;
package/out/page/html.js DELETED
@@ -1,42 +0,0 @@
1
- export function captureAncestorsHtml(el, includeText = true) {
2
- const path = [];
3
- let current = el;
4
- while (current) {
5
- path.push(captureHtmlLine(current));
6
- current = current.parentElement;
7
- }
8
- if (includeText) {
9
- const anyEl = el;
10
- path.unshift(anyEl.value || anyEl.innerText || anyEl.textContent || '');
11
- }
12
- return path.reverse().filter(Boolean);
13
- }
14
- export function captureHtmlLine(el) {
15
- const html = [];
16
- if (el instanceof HTMLElement) {
17
- html.push(`${el.tagName.toLowerCase()}`);
18
- for (const attr of el.attributes) {
19
- html.push(`${attr.name}="${attr.value}"`);
20
- }
21
- return `<${html.join(' ')}>`;
22
- }
23
- if (el instanceof Text) {
24
- return el.textContent;
25
- }
26
- return '';
27
- }
28
- export function captureHtml(el) {
29
- if (el instanceof HTMLElement) {
30
- const anyEl = el;
31
- return [
32
- captureHtmlLine(el),
33
- anyEl.value || anyEl.innerText || anyEl.textContent || '',
34
- `</${el.tagName.toLowerCase()}>`,
35
- ].filter(Boolean).join('');
36
- }
37
- if (el instanceof Text) {
38
- return el.textContent;
39
- }
40
- return '';
41
- }
42
- //# sourceMappingURL=html.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"html.js","sourceRoot":"","sources":["../../src/page/html.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,oBAAoB,CAAC,EAAgB,EAAE,WAAW,GAAG,IAAI;IACrE,MAAM,IAAI,GAAG,EAAE,CAAC;IAChB,IAAI,OAAO,GAAwB,EAAE,CAAC;IACtC,OAAO,OAAO,EAAE,CAAC;QACb,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;QACpC,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC;IACpC,CAAC;IACD,IAAI,WAAW,EAAE,CAAC;QACd,MAAM,KAAK,GAAG,EAAS,CAAC;QACxB,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,EAAgB;IAC5C,MAAM,IAAI,GAAG,EAAE,CAAC;IAChB,IAAI,EAAE,YAAY,WAAW,EAAE,CAAC;QAC5B,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QACzC,KAAK,MAAM,IAAI,IAAI,EAAE,CAAC,UAAU,EAAE,CAAC;YAC/B,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;QAC9C,CAAC;QACD,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;IACjC,CAAC;IACD,IAAI,EAAE,YAAY,IAAI,EAAE,CAAC;QACrB,OAAO,EAAE,CAAC,WAAW,CAAC;IAC1B,CAAC;IACD,OAAO,EAAE,CAAC;AACd,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,EAAgB;IACxC,IAAI,EAAE,YAAY,WAAW,EAAE,CAAC;QAC5B,MAAM,KAAK,GAAG,EAAS,CAAC;QACxB,OAAO;YACH,eAAe,CAAC,EAAE,CAAC;YACnB,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,WAAW,IAAI,EAAE;YACzD,KAAK,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,GAAG;SACnC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC/B,CAAC;IACD,IAAI,EAAE,YAAY,IAAI,EAAE,CAAC;QACrB,OAAO,EAAE,CAAC,WAAW,CAAC;IAC1B,CAAC;IACD,OAAO,EAAE,CAAC;AACd,CAAC"}
@@ -1,19 +0,0 @@
1
- export interface VisibilityOptions {
2
- checkOpacity: boolean;
3
- checkVisibility: boolean;
4
- checkTransform: boolean;
5
- }
6
- /**
7
- * Element not visible with descendants if:
8
- *
9
- * - opacity < 0.1
10
- * - display: none
11
- * - visibility: hidden
12
- * - transform: scale(0)
13
- */
14
- export declare function isHidden(element: Element, options?: Partial<VisibilityOptions>): boolean;
15
- export declare function hasVisibleArea(element: Element): boolean;
16
- export declare function deepIsHidden(element: Element, options?: Partial<VisibilityOptions>): boolean;
17
- export declare function normalizeText(str: string): string;
18
- export declare function containsSelector(el: Element, selector: string): boolean;
19
- export declare function isRecursiveInline(el: Element, ignoreTags?: string[]): boolean;
package/out/page/utils.js DELETED
@@ -1,68 +0,0 @@
1
- /**
2
- * Element not visible with descendants if:
3
- *
4
- * - opacity < 0.1
5
- * - display: none
6
- * - visibility: hidden
7
- * - transform: scale(0)
8
- */
9
- export function isHidden(element, options = {}) {
10
- const { checkOpacity = true, checkVisibility = true, checkTransform = true, } = options;
11
- const style = getComputedStyle(element);
12
- const opacity = Number(style.opacity);
13
- const display = style.display;
14
- const visibility = style.visibility;
15
- const transform = style.transform;
16
- if (display === 'none' ||
17
- (checkOpacity && opacity === 0) ||
18
- (checkVisibility && (visibility === 'hidden')) ||
19
- (checkTransform && transform.includes('scale(0)'))) {
20
- return true;
21
- }
22
- if (!element.checkVisibility()) {
23
- return true;
24
- }
25
- return false;
26
- }
27
- export function hasVisibleArea(element) {
28
- const rect = element.getBoundingClientRect();
29
- const area = rect.width * rect.height;
30
- return area > 100;
31
- }
32
- export function deepIsHidden(element, options = {}) {
33
- if (isHidden(element, options)) {
34
- return true;
35
- }
36
- if (!hasVisibleArea(element)) {
37
- return [...element.children].every(el => deepIsHidden(el, options));
38
- }
39
- return false;
40
- }
41
- export function normalizeText(str) {
42
- return str
43
- .replace(/\p{Cf}/gu, ' ')
44
- .replace(/\s+/g, ' ')
45
- .trim();
46
- }
47
- export function containsSelector(el, selector) {
48
- return el.matches(selector) || !!el.querySelector(selector);
49
- }
50
- export function isRecursiveInline(el, ignoreTags = []) {
51
- for (const child of el.childNodes) {
52
- if (child instanceof Element) {
53
- if (ignoreTags.includes(child.tagName.toLowerCase())) {
54
- return false;
55
- }
56
- const display = getComputedStyle(child).display;
57
- const inline = display === 'inline' || display === 'inline-block';
58
- if (!inline) {
59
- return false;
60
- }
61
- if (!isRecursiveInline(child, ignoreTags)) {
62
- return false;
63
- }
64
- }
65
- }
66
- return true;
67
- }
68
- //# sourceMappingURL=utils.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/page/utils.ts"],"names":[],"mappings":"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"}