@sightmap/react 0.6.0 → 0.8.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/dist/index.d.ts +13 -2
- package/dist/index.js +349 -5
- package/dist/index.js.map +1 -1
- package/dist/runtime-types-Cvx7dsB4.d.ts +91 -0
- package/dist/runtime-types.d.ts +2 -51
- package/dist/vite.d.ts +21 -8
- package/dist/vite.js +54 -29
- package/dist/vite.js.map +1 -1
- package/package.json +7 -28
- package/dist/cli/index.d.ts +0 -1
- package/dist/cli/index.js +0 -1149
- package/dist/cli/index.js.map +0 -1
- package/dist/plugin/adapters/rr7-declarative.d.ts +0 -6
- package/dist/plugin/adapters/rr7-declarative.js +0 -315
- package/dist/plugin/adapters/rr7-declarative.js.map +0 -1
- package/dist/plugin/adapters/rr7-framework.d.ts +0 -7
- package/dist/plugin/adapters/rr7-framework.js +0 -235
- package/dist/plugin/adapters/rr7-framework.js.map +0 -1
- package/dist/router-adapter-CsmLmHVQ.d.ts +0 -29
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { S as SightmapSnapshot } from './runtime-types-Cvx7dsB4.js';
|
|
3
|
+
export { C as CandidateSelector, a as ComponentNode, b as SelectorSource, c as SelectorStability, d as SightmapMarker, U as UnmarkedCandidate } from './runtime-types-Cvx7dsB4.js';
|
|
2
4
|
import { ReactNode } from 'react';
|
|
3
5
|
import { Sightmap, Diagnostic } from '@sightmap/sightmap';
|
|
4
|
-
export {
|
|
6
|
+
export { sightmap } from './vite.js';
|
|
7
|
+
import 'vite';
|
|
8
|
+
|
|
9
|
+
declare global {
|
|
10
|
+
interface Window {
|
|
11
|
+
__sightmap__?: {
|
|
12
|
+
snapshot: () => SightmapSnapshot;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
}
|
|
5
16
|
|
|
6
17
|
type RuntimeMode = "dev" | "enabled" | "off";
|
|
7
18
|
type SightmapProviderProps = {
|
|
@@ -14,4 +25,4 @@ type SightmapProviderProps = {
|
|
|
14
25
|
declare function useSightmap(): Sightmap | null;
|
|
15
26
|
declare function SightmapProvider(props: SightmapProviderProps): react_jsx_runtime.JSX.Element;
|
|
16
27
|
|
|
17
|
-
export { SightmapProvider, type SightmapProviderProps, useSightmap };
|
|
28
|
+
export { SightmapProvider, type SightmapProviderProps, SightmapSnapshot, useSightmap };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,286 @@
|
|
|
1
|
+
// src/runtime/bippy-install.ts
|
|
2
|
+
import { instrument } from "bippy";
|
|
3
|
+
|
|
4
|
+
// src/runtime/serialize.ts
|
|
5
|
+
import {
|
|
6
|
+
traverseFiber,
|
|
7
|
+
getDisplayName,
|
|
8
|
+
isCompositeFiber
|
|
9
|
+
} from "bippy";
|
|
10
|
+
|
|
11
|
+
// src/runtime/rank-selectors.ts
|
|
12
|
+
function rankSelectors(el) {
|
|
13
|
+
const out = [];
|
|
14
|
+
const dsm = el.getAttribute("data-sightmap");
|
|
15
|
+
if (dsm !== null) {
|
|
16
|
+
out.push({
|
|
17
|
+
selector: `[data-sightmap="${cssEsc(dsm)}"]`,
|
|
18
|
+
stability: "high",
|
|
19
|
+
source: "data-sightmap"
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
for (const attr of ["data-testid", "data-cy", "data-test"]) {
|
|
23
|
+
const v = el.getAttribute(attr);
|
|
24
|
+
if (v !== null) {
|
|
25
|
+
out.push({
|
|
26
|
+
selector: `[${attr}="${cssEsc(v)}"]`,
|
|
27
|
+
stability: "high",
|
|
28
|
+
source: attr
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const role = el.getAttribute("role");
|
|
33
|
+
const aria = el.getAttribute("aria-label");
|
|
34
|
+
if (role && aria) {
|
|
35
|
+
out.push({
|
|
36
|
+
selector: `[role="${cssEsc(role)}"][aria-label="${cssEsc(aria)}"]`,
|
|
37
|
+
stability: "medium",
|
|
38
|
+
source: "aria"
|
|
39
|
+
});
|
|
40
|
+
} else if (aria) {
|
|
41
|
+
out.push({
|
|
42
|
+
selector: `[aria-label="${cssEsc(aria)}"]`,
|
|
43
|
+
stability: "medium",
|
|
44
|
+
source: "aria-label"
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
const name = el.getAttribute("name");
|
|
48
|
+
if (name !== null && /^(form|input|button|select|textarea|nav)$/i.test(el.tagName)) {
|
|
49
|
+
out.push({
|
|
50
|
+
selector: `${el.tagName.toLowerCase()}[name="${cssEsc(name)}"]`,
|
|
51
|
+
stability: "medium",
|
|
52
|
+
source: "semantic-name"
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
const id = el.id;
|
|
56
|
+
if (id && isHumanShapedId(id)) {
|
|
57
|
+
out.push({
|
|
58
|
+
selector: `#${cssEsc(id)}`,
|
|
59
|
+
stability: "high",
|
|
60
|
+
source: "id"
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
return out;
|
|
64
|
+
}
|
|
65
|
+
function cssEsc(v) {
|
|
66
|
+
return v.replace(/"/g, '\\"');
|
|
67
|
+
}
|
|
68
|
+
function isHumanShapedId(id) {
|
|
69
|
+
if (/[0-9]{6,}/.test(id)) return false;
|
|
70
|
+
if (/^[a-z]+-[a-f0-9]{8,}/i.test(id)) return false;
|
|
71
|
+
if (/:r[0-9a-z]+:/i.test(id)) return false;
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// src/runtime/portal-aware-walker.ts
|
|
76
|
+
var HOST_PORTAL_TAG = 4;
|
|
77
|
+
var MAX_NODES_DEFAULT = 5e3;
|
|
78
|
+
function findHostElementForFiber(fiber, inDocument, maxNodes = MAX_NODES_DEFAULT) {
|
|
79
|
+
if (!fiber.child) return null;
|
|
80
|
+
const stack = [fiber.child];
|
|
81
|
+
let walks = 0;
|
|
82
|
+
while (stack.length > 0 && walks < maxNodes) {
|
|
83
|
+
walks++;
|
|
84
|
+
const f = stack.pop();
|
|
85
|
+
if (!f) continue;
|
|
86
|
+
if (f.sibling) stack.push(f.sibling);
|
|
87
|
+
if (f.tag === HOST_PORTAL_TAG) continue;
|
|
88
|
+
const stateNode = f.stateNode;
|
|
89
|
+
if (stateNode && typeof stateNode === "object" && "tagName" in stateNode) {
|
|
90
|
+
if (inDocument(stateNode)) return stateNode;
|
|
91
|
+
}
|
|
92
|
+
if (f.child) stack.push(f.child);
|
|
93
|
+
}
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// src/runtime/serialize.ts
|
|
98
|
+
var FRAMEWORK_NOISE = /* @__PURE__ */ new Set([
|
|
99
|
+
"Routes",
|
|
100
|
+
"Route",
|
|
101
|
+
"RenderedRoute",
|
|
102
|
+
"Outlet",
|
|
103
|
+
"BrowserRouter",
|
|
104
|
+
"Router",
|
|
105
|
+
"RouterProvider",
|
|
106
|
+
"DataRouterProvider",
|
|
107
|
+
"RouterProviderImpl",
|
|
108
|
+
"LinkWithRef",
|
|
109
|
+
"StrictMode",
|
|
110
|
+
"SightmapProvider",
|
|
111
|
+
"Fragment",
|
|
112
|
+
"Anonymous",
|
|
113
|
+
"Suspense",
|
|
114
|
+
"ErrorBoundary",
|
|
115
|
+
"Provider",
|
|
116
|
+
"Consumer",
|
|
117
|
+
"ThemeProvider",
|
|
118
|
+
"Hydration",
|
|
119
|
+
"HydrateFallback",
|
|
120
|
+
"RemixErrorBoundary",
|
|
121
|
+
"HydratedRouter",
|
|
122
|
+
"DataRoutes",
|
|
123
|
+
"WithHydrateFallbackProps2",
|
|
124
|
+
"RenderErrorBoundary",
|
|
125
|
+
"Layout"
|
|
126
|
+
]);
|
|
127
|
+
function serializeSnapshot(opts) {
|
|
128
|
+
const roots = Array.from(opts.trackedRoots);
|
|
129
|
+
if (roots.length === 0) {
|
|
130
|
+
return {
|
|
131
|
+
capturedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
132
|
+
route: "?",
|
|
133
|
+
commits: 0,
|
|
134
|
+
components: [],
|
|
135
|
+
markers: [],
|
|
136
|
+
unmarkedCandidates: []
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
const root = roots.find((r) => r.current?.child !== null) ?? roots[0];
|
|
140
|
+
if (!root) {
|
|
141
|
+
return {
|
|
142
|
+
capturedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
143
|
+
route: "?",
|
|
144
|
+
commits: 0,
|
|
145
|
+
components: [],
|
|
146
|
+
markers: [],
|
|
147
|
+
unmarkedCandidates: []
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
const rootFiber = root.current;
|
|
151
|
+
const components = collectComponents(rootFiber);
|
|
152
|
+
const markers = collectMarkers();
|
|
153
|
+
const unmarkedCandidates = collectUnmarkedCandidates(rootFiber);
|
|
154
|
+
return {
|
|
155
|
+
capturedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
156
|
+
route: typeof window !== "undefined" && window.location ? window.location.pathname + (window.location.search ?? "") : "?",
|
|
157
|
+
commits: roots.length,
|
|
158
|
+
components,
|
|
159
|
+
markers,
|
|
160
|
+
unmarkedCandidates
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
function collectComponents(rootFiber) {
|
|
164
|
+
const out = [];
|
|
165
|
+
const depthByFiber = /* @__PURE__ */ new Map();
|
|
166
|
+
depthByFiber.set(rootFiber, 0);
|
|
167
|
+
traverseFiber(rootFiber, (f) => {
|
|
168
|
+
const depth = depthByFiber.get(f) ?? 0;
|
|
169
|
+
let c = f.child;
|
|
170
|
+
while (c) {
|
|
171
|
+
depthByFiber.set(c, depth + 1);
|
|
172
|
+
c = c.sibling;
|
|
173
|
+
}
|
|
174
|
+
if (!isCompositeFiber(f)) return false;
|
|
175
|
+
const name = getDisplayName(f);
|
|
176
|
+
if (!name) return false;
|
|
177
|
+
const childNames = [];
|
|
178
|
+
let cc = f.child;
|
|
179
|
+
while (cc) {
|
|
180
|
+
if (isCompositeFiber(cc)) {
|
|
181
|
+
const n = getDisplayName(cc);
|
|
182
|
+
if (n) childNames.push(n);
|
|
183
|
+
}
|
|
184
|
+
cc = cc.sibling;
|
|
185
|
+
}
|
|
186
|
+
out.push({ displayName: name, depth, children: childNames });
|
|
187
|
+
return false;
|
|
188
|
+
});
|
|
189
|
+
return out;
|
|
190
|
+
}
|
|
191
|
+
function collectMarkers() {
|
|
192
|
+
const out = [];
|
|
193
|
+
if (typeof document === "undefined") return out;
|
|
194
|
+
const els = document.querySelectorAll("[data-sightmap]");
|
|
195
|
+
for (let i = 0; i < els.length; i++) {
|
|
196
|
+
const el = els[i];
|
|
197
|
+
const name = el.getAttribute("data-sightmap") ?? "";
|
|
198
|
+
const fiber = bridgeDomToFiber(el);
|
|
199
|
+
const nearestComponent = nearestCompositeName(fiber);
|
|
200
|
+
out.push({
|
|
201
|
+
name,
|
|
202
|
+
hostTag: el.tagName.toLowerCase(),
|
|
203
|
+
...nearestComponent !== void 0 ? { nearestComponent } : {},
|
|
204
|
+
domDepth: domDepth(el),
|
|
205
|
+
candidateSelectors: rankSelectors(el)
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
return out;
|
|
209
|
+
}
|
|
210
|
+
function collectUnmarkedCandidates(rootFiber) {
|
|
211
|
+
const out = [];
|
|
212
|
+
const seen = /* @__PURE__ */ new Set();
|
|
213
|
+
traverseFiber(rootFiber, (f) => {
|
|
214
|
+
if (!isCompositeFiber(f)) return false;
|
|
215
|
+
const name = getDisplayName(f);
|
|
216
|
+
if (!name || seen.has(name) || FRAMEWORK_NOISE.has(name)) return false;
|
|
217
|
+
seen.add(name);
|
|
218
|
+
const hostEl = findHostElementForFiber(f, (el) => document.contains(el));
|
|
219
|
+
if (!hostEl) return false;
|
|
220
|
+
const selectors = rankSelectors(hostEl);
|
|
221
|
+
if (selectors.length === 0) return false;
|
|
222
|
+
out.push({
|
|
223
|
+
displayName: name,
|
|
224
|
+
hostTag: hostEl.tagName.toLowerCase(),
|
|
225
|
+
selectors,
|
|
226
|
+
domDepth: domDepth(hostEl)
|
|
227
|
+
});
|
|
228
|
+
return false;
|
|
229
|
+
});
|
|
230
|
+
return out;
|
|
231
|
+
}
|
|
232
|
+
function bridgeDomToFiber(el) {
|
|
233
|
+
for (const key of Object.keys(el)) {
|
|
234
|
+
if (key.startsWith("__reactFiber$")) {
|
|
235
|
+
return el[key] ?? null;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return null;
|
|
239
|
+
}
|
|
240
|
+
function nearestCompositeName(fiber) {
|
|
241
|
+
let f = fiber;
|
|
242
|
+
let walks = 0;
|
|
243
|
+
while (f && walks < 50) {
|
|
244
|
+
if (isCompositeFiber(f)) {
|
|
245
|
+
const n = getDisplayName(f);
|
|
246
|
+
if (n) return n;
|
|
247
|
+
}
|
|
248
|
+
f = f.return;
|
|
249
|
+
walks++;
|
|
250
|
+
}
|
|
251
|
+
return void 0;
|
|
252
|
+
}
|
|
253
|
+
function domDepth(el) {
|
|
254
|
+
let d = 0;
|
|
255
|
+
let cur = el.parentElement;
|
|
256
|
+
while (cur && cur !== document.body) {
|
|
257
|
+
d++;
|
|
258
|
+
cur = cur.parentElement;
|
|
259
|
+
}
|
|
260
|
+
return d;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// src/runtime/bippy-install.ts
|
|
264
|
+
var trackedRoots = /* @__PURE__ */ new Set();
|
|
265
|
+
instrument({
|
|
266
|
+
onCommitFiberRoot: (_id, root) => {
|
|
267
|
+
trackedRoots.add(root);
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
if (typeof window !== "undefined") {
|
|
271
|
+
window.__sightmap__ = { snapshot: () => serializeSnapshot({ trackedRoots }) };
|
|
272
|
+
setTimeout(() => {
|
|
273
|
+
if (trackedRoots.size > 0) return;
|
|
274
|
+
if (typeof document === "undefined") return;
|
|
275
|
+
const rootEl = document.querySelector("#root, [data-reactroot], body > div");
|
|
276
|
+
const domHasContent = (rootEl?.children.length ?? 0) > 0;
|
|
277
|
+
if (!domHasContent) return;
|
|
278
|
+
console.error(
|
|
279
|
+
"[sightmap] Late registration: SightmapProvider's runtime hook missed React-DOM's renderer registration. Snapshots will be empty even though the DOM rendered.\n\nFix one of:\n 1. Import the @sightmap/react entry FIRST in your app entry file (before react-dom and your app code).\n 2. Use the auto-inject Vite plugin option (sightmap({ autoInject: true })).\n 3. If you must lazy-load the provider, force a no-op state update after install to flush a commit."
|
|
280
|
+
);
|
|
281
|
+
}, 1e3);
|
|
282
|
+
}
|
|
283
|
+
|
|
1
284
|
// src/provider.tsx
|
|
2
285
|
import { createContext, useContext, useEffect, useRef, useState } from "react";
|
|
3
286
|
import { parse, merge } from "@sightmap/sightmap";
|
|
@@ -154,7 +437,7 @@ var SDK_VERSION = "0.1.0";
|
|
|
154
437
|
var SPEC_VERSION = "1";
|
|
155
438
|
function SightmapProvider(props) {
|
|
156
439
|
const { sightmap: initial, source = "/__sightmap__/sightmap.json", runtimeIntrospection = "dev", onError, children } = props;
|
|
157
|
-
const [
|
|
440
|
+
const [sightmap2, setSightmap] = useState(initial ?? null);
|
|
158
441
|
const containerRef = useRef(null);
|
|
159
442
|
useEffect(() => {
|
|
160
443
|
if (initial) return;
|
|
@@ -179,10 +462,10 @@ function SightmapProvider(props) {
|
|
|
179
462
|
}, [initial, source, onError]);
|
|
180
463
|
useEffect(() => {
|
|
181
464
|
const enabled = runtimeIntrospection === "enabled" || runtimeIntrospection === "dev" && process.env.NODE_ENV !== "production";
|
|
182
|
-
if (!enabled || !
|
|
465
|
+
if (!enabled || !sightmap2) return;
|
|
183
466
|
const hook = createHook({
|
|
184
467
|
getContainer: () => containerRef.current,
|
|
185
|
-
getSightmap: () =>
|
|
468
|
+
getSightmap: () => sightmap2,
|
|
186
469
|
// Read fresh on every call. Both popstate and pushState/replaceState (via react-router)
|
|
187
470
|
// mutate window.location.pathname synchronously; reading on demand always sees the
|
|
188
471
|
// current value without needing a listener.
|
|
@@ -191,11 +474,72 @@ function SightmapProvider(props) {
|
|
|
191
474
|
specVersion: SPEC_VERSION
|
|
192
475
|
});
|
|
193
476
|
return installHook(hook);
|
|
194
|
-
}, [runtimeIntrospection,
|
|
195
|
-
return /* @__PURE__ */ jsx(SightmapContext.Provider, { value:
|
|
477
|
+
}, [runtimeIntrospection, sightmap2]);
|
|
478
|
+
return /* @__PURE__ */ jsx(SightmapContext.Provider, { value: sightmap2, children: /* @__PURE__ */ jsx("div", { ref: containerRef, "data-sightmap-root": "", children }) });
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
// src/vite.ts
|
|
482
|
+
function sightmap(options = {}) {
|
|
483
|
+
let cached = null;
|
|
484
|
+
const cache = {
|
|
485
|
+
set(s) {
|
|
486
|
+
cached = s;
|
|
487
|
+
},
|
|
488
|
+
get() {
|
|
489
|
+
return cached;
|
|
490
|
+
}
|
|
491
|
+
};
|
|
492
|
+
const ENTRY_PATTERN = /(src|app)\/(main|index|entry\.client)\.(t|j)sx?$/;
|
|
493
|
+
const INJECT_LINE = `import "@sightmap/react";
|
|
494
|
+
`;
|
|
495
|
+
return {
|
|
496
|
+
name: "sightmap-react",
|
|
497
|
+
configureServer(server) {
|
|
498
|
+
server.middlewares.use("/__sightmap__/snapshot.json", (req, res) => {
|
|
499
|
+
if (req.method === "POST") {
|
|
500
|
+
const chunks = [];
|
|
501
|
+
req.on("data", (c) => chunks.push(c));
|
|
502
|
+
req.on("end", () => {
|
|
503
|
+
try {
|
|
504
|
+
const body = JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
505
|
+
cache.set(body);
|
|
506
|
+
res.statusCode = 204;
|
|
507
|
+
res.end();
|
|
508
|
+
} catch (e) {
|
|
509
|
+
res.statusCode = 400;
|
|
510
|
+
res.end(`bad json: ${e.message}`);
|
|
511
|
+
}
|
|
512
|
+
});
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
if (req.method === "GET") {
|
|
516
|
+
const snap = cache.get();
|
|
517
|
+
if (!snap) {
|
|
518
|
+
res.statusCode = 404;
|
|
519
|
+
res.end(`{"error":"no snapshot cached yet \u2014 visit a page first"}`);
|
|
520
|
+
return;
|
|
521
|
+
}
|
|
522
|
+
res.statusCode = 200;
|
|
523
|
+
res.setHeader("content-type", "application/json");
|
|
524
|
+
res.end(JSON.stringify(snap));
|
|
525
|
+
return;
|
|
526
|
+
}
|
|
527
|
+
res.statusCode = 405;
|
|
528
|
+
res.end();
|
|
529
|
+
});
|
|
530
|
+
},
|
|
531
|
+
transform(code, id) {
|
|
532
|
+
if (!options.autoInject) return null;
|
|
533
|
+
if (!ENTRY_PATTERN.test(id)) return null;
|
|
534
|
+
if (code.includes("@sightmap/react")) return null;
|
|
535
|
+
return { code: INJECT_LINE + code, map: null };
|
|
536
|
+
},
|
|
537
|
+
__test_cache: cache
|
|
538
|
+
};
|
|
196
539
|
}
|
|
197
540
|
export {
|
|
198
541
|
SightmapProvider,
|
|
542
|
+
sightmap,
|
|
199
543
|
useSightmap
|
|
200
544
|
};
|
|
201
545
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/provider.tsx","../src/runtime/hook.ts","../src/runtime/surface.ts","../src/runtime/walker.ts"],"sourcesContent":["// src/provider.tsx\nimport { createContext, useContext, useEffect, useRef, useState, type ReactNode } from \"react\";\nimport type { Sightmap } from \"@sightmap/sightmap\";\nimport { parse, merge } from \"@sightmap/sightmap\";\nimport type { Diagnostic } from \"@sightmap/sightmap\";\nimport { installHook } from \"./runtime/hook.js\";\nimport { createHook } from \"./runtime/surface.js\";\n\ntype RuntimeMode = \"dev\" | \"enabled\" | \"off\";\n\nexport type SightmapProviderProps = {\n sightmap?: Sightmap;\n source?: string;\n runtimeIntrospection?: RuntimeMode;\n onError?: (diagnostic: Diagnostic) => void;\n children: ReactNode;\n};\n\nconst SightmapContext = createContext<Sightmap | null>(null);\n\nexport function useSightmap(): Sightmap | null {\n return useContext(SightmapContext);\n}\n\nconst SDK_VERSION = \"0.1.0\";\nconst SPEC_VERSION = \"1\";\n\nexport function SightmapProvider(props: SightmapProviderProps) {\n const { sightmap: initial, source = \"/__sightmap__/sightmap.json\", runtimeIntrospection = \"dev\", onError, children } = props;\n const [sightmap, setSightmap] = useState<Sightmap | null>(initial ?? null);\n const containerRef = useRef<HTMLDivElement>(null);\n\n // Load from `source` if no initial sightmap was provided.\n useEffect(() => {\n if (initial) return;\n let cancelled = false;\n fetch(source, { credentials: \"same-origin\" })\n .then((r) => r.json())\n .then((json: unknown) => {\n if (cancelled) return;\n // The dev middleware returns a parsed Sightmap object; in the future, source could be a YAML string.\n if (typeof json === \"string\") {\n setSightmap(merge([parse(json)]));\n } else {\n setSightmap(json as Sightmap);\n }\n })\n .catch((err) => {\n onError?.({\n severity: \"error\",\n code: \"react.sightmap-fetch-failed\",\n message: `Failed to load sightmap from ${source}: ${(err as Error).message}`,\n });\n });\n return () => { cancelled = true; };\n }, [initial, source, onError]);\n\n // Install/teardown the hook based on lifetime mode.\n useEffect(() => {\n const enabled = runtimeIntrospection === \"enabled\"\n || (runtimeIntrospection === \"dev\" && process.env.NODE_ENV !== \"production\");\n if (!enabled || !sightmap) return;\n\n const hook = createHook({\n getContainer: () => containerRef.current,\n getSightmap: () => sightmap,\n // Read fresh on every call. Both popstate and pushState/replaceState (via react-router)\n // mutate window.location.pathname synchronously; reading on demand always sees the\n // current value without needing a listener.\n getCurrentRoute: () => window.location.pathname,\n sdkVersion: SDK_VERSION,\n specVersion: SPEC_VERSION,\n });\n return installHook(hook);\n }, [runtimeIntrospection, sightmap]);\n\n return (\n <SightmapContext.Provider value={sightmap}>\n <div ref={containerRef} data-sightmap-root=\"\">{children}</div>\n </SightmapContext.Provider>\n );\n}\n","// src/runtime/hook.ts\nimport type { SightmapHook } from \"./types.js\";\n\nexport function installHook(hook: SightmapHook): () => void {\n if (typeof window === \"undefined\") return () => {};\n if (window.__SIGHTMAP__) return () => {}; // already installed (StrictMode double-mount)\n window.__SIGHTMAP__ = hook;\n return () => {\n if (window.__SIGHTMAP__ === hook) delete window.__SIGHTMAP__;\n };\n}\n","// src/runtime/surface.ts\nimport type { Sightmap, ResolvedView, MatchResult } from \"@sightmap/sightmap\";\nimport { match as coreMatch } from \"@sightmap/sightmap\";\nimport type { SightmapHook, ComponentNode } from \"./types.js\";\nimport { walkFromRoot } from \"./walker.js\";\n\nexport type SurfaceContext = {\n getContainer: () => Element | null;\n getSightmap: () => Sightmap;\n getCurrentRoute: () => string;\n sdkVersion: string;\n specVersion: string;\n};\n\nexport function createHook(ctx: SurfaceContext): SightmapHook {\n return {\n version: () => ({ sdk: ctx.sdkVersion, spec: ctx.specVersion }),\n getSightmap: ctx.getSightmap,\n getCurrentView: () => {\n const result = coreMatch(ctx.getSightmap(), { url: ctx.getCurrentRoute() });\n return result.view;\n },\n match: (req) => coreMatch(ctx.getSightmap(), req),\n walkTree: (opts) => {\n const container = ctx.getContainer();\n if (!container) return [];\n const all = walkFromRoot(container);\n if (!opts) return all;\n let scoped = all;\n if (opts.rootId !== undefined) {\n scoped = all.filter((n) => isDescendant(all, n.id, opts.rootId!));\n }\n if (opts.maxDepth !== undefined) {\n const baseDepth = opts.rootId\n ? (scoped.find((n) => n.id === opts.rootId)?.depth ?? 0)\n : 0;\n scoped = scoped.filter((n) => n.depth - baseDepth <= opts.maxDepth!);\n }\n return scoped;\n },\n inspectAt: (x, y) => {\n const container = ctx.getContainer();\n if (!container) return null;\n const target = document.elementFromPoint(x, y);\n if (!target) return null;\n const all = walkFromRoot(container);\n return all.find((n) => n.dom !== null && nodeMatchesEl(n, target as Element)) ?? null;\n },\n findByDataSightmap: (name) => {\n const container = ctx.getContainer();\n if (!container) return [];\n return walkFromRoot(container).filter((n) => n.dom?.dataSightmap === name);\n },\n };\n}\n\nfunction isDescendant(all: ComponentNode[], id: string, rootId: string): boolean {\n let cursor: ComponentNode | undefined = all.find((n) => n.id === id);\n while (cursor) {\n if (cursor.id === rootId) return true;\n if (cursor.parentId === null) return false;\n cursor = all.find((n) => n.id === cursor!.parentId);\n }\n return false;\n}\n\nfunction nodeMatchesEl(node: ComponentNode, el: Element): boolean {\n return node.dom?.tagName === el.tagName.toLowerCase()\n && node.dom?.dataSightmap === el.getAttribute(\"data-sightmap\");\n}\n","// src/runtime/walker.ts\nimport type { ComponentNode } from \"./types.js\";\n\n/**\n * Walk the React fiber tree starting from a DOM container.\n *\n * Implementation note: React 19 stores the fiber root on the container via an\n * internal property. We probe a few known shapes (the format has changed across\n * minor versions). If fiber access becomes load-bearing, replace this with a\n * subscription via the global DevTools-style hook (see Task 20) which calls us\n * with the FiberRoot directly.\n */\nexport function walkFromRoot(container: Element): ComponentNode[] {\n const fiberRoot = findFiberRoot(container);\n if (!fiberRoot) return [];\n const nodes: ComponentNode[] = [];\n let nextId = 0;\n const stack: Array<{ fiber: any; parentId: string | null; depth: number }> = [\n { fiber: fiberRoot.current, parentId: null, depth: 0 },\n ];\n while (stack.length > 0) {\n const { fiber, parentId, depth } = stack.pop()!;\n if (!fiber) continue;\n const id = String(nextId++);\n const node: ComponentNode = {\n id,\n parentId,\n depth,\n type: typeName(fiber),\n key: fiber.key ?? null,\n dom: fiber.stateNode instanceof Element ? domDescriptor(fiber.stateNode) : null,\n source: sourceFromFiber(fiber),\n childIds: [],\n };\n nodes.push(node);\n if (parentId !== null) {\n const parent = nodes.find((n) => n.id === parentId);\n if (parent) parent.childIds.push(id);\n }\n // Push children in reverse so the natural traversal is depth-first left→right.\n const children: any[] = [];\n let child = fiber.child;\n while (child) {\n children.push(child);\n child = child.sibling;\n }\n for (let i = children.length - 1; i >= 0; i--) {\n stack.push({ fiber: children[i], parentId: id, depth: depth + 1 });\n }\n }\n return nodes;\n}\n\nfunction findFiberRoot(container: Element): { current: any } | null {\n for (const key of Object.keys(container)) {\n if (key.startsWith(\"__reactContainer$\") || key.startsWith(\"__reactFiber$\")) {\n const fiber = (container as any)[key];\n let root = fiber;\n while (root?.return) root = root.return;\n if (root?.stateNode?.current) return root.stateNode;\n }\n }\n return null;\n}\n\nfunction typeName(fiber: any): string {\n const t = fiber.type;\n if (typeof t === \"string\") return t;\n if (t?.displayName) return t.displayName;\n if (t?.name) return t.name;\n return \"Unknown\";\n}\n\nfunction domDescriptor(el: Element): NonNullable<ComponentNode[\"dom\"]> {\n return {\n tagName: el.tagName.toLowerCase(),\n dataSightmap: el.getAttribute(\"data-sightmap\"),\n testId: el.getAttribute(\"data-testid\"),\n classes: Array.from(el.classList),\n };\n}\n\nfunction sourceFromFiber(fiber: any): ComponentNode[\"source\"] {\n const src = fiber._debugSource ?? fiber.elementType?.__source ?? null;\n if (src && typeof src.fileName === \"string\") {\n return { file: src.fileName, line: src.lineNumber ?? 0, col: src.columnNumber ?? 0 };\n }\n return null;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/runtime/bippy-install.ts","../src/runtime/serialize.ts","../src/runtime/rank-selectors.ts","../src/runtime/portal-aware-walker.ts","../src/provider.tsx","../src/runtime/hook.ts","../src/runtime/surface.ts","../src/runtime/walker.ts","../src/vite.ts"],"sourcesContent":["// Module-init side effects only. Importing this file installs the bippy hook\n// and exposes window.__sightmap__.snapshot(). Provider renders Fragment.\n//\n// CRITICAL: This module must be imported BEFORE react-dom in the app entry.\n// The runtime guard below catches the common late-init mistake.\n\nimport { instrument, type FiberRoot } from \"bippy\";\nimport { serializeSnapshot } from \"./serialize.js\";\nimport type { SightmapSnapshot } from \"./types.js\";\n\ndeclare global {\n interface Window {\n __sightmap__?: { snapshot: () => SightmapSnapshot };\n }\n}\n\nconst trackedRoots = new Set<FiberRoot>();\n\ninstrument({\n onCommitFiberRoot: (_id, root) => {\n trackedRoots.add(root);\n },\n});\n\nif (typeof window !== \"undefined\") {\n window.__sightmap__ = { snapshot: () => serializeSnapshot({ trackedRoots }) };\n\n // 1s grace window. If DOM has content but we saw zero commits, the import\n // ordering is wrong — fire a single actionable error.\n setTimeout(() => {\n if (trackedRoots.size > 0) return;\n if (typeof document === \"undefined\") return;\n const rootEl = document.querySelector(\"#root, [data-reactroot], body > div\");\n const domHasContent = (rootEl?.children.length ?? 0) > 0;\n if (!domHasContent) return;\n // eslint-disable-next-line no-console\n console.error(\n \"[sightmap] Late registration: SightmapProvider's runtime hook \" +\n \"missed React-DOM's renderer registration. Snapshots will be empty \" +\n \"even though the DOM rendered.\\n\\n\" +\n \"Fix one of:\\n\" +\n \" 1. Import the @sightmap/react entry FIRST in your app entry file \" +\n \"(before react-dom and your app code).\\n\" +\n \" 2. Use the auto-inject Vite plugin option (sightmap({ autoInject: true })).\\n\" +\n \" 3. If you must lazy-load the provider, force a no-op state update \" +\n \"after install to flush a commit.\",\n );\n }, 1000);\n}\n\nexport { trackedRoots };\n","import {\n traverseFiber,\n getDisplayName,\n isCompositeFiber,\n type Fiber,\n type FiberRoot,\n} from \"bippy\";\nimport { rankSelectors } from \"./rank-selectors.js\";\nimport { findHostElementForFiber } from \"./portal-aware-walker.js\";\nimport type {\n SightmapSnapshot,\n SightmapMarker,\n UnmarkedCandidate,\n SnapshotComponent,\n} from \"./types.js\";\n\nexport interface SerializeOptions {\n trackedRoots: Set<unknown>;\n}\n\nconst FRAMEWORK_NOISE = new Set([\n \"Routes\", \"Route\", \"RenderedRoute\", \"Outlet\", \"BrowserRouter\",\n \"Router\", \"RouterProvider\", \"DataRouterProvider\", \"RouterProviderImpl\",\n \"LinkWithRef\", \"StrictMode\", \"SightmapProvider\", \"Fragment\", \"Anonymous\",\n \"Suspense\", \"ErrorBoundary\", \"Provider\", \"Consumer\",\n \"ThemeProvider\", \"Hydration\", \"HydrateFallback\",\n \"RemixErrorBoundary\", \"HydratedRouter\", \"DataRoutes\",\n \"WithHydrateFallbackProps2\", \"RenderErrorBoundary\", \"Layout\",\n]);\n\nexport function serializeSnapshot(opts: SerializeOptions): SightmapSnapshot {\n const roots = Array.from(opts.trackedRoots) as FiberRoot[];\n if (roots.length === 0) {\n return {\n capturedAt: new Date().toISOString(),\n route: \"?\",\n commits: 0,\n components: [],\n markers: [],\n unmarkedCandidates: [],\n };\n }\n const root = roots.find((r) => r.current?.child !== null) ?? roots[0];\n if (!root) {\n return {\n capturedAt: new Date().toISOString(),\n route: \"?\",\n commits: 0,\n components: [],\n markers: [],\n unmarkedCandidates: [],\n };\n }\n const rootFiber = root.current as Fiber;\n\n const components = collectComponents(rootFiber);\n const markers = collectMarkers();\n const unmarkedCandidates = collectUnmarkedCandidates(rootFiber);\n\n return {\n capturedAt: new Date().toISOString(),\n route:\n typeof window !== \"undefined\" && window.location\n ? window.location.pathname + (window.location.search ?? \"\")\n : \"?\",\n commits: roots.length,\n components,\n markers,\n unmarkedCandidates,\n };\n}\n\nfunction collectComponents(rootFiber: Fiber): SnapshotComponent[] {\n const out: SnapshotComponent[] = [];\n const depthByFiber = new Map<Fiber, number>();\n depthByFiber.set(rootFiber, 0);\n\n traverseFiber(rootFiber, (f) => {\n const depth = depthByFiber.get(f) ?? 0;\n let c = f.child;\n while (c) {\n depthByFiber.set(c, depth + 1);\n c = c.sibling;\n }\n if (!isCompositeFiber(f)) return false;\n const name = getDisplayName(f);\n if (!name) return false;\n const childNames: string[] = [];\n let cc = f.child;\n while (cc) {\n if (isCompositeFiber(cc)) {\n const n = getDisplayName(cc);\n if (n) childNames.push(n);\n }\n cc = cc.sibling;\n }\n out.push({ displayName: name, depth, children: childNames });\n return false;\n });\n\n return out;\n}\n\nfunction collectMarkers(): SightmapMarker[] {\n const out: SightmapMarker[] = [];\n if (typeof document === \"undefined\") return out;\n const els = document.querySelectorAll<HTMLElement>(\"[data-sightmap]\");\n for (let i = 0; i < els.length; i++) {\n const el = els[i]!;\n const name = el.getAttribute(\"data-sightmap\") ?? \"\";\n const fiber = bridgeDomToFiber(el);\n const nearestComponent = nearestCompositeName(fiber);\n out.push({\n name,\n hostTag: el.tagName.toLowerCase(),\n ...(nearestComponent !== undefined ? { nearestComponent } : {}),\n domDepth: domDepth(el),\n candidateSelectors: rankSelectors(el),\n });\n }\n return out;\n}\n\nfunction collectUnmarkedCandidates(rootFiber: Fiber): UnmarkedCandidate[] {\n const out: UnmarkedCandidate[] = [];\n const seen = new Set<string>();\n traverseFiber(rootFiber, (f) => {\n if (!isCompositeFiber(f)) return false;\n const name = getDisplayName(f);\n if (!name || seen.has(name) || FRAMEWORK_NOISE.has(name)) return false;\n seen.add(name);\n const hostEl = findHostElementForFiber(f, (el) => document.contains(el));\n if (!hostEl) return false;\n const selectors = rankSelectors(hostEl);\n if (selectors.length === 0) return false;\n out.push({\n displayName: name,\n hostTag: hostEl.tagName.toLowerCase(),\n selectors,\n domDepth: domDepth(hostEl),\n });\n return false;\n });\n return out;\n}\n\nfunction bridgeDomToFiber(el: HTMLElement): Fiber | null {\n for (const key of Object.keys(el)) {\n if (key.startsWith(\"__reactFiber$\")) {\n return (el as unknown as Record<string, Fiber>)[key] ?? null;\n }\n }\n return null;\n}\n\nfunction nearestCompositeName(fiber: Fiber | null): string | undefined {\n let f: Fiber | null = fiber;\n let walks = 0;\n while (f && walks < 50) {\n if (isCompositeFiber(f)) {\n const n = getDisplayName(f);\n if (n) return n;\n }\n f = f.return;\n walks++;\n }\n return undefined;\n}\n\nfunction domDepth(el: HTMLElement): number {\n let d = 0;\n let cur: HTMLElement | null = el.parentElement;\n while (cur && cur !== document.body) {\n d++;\n cur = cur.parentElement;\n }\n return d;\n}\n","import type { CandidateSelector } from \"./types.js\";\n\n/**\n * Rank candidate selectors for a DOM element by stability/specificity:\n * 1. existing data-sightmap — explicit author intent, high\n * 2. data-testid / data-cy / data-test — test attributes, high\n * 3. role + aria-label / aria-label alone — a11y, medium\n * 4. <form|input|button|select|textarea|nav> + name attr — semantic, medium\n * 5. ID, if human-shaped — high\n *\n * Skip \"generated\" IDs (long hex runs, headlessui-style :r9: tokens) which\n * change every render.\n *\n * Returns [] when nothing stable was found; callers should propose adding a\n * data-sightmap attribute for those composites.\n */\nexport function rankSelectors(el: HTMLElement): CandidateSelector[] {\n const out: CandidateSelector[] = [];\n\n const dsm = el.getAttribute(\"data-sightmap\");\n if (dsm !== null) {\n out.push({\n selector: `[data-sightmap=\"${cssEsc(dsm)}\"]`,\n stability: \"high\",\n source: \"data-sightmap\",\n });\n }\n\n for (const attr of [\"data-testid\", \"data-cy\", \"data-test\"] as const) {\n const v = el.getAttribute(attr);\n if (v !== null) {\n out.push({\n selector: `[${attr}=\"${cssEsc(v)}\"]`,\n stability: \"high\",\n source: attr,\n });\n }\n }\n\n const role = el.getAttribute(\"role\");\n const aria = el.getAttribute(\"aria-label\");\n if (role && aria) {\n out.push({\n selector: `[role=\"${cssEsc(role)}\"][aria-label=\"${cssEsc(aria)}\"]`,\n stability: \"medium\",\n source: \"aria\",\n });\n } else if (aria) {\n out.push({\n selector: `[aria-label=\"${cssEsc(aria)}\"]`,\n stability: \"medium\",\n source: \"aria-label\",\n });\n }\n\n const name = el.getAttribute(\"name\");\n if (name !== null && /^(form|input|button|select|textarea|nav)$/i.test(el.tagName)) {\n out.push({\n selector: `${el.tagName.toLowerCase()}[name=\"${cssEsc(name)}\"]`,\n stability: \"medium\",\n source: \"semantic-name\",\n });\n }\n\n const id = el.id;\n if (id && isHumanShapedId(id)) {\n out.push({\n selector: `#${cssEsc(id)}`,\n stability: \"high\",\n source: \"id\",\n });\n }\n\n return out;\n}\n\nfunction cssEsc(v: string): string {\n return v.replace(/\"/g, '\\\\\"');\n}\n\nfunction isHumanShapedId(id: string): boolean {\n // Reject long hex runs (6+ digits or hex chars), headlessui-style `name-:r9:`,\n // and other auto-generated identifiers that change between renders.\n if (/[0-9]{6,}/.test(id)) return false;\n if (/^[a-z]+-[a-f0-9]{8,}/i.test(id)) return false;\n if (/:r[0-9a-z]+:/i.test(id)) return false;\n return true;\n}\n","import type { Fiber } from \"bippy\";\n\n/**\n * Find the first HTMLElement rendered DOWN from a composite fiber, skipping\n * Portal subtrees. Portals mount elsewhere in the DOM and shouldn't be\n * attributed to ancestor composites.\n *\n * The `inDocument` predicate filters out detached / portal-mounted elements\n * that escaped the static tag check (e.g. via custom portals that don't use\n * React's portal API). Callers typically pass `(el) => document.contains(el)`.\n *\n * Returns null if no qualifying host element exists within `maxNodes` walked\n * fibers (default 5000 — generous but bounded to avoid runaway walks on\n * pathological trees).\n */\nconst HOST_PORTAL_TAG = 4;\nconst MAX_NODES_DEFAULT = 5000;\n\nexport function findHostElementForFiber(\n fiber: Fiber,\n inDocument: (el: HTMLElement) => boolean,\n maxNodes: number = MAX_NODES_DEFAULT,\n): HTMLElement | null {\n if (!fiber.child) return null;\n\n // Iterative DFS using an explicit stack so we never blow the call stack.\n const stack: Fiber[] = [fiber.child];\n let walks = 0;\n\n while (stack.length > 0 && walks < maxNodes) {\n walks++;\n const f = stack.pop();\n if (!f) continue;\n\n // Defer sibling traversal until after we've descended (LIFO depth-first).\n if (f.sibling) stack.push(f.sibling);\n\n // Portal subtree → skip entirely, don't push children.\n if (f.tag === HOST_PORTAL_TAG) continue;\n\n // Check if stateNode is an HTMLElement (or duck-typed as one in tests).\n const stateNode = f.stateNode;\n if (stateNode && typeof stateNode === \"object\" && \"tagName\" in stateNode) {\n if (inDocument(stateNode as HTMLElement)) return stateNode as HTMLElement;\n }\n\n if (f.child) stack.push(f.child);\n }\n\n return null;\n}\n","// src/provider.tsx\n// Module side effects: install bippy hook, expose window.__sightmap__.snapshot.\n// MUST run before react-dom does any work, so it sits at the top of the\n// provider module and the provider should be imported first in app entries.\nimport \"./runtime/bippy-install.js\";\n\nimport { createContext, useContext, useEffect, useRef, useState, type ReactNode } from \"react\";\nimport type { Sightmap } from \"@sightmap/sightmap\";\nimport { parse, merge } from \"@sightmap/sightmap\";\nimport type { Diagnostic } from \"@sightmap/sightmap\";\nimport { installHook } from \"./runtime/hook.js\";\nimport { createHook } from \"./runtime/surface.js\";\n\ntype RuntimeMode = \"dev\" | \"enabled\" | \"off\";\n\nexport type SightmapProviderProps = {\n sightmap?: Sightmap;\n source?: string;\n runtimeIntrospection?: RuntimeMode;\n onError?: (diagnostic: Diagnostic) => void;\n children: ReactNode;\n};\n\nconst SightmapContext = createContext<Sightmap | null>(null);\n\nexport function useSightmap(): Sightmap | null {\n return useContext(SightmapContext);\n}\n\nconst SDK_VERSION = \"0.1.0\";\nconst SPEC_VERSION = \"1\";\n\nexport function SightmapProvider(props: SightmapProviderProps) {\n const { sightmap: initial, source = \"/__sightmap__/sightmap.json\", runtimeIntrospection = \"dev\", onError, children } = props;\n const [sightmap, setSightmap] = useState<Sightmap | null>(initial ?? null);\n const containerRef = useRef<HTMLDivElement>(null);\n\n // Load from `source` if no initial sightmap was provided.\n useEffect(() => {\n if (initial) return;\n let cancelled = false;\n fetch(source, { credentials: \"same-origin\" })\n .then((r) => r.json())\n .then((json: unknown) => {\n if (cancelled) return;\n // The dev middleware returns a parsed Sightmap object; in the future, source could be a YAML string.\n if (typeof json === \"string\") {\n setSightmap(merge([parse(json)]));\n } else {\n setSightmap(json as Sightmap);\n }\n })\n .catch((err) => {\n onError?.({\n severity: \"error\",\n code: \"react.sightmap-fetch-failed\",\n message: `Failed to load sightmap from ${source}: ${(err as Error).message}`,\n });\n });\n return () => { cancelled = true; };\n }, [initial, source, onError]);\n\n // Install/teardown the hook based on lifetime mode.\n useEffect(() => {\n const enabled = runtimeIntrospection === \"enabled\"\n || (runtimeIntrospection === \"dev\" && process.env.NODE_ENV !== \"production\");\n if (!enabled || !sightmap) return;\n\n const hook = createHook({\n getContainer: () => containerRef.current,\n getSightmap: () => sightmap,\n // Read fresh on every call. Both popstate and pushState/replaceState (via react-router)\n // mutate window.location.pathname synchronously; reading on demand always sees the\n // current value without needing a listener.\n getCurrentRoute: () => window.location.pathname,\n sdkVersion: SDK_VERSION,\n specVersion: SPEC_VERSION,\n });\n return installHook(hook);\n }, [runtimeIntrospection, sightmap]);\n\n return (\n <SightmapContext.Provider value={sightmap}>\n <div ref={containerRef} data-sightmap-root=\"\">{children}</div>\n </SightmapContext.Provider>\n );\n}\n","// src/runtime/hook.ts\nimport type { SightmapHook } from \"./types.js\";\n\nexport function installHook(hook: SightmapHook): () => void {\n if (typeof window === \"undefined\") return () => {};\n if (window.__SIGHTMAP__) return () => {}; // already installed (StrictMode double-mount)\n window.__SIGHTMAP__ = hook;\n return () => {\n if (window.__SIGHTMAP__ === hook) delete window.__SIGHTMAP__;\n };\n}\n","// src/runtime/surface.ts\nimport type { Sightmap, ResolvedView, MatchResult } from \"@sightmap/sightmap\";\nimport { match as coreMatch } from \"@sightmap/sightmap\";\nimport type { SightmapHook, ComponentNode } from \"./types.js\";\nimport { walkFromRoot } from \"./walker.js\";\n\nexport type SurfaceContext = {\n getContainer: () => Element | null;\n getSightmap: () => Sightmap;\n getCurrentRoute: () => string;\n sdkVersion: string;\n specVersion: string;\n};\n\nexport function createHook(ctx: SurfaceContext): SightmapHook {\n return {\n version: () => ({ sdk: ctx.sdkVersion, spec: ctx.specVersion }),\n getSightmap: ctx.getSightmap,\n getCurrentView: () => {\n const result = coreMatch(ctx.getSightmap(), { url: ctx.getCurrentRoute() });\n return result.view;\n },\n match: (req) => coreMatch(ctx.getSightmap(), req),\n walkTree: (opts) => {\n const container = ctx.getContainer();\n if (!container) return [];\n const all = walkFromRoot(container);\n if (!opts) return all;\n let scoped = all;\n if (opts.rootId !== undefined) {\n scoped = all.filter((n) => isDescendant(all, n.id, opts.rootId!));\n }\n if (opts.maxDepth !== undefined) {\n const baseDepth = opts.rootId\n ? (scoped.find((n) => n.id === opts.rootId)?.depth ?? 0)\n : 0;\n scoped = scoped.filter((n) => n.depth - baseDepth <= opts.maxDepth!);\n }\n return scoped;\n },\n inspectAt: (x, y) => {\n const container = ctx.getContainer();\n if (!container) return null;\n const target = document.elementFromPoint(x, y);\n if (!target) return null;\n const all = walkFromRoot(container);\n return all.find((n) => n.dom !== null && nodeMatchesEl(n, target as Element)) ?? null;\n },\n findByDataSightmap: (name) => {\n const container = ctx.getContainer();\n if (!container) return [];\n return walkFromRoot(container).filter((n) => n.dom?.dataSightmap === name);\n },\n };\n}\n\nfunction isDescendant(all: ComponentNode[], id: string, rootId: string): boolean {\n let cursor: ComponentNode | undefined = all.find((n) => n.id === id);\n while (cursor) {\n if (cursor.id === rootId) return true;\n if (cursor.parentId === null) return false;\n cursor = all.find((n) => n.id === cursor!.parentId);\n }\n return false;\n}\n\nfunction nodeMatchesEl(node: ComponentNode, el: Element): boolean {\n return node.dom?.tagName === el.tagName.toLowerCase()\n && node.dom?.dataSightmap === el.getAttribute(\"data-sightmap\");\n}\n","// src/runtime/walker.ts\nimport type { ComponentNode } from \"./types.js\";\n\n/**\n * Walk the React fiber tree starting from a DOM container.\n *\n * Implementation note: React 19 stores the fiber root on the container via an\n * internal property. We probe a few known shapes (the format has changed across\n * minor versions). If fiber access becomes load-bearing, replace this with a\n * subscription via the global DevTools-style hook (see Task 20) which calls us\n * with the FiberRoot directly.\n */\nexport function walkFromRoot(container: Element): ComponentNode[] {\n const fiberRoot = findFiberRoot(container);\n if (!fiberRoot) return [];\n const nodes: ComponentNode[] = [];\n let nextId = 0;\n const stack: Array<{ fiber: any; parentId: string | null; depth: number }> = [\n { fiber: fiberRoot.current, parentId: null, depth: 0 },\n ];\n while (stack.length > 0) {\n const { fiber, parentId, depth } = stack.pop()!;\n if (!fiber) continue;\n const id = String(nextId++);\n const node: ComponentNode = {\n id,\n parentId,\n depth,\n type: typeName(fiber),\n key: fiber.key ?? null,\n dom: fiber.stateNode instanceof Element ? domDescriptor(fiber.stateNode) : null,\n source: sourceFromFiber(fiber),\n childIds: [],\n };\n nodes.push(node);\n if (parentId !== null) {\n const parent = nodes.find((n) => n.id === parentId);\n if (parent) parent.childIds.push(id);\n }\n // Push children in reverse so the natural traversal is depth-first left→right.\n const children: any[] = [];\n let child = fiber.child;\n while (child) {\n children.push(child);\n child = child.sibling;\n }\n for (let i = children.length - 1; i >= 0; i--) {\n stack.push({ fiber: children[i], parentId: id, depth: depth + 1 });\n }\n }\n return nodes;\n}\n\nfunction findFiberRoot(container: Element): { current: any } | null {\n for (const key of Object.keys(container)) {\n if (key.startsWith(\"__reactContainer$\") || key.startsWith(\"__reactFiber$\")) {\n const fiber = (container as any)[key];\n let root = fiber;\n while (root?.return) root = root.return;\n if (root?.stateNode?.current) return root.stateNode;\n }\n }\n return null;\n}\n\nfunction typeName(fiber: any): string {\n const t = fiber.type;\n if (typeof t === \"string\") return t;\n if (t?.displayName) return t.displayName;\n if (t?.name) return t.name;\n return \"Unknown\";\n}\n\nfunction domDescriptor(el: Element): NonNullable<ComponentNode[\"dom\"]> {\n return {\n tagName: el.tagName.toLowerCase(),\n dataSightmap: el.getAttribute(\"data-sightmap\"),\n testId: el.getAttribute(\"data-testid\"),\n classes: Array.from(el.classList),\n };\n}\n\nfunction sourceFromFiber(fiber: any): ComponentNode[\"source\"] {\n const src = fiber._debugSource ?? fiber.elementType?.__source ?? null;\n if (src && typeof src.fileName === \"string\") {\n return { file: src.fileName, line: src.lineNumber ?? 0, col: src.columnNumber ?? 0 };\n }\n return null;\n}\n","import type { Plugin } from \"vite\";\nimport type { SightmapSnapshot } from \"./runtime/types.js\";\n\nexport interface SightmapPluginOptions {\n /**\n * When true, the plugin prepends `import \"@sightmap/react\";` to the app\n * entry (matched by filename ending in `main.tsx|tsx|jsx|ts|js` under\n * the project's `src/` or `app/`). This guarantees the bippy hook\n * installs before react-dom imports.\n */\n autoInject?: boolean;\n}\n\ninterface SnapshotCache {\n set(s: SightmapSnapshot): void;\n get(): SightmapSnapshot | null;\n}\n\nexport interface SightmapVitePlugin extends Plugin {\n /** Test-only handle for unit tests. Stable contract: don't use in production. */\n __test_cache: SnapshotCache;\n}\n\nexport function sightmap(options: SightmapPluginOptions = {}): SightmapVitePlugin {\n let cached: SightmapSnapshot | null = null;\n const cache: SnapshotCache = {\n set(s) { cached = s; },\n get() { return cached; },\n };\n\n const ENTRY_PATTERN = /(src|app)\\/(main|index|entry\\.client)\\.(t|j)sx?$/;\n const INJECT_LINE = `import \"@sightmap/react\";\\n`;\n\n return {\n name: \"sightmap-react\",\n\n configureServer(server) {\n server.middlewares.use(\"/__sightmap__/snapshot.json\", (req, res) => {\n if (req.method === \"POST\") {\n const chunks: Buffer[] = [];\n req.on(\"data\", (c: Buffer) => chunks.push(c));\n req.on(\"end\", () => {\n try {\n const body = JSON.parse(Buffer.concat(chunks).toString(\"utf8\")) as SightmapSnapshot;\n cache.set(body);\n res.statusCode = 204;\n res.end();\n } catch (e) {\n res.statusCode = 400;\n res.end(`bad json: ${(e as Error).message}`);\n }\n });\n return;\n }\n if (req.method === \"GET\") {\n const snap = cache.get();\n if (!snap) {\n res.statusCode = 404;\n res.end(`{\"error\":\"no snapshot cached yet — visit a page first\"}`);\n return;\n }\n res.statusCode = 200;\n res.setHeader(\"content-type\", \"application/json\");\n res.end(JSON.stringify(snap));\n return;\n }\n res.statusCode = 405;\n res.end();\n });\n },\n\n transform(code, id) {\n if (!options.autoInject) return null;\n if (!ENTRY_PATTERN.test(id)) return null;\n if (code.includes(\"@sightmap/react\")) return null;\n return { code: INJECT_LINE + code, map: null };\n },\n\n __test_cache: cache,\n };\n}\n"],"mappings":"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","names":["sightmap"]}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { Sightmap, ResolvedView, MatchResult } from '@sightmap/sightmap';
|
|
2
|
+
|
|
3
|
+
type ComponentNode = {
|
|
4
|
+
id: string;
|
|
5
|
+
parentId: string | null;
|
|
6
|
+
depth: number;
|
|
7
|
+
type: string;
|
|
8
|
+
key: string | null;
|
|
9
|
+
dom: {
|
|
10
|
+
tagName: string;
|
|
11
|
+
dataSightmap: string | null;
|
|
12
|
+
testId: string | null;
|
|
13
|
+
classes: string[];
|
|
14
|
+
} | null;
|
|
15
|
+
source: {
|
|
16
|
+
file: string;
|
|
17
|
+
line: number;
|
|
18
|
+
col: number;
|
|
19
|
+
} | null;
|
|
20
|
+
childIds: string[];
|
|
21
|
+
};
|
|
22
|
+
type SelectorProposal = {
|
|
23
|
+
selector: string;
|
|
24
|
+
strategy: "data-sightmap" | "data-testid" | "id" | "role-text" | "path";
|
|
25
|
+
matches: number;
|
|
26
|
+
};
|
|
27
|
+
type SightmapHook = {
|
|
28
|
+
version(): {
|
|
29
|
+
sdk: string;
|
|
30
|
+
spec: string;
|
|
31
|
+
};
|
|
32
|
+
getSightmap(): Sightmap;
|
|
33
|
+
getCurrentView(): ResolvedView | null;
|
|
34
|
+
match(req: {
|
|
35
|
+
url: string;
|
|
36
|
+
method?: string;
|
|
37
|
+
}): MatchResult;
|
|
38
|
+
walkTree(opts?: {
|
|
39
|
+
rootId?: string;
|
|
40
|
+
maxDepth?: number;
|
|
41
|
+
}): ComponentNode[];
|
|
42
|
+
inspectAt(x: number, y: number): ComponentNode | null;
|
|
43
|
+
findByDataSightmap(name: string): ComponentNode[];
|
|
44
|
+
};
|
|
45
|
+
declare global {
|
|
46
|
+
interface Window {
|
|
47
|
+
__SIGHTMAP__?: SightmapHook;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
type SelectorStability = "high" | "medium" | "low";
|
|
51
|
+
type SelectorSource = "data-sightmap" | "data-testid" | "data-cy" | "data-test" | "id" | "aria" | "aria-label" | "semantic-name" | "synthesized";
|
|
52
|
+
interface CandidateSelector {
|
|
53
|
+
selector: string;
|
|
54
|
+
stability: SelectorStability;
|
|
55
|
+
source: SelectorSource;
|
|
56
|
+
}
|
|
57
|
+
interface SightmapMarker {
|
|
58
|
+
/** value of data-sightmap attribute */
|
|
59
|
+
name: string;
|
|
60
|
+
hostTag: string;
|
|
61
|
+
nearestComponent?: string;
|
|
62
|
+
domDepth: number;
|
|
63
|
+
candidateSelectors: CandidateSelector[];
|
|
64
|
+
}
|
|
65
|
+
interface UnmarkedCandidate {
|
|
66
|
+
displayName: string;
|
|
67
|
+
hostTag: string;
|
|
68
|
+
selectors: CandidateSelector[];
|
|
69
|
+
domDepth: number;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Lightweight fiber-tree component projection used in {@link SightmapSnapshot}.
|
|
73
|
+
* Distinct from {@link ComponentNode} (which is the legacy DOM-anchored walker
|
|
74
|
+
* shape consumed by `surface.ts` / `walker.ts`); this one is produced by the
|
|
75
|
+
* bippy-based snapshot serializer.
|
|
76
|
+
*/
|
|
77
|
+
interface SnapshotComponent {
|
|
78
|
+
displayName: string;
|
|
79
|
+
depth: number;
|
|
80
|
+
children: string[];
|
|
81
|
+
}
|
|
82
|
+
interface SightmapSnapshot {
|
|
83
|
+
capturedAt: string;
|
|
84
|
+
route: string;
|
|
85
|
+
commits: number;
|
|
86
|
+
components: SnapshotComponent[];
|
|
87
|
+
markers: SightmapMarker[];
|
|
88
|
+
unmarkedCandidates: UnmarkedCandidate[];
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export type { CandidateSelector as C, SightmapSnapshot as S, UnmarkedCandidate as U, ComponentNode as a, SelectorSource as b, SelectorStability as c, SightmapMarker as d, SelectorProposal as e, SightmapHook as f };
|
package/dist/runtime-types.d.ts
CHANGED
|
@@ -1,51 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
type ComponentNode = {
|
|
4
|
-
id: string;
|
|
5
|
-
parentId: string | null;
|
|
6
|
-
depth: number;
|
|
7
|
-
type: string;
|
|
8
|
-
key: string | null;
|
|
9
|
-
dom: {
|
|
10
|
-
tagName: string;
|
|
11
|
-
dataSightmap: string | null;
|
|
12
|
-
testId: string | null;
|
|
13
|
-
classes: string[];
|
|
14
|
-
} | null;
|
|
15
|
-
source: {
|
|
16
|
-
file: string;
|
|
17
|
-
line: number;
|
|
18
|
-
col: number;
|
|
19
|
-
} | null;
|
|
20
|
-
childIds: string[];
|
|
21
|
-
};
|
|
22
|
-
type SelectorProposal = {
|
|
23
|
-
selector: string;
|
|
24
|
-
strategy: "data-sightmap" | "data-testid" | "id" | "role-text" | "path";
|
|
25
|
-
matches: number;
|
|
26
|
-
};
|
|
27
|
-
type SightmapHook = {
|
|
28
|
-
version(): {
|
|
29
|
-
sdk: string;
|
|
30
|
-
spec: string;
|
|
31
|
-
};
|
|
32
|
-
getSightmap(): Sightmap;
|
|
33
|
-
getCurrentView(): ResolvedView | null;
|
|
34
|
-
match(req: {
|
|
35
|
-
url: string;
|
|
36
|
-
method?: string;
|
|
37
|
-
}): MatchResult;
|
|
38
|
-
walkTree(opts?: {
|
|
39
|
-
rootId?: string;
|
|
40
|
-
maxDepth?: number;
|
|
41
|
-
}): ComponentNode[];
|
|
42
|
-
inspectAt(x: number, y: number): ComponentNode | null;
|
|
43
|
-
findByDataSightmap(name: string): ComponentNode[];
|
|
44
|
-
};
|
|
45
|
-
declare global {
|
|
46
|
-
interface Window {
|
|
47
|
-
__SIGHTMAP__?: SightmapHook;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export type { ComponentNode, SelectorProposal, SightmapHook };
|
|
1
|
+
export { a as ComponentNode, e as SelectorProposal, f as SightmapHook } from './runtime-types-Cvx7dsB4.js';
|
|
2
|
+
import '@sightmap/sightmap';
|