react-grab 0.0.9 → 0.0.12
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/dist/index.d.ts +36 -2
- package/dist/index.global.js +765 -320
- package/package.json +1 -1
- package/dist/core.cjs +0 -259
- package/dist/core.d.cts +0 -10
- package/dist/core.d.ts +0 -10
- package/dist/core.js +0 -254
package/package.json
CHANGED
package/dist/core.cjs
DELETED
|
@@ -1,259 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var bippy = require('bippy');
|
|
4
|
-
var source = require('bippy/dist/source');
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* @license MIT
|
|
8
|
-
*
|
|
9
|
-
* Copyright (c) 2025 Aiden Bai
|
|
10
|
-
*
|
|
11
|
-
* This source code is licensed under the MIT license found in the
|
|
12
|
-
* LICENSE file in the root directory of this source tree.
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
var getStack = async (element) => {
|
|
16
|
-
const fiber = bippy.getFiberFromHostInstance(element);
|
|
17
|
-
if (!fiber) return null;
|
|
18
|
-
const stackTrace = source.getFiberStackTrace(fiber);
|
|
19
|
-
console.log(stackTrace);
|
|
20
|
-
const rawOwnerStack = await source.getOwnerStack(stackTrace);
|
|
21
|
-
console.log(rawOwnerStack);
|
|
22
|
-
const stack = rawOwnerStack.map((item) => ({
|
|
23
|
-
componentName: item.name,
|
|
24
|
-
fileName: item.source?.fileName
|
|
25
|
-
}));
|
|
26
|
-
return stack;
|
|
27
|
-
};
|
|
28
|
-
var filterStack = (stack) => {
|
|
29
|
-
return stack.filter(
|
|
30
|
-
(item) => item.fileName && !item.fileName.includes("node_modules") && item.componentName.length > 1 && !item.fileName.startsWith("_")
|
|
31
|
-
);
|
|
32
|
-
};
|
|
33
|
-
var findCommonRoot = (paths) => {
|
|
34
|
-
if (paths.length === 0) return "";
|
|
35
|
-
if (paths.length === 1) {
|
|
36
|
-
const lastSlash2 = paths[0].lastIndexOf("/");
|
|
37
|
-
return lastSlash2 > 0 ? paths[0].substring(0, lastSlash2 + 1) : "";
|
|
38
|
-
}
|
|
39
|
-
let commonPrefix = paths[0];
|
|
40
|
-
for (let i = 1; i < paths.length; i++) {
|
|
41
|
-
const path = paths[i];
|
|
42
|
-
let j = 0;
|
|
43
|
-
while (j < commonPrefix.length && j < path.length && commonPrefix[j] === path[j]) {
|
|
44
|
-
j++;
|
|
45
|
-
}
|
|
46
|
-
commonPrefix = commonPrefix.substring(0, j);
|
|
47
|
-
}
|
|
48
|
-
const lastSlash = commonPrefix.lastIndexOf("/");
|
|
49
|
-
return lastSlash > 0 ? commonPrefix.substring(0, lastSlash + 1) : "";
|
|
50
|
-
};
|
|
51
|
-
var serializeStack = (stack) => {
|
|
52
|
-
const filePaths = stack.map((item) => item.fileName).filter((path) => !!path);
|
|
53
|
-
const commonRoot = findCommonRoot(filePaths);
|
|
54
|
-
return stack.map((item) => {
|
|
55
|
-
let fileName = item.fileName;
|
|
56
|
-
if (fileName && commonRoot) {
|
|
57
|
-
fileName = fileName.startsWith(commonRoot) ? fileName.substring(commonRoot.length) : fileName;
|
|
58
|
-
}
|
|
59
|
-
return `${item.componentName}${fileName ? ` (${fileName})` : ""}`;
|
|
60
|
-
}).join("\n");
|
|
61
|
-
};
|
|
62
|
-
var getHTMLSnippet = (element) => {
|
|
63
|
-
const semanticTags = /* @__PURE__ */ new Set([
|
|
64
|
-
"article",
|
|
65
|
-
"aside",
|
|
66
|
-
"footer",
|
|
67
|
-
"form",
|
|
68
|
-
"header",
|
|
69
|
-
"main",
|
|
70
|
-
"nav",
|
|
71
|
-
"section"
|
|
72
|
-
]);
|
|
73
|
-
const hasDistinguishingFeatures = (el) => {
|
|
74
|
-
const tagName = el.tagName.toLowerCase();
|
|
75
|
-
if (semanticTags.has(tagName)) return true;
|
|
76
|
-
if (el.id) return true;
|
|
77
|
-
if (el.className && typeof el.className === "string") {
|
|
78
|
-
const classes = el.className.trim();
|
|
79
|
-
if (classes && classes.length > 0) return true;
|
|
80
|
-
}
|
|
81
|
-
return Array.from(el.attributes).some(
|
|
82
|
-
(attr) => attr.name.startsWith("data-")
|
|
83
|
-
);
|
|
84
|
-
};
|
|
85
|
-
const getAncestorChain = (el, maxDepth = 10) => {
|
|
86
|
-
const ancestors2 = [];
|
|
87
|
-
let current = el.parentElement;
|
|
88
|
-
let depth = 0;
|
|
89
|
-
while (current && depth < maxDepth && current.tagName !== "BODY") {
|
|
90
|
-
if (hasDistinguishingFeatures(current)) {
|
|
91
|
-
ancestors2.push(current);
|
|
92
|
-
if (ancestors2.length >= 3) break;
|
|
93
|
-
}
|
|
94
|
-
current = current.parentElement;
|
|
95
|
-
depth++;
|
|
96
|
-
}
|
|
97
|
-
return ancestors2.reverse();
|
|
98
|
-
};
|
|
99
|
-
const getCSSPath = (el) => {
|
|
100
|
-
const parts = [];
|
|
101
|
-
let current = el;
|
|
102
|
-
let depth = 0;
|
|
103
|
-
const maxDepth = 5;
|
|
104
|
-
while (current && depth < maxDepth && current.tagName !== "BODY") {
|
|
105
|
-
let selector = current.tagName.toLowerCase();
|
|
106
|
-
if (current.id) {
|
|
107
|
-
selector += `#${current.id}`;
|
|
108
|
-
parts.unshift(selector);
|
|
109
|
-
break;
|
|
110
|
-
} else if (current.className && typeof current.className === "string" && current.className.trim()) {
|
|
111
|
-
const classes = current.className.trim().split(/\s+/).slice(0, 2);
|
|
112
|
-
selector += `.${classes.join(".")}`;
|
|
113
|
-
}
|
|
114
|
-
if (!current.id && (!current.className || !current.className.trim()) && current.parentElement) {
|
|
115
|
-
const siblings = Array.from(current.parentElement.children);
|
|
116
|
-
const index = siblings.indexOf(current);
|
|
117
|
-
if (index >= 0 && siblings.length > 1) {
|
|
118
|
-
selector += `:nth-child(${index + 1})`;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
parts.unshift(selector);
|
|
122
|
-
current = current.parentElement;
|
|
123
|
-
depth++;
|
|
124
|
-
}
|
|
125
|
-
return parts.join(" > ");
|
|
126
|
-
};
|
|
127
|
-
const getElementTag = (el, compact = false) => {
|
|
128
|
-
const tagName = el.tagName.toLowerCase();
|
|
129
|
-
const attrs = [];
|
|
130
|
-
if (el.id) {
|
|
131
|
-
attrs.push(`id="${el.id}"`);
|
|
132
|
-
}
|
|
133
|
-
if (el.className && typeof el.className === "string") {
|
|
134
|
-
const classes = el.className.trim().split(/\s+/);
|
|
135
|
-
if (classes.length > 0 && classes[0]) {
|
|
136
|
-
const displayClasses = compact ? classes.slice(0, 3) : classes;
|
|
137
|
-
let classStr = displayClasses.join(" ");
|
|
138
|
-
if (classStr.length > 30) {
|
|
139
|
-
classStr = classStr.substring(0, 30) + "...";
|
|
140
|
-
}
|
|
141
|
-
attrs.push(`class="${classStr}"`);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
const dataAttrs = Array.from(el.attributes).filter(
|
|
145
|
-
(attr) => attr.name.startsWith("data-")
|
|
146
|
-
);
|
|
147
|
-
const displayDataAttrs = compact ? dataAttrs.slice(0, 1) : dataAttrs;
|
|
148
|
-
for (const attr of displayDataAttrs) {
|
|
149
|
-
let value = attr.value;
|
|
150
|
-
if (value.length > 20) {
|
|
151
|
-
value = value.substring(0, 20) + "...";
|
|
152
|
-
}
|
|
153
|
-
attrs.push(`${attr.name}="${value}"`);
|
|
154
|
-
}
|
|
155
|
-
const ariaLabel = el.getAttribute("aria-label");
|
|
156
|
-
if (ariaLabel && !compact) {
|
|
157
|
-
let value = ariaLabel;
|
|
158
|
-
if (value.length > 20) {
|
|
159
|
-
value = value.substring(0, 20) + "...";
|
|
160
|
-
}
|
|
161
|
-
attrs.push(`aria-label="${value}"`);
|
|
162
|
-
}
|
|
163
|
-
return attrs.length > 0 ? `<${tagName} ${attrs.join(" ")}>` : `<${tagName}>`;
|
|
164
|
-
};
|
|
165
|
-
const getClosingTag = (el) => {
|
|
166
|
-
return `</${el.tagName.toLowerCase()}>`;
|
|
167
|
-
};
|
|
168
|
-
const getTextContent = (el) => {
|
|
169
|
-
let text = el.textContent || "";
|
|
170
|
-
text = text.trim().replace(/\s+/g, " ");
|
|
171
|
-
const maxLength = 60;
|
|
172
|
-
if (text.length > maxLength) {
|
|
173
|
-
text = text.substring(0, maxLength) + "...";
|
|
174
|
-
}
|
|
175
|
-
return text;
|
|
176
|
-
};
|
|
177
|
-
const getSiblingIdentifier = (el) => {
|
|
178
|
-
if (el.id) return `#${el.id}`;
|
|
179
|
-
if (el.className && typeof el.className === "string") {
|
|
180
|
-
const classes = el.className.trim().split(/\s+/);
|
|
181
|
-
if (classes.length > 0 && classes[0]) {
|
|
182
|
-
return `.${classes[0]}`;
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
return null;
|
|
186
|
-
};
|
|
187
|
-
const lines = [];
|
|
188
|
-
lines.push(`Path: ${getCSSPath(element)}`);
|
|
189
|
-
lines.push("");
|
|
190
|
-
const ancestors = getAncestorChain(element);
|
|
191
|
-
for (let i = 0; i < ancestors.length; i++) {
|
|
192
|
-
const indent2 = " ".repeat(i);
|
|
193
|
-
lines.push(indent2 + getElementTag(ancestors[i], true));
|
|
194
|
-
}
|
|
195
|
-
const parent = element.parentElement;
|
|
196
|
-
let targetIndex = -1;
|
|
197
|
-
if (parent) {
|
|
198
|
-
const siblings = Array.from(parent.children);
|
|
199
|
-
targetIndex = siblings.indexOf(element);
|
|
200
|
-
if (targetIndex > 0) {
|
|
201
|
-
const prevSibling = siblings[targetIndex - 1];
|
|
202
|
-
const prevId = getSiblingIdentifier(prevSibling);
|
|
203
|
-
if (prevId && targetIndex <= 2) {
|
|
204
|
-
const indent2 = " ".repeat(ancestors.length);
|
|
205
|
-
lines.push(`${indent2} ${getElementTag(prevSibling, true)}`);
|
|
206
|
-
lines.push(`${indent2} </${prevSibling.tagName.toLowerCase()}>`);
|
|
207
|
-
} else if (targetIndex > 0) {
|
|
208
|
-
const indent2 = " ".repeat(ancestors.length);
|
|
209
|
-
lines.push(`${indent2} ... (${targetIndex} element${targetIndex === 1 ? "" : "s"})`);
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
const indent = " ".repeat(ancestors.length);
|
|
214
|
-
lines.push(indent + " <!-- SELECTED -->");
|
|
215
|
-
const textContent = getTextContent(element);
|
|
216
|
-
const childrenCount = element.children.length;
|
|
217
|
-
if (textContent && childrenCount === 0 && textContent.length < 40) {
|
|
218
|
-
lines.push(
|
|
219
|
-
`${indent} ${getElementTag(element)}${textContent}${getClosingTag(element)}`
|
|
220
|
-
);
|
|
221
|
-
} else {
|
|
222
|
-
lines.push(indent + " " + getElementTag(element));
|
|
223
|
-
if (textContent) {
|
|
224
|
-
lines.push(`${indent} ${textContent}`);
|
|
225
|
-
}
|
|
226
|
-
if (childrenCount > 0) {
|
|
227
|
-
lines.push(
|
|
228
|
-
`${indent} ... (${childrenCount} element${childrenCount === 1 ? "" : "s"})`
|
|
229
|
-
);
|
|
230
|
-
}
|
|
231
|
-
lines.push(indent + " " + getClosingTag(element));
|
|
232
|
-
}
|
|
233
|
-
if (parent && targetIndex >= 0) {
|
|
234
|
-
const siblings = Array.from(parent.children);
|
|
235
|
-
const siblingsAfter = siblings.length - targetIndex - 1;
|
|
236
|
-
if (siblingsAfter > 0) {
|
|
237
|
-
const nextSibling = siblings[targetIndex + 1];
|
|
238
|
-
const nextId = getSiblingIdentifier(nextSibling);
|
|
239
|
-
if (nextId && siblingsAfter <= 2) {
|
|
240
|
-
lines.push(`${indent} ${getElementTag(nextSibling, true)}`);
|
|
241
|
-
lines.push(`${indent} </${nextSibling.tagName.toLowerCase()}>`);
|
|
242
|
-
} else {
|
|
243
|
-
lines.push(
|
|
244
|
-
`${indent} ... (${siblingsAfter} element${siblingsAfter === 1 ? "" : "s"})`
|
|
245
|
-
);
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
for (let i = ancestors.length - 1; i >= 0; i--) {
|
|
250
|
-
const indent2 = " ".repeat(i);
|
|
251
|
-
lines.push(indent2 + getClosingTag(ancestors[i]));
|
|
252
|
-
}
|
|
253
|
-
return lines.join("\n");
|
|
254
|
-
};
|
|
255
|
-
|
|
256
|
-
exports.filterStack = filterStack;
|
|
257
|
-
exports.getHTMLSnippet = getHTMLSnippet;
|
|
258
|
-
exports.getStack = getStack;
|
|
259
|
-
exports.serializeStack = serializeStack;
|
package/dist/core.d.cts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
interface StackItem {
|
|
2
|
-
componentName: string;
|
|
3
|
-
fileName: string | undefined;
|
|
4
|
-
}
|
|
5
|
-
declare const getStack: (element: Element) => Promise<StackItem[] | null>;
|
|
6
|
-
declare const filterStack: (stack: StackItem[]) => StackItem[];
|
|
7
|
-
declare const serializeStack: (stack: StackItem[]) => string;
|
|
8
|
-
declare const getHTMLSnippet: (element: Element) => string;
|
|
9
|
-
|
|
10
|
-
export { type StackItem, filterStack, getHTMLSnippet, getStack, serializeStack };
|
package/dist/core.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
interface StackItem {
|
|
2
|
-
componentName: string;
|
|
3
|
-
fileName: string | undefined;
|
|
4
|
-
}
|
|
5
|
-
declare const getStack: (element: Element) => Promise<StackItem[] | null>;
|
|
6
|
-
declare const filterStack: (stack: StackItem[]) => StackItem[];
|
|
7
|
-
declare const serializeStack: (stack: StackItem[]) => string;
|
|
8
|
-
declare const getHTMLSnippet: (element: Element) => string;
|
|
9
|
-
|
|
10
|
-
export { type StackItem, filterStack, getHTMLSnippet, getStack, serializeStack };
|
package/dist/core.js
DELETED
|
@@ -1,254 +0,0 @@
|
|
|
1
|
-
import { getFiberFromHostInstance } from 'bippy';
|
|
2
|
-
import { getFiberStackTrace, getOwnerStack } from 'bippy/dist/source';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* @license MIT
|
|
6
|
-
*
|
|
7
|
-
* Copyright (c) 2025 Aiden Bai
|
|
8
|
-
*
|
|
9
|
-
* This source code is licensed under the MIT license found in the
|
|
10
|
-
* LICENSE file in the root directory of this source tree.
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
var getStack = async (element) => {
|
|
14
|
-
const fiber = getFiberFromHostInstance(element);
|
|
15
|
-
if (!fiber) return null;
|
|
16
|
-
const stackTrace = getFiberStackTrace(fiber);
|
|
17
|
-
console.log(stackTrace);
|
|
18
|
-
const rawOwnerStack = await getOwnerStack(stackTrace);
|
|
19
|
-
console.log(rawOwnerStack);
|
|
20
|
-
const stack = rawOwnerStack.map((item) => ({
|
|
21
|
-
componentName: item.name,
|
|
22
|
-
fileName: item.source?.fileName
|
|
23
|
-
}));
|
|
24
|
-
return stack;
|
|
25
|
-
};
|
|
26
|
-
var filterStack = (stack) => {
|
|
27
|
-
return stack.filter(
|
|
28
|
-
(item) => item.fileName && !item.fileName.includes("node_modules") && item.componentName.length > 1 && !item.fileName.startsWith("_")
|
|
29
|
-
);
|
|
30
|
-
};
|
|
31
|
-
var findCommonRoot = (paths) => {
|
|
32
|
-
if (paths.length === 0) return "";
|
|
33
|
-
if (paths.length === 1) {
|
|
34
|
-
const lastSlash2 = paths[0].lastIndexOf("/");
|
|
35
|
-
return lastSlash2 > 0 ? paths[0].substring(0, lastSlash2 + 1) : "";
|
|
36
|
-
}
|
|
37
|
-
let commonPrefix = paths[0];
|
|
38
|
-
for (let i = 1; i < paths.length; i++) {
|
|
39
|
-
const path = paths[i];
|
|
40
|
-
let j = 0;
|
|
41
|
-
while (j < commonPrefix.length && j < path.length && commonPrefix[j] === path[j]) {
|
|
42
|
-
j++;
|
|
43
|
-
}
|
|
44
|
-
commonPrefix = commonPrefix.substring(0, j);
|
|
45
|
-
}
|
|
46
|
-
const lastSlash = commonPrefix.lastIndexOf("/");
|
|
47
|
-
return lastSlash > 0 ? commonPrefix.substring(0, lastSlash + 1) : "";
|
|
48
|
-
};
|
|
49
|
-
var serializeStack = (stack) => {
|
|
50
|
-
const filePaths = stack.map((item) => item.fileName).filter((path) => !!path);
|
|
51
|
-
const commonRoot = findCommonRoot(filePaths);
|
|
52
|
-
return stack.map((item) => {
|
|
53
|
-
let fileName = item.fileName;
|
|
54
|
-
if (fileName && commonRoot) {
|
|
55
|
-
fileName = fileName.startsWith(commonRoot) ? fileName.substring(commonRoot.length) : fileName;
|
|
56
|
-
}
|
|
57
|
-
return `${item.componentName}${fileName ? ` (${fileName})` : ""}`;
|
|
58
|
-
}).join("\n");
|
|
59
|
-
};
|
|
60
|
-
var getHTMLSnippet = (element) => {
|
|
61
|
-
const semanticTags = /* @__PURE__ */ new Set([
|
|
62
|
-
"article",
|
|
63
|
-
"aside",
|
|
64
|
-
"footer",
|
|
65
|
-
"form",
|
|
66
|
-
"header",
|
|
67
|
-
"main",
|
|
68
|
-
"nav",
|
|
69
|
-
"section"
|
|
70
|
-
]);
|
|
71
|
-
const hasDistinguishingFeatures = (el) => {
|
|
72
|
-
const tagName = el.tagName.toLowerCase();
|
|
73
|
-
if (semanticTags.has(tagName)) return true;
|
|
74
|
-
if (el.id) return true;
|
|
75
|
-
if (el.className && typeof el.className === "string") {
|
|
76
|
-
const classes = el.className.trim();
|
|
77
|
-
if (classes && classes.length > 0) return true;
|
|
78
|
-
}
|
|
79
|
-
return Array.from(el.attributes).some(
|
|
80
|
-
(attr) => attr.name.startsWith("data-")
|
|
81
|
-
);
|
|
82
|
-
};
|
|
83
|
-
const getAncestorChain = (el, maxDepth = 10) => {
|
|
84
|
-
const ancestors2 = [];
|
|
85
|
-
let current = el.parentElement;
|
|
86
|
-
let depth = 0;
|
|
87
|
-
while (current && depth < maxDepth && current.tagName !== "BODY") {
|
|
88
|
-
if (hasDistinguishingFeatures(current)) {
|
|
89
|
-
ancestors2.push(current);
|
|
90
|
-
if (ancestors2.length >= 3) break;
|
|
91
|
-
}
|
|
92
|
-
current = current.parentElement;
|
|
93
|
-
depth++;
|
|
94
|
-
}
|
|
95
|
-
return ancestors2.reverse();
|
|
96
|
-
};
|
|
97
|
-
const getCSSPath = (el) => {
|
|
98
|
-
const parts = [];
|
|
99
|
-
let current = el;
|
|
100
|
-
let depth = 0;
|
|
101
|
-
const maxDepth = 5;
|
|
102
|
-
while (current && depth < maxDepth && current.tagName !== "BODY") {
|
|
103
|
-
let selector = current.tagName.toLowerCase();
|
|
104
|
-
if (current.id) {
|
|
105
|
-
selector += `#${current.id}`;
|
|
106
|
-
parts.unshift(selector);
|
|
107
|
-
break;
|
|
108
|
-
} else if (current.className && typeof current.className === "string" && current.className.trim()) {
|
|
109
|
-
const classes = current.className.trim().split(/\s+/).slice(0, 2);
|
|
110
|
-
selector += `.${classes.join(".")}`;
|
|
111
|
-
}
|
|
112
|
-
if (!current.id && (!current.className || !current.className.trim()) && current.parentElement) {
|
|
113
|
-
const siblings = Array.from(current.parentElement.children);
|
|
114
|
-
const index = siblings.indexOf(current);
|
|
115
|
-
if (index >= 0 && siblings.length > 1) {
|
|
116
|
-
selector += `:nth-child(${index + 1})`;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
parts.unshift(selector);
|
|
120
|
-
current = current.parentElement;
|
|
121
|
-
depth++;
|
|
122
|
-
}
|
|
123
|
-
return parts.join(" > ");
|
|
124
|
-
};
|
|
125
|
-
const getElementTag = (el, compact = false) => {
|
|
126
|
-
const tagName = el.tagName.toLowerCase();
|
|
127
|
-
const attrs = [];
|
|
128
|
-
if (el.id) {
|
|
129
|
-
attrs.push(`id="${el.id}"`);
|
|
130
|
-
}
|
|
131
|
-
if (el.className && typeof el.className === "string") {
|
|
132
|
-
const classes = el.className.trim().split(/\s+/);
|
|
133
|
-
if (classes.length > 0 && classes[0]) {
|
|
134
|
-
const displayClasses = compact ? classes.slice(0, 3) : classes;
|
|
135
|
-
let classStr = displayClasses.join(" ");
|
|
136
|
-
if (classStr.length > 30) {
|
|
137
|
-
classStr = classStr.substring(0, 30) + "...";
|
|
138
|
-
}
|
|
139
|
-
attrs.push(`class="${classStr}"`);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
const dataAttrs = Array.from(el.attributes).filter(
|
|
143
|
-
(attr) => attr.name.startsWith("data-")
|
|
144
|
-
);
|
|
145
|
-
const displayDataAttrs = compact ? dataAttrs.slice(0, 1) : dataAttrs;
|
|
146
|
-
for (const attr of displayDataAttrs) {
|
|
147
|
-
let value = attr.value;
|
|
148
|
-
if (value.length > 20) {
|
|
149
|
-
value = value.substring(0, 20) + "...";
|
|
150
|
-
}
|
|
151
|
-
attrs.push(`${attr.name}="${value}"`);
|
|
152
|
-
}
|
|
153
|
-
const ariaLabel = el.getAttribute("aria-label");
|
|
154
|
-
if (ariaLabel && !compact) {
|
|
155
|
-
let value = ariaLabel;
|
|
156
|
-
if (value.length > 20) {
|
|
157
|
-
value = value.substring(0, 20) + "...";
|
|
158
|
-
}
|
|
159
|
-
attrs.push(`aria-label="${value}"`);
|
|
160
|
-
}
|
|
161
|
-
return attrs.length > 0 ? `<${tagName} ${attrs.join(" ")}>` : `<${tagName}>`;
|
|
162
|
-
};
|
|
163
|
-
const getClosingTag = (el) => {
|
|
164
|
-
return `</${el.tagName.toLowerCase()}>`;
|
|
165
|
-
};
|
|
166
|
-
const getTextContent = (el) => {
|
|
167
|
-
let text = el.textContent || "";
|
|
168
|
-
text = text.trim().replace(/\s+/g, " ");
|
|
169
|
-
const maxLength = 60;
|
|
170
|
-
if (text.length > maxLength) {
|
|
171
|
-
text = text.substring(0, maxLength) + "...";
|
|
172
|
-
}
|
|
173
|
-
return text;
|
|
174
|
-
};
|
|
175
|
-
const getSiblingIdentifier = (el) => {
|
|
176
|
-
if (el.id) return `#${el.id}`;
|
|
177
|
-
if (el.className && typeof el.className === "string") {
|
|
178
|
-
const classes = el.className.trim().split(/\s+/);
|
|
179
|
-
if (classes.length > 0 && classes[0]) {
|
|
180
|
-
return `.${classes[0]}`;
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
return null;
|
|
184
|
-
};
|
|
185
|
-
const lines = [];
|
|
186
|
-
lines.push(`Path: ${getCSSPath(element)}`);
|
|
187
|
-
lines.push("");
|
|
188
|
-
const ancestors = getAncestorChain(element);
|
|
189
|
-
for (let i = 0; i < ancestors.length; i++) {
|
|
190
|
-
const indent2 = " ".repeat(i);
|
|
191
|
-
lines.push(indent2 + getElementTag(ancestors[i], true));
|
|
192
|
-
}
|
|
193
|
-
const parent = element.parentElement;
|
|
194
|
-
let targetIndex = -1;
|
|
195
|
-
if (parent) {
|
|
196
|
-
const siblings = Array.from(parent.children);
|
|
197
|
-
targetIndex = siblings.indexOf(element);
|
|
198
|
-
if (targetIndex > 0) {
|
|
199
|
-
const prevSibling = siblings[targetIndex - 1];
|
|
200
|
-
const prevId = getSiblingIdentifier(prevSibling);
|
|
201
|
-
if (prevId && targetIndex <= 2) {
|
|
202
|
-
const indent2 = " ".repeat(ancestors.length);
|
|
203
|
-
lines.push(`${indent2} ${getElementTag(prevSibling, true)}`);
|
|
204
|
-
lines.push(`${indent2} </${prevSibling.tagName.toLowerCase()}>`);
|
|
205
|
-
} else if (targetIndex > 0) {
|
|
206
|
-
const indent2 = " ".repeat(ancestors.length);
|
|
207
|
-
lines.push(`${indent2} ... (${targetIndex} element${targetIndex === 1 ? "" : "s"})`);
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
const indent = " ".repeat(ancestors.length);
|
|
212
|
-
lines.push(indent + " <!-- SELECTED -->");
|
|
213
|
-
const textContent = getTextContent(element);
|
|
214
|
-
const childrenCount = element.children.length;
|
|
215
|
-
if (textContent && childrenCount === 0 && textContent.length < 40) {
|
|
216
|
-
lines.push(
|
|
217
|
-
`${indent} ${getElementTag(element)}${textContent}${getClosingTag(element)}`
|
|
218
|
-
);
|
|
219
|
-
} else {
|
|
220
|
-
lines.push(indent + " " + getElementTag(element));
|
|
221
|
-
if (textContent) {
|
|
222
|
-
lines.push(`${indent} ${textContent}`);
|
|
223
|
-
}
|
|
224
|
-
if (childrenCount > 0) {
|
|
225
|
-
lines.push(
|
|
226
|
-
`${indent} ... (${childrenCount} element${childrenCount === 1 ? "" : "s"})`
|
|
227
|
-
);
|
|
228
|
-
}
|
|
229
|
-
lines.push(indent + " " + getClosingTag(element));
|
|
230
|
-
}
|
|
231
|
-
if (parent && targetIndex >= 0) {
|
|
232
|
-
const siblings = Array.from(parent.children);
|
|
233
|
-
const siblingsAfter = siblings.length - targetIndex - 1;
|
|
234
|
-
if (siblingsAfter > 0) {
|
|
235
|
-
const nextSibling = siblings[targetIndex + 1];
|
|
236
|
-
const nextId = getSiblingIdentifier(nextSibling);
|
|
237
|
-
if (nextId && siblingsAfter <= 2) {
|
|
238
|
-
lines.push(`${indent} ${getElementTag(nextSibling, true)}`);
|
|
239
|
-
lines.push(`${indent} </${nextSibling.tagName.toLowerCase()}>`);
|
|
240
|
-
} else {
|
|
241
|
-
lines.push(
|
|
242
|
-
`${indent} ... (${siblingsAfter} element${siblingsAfter === 1 ? "" : "s"})`
|
|
243
|
-
);
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
for (let i = ancestors.length - 1; i >= 0; i--) {
|
|
248
|
-
const indent2 = " ".repeat(i);
|
|
249
|
-
lines.push(indent2 + getClosingTag(ancestors[i]));
|
|
250
|
-
}
|
|
251
|
-
return lines.join("\n");
|
|
252
|
-
};
|
|
253
|
-
|
|
254
|
-
export { filterStack, getHTMLSnippet, getStack, serializeStack };
|