@treelocator/runtime 0.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.
- package/.eslintrc +3 -0
- package/.turbo/turbo-build.log +30 -0
- package/.turbo/turbo-test.log +18 -0
- package/.turbo/turbo-ts.log +4 -0
- package/LICENSE +22 -0
- package/babel.config.js +14 -0
- package/dist/_generated_styles.d.ts +2 -0
- package/dist/_generated_styles.js +1734 -0
- package/dist/_generated_tree_icon.d.ts +2 -0
- package/dist/_generated_tree_icon.js +2 -0
- package/dist/adapters/HtmlElementTreeNode.d.ts +16 -0
- package/dist/adapters/HtmlElementTreeNode.js +43 -0
- package/dist/adapters/adapterApi.d.ts +30 -0
- package/dist/adapters/adapterApi.js +1 -0
- package/dist/adapters/createTreeNode.d.ts +2 -0
- package/dist/adapters/createTreeNode.js +17 -0
- package/dist/adapters/getElementInfo.d.ts +2 -0
- package/dist/adapters/getElementInfo.js +19 -0
- package/dist/adapters/getParentsPath.d.ts +2 -0
- package/dist/adapters/getParentsPath.js +35 -0
- package/dist/adapters/getTree.d.ts +1 -0
- package/dist/adapters/getTree.js +35 -0
- package/dist/adapters/goUpByTheTree.d.ts +7 -0
- package/dist/adapters/goUpByTheTree.js +22 -0
- package/dist/adapters/jsx/getExpressionData.d.ts +2 -0
- package/dist/adapters/jsx/getExpressionData.js +44 -0
- package/dist/adapters/jsx/getJSXComponentBoundingBox.d.ts +5 -0
- package/dist/adapters/jsx/getJSXComponentBoundingBox.js +46 -0
- package/dist/adapters/jsx/jsxAdapter.d.ts +11 -0
- package/dist/adapters/jsx/jsxAdapter.js +208 -0
- package/dist/adapters/jsx/runtimeStore.d.ts +10 -0
- package/dist/adapters/jsx/runtimeStore.js +87 -0
- package/dist/adapters/react/fiberToSimple.d.ts +3 -0
- package/dist/adapters/react/fiberToSimple.js +55 -0
- package/dist/adapters/react/findDebugSource.d.ts +5 -0
- package/dist/adapters/react/findDebugSource.js +13 -0
- package/dist/adapters/react/findFiberByHtmlElement.d.ts +2 -0
- package/dist/adapters/react/findFiberByHtmlElement.js +22 -0
- package/dist/adapters/react/gatherFiberRoots.d.ts +2 -0
- package/dist/adapters/react/gatherFiberRoots.js +29 -0
- package/dist/adapters/react/getAllFiberChildren.d.ts +2 -0
- package/dist/adapters/react/getAllFiberChildren.js +9 -0
- package/dist/adapters/react/getAllParentsElementsAndRootComponent.d.ts +8 -0
- package/dist/adapters/react/getAllParentsElementsAndRootComponent.js +34 -0
- package/dist/adapters/react/getAllWrappingParents.d.ts +2 -0
- package/dist/adapters/react/getAllWrappingParents.js +19 -0
- package/dist/adapters/react/getFiberComponentBoundingBox.d.ts +3 -0
- package/dist/adapters/react/getFiberComponentBoundingBox.js +27 -0
- package/dist/adapters/react/getFiberLabel.d.ts +3 -0
- package/dist/adapters/react/getFiberLabel.js +14 -0
- package/dist/adapters/react/getFiberOwnBoundingBox.d.ts +3 -0
- package/dist/adapters/react/getFiberOwnBoundingBox.js +6 -0
- package/dist/adapters/react/isStyled.d.ts +2 -0
- package/dist/adapters/react/isStyled.js +3 -0
- package/dist/adapters/react/makeFiberId.d.ts +2 -0
- package/dist/adapters/react/makeFiberId.js +16 -0
- package/dist/adapters/react/reactAdapter.d.ts +11 -0
- package/dist/adapters/react/reactAdapter.js +114 -0
- package/dist/adapters/react/searchDevtoolsRenderersForClosestTarget.d.ts +1 -0
- package/dist/adapters/react/searchDevtoolsRenderersForClosestTarget.js +11 -0
- package/dist/adapters/svelte/svelteAdapter.d.ts +22 -0
- package/dist/adapters/svelte/svelteAdapter.js +88 -0
- package/dist/adapters/vue/getVNodeBoundingBox.d.ts +4 -0
- package/dist/adapters/vue/getVNodeBoundingBox.js +31 -0
- package/dist/adapters/vue/vueAdapter.d.ts +15 -0
- package/dist/adapters/vue/vueAdapter.js +113 -0
- package/dist/browserApi.d.ts +103 -0
- package/dist/browserApi.js +160 -0
- package/dist/components/Button.d.ts +4 -0
- package/dist/components/Button.js +17 -0
- package/dist/components/ComponentOutline.d.ts +7 -0
- package/dist/components/ComponentOutline.js +93 -0
- package/dist/components/MaybeOutline.d.ts +7 -0
- package/dist/components/MaybeOutline.js +43 -0
- package/dist/components/Outline.d.ts +25 -0
- package/dist/components/Outline.js +135 -0
- package/dist/components/RenderBoxes.d.ts +4 -0
- package/dist/components/RenderBoxes.js +73 -0
- package/dist/components/Runtime.d.ts +3 -0
- package/dist/components/Runtime.js +188 -0
- package/dist/components/SimpleNodeOutline.d.ts +4 -0
- package/dist/components/SimpleNodeOutline.js +47 -0
- package/dist/components/Toast.d.ts +4 -0
- package/dist/components/Toast.js +68 -0
- package/dist/components/Tooltip.d.ts +5 -0
- package/dist/components/Tooltip.js +21 -0
- package/dist/consts.d.ts +6 -0
- package/dist/consts.js +5 -0
- package/dist/functions/cropPath.d.ts +1 -0
- package/dist/functions/cropPath.js +9 -0
- package/dist/functions/cropPath.test.d.ts +1 -0
- package/dist/functions/cropPath.test.js +16 -0
- package/dist/functions/deduplicateLabels.d.ts +2 -0
- package/dist/functions/deduplicateLabels.js +12 -0
- package/dist/functions/evalTemplate.d.ts +3 -0
- package/dist/functions/evalTemplate.js +7 -0
- package/dist/functions/evalTemplate.test.d.ts +1 -0
- package/dist/functions/evalTemplate.test.js +11 -0
- package/dist/functions/findNames.d.ts +5 -0
- package/dist/functions/findNames.js +15 -0
- package/dist/functions/formatAncestryChain.d.ts +9 -0
- package/dist/functions/formatAncestryChain.js +56 -0
- package/dist/functions/getBoundingRect.d.ts +1 -0
- package/dist/functions/getBoundingRect.js +11 -0
- package/dist/functions/getComposedBoundingBox.d.ts +2 -0
- package/dist/functions/getComposedBoundingBox.js +20 -0
- package/dist/functions/getIdsOnPathToRoot.d.ts +3 -0
- package/dist/functions/getIdsOnPathToRoot.js +15 -0
- package/dist/functions/getMultipleElementsBoundingBox.d.ts +2 -0
- package/dist/functions/getMultipleElementsBoundingBox.js +20 -0
- package/dist/functions/getPathToParent.d.ts +1 -0
- package/dist/functions/getPathToParent.js +15 -0
- package/dist/functions/getReferenceId.d.ts +1 -0
- package/dist/functions/getReferenceId.js +9 -0
- package/dist/functions/getUsableFileName.d.ts +1 -0
- package/dist/functions/getUsableFileName.js +17 -0
- package/dist/functions/getUsableFileName.test.d.ts +1 -0
- package/dist/functions/getUsableFileName.test.js +16 -0
- package/dist/functions/getUsableName.d.ts +2 -0
- package/dist/functions/getUsableName.js +47 -0
- package/dist/functions/isCombinationModifiersPressed.d.ts +4 -0
- package/dist/functions/isCombinationModifiersPressed.js +16 -0
- package/dist/functions/isLocatorsOwnElement.d.ts +1 -0
- package/dist/functions/isLocatorsOwnElement.js +3 -0
- package/dist/functions/mergeRects.d.ts +2 -0
- package/dist/functions/mergeRects.js +10 -0
- package/dist/functions/mergeRects.test.d.ts +1 -0
- package/dist/functions/mergeRects.test.js +23 -0
- package/dist/functions/nonNullable.d.ts +1 -0
- package/dist/functions/nonNullable.js +3 -0
- package/dist/functions/parseDataId.d.ts +3 -0
- package/dist/functions/parseDataId.js +44 -0
- package/dist/functions/transformPath.d.ts +1 -0
- package/dist/functions/transformPath.js +7 -0
- package/dist/functions/transformPath.test.d.ts +1 -0
- package/dist/functions/transformPath.test.js +16 -0
- package/dist/global.d.js +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +13 -0
- package/dist/initRuntime.d.ts +8 -0
- package/dist/initRuntime.js +80 -0
- package/dist/output.css +1733 -0
- package/dist/types/LabelData.d.ts +5 -0
- package/dist/types/LabelData.js +1 -0
- package/dist/types/TreeNode.d.ts +19 -0
- package/dist/types/TreeNode.js +1 -0
- package/dist/types/types.d.ts +53 -0
- package/dist/types/types.js +1 -0
- package/jest.config.ts +195 -0
- package/package.json +75 -0
- package/scripts/wrapCSS.js +26 -0
- package/scripts/wrapImage.js +24 -0
- package/src/_generated_styles.ts +1734 -0
- package/src/_generated_tree_icon.ts +2 -0
- package/src/adapters/HtmlElementTreeNode.ts +51 -0
- package/src/adapters/adapterApi.ts +35 -0
- package/src/adapters/createTreeNode.ts +25 -0
- package/src/adapters/getElementInfo.tsx +27 -0
- package/src/adapters/getParentsPath.tsx +49 -0
- package/src/adapters/getTree.tsx +45 -0
- package/src/adapters/goUpByTheTree.ts +20 -0
- package/src/adapters/jsx/getExpressionData.ts +47 -0
- package/src/adapters/jsx/getJSXComponentBoundingBox.ts +63 -0
- package/src/adapters/jsx/jsxAdapter.ts +276 -0
- package/src/adapters/jsx/runtimeStore.ts +94 -0
- package/src/adapters/react/fiberToSimple.tsx +72 -0
- package/src/adapters/react/findDebugSource.ts +15 -0
- package/src/adapters/react/findFiberByHtmlElement.ts +27 -0
- package/src/adapters/react/gatherFiberRoots.tsx +36 -0
- package/src/adapters/react/getAllFiberChildren.tsx +11 -0
- package/src/adapters/react/getAllParentsElementsAndRootComponent.ts +52 -0
- package/src/adapters/react/getAllWrappingParents.ts +25 -0
- package/src/adapters/react/getFiberComponentBoundingBox.ts +30 -0
- package/src/adapters/react/getFiberLabel.ts +20 -0
- package/src/adapters/react/getFiberOwnBoundingBox.ts +9 -0
- package/src/adapters/react/isStyled.ts +5 -0
- package/src/adapters/react/makeFiberId.tsx +19 -0
- package/src/adapters/react/reactAdapter.ts +148 -0
- package/src/adapters/react/searchDevtoolsRenderersForClosestTarget.ts +15 -0
- package/src/adapters/svelte/svelteAdapter.ts +111 -0
- package/src/adapters/vue/getVNodeBoundingBox.tsx +42 -0
- package/src/adapters/vue/vueAdapter.ts +139 -0
- package/src/assets/tree-icon.png +0 -0
- package/src/browserApi.ts +288 -0
- package/src/components/Button.tsx +14 -0
- package/src/components/ComponentOutline.tsx +98 -0
- package/src/components/MaybeOutline.tsx +49 -0
- package/src/components/Outline.tsx +153 -0
- package/src/components/RenderBoxes.tsx +57 -0
- package/src/components/Runtime.tsx +246 -0
- package/src/components/SimpleNodeOutline.tsx +27 -0
- package/src/components/Toast.tsx +83 -0
- package/src/components/Tooltip.tsx +28 -0
- package/src/consts.ts +7 -0
- package/src/functions/cropPath.test.ts +18 -0
- package/src/functions/cropPath.ts +12 -0
- package/src/functions/deduplicateLabels.ts +16 -0
- package/src/functions/evalTemplate.test.ts +12 -0
- package/src/functions/evalTemplate.ts +8 -0
- package/src/functions/findNames.ts +20 -0
- package/src/functions/formatAncestryChain.ts +80 -0
- package/src/functions/getBoundingRect.tsx +11 -0
- package/src/functions/getComposedBoundingBox.tsx +25 -0
- package/src/functions/getIdsOnPathToRoot.tsx +21 -0
- package/src/functions/getMultipleElementsBoundingBox.tsx +25 -0
- package/src/functions/getPathToParent.tsx +17 -0
- package/src/functions/getReferenceId.tsx +10 -0
- package/src/functions/getUsableFileName.test.tsx +24 -0
- package/src/functions/getUsableFileName.tsx +19 -0
- package/src/functions/getUsableName.ts +52 -0
- package/src/functions/isCombinationModifiersPressed.ts +32 -0
- package/src/functions/isLocatorsOwnElement.tsx +9 -0
- package/src/functions/mergeRects.test.ts +15 -0
- package/src/functions/mergeRects.tsx +12 -0
- package/src/functions/nonNullable.ts +3 -0
- package/src/functions/parseDataId.ts +62 -0
- package/src/functions/transformPath.test.ts +28 -0
- package/src/functions/transformPath.ts +7 -0
- package/src/global.d.ts +31 -0
- package/src/index.ts +18 -0
- package/src/initRuntime.ts +83 -0
- package/src/main.css +3 -0
- package/src/types/LabelData.ts +6 -0
- package/src/types/TreeNode.ts +22 -0
- package/src/types/types.ts +55 -0
- package/tailwind.config.js +9 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { template as _$template } from "solid-js/web";
|
|
2
|
+
import { createComponent as _$createComponent } from "solid-js/web";
|
|
3
|
+
import { insert as _$insert } from "solid-js/web";
|
|
4
|
+
import { setAttribute as _$setAttribute } from "solid-js/web";
|
|
5
|
+
import { effect as _$effect } from "solid-js/web";
|
|
6
|
+
import { setStyleProperty as _$setStyleProperty } from "solid-js/web";
|
|
7
|
+
var _tmpl$ = /*#__PURE__*/_$template(`<div style="z-index:99999;background-color:rgba(56, 189, 248, 0.5);pointer-events:none">`),
|
|
8
|
+
_tmpl$2 = /*#__PURE__*/_$template(`<div style=z-index:100000;pointer-events:none><img alt=Tree>`),
|
|
9
|
+
_tmpl$3 = /*#__PURE__*/_$template(`<div style="background-color:#111827;border-radius:8px;box-shadow:0 10px 15px -3px rgba(0, 0, 0, 0.1);font-size:14px;z-index:100000;pointer-events:auto">`);
|
|
10
|
+
import { createSignal, onCleanup, onMount } from "solid-js";
|
|
11
|
+
import { Portal } from "solid-js/web";
|
|
12
|
+
import TREE_ICON from "../_generated_tree_icon";
|
|
13
|
+
export function Toast(props) {
|
|
14
|
+
let timeoutId;
|
|
15
|
+
const [flashOpacity, setFlashOpacity] = createSignal(1);
|
|
16
|
+
onMount(() => {
|
|
17
|
+
// Start flash fade after a brief moment so it's visible
|
|
18
|
+
setTimeout(() => {
|
|
19
|
+
setFlashOpacity(0);
|
|
20
|
+
}, 100);
|
|
21
|
+
timeoutId = setTimeout(() => {
|
|
22
|
+
props.onClose();
|
|
23
|
+
}, 1500);
|
|
24
|
+
});
|
|
25
|
+
onCleanup(() => {
|
|
26
|
+
clearTimeout(timeoutId);
|
|
27
|
+
});
|
|
28
|
+
return _$createComponent(Portal, {
|
|
29
|
+
get mount() {
|
|
30
|
+
return document.body;
|
|
31
|
+
},
|
|
32
|
+
get children() {
|
|
33
|
+
return [(() => {
|
|
34
|
+
var _el$ = _tmpl$();
|
|
35
|
+
_$setStyleProperty(_el$, "position", "fixed");
|
|
36
|
+
_$setStyleProperty(_el$, "top", "0");
|
|
37
|
+
_$setStyleProperty(_el$, "left", "0");
|
|
38
|
+
_$setStyleProperty(_el$, "right", "0");
|
|
39
|
+
_$setStyleProperty(_el$, "bottom", "0");
|
|
40
|
+
_$setStyleProperty(_el$, "width", "100vw");
|
|
41
|
+
_$setStyleProperty(_el$, "height", "100vh");
|
|
42
|
+
_$setStyleProperty(_el$, "transition", "opacity 0.3s ease-out");
|
|
43
|
+
_$effect(_$p => _$setStyleProperty(_el$, "opacity", flashOpacity()));
|
|
44
|
+
return _el$;
|
|
45
|
+
})(), (() => {
|
|
46
|
+
var _el$2 = _tmpl$2(),
|
|
47
|
+
_el$3 = _el$2.firstChild;
|
|
48
|
+
_$setStyleProperty(_el$2, "position", "fixed");
|
|
49
|
+
_$setStyleProperty(_el$2, "bottom", "16px");
|
|
50
|
+
_$setStyleProperty(_el$2, "left", "16px");
|
|
51
|
+
_$setAttribute(_el$3, "src", TREE_ICON);
|
|
52
|
+
_$setStyleProperty(_el$3, "width", "32px");
|
|
53
|
+
_$setStyleProperty(_el$3, "height", "32px");
|
|
54
|
+
return _el$2;
|
|
55
|
+
})(), (() => {
|
|
56
|
+
var _el$4 = _tmpl$3();
|
|
57
|
+
_$setStyleProperty(_el$4, "position", "fixed");
|
|
58
|
+
_$setStyleProperty(_el$4, "bottom", "16px");
|
|
59
|
+
_$setStyleProperty(_el$4, "left", "50%");
|
|
60
|
+
_$setStyleProperty(_el$4, "transform", "translateX(-50%)");
|
|
61
|
+
_$setStyleProperty(_el$4, "color", "white");
|
|
62
|
+
_$setStyleProperty(_el$4, "padding", "8px 16px");
|
|
63
|
+
_$insert(_el$4, () => props.message);
|
|
64
|
+
return _el$4;
|
|
65
|
+
})()];
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { template as _$template } from "solid-js/web";
|
|
2
|
+
import { className as _$className } from "solid-js/web";
|
|
3
|
+
import { effect as _$effect } from "solid-js/web";
|
|
4
|
+
import { insert as _$insert } from "solid-js/web";
|
|
5
|
+
var _tmpl$ = /*#__PURE__*/_$template(`<div class="group/tooltip relative block"><div role=tooltip>`);
|
|
6
|
+
export default function Tooltip(props) {
|
|
7
|
+
const positionMap = {
|
|
8
|
+
bottom: "-bottom-7 left-1/2 -translate-x-1/2 transform",
|
|
9
|
+
left: "-left-2 top-1/2 -translate-y-1/2 -translate-x-full transform",
|
|
10
|
+
right: "-right-2 top-1/2 -translate-y-1/2 translate-x-full transform",
|
|
11
|
+
top: "-top-7 left-1/2 -translate-x-1/2 transform"
|
|
12
|
+
};
|
|
13
|
+
return (() => {
|
|
14
|
+
var _el$ = _tmpl$(),
|
|
15
|
+
_el$2 = _el$.firstChild;
|
|
16
|
+
_$insert(_el$, () => props.children, _el$2);
|
|
17
|
+
_$insert(_el$2, () => props.tooltipText);
|
|
18
|
+
_$effect(() => _$className(_el$2, "pointer-events-none invisible absolute z-10 whitespace-nowrap rounded bg-gray-700 px-2 py-1 text-center text-xs text-white opacity-0 transition-opacity duration-300 group-hover/tooltip:visible group-hover/tooltip:opacity-100" + " " + positionMap[props.position || "top"]));
|
|
19
|
+
return _el$;
|
|
20
|
+
})();
|
|
21
|
+
}
|
package/dist/consts.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const HREF_TARGET = "_self";
|
|
2
|
+
export declare const PADDING = 6;
|
|
3
|
+
export declare const baseColor = "#e90139";
|
|
4
|
+
export declare const hoverColor = "#C70139";
|
|
5
|
+
export declare const fontFamily = "Helvetica, sans-serif, Arial";
|
|
6
|
+
export type AdapterId = "react" | "jsx" | "svelte" | "vue";
|
package/dist/consts.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function cropPath(fullPath: string): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import cropPath from "./cropPath";
|
|
2
|
+
import { describe, expect, test } from "vitest";
|
|
3
|
+
describe("cropPath", () => {
|
|
4
|
+
test("crop", () => {
|
|
5
|
+
expect(cropPath("aaa/bbb/ccc/ddd.tsx")).toBe(".../bbb/ccc/ddd.tsx");
|
|
6
|
+
expect(cropPath("/aaa/bbb/ccc/ddd.tsx")).toBe(".../bbb/ccc/ddd.tsx");
|
|
7
|
+
});
|
|
8
|
+
test("no crop", () => {
|
|
9
|
+
// expect(cropPath("/bbb/ccc/ddd.tsx")).toBe("/bbb/ccc/ddd.tsx");
|
|
10
|
+
expect(cropPath("bbb/ccc/ddd.tsx")).toBe("bbb/ccc/ddd.tsx");
|
|
11
|
+
expect(cropPath("/ccc/ddd.tsx")).toBe("/ccc/ddd.tsx");
|
|
12
|
+
expect(cropPath("ccc/ddd.tsx")).toBe("ccc/ddd.tsx");
|
|
13
|
+
expect(cropPath("")).toBe("");
|
|
14
|
+
expect(cropPath("xxx")).toBe("xxx");
|
|
15
|
+
});
|
|
16
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import nonNullable from "./nonNullable";
|
|
2
|
+
export function deduplicateLabels(labels) {
|
|
3
|
+
const labelsIds = {};
|
|
4
|
+
return labels.map(label => {
|
|
5
|
+
const id = JSON.stringify(label);
|
|
6
|
+
if (labelsIds[id]) {
|
|
7
|
+
return null;
|
|
8
|
+
}
|
|
9
|
+
labelsIds[id] = true;
|
|
10
|
+
return label;
|
|
11
|
+
}).filter(nonNullable);
|
|
12
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { evalTemplate } from "./evalTemplate";
|
|
2
|
+
import { describe, expect, test } from "vitest";
|
|
3
|
+
describe("evalTemplate", () => {
|
|
4
|
+
test("basic", () => {
|
|
5
|
+
const res = evalTemplate("https://example.com/${filePath}${ext}", {
|
|
6
|
+
filePath: "test",
|
|
7
|
+
ext: ".js"
|
|
8
|
+
});
|
|
9
|
+
expect(res).toBe("https://example.com/test.js");
|
|
10
|
+
});
|
|
11
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { getUsableName } from "./getUsableName";
|
|
2
|
+
export function findNames(fiber) {
|
|
3
|
+
// if (fiber._debugOwner?.elementType?.styledComponentId) {
|
|
4
|
+
// // This is special case for styled-components, we need to show one level up
|
|
5
|
+
// return {
|
|
6
|
+
// name: getUsableName(fiber._debugOwner),
|
|
7
|
+
// wrappingComponent: getUsableName(fiber._debugOwner?._debugOwner),
|
|
8
|
+
// };
|
|
9
|
+
// } else {
|
|
10
|
+
return {
|
|
11
|
+
name: getUsableName(fiber),
|
|
12
|
+
wrappingComponent: getUsableName(fiber._debugOwner)
|
|
13
|
+
};
|
|
14
|
+
// }
|
|
15
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { TreeNode } from "../types/TreeNode";
|
|
2
|
+
export interface AncestryItem {
|
|
3
|
+
elementName: string;
|
|
4
|
+
componentName?: string;
|
|
5
|
+
filePath?: string;
|
|
6
|
+
line?: number;
|
|
7
|
+
}
|
|
8
|
+
export declare function collectAncestry(node: TreeNode): AncestryItem[];
|
|
9
|
+
export declare function formatAncestryChain(items: AncestryItem[]): string;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// Elements to exclude from ancestry (not useful for debugging)
|
|
2
|
+
const EXCLUDED_ELEMENTS = new Set(["html", "body", "head"]);
|
|
3
|
+
export function collectAncestry(node) {
|
|
4
|
+
const items = [];
|
|
5
|
+
let current = node;
|
|
6
|
+
while (current) {
|
|
7
|
+
// Skip html, body, head elements
|
|
8
|
+
if (EXCLUDED_ELEMENTS.has(current.name)) {
|
|
9
|
+
current = current.getParent();
|
|
10
|
+
continue;
|
|
11
|
+
}
|
|
12
|
+
const component = current.getComponent();
|
|
13
|
+
const source = current.getSource();
|
|
14
|
+
const item = {
|
|
15
|
+
elementName: current.name
|
|
16
|
+
};
|
|
17
|
+
if (component) {
|
|
18
|
+
item.componentName = component.label;
|
|
19
|
+
if (component.callLink) {
|
|
20
|
+
item.filePath = component.callLink.fileName;
|
|
21
|
+
item.line = component.callLink.lineNumber;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
if (!item.filePath && source) {
|
|
25
|
+
item.filePath = source.fileName;
|
|
26
|
+
item.line = source.lineNumber;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Only include items that have useful info (component name or file path)
|
|
30
|
+
if (item.componentName || item.filePath) {
|
|
31
|
+
items.push(item);
|
|
32
|
+
}
|
|
33
|
+
current = current.getParent();
|
|
34
|
+
}
|
|
35
|
+
return items;
|
|
36
|
+
}
|
|
37
|
+
export function formatAncestryChain(items) {
|
|
38
|
+
if (items.length === 0) {
|
|
39
|
+
return "";
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Reverse so root is at top, clicked element at bottom
|
|
43
|
+
const reversed = [...items].reverse();
|
|
44
|
+
const lines = [];
|
|
45
|
+
reversed.forEach((item, index) => {
|
|
46
|
+
const indent = " ".repeat(index);
|
|
47
|
+
const prefix = index === 0 ? "" : "└─ ";
|
|
48
|
+
let description = item.elementName;
|
|
49
|
+
if (item.componentName) {
|
|
50
|
+
description = `${item.elementName} in ${item.componentName}`;
|
|
51
|
+
}
|
|
52
|
+
const location = item.filePath ? ` at ${item.filePath}:${item.line}` : "";
|
|
53
|
+
lines.push(`${indent}${prefix}${description}${location}`);
|
|
54
|
+
});
|
|
55
|
+
return lines.join("\n");
|
|
56
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getBoundingRect(node: Element | Text): DOMRect | null;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export function getBoundingRect(node) {
|
|
2
|
+
if (node instanceof Element) {
|
|
3
|
+
return node.getBoundingClientRect();
|
|
4
|
+
} else if (node instanceof Text) {
|
|
5
|
+
const range = document.createRange();
|
|
6
|
+
range.selectNodeContents(node);
|
|
7
|
+
return range.getBoundingClientRect();
|
|
8
|
+
} else {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { mergeRects } from "./mergeRects";
|
|
2
|
+
export function getComposedBoundingBox(children) {
|
|
3
|
+
let composedRect = null;
|
|
4
|
+
children.forEach(child => {
|
|
5
|
+
const box = child.box;
|
|
6
|
+
if (!box) {
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
if (box.width <= 0 || box.height <= 0) {
|
|
10
|
+
// ignore zero-sized rects
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
if (composedRect) {
|
|
14
|
+
composedRect = mergeRects(composedRect, box);
|
|
15
|
+
} else {
|
|
16
|
+
composedRect = box;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
return composedRect;
|
|
20
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { findFiberByHtmlElement } from "./../adapters/react/findFiberByHtmlElement";
|
|
2
|
+
import { makeFiberId } from "./../adapters/react/makeFiberId";
|
|
3
|
+
export function getIdsOnPathToRoot(element) {
|
|
4
|
+
const fiber = findFiberByHtmlElement(element, false);
|
|
5
|
+
if (!fiber) {
|
|
6
|
+
return {};
|
|
7
|
+
}
|
|
8
|
+
const res = {};
|
|
9
|
+
let parent = fiber?._debugOwner;
|
|
10
|
+
while (parent) {
|
|
11
|
+
res[makeFiberId(parent)] = true;
|
|
12
|
+
parent = parent?._debugOwner;
|
|
13
|
+
}
|
|
14
|
+
return res;
|
|
15
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { mergeRects } from "./mergeRects";
|
|
2
|
+
export function getMultipleElementsBoundingBox(children) {
|
|
3
|
+
let composedRect = null;
|
|
4
|
+
children.forEach(child => {
|
|
5
|
+
const box = child.getBoundingClientRect();
|
|
6
|
+
if (!box) {
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
if (box.width <= 0 || box.height <= 0) {
|
|
10
|
+
// ignore zero-sized rects
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
if (composedRect) {
|
|
14
|
+
composedRect = mergeRects(composedRect, box);
|
|
15
|
+
} else {
|
|
16
|
+
composedRect = box;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
return composedRect;
|
|
20
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getPathToParent(element: HTMLElement): import("../types/types").SimpleNode | undefined;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { findFiberByHtmlElement } from "../adapters/react/findFiberByHtmlElement";
|
|
2
|
+
import { fiberToSimple } from "../adapters/react/fiberToSimple";
|
|
3
|
+
export function getPathToParent(element) {
|
|
4
|
+
const fiber = findFiberByHtmlElement(element, false);
|
|
5
|
+
if (!fiber) {
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
8
|
+
let res = fiberToSimple(fiber);
|
|
9
|
+
let parent = fiber?._debugOwner;
|
|
10
|
+
while (parent) {
|
|
11
|
+
res = fiberToSimple(parent, [res]);
|
|
12
|
+
parent = parent?._debugOwner;
|
|
13
|
+
}
|
|
14
|
+
return res;
|
|
15
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getReferenceId(ref: object): number;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function getUsableFileName(path: string): string;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export default function getUsableFileName(path) {
|
|
2
|
+
const pathSegments = path.split("/");
|
|
3
|
+
|
|
4
|
+
// If the path has only one segment, return it directly.
|
|
5
|
+
if (pathSegments.length === 1) {
|
|
6
|
+
return pathSegments[0] || "unnamed";
|
|
7
|
+
}
|
|
8
|
+
const fileName = pathSegments[pathSegments.length - 1] || "unnamed";
|
|
9
|
+
if (fileName.startsWith("index.")) {
|
|
10
|
+
// If the file name is index.<extension>, return the parent folder's name
|
|
11
|
+
// along with the filename.
|
|
12
|
+
return `${pathSegments[pathSegments.length - 2]}/${fileName}`;
|
|
13
|
+
} else {
|
|
14
|
+
// Otherwise, just return the filename.
|
|
15
|
+
return fileName;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import getUsableFileName from "./getUsableFileName"; // assuming the function is in filenameUtils.ts
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
describe("getUsableFileName", () => {
|
|
4
|
+
it("should return filename if it is not index.<extension>", () => {
|
|
5
|
+
expect(getUsableFileName("myProject/utils/getSomething.js")).toBe("getSomething.js");
|
|
6
|
+
});
|
|
7
|
+
it("should return parent folder and filename if the filename is index.<extension>", () => {
|
|
8
|
+
expect(getUsableFileName("myProject/Button/index.tsx")).toBe("Button/index.tsx");
|
|
9
|
+
});
|
|
10
|
+
it("should handle paths with only one segment", () => {
|
|
11
|
+
expect(getUsableFileName("file.ts")).toBe("file.ts");
|
|
12
|
+
});
|
|
13
|
+
it("should handle paths with index.<extension> without parent folder", () => {
|
|
14
|
+
expect(getUsableFileName("index.ts")).toBe("index.ts");
|
|
15
|
+
});
|
|
16
|
+
});
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// function printDebugOwnerTree(fiber: Fiber): string | null {
|
|
2
|
+
// let current: Fiber | null = fiber || null;
|
|
3
|
+
// let results = [];
|
|
4
|
+
// while (current) {
|
|
5
|
+
// results.push(getUsableName(current));
|
|
6
|
+
// current = current._debugOwner || null;
|
|
7
|
+
// }
|
|
8
|
+
// console.log('DEBUG OWNER: ', results);
|
|
9
|
+
// return null;
|
|
10
|
+
// }
|
|
11
|
+
// function printReturnTree(fiber: Fiber): string | null {
|
|
12
|
+
// let current: Fiber | null = fiber || null;
|
|
13
|
+
// let results = [];
|
|
14
|
+
// while (current) {
|
|
15
|
+
// results.push(getUsableName(current));
|
|
16
|
+
// current = current.return || null;
|
|
17
|
+
// }
|
|
18
|
+
// console.log('RETURN: ', results);
|
|
19
|
+
// return null;
|
|
20
|
+
// }
|
|
21
|
+
|
|
22
|
+
export function getUsableName(fiber) {
|
|
23
|
+
if (!fiber) {
|
|
24
|
+
return "Not found";
|
|
25
|
+
}
|
|
26
|
+
if (typeof fiber.elementType === "string") {
|
|
27
|
+
return fiber.elementType;
|
|
28
|
+
}
|
|
29
|
+
if (!fiber.elementType) {
|
|
30
|
+
return "Anonymous";
|
|
31
|
+
}
|
|
32
|
+
if (fiber.elementType.name) {
|
|
33
|
+
return fiber.elementType.name;
|
|
34
|
+
}
|
|
35
|
+
// Not sure about this
|
|
36
|
+
if (fiber.elementType.displayName) {
|
|
37
|
+
return fiber.elementType.displayName;
|
|
38
|
+
}
|
|
39
|
+
// Used in rect.memo
|
|
40
|
+
if (fiber.elementType.type?.name) {
|
|
41
|
+
return fiber.elementType.type.name;
|
|
42
|
+
}
|
|
43
|
+
if (fiber.elementType._payload?._result?.name) {
|
|
44
|
+
return fiber.elementType._payload._result.name;
|
|
45
|
+
}
|
|
46
|
+
return "Anonymous";
|
|
47
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export function getMouseModifiers() {
|
|
2
|
+
const mouseModifiers = document.documentElement.dataset.locatorMouseModifiers || "alt";
|
|
3
|
+
const mouseModifiersArray = mouseModifiers.split("+");
|
|
4
|
+
const modifiers = {};
|
|
5
|
+
mouseModifiersArray.forEach(modifier => {
|
|
6
|
+
modifiers[modifier] = true;
|
|
7
|
+
}, {});
|
|
8
|
+
return modifiers;
|
|
9
|
+
}
|
|
10
|
+
export function isCombinationModifiersPressed(e, rightClick = false) {
|
|
11
|
+
const modifiers = getMouseModifiers();
|
|
12
|
+
if (rightClick) {
|
|
13
|
+
return e.altKey == !!modifiers.alt && e.metaKey == !!modifiers.meta && e.shiftKey == !!modifiers.shift;
|
|
14
|
+
}
|
|
15
|
+
return e.altKey == !!modifiers.alt && e.ctrlKey == !!modifiers.ctrl && e.metaKey == !!modifiers.meta && e.shiftKey == !!modifiers.shift;
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function isLocatorsOwnElement(element: HTMLElement): boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { mergeRects } from "./mergeRects";
|
|
2
|
+
import { describe, expect, test } from "vitest";
|
|
3
|
+
describe("mergeRects", () => {
|
|
4
|
+
test("basic", () => {
|
|
5
|
+
const a = {
|
|
6
|
+
x: 0,
|
|
7
|
+
y: 0,
|
|
8
|
+
width: 10,
|
|
9
|
+
height: 10
|
|
10
|
+
};
|
|
11
|
+
const b = {
|
|
12
|
+
x: 5,
|
|
13
|
+
y: 5,
|
|
14
|
+
width: 10,
|
|
15
|
+
height: 10
|
|
16
|
+
};
|
|
17
|
+
const res = mergeRects(a, b);
|
|
18
|
+
expect(res.x).toEqual(0);
|
|
19
|
+
expect(res.y).toEqual(0);
|
|
20
|
+
expect(res.width).toEqual(15);
|
|
21
|
+
expect(res.height).toEqual(15);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function nonNullable<T>(value: T): value is NonNullable<T>;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare function parseDataId(dataId: string): [fileFullPath: string, id: string];
|
|
2
|
+
export declare function parseDataPath(dataPath: string): [fileFullPath: string, line: number, column: number] | null;
|
|
3
|
+
export declare function splitFullPath(fullPath: string): [projectPath: string, filePath: string];
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export function parseDataId(dataId) {
|
|
2
|
+
const [fileFullPath, id] = dataId.split("::");
|
|
3
|
+
if (!fileFullPath || !id) {
|
|
4
|
+
throw new Error("locatorjsId is malformed");
|
|
5
|
+
}
|
|
6
|
+
return [fileFullPath, id];
|
|
7
|
+
}
|
|
8
|
+
export function parseDataPath(dataPath) {
|
|
9
|
+
// Format: /path/to/file.tsx:line:column
|
|
10
|
+
// Need to handle Windows paths like C:\path\to\file.tsx:line:column
|
|
11
|
+
|
|
12
|
+
// Find the last two colons (for line and column)
|
|
13
|
+
const lastColonIndex = dataPath.lastIndexOf(":");
|
|
14
|
+
if (lastColonIndex === -1) return null;
|
|
15
|
+
const secondLastColonIndex = dataPath.lastIndexOf(":", lastColonIndex - 1);
|
|
16
|
+
if (secondLastColonIndex === -1) return null;
|
|
17
|
+
const fileFullPath = dataPath.substring(0, secondLastColonIndex);
|
|
18
|
+
const lineStr = dataPath.substring(secondLastColonIndex + 1, lastColonIndex);
|
|
19
|
+
const columnStr = dataPath.substring(lastColonIndex + 1);
|
|
20
|
+
const line = parseInt(lineStr, 10);
|
|
21
|
+
const column = parseInt(columnStr, 10);
|
|
22
|
+
if (Number.isNaN(line) || Number.isNaN(column)) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
return [fileFullPath, line, column];
|
|
26
|
+
}
|
|
27
|
+
export function splitFullPath(fullPath) {
|
|
28
|
+
// Try to find a common project root indicator
|
|
29
|
+
const indicators = ["/src/", "/app/", "/pages/", "/components/"];
|
|
30
|
+
for (const indicator of indicators) {
|
|
31
|
+
const index = fullPath.indexOf(indicator);
|
|
32
|
+
if (index !== -1) {
|
|
33
|
+
return [fullPath.substring(0, index), fullPath.substring(index)];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Fallback: treat the whole path as project path with empty file path
|
|
38
|
+
// or try to split at the last reasonable directory
|
|
39
|
+
const lastSlash = fullPath.lastIndexOf("/");
|
|
40
|
+
if (lastSlash !== -1) {
|
|
41
|
+
return [fullPath.substring(0, lastSlash + 1), fullPath.substring(lastSlash + 1)];
|
|
42
|
+
}
|
|
43
|
+
return [fullPath, ""];
|
|
44
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function transformPath(path: string, from: string, to: string): string;
|