@treelocator/runtime 0.1.7 → 0.1.8
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/.turbo/turbo-build.log +10 -10
- package/dist/adapters/adapterApi.d.ts +1 -1
- package/dist/adapters/jsx/getExpressionData.d.ts +1 -1
- package/dist/adapters/jsx/getExpressionData.js +8 -4
- package/dist/adapters/jsx/getJSXComponentBoundingBox.d.ts +1 -1
- package/dist/adapters/jsx/getJSXComponentBoundingBox.js +11 -6
- package/dist/adapters/jsx/jsxAdapter.js +13 -8
- package/dist/components/Runtime.js +1 -1
- package/package.json +2 -2
- package/src/adapters/adapterApi.ts +1 -1
- package/src/adapters/jsx/getExpressionData.ts +9 -5
- package/src/adapters/jsx/getJSXComponentBoundingBox.ts +13 -8
- package/src/adapters/jsx/jsxAdapter.ts +14 -12
- package/src/components/Runtime.tsx +3 -1
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
|
|
2
|
-
> @treelocator/runtime@0.1.
|
|
2
|
+
> @treelocator/runtime@0.1.8 build /Users/wende/projects/locatorjs/packages/runtime
|
|
3
3
|
> concurrently pnpm:build:*
|
|
4
4
|
|
|
5
|
+
[tailwind]
|
|
6
|
+
[tailwind] > @treelocator/runtime@0.1.8 build:tailwind /Users/wende/projects/locatorjs/packages/runtime
|
|
7
|
+
[tailwind] > tailwindcss -i ./src/main.css -o ./dist/output.css
|
|
8
|
+
[tailwind]
|
|
5
9
|
[babel]
|
|
6
|
-
[babel] > @treelocator/runtime@0.1.
|
|
10
|
+
[babel] > @treelocator/runtime@0.1.8 build:babel /Users/wende/projects/locatorjs/packages/runtime
|
|
7
11
|
[babel] > babel src --out-dir dist --extensions .js,.jsx,.ts,.tsx
|
|
8
12
|
[babel]
|
|
9
13
|
[ts]
|
|
10
|
-
[ts] > @treelocator/runtime@0.1.
|
|
14
|
+
[ts] > @treelocator/runtime@0.1.8 build:ts /Users/wende/projects/locatorjs/packages/runtime
|
|
11
15
|
[ts] > tsc --declaration --emitDeclarationOnly --noEmit false --outDir dist
|
|
12
16
|
[ts]
|
|
13
17
|
[wrapImage]
|
|
14
|
-
[wrapImage] > @treelocator/runtime@0.1.
|
|
18
|
+
[wrapImage] > @treelocator/runtime@0.1.8 build:wrapImage /Users/wende/projects/locatorjs/packages/runtime
|
|
15
19
|
[wrapImage] > node ./scripts/wrapImage.js
|
|
16
20
|
[wrapImage]
|
|
17
|
-
[tailwind]
|
|
18
|
-
[tailwind] > @treelocator/runtime@0.1.7 build:tailwind /Users/wende/projects/locatorjs/packages/runtime
|
|
19
|
-
[tailwind] > tailwindcss -i ./src/main.css -o ./dist/output.css
|
|
20
|
-
[tailwind]
|
|
21
21
|
[wrapImage] Tree icon file generated
|
|
22
22
|
[wrapImage] pnpm run build:wrapImage exited with code 0
|
|
23
23
|
[tailwind]
|
|
24
24
|
[tailwind] Rebuilding...
|
|
25
25
|
[tailwind]
|
|
26
|
-
[tailwind] Done in
|
|
26
|
+
[tailwind] Done in 164ms.
|
|
27
27
|
[tailwind] pnpm run build:tailwind exited with code 0
|
|
28
|
-
[babel] Successfully compiled 72 files with Babel (
|
|
28
|
+
[babel] Successfully compiled 72 files with Babel (409ms).
|
|
29
29
|
[babel] pnpm run build:babel exited with code 0
|
|
30
30
|
[ts] pnpm run build:ts exited with code 0
|
|
@@ -8,7 +8,7 @@ export type ElementInfo = {
|
|
|
8
8
|
};
|
|
9
9
|
export type FullElementInfo = {
|
|
10
10
|
thisElement: ElementInfo;
|
|
11
|
-
htmlElement: HTMLElement;
|
|
11
|
+
htmlElement: HTMLElement | SVGElement;
|
|
12
12
|
parentElements: ElementInfo[];
|
|
13
13
|
componentBox: SimpleDOMRect;
|
|
14
14
|
componentsLabels: LabelData[];
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { ExpressionInfo, FileStorage } from "@locator/shared";
|
|
2
|
-
export declare function getExpressionData(target:
|
|
2
|
+
export declare function getExpressionData(target: Element, fileData: FileStorage | null): ExpressionInfo | null;
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import { parseDataId, parseDataPath } from "../../functions/parseDataId";
|
|
2
2
|
export function getExpressionData(target, fileData) {
|
|
3
|
+
// Use getAttribute instead of dataset to support both HTML and SVG elements
|
|
4
|
+
const dataLocatorjs = target.getAttribute("data-locatorjs");
|
|
5
|
+
const dataLocatorjsId = target.getAttribute("data-locatorjs-id");
|
|
6
|
+
|
|
3
7
|
// First check for data-locatorjs (path-based, for server components)
|
|
4
|
-
if (
|
|
5
|
-
const parsed = parseDataPath(
|
|
8
|
+
if (dataLocatorjs) {
|
|
9
|
+
const parsed = parseDataPath(dataLocatorjs);
|
|
6
10
|
if (parsed) {
|
|
7
11
|
const [, line, column] = parsed;
|
|
8
12
|
|
|
@@ -33,8 +37,8 @@ export function getExpressionData(target, fileData) {
|
|
|
33
37
|
}
|
|
34
38
|
|
|
35
39
|
// Fall back to data-locatorjs-id (ID-based, traditional approach)
|
|
36
|
-
if (
|
|
37
|
-
const [, id] = parseDataId(
|
|
40
|
+
if (dataLocatorjsId && fileData) {
|
|
41
|
+
const [, id] = parseDataId(dataLocatorjsId);
|
|
38
42
|
const expData = fileData.expressions[Number(id)];
|
|
39
43
|
if (expData) {
|
|
40
44
|
return expData;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { FileStorage } from "@locator/shared";
|
|
2
2
|
import type { SimpleDOMRect } from "../../types/types";
|
|
3
|
-
export declare function getJSXComponentBoundingBox(found:
|
|
3
|
+
export declare function getJSXComponentBoundingBox(found: Element, locatorData: {
|
|
4
4
|
[filename: string]: FileStorage;
|
|
5
5
|
}, componentFolder: string, componentId: number): SimpleDOMRect;
|
|
@@ -9,19 +9,24 @@ export function getJSXComponentBoundingBox(found, locatorData, componentFolder,
|
|
|
9
9
|
if (!parent) {
|
|
10
10
|
return;
|
|
11
11
|
}
|
|
12
|
-
|
|
12
|
+
// Support both HTMLElement and SVGElement
|
|
13
|
+
if (parent instanceof HTMLElement || parent instanceof SVGElement) {
|
|
14
|
+
// Use getAttribute instead of dataset to support both HTML and SVG elements
|
|
15
|
+
const dataLocatorjs = parent.getAttribute("data-locatorjs");
|
|
16
|
+
const dataLocatorjsId = parent.getAttribute("data-locatorjs-id");
|
|
17
|
+
|
|
13
18
|
// Check for either data-locatorjs (path-based) or data-locatorjs-id (ID-based)
|
|
14
|
-
if (
|
|
19
|
+
if (dataLocatorjs || dataLocatorjsId) {
|
|
15
20
|
let fileFullPath;
|
|
16
|
-
if (
|
|
17
|
-
const parsed = parseDataPath(
|
|
21
|
+
if (dataLocatorjs) {
|
|
22
|
+
const parsed = parseDataPath(dataLocatorjs);
|
|
18
23
|
if (!parsed) {
|
|
19
24
|
goParent(parent);
|
|
20
25
|
return;
|
|
21
26
|
}
|
|
22
27
|
[fileFullPath] = parsed;
|
|
23
|
-
} else if (
|
|
24
|
-
[fileFullPath] = parseDataId(
|
|
28
|
+
} else if (dataLocatorjsId) {
|
|
29
|
+
[fileFullPath] = parseDataId(dataLocatorjsId);
|
|
25
30
|
} else {
|
|
26
31
|
goParent(parent);
|
|
27
32
|
return;
|
|
@@ -5,10 +5,13 @@ import { getExpressionData } from "./getExpressionData";
|
|
|
5
5
|
import { getJSXComponentBoundingBox } from "./getJSXComponentBoundingBox";
|
|
6
6
|
export function getElementInfo(target) {
|
|
7
7
|
const found = target.closest("[data-locatorjs-id], [data-locatorjs]");
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
|
|
9
|
+
// Support both HTMLElement and SVGElement
|
|
10
|
+
// SVG elements don't have dataset, so use getAttribute instead
|
|
11
|
+
const dataId = found?.getAttribute("data-locatorjs-id");
|
|
12
|
+
const dataPath = found?.getAttribute("data-locatorjs");
|
|
13
|
+
const styledDataId = found?.getAttribute("data-locatorjs-styled");
|
|
14
|
+
if (found && (found instanceof HTMLElement || found instanceof SVGElement) && (dataId || dataPath || styledDataId)) {
|
|
12
15
|
if (!dataId && !dataPath) {
|
|
13
16
|
return null;
|
|
14
17
|
}
|
|
@@ -89,8 +92,9 @@ export function getElementInfo(target) {
|
|
|
89
92
|
}
|
|
90
93
|
export class JSXTreeNodeElement extends HtmlElementTreeNode {
|
|
91
94
|
getSource() {
|
|
92
|
-
|
|
93
|
-
const
|
|
95
|
+
// Use getAttribute instead of dataset to support both HTML and SVG elements
|
|
96
|
+
const dataId = this.element.getAttribute("data-locatorjs-id");
|
|
97
|
+
const dataPath = this.element.getAttribute("data-locatorjs");
|
|
94
98
|
if (!dataId && !dataPath) {
|
|
95
99
|
return null;
|
|
96
100
|
}
|
|
@@ -131,8 +135,9 @@ export class JSXTreeNodeElement extends HtmlElementTreeNode {
|
|
|
131
135
|
return null;
|
|
132
136
|
}
|
|
133
137
|
getComponent() {
|
|
134
|
-
|
|
135
|
-
const
|
|
138
|
+
// Use getAttribute instead of dataset to support both HTML and SVG elements
|
|
139
|
+
const dataId = this.element.getAttribute("data-locatorjs-id");
|
|
140
|
+
const dataPath = this.element.getAttribute("data-locatorjs");
|
|
136
141
|
if (!dataId && !dataPath) {
|
|
137
142
|
return null;
|
|
138
143
|
}
|
|
@@ -64,7 +64,7 @@ function Runtime(props) {
|
|
|
64
64
|
if (!element) {
|
|
65
65
|
const target = e.target;
|
|
66
66
|
if (target && (target instanceof HTMLElement || target instanceof SVGElement)) {
|
|
67
|
-
element = target instanceof SVGElement ? target.closest('svg') ?? target : target;
|
|
67
|
+
element = target instanceof SVGElement ? target.closest('[data-locatorjs-id], [data-locatorjs]') ?? target.closest('svg') ?? target : target;
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
if (element && !isLocatorsOwnElement(element)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@treelocator/runtime",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"description": "TreeLocatorJS runtime for component ancestry tracking. Alt+click any element to copy its component tree to clipboard. Exposes window.__treelocator__ API for browser automation (Playwright, Puppeteer, Selenium, Cypress).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"locator",
|
|
@@ -72,5 +72,5 @@
|
|
|
72
72
|
"directory": "packages/runtime"
|
|
73
73
|
},
|
|
74
74
|
"license": "MIT",
|
|
75
|
-
"gitHead": "
|
|
75
|
+
"gitHead": "69fb05167bd689b2e3602fcbc74a70912695f136"
|
|
76
76
|
}
|
|
@@ -10,7 +10,7 @@ export type ElementInfo = {
|
|
|
10
10
|
|
|
11
11
|
export type FullElementInfo = {
|
|
12
12
|
thisElement: ElementInfo;
|
|
13
|
-
htmlElement: HTMLElement;
|
|
13
|
+
htmlElement: HTMLElement | SVGElement;
|
|
14
14
|
parentElements: ElementInfo[];
|
|
15
15
|
componentBox: SimpleDOMRect;
|
|
16
16
|
componentsLabels: LabelData[];
|
|
@@ -2,12 +2,16 @@ import type { ExpressionInfo, FileStorage } from "@locator/shared";
|
|
|
2
2
|
import { parseDataId, parseDataPath } from "../../functions/parseDataId";
|
|
3
3
|
|
|
4
4
|
export function getExpressionData(
|
|
5
|
-
target:
|
|
5
|
+
target: Element,
|
|
6
6
|
fileData: FileStorage | null
|
|
7
7
|
): ExpressionInfo | null {
|
|
8
|
+
// Use getAttribute instead of dataset to support both HTML and SVG elements
|
|
9
|
+
const dataLocatorjs = target.getAttribute("data-locatorjs");
|
|
10
|
+
const dataLocatorjsId = target.getAttribute("data-locatorjs-id");
|
|
11
|
+
|
|
8
12
|
// First check for data-locatorjs (path-based, for server components)
|
|
9
|
-
if (
|
|
10
|
-
const parsed = parseDataPath(
|
|
13
|
+
if (dataLocatorjs) {
|
|
14
|
+
const parsed = parseDataPath(dataLocatorjs);
|
|
11
15
|
if (parsed) {
|
|
12
16
|
const [, line, column] = parsed;
|
|
13
17
|
|
|
@@ -35,8 +39,8 @@ export function getExpressionData(
|
|
|
35
39
|
}
|
|
36
40
|
|
|
37
41
|
// Fall back to data-locatorjs-id (ID-based, traditional approach)
|
|
38
|
-
if (
|
|
39
|
-
const [, id] = parseDataId(
|
|
42
|
+
if (dataLocatorjsId && fileData) {
|
|
43
|
+
const [, id] = parseDataId(dataLocatorjsId);
|
|
40
44
|
const expData = fileData.expressions[Number(id)];
|
|
41
45
|
if (expData) {
|
|
42
46
|
return expData;
|
|
@@ -5,32 +5,37 @@ import type { SimpleDOMRect } from "../../types/types";
|
|
|
5
5
|
import { getExpressionData } from "./getExpressionData";
|
|
6
6
|
|
|
7
7
|
export function getJSXComponentBoundingBox(
|
|
8
|
-
found:
|
|
8
|
+
found: Element,
|
|
9
9
|
locatorData: { [filename: string]: FileStorage },
|
|
10
10
|
componentFolder: string,
|
|
11
11
|
componentId: number
|
|
12
12
|
): SimpleDOMRect {
|
|
13
13
|
let composedBox: SimpleDOMRect = found.getBoundingClientRect();
|
|
14
14
|
// Currently it works well only for components with one root element, but for components with multiple root elements we would need to track instance ids.
|
|
15
|
-
function goParent(current:
|
|
15
|
+
function goParent(current: Element) {
|
|
16
16
|
const parent = current.parentNode;
|
|
17
17
|
if (!parent) {
|
|
18
18
|
return;
|
|
19
19
|
}
|
|
20
|
-
|
|
20
|
+
// Support both HTMLElement and SVGElement
|
|
21
|
+
if (parent instanceof HTMLElement || parent instanceof SVGElement) {
|
|
22
|
+
// Use getAttribute instead of dataset to support both HTML and SVG elements
|
|
23
|
+
const dataLocatorjs = parent.getAttribute("data-locatorjs");
|
|
24
|
+
const dataLocatorjsId = parent.getAttribute("data-locatorjs-id");
|
|
25
|
+
|
|
21
26
|
// Check for either data-locatorjs (path-based) or data-locatorjs-id (ID-based)
|
|
22
|
-
if (
|
|
27
|
+
if (dataLocatorjs || dataLocatorjsId) {
|
|
23
28
|
let fileFullPath: string;
|
|
24
29
|
|
|
25
|
-
if (
|
|
26
|
-
const parsed = parseDataPath(
|
|
30
|
+
if (dataLocatorjs) {
|
|
31
|
+
const parsed = parseDataPath(dataLocatorjs);
|
|
27
32
|
if (!parsed) {
|
|
28
33
|
goParent(parent);
|
|
29
34
|
return;
|
|
30
35
|
}
|
|
31
36
|
[fileFullPath] = parsed;
|
|
32
|
-
} else if (
|
|
33
|
-
[fileFullPath] = parseDataId(
|
|
37
|
+
} else if (dataLocatorjsId) {
|
|
38
|
+
[fileFullPath] = parseDataId(dataLocatorjsId);
|
|
34
39
|
} else {
|
|
35
40
|
goParent(parent);
|
|
36
41
|
return;
|
|
@@ -20,17 +20,17 @@ import { getJSXComponentBoundingBox } from "./getJSXComponentBoundingBox";
|
|
|
20
20
|
export function getElementInfo(target: HTMLElement): FullElementInfo | null {
|
|
21
21
|
const found = target.closest("[data-locatorjs-id], [data-locatorjs]");
|
|
22
22
|
|
|
23
|
+
// Support both HTMLElement and SVGElement
|
|
24
|
+
// SVG elements don't have dataset, so use getAttribute instead
|
|
25
|
+
const dataId = found?.getAttribute("data-locatorjs-id");
|
|
26
|
+
const dataPath = found?.getAttribute("data-locatorjs");
|
|
27
|
+
const styledDataId = found?.getAttribute("data-locatorjs-styled");
|
|
28
|
+
|
|
23
29
|
if (
|
|
24
30
|
found &&
|
|
25
|
-
found instanceof HTMLElement &&
|
|
26
|
-
|
|
27
|
-
(found.dataset.locatorjsId ||
|
|
28
|
-
found.dataset.locatorjs ||
|
|
29
|
-
found.dataset.locatorjsStyled)
|
|
31
|
+
(found instanceof HTMLElement || found instanceof SVGElement) &&
|
|
32
|
+
(dataId || dataPath || styledDataId)
|
|
30
33
|
) {
|
|
31
|
-
const dataId = found.dataset.locatorjsId;
|
|
32
|
-
const dataPath = found.dataset.locatorjs;
|
|
33
|
-
const styledDataId = found.dataset.locatorjsStyled;
|
|
34
34
|
|
|
35
35
|
if (!dataId && !dataPath) {
|
|
36
36
|
return null;
|
|
@@ -135,8 +135,9 @@ export function getElementInfo(target: HTMLElement): FullElementInfo | null {
|
|
|
135
135
|
|
|
136
136
|
export class JSXTreeNodeElement extends HtmlElementTreeNode {
|
|
137
137
|
getSource(): Source | null {
|
|
138
|
-
|
|
139
|
-
const
|
|
138
|
+
// Use getAttribute instead of dataset to support both HTML and SVG elements
|
|
139
|
+
const dataId = this.element.getAttribute("data-locatorjs-id");
|
|
140
|
+
const dataPath = this.element.getAttribute("data-locatorjs");
|
|
140
141
|
|
|
141
142
|
if (!dataId && !dataPath) {
|
|
142
143
|
return null;
|
|
@@ -184,8 +185,9 @@ export class JSXTreeNodeElement extends HtmlElementTreeNode {
|
|
|
184
185
|
return null;
|
|
185
186
|
}
|
|
186
187
|
getComponent(): TreeNodeComponent | null {
|
|
187
|
-
|
|
188
|
-
const
|
|
188
|
+
// Use getAttribute instead of dataset to support both HTML and SVG elements
|
|
189
|
+
const dataId = this.element.getAttribute("data-locatorjs-id");
|
|
190
|
+
const dataPath = this.element.getAttribute("data-locatorjs");
|
|
189
191
|
|
|
190
192
|
if (!dataId && !dataPath) {
|
|
191
193
|
return null;
|
|
@@ -74,7 +74,9 @@ function Runtime(props: RuntimeProps) {
|
|
|
74
74
|
const target = e.target;
|
|
75
75
|
if (target && (target instanceof HTMLElement || target instanceof SVGElement)) {
|
|
76
76
|
element = target instanceof SVGElement
|
|
77
|
-
? (target.closest('
|
|
77
|
+
? (target.closest('[data-locatorjs-id], [data-locatorjs]') as HTMLElement | null) ??
|
|
78
|
+
(target.closest('svg') as HTMLElement | null) ??
|
|
79
|
+
(target as unknown as HTMLElement)
|
|
78
80
|
: target;
|
|
79
81
|
}
|
|
80
82
|
}
|