one 1.2.83 → 1.2.84
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/devtools/dev.mjs +44 -0
- package/devtools/devtools.mjs +540 -0
- package/devtools/source-inspector.mjs +201 -0
- package/dist/cjs/cli/daemon.cjs +136 -0
- package/dist/cjs/cli/daemon.js +112 -0
- package/dist/cjs/cli/daemon.js.map +6 -0
- package/dist/cjs/cli/daemon.native.js +173 -0
- package/dist/cjs/cli/daemon.native.js.map +1 -0
- package/dist/cjs/createHandleRequest.cjs +15 -8
- package/dist/cjs/createHandleRequest.js +10 -6
- package/dist/cjs/createHandleRequest.js.map +1 -1
- package/dist/cjs/createHandleRequest.native.js +8 -3
- package/dist/cjs/createHandleRequest.native.js.map +1 -1
- package/dist/cjs/daemon/index.cjs +24 -0
- package/dist/cjs/daemon/index.js +21 -0
- package/dist/cjs/daemon/index.js.map +6 -0
- package/dist/cjs/daemon/index.native.js +27 -0
- package/dist/cjs/daemon/index.native.js.map +1 -0
- package/dist/cjs/daemon/ipc.cjs +235 -0
- package/dist/cjs/daemon/ipc.js +204 -0
- package/dist/cjs/daemon/ipc.js.map +6 -0
- package/dist/cjs/daemon/ipc.native.js +276 -0
- package/dist/cjs/daemon/ipc.native.js.map +1 -0
- package/dist/cjs/daemon/picker.cjs +223 -0
- package/dist/cjs/daemon/picker.js +191 -0
- package/dist/cjs/daemon/picker.js.map +6 -0
- package/dist/cjs/daemon/picker.native.js +308 -0
- package/dist/cjs/daemon/picker.native.js.map +1 -0
- package/dist/cjs/daemon/proxy.cjs +75 -0
- package/dist/cjs/daemon/proxy.js +70 -0
- package/dist/cjs/daemon/proxy.js.map +6 -0
- package/dist/cjs/daemon/proxy.native.js +81 -0
- package/dist/cjs/daemon/proxy.native.js.map +1 -0
- package/dist/cjs/daemon/registry.cjs +85 -0
- package/dist/cjs/daemon/registry.js +81 -0
- package/dist/cjs/daemon/registry.js.map +6 -0
- package/dist/cjs/daemon/registry.native.js +120 -0
- package/dist/cjs/daemon/registry.native.js.map +1 -0
- package/dist/cjs/daemon/server.cjs +178 -0
- package/dist/cjs/daemon/server.js +179 -0
- package/dist/cjs/daemon/server.js.map +6 -0
- package/dist/cjs/daemon/server.native.js +200 -0
- package/dist/cjs/daemon/server.native.js.map +1 -0
- package/dist/cjs/daemon/tui.cjs +223 -0
- package/dist/cjs/daemon/tui.js +192 -0
- package/dist/cjs/daemon/tui.js.map +6 -0
- package/dist/cjs/daemon/tui.native.js +234 -0
- package/dist/cjs/daemon/tui.native.js.map +1 -0
- package/dist/cjs/daemon/types.cjs +16 -0
- package/dist/cjs/daemon/types.js +14 -0
- package/dist/cjs/daemon/types.js.map +6 -0
- package/dist/cjs/daemon/types.native.js +19 -0
- package/dist/cjs/daemon/types.native.js.map +1 -0
- package/dist/cjs/daemon/utils.cjs +74 -0
- package/dist/cjs/daemon/utils.js +65 -0
- package/dist/cjs/daemon/utils.js.map +6 -0
- package/dist/cjs/daemon/utils.native.js +83 -0
- package/dist/cjs/daemon/utils.native.js.map +1 -0
- package/dist/cjs/fork/createMemoryHistory.cjs +22 -8
- package/dist/cjs/fork/createMemoryHistory.js +20 -6
- package/dist/cjs/fork/createMemoryHistory.js.map +1 -1
- package/dist/cjs/fork/createMemoryHistory.native.js +22 -8
- package/dist/cjs/fork/createMemoryHistory.native.js.map +1 -1
- package/dist/cjs/fork/useLinking.cjs +52 -13
- package/dist/cjs/fork/useLinking.js +35 -10
- package/dist/cjs/fork/useLinking.js.map +1 -1
- package/dist/cjs/index.cjs +6 -2
- package/dist/cjs/index.js +4 -2
- package/dist/cjs/index.js.map +2 -2
- package/dist/cjs/index.native.js +6 -2
- package/dist/cjs/index.native.js.map +1 -1
- package/dist/cjs/router/linkingConfig.cjs +13 -2
- package/dist/cjs/router/linkingConfig.js +14 -5
- package/dist/cjs/router/linkingConfig.js.map +1 -1
- package/dist/cjs/router/linkingConfig.native.js +10 -1
- package/dist/cjs/router/linkingConfig.native.js.map +1 -1
- package/dist/cjs/router/routeMask.cjs +137 -0
- package/dist/cjs/router/routeMask.js +127 -0
- package/dist/cjs/router/routeMask.js.map +6 -0
- package/dist/cjs/router/routeMask.native.js +160 -0
- package/dist/cjs/router/routeMask.native.js.map +1 -0
- package/dist/cjs/router/router.cjs +26 -3
- package/dist/cjs/router/router.js +23 -3
- package/dist/cjs/router/router.js.map +1 -1
- package/dist/cjs/router/router.native.js +26 -3
- package/dist/cjs/router/router.native.js.map +1 -1
- package/dist/cjs/server/PreloadScripts.native.js +45 -39
- package/dist/cjs/server/PreloadScripts.native.js.map +1 -6
- package/dist/cjs/vite/DevHead.cjs +2 -909
- package/dist/cjs/vite/DevHead.js +1 -917
- package/dist/cjs/vite/DevHead.js.map +1 -1
- package/dist/cjs/vite/DevHead.native.js +1 -882
- package/dist/cjs/vite/DevHead.native.js.map +1 -1
- package/dist/cjs/vite/one.cjs +4 -1
- package/dist/cjs/vite/one.js +4 -2
- package/dist/cjs/vite/one.js.map +1 -1
- package/dist/cjs/vite/one.native.js +4 -1
- package/dist/cjs/vite/one.native.js.map +1 -1
- package/dist/cjs/vite/plugins/devtoolsPlugin.cjs +55 -0
- package/dist/cjs/vite/plugins/devtoolsPlugin.js +49 -0
- package/dist/cjs/vite/plugins/devtoolsPlugin.js.map +6 -0
- package/dist/cjs/vite/plugins/devtoolsPlugin.native.js +58 -0
- package/dist/cjs/vite/plugins/devtoolsPlugin.native.js.map +1 -0
- package/dist/cjs/vite/plugins/fileSystemRouterPlugin.cjs +1 -6
- package/dist/cjs/vite/plugins/fileSystemRouterPlugin.js +1 -6
- package/dist/cjs/vite/plugins/fileSystemRouterPlugin.js.map +1 -1
- package/dist/cjs/vite/plugins/fileSystemRouterPlugin.native.js +1 -6
- package/dist/cjs/vite/plugins/fileSystemRouterPlugin.native.js.map +1 -1
- package/dist/cjs/vite/plugins/virtualEntryPlugin.cjs +7 -1
- package/dist/cjs/vite/plugins/virtualEntryPlugin.js +5 -1
- package/dist/cjs/vite/plugins/virtualEntryPlugin.js.map +1 -1
- package/dist/cjs/vite/plugins/virtualEntryPlugin.native.js +8 -1
- package/dist/cjs/vite/plugins/virtualEntryPlugin.native.js.map +1 -1
- package/dist/esm/cli/daemon.js +89 -0
- package/dist/esm/cli/daemon.js.map +6 -0
- package/dist/esm/cli/daemon.mjs +102 -0
- package/dist/esm/cli/daemon.mjs.map +1 -0
- package/dist/esm/cli/daemon.native.js +136 -0
- package/dist/esm/cli/daemon.native.js.map +1 -0
- package/dist/esm/createHandleRequest.js +10 -5
- package/dist/esm/createHandleRequest.js.map +1 -1
- package/dist/esm/createHandleRequest.mjs +15 -8
- package/dist/esm/createHandleRequest.mjs.map +1 -1
- package/dist/esm/createHandleRequest.native.js +8 -3
- package/dist/esm/createHandleRequest.native.js.map +1 -1
- package/dist/esm/daemon/index.js +8 -0
- package/dist/esm/daemon/index.js.map +6 -0
- package/dist/esm/daemon/index.mjs +8 -0
- package/dist/esm/daemon/index.mjs.map +1 -0
- package/dist/esm/daemon/index.native.js +8 -0
- package/dist/esm/daemon/index.native.js.map +1 -0
- package/dist/esm/daemon/ipc.js +192 -0
- package/dist/esm/daemon/ipc.js.map +6 -0
- package/dist/esm/daemon/ipc.mjs +191 -0
- package/dist/esm/daemon/ipc.mjs.map +1 -0
- package/dist/esm/daemon/ipc.native.js +229 -0
- package/dist/esm/daemon/ipc.native.js.map +1 -0
- package/dist/esm/daemon/picker.js +169 -0
- package/dist/esm/daemon/picker.js.map +6 -0
- package/dist/esm/daemon/picker.mjs +186 -0
- package/dist/esm/daemon/picker.mjs.map +1 -0
- package/dist/esm/daemon/picker.native.js +268 -0
- package/dist/esm/daemon/picker.native.js.map +1 -0
- package/dist/esm/daemon/proxy.js +47 -0
- package/dist/esm/daemon/proxy.js.map +6 -0
- package/dist/esm/daemon/proxy.mjs +40 -0
- package/dist/esm/daemon/proxy.mjs.map +1 -0
- package/dist/esm/daemon/proxy.native.js +43 -0
- package/dist/esm/daemon/proxy.native.js.map +1 -0
- package/dist/esm/daemon/registry.js +65 -0
- package/dist/esm/daemon/registry.js.map +6 -0
- package/dist/esm/daemon/registry.mjs +53 -0
- package/dist/esm/daemon/registry.mjs.map +1 -0
- package/dist/esm/daemon/registry.native.js +85 -0
- package/dist/esm/daemon/registry.native.js.map +1 -0
- package/dist/esm/daemon/server.js +167 -0
- package/dist/esm/daemon/server.js.map +6 -0
- package/dist/esm/daemon/server.mjs +143 -0
- package/dist/esm/daemon/server.mjs.map +1 -0
- package/dist/esm/daemon/server.native.js +162 -0
- package/dist/esm/daemon/server.native.js.map +1 -0
- package/dist/esm/daemon/tui.js +171 -0
- package/dist/esm/daemon/tui.js.map +6 -0
- package/dist/esm/daemon/tui.mjs +187 -0
- package/dist/esm/daemon/tui.mjs.map +1 -0
- package/dist/esm/daemon/tui.native.js +195 -0
- package/dist/esm/daemon/tui.native.js.map +1 -0
- package/dist/esm/daemon/types.js +1 -0
- package/dist/esm/daemon/types.js.map +6 -0
- package/dist/esm/daemon/types.mjs +2 -0
- package/dist/esm/daemon/types.mjs.map +1 -0
- package/dist/esm/daemon/types.native.js +2 -0
- package/dist/esm/daemon/types.native.js.map +1 -0
- package/dist/esm/daemon/utils.js +42 -0
- package/dist/esm/daemon/utils.js.map +6 -0
- package/dist/esm/daemon/utils.mjs +39 -0
- package/dist/esm/daemon/utils.mjs.map +1 -0
- package/dist/esm/daemon/utils.native.js +45 -0
- package/dist/esm/daemon/utils.native.js.map +1 -0
- package/dist/esm/fork/createMemoryHistory.js +20 -6
- package/dist/esm/fork/createMemoryHistory.js.map +1 -1
- package/dist/esm/fork/createMemoryHistory.mjs +22 -8
- package/dist/esm/fork/createMemoryHistory.mjs.map +1 -1
- package/dist/esm/fork/createMemoryHistory.native.js +22 -8
- package/dist/esm/fork/createMemoryHistory.native.js.map +1 -1
- package/dist/esm/fork/useLinking.js +35 -9
- package/dist/esm/fork/useLinking.js.map +1 -1
- package/dist/esm/fork/useLinking.mjs +52 -13
- package/dist/esm/fork/useLinking.mjs.map +1 -1
- package/dist/esm/index.js +4 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index.mjs +3 -1
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/index.native.js +3 -1
- package/dist/esm/index.native.js.map +1 -1
- package/dist/esm/router/linkingConfig.js +14 -4
- package/dist/esm/router/linkingConfig.js.map +1 -1
- package/dist/esm/router/linkingConfig.mjs +12 -1
- package/dist/esm/router/linkingConfig.mjs.map +1 -1
- package/dist/esm/router/linkingConfig.native.js +10 -1
- package/dist/esm/router/linkingConfig.native.js.map +1 -1
- package/dist/esm/router/routeMask.js +111 -0
- package/dist/esm/router/routeMask.js.map +6 -0
- package/dist/esm/router/routeMask.mjs +108 -0
- package/dist/esm/router/routeMask.mjs.map +1 -0
- package/dist/esm/router/routeMask.native.js +128 -0
- package/dist/esm/router/routeMask.native.js.map +1 -0
- package/dist/esm/router/router.js +23 -2
- package/dist/esm/router/router.js.map +1 -1
- package/dist/esm/router/router.mjs +24 -3
- package/dist/esm/router/router.mjs.map +1 -1
- package/dist/esm/router/router.native.js +24 -3
- package/dist/esm/router/router.native.js.map +1 -1
- package/dist/esm/server/PreloadScripts.native.js +29 -33
- package/dist/esm/server/PreloadScripts.native.js.map +1 -6
- package/dist/esm/vite/DevHead.js +1 -917
- package/dist/esm/vite/DevHead.js.map +1 -1
- package/dist/esm/vite/DevHead.mjs +2 -909
- package/dist/esm/vite/DevHead.mjs.map +1 -1
- package/dist/esm/vite/DevHead.native.js +0 -881
- package/dist/esm/vite/DevHead.native.js.map +1 -1
- package/dist/esm/vite/one.js +4 -1
- package/dist/esm/vite/one.js.map +1 -1
- package/dist/esm/vite/one.mjs +4 -1
- package/dist/esm/vite/one.mjs.map +1 -1
- package/dist/esm/vite/one.native.js +4 -1
- package/dist/esm/vite/one.native.js.map +1 -1
- package/dist/esm/vite/plugins/devtoolsPlugin.js +33 -0
- package/dist/esm/vite/plugins/devtoolsPlugin.js.map +6 -0
- package/dist/esm/vite/plugins/devtoolsPlugin.mjs +31 -0
- package/dist/esm/vite/plugins/devtoolsPlugin.mjs.map +1 -0
- package/dist/esm/vite/plugins/devtoolsPlugin.native.js +31 -0
- package/dist/esm/vite/plugins/devtoolsPlugin.native.js.map +1 -0
- package/dist/esm/vite/plugins/fileSystemRouterPlugin.js +1 -6
- package/dist/esm/vite/plugins/fileSystemRouterPlugin.js.map +1 -1
- package/dist/esm/vite/plugins/fileSystemRouterPlugin.mjs +1 -6
- package/dist/esm/vite/plugins/fileSystemRouterPlugin.mjs.map +1 -1
- package/dist/esm/vite/plugins/fileSystemRouterPlugin.native.js +1 -6
- package/dist/esm/vite/plugins/fileSystemRouterPlugin.native.js.map +1 -1
- package/dist/esm/vite/plugins/virtualEntryPlugin.js +5 -1
- package/dist/esm/vite/plugins/virtualEntryPlugin.js.map +1 -1
- package/dist/esm/vite/plugins/virtualEntryPlugin.mjs +7 -1
- package/dist/esm/vite/plugins/virtualEntryPlugin.mjs.map +1 -1
- package/dist/esm/vite/plugins/virtualEntryPlugin.native.js +8 -1
- package/dist/esm/vite/plugins/virtualEntryPlugin.native.js.map +1 -1
- package/package.json +12 -10
- package/src/createHandleRequest.ts +16 -3
- package/src/fork/createMemoryHistory.tsx +39 -4
- package/src/fork/useLinking.ts +83 -12
- package/src/index.ts +3 -0
- package/src/router/linkingConfig.ts +21 -4
- package/src/router/routeMask.ts +293 -0
- package/src/router/router.ts +53 -1
- package/src/vite/DevHead.tsx +1 -924
- package/src/vite/one.ts +4 -0
- package/src/vite/plugins/devtoolsPlugin.ts +45 -0
- package/src/vite/plugins/fileSystemRouterPlugin.tsx +2 -7
- package/src/vite/plugins/virtualEntryPlugin.ts +12 -3
- package/src/vite/types.ts +1 -0
- package/types/cli/daemon.d.ts.map +1 -0
- package/types/createHandleRequest.d.ts.map +1 -1
- package/types/daemon/index.d.ts.map +1 -0
- package/types/daemon/ipc.d.ts.map +1 -0
- package/types/daemon/picker.d.ts.map +1 -0
- package/types/daemon/proxy.d.ts.map +1 -0
- package/types/daemon/registry.d.ts.map +1 -0
- package/types/daemon/server.d.ts.map +1 -0
- package/types/daemon/tui.d.ts.map +1 -0
- package/types/daemon/types.d.ts.map +1 -0
- package/types/daemon/utils.d.ts.map +1 -0
- package/types/fork/createMemoryHistory.d.ts +6 -2
- package/types/fork/createMemoryHistory.d.ts.map +1 -1
- package/types/fork/useLinking.d.ts.map +1 -1
- package/types/index.d.ts +2 -0
- package/types/index.d.ts.map +1 -1
- package/types/router/linkingConfig.d.ts.map +1 -1
- package/types/router/routeMask.d.ts +130 -0
- package/types/router/routeMask.d.ts.map +1 -0
- package/types/router/router.d.ts +23 -0
- package/types/router/router.d.ts.map +1 -1
- package/types/vite/DevHead.d.ts.map +1 -1
- package/types/vite/one.d.ts.map +1 -1
- package/types/vite/plugins/devtoolsPlugin.d.ts +5 -0
- package/types/vite/plugins/devtoolsPlugin.d.ts.map +1 -0
- package/types/vite/plugins/fileSystemRouterPlugin.d.ts.map +1 -1
- package/types/vite/plugins/virtualEntryPlugin.d.ts +1 -3
- package/types/vite/plugins/virtualEntryPlugin.d.ts.map +1 -1
- package/types/vite/types.d.ts.map +1 -1
|
@@ -1,886 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { VIRTUAL_SSR_CSS_HREF } from "../constants.native.js";
|
|
3
|
-
var ROUTE_HMR_SCRIPT = 'import { createHotContext } from "/@vite/client"; const hot = createHotContext("/__one_route_hmr"); hot.on("one:route-update", (data) => { if (window.__oneRouteCache) { if (data?.file) { window.__oneRouteCache.clearFile(data.file); } else { window.__oneRouteCache.clear(); } } window.dispatchEvent(new CustomEvent("one-hmr-update")); });',
|
|
4
|
-
LOADER_HMR_SCRIPT = 'import { createHotContext } from "/@vite/client"; const hot = createHotContext("/__one_loader_hmr"); hot.on("one:loader-data-update", async (data) => { if (data?.routePaths && window.__oneRefetchLoader) { const currentPath = window.location.pathname.replace(/\\/$/, "") || "/"; for (const routePath of data.routePaths) { if (routePath === currentPath) { try { await window.__oneRefetchLoader(routePath); } catch (err) { console.error("[one] Error refetching loader:", err); } } } } });',
|
|
5
|
-
REACT_REFRESH_SCRIPT = 'import { injectIntoGlobalHook } from "/@react-refresh"; injectIntoGlobalHook(window); window.$RefreshReg$ = () => {}; window.$RefreshSig$ = () => (type) => type;',
|
|
6
|
-
ONE_DEVTOOLS_SCRIPT = `
|
|
7
|
-
(function() {
|
|
8
|
-
try {
|
|
9
|
-
var host = null;
|
|
10
|
-
var shadow = null;
|
|
11
|
-
var spotlightDialog = null;
|
|
12
|
-
var panelDialog = null;
|
|
13
|
-
var panel = null;
|
|
14
|
-
var activeTab = 'seo';
|
|
15
|
-
var isDragging = false;
|
|
16
|
-
var dragOffset = { x: 0, y: 0 };
|
|
17
|
-
var panelPos = { x: 20, y: 20 };
|
|
18
|
-
var snappedEdge = { h: null, v: null };
|
|
19
|
-
var removalObserver = null;
|
|
20
|
-
|
|
21
|
-
var LOGO_SVG = '<svg width="24" height="24" viewBox="0 0 100 100"><circle cx="50" cy="50" r="48" fill="#FCD34D" stroke="#222" stroke-width="2"/><circle cx="50" cy="35" r="16" fill="white"/><text x="50" y="41" text-anchor="middle" font-family="system-ui" font-size="16" font-weight="bold" fill="#222">1</text></svg>';
|
|
22
|
-
|
|
23
|
-
function escapeHtml(str) {
|
|
24
|
-
if (!str) return '';
|
|
25
|
-
return String(str).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function createHost() {
|
|
29
|
-
if (host) return;
|
|
30
|
-
host = document.createElement('div');
|
|
31
|
-
host.id = 'one-devtools';
|
|
32
|
-
shadow = host.attachShadow({ mode: 'open' });
|
|
33
|
-
|
|
34
|
-
var css = \`
|
|
35
|
-
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
36
|
-
|
|
37
|
-
dialog {
|
|
38
|
-
border: none;
|
|
39
|
-
padding: 0;
|
|
40
|
-
background: transparent;
|
|
41
|
-
max-width: none;
|
|
42
|
-
max-height: none;
|
|
43
|
-
overflow: visible;
|
|
44
|
-
}
|
|
45
|
-
dialog::backdrop {
|
|
46
|
-
background: transparent;
|
|
47
|
-
}
|
|
48
|
-
#spotlight-dialog::backdrop {
|
|
49
|
-
background: rgba(0,0,0,0.3);
|
|
50
|
-
backdrop-filter: blur(8px);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
.spotlight {
|
|
54
|
-
display: flex;
|
|
55
|
-
align-items: center;
|
|
56
|
-
justify-content: center;
|
|
57
|
-
position: fixed;
|
|
58
|
-
inset: 0;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
.spotlight-box {
|
|
62
|
-
background: #1a1a1a;
|
|
63
|
-
border-radius: 12px;
|
|
64
|
-
width: 320px;
|
|
65
|
-
max-width: 90vw;
|
|
66
|
-
overflow: hidden;
|
|
67
|
-
box-shadow: 0 16px 48px rgba(0,0,0,0.5);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
.spotlight-header {
|
|
71
|
-
display: flex;
|
|
72
|
-
align-items: center;
|
|
73
|
-
padding: 12px 16px;
|
|
74
|
-
border-bottom: 1px solid #252525;
|
|
75
|
-
gap: 10px;
|
|
76
|
-
}
|
|
77
|
-
.spotlight-header svg { width: 20px; height: 20px; flex-shrink: 0; }
|
|
78
|
-
.spotlight-header-title { font: 13px system-ui, sans-serif; color: #ccc; flex: 1; }
|
|
79
|
-
.spotlight-header-version { font: 11px system-ui, sans-serif; color: #666; }
|
|
80
|
-
|
|
81
|
-
.spotlight-item {
|
|
82
|
-
display: flex;
|
|
83
|
-
align-items: center;
|
|
84
|
-
gap: 12px;
|
|
85
|
-
padding: 12px 16px;
|
|
86
|
-
color: #ccc;
|
|
87
|
-
font: 13px system-ui, sans-serif;
|
|
88
|
-
cursor: pointer;
|
|
89
|
-
transition: background 0.1s;
|
|
90
|
-
border-bottom: 1px solid #252525;
|
|
91
|
-
}
|
|
92
|
-
.spotlight-item:last-child { border-bottom: none; }
|
|
93
|
-
.spotlight-item:hover { background: #252525; color: #fff; }
|
|
94
|
-
.spotlight-item .key {
|
|
95
|
-
background: #333;
|
|
96
|
-
color: #888;
|
|
97
|
-
padding: 2px 6px;
|
|
98
|
-
border-radius: 4px;
|
|
99
|
-
font-size: 11px;
|
|
100
|
-
margin-left: auto;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
.panel-dialog {
|
|
104
|
-
position: fixed;
|
|
105
|
-
margin: 0;
|
|
106
|
-
inset: unset;
|
|
107
|
-
z-index: 2147483647;
|
|
108
|
-
}
|
|
109
|
-
.panel-dialog::backdrop {
|
|
110
|
-
display: none;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
.panel {
|
|
114
|
-
width: 420px;
|
|
115
|
-
max-width: calc(100vw - 40px);
|
|
116
|
-
max-height: calc(100vh - 40px);
|
|
117
|
-
background: #161616;
|
|
118
|
-
border-radius: 10px;
|
|
119
|
-
box-shadow: 0 12px 40px rgba(0,0,0,0.4);
|
|
120
|
-
display: flex;
|
|
121
|
-
flex-direction: column;
|
|
122
|
-
overflow: hidden;
|
|
123
|
-
font: 13px system-ui, sans-serif;
|
|
124
|
-
color: #ccc;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
.panel-header {
|
|
128
|
-
display: flex;
|
|
129
|
-
align-items: center;
|
|
130
|
-
padding: 8px 12px;
|
|
131
|
-
background: #1a1a1a;
|
|
132
|
-
cursor: grab;
|
|
133
|
-
user-select: none;
|
|
134
|
-
gap: 8px;
|
|
135
|
-
}
|
|
136
|
-
.panel-header:active { cursor: grabbing; }
|
|
137
|
-
.panel-header svg { width: 18px; height: 18px; }
|
|
138
|
-
.panel-title { font-weight: 500; color: #999; font-size: 12px; flex: 1; }
|
|
139
|
-
.panel-close {
|
|
140
|
-
background: none;
|
|
141
|
-
border: none;
|
|
142
|
-
color: #666;
|
|
143
|
-
cursor: pointer;
|
|
144
|
-
padding: 4px;
|
|
145
|
-
font-size: 16px;
|
|
146
|
-
line-height: 1;
|
|
147
|
-
}
|
|
148
|
-
.panel-close:hover { color: #fff; }
|
|
149
|
-
|
|
150
|
-
.tabs {
|
|
151
|
-
display: flex;
|
|
152
|
-
background: #1a1a1a;
|
|
153
|
-
padding: 0 8px;
|
|
154
|
-
gap: 2px;
|
|
155
|
-
overflow-x: auto;
|
|
156
|
-
}
|
|
157
|
-
.tab {
|
|
158
|
-
padding: 8px 12px;
|
|
159
|
-
background: none;
|
|
160
|
-
border: none;
|
|
161
|
-
color: #666;
|
|
162
|
-
font: 12px system-ui, sans-serif;
|
|
163
|
-
cursor: pointer;
|
|
164
|
-
border-bottom: 2px solid transparent;
|
|
165
|
-
transition: all 0.1s;
|
|
166
|
-
}
|
|
167
|
-
.tab:hover { color: #999; }
|
|
168
|
-
.tab.active { color: #fff; border-bottom-color: #666; }
|
|
169
|
-
|
|
170
|
-
.content {
|
|
171
|
-
flex: 1;
|
|
172
|
-
overflow-y: auto;
|
|
173
|
-
padding: 12px;
|
|
174
|
-
min-height: 200px;
|
|
175
|
-
max-height: calc(100vh - 140px);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
.section { margin-bottom: 12px; }
|
|
179
|
-
.section-title { font-size: 11px; color: #666; margin-bottom: 6px; text-transform: uppercase; letter-spacing: 0.5px; }
|
|
180
|
-
|
|
181
|
-
.info-row {
|
|
182
|
-
display: flex;
|
|
183
|
-
gap: 12px;
|
|
184
|
-
padding: 8px 0;
|
|
185
|
-
border-bottom: 1px solid #222;
|
|
186
|
-
}
|
|
187
|
-
.info-row:last-child { border-bottom: none; }
|
|
188
|
-
.info-label { color: #666; font-size: 11px; width: 90px; flex-shrink: 0; padding-top: 1px; }
|
|
189
|
-
.info-value { color: #ccc; font-family: monospace; font-size: 12px; word-break: break-word; line-height: 1.4; flex: 1; }
|
|
190
|
-
|
|
191
|
-
.badge {
|
|
192
|
-
display: inline-block;
|
|
193
|
-
padding: 2px 6px;
|
|
194
|
-
border-radius: 4px;
|
|
195
|
-
font-size: 10px;
|
|
196
|
-
text-transform: uppercase;
|
|
197
|
-
}
|
|
198
|
-
.badge-error { background: #3a2020; color: #f87171; }
|
|
199
|
-
.badge-warn { background: #3a3520; color: #fbbf24; }
|
|
200
|
-
.badge-info { background: #202a3a; color: #60a5fa; }
|
|
201
|
-
.badge-success { background: #1a3a20; color: #4ade80; }
|
|
202
|
-
|
|
203
|
-
.empty { text-align: center; color: #555; padding: 24px; }
|
|
204
|
-
|
|
205
|
-
.error-item {
|
|
206
|
-
background: #1e1e1e;
|
|
207
|
-
border-radius: 6px;
|
|
208
|
-
padding: 10px;
|
|
209
|
-
margin-bottom: 8px;
|
|
210
|
-
border-left: 3px solid #666;
|
|
211
|
-
}
|
|
212
|
-
.error-item.error { border-left-color: #f87171; }
|
|
213
|
-
.error-msg { color: #f87171; font-family: monospace; font-size: 12px; margin-top: 6px; }
|
|
214
|
-
|
|
215
|
-
.timing-bar {
|
|
216
|
-
height: 16px;
|
|
217
|
-
background: #252525;
|
|
218
|
-
border-radius: 4px;
|
|
219
|
-
overflow: hidden;
|
|
220
|
-
display: flex;
|
|
221
|
-
margin: 4px 0;
|
|
222
|
-
}
|
|
223
|
-
.timing-segment { height: 100%; display: flex; align-items: center; justify-content: center; font-size: 9px; color: #fff; }
|
|
224
|
-
.timing-module { background: #555; }
|
|
225
|
-
.timing-exec { background: #888; }
|
|
226
|
-
|
|
227
|
-
.preview-card {
|
|
228
|
-
background: #1e1e1e;
|
|
229
|
-
border-radius: 6px;
|
|
230
|
-
padding: 10px;
|
|
231
|
-
margin-bottom: 10px;
|
|
232
|
-
}
|
|
233
|
-
.preview-title { font-size: 11px; color: #666; margin-bottom: 6px; }
|
|
234
|
-
|
|
235
|
-
.issue-item {
|
|
236
|
-
display: flex;
|
|
237
|
-
align-items: center;
|
|
238
|
-
gap: 8px;
|
|
239
|
-
padding: 6px 0;
|
|
240
|
-
font-size: 12px;
|
|
241
|
-
}
|
|
242
|
-
.issue-icon { font-size: 10px; }
|
|
243
|
-
\`;
|
|
244
|
-
|
|
245
|
-
shadow.innerHTML = '<style>' + css + '</style><dialog id="spotlight-dialog"><div class="spotlight"><div class="spotlight-box" id="spotlight-box"></div></div></dialog><dialog class="panel-dialog" id="panel-dialog"><div class="panel" id="panel"></div></dialog>';
|
|
246
|
-
document.body.appendChild(host);
|
|
247
|
-
|
|
248
|
-
setupSpotlight();
|
|
249
|
-
setupPanel();
|
|
250
|
-
setupKeyboard();
|
|
251
|
-
setupRemovalObserver();
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
// watch for React hydration removing our element and re-create it
|
|
255
|
-
function setupRemovalObserver() {
|
|
256
|
-
if (removalObserver) return;
|
|
257
|
-
removalObserver = new MutationObserver(function(mutations) {
|
|
258
|
-
for (var i = 0; i < mutations.length; i++) {
|
|
259
|
-
var mutation = mutations[i];
|
|
260
|
-
if (mutation.type === 'childList') {
|
|
261
|
-
for (var j = 0; j < mutation.removedNodes.length; j++) {
|
|
262
|
-
var node = mutation.removedNodes[j];
|
|
263
|
-
if (node === host) {
|
|
264
|
-
// our element was removed (likely by React hydration), re-create it
|
|
265
|
-
host = null;
|
|
266
|
-
shadow = null;
|
|
267
|
-
spotlightDialog = null;
|
|
268
|
-
panelDialog = null;
|
|
269
|
-
panel = null;
|
|
270
|
-
setTimeout(createHost, 0);
|
|
271
|
-
return;
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
});
|
|
277
|
-
removalObserver.observe(document.body, { childList: true });
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
function setupSpotlight() {
|
|
281
|
-
spotlightDialog = shadow.getElementById('spotlight-dialog');
|
|
282
|
-
var box = shadow.getElementById('spotlight-box');
|
|
283
|
-
|
|
284
|
-
var items = [
|
|
285
|
-
{ id: 'seo', name: 'SEO Preview', key: '\u2325S' },
|
|
286
|
-
{ id: 'route', name: 'Route Info', key: '\u2325R' },
|
|
287
|
-
{ id: 'loader', name: 'Loader Timing', key: '\u2325L' },
|
|
288
|
-
{ id: 'errors', name: 'Errors', key: '\u2325E' },
|
|
289
|
-
];
|
|
290
|
-
|
|
291
|
-
var header = '<div class="spotlight-header">' + LOGO_SVG + '<span class="spotlight-header-title">Dev Tools</span><span class="spotlight-header-version">v1.2.57</span></div>';
|
|
292
|
-
box.innerHTML = header + items.map(function(item) {
|
|
293
|
-
return '<div class="spotlight-item" data-tab="' + item.id + '"><span>' + item.name + '</span><span class="key">' + item.key + '</span></div>';
|
|
294
|
-
}).join('');
|
|
295
|
-
|
|
296
|
-
box.addEventListener('click', function(e) {
|
|
297
|
-
var item = e.target.closest('.spotlight-item');
|
|
298
|
-
if (item) {
|
|
299
|
-
activeTab = item.dataset.tab;
|
|
300
|
-
hideSpotlight();
|
|
301
|
-
showPanel();
|
|
302
|
-
}
|
|
303
|
-
});
|
|
304
|
-
|
|
305
|
-
// close on backdrop click
|
|
306
|
-
spotlightDialog.addEventListener('click', function(e) {
|
|
307
|
-
if (e.target === spotlightDialog) spotlightDialog.close();
|
|
308
|
-
});
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
function setupPanel() {
|
|
312
|
-
panelDialog = shadow.getElementById('panel-dialog');
|
|
313
|
-
panel = shadow.getElementById('panel');
|
|
314
|
-
panel.innerHTML = '<div class="panel-header" id="panel-header">' + LOGO_SVG + '<span class="panel-title">DevTools</span><button class="panel-close" id="panel-close">\xD7</button></div><div class="tabs" id="tabs"><button class="tab active" data-tab="seo">SEO</button><button class="tab" data-tab="route">Route</button><button class="tab" data-tab="loader">Loader</button><button class="tab" data-tab="errors">Errors</button></div><div class="content" id="content"></div>';
|
|
315
|
-
|
|
316
|
-
shadow.getElementById('panel-close').addEventListener('click', hidePanel);
|
|
317
|
-
|
|
318
|
-
var tabs = shadow.getElementById('tabs');
|
|
319
|
-
tabs.addEventListener('click', function(e) {
|
|
320
|
-
var tab = e.target.closest('.tab');
|
|
321
|
-
if (tab) {
|
|
322
|
-
activeTab = tab.dataset.tab;
|
|
323
|
-
updateTabs();
|
|
324
|
-
updateContent();
|
|
325
|
-
}
|
|
326
|
-
});
|
|
327
|
-
|
|
328
|
-
setupDrag();
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
function setupDrag() {
|
|
332
|
-
var header = shadow.getElementById('panel-header');
|
|
333
|
-
|
|
334
|
-
header.addEventListener('mousedown', function(e) {
|
|
335
|
-
if (e.target.closest('.panel-close')) return;
|
|
336
|
-
isDragging = true;
|
|
337
|
-
var rect = panelDialog.getBoundingClientRect();
|
|
338
|
-
dragOffset.x = e.clientX - rect.left;
|
|
339
|
-
dragOffset.y = e.clientY - rect.top;
|
|
340
|
-
// Store current position before resetting snap state
|
|
341
|
-
panelPos.x = rect.left;
|
|
342
|
-
panelPos.y = rect.top;
|
|
343
|
-
snappedEdge = { h: null, v: null };
|
|
344
|
-
});
|
|
345
|
-
|
|
346
|
-
document.addEventListener('mousemove', function(e) {
|
|
347
|
-
if (!isDragging) return;
|
|
348
|
-
var x = e.clientX - dragOffset.x;
|
|
349
|
-
var y = e.clientY - dragOffset.y;
|
|
350
|
-
var snapDist = 20;
|
|
351
|
-
var w = window.innerWidth;
|
|
352
|
-
var h = window.innerHeight;
|
|
353
|
-
var pw = panelDialog.offsetWidth;
|
|
354
|
-
var ph = panelDialog.offsetHeight;
|
|
355
|
-
var pad = 10;
|
|
356
|
-
|
|
357
|
-
var snapH = null;
|
|
358
|
-
var snapV = null;
|
|
359
|
-
|
|
360
|
-
if (x < snapDist) { snapH = 'left'; }
|
|
361
|
-
else if (x + pw > w - snapDist) { snapH = 'right'; }
|
|
362
|
-
if (y < snapDist) { snapV = 'top'; }
|
|
363
|
-
else if (y + ph > h - snapDist) { snapV = 'bottom'; }
|
|
364
|
-
|
|
365
|
-
snappedEdge = { h: snapH, v: snapV };
|
|
366
|
-
|
|
367
|
-
// Apply horizontal positioning
|
|
368
|
-
if (snapH === 'left') {
|
|
369
|
-
panelDialog.style.left = pad + 'px';
|
|
370
|
-
panelDialog.style.right = 'auto';
|
|
371
|
-
} else if (snapH === 'right') {
|
|
372
|
-
panelDialog.style.left = 'auto';
|
|
373
|
-
panelDialog.style.right = pad + 'px';
|
|
374
|
-
} else {
|
|
375
|
-
panelDialog.style.left = x + 'px';
|
|
376
|
-
panelDialog.style.right = 'auto';
|
|
377
|
-
panelPos.x = x;
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
// Apply vertical positioning
|
|
381
|
-
if (snapV === 'top') {
|
|
382
|
-
panelDialog.style.top = pad + 'px';
|
|
383
|
-
panelDialog.style.bottom = 'auto';
|
|
384
|
-
} else if (snapV === 'bottom') {
|
|
385
|
-
panelDialog.style.top = 'auto';
|
|
386
|
-
panelDialog.style.bottom = pad + 'px';
|
|
387
|
-
} else {
|
|
388
|
-
panelDialog.style.top = y + 'px';
|
|
389
|
-
panelDialog.style.bottom = 'auto';
|
|
390
|
-
panelPos.y = y;
|
|
391
|
-
}
|
|
392
|
-
});
|
|
393
|
-
|
|
394
|
-
document.addEventListener('mouseup', function() {
|
|
395
|
-
isDragging = false;
|
|
396
|
-
});
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
var keyboardSetup = false;
|
|
400
|
-
function setupKeyboard() {
|
|
401
|
-
if (keyboardSetup) return;
|
|
402
|
-
keyboardSetup = true;
|
|
403
|
-
document.addEventListener('keydown', function(e) {
|
|
404
|
-
if (e.altKey && e.code === 'Space') {
|
|
405
|
-
e.preventDefault();
|
|
406
|
-
toggleSpotlight();
|
|
407
|
-
} else if (e.altKey) {
|
|
408
|
-
var tabMap = { KeyS: 'seo', KeyR: 'route', KeyL: 'loader', KeyE: 'errors' };
|
|
409
|
-
var tab = tabMap[e.code];
|
|
410
|
-
if (tab) {
|
|
411
|
-
e.preventDefault();
|
|
412
|
-
activeTab = tab;
|
|
413
|
-
hideSpotlight();
|
|
414
|
-
showPanel();
|
|
415
|
-
}
|
|
416
|
-
} else if (e.code === 'Escape') {
|
|
417
|
-
// dialogs handle escape natively, but we need to handle the case where escape is pressed
|
|
418
|
-
// when only one is open
|
|
419
|
-
if (spotlightDialog && spotlightDialog.open) spotlightDialog.close();
|
|
420
|
-
else if (panelDialog && panelDialog.open) panelDialog.close();
|
|
421
|
-
}
|
|
422
|
-
});
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
function toggleSpotlight() {
|
|
426
|
-
if (spotlightDialog && spotlightDialog.open) hideSpotlight();
|
|
427
|
-
else showSpotlight();
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
function showSpotlight() {
|
|
431
|
-
if (!host) createHost();
|
|
432
|
-
spotlightDialog.showModal();
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
function hideSpotlight() {
|
|
436
|
-
spotlightDialog.close();
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
function showPanel() {
|
|
440
|
-
if (!host) createHost();
|
|
441
|
-
var pad = 10;
|
|
442
|
-
// Apply horizontal positioning based on snap state
|
|
443
|
-
if (snappedEdge.h === 'left') {
|
|
444
|
-
panelDialog.style.left = pad + 'px';
|
|
445
|
-
panelDialog.style.right = 'auto';
|
|
446
|
-
} else if (snappedEdge.h === 'right') {
|
|
447
|
-
panelDialog.style.left = 'auto';
|
|
448
|
-
panelDialog.style.right = pad + 'px';
|
|
449
|
-
} else {
|
|
450
|
-
panelDialog.style.left = panelPos.x + 'px';
|
|
451
|
-
panelDialog.style.right = 'auto';
|
|
452
|
-
}
|
|
453
|
-
// Apply vertical positioning based on snap state
|
|
454
|
-
if (snappedEdge.v === 'top') {
|
|
455
|
-
panelDialog.style.top = pad + 'px';
|
|
456
|
-
panelDialog.style.bottom = 'auto';
|
|
457
|
-
} else if (snappedEdge.v === 'bottom') {
|
|
458
|
-
panelDialog.style.top = 'auto';
|
|
459
|
-
panelDialog.style.bottom = pad + 'px';
|
|
460
|
-
} else {
|
|
461
|
-
panelDialog.style.top = panelPos.y + 'px';
|
|
462
|
-
panelDialog.style.bottom = 'auto';
|
|
463
|
-
}
|
|
464
|
-
panelDialog.show();
|
|
465
|
-
updateTabs();
|
|
466
|
-
updateContent();
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
function hidePanel() {
|
|
470
|
-
panelDialog.close();
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
function updateTabs() {
|
|
474
|
-
shadow.querySelectorAll('.tab').forEach(function(t) {
|
|
475
|
-
t.classList.toggle('active', t.dataset.tab === activeTab);
|
|
476
|
-
});
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
function updateContent() {
|
|
480
|
-
var content = shadow.getElementById('content');
|
|
481
|
-
if (activeTab === 'seo') content.innerHTML = getSeoContent();
|
|
482
|
-
else if (activeTab === 'route') content.innerHTML = getRouteContent();
|
|
483
|
-
else if (activeTab === 'loader') content.innerHTML = getLoaderContent();
|
|
484
|
-
else if (activeTab === 'errors') content.innerHTML = getErrorsContent();
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
function getSeoContent() {
|
|
488
|
-
var title = document.title || '';
|
|
489
|
-
var desc = document.querySelector('meta[name="description"]')?.content || '';
|
|
490
|
-
var ogTitle = document.querySelector('meta[property="og:title"]')?.content || '';
|
|
491
|
-
var ogDesc = document.querySelector('meta[property="og:description"]')?.content || '';
|
|
492
|
-
var ogImage = document.querySelector('meta[property="og:image"]')?.content || '';
|
|
493
|
-
|
|
494
|
-
var issues = [];
|
|
495
|
-
if (!title) issues.push({ type: 'error', msg: 'Missing title' });
|
|
496
|
-
else if (title.length > 60) issues.push({ type: 'warn', msg: 'Title too long (>60)' });
|
|
497
|
-
if (!desc) issues.push({ type: 'error', msg: 'Missing description' });
|
|
498
|
-
else if (desc.length > 160) issues.push({ type: 'warn', msg: 'Description too long (>160)' });
|
|
499
|
-
if (!ogTitle) issues.push({ type: 'warn', msg: 'Missing og:title' });
|
|
500
|
-
if (!ogImage) issues.push({ type: 'warn', msg: 'Missing og:image' });
|
|
501
|
-
|
|
502
|
-
var html = '';
|
|
503
|
-
if (issues.length) {
|
|
504
|
-
html += '<div class="section"><div class="section-title">Issues</div>';
|
|
505
|
-
issues.forEach(function(i) {
|
|
506
|
-
html += '<div class="issue-item"><span class="issue-icon">' + (i.type === 'error' ? '\u2716' : '\u26A0') + '</span><span>' + escapeHtml(i.msg) + '</span></div>';
|
|
507
|
-
});
|
|
508
|
-
html += '</div>';
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
html += '<div class="section"><div class="section-title">Google Preview</div><div class="preview-card" style="background:#fff;color:#202124;padding:12px;border-radius:8px;">';
|
|
512
|
-
html += '<div style="font-size:12px;color:#202124;margin-bottom:2px;">' + escapeHtml(location.hostname) + '</div>';
|
|
513
|
-
html += '<div style="font-size:16px;color:#1a0dab;margin-bottom:4px;">' + escapeHtml(title || 'No title') + '</div>';
|
|
514
|
-
html += '<div style="font-size:13px;color:#4d5156;">' + escapeHtml(desc ? desc.slice(0,160) : 'No description') + '</div>';
|
|
515
|
-
html += '</div></div>';
|
|
516
|
-
|
|
517
|
-
if (ogImage) {
|
|
518
|
-
html += '<div class="section"><div class="section-title">Social Preview</div>';
|
|
519
|
-
html += '<div class="preview-card" style="background:#fff;border-radius:12px;overflow:hidden;border:1px solid #e1e8ed;">';
|
|
520
|
-
html += '<img src="' + escapeHtml(ogImage) + '" style="width:100%;height:auto;display:block;border-bottom:1px solid #e1e8ed;" onerror="this.style.display="none"" />';
|
|
521
|
-
html += '<div style="padding:12px;">';
|
|
522
|
-
html += '<div style="font-size:12px;color:#8899a6;text-transform:uppercase;margin-bottom:2px;">' + escapeHtml(location.hostname) + '</div>';
|
|
523
|
-
html += '<div style="font-size:15px;color:#1c2022;font-weight:700;margin-bottom:4px;line-height:1.3;">' + escapeHtml(ogTitle || title || 'No title') + '</div>';
|
|
524
|
-
html += '<div style="font-size:14px;color:#8899a6;line-height:1.3;">' + escapeHtml((ogDesc || desc || '').slice(0,100)) + '</div>';
|
|
525
|
-
html += '</div></div></div>';
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
html += '<div class="section"><div class="section-title">Meta Tags</div>';
|
|
529
|
-
html += '<div class="info-row"><div class="info-label">title</div><div class="info-value">' + escapeHtml(title || '-') + '</div></div>';
|
|
530
|
-
html += '<div class="info-row"><div class="info-label">description</div><div class="info-value">' + escapeHtml(desc || '-') + '</div></div>';
|
|
531
|
-
html += '<div class="info-row"><div class="info-label">og:title</div><div class="info-value">' + escapeHtml(ogTitle || '-') + '</div></div>';
|
|
532
|
-
html += '<div class="info-row"><div class="info-label">og:description</div><div class="info-value">' + escapeHtml(ogDesc || '-') + '</div></div>';
|
|
533
|
-
html += '<div class="info-row"><div class="info-label">og:image</div><div class="info-value">' + escapeHtml(ogImage || '-') + '</div></div>';
|
|
534
|
-
html += '</div>';
|
|
535
|
-
|
|
536
|
-
return html;
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
function getRouteContent() {
|
|
540
|
-
var pathname = location.pathname;
|
|
541
|
-
var segments = pathname.split('/').filter(Boolean);
|
|
542
|
-
var search = location.search;
|
|
543
|
-
var hash = location.hash;
|
|
544
|
-
var devtools = window.__oneDevtools || {};
|
|
545
|
-
var routeInfo = devtools.routeInfo || {};
|
|
546
|
-
var params = routeInfo.params || {};
|
|
547
|
-
|
|
548
|
-
var html = '<div class="section"><div class="section-title">Current Route</div>';
|
|
549
|
-
html += '<div class="info-row"><span class="info-label">pathname</span><span class="info-value">' + escapeHtml(pathname) + '</span></div>';
|
|
550
|
-
html += '<div class="info-row"><span class="info-label">segments</span><span class="info-value">' + (segments.length ? segments.map(function(s) { return '<span style="background:#252525;padding:2px 6px;border-radius:4px;margin-right:4px;">' + escapeHtml(s) + '</span>'; }).join('') : '/') + '</span></div>';
|
|
551
|
-
if (search) html += '<div class="info-row"><span class="info-label">search</span><span class="info-value">' + escapeHtml(search) + '</span></div>';
|
|
552
|
-
if (hash) html += '<div class="info-row"><span class="info-label">hash</span><span class="info-value">' + escapeHtml(hash) + '</span></div>';
|
|
553
|
-
html += '</div>';
|
|
554
|
-
|
|
555
|
-
if (Object.keys(params).length) {
|
|
556
|
-
html += '<div class="section"><div class="section-title">Route Params</div>';
|
|
557
|
-
Object.entries(params).forEach(function(kv) {
|
|
558
|
-
html += '<div class="info-row"><span class="info-label">' + escapeHtml(kv[0]) + '</span><span class="info-value">' + escapeHtml(String(kv[1])) + '</span></div>';
|
|
559
|
-
});
|
|
560
|
-
html += '</div>';
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
html += '<div class="section"><div class="section-title">Full URL</div>';
|
|
564
|
-
html += '<div style="font-family:monospace;font-size:11px;color:#666;word-break:break-all;">' + escapeHtml(location.href) + '</div>';
|
|
565
|
-
html += '</div>';
|
|
566
|
-
|
|
567
|
-
return html;
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
function getLoaderContent() {
|
|
571
|
-
var devtools = window.__oneDevtools || {};
|
|
572
|
-
var history = typeof devtools.getLoaderTimingHistory === 'function' ? devtools.getLoaderTimingHistory() || [] : [];
|
|
573
|
-
|
|
574
|
-
if (!history.length) {
|
|
575
|
-
return '<div class="empty">No loader timings recorded yet</div>';
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
var maxTime = Math.max.apply(null, history.map(function(t) { return t.totalTime || 0; }));
|
|
579
|
-
var html = '';
|
|
580
|
-
|
|
581
|
-
history.forEach(function(t) {
|
|
582
|
-
var modPct = t.moduleLoadTime && t.totalTime ? (t.moduleLoadTime / t.totalTime) * 100 : 0;
|
|
583
|
-
var execPct = t.executionTime && t.totalTime ? (t.executionTime / t.totalTime) * 100 : 0;
|
|
584
|
-
var widthPct = t.totalTime && maxTime ? (t.totalTime / maxTime) * 100 : 0;
|
|
585
|
-
|
|
586
|
-
html += '<div class="error-item' + (t.error ? ' error' : '') + '">';
|
|
587
|
-
html += '<div style="display:flex;justify-content:space-between;align-items:center;">';
|
|
588
|
-
html += '<span style="font-family:monospace;font-size:11px;">' + escapeHtml(t.path) + '</span>';
|
|
589
|
-
html += '<span class="badge badge-' + (t.error ? 'error' : 'success') + '">' + (t.totalTime ? Math.round(t.totalTime) + 'ms' : '-') + '</span>';
|
|
590
|
-
html += '</div>';
|
|
591
|
-
if (!t.error) {
|
|
592
|
-
html += '<div class="timing-bar" style="width:' + Math.max(20, widthPct) + '%;">';
|
|
593
|
-
html += '<div class="timing-segment timing-module" style="width:' + modPct + '%;" title="Module: ' + Math.round(t.moduleLoadTime || 0) + 'ms"></div>';
|
|
594
|
-
html += '<div class="timing-segment timing-exec" style="width:' + execPct + '%;" title="Exec: ' + Math.round(t.executionTime || 0) + 'ms"></div>';
|
|
595
|
-
html += '</div>';
|
|
596
|
-
}
|
|
597
|
-
if (t.error) html += '<div class="error-msg">' + escapeHtml(t.error) + '</div>';
|
|
598
|
-
html += '</div>';
|
|
599
|
-
});
|
|
600
|
-
|
|
601
|
-
return html;
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
function getErrorsContent() {
|
|
605
|
-
var devtools = window.__oneDevtools || {};
|
|
606
|
-
var errors = devtools.errorHistory || [];
|
|
607
|
-
|
|
608
|
-
if (!errors.length) {
|
|
609
|
-
return '<div class="empty">\u2713 No errors recorded</div>';
|
|
610
|
-
}
|
|
611
|
-
|
|
612
|
-
var html = '';
|
|
613
|
-
errors.forEach(function(err) {
|
|
614
|
-
html += '<div class="error-item error">';
|
|
615
|
-
html += '<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:6px;">';
|
|
616
|
-
html += '<span class="badge badge-error">' + escapeHtml(err.type || 'error') + '</span>';
|
|
617
|
-
html += '<span style="font-size:11px;color:#666;">' + new Date(err.timestamp).toLocaleTimeString() + '</span>';
|
|
618
|
-
html += '</div>';
|
|
619
|
-
html += '<div class="error-msg">' + escapeHtml(err.error?.message || 'Unknown error') + '</div>';
|
|
620
|
-
html += '</div>';
|
|
621
|
-
});
|
|
622
|
-
|
|
623
|
-
return html;
|
|
624
|
-
}
|
|
625
|
-
|
|
626
|
-
// Initialize after React hydration completes
|
|
627
|
-
// use requestIdleCallback to wait for the browser to be idle (after hydration)
|
|
628
|
-
function initAfterHydration() {
|
|
629
|
-
if (typeof requestIdleCallback !== 'undefined') {
|
|
630
|
-
requestIdleCallback(createHost, { timeout: 3000 });
|
|
631
|
-
} else {
|
|
632
|
-
setTimeout(createHost, 100);
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
if (document.readyState === 'complete') {
|
|
637
|
-
initAfterHydration();
|
|
638
|
-
} else {
|
|
639
|
-
window.addEventListener('load', initAfterHydration);
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
// Listen for events
|
|
643
|
-
window.addEventListener('one-loader-timing', function() {
|
|
644
|
-
if (panelDialog && panelDialog.open && activeTab === 'loader') updateContent();
|
|
645
|
-
});
|
|
646
|
-
window.addEventListener('one-error', function(e) {
|
|
647
|
-
var devtools = window.__oneDevtools = window.__oneDevtools || {};
|
|
648
|
-
devtools.errorHistory = devtools.errorHistory || [];
|
|
649
|
-
devtools.errorHistory.unshift(e.detail);
|
|
650
|
-
if (devtools.errorHistory.length > 20) devtools.errorHistory = devtools.errorHistory.slice(0, 20);
|
|
651
|
-
if (panelDialog && panelDialog.open && activeTab === 'errors') updateContent();
|
|
652
|
-
});
|
|
653
|
-
|
|
654
|
-
// Update on navigation
|
|
655
|
-
function onNavigate() {
|
|
656
|
-
if (panelDialog && panelDialog.open) updateContent();
|
|
657
|
-
}
|
|
658
|
-
window.addEventListener('popstate', onNavigate);
|
|
659
|
-
window.addEventListener('one-hmr-update', onNavigate);
|
|
660
|
-
// Also catch pushState/replaceState
|
|
661
|
-
var origPushState = history.pushState;
|
|
662
|
-
var origReplaceState = history.replaceState;
|
|
663
|
-
history.pushState = function() {
|
|
664
|
-
origPushState.apply(this, arguments);
|
|
665
|
-
setTimeout(onNavigate, 0);
|
|
666
|
-
};
|
|
667
|
-
history.replaceState = function() {
|
|
668
|
-
origReplaceState.apply(this, arguments);
|
|
669
|
-
setTimeout(onNavigate, 0);
|
|
670
|
-
};
|
|
671
|
-
|
|
672
|
-
} catch (e) {
|
|
673
|
-
console.error('[One DevTools] Failed to initialize:', e);
|
|
674
|
-
}
|
|
675
|
-
})();
|
|
676
|
-
`,
|
|
677
|
-
SOURCE_INSPECTOR_SCRIPT = `
|
|
678
|
-
(function() {
|
|
679
|
-
try {
|
|
680
|
-
var active = false;
|
|
681
|
-
var host = null;
|
|
682
|
-
var shadow = null;
|
|
683
|
-
var overlay = null;
|
|
684
|
-
var tag = null;
|
|
685
|
-
var holdTimer = null;
|
|
686
|
-
var holdDelay = 500;
|
|
687
|
-
var mousePos = { x: 0, y: 0 };
|
|
688
|
-
var removalObserver = null;
|
|
689
|
-
|
|
690
|
-
function createHost() {
|
|
691
|
-
if (host) return;
|
|
692
|
-
host = document.createElement('div');
|
|
693
|
-
host.id = 'one-source-inspector';
|
|
694
|
-
shadow = host.attachShadow({ mode: 'open' });
|
|
695
|
-
shadow.innerHTML = \`
|
|
696
|
-
<style>
|
|
697
|
-
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
698
|
-
.overlay {
|
|
699
|
-
position: fixed;
|
|
700
|
-
pointer-events: none;
|
|
701
|
-
z-index: 100000;
|
|
702
|
-
background: rgba(100,100,100,0.2);
|
|
703
|
-
border: 2px solid rgba(100,100,100,0.6);
|
|
704
|
-
border-radius: 2px;
|
|
705
|
-
transition: all 0.05s;
|
|
706
|
-
display: none;
|
|
707
|
-
}
|
|
708
|
-
.tag {
|
|
709
|
-
position: fixed;
|
|
710
|
-
pointer-events: none;
|
|
711
|
-
z-index: 100001;
|
|
712
|
-
background: rgba(60,60,60,0.95);
|
|
713
|
-
color: white;
|
|
714
|
-
padding: 4px 8px;
|
|
715
|
-
font-size: 12px;
|
|
716
|
-
font-family: system-ui, -apple-system, sans-serif;
|
|
717
|
-
border-radius: 4px;
|
|
718
|
-
white-space: nowrap;
|
|
719
|
-
box-shadow: 0 2px 8px rgba(0,0,0,0.3);
|
|
720
|
-
display: none;
|
|
721
|
-
}
|
|
722
|
-
</style>
|
|
723
|
-
<div class="overlay"></div>
|
|
724
|
-
<div class="tag"></div>
|
|
725
|
-
\`;
|
|
726
|
-
document.body.appendChild(host);
|
|
727
|
-
overlay = shadow.querySelector('.overlay');
|
|
728
|
-
tag = shadow.querySelector('.tag');
|
|
729
|
-
setupRemovalObserver();
|
|
730
|
-
}
|
|
731
|
-
|
|
732
|
-
// watch for React hydration removing our element and re-create it
|
|
733
|
-
function setupRemovalObserver() {
|
|
734
|
-
if (removalObserver) return;
|
|
735
|
-
removalObserver = new MutationObserver(function(mutations) {
|
|
736
|
-
for (var i = 0; i < mutations.length; i++) {
|
|
737
|
-
var mutation = mutations[i];
|
|
738
|
-
if (mutation.type === 'childList') {
|
|
739
|
-
for (var j = 0; j < mutation.removedNodes.length; j++) {
|
|
740
|
-
var node = mutation.removedNodes[j];
|
|
741
|
-
if (node === host) {
|
|
742
|
-
host = null;
|
|
743
|
-
shadow = null;
|
|
744
|
-
overlay = null;
|
|
745
|
-
tag = null;
|
|
746
|
-
// don't auto-recreate - will be created on next hover
|
|
747
|
-
return;
|
|
748
|
-
}
|
|
749
|
-
}
|
|
750
|
-
}
|
|
751
|
-
}
|
|
752
|
-
});
|
|
753
|
-
removalObserver.observe(document.body, { childList: true });
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
function hideOverlay() {
|
|
757
|
-
if (overlay) overlay.style.display = 'none';
|
|
758
|
-
if (tag) tag.style.display = 'none';
|
|
759
|
-
}
|
|
760
|
-
|
|
761
|
-
function showOverlay(el, source) {
|
|
762
|
-
if (!host) createHost();
|
|
763
|
-
var rect = el.getBoundingClientRect();
|
|
764
|
-
overlay.style.display = 'block';
|
|
765
|
-
overlay.style.top = rect.top + 'px';
|
|
766
|
-
overlay.style.left = rect.left + 'px';
|
|
767
|
-
overlay.style.width = rect.width + 'px';
|
|
768
|
-
overlay.style.height = rect.height + 'px';
|
|
769
|
-
tag.style.display = 'block';
|
|
770
|
-
tag.textContent = source;
|
|
771
|
-
var top = rect.top - 28;
|
|
772
|
-
if (top < 0) top = rect.bottom + 4;
|
|
773
|
-
tag.style.top = top + 'px';
|
|
774
|
-
tag.style.left = Math.max(4, Math.min(rect.left, window.innerWidth - 200)) + 'px';
|
|
775
|
-
}
|
|
776
|
-
|
|
777
|
-
function cancelHold() {
|
|
778
|
-
clearTimeout(holdTimer);
|
|
779
|
-
holdTimer = null;
|
|
780
|
-
}
|
|
781
|
-
|
|
782
|
-
function updateOverlayAtPosition(x, y) {
|
|
783
|
-
// Use elementsFromPoint to get all elements at position, ordered from topmost/innermost to bottom
|
|
784
|
-
var allElements = document.elementsFromPoint(x, y);
|
|
785
|
-
// Find the first (innermost) element with data-one-source
|
|
786
|
-
var el = null;
|
|
787
|
-
for (var i = 0; i < allElements.length; i++) {
|
|
788
|
-
if (allElements[i].hasAttribute('data-one-source')) {
|
|
789
|
-
el = allElements[i];
|
|
790
|
-
break;
|
|
791
|
-
}
|
|
792
|
-
}
|
|
793
|
-
if (el) {
|
|
794
|
-
var source = el.getAttribute('data-one-source');
|
|
795
|
-
var lastColon = source.lastIndexOf(':');
|
|
796
|
-
var filePath = source.slice(0, lastColon);
|
|
797
|
-
var idx = source.slice(lastColon + 1);
|
|
798
|
-
var info = window.__oneSourceInfo && window.__oneSourceInfo[filePath];
|
|
799
|
-
var lineCol = info && info[idx];
|
|
800
|
-
var displaySource = lineCol ? filePath + ':' + lineCol[0] + ':' + lineCol[1] : source;
|
|
801
|
-
showOverlay(el, displaySource);
|
|
802
|
-
} else {
|
|
803
|
-
hideOverlay();
|
|
804
|
-
}
|
|
805
|
-
}
|
|
806
|
-
|
|
807
|
-
function activate() {
|
|
808
|
-
active = true;
|
|
809
|
-
// Immediately show overlay at current mouse position
|
|
810
|
-
updateOverlayAtPosition(mousePos.x, mousePos.y);
|
|
811
|
-
}
|
|
812
|
-
|
|
813
|
-
function deactivate() {
|
|
814
|
-
cancelHold();
|
|
815
|
-
active = false;
|
|
816
|
-
hideOverlay();
|
|
817
|
-
}
|
|
818
|
-
|
|
819
|
-
window.addEventListener('keydown', function(e) {
|
|
820
|
-
// Only trigger on Alt/Option key held alone
|
|
821
|
-
if (e.key !== 'Alt') {
|
|
822
|
-
cancelHold();
|
|
823
|
-
return;
|
|
824
|
-
}
|
|
825
|
-
// Ignore if other modifier keys are pressed
|
|
826
|
-
if (e.metaKey || e.ctrlKey || e.shiftKey) {
|
|
827
|
-
cancelHold();
|
|
828
|
-
return;
|
|
829
|
-
}
|
|
830
|
-
if (e.defaultPrevented) return;
|
|
831
|
-
if (holdTimer) return; // already waiting
|
|
832
|
-
holdTimer = setTimeout(activate, holdDelay);
|
|
833
|
-
});
|
|
834
|
-
|
|
835
|
-
window.addEventListener('keyup', function(e) {
|
|
836
|
-
if (e.defaultPrevented) return;
|
|
837
|
-
deactivate();
|
|
838
|
-
});
|
|
839
|
-
|
|
840
|
-
window.addEventListener('blur', deactivate);
|
|
841
|
-
|
|
842
|
-
document.addEventListener('mousemove', function(e) {
|
|
843
|
-
// Always track mouse position
|
|
844
|
-
mousePos.x = e.clientX;
|
|
845
|
-
mousePos.y = e.clientY;
|
|
846
|
-
if (!active) return;
|
|
847
|
-
updateOverlayAtPosition(e.clientX, e.clientY);
|
|
848
|
-
});
|
|
849
|
-
|
|
850
|
-
document.addEventListener('click', function(e) {
|
|
851
|
-
if (!active) return;
|
|
852
|
-
// Use elementsFromPoint to find innermost sourced element
|
|
853
|
-
var allElements = document.elementsFromPoint(e.clientX, e.clientY);
|
|
854
|
-
var el = null;
|
|
855
|
-
for (var i = 0; i < allElements.length; i++) {
|
|
856
|
-
if (allElements[i].hasAttribute('data-one-source')) {
|
|
857
|
-
el = allElements[i];
|
|
858
|
-
break;
|
|
859
|
-
}
|
|
860
|
-
}
|
|
861
|
-
if (el) {
|
|
862
|
-
e.preventDefault();
|
|
863
|
-
e.stopPropagation();
|
|
864
|
-
var source = el.getAttribute('data-one-source');
|
|
865
|
-
// Parse source: "/path/to/file.tsx:index"
|
|
866
|
-
var lastColon = source.lastIndexOf(':');
|
|
867
|
-
var filePath = source.slice(0, lastColon);
|
|
868
|
-
var idx = source.slice(lastColon + 1);
|
|
869
|
-
// Look up actual line/column from source info
|
|
870
|
-
var info = window.__oneSourceInfo && window.__oneSourceInfo[filePath];
|
|
871
|
-
var lineCol = info && info[idx];
|
|
872
|
-
var url = '/__one/open-source?source=' + encodeURIComponent(source);
|
|
873
|
-
if (lineCol) {
|
|
874
|
-
url += '&line=' + lineCol[0] + '&column=' + lineCol[1];
|
|
875
|
-
}
|
|
876
|
-
fetch(url);
|
|
877
|
-
}
|
|
878
|
-
}, true);
|
|
879
|
-
} catch (e) {
|
|
880
|
-
console.error('[Source Inspector] Failed to initialize:', e);
|
|
881
|
-
}
|
|
882
|
-
})();
|
|
883
|
-
`;
|
|
884
3
|
function DevHead() {
|
|
885
4
|
return null;
|
|
886
5
|
}
|