diff --git a/src/content-main-world.ts b/src/content-main-world.ts
index 79ac6d1..1020107 100644
--- a/src/content-main-world.ts
+++ b/src/content-main-world.ts
@@ -11,6 +11,7 @@ let inspecting = false;
let openInEditorUrl = DEFAULT_OPEN_IN_EDITOR_URL;
const mousePos = { x: 0, y: 0 };
let openInEditorMethod = 'url';
+let pathMappings = '';
const getInspectName = (element: HTMLElement) => {
const fiber = findFiberByHostInstance(element);
@@ -74,7 +75,7 @@ const handleInspectorClick = async (e: MouseEvent) => {
target.id = tmpId;
window.postMessage("inspected", "*");
- const deepLink = getEditorLink(openInEditorUrl, fiber._debugSource)
+ const deepLink = getEditorLink(openInEditorUrl, fiber._debugSource, pathMappings)
if(openInEditorMethod === 'fetch'){
fetch(deepLink);
}else{
@@ -101,6 +102,7 @@ window.addEventListener("message", ({ data }) => {
if (data.type === "options" && data.openInEditorUrl) {
openInEditorUrl = data.openInEditorUrl;
openInEditorMethod = data.openInEditorMethod;
+ pathMappings = data.pathMappings || '';
}
});
diff --git a/src/content.ts b/src/content.ts
index 540c89b..9d56c12 100644
--- a/src/content.ts
+++ b/src/content.ts
@@ -11,7 +11,7 @@ script.onload = () => {
if (request === "inspect") {
window.postMessage(request, "*");
chrome.storage.sync.get(
- { openInEditorUrl: DEFAULT_OPEN_IN_EDITOR_URL, openInEditorMethod:'url' },
+ { openInEditorUrl: DEFAULT_OPEN_IN_EDITOR_URL, openInEditorMethod:'url', pathMappings: '' },
(items) => {
window.postMessage({ type: "options", ...items }, "*");
}
diff --git a/src/options.html b/src/options.html
index 6b5b312..e2bbba5 100644
--- a/src/options.html
+++ b/src/options.html
@@ -125,6 +125,15 @@
React Inspector Options
+
diff --git a/src/options.ts b/src/options.ts
index 049a9b9..dc6ee1c 100644
--- a/src/options.ts
+++ b/src/options.ts
@@ -7,26 +7,32 @@ const getElements = () => {
const openInEditorMethod = document.getElementById('open-in-editor-method') as HTMLSelectElement;
- return {openInEditorUrl,openInEditorMethod}
+ const pathMappings = document.getElementById('path-mappings') as HTMLTextAreaElement;
+
+ return {openInEditorUrl, openInEditorMethod, pathMappings}
}
const initOptions = () => {
-
- const { openInEditorUrl, openInEditorMethod } = getElements();
+ const { openInEditorUrl, openInEditorMethod, pathMappings } = getElements();
chrome.storage.sync.get(
- { openInEditorUrl: DEFAULT_OPEN_IN_EDITOR_URL, openInEditorMethod:'url' },
+ { openInEditorUrl: DEFAULT_OPEN_IN_EDITOR_URL, openInEditorMethod:'url', pathMappings: '' },
(items) => {
openInEditorUrl.value = items.openInEditorUrl;
openInEditorMethod.value = items.openInEditorMethod;
+ pathMappings.value = items.pathMappings;
}
);
};
const saveOptions = (feedbackMsg: string) => {
- const { openInEditorUrl, openInEditorMethod } = getElements();
+ const { openInEditorUrl, openInEditorMethod, pathMappings } = getElements();
- chrome.storage.sync.set({ openInEditorUrl: openInEditorUrl.value, openInEditorMethod:openInEditorMethod.value }, () => {
+ chrome.storage.sync.set({
+ openInEditorUrl: openInEditorUrl.value,
+ openInEditorMethod: openInEditorMethod.value,
+ pathMappings: pathMappings.value
+ }, () => {
const status = document.getElementById("status")!;
status.textContent = feedbackMsg;
setTimeout(() => {
diff --git a/src/utils.ts b/src/utils.ts
index e719946..a1fafbd 100644
--- a/src/utils.ts
+++ b/src/utils.ts
@@ -16,34 +16,54 @@ export const checkDevtoolsGlobalHook = (): boolean =>
window.__REACT_DEVTOOLS_GLOBAL_HOOK__ &&
window.__REACT_DEVTOOLS_GLOBAL_HOOK__.renderers &&
window.__REACT_DEVTOOLS_GLOBAL_HOOK__.renderers.size > 0 &&
- window.__REACT_DEVTOOLS_GLOBAL_HOOK__.renderers.get(1);
-
-// TODO Refactoring needed ref react/packages/react-devtools-shared/src/backend/agent.js getBestMatchingRendererInterface
-const getDevtoolsGlobalHookRenderer = () => {
- if (!checkDevtoolsGlobalHook()) return null;
- return window.__REACT_DEVTOOLS_GLOBAL_HOOK__.renderers.get(1);
-};
+ window.__REACT_DEVTOOLS_GLOBAL_HOOK__.renderers.values().length > 0;
export const findFiberByHostInstance = (
target: HTMLElement
): { _debugSource: DebugSource } | null => {
if (!checkDevtoolsGlobalHook()) return null;
+ const renderers = window.__REACT_DEVTOOLS_GLOBAL_HOOK__.renderers;
+
+ // Try all available renderers
+ for (const [, renderer] of renderers.entries()) {
+ if (!renderer?.findFiberByHostInstance) continue;
+
+ const fiber = renderer.findFiberByHostInstance(target);
+ if (fiber && fiber._debugSource) {
+ return fiber;
+ }
+ }
+
+ return null;
+};
- const renderer = getDevtoolsGlobalHookRenderer();
- if (!renderer) return null;
+export const applyPathMappings = (path: string, pathMappings: string): string => {
+ if (!path || !pathMappings) return path;
- const fiber = renderer.findFiberByHostInstance(target) || null;
+ const lines = pathMappings.split('\n');
+ for (const line of lines) {
+ const trimmed = line.trim();
+ if (!trimmed) continue;
- return fiber && fiber._debugSource ? fiber : null;
+ const [from, to] = trimmed.split('|');
+ if (from && to && path.startsWith(from.trim())) {
+ return path.replace(from.trim(), to.trim());
+ }
+ }
+
+ return path;
};
export const getEditorLink = (
openInEditorUrl: string,
- debugSource: DebugSource
+ debugSource: DebugSource,
+ pathMappings: string = ''
) => {
- const { fileName, columnNumber, lineNumber } = debugSource;
+ const { columnNumber, lineNumber } = debugSource;
+ const fileName = applyPathMappings(debugSource.fileName || '', pathMappings);
+
return openInEditorUrl
- .replace("{path}", fileName || "")
+ .replace("{path}", fileName)
.replace("{line}", lineNumber ? lineNumber.toString() : "0")
.replace("{column}", columnNumber ? columnNumber.toString() : "0");
};