@treelocator/runtime 0.4.1 → 0.4.5
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/_generated_styles.js +115 -15
- package/dist/adapters/getElementInfo.js +3 -17
- package/dist/adapters/getParentsPath.js +3 -33
- package/dist/adapters/getTree.js +3 -33
- package/dist/adapters/jsx/getJSXComponentBoundingBox.js +0 -1
- package/dist/adapters/jsx/jsxAdapter.js +0 -3
- package/dist/adapters/jsx/runtimeStore.js +0 -12
- package/dist/adapters/react/reactAdapter.js +0 -8
- package/dist/adapters/resolveAdapter.d.ts +8 -0
- package/dist/adapters/resolveAdapter.js +28 -0
- package/dist/adapters/vue/vueAdapter.js +0 -14
- package/dist/browserApi.d.ts +1 -1
- package/dist/browserApi.js +8 -10
- package/dist/components/MaybeOutline.d.ts +1 -0
- package/dist/components/MaybeOutline.js +38 -29
- package/dist/components/Outline.d.ts +1 -0
- package/dist/components/Outline.js +20 -16
- package/dist/components/Runtime.js +30 -18
- package/dist/dejitter/recorder.js +0 -1
- package/dist/functions/formatAncestryChain.d.ts +6 -0
- package/dist/functions/formatAncestryChain.js +11 -0
- package/dist/functions/formatAncestryChain.test.js +75 -1
- package/dist/functions/getUsableName.js +0 -21
- package/dist/output.css +10 -40
- package/dist/types/types.d.ts +1 -32
- package/package.json +1 -1
- package/src/_generated_styles.ts +115 -15
- package/src/adapters/getElementInfo.tsx +3 -23
- package/src/adapters/getParentsPath.tsx +3 -42
- package/src/adapters/getTree.tsx +3 -42
- package/src/adapters/jsx/getJSXComponentBoundingBox.ts +0 -1
- package/src/adapters/jsx/jsxAdapter.ts +0 -2
- package/src/adapters/jsx/runtimeStore.ts +0 -11
- package/src/adapters/react/reactAdapter.ts +0 -7
- package/src/adapters/resolveAdapter.ts +38 -0
- package/src/adapters/vue/vueAdapter.ts +0 -14
- package/src/browserApi.ts +9 -12
- package/src/components/MaybeOutline.tsx +4 -2
- package/src/components/Outline.tsx +2 -1
- package/src/components/Runtime.tsx +27 -18
- package/src/dejitter/recorder.ts +43 -44
- package/src/functions/formatAncestryChain.test.ts +47 -0
- package/src/functions/formatAncestryChain.ts +11 -0
- package/src/functions/getUsableName.ts +0 -21
- package/src/types/types.ts +1 -32
- package/src/adapters/react/fiberToSimple.tsx +0 -72
- package/src/adapters/react/gatherFiberRoots.tsx +0 -36
- package/src/adapters/react/makeFiberId.tsx +0 -19
- package/src/adapters/react/searchDevtoolsRenderersForClosestTarget.ts +0 -15
- package/src/components/Button.tsx +0 -14
- package/src/components/ComponentOutline.tsx +0 -98
- package/src/components/SimpleNodeOutline.tsx +0 -27
- package/src/components/Tooltip.tsx +0 -28
- package/src/functions/cropPath.test.ts +0 -18
- package/src/functions/cropPath.ts +0 -12
- package/src/functions/evalTemplate.test.ts +0 -12
- package/src/functions/evalTemplate.ts +0 -8
- package/src/functions/findNames.ts +0 -20
- package/src/functions/getBoundingRect.tsx +0 -11
- package/src/functions/getComposedBoundingBox.tsx +0 -25
- package/src/functions/getIdsOnPathToRoot.tsx +0 -21
- package/src/functions/getMultipleElementsBoundingBox.tsx +0 -25
- package/src/functions/getPathToParent.tsx +0 -17
- package/src/functions/getUsableFileName.test.tsx +0 -24
- package/src/functions/getUsableFileName.tsx +0 -19
- package/src/functions/transformPath.test.ts +0 -28
- package/src/functions/transformPath.ts +0 -7
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { Fiber } from "@locator/shared";
|
|
2
|
-
|
|
3
|
-
let globalIdCounter = 0;
|
|
4
|
-
const globalIdMap = new WeakMap<Fiber, string>();
|
|
5
|
-
|
|
6
|
-
export function makeFiberId(fiber: Fiber) {
|
|
7
|
-
if (fiber._debugID) {
|
|
8
|
-
return fiber._debugID.toString();
|
|
9
|
-
}
|
|
10
|
-
const found = globalIdMap.get(fiber);
|
|
11
|
-
if (found) {
|
|
12
|
-
return found;
|
|
13
|
-
} else {
|
|
14
|
-
globalIdCounter++;
|
|
15
|
-
const id = `fiber:${globalIdCounter}`;
|
|
16
|
-
globalIdMap.set(fiber, id);
|
|
17
|
-
return id;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { findFiberByHtmlElement } from "./findFiberByHtmlElement";
|
|
2
|
-
|
|
3
|
-
export function searchDevtoolsRenderersForClosestTarget(
|
|
4
|
-
target: HTMLElement
|
|
5
|
-
): HTMLElement | null {
|
|
6
|
-
let closest: HTMLElement | null = target;
|
|
7
|
-
while (closest) {
|
|
8
|
-
if (findFiberByHtmlElement(closest, false)) {
|
|
9
|
-
return closest;
|
|
10
|
-
}
|
|
11
|
-
closest = closest.parentElement;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
return null;
|
|
15
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export function Button(props: { onClick: () => void; children: any }) {
|
|
2
|
-
return (
|
|
3
|
-
<button
|
|
4
|
-
class="py-1 px-1 hover:bg-white/30 pointer hover:text-gray-100 rounded"
|
|
5
|
-
onClick={(e) => {
|
|
6
|
-
e.preventDefault();
|
|
7
|
-
e.stopPropagation();
|
|
8
|
-
props.onClick();
|
|
9
|
-
}}
|
|
10
|
-
>
|
|
11
|
-
{props.children}
|
|
12
|
-
</button>
|
|
13
|
-
);
|
|
14
|
-
}
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import { For } from "solid-js";
|
|
2
|
-
import { PADDING } from "../consts";
|
|
3
|
-
import { LabelData } from "../types/LabelData";
|
|
4
|
-
import { SimpleDOMRect } from "../types/types";
|
|
5
|
-
|
|
6
|
-
export function ComponentOutline(props: {
|
|
7
|
-
bbox: SimpleDOMRect;
|
|
8
|
-
labels: LabelData[];
|
|
9
|
-
element: HTMLElement;
|
|
10
|
-
}) {
|
|
11
|
-
const isInside = () => props.bbox.height >= window.innerHeight - 40;
|
|
12
|
-
const isBelow = () => props.bbox.y < 30 && !isInside();
|
|
13
|
-
|
|
14
|
-
const left = () => Math.max(props.bbox.x - PADDING, 0);
|
|
15
|
-
const top = () => Math.max(props.bbox.y - PADDING, 0);
|
|
16
|
-
|
|
17
|
-
const cutFromTop = () => (props.bbox.y < 0 ? -(props.bbox.y - PADDING) : 0);
|
|
18
|
-
const cutFromLeft = () => (props.bbox.x < 0 ? -(props.bbox.x - PADDING) : 0);
|
|
19
|
-
|
|
20
|
-
const width = () =>
|
|
21
|
-
Math.min(props.bbox.width - cutFromLeft() + PADDING * 2, window.innerWidth);
|
|
22
|
-
const height = () =>
|
|
23
|
-
Math.min(
|
|
24
|
-
props.bbox.height - cutFromTop() + PADDING * 2,
|
|
25
|
-
window.innerHeight
|
|
26
|
-
);
|
|
27
|
-
|
|
28
|
-
return (
|
|
29
|
-
<div
|
|
30
|
-
class="border border-purple-500"
|
|
31
|
-
style={{
|
|
32
|
-
"z-index": 1,
|
|
33
|
-
position: "fixed",
|
|
34
|
-
left: left() + "px",
|
|
35
|
-
top: top() + "px",
|
|
36
|
-
width: width() + "px",
|
|
37
|
-
height: height() + "px",
|
|
38
|
-
"border-top-left-radius": left() === 0 || top() === 0 ? "0" : "8px",
|
|
39
|
-
"border-top-right-radius":
|
|
40
|
-
left() + width() === window.innerWidth || top() === 0 ? "0" : "8px",
|
|
41
|
-
"border-bottom-left-radius":
|
|
42
|
-
left() === 0 || top() + height() === window.innerHeight ? "0" : "8px",
|
|
43
|
-
"border-bottom-right-radius":
|
|
44
|
-
left() + width() === window.innerWidth ||
|
|
45
|
-
top() + height() === window.innerHeight
|
|
46
|
-
? "0"
|
|
47
|
-
: "8px",
|
|
48
|
-
}}
|
|
49
|
-
>
|
|
50
|
-
<div
|
|
51
|
-
id="locatorjs-labels-section"
|
|
52
|
-
style={{
|
|
53
|
-
position: "absolute",
|
|
54
|
-
display: "flex",
|
|
55
|
-
"justify-content": "center",
|
|
56
|
-
bottom: isBelow() ? (isInside() ? "2px" : "-28px") : undefined,
|
|
57
|
-
top: isBelow() ? undefined : isInside() ? "2px" : "-28px",
|
|
58
|
-
left: "0px",
|
|
59
|
-
width: "100%",
|
|
60
|
-
"pointer-events": "auto",
|
|
61
|
-
cursor: "pointer",
|
|
62
|
-
...(isBelow()
|
|
63
|
-
? {
|
|
64
|
-
"border-bottom-left-radius": "100%",
|
|
65
|
-
"border-bottom-right-radius": "100%",
|
|
66
|
-
}
|
|
67
|
-
: {
|
|
68
|
-
"border-top-left-radius": "100%",
|
|
69
|
-
"border-top-right-radius": "100%",
|
|
70
|
-
}),
|
|
71
|
-
}}
|
|
72
|
-
>
|
|
73
|
-
<div
|
|
74
|
-
id="locatorjs-labels-wrapper"
|
|
75
|
-
style={{
|
|
76
|
-
padding: isBelow() ? "10px 10px 2px 10px" : "2px 10px 10px 10px",
|
|
77
|
-
}}
|
|
78
|
-
>
|
|
79
|
-
<For each={props.labels}>
|
|
80
|
-
{(label) => {
|
|
81
|
-
const labelClass =
|
|
82
|
-
"bg-purple-500 block text-white text-xs font-bold text-center px-1 py-0.5 rounded whitespace-nowrap pointer-events-auto";
|
|
83
|
-
const labelStyles = {
|
|
84
|
-
"line-height": "18px",
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
return (
|
|
88
|
-
<div class={labelClass} style={labelStyles}>
|
|
89
|
-
{label.label}
|
|
90
|
-
</div>
|
|
91
|
-
);
|
|
92
|
-
}}
|
|
93
|
-
</For>
|
|
94
|
-
</div>
|
|
95
|
-
</div>
|
|
96
|
-
</div>
|
|
97
|
-
);
|
|
98
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { TreeNode } from "../types/TreeNode";
|
|
2
|
-
|
|
3
|
-
export function SimpleNodeOutline(props: { node: TreeNode }) {
|
|
4
|
-
const offset = () => (props.node.type === "component" ? 2 : 0);
|
|
5
|
-
const box = () => props.node.getBox();
|
|
6
|
-
return (
|
|
7
|
-
<div>
|
|
8
|
-
{box() ? (
|
|
9
|
-
<div
|
|
10
|
-
style={{
|
|
11
|
-
position: "fixed",
|
|
12
|
-
left: box()!.x - offset() + "px",
|
|
13
|
-
top: box()!.y - offset() + "px",
|
|
14
|
-
width: box()!.width + offset() * 2 + "px",
|
|
15
|
-
height: box()!.height + offset() * 2 + "px",
|
|
16
|
-
border:
|
|
17
|
-
props.node.type === "component"
|
|
18
|
-
? "2px solid rgba(200,0,0,1)"
|
|
19
|
-
: "1px solid rgba(200,0,0,1)",
|
|
20
|
-
"border-radius": props.node.type === "component" ? "5px" : "3px",
|
|
21
|
-
"z-index": props.node.type === "component" ? 1000 : 10,
|
|
22
|
-
}}
|
|
23
|
-
/>
|
|
24
|
-
) : null}
|
|
25
|
-
</div>
|
|
26
|
-
);
|
|
27
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
export default function Tooltip(props: {
|
|
2
|
-
tooltipText?: string;
|
|
3
|
-
position?: "bottom" | "left" | "right" | "top";
|
|
4
|
-
children: any;
|
|
5
|
-
}) {
|
|
6
|
-
const positionMap = {
|
|
7
|
-
bottom: "-bottom-7 left-1/2 -translate-x-1/2 transform",
|
|
8
|
-
left: "-left-2 top-1/2 -translate-y-1/2 -translate-x-full transform",
|
|
9
|
-
right: "-right-2 top-1/2 -translate-y-1/2 translate-x-full transform",
|
|
10
|
-
top: "-top-7 left-1/2 -translate-x-1/2 transform",
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
return (
|
|
14
|
-
<div class="group/tooltip relative block">
|
|
15
|
-
{props.children}
|
|
16
|
-
<div
|
|
17
|
-
class={
|
|
18
|
-
"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" +
|
|
19
|
-
" " +
|
|
20
|
-
positionMap[props.position || "top"]
|
|
21
|
-
}
|
|
22
|
-
role="tooltip"
|
|
23
|
-
>
|
|
24
|
-
{props.tooltipText}
|
|
25
|
-
</div>
|
|
26
|
-
</div>
|
|
27
|
-
);
|
|
28
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import cropPath from "./cropPath";
|
|
2
|
-
import { describe, expect, test } from "vitest";
|
|
3
|
-
|
|
4
|
-
describe("cropPath", () => {
|
|
5
|
-
test("crop", () => {
|
|
6
|
-
expect(cropPath("aaa/bbb/ccc/ddd.tsx")).toBe(".../bbb/ccc/ddd.tsx");
|
|
7
|
-
expect(cropPath("/aaa/bbb/ccc/ddd.tsx")).toBe(".../bbb/ccc/ddd.tsx");
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
test("no crop", () => {
|
|
11
|
-
// expect(cropPath("/bbb/ccc/ddd.tsx")).toBe("/bbb/ccc/ddd.tsx");
|
|
12
|
-
expect(cropPath("bbb/ccc/ddd.tsx")).toBe("bbb/ccc/ddd.tsx");
|
|
13
|
-
expect(cropPath("/ccc/ddd.tsx")).toBe("/ccc/ddd.tsx");
|
|
14
|
-
expect(cropPath("ccc/ddd.tsx")).toBe("ccc/ddd.tsx");
|
|
15
|
-
expect(cropPath("")).toBe("");
|
|
16
|
-
expect(cropPath("xxx")).toBe("xxx");
|
|
17
|
-
});
|
|
18
|
-
});
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export default function cropPath(fullPath: string) {
|
|
2
|
-
const array = fullPath.split("/");
|
|
3
|
-
|
|
4
|
-
const newPath = array
|
|
5
|
-
.slice(Math.max(array.length - 3, 0), array.length)
|
|
6
|
-
.join("/");
|
|
7
|
-
if (newPath !== fullPath) {
|
|
8
|
-
return `.../${newPath}`;
|
|
9
|
-
} else {
|
|
10
|
-
return newPath;
|
|
11
|
-
}
|
|
12
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { evalTemplate } from "./evalTemplate";
|
|
2
|
-
import { describe, expect, test } from "vitest";
|
|
3
|
-
|
|
4
|
-
describe("evalTemplate", () => {
|
|
5
|
-
test("basic", () => {
|
|
6
|
-
const res = evalTemplate("https://example.com/${filePath}${ext}", {
|
|
7
|
-
filePath: "test",
|
|
8
|
-
ext: ".js",
|
|
9
|
-
});
|
|
10
|
-
expect(res).toBe("https://example.com/test.js");
|
|
11
|
-
});
|
|
12
|
-
});
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { Fiber } from "@locator/shared";
|
|
2
|
-
import { getUsableName } from "./getUsableName";
|
|
3
|
-
|
|
4
|
-
export function findNames(fiber: Fiber): {
|
|
5
|
-
name: string;
|
|
6
|
-
wrappingComponent: string;
|
|
7
|
-
} {
|
|
8
|
-
// if (fiber._debugOwner?.elementType?.styledComponentId) {
|
|
9
|
-
// // This is special case for styled-components, we need to show one level up
|
|
10
|
-
// return {
|
|
11
|
-
// name: getUsableName(fiber._debugOwner),
|
|
12
|
-
// wrappingComponent: getUsableName(fiber._debugOwner?._debugOwner),
|
|
13
|
-
// };
|
|
14
|
-
// } else {
|
|
15
|
-
return {
|
|
16
|
-
name: getUsableName(fiber),
|
|
17
|
-
wrappingComponent: getUsableName(fiber._debugOwner),
|
|
18
|
-
};
|
|
19
|
-
// }
|
|
20
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export function getBoundingRect(node: Element | Text): DOMRect | null {
|
|
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
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { mergeRects } from "./mergeRects";
|
|
2
|
-
import { SimpleDOMRect, SimpleNode } from "./../types/types";
|
|
3
|
-
|
|
4
|
-
export function getComposedBoundingBox(
|
|
5
|
-
children: SimpleNode[]
|
|
6
|
-
): SimpleDOMRect | null {
|
|
7
|
-
let composedRect: SimpleDOMRect | null = null;
|
|
8
|
-
|
|
9
|
-
children.forEach((child) => {
|
|
10
|
-
const box = child.box;
|
|
11
|
-
if (!box) {
|
|
12
|
-
return;
|
|
13
|
-
}
|
|
14
|
-
if (box.width <= 0 || box.height <= 0) {
|
|
15
|
-
// ignore zero-sized rects
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
if (composedRect) {
|
|
19
|
-
composedRect = mergeRects(composedRect, box);
|
|
20
|
-
} else {
|
|
21
|
-
composedRect = box;
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
|
-
return composedRect;
|
|
25
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { findFiberByHtmlElement } from "./../adapters/react/findFiberByHtmlElement";
|
|
2
|
-
import { makeFiberId } from "./../adapters/react/makeFiberId";
|
|
3
|
-
|
|
4
|
-
export function getIdsOnPathToRoot(element: HTMLElement): {
|
|
5
|
-
[id: string]: true;
|
|
6
|
-
} {
|
|
7
|
-
const fiber = findFiberByHtmlElement(element, false);
|
|
8
|
-
if (!fiber) {
|
|
9
|
-
return {};
|
|
10
|
-
}
|
|
11
|
-
const res: {
|
|
12
|
-
[id: string]: true;
|
|
13
|
-
} = {};
|
|
14
|
-
let parent = fiber?._debugOwner;
|
|
15
|
-
|
|
16
|
-
while (parent) {
|
|
17
|
-
res[makeFiberId(parent)] = true;
|
|
18
|
-
parent = parent?._debugOwner;
|
|
19
|
-
}
|
|
20
|
-
return res;
|
|
21
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { mergeRects } from "./mergeRects";
|
|
2
|
-
import { SimpleDOMRect } from "../types/types";
|
|
3
|
-
|
|
4
|
-
export function getMultipleElementsBoundingBox(
|
|
5
|
-
children: HTMLElement[]
|
|
6
|
-
): SimpleDOMRect | null {
|
|
7
|
-
let composedRect: SimpleDOMRect | null = null;
|
|
8
|
-
|
|
9
|
-
children.forEach((child) => {
|
|
10
|
-
const box = child.getBoundingClientRect();
|
|
11
|
-
if (!box) {
|
|
12
|
-
return;
|
|
13
|
-
}
|
|
14
|
-
if (box.width <= 0 || box.height <= 0) {
|
|
15
|
-
// ignore zero-sized rects
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
if (composedRect) {
|
|
19
|
-
composedRect = mergeRects(composedRect, box);
|
|
20
|
-
} else {
|
|
21
|
-
composedRect = box;
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
|
-
return composedRect;
|
|
25
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { findFiberByHtmlElement } from "../adapters/react/findFiberByHtmlElement";
|
|
2
|
-
import { fiberToSimple } from "../adapters/react/fiberToSimple";
|
|
3
|
-
|
|
4
|
-
export function getPathToParent(element: HTMLElement) {
|
|
5
|
-
const fiber = findFiberByHtmlElement(element, false);
|
|
6
|
-
if (!fiber) {
|
|
7
|
-
return;
|
|
8
|
-
}
|
|
9
|
-
let res = fiberToSimple(fiber);
|
|
10
|
-
let parent = fiber?._debugOwner;
|
|
11
|
-
|
|
12
|
-
while (parent) {
|
|
13
|
-
res = fiberToSimple(parent, [res]);
|
|
14
|
-
parent = parent?._debugOwner;
|
|
15
|
-
}
|
|
16
|
-
return res;
|
|
17
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import getUsableFileName from "./getUsableFileName"; // assuming the function is in filenameUtils.ts
|
|
2
|
-
import { describe, expect, it } from "vitest";
|
|
3
|
-
|
|
4
|
-
describe("getUsableFileName", () => {
|
|
5
|
-
it("should return filename if it is not index.<extension>", () => {
|
|
6
|
-
expect(getUsableFileName("myProject/utils/getSomething.js")).toBe(
|
|
7
|
-
"getSomething.js"
|
|
8
|
-
);
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
it("should return parent folder and filename if the filename is index.<extension>", () => {
|
|
12
|
-
expect(getUsableFileName("myProject/Button/index.tsx")).toBe(
|
|
13
|
-
"Button/index.tsx"
|
|
14
|
-
);
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
it("should handle paths with only one segment", () => {
|
|
18
|
-
expect(getUsableFileName("file.ts")).toBe("file.ts");
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
it("should handle paths with index.<extension> without parent folder", () => {
|
|
22
|
-
expect(getUsableFileName("index.ts")).toBe("index.ts");
|
|
23
|
-
});
|
|
24
|
-
});
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
export default function getUsableFileName(path: string): string {
|
|
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
|
-
|
|
9
|
-
const fileName = pathSegments[pathSegments.length - 1] || "unnamed";
|
|
10
|
-
|
|
11
|
-
if (fileName.startsWith("index.")) {
|
|
12
|
-
// If the file name is index.<extension>, return the parent folder's name
|
|
13
|
-
// along with the filename.
|
|
14
|
-
return `${pathSegments[pathSegments.length - 2]}/${fileName}`;
|
|
15
|
-
} else {
|
|
16
|
-
// Otherwise, just return the filename.
|
|
17
|
-
return fileName;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { transformPath } from "./transformPath";
|
|
2
|
-
import { describe, expect, test } from "vitest";
|
|
3
|
-
|
|
4
|
-
describe("transformPath", () => {
|
|
5
|
-
test("replacing internal url to external", () => {
|
|
6
|
-
expect(transformPath("/app/src/myFile.js", "/app/", "C://myPath/")).toBe(
|
|
7
|
-
"C://myPath/src/myFile.js"
|
|
8
|
-
);
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
test("unifying absolute and relative paths", () => {
|
|
12
|
-
const from = "^/src/";
|
|
13
|
-
const to = "/myPath/src/";
|
|
14
|
-
|
|
15
|
-
expect(transformPath("/src/myFile.js", from, to)).toBe(
|
|
16
|
-
"/myPath/src/myFile.js"
|
|
17
|
-
);
|
|
18
|
-
expect(transformPath("/myPath/src/myFile.js", from, to)).toBe(
|
|
19
|
-
"/myPath/src/myFile.js"
|
|
20
|
-
);
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
test("invalid regex should keep original", () => {
|
|
24
|
-
expect(transformPath("/app/src/myFile.js", "[", "C://myPath/")).toBe(
|
|
25
|
-
"/app/src/myFile.js"
|
|
26
|
-
);
|
|
27
|
-
});
|
|
28
|
-
});
|