why-hydration 0.1.0 → 0.1.2
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/README.md +49 -2
- package/dist/{chunk-EPJM3LH3.cjs → chunk-AN3N7274.cjs} +224 -32
- package/dist/chunk-AN3N7274.cjs.map +1 -0
- package/dist/{chunk-LNVWRW65.js → chunk-HRNL75RP.js} +224 -32
- package/dist/chunk-HRNL75RP.js.map +1 -0
- package/dist/{chunk-R6344ZUK.cjs → chunk-I45YRDCA.cjs} +114 -14
- package/dist/chunk-I45YRDCA.cjs.map +1 -0
- package/dist/{chunk-PVXOK7GJ.js → chunk-QYZQHTZS.js} +108 -8
- package/dist/chunk-QYZQHTZS.js.map +1 -0
- package/dist/index.cjs +17 -17
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +1 -1
- package/dist/next/index.cjs +5 -9
- package/dist/next/index.d.cts +1 -2
- package/dist/next/index.d.ts +1 -2
- package/dist/next/index.js +3 -3
- package/dist/next/script.cjs +31 -6
- package/dist/next/script.cjs.map +1 -1
- package/dist/next/script.js +14 -2
- package/dist/next/script.js.map +1 -1
- package/dist/react.cjs +5 -4
- package/dist/react.d.cts +2 -2
- package/dist/react.d.ts +2 -2
- package/dist/react.js +3 -2
- package/dist/{types-DTlltJb9.d.cts → types-6wTih14e.d.cts} +2 -2
- package/dist/{types-DTlltJb9.d.ts → types-6wTih14e.d.ts} +2 -2
- package/package.json +14 -1
- package/dist/chunk-EPJM3LH3.cjs.map +0 -1
- package/dist/chunk-HYG6GVWO.js +0 -16
- package/dist/chunk-HYG6GVWO.js.map +0 -1
- package/dist/chunk-LNVWRW65.js.map +0 -1
- package/dist/chunk-PVXOK7GJ.js.map +0 -1
- package/dist/chunk-QGAEURQY.cjs +0 -38
- package/dist/chunk-QGAEURQY.cjs.map +0 -1
- package/dist/chunk-R6344ZUK.cjs.map +0 -1
package/README.md
CHANGED
|
@@ -1,9 +1,21 @@
|
|
|
1
1
|
# why-hydration
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/why-hydration)
|
|
4
|
+
[](https://www.npmjs.com/package/why-hydration)
|
|
5
|
+
[](https://bundlephobia.com/package/why-hydration)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
|
|
8
|
+
📦 **npm:** https://www.npmjs.com/package/why-hydration
|
|
9
|
+
|
|
3
10
|
**Tells you which component broke hydration, what differed, and how to fix it — in dev, with zero production cost.**
|
|
4
11
|
|
|
12
|
+
A **React hydration error / hydration mismatch debugger** for **Next.js** (App
|
|
13
|
+
Router & Pages Router), **Remix**, **Vite**, and any React SSR app. It points at
|
|
14
|
+
the exact **component, file, and value** behind "Hydration failed because the
|
|
15
|
+
server rendered HTML didn't match the client" — and tells you how to fix it.
|
|
16
|
+
|
|
5
17
|
<p align="center">
|
|
6
|
-
<img src="docs/screenshots/overlay-hero.png" alt="why-hydration overlay showing
|
|
18
|
+
<img src="docs/screenshots/overlay-hero.png" alt="why-hydration overlay showing classified React hydration mismatches in a Next.js app with component names" width="440">
|
|
7
19
|
</p>
|
|
8
20
|
|
|
9
21
|
React's hydration warnings tell you _that_ something mismatched, rarely _which
|
|
@@ -21,10 +33,13 @@ the client DOM, classifies the root cause, and hands you a specific fix.
|
|
|
21
33
|
or format the value after mount.
|
|
22
34
|
```
|
|
23
35
|
|
|
24
|
-
- 🔍 **Where** — component (
|
|
36
|
+
- 🔍 **Where** — the **component name** (e.g. `<PriceTag>`) and **source file:line**,
|
|
37
|
+
read from React's own fiber/diff, plus the exact DOM node + selector path.
|
|
25
38
|
- 🔀 **What** — server value vs client value, side by side.
|
|
26
39
|
- 🧠 **Why** — the cause, classified into a known category with a confidence score.
|
|
27
40
|
- 🛠️ **Fix** — a specific, actionable suggestion with a docs link.
|
|
41
|
+
- 🧹 **Low noise** — skips third-party/extension injections (ads, consent, chat,
|
|
42
|
+
Grammarly) so you see _your_ bug, not their DOM.
|
|
28
43
|
- 🫧 **Zero prod cost** — everything is gated on `process.env.NODE_ENV` and
|
|
29
44
|
tree-shakes to a **no-op** (~0 B, size-budgeted in CI).
|
|
30
45
|
- 🌐 **Arabic-first** — digit-script mismatches (٠١٢ vs 012) are a first-class cause.
|
|
@@ -149,6 +164,25 @@ A clean page with no mismatches shows **nothing** — no overlay, no logs.
|
|
|
149
164
|
|
|
150
165
|
---
|
|
151
166
|
|
|
167
|
+
## When it detects (full load vs client navigation)
|
|
168
|
+
|
|
169
|
+
Hydration mismatches happen **only during the initial server render + hydration**
|
|
170
|
+
— i.e. a **full page load, refresh, or direct URL entry** to an SSR'd route.
|
|
171
|
+
`why-hydration` detects those.
|
|
172
|
+
|
|
173
|
+
**Client-side navigation** (Next.js `<Link>` / `router.push`, React Router) does
|
|
174
|
+
**not** re-hydrate — the destination is rendered entirely on the client, so there
|
|
175
|
+
is no server HTML to diverge from and **no hydration mismatch can occur**. This is
|
|
176
|
+
React's design, not a limitation. To reproduce a mismatch on a specific route,
|
|
177
|
+
**refresh that route** (or open its URL directly).
|
|
178
|
+
|
|
179
|
+
Detection covers both React's console warning path and a real server-vs-client
|
|
180
|
+
DOM diff, and re-checks across a short settling window (React applies client
|
|
181
|
+
values to mismatched subtrees a few hundred ms after hydration), so time- and
|
|
182
|
+
render-order-dependent mismatches are caught reliably.
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
152
186
|
## Options
|
|
153
187
|
|
|
154
188
|
```tsx
|
|
@@ -304,6 +338,19 @@ early third-party script before hydration.
|
|
|
304
338
|
third-party init to post-hydration.
|
|
305
339
|
**Reference:** [React `suppressHydrationWarning`](https://react.dev/reference/react-dom/components/common#suppressing-unavoidable-hydration-mismatch-errors).
|
|
306
340
|
|
|
341
|
+
<a id="cause-attribute-mismatch"></a>
|
|
342
|
+
|
|
343
|
+
### attribute-mismatch
|
|
344
|
+
|
|
345
|
+
A `class`, `style`, or other attribute differs between server and client — the
|
|
346
|
+
report lists the exact tokens (e.g. _added on client: `forceHide`_). Usually a
|
|
347
|
+
class/style applied by a client-only conditional (viewport, media query, theme,
|
|
348
|
+
or feature flag) during the first render. React does **not** patch mismatched
|
|
349
|
+
attributes, so `why-hydration` reads these from React's own diff.
|
|
350
|
+
**Fix:** render the same attribute on the server and the first client paint —
|
|
351
|
+
move the condition into `useEffect`/a mounted flag, or use CSS media queries.
|
|
352
|
+
**Reference:** [React — different client/server content](https://react.dev/reference/react-dom/client/hydrateRoot#handling-different-client-and-server-content).
|
|
353
|
+
|
|
307
354
|
<a id="cause-unknown"></a>
|
|
308
355
|
|
|
309
356
|
### unknown
|
|
@@ -137,10 +137,26 @@ function normalizeAttr(name, value) {
|
|
|
137
137
|
return value.trim().split(/\s+/).filter(Boolean).sort().join(" ");
|
|
138
138
|
}
|
|
139
139
|
if (name === "style") {
|
|
140
|
-
return value
|
|
140
|
+
return normalizeStyle(value);
|
|
141
141
|
}
|
|
142
142
|
return value;
|
|
143
143
|
}
|
|
144
|
+
function normalizeStyle(value) {
|
|
145
|
+
if (typeof document !== "undefined") {
|
|
146
|
+
try {
|
|
147
|
+
const el = document.createElement("div");
|
|
148
|
+
el.style.cssText = value;
|
|
149
|
+
const decls = [];
|
|
150
|
+
for (let i = 0; i < el.style.length; i++) {
|
|
151
|
+
const prop = el.style.item(i);
|
|
152
|
+
decls.push(`${prop}:${el.style.getPropertyValue(prop)}`);
|
|
153
|
+
}
|
|
154
|
+
return decls.sort().join(";");
|
|
155
|
+
} catch {
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return value.split(";").map((s) => s.trim()).filter(Boolean).sort().join(";");
|
|
159
|
+
}
|
|
144
160
|
var NOISE_TAGS = /* @__PURE__ */ new Set([
|
|
145
161
|
"SCRIPT",
|
|
146
162
|
"STYLE",
|
|
@@ -148,12 +164,25 @@ var NOISE_TAGS = /* @__PURE__ */ new Set([
|
|
|
148
164
|
"TEMPLATE",
|
|
149
165
|
"NOSCRIPT"
|
|
150
166
|
]);
|
|
167
|
+
var TRACKER_MARKER = /googlefc|adsbygoogle|google_ads|googletag|__tcfapi|onetrust|optanon|cookiebot|usercentrics|didomi|quantcast|grammarly|gtm|hotjar|fullstory|intercom|drift|zendesk|livechat|tawk|hubspot|turnstile|recaptcha/i;
|
|
168
|
+
function isThirdPartyNoiseElement(el) {
|
|
169
|
+
const identity = `${el.getAttribute("name") ?? ""} ${el.id} ${typeof el.className === "string" ? el.className : ""}`;
|
|
170
|
+
if (TRACKER_MARKER.test(identity)) return true;
|
|
171
|
+
if (el.tagName === "IFRAME") {
|
|
172
|
+
const src = el.getAttribute("src") ?? "";
|
|
173
|
+
const style = (el.getAttribute("style") ?? "").toLowerCase();
|
|
174
|
+
const hidden = /display\s*:\s*none/.test(style) || /visibility\s*:\s*hidden/.test(style) || /(?:left|top)\s*:\s*-\d{3,}px/.test(style) || /(?:width|height)\s*:\s*0(?:px)?\b/.test(style) || el.hasAttribute("hidden") || el.getAttribute("aria-hidden") === "true";
|
|
175
|
+
if (src === "about:blank" || hidden) return true;
|
|
176
|
+
}
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
151
179
|
function isNoiseElement(node) {
|
|
152
180
|
if (node.nodeType !== Node.ELEMENT_NODE) return false;
|
|
153
181
|
const el = node;
|
|
154
182
|
if (el.hasAttribute("data-why-hydration")) return true;
|
|
155
183
|
if (NOISE_TAGS.has(el.tagName)) return true;
|
|
156
184
|
if (el.tagName.includes("-ROUTE-ANNOUNCER")) return true;
|
|
185
|
+
if (isThirdPartyNoiseElement(el)) return true;
|
|
157
186
|
return false;
|
|
158
187
|
}
|
|
159
188
|
function meaningfulChildNodes(parent) {
|
|
@@ -163,6 +192,7 @@ function meaningfulChildNodes(parent) {
|
|
|
163
192
|
);
|
|
164
193
|
return children.filter((node) => {
|
|
165
194
|
if (isNoiseElement(node)) return false;
|
|
195
|
+
if (node.nodeType === Node.COMMENT_NODE) return false;
|
|
166
196
|
if (node.nodeType !== Node.TEXT_NODE) return true;
|
|
167
197
|
const text = node.textContent ?? "";
|
|
168
198
|
if (text.trim() !== "") return true;
|
|
@@ -238,13 +268,39 @@ function hasArabicIndicDigits(value) {
|
|
|
238
268
|
function hasLatinDigits(value) {
|
|
239
269
|
return LATIN_DIGITS.test(value);
|
|
240
270
|
}
|
|
271
|
+
var NUMERIC_LIKE = /^[+-]?[\d.,\s\u00a0\u2009]+$/;
|
|
241
272
|
function isSameNumberDifferentSeparators(a, b) {
|
|
242
|
-
const
|
|
243
|
-
const
|
|
244
|
-
|
|
273
|
+
const at = a.trim();
|
|
274
|
+
const bt = b.trim();
|
|
275
|
+
if (!NUMERIC_LIKE.test(at) || !NUMERIC_LIKE.test(bt)) return false;
|
|
276
|
+
const digitsOnly = (s) => s.replace(/\D/g, "");
|
|
277
|
+
const da = digitsOnly(at);
|
|
278
|
+
const db = digitsOnly(bt);
|
|
245
279
|
if (!da || da !== db) return false;
|
|
246
|
-
const hasSep = (s) => /[.,\s\u00a0\u2009]/.test(s
|
|
247
|
-
return (hasSep(
|
|
280
|
+
const hasSep = (s) => /[.,\s\u00a0\u2009]/.test(s);
|
|
281
|
+
return (hasSep(at) || hasSep(bt)) && at !== bt;
|
|
282
|
+
}
|
|
283
|
+
var CONTENT_ATTRIBUTES = /* @__PURE__ */ new Set([
|
|
284
|
+
"value",
|
|
285
|
+
"placeholder",
|
|
286
|
+
"title",
|
|
287
|
+
"alt",
|
|
288
|
+
"label",
|
|
289
|
+
"aria-label",
|
|
290
|
+
"aria-valuetext",
|
|
291
|
+
"content",
|
|
292
|
+
"datetime"
|
|
293
|
+
]);
|
|
294
|
+
function isContentAttribute(name) {
|
|
295
|
+
return CONTENT_ATTRIBUTES.has(name.toLowerCase());
|
|
296
|
+
}
|
|
297
|
+
var THIRD_PARTY_MARKERS = /googlefc|adsbygoogle|google_ads|googletag|__tcfapi|onetrust|optanon|cookiebot|usercentrics|iubenda|didomi|quantcast|grammarly|data-gramm|gtm-|_hjsettings|hotjar|fullstory|intercom|drift|zendesk|livechat|tawk|hubspot|turnstile|recaptcha/i;
|
|
298
|
+
function looksLikeThirdPartyNode(html, tagName) {
|
|
299
|
+
const tag = (tagName ?? "").toUpperCase();
|
|
300
|
+
if (tag === "IFRAME" || tag === "EMBED" || tag === "OBJECT") return true;
|
|
301
|
+
const h = (html ?? "").toLowerCase();
|
|
302
|
+
if (!h) return false;
|
|
303
|
+
return THIRD_PARTY_MARKERS.test(h) || h.includes("about:blank");
|
|
248
304
|
}
|
|
249
305
|
function isSameDateDifferentOrder(a, b) {
|
|
250
306
|
const partsA = a.trim().match(/^(\d{1,4})[/.-](\d{1,2})[/.-](\d{1,4})$/);
|
|
@@ -322,8 +378,15 @@ function docs(category) {
|
|
|
322
378
|
function bothDiffer(d) {
|
|
323
379
|
return d.server != null && d.client != null && d.server.trim() !== d.client.trim();
|
|
324
380
|
}
|
|
381
|
+
function isValueDivergence(d) {
|
|
382
|
+
if (d.kind === "text") return true;
|
|
383
|
+
if (d.kind === "attribute" && d.attribute) {
|
|
384
|
+
return isContentAttribute(d.attribute);
|
|
385
|
+
}
|
|
386
|
+
return false;
|
|
387
|
+
}
|
|
325
388
|
var nonDeterministic = (d) => {
|
|
326
|
-
if (d
|
|
389
|
+
if (!isValueDivergence(d)) return null;
|
|
327
390
|
if (!bothDiffer(d)) return null;
|
|
328
391
|
if (!isRandomLike(d.server) || !isRandomLike(d.client)) return null;
|
|
329
392
|
return {
|
|
@@ -335,7 +398,7 @@ var nonDeterministic = (d) => {
|
|
|
335
398
|
};
|
|
336
399
|
};
|
|
337
400
|
var dateTime = (d) => {
|
|
338
|
-
if (d
|
|
401
|
+
if (!isValueDivergence(d)) return null;
|
|
339
402
|
if (!bothDiffer(d)) return null;
|
|
340
403
|
const serverTs = toTimestamp(d.server);
|
|
341
404
|
const clientTs = toTimestamp(d.client);
|
|
@@ -354,7 +417,7 @@ var dateTime = (d) => {
|
|
|
354
417
|
};
|
|
355
418
|
};
|
|
356
419
|
var localeFormat = (d) => {
|
|
357
|
-
if (d
|
|
420
|
+
if (!isValueDivergence(d)) return null;
|
|
358
421
|
if (!bothDiffer(d)) return null;
|
|
359
422
|
const { server, client } = d;
|
|
360
423
|
const scriptMismatch = hasArabicIndicDigits(server) && hasLatinDigits(client) || hasLatinDigits(server) && hasArabicIndicDigits(client);
|
|
@@ -462,17 +525,71 @@ var thirdPartyDomMutation = (d) => {
|
|
|
462
525
|
};
|
|
463
526
|
}
|
|
464
527
|
}
|
|
528
|
+
if ((d.kind === "node-added" || d.kind === "node-removed") && looksLikeThirdPartyNode(d.client ?? d.server, d.tagName)) {
|
|
529
|
+
const tag = (d.tagName ?? "element").toLowerCase();
|
|
530
|
+
return {
|
|
531
|
+
category: "third-party-dom-mutation",
|
|
532
|
+
confidence: 0.7,
|
|
533
|
+
explanation: `A <${tag}> was injected by a third-party script or browser extension (ads, consent, analytics, chat) after the server render. It is not part of your app's hydration, so this is usually harmless noise.`,
|
|
534
|
+
suggestion: 'If React warns about it, add `suppressHydrationWarning` to the nearest server-rendered wrapper, or load the third-party script after hydration (e.g. Next.js `<Script strategy="afterInteractive">`).',
|
|
535
|
+
docsUrl: docs("third-party-dom-mutation")
|
|
536
|
+
};
|
|
537
|
+
}
|
|
465
538
|
return null;
|
|
466
539
|
};
|
|
540
|
+
var attributeMismatch = (d) => {
|
|
541
|
+
if (d.kind !== "attribute" || !d.attribute) return null;
|
|
542
|
+
const attr = d.attribute.toLowerCase();
|
|
543
|
+
const server = d.server ?? "";
|
|
544
|
+
const client = d.client ?? "";
|
|
545
|
+
if (attr === "class" || attr === "classname") {
|
|
546
|
+
const serverSet = new Set(server.split(/\s+/).filter(Boolean));
|
|
547
|
+
const clientSet = new Set(client.split(/\s+/).filter(Boolean));
|
|
548
|
+
const added = [...clientSet].filter((c) => !serverSet.has(c));
|
|
549
|
+
const removed = [...serverSet].filter((c) => !clientSet.has(c));
|
|
550
|
+
const parts = [];
|
|
551
|
+
if (added.length) parts.push(`added on client: ${added.join(", ")}`);
|
|
552
|
+
if (removed.length) parts.push(`removed on client: ${removed.join(", ")}`);
|
|
553
|
+
const detail = parts.length ? ` (${parts.join("; ")})` : "";
|
|
554
|
+
return {
|
|
555
|
+
category: "attribute-mismatch",
|
|
556
|
+
confidence: 0.8,
|
|
557
|
+
explanation: `The \`class\` differs between server and client${detail}. A class was applied conditionally on the client \u2014 commonly a viewport, media-query, theme, or feature-flag check that runs during the first render.`,
|
|
558
|
+
suggestion: "Render the same className on the server and the first client paint. Move client-only conditions into `useEffect`/a mounted flag, or drive the visual change with CSS media queries instead of a JS class toggle.",
|
|
559
|
+
docsUrl: docs("attribute-mismatch")
|
|
560
|
+
};
|
|
561
|
+
}
|
|
562
|
+
if (attr === "style") {
|
|
563
|
+
return {
|
|
564
|
+
category: "attribute-mismatch",
|
|
565
|
+
confidence: 0.75,
|
|
566
|
+
explanation: "The inline `style` differs between server and client \u2014 an inline style was computed from client-only state (viewport size, theme, scroll position) during render.",
|
|
567
|
+
suggestion: "Compute the style after mount (`useEffect`) so the first client render matches the server, or move it to a CSS class / media query.",
|
|
568
|
+
docsUrl: docs("attribute-mismatch")
|
|
569
|
+
};
|
|
570
|
+
}
|
|
571
|
+
return {
|
|
572
|
+
category: "attribute-mismatch",
|
|
573
|
+
confidence: 0.6,
|
|
574
|
+
explanation: `The \`${d.attribute}\` attribute differs between server (\`${server}\`) and client (\`${client}\`) \u2014 its value was derived from something that differs between the server and the first client render.`,
|
|
575
|
+
suggestion: "Make the attribute deterministic across server and client, or set it after mount so the first client render matches the server HTML.",
|
|
576
|
+
docsUrl: docs("attribute-mismatch")
|
|
577
|
+
};
|
|
578
|
+
};
|
|
467
579
|
var BUILT_IN_RULES = [
|
|
468
580
|
nonDeterministic,
|
|
469
581
|
dateTime,
|
|
470
582
|
localeFormat,
|
|
583
|
+
// Third-party runs before browser-only/viewport so an injected iframe is
|
|
584
|
+
// labelled correctly instead of "browser-only API" or "viewport branching".
|
|
585
|
+
thirdPartyDomMutation,
|
|
471
586
|
browserOnlyApi,
|
|
472
587
|
viewportBranching,
|
|
473
588
|
invalidNesting,
|
|
474
589
|
whitespaceMinification,
|
|
475
|
-
|
|
590
|
+
// Catch-all for class/style/generic attribute diffs — after the specific
|
|
591
|
+
// rules so extension attributes and content values are handled first.
|
|
592
|
+
attributeMismatch
|
|
476
593
|
];
|
|
477
594
|
var UNKNOWN_CAUSE = {
|
|
478
595
|
category: "unknown",
|
|
@@ -536,7 +653,6 @@ function buildReport(divergence, cause, context = {}) {
|
|
|
536
653
|
function signatureOf(report) {
|
|
537
654
|
return [
|
|
538
655
|
report.node.kind,
|
|
539
|
-
report.node.path,
|
|
540
656
|
report.node.attribute ?? "",
|
|
541
657
|
report.cause.category,
|
|
542
658
|
report.server ?? "",
|
|
@@ -589,19 +705,107 @@ var ReportCollector = class {
|
|
|
589
705
|
|
|
590
706
|
// src/core/react-message.ts
|
|
591
707
|
function isHydrationMessage(message) {
|
|
592
|
-
return /hydrat/i.test(message) || /did not match/i.test(message) || /server (?:HTML|rendered)/i.test(message) || /validateDOMNesting/i.test(message) || /Text content does not match/i.test(message);
|
|
708
|
+
return /hydrat/i.test(message) || /did(?:n't| not) match/i.test(message) || /won't be patched up/i.test(message) || /hydration-mismatch/i.test(message) || /server (?:HTML|rendered)/i.test(message) || /validateDOMNesting/i.test(message) || /Text content does not match/i.test(message);
|
|
709
|
+
}
|
|
710
|
+
function stringify(v) {
|
|
711
|
+
return typeof v === "string" ? v : String(v);
|
|
593
712
|
}
|
|
594
713
|
function formatConsoleArgs(args) {
|
|
595
714
|
if (args.length === 0) return "";
|
|
596
715
|
const [first, ...rest] = args;
|
|
597
716
|
if (typeof first === "string" && /%[sco]/.test(first)) {
|
|
598
717
|
let i = 0;
|
|
599
|
-
|
|
718
|
+
const expanded = first.replace(/%[sco]/g, () => stringify(rest[i++] ?? ""));
|
|
719
|
+
const leftover = rest.slice(i).map(stringify).filter(Boolean);
|
|
720
|
+
return [expanded, ...leftover].join("\n").trim();
|
|
721
|
+
}
|
|
722
|
+
return args.map(stringify).join(" ");
|
|
723
|
+
}
|
|
724
|
+
function isInternalComponent(name) {
|
|
725
|
+
return /^(Inner|Outer|Segment|Client|Server|Redirect|Error|Loading|HTTPAccess|RenderFrom|ScrollAndFocus|Metadata|Outlet|ViewTransition|NotFound|Hot|DevRoot|App)$/.test(
|
|
726
|
+
name
|
|
727
|
+
) || /^(Inner|Outer|Segment|Client|Server|Redirect|Error|Loading|HTTPAccess|RenderFrom|ScrollAndFocus|Metadata|Outlet|ViewTransition|NotFound|Hot|DevRoot)[A-Z]/.test(
|
|
728
|
+
name
|
|
729
|
+
) || /(Boundary|Router|Handler|Provider|Context|Root|Node)$/.test(name) || name === "Fragment" || name === "Suspense";
|
|
730
|
+
}
|
|
731
|
+
function extractComponentFromMessage(message) {
|
|
732
|
+
const names = [];
|
|
733
|
+
const re = /<([A-Z][A-Za-z0-9_]*)\b/g;
|
|
734
|
+
let m;
|
|
735
|
+
while ((m = re.exec(message)) !== null) {
|
|
736
|
+
const name = m[1];
|
|
737
|
+
if (name && !isInternalComponent(name)) names.push(name);
|
|
738
|
+
}
|
|
739
|
+
return names.length ? names[names.length - 1] : void 0;
|
|
740
|
+
}
|
|
741
|
+
var ATTR_RE = /^([\w:-]+)=(?:"([\s\S]*)"|\{([\s\S]*)\})$/;
|
|
742
|
+
function parseModernDiff(message) {
|
|
743
|
+
const plus = [];
|
|
744
|
+
const minus = [];
|
|
745
|
+
for (const raw of message.split("\n")) {
|
|
746
|
+
const line = raw.trim();
|
|
747
|
+
const p = /^\+\s+(.+)$/.exec(line);
|
|
748
|
+
const mn = /^-\s+(.+)$/.exec(line);
|
|
749
|
+
if (p && p[1]) plus.push(p[1].trim());
|
|
750
|
+
else if (mn && mn[1]) minus.push(mn[1].trim());
|
|
751
|
+
}
|
|
752
|
+
if (plus.length === 0 && minus.length === 0) return null;
|
|
753
|
+
for (const p of plus) {
|
|
754
|
+
const pm = ATTR_RE.exec(p);
|
|
755
|
+
if (!pm) continue;
|
|
756
|
+
const name = pm[1];
|
|
757
|
+
const clientValue = pm[2] ?? pm[3] ?? "";
|
|
758
|
+
const matched = minus.find((mm) => {
|
|
759
|
+
const parsed = ATTR_RE.exec(mm);
|
|
760
|
+
return parsed && parsed[1] === name;
|
|
761
|
+
});
|
|
762
|
+
if (matched) {
|
|
763
|
+
const parsed = ATTR_RE.exec(matched);
|
|
764
|
+
const serverValue = parsed ? parsed[2] ?? parsed[3] ?? "" : "";
|
|
765
|
+
return {
|
|
766
|
+
kind: "attribute",
|
|
767
|
+
path: "body",
|
|
768
|
+
attribute: name,
|
|
769
|
+
server: serverValue,
|
|
770
|
+
client: clientValue,
|
|
771
|
+
reactMessage: message
|
|
772
|
+
};
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
const client = plus.find((p) => !ATTR_RE.test(p)) ?? null;
|
|
776
|
+
const server = minus.find((m) => !ATTR_RE.test(m)) ?? null;
|
|
777
|
+
if (client !== null || server !== null) {
|
|
778
|
+
return {
|
|
779
|
+
kind: "text",
|
|
780
|
+
path: "body",
|
|
781
|
+
server,
|
|
782
|
+
client,
|
|
783
|
+
reactMessage: message
|
|
784
|
+
};
|
|
600
785
|
}
|
|
601
|
-
return
|
|
786
|
+
return null;
|
|
602
787
|
}
|
|
603
788
|
function parseHydrationMessage(message) {
|
|
604
789
|
if (!isHydrationMessage(message)) return null;
|
|
790
|
+
const nesting = /<(\w+)>\s*cannot (?:appear as a|be a|contain a) (?:child|descendant)/i.exec(
|
|
791
|
+
message
|
|
792
|
+
);
|
|
793
|
+
if (nesting || /validateDOMNesting/i.test(message)) {
|
|
794
|
+
const pair = /<(\w+)>\s*cannot (?:appear as a|be a) (?:child|descendant) of <?(\w+)>?/i.exec(
|
|
795
|
+
message
|
|
796
|
+
);
|
|
797
|
+
return {
|
|
798
|
+
kind: "structure",
|
|
799
|
+
path: "body",
|
|
800
|
+
tagName: pair ? pair[1]?.toUpperCase() : void 0,
|
|
801
|
+
parentTagName: pair ? pair[2]?.toUpperCase() : void 0,
|
|
802
|
+
server: null,
|
|
803
|
+
client: null,
|
|
804
|
+
reactMessage: message
|
|
805
|
+
};
|
|
806
|
+
}
|
|
807
|
+
const modern = parseModernDiff(message);
|
|
808
|
+
if (modern) return modern;
|
|
605
809
|
const text = /Text content (?:did not match|does not match)[^:]*Server:\s*"?(.*?)"?\s+Client:\s*"?(.*?)"?\s*$/i.exec(
|
|
606
810
|
message
|
|
607
811
|
);
|
|
@@ -627,20 +831,6 @@ function parseHydrationMessage(message) {
|
|
|
627
831
|
reactMessage: message
|
|
628
832
|
};
|
|
629
833
|
}
|
|
630
|
-
const nesting = /<(\w+)>\s*cannot (?:appear as a|be a) (?:child|descendant) of <?(\w+)>?/i.exec(
|
|
631
|
-
message
|
|
632
|
-
);
|
|
633
|
-
if (nesting || /validateDOMNesting/i.test(message)) {
|
|
634
|
-
return {
|
|
635
|
-
kind: "structure",
|
|
636
|
-
path: "body",
|
|
637
|
-
tagName: nesting ? nesting[1]?.toUpperCase() : void 0,
|
|
638
|
-
parentTagName: nesting ? nesting[2]?.toUpperCase() : void 0,
|
|
639
|
-
server: null,
|
|
640
|
-
client: null,
|
|
641
|
-
reactMessage: message
|
|
642
|
-
};
|
|
643
|
-
}
|
|
644
834
|
const expected = /Expected server HTML to contain a matching <(\w+)>(?: in <(\w+)>)?/i.exec(
|
|
645
835
|
message
|
|
646
836
|
);
|
|
@@ -678,7 +868,7 @@ function parseHydrationMessage(message) {
|
|
|
678
868
|
}
|
|
679
869
|
|
|
680
870
|
// src/core/inspect.ts
|
|
681
|
-
function inspectRoot(root, collector, context = {}) {
|
|
871
|
+
function inspectRoot(root, collector, context = {}, enrich) {
|
|
682
872
|
const serverHtml = chunkOGQEPU7G_cjs.getServerHtmlForRoot(root);
|
|
683
873
|
if (serverHtml == null) return false;
|
|
684
874
|
const divergence = diffSnapshotAgainstDom(serverHtml, root);
|
|
@@ -686,13 +876,15 @@ function inspectRoot(root, collector, context = {}) {
|
|
|
686
876
|
if (context.reactMessage && !divergence.reactMessage) {
|
|
687
877
|
divergence.reactMessage = context.reactMessage;
|
|
688
878
|
}
|
|
689
|
-
|
|
879
|
+
const enriched = enrich ? enrich(divergence) : {};
|
|
880
|
+
return collector.report(divergence, { ...context, ...enriched }) != null;
|
|
690
881
|
}
|
|
691
882
|
function reportFromMessage(message, collector, context = {}) {
|
|
692
883
|
const divergence = parseHydrationMessage(message);
|
|
693
884
|
if (!divergence) return false;
|
|
694
885
|
return collector.report(divergence, {
|
|
695
886
|
...context,
|
|
887
|
+
component: extractComponentFromMessage(message) ?? context.component,
|
|
696
888
|
reactMessage: message
|
|
697
889
|
}) != null;
|
|
698
890
|
}
|
|
@@ -713,5 +905,5 @@ exports.parseHydrationMessage = parseHydrationMessage;
|
|
|
713
905
|
exports.parseServerHtml = parseServerHtml;
|
|
714
906
|
exports.reportFromMessage = reportFromMessage;
|
|
715
907
|
exports.signatureOf = signatureOf;
|
|
716
|
-
//# sourceMappingURL=chunk-
|
|
717
|
-
//# sourceMappingURL=chunk-
|
|
908
|
+
//# sourceMappingURL=chunk-AN3N7274.cjs.map
|
|
909
|
+
//# sourceMappingURL=chunk-AN3N7274.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/env.ts","../src/core/diff.ts","../src/core/classify/detectors.ts","../src/core/classify/rules.ts","../src/core/classify/index.ts","../src/core/report.ts","../src/core/react-message.ts","../src/core/inspect.ts"],"names":["getServerHtmlForRoot"],"mappings":"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","file":"chunk-AN3N7274.cjs","sourcesContent":["export const isDev: boolean =\n typeof process !== 'undefined' &&\n process.env != null &&\n process.env.NODE_ENV !== 'production';\n","import type { Divergence } from './types';\n\nconst IGNORED_ATTRIBUTES = new Set<string>(['data-reactroot']);\n\nexport function parseServerHtml(html: string, rootTagName: string): Element {\n const container = document.createElement(rootTagName || 'div');\n container.innerHTML = html;\n return container;\n}\n\nexport function diffTrees(\n serverRoot: Element,\n clientRoot: Element,\n basePath = tagPath(clientRoot),\n): Divergence | null {\n return diffChildren(serverRoot, clientRoot, basePath);\n}\n\nexport function diffSnapshotAgainstDom(\n serverHtml: string,\n clientRoot: Element,\n): Divergence | null {\n const serverRoot = parseServerHtml(serverHtml, clientRoot.tagName);\n return diffTrees(serverRoot, clientRoot);\n}\n\nfunction diffChildren(\n serverParent: Node,\n clientParent: Node,\n parentPath: string,\n): Divergence | null {\n const serverChildren = meaningfulChildNodes(serverParent);\n const clientChildren = meaningfulChildNodes(clientParent);\n const max = Math.max(serverChildren.length, clientChildren.length);\n\n for (let i = 0; i < max; i++) {\n const serverNode = serverChildren[i] ?? null;\n const clientNode = clientChildren[i] ?? null;\n const path = childPath(parentPath, (clientNode ?? serverNode) as Node, i);\n\n if (serverNode && !clientNode) {\n return {\n kind: 'node-removed',\n path,\n tagName: elementTag(serverNode),\n parentTagName: elementTag(clientParent),\n server: serialize(serverNode),\n client: null,\n element: asElement(clientParent),\n };\n }\n if (!serverNode && clientNode) {\n return {\n kind: 'node-added',\n path,\n tagName: elementTag(clientNode),\n parentTagName: elementTag(clientParent),\n server: null,\n client: serialize(clientNode),\n element: asElement(clientNode),\n };\n }\n if (!serverNode || !clientNode) continue;\n\n const divergence = diffNode(\n serverNode,\n clientNode,\n path,\n elementTag(clientParent),\n );\n if (divergence) return divergence;\n }\n return null;\n}\n\nfunction diffNode(\n serverNode: Node,\n clientNode: Node,\n path: string,\n parentTag: string | undefined,\n): Divergence | null {\n if (serverNode.nodeType !== clientNode.nodeType) {\n return {\n kind: 'structure',\n path,\n tagName: elementTag(clientNode),\n parentTagName: parentTag,\n server: serialize(serverNode),\n client: serialize(clientNode),\n element: asElement(clientNode),\n };\n }\n\n if (\n serverNode.nodeType === Node.TEXT_NODE ||\n serverNode.nodeType === Node.COMMENT_NODE\n ) {\n const serverText = serverNode.textContent ?? '';\n const clientText = clientNode.textContent ?? '';\n if (serverText !== clientText) {\n return {\n kind: 'text',\n path,\n parentTagName: parentTag,\n server: serverText,\n client: clientText,\n element: asElement(clientNode.parentNode),\n };\n }\n return null;\n }\n\n if (serverNode.nodeType === Node.ELEMENT_NODE) {\n const serverEl = serverNode as Element;\n const clientEl = clientNode as Element;\n\n if (serverEl.tagName !== clientEl.tagName) {\n return {\n kind: 'structure',\n path,\n tagName: clientEl.tagName,\n parentTagName: parentTag,\n server: serialize(serverEl),\n client: serialize(clientEl),\n element: clientEl,\n };\n }\n\n const attrDivergence = diffAttributes(serverEl, clientEl, path, parentTag);\n if (attrDivergence) return attrDivergence;\n\n return diffChildren(serverEl, clientEl, path);\n }\n\n return null;\n}\n\nfunction diffAttributes(\n serverEl: Element,\n clientEl: Element,\n path: string,\n parentTag: string | undefined,\n): Divergence | null {\n const names = new Set<string>();\n for (const a of Array.from(serverEl.attributes)) names.add(a.name);\n for (const a of Array.from(clientEl.attributes)) names.add(a.name);\n\n for (const name of names) {\n if (IGNORED_ATTRIBUTES.has(name)) continue;\n const serverValue = serverEl.getAttribute(name);\n const clientValue = clientEl.getAttribute(name);\n if (normalizeAttr(name, serverValue) === normalizeAttr(name, clientValue)) {\n continue;\n }\n return {\n kind: 'attribute',\n path,\n tagName: clientEl.tagName,\n parentTagName: parentTag,\n attribute: name,\n server: serverValue,\n client: clientValue,\n element: clientEl,\n };\n }\n return null;\n}\n\nfunction normalizeAttr(name: string, value: string | null): string | null {\n if (value == null) return null;\n if (name === 'class') {\n return value.trim().split(/\\s+/).filter(Boolean).sort().join(' ');\n }\n if (name === 'style') {\n return normalizeStyle(value);\n }\n return value;\n}\n\n/**\n * Canonicalize an inline style string so the server snapshot (React's raw\n * serialization, e.g. `color:#0f172a`) compares equal to the live DOM value the\n * browser has normalized via CSSOM (e.g. `color: rgb(15, 23, 42);`). We round\n * each declaration through a throwaway element's CSSOM, then sort so property\n * order doesn't matter either.\n */\nfunction normalizeStyle(value: string): string {\n if (typeof document !== 'undefined') {\n try {\n const el = document.createElement('div');\n el.style.cssText = value;\n const decls: string[] = [];\n for (let i = 0; i < el.style.length; i++) {\n const prop = el.style.item(i);\n decls.push(`${prop}:${el.style.getPropertyValue(prop)}`);\n }\n return decls.sort().join(';');\n } catch {\n /* fall through to string normalization */\n }\n }\n return value\n .split(';')\n .map((s) => s.trim())\n .filter(Boolean)\n .sort()\n .join(';');\n}\n\nconst NOISE_TAGS = new Set<string>([\n 'SCRIPT',\n 'STYLE',\n 'LINK',\n 'TEMPLATE',\n 'NOSCRIPT',\n]);\n\n// Markers of ads / consent / analytics / chat widgets on a node's identity.\nconst TRACKER_MARKER =\n /googlefc|adsbygoogle|google_ads|googletag|__tcfapi|onetrust|optanon|cookiebot|usercentrics|didomi|quantcast|grammarly|gtm|hotjar|fullstory|intercom|drift|zendesk|livechat|tawk|hubspot|turnstile|recaptcha/i;\n\n// Invisible utility nodes injected by third-party scripts (hidden iframes,\n// consent/analytics frames, `about:blank`). They are pure post-load noise and\n// must be skipped so they never mask the developer's real mismatch or get\n// reported themselves. This is the exact shape of Google's `googlefcInactive`\n// hidden iframe seen in the wild.\nfunction isThirdPartyNoiseElement(el: Element): boolean {\n const identity = `${el.getAttribute('name') ?? ''} ${el.id} ${\n typeof el.className === 'string' ? el.className : ''\n }`;\n if (TRACKER_MARKER.test(identity)) return true;\n if (el.tagName === 'IFRAME') {\n const src = el.getAttribute('src') ?? '';\n const style = (el.getAttribute('style') ?? '').toLowerCase();\n const hidden =\n /display\\s*:\\s*none/.test(style) ||\n /visibility\\s*:\\s*hidden/.test(style) ||\n /(?:left|top)\\s*:\\s*-\\d{3,}px/.test(style) ||\n /(?:width|height)\\s*:\\s*0(?:px)?\\b/.test(style) ||\n el.hasAttribute('hidden') ||\n el.getAttribute('aria-hidden') === 'true';\n if (src === 'about:blank' || hidden) return true;\n }\n return false;\n}\n\nfunction isNoiseElement(node: Node): boolean {\n if (node.nodeType !== Node.ELEMENT_NODE) return false;\n const el = node as Element;\n if (el.hasAttribute('data-why-hydration')) return true;\n if (NOISE_TAGS.has(el.tagName)) return true;\n if (el.tagName.includes('-ROUTE-ANNOUNCER')) return true;\n if (isThirdPartyNoiseElement(el)) return true;\n return false;\n}\n\nfunction meaningfulChildNodes(parent: Node): Node[] {\n const children = Array.from(parent.childNodes);\n const hasElement = children.some(\n (n) => n.nodeType === Node.ELEMENT_NODE && !isNoiseElement(n),\n );\n return children.filter((node) => {\n if (isNoiseElement(node)) return false;\n // Comment nodes are framework markers (React `<!--$-->` / `<!--/$-->`\n // Suspense boundaries, RSC payload markers), never the user's real\n // mismatch. Skipping them symmetrically avoids false positives.\n if (node.nodeType === Node.COMMENT_NODE) return false;\n if (node.nodeType !== Node.TEXT_NODE) return true;\n const text = node.textContent ?? '';\n if (text.trim() !== '') return true;\n return !hasElement;\n });\n}\n\nfunction serialize(node: Node): string {\n if (node.nodeType === Node.ELEMENT_NODE) {\n return (node as Element).outerHTML;\n }\n return node.textContent ?? '';\n}\n\nfunction asElement(node: Node | null | undefined): Element | null {\n if (!node) return null;\n return node.nodeType === Node.ELEMENT_NODE ? (node as Element) : null;\n}\n\nfunction elementTag(node: Node): string | undefined {\n return node.nodeType === Node.ELEMENT_NODE\n ? (node as Element).tagName\n : undefined;\n}\n\nfunction tagPath(el: Element): string {\n return el.tagName.toLowerCase();\n}\n\nfunction childPath(parentPath: string, node: Node, index: number): string {\n if (node.nodeType === Node.ELEMENT_NODE) {\n const tag = (node as Element).tagName.toLowerCase();\n return `${parentPath} > ${tag}:nth-child(${index + 1})`;\n }\n if (node.nodeType === Node.COMMENT_NODE) {\n return `${parentPath} > #comment[${index}]`;\n }\n return `${parentPath} > #text[${index}]`;\n}\n","const UUID_RE =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\nconst REACT_ID_RE = /^:[rR][0-9a-z]*:$/;\nconst HEX_TOKEN_RE = /^[0-9a-f]{16,}$/i;\nconst RANDOM_DECIMAL_RE = /^0?\\.\\d{6,}$/;\nconst NANOID_RE = /^[A-Za-z0-9_-]{10,}$/;\n\nconst ARABIC_INDIC_DIGITS = /[٠-٩۰-۹]/;\nconst LATIN_DIGITS = /[0-9]/;\n\nexport function isRandomLike(value: string): boolean {\n const v = value.trim();\n if (!v) return false;\n if (UUID_RE.test(v)) return true;\n if (REACT_ID_RE.test(v)) return true;\n if (HEX_TOKEN_RE.test(v)) return true;\n if (RANDOM_DECIMAL_RE.test(v)) return true;\n if (NANOID_RE.test(v) && /[A-Za-z]/.test(v) && /[0-9]/.test(v)) return true;\n return false;\n}\n\nexport function looksLikeTime(value: string): boolean {\n return /\\b\\d{1,2}:\\d{2}(?::\\d{2})?(?:\\s?[AaPp][Mm])?\\b/.test(value.trim());\n}\n\nexport function toTimestamp(value: string): number | null {\n const v = value.trim();\n if (!v) return null;\n if (/^\\d{10,13}$/.test(v)) {\n const n = Number(v);\n return v.length === 10 ? n * 1000 : n;\n }\n const parsed = Date.parse(v);\n if (!Number.isNaN(parsed)) return parsed;\n if (looksLikeTime(v)) {\n const anchored = Date.parse(`1970-01-01 ${v}`);\n if (!Number.isNaN(anchored)) return anchored;\n }\n return null;\n}\n\nexport function hasArabicIndicDigits(value: string): boolean {\n return ARABIC_INDIC_DIGITS.test(value);\n}\n\nexport function hasLatinDigits(value: string): boolean {\n return LATIN_DIGITS.test(value);\n}\n\n// A value made only of digits, separators and an optional sign \\u2014 i.e. it\n// actually looks like a formatted number. Guards against class lists, ids, and\n// arbitrary text that merely contain digits (e.g. \"radius-8 border p-8\").\nconst NUMERIC_LIKE = /^[+-]?[\\d.,\\s\\u00a0\\u2009]+$/;\n\nexport function isSameNumberDifferentSeparators(a: string, b: string): boolean {\n const at = a.trim();\n const bt = b.trim();\n if (!NUMERIC_LIKE.test(at) || !NUMERIC_LIKE.test(bt)) return false;\n const digitsOnly = (s: string) => s.replace(/\\D/g, '');\n const da = digitsOnly(at);\n const db = digitsOnly(bt);\n if (!da || da !== db) return false;\n const hasSep = (s: string) => /[.,\\s\\u00a0\\u2009]/.test(s);\n return (hasSep(at) || hasSep(bt)) && at !== bt;\n}\n\n// Attributes whose value is human-facing content that can carry locale/date/\n// random formatting. Structural attributes (class, style, id, href\\u2026) are not.\nconst CONTENT_ATTRIBUTES = new Set<string>([\n 'value',\n 'placeholder',\n 'title',\n 'alt',\n 'label',\n 'aria-label',\n 'aria-valuetext',\n 'content',\n 'datetime',\n]);\n\nexport function isContentAttribute(name: string): boolean {\n return CONTENT_ATTRIBUTES.has(name.toLowerCase());\n}\n\n// Markers of third-party scripts / consent / analytics / chat widgets that\n// inject nodes after the server render (not part of the app's hydration).\nconst THIRD_PARTY_MARKERS =\n /googlefc|adsbygoogle|google_ads|googletag|__tcfapi|onetrust|optanon|cookiebot|usercentrics|iubenda|didomi|quantcast|grammarly|data-gramm|gtm-|_hjsettings|hotjar|fullstory|intercom|drift|zendesk|livechat|tawk|hubspot|turnstile|recaptcha/i;\n\n// True when a *node-added / node-removed* divergence is almost certainly a\n// third-party injection rather than the developer's own hydration mismatch.\nexport function looksLikeThirdPartyNode(\n html: string | null,\n tagName: string | undefined,\n): boolean {\n const tag = (tagName ?? '').toUpperCase();\n if (tag === 'IFRAME' || tag === 'EMBED' || tag === 'OBJECT') return true;\n const h = (html ?? '').toLowerCase();\n if (!h) return false;\n return THIRD_PARTY_MARKERS.test(h) || h.includes('about:blank');\n}\n\nexport function isSameDateDifferentOrder(a: string, b: string): boolean {\n const partsA = a.trim().match(/^(\\d{1,4})[/.-](\\d{1,2})[/.-](\\d{1,4})$/);\n const partsB = b.trim().match(/^(\\d{1,4})[/.-](\\d{1,2})[/.-](\\d{1,4})$/);\n if (!partsA || !partsB) return false;\n const setA = [partsA[1], partsA[2], partsA[3]].sort().join('|');\n const setB = [partsB[1], partsB[2], partsB[3]].sort().join('|');\n return setA === setB && a.trim() !== b.trim();\n}\n\nexport const EXTENSION_ATTRIBUTES = new Set<string>([\n 'cz-shortcut-listen',\n 'data-gramm',\n 'data-gramm_editor',\n 'data-gramm_id',\n 'data-gr-c-s-loaded',\n 'data-lt-installed',\n 'data-new-gr-c-s-check-loaded',\n 'data-new-gr-c-s-loaded',\n 'spellcheck-extension',\n 'bis_register',\n '__processed_by_react_dev_tools',\n]);\n\nexport function isExtensionAttribute(name: string): boolean {\n const n = name.toLowerCase();\n if (EXTENSION_ATTRIBUTES.has(n)) return true;\n return (\n n.startsWith('data-gr-') ||\n n.startsWith('data-gramm') ||\n n.startsWith('__bis') ||\n n.startsWith('bis_')\n );\n}\n\nconst BLOCK_TAGS = new Set([\n 'DIV',\n 'P',\n 'SECTION',\n 'ARTICLE',\n 'UL',\n 'OL',\n 'LI',\n 'TABLE',\n 'HEADER',\n 'FOOTER',\n 'MAIN',\n 'ASIDE',\n 'NAV',\n 'H1',\n 'H2',\n 'H3',\n 'H4',\n 'H5',\n 'H6',\n 'FORM',\n 'BLOCKQUOTE',\n 'PRE',\n 'HR',\n]);\n\nexport function isInvalidNesting(\n parentTag: string | undefined,\n childTag: string | undefined,\n): boolean {\n if (!parentTag || !childTag) return false;\n const p = parentTag.toUpperCase();\n const c = childTag.toUpperCase();\n if (p === 'P' && BLOCK_TAGS.has(c)) return true;\n if (p === 'A' && c === 'A') return true;\n if (p === 'BUTTON' && (c === 'BUTTON' || c === 'A')) return true;\n if ((p === 'TABLE' || p === 'THEAD' || p === 'TBODY') && c === 'DIV') {\n return true;\n }\n return false;\n}\n\nexport function messageIndicatesInvalidNesting(message?: string): boolean {\n if (!message) return false;\n return (\n /validateDOMNesting/i.test(message) ||\n /cannot (?:be a|contain).*(?:descendant|child)/i.test(message) ||\n /cannot appear as a (?:child|descendant)/i.test(message)\n );\n}\n","import type { Cause, Classifier, Divergence } from '../types';\nimport {\n hasArabicIndicDigits,\n hasLatinDigits,\n isContentAttribute,\n isExtensionAttribute,\n isInvalidNesting,\n isRandomLike,\n isSameDateDifferentOrder,\n isSameNumberDifferentSeparators,\n looksLikeThirdPartyNode,\n looksLikeTime,\n messageIndicatesInvalidNesting,\n toTimestamp,\n} from './detectors';\n\nexport const DOCS_BASE =\n 'https://github.com/razan-aboushi/why-hydration#cause-';\n\nfunction docs(category: string): string {\n return `${DOCS_BASE}${category}`;\n}\n\nfunction bothDiffer(d: Divergence): d is Divergence & {\n server: string;\n client: string;\n} {\n return (\n d.server != null && d.client != null && d.server.trim() !== d.client.trim()\n );\n}\n\n// The value-formatting rules (random / date / locale) only make sense for\n// human-facing text: text nodes and content-like attributes. Applied to\n// `class`/`style`/`id`/etc. they false-match (e.g. a class list with digits\n// looks like \"the same number with different separators\").\nfunction isValueDivergence(d: Divergence): boolean {\n if (d.kind === 'text') return true;\n if (d.kind === 'attribute' && d.attribute) {\n return isContentAttribute(d.attribute);\n }\n return false;\n}\n\nconst nonDeterministic: Classifier = (d) => {\n if (!isValueDivergence(d)) return null;\n if (!bothDiffer(d)) return null;\n if (!isRandomLike(d.server) || !isRandomLike(d.client)) return null;\n return {\n category: 'non-deterministic-value',\n confidence: 0.9,\n explanation:\n 'The server and client rendered different random-looking values ' +\n '(an id, token, or Math.random() output). Anything non-deterministic ' +\n 'in render produces a different value on each side.',\n suggestion:\n 'Use React `useId()` for ids. For random values, generate them after ' +\n 'mount (in `useEffect`) or pass a value down from the server so both ' +\n 'sides agree. Never call `Math.random()`/`crypto` during render.',\n docsUrl: docs('non-deterministic-value'),\n };\n};\n\nconst dateTime: Classifier = (d) => {\n if (!isValueDivergence(d)) return null;\n if (!bothDiffer(d)) return null;\n const serverTs = toTimestamp(d.server);\n const clientTs = toTimestamp(d.client);\n const bothTimes = looksLikeTime(d.server) && looksLikeTime(d.client);\n if (serverTs == null || clientTs == null) {\n if (!bothTimes) return null;\n }\n const delta =\n serverTs != null && clientTs != null ? Math.abs(serverTs - clientTs) : 0;\n const smallDelta = delta > 0 && delta < 24 * 60 * 60 * 1000;\n return {\n category: 'date-time',\n confidence: smallDelta || bothTimes ? 0.85 : 0.7,\n explanation:\n 'The values are dates/times that differ between server render and ' +\n 'client render — the clock moved (or the timezone differs) between the ' +\n 'two environments.',\n suggestion:\n 'Render the current time after mount, or pass a single server ' +\n 'timestamp down and format it identically on both sides. Pin an ' +\n 'explicit timezone when formatting.',\n docsUrl: docs('date-time'),\n };\n};\n\nconst localeFormat: Classifier = (d) => {\n if (!isValueDivergence(d)) return null;\n if (!bothDiffer(d)) return null;\n const { server, client } = d;\n\n const scriptMismatch =\n (hasArabicIndicDigits(server) && hasLatinDigits(client)) ||\n (hasLatinDigits(server) && hasArabicIndicDigits(client));\n if (scriptMismatch) {\n return {\n category: 'locale-format',\n confidence: 0.92,\n explanation:\n 'The same value was formatted with different digit scripts ' +\n '(Arabic-Indic ٠١٢ vs Latin 012). The server and client resolved to ' +\n 'different locales.',\n suggestion:\n 'Pass an explicit `locale` (and timezone) to `Intl.NumberFormat` / ' +\n '`toLocaleString` on both server and client, or format the value ' +\n 'after mount so only the client locale is ever used.',\n docsUrl: docs('locale-format'),\n };\n }\n\n if (isSameNumberDifferentSeparators(server, client)) {\n return {\n category: 'locale-format',\n confidence: 0.82,\n explanation:\n 'The same number was formatted with different grouping/decimal ' +\n 'separators between server and client (e.g. 1,234.56 vs 1.234,56).',\n suggestion:\n 'Pass an explicit locale to `Intl.NumberFormat`/`toLocaleString` on ' +\n 'both sides so the separators match.',\n docsUrl: docs('locale-format'),\n };\n }\n\n if (isSameDateDifferentOrder(server, client)) {\n return {\n category: 'locale-format',\n confidence: 0.75,\n explanation:\n 'The same date was rendered in a different field order ' +\n '(MM/DD vs DD/MM) between server and client.',\n suggestion:\n 'Format dates with an explicit locale and timezone via `Intl` on ' +\n 'both sides.',\n docsUrl: docs('locale-format'),\n };\n }\n return null;\n};\n\nconst browserOnlyApi: Classifier = (d) => {\n const serverEmpty = d.server == null || d.server.trim() === '';\n const clientHasContent = d.client != null && d.client.trim() !== '';\n const shape =\n (d.kind === 'text' || d.kind === 'node-added') &&\n serverEmpty &&\n clientHasContent;\n if (!shape) return null;\n return {\n category: 'browser-only-api',\n confidence: 0.75,\n explanation:\n 'The client rendered content the server left empty — the signature of ' +\n 'reading a browser-only API (`window`, `document`, `localStorage`, ' +\n '`navigator`, `matchMedia`) during render.',\n suggestion:\n 'Gate browser-only reads behind a mounted flag or `useEffect`, or use ' +\n '`useSyncExternalStore` with a server snapshot so the first client ' +\n 'render matches the server.',\n docsUrl: docs('browser-only-api'),\n };\n};\n\nconst viewportBranching: Classifier = (d) => {\n const structural =\n d.kind === 'structure' ||\n d.kind === 'node-added' ||\n d.kind === 'node-removed';\n if (!structural) return null;\n if (\n isInvalidNesting(d.parentTagName, d.tagName) ||\n messageIndicatesInvalidNesting(d.reactMessage)\n ) {\n return null;\n }\n return {\n category: 'viewport-branching',\n confidence: 0.6,\n explanation:\n 'A whole subtree was added, removed, or swapped between server and ' +\n 'client — typically a JavaScript width/viewport check that branches ' +\n 'the tree at first render.',\n suggestion:\n 'Render both branches and switch between them with CSS media queries at ' +\n 'first paint instead of branching in JavaScript, or defer the ' +\n 'JS-driven branch until after mount.',\n docsUrl: docs('viewport-branching'),\n };\n};\n\nconst invalidNesting: Classifier = (d) => {\n const byMessage = messageIndicatesInvalidNesting(d.reactMessage);\n const byShape = isInvalidNesting(d.parentTagName, d.tagName);\n if (!byMessage && !byShape) return null;\n return {\n category: 'invalid-html-nesting',\n confidence: byMessage ? 0.9 : 0.72,\n explanation:\n 'A node was moved or ejected because the markup is invalid HTML ' +\n '(e.g. a `<div>` inside a `<p>`, or nested `<a>`). The browser repairs ' +\n 'the server DOM, so it no longer matches what React expects.',\n suggestion:\n 'Fix the markup validity: block elements cannot live inside `<p>`, ' +\n 'anchors cannot nest, etc. Replace the invalid parent with a `<div>` or ' +\n 'restructure the tree.',\n docsUrl: docs('invalid-html-nesting'),\n };\n};\n\nconst whitespaceMinification: Classifier = (d) => {\n if (d.kind !== 'text') return null;\n if (d.server == null || d.client == null) return null;\n if (d.server === d.client) return null;\n const collapse = (s: string) => s.replace(/\\s+/g, ' ').trim();\n if (collapse(d.server) !== collapse(d.client)) return null;\n return {\n category: 'whitespace-minification',\n confidence: 0.7,\n explanation:\n 'The mismatch is whitespace-only — the text is identical apart from ' +\n 'spaces/newlines. An HTML minifier likely collapsed whitespace around ' +\n 'the hydration root differently from React.',\n suggestion:\n 'Check your HTML minifier settings (e.g. `conservativeCollapse`) around ' +\n 'the app root, or avoid minifying whitespace inside hydrated markup.',\n docsUrl: docs('whitespace-minification'),\n };\n};\n\nconst thirdPartyDomMutation: Classifier = (d) => {\n if (d.kind === 'attribute' && d.attribute) {\n if (isExtensionAttribute(d.attribute)) {\n return {\n category: 'third-party-dom-mutation',\n confidence: 0.88,\n explanation:\n `The attribute \\`${d.attribute}\\` was injected by a browser ` +\n 'extension or third-party script (e.g. Grammarly, ColorZilla) ' +\n 'before hydration, so the client DOM no longer matches the server.',\n suggestion:\n 'This is usually harmless. Add `suppressHydrationWarning` to the ' +\n 'affected element, or defer third-party script init until after ' +\n 'hydration.',\n docsUrl: docs('third-party-dom-mutation'),\n };\n }\n const atRoot = /^(html|body)\\b/.test(d.path) && d.server == null;\n if (atRoot) {\n return {\n category: 'third-party-dom-mutation',\n confidence: 0.6,\n explanation:\n `An attribute (\\`${d.attribute}\\`) appeared on a root element that ` +\n 'the server never sent — a hallmark of an extension or early ' +\n 'third-party script mutating the DOM.',\n suggestion:\n 'Add `suppressHydrationWarning` to the root element, or defer the ' +\n 'third-party script until after hydration.',\n docsUrl: docs('third-party-dom-mutation'),\n };\n }\n }\n\n // An injected node (iframe/embed, or a known ads/consent/analytics/chat\n // marker) the server never rendered — not part of the app's hydration.\n if (\n (d.kind === 'node-added' || d.kind === 'node-removed') &&\n looksLikeThirdPartyNode(d.client ?? d.server, d.tagName)\n ) {\n const tag = (d.tagName ?? 'element').toLowerCase();\n return {\n category: 'third-party-dom-mutation',\n confidence: 0.7,\n explanation:\n `A <${tag}> was injected by a third-party script or browser extension ` +\n '(ads, consent, analytics, chat) after the server render. It is not ' +\n \"part of your app's hydration, so this is usually harmless noise.\",\n suggestion:\n 'If React warns about it, add `suppressHydrationWarning` to the ' +\n 'nearest server-rendered wrapper, or load the third-party script after ' +\n 'hydration (e.g. Next.js `<Script strategy=\"afterInteractive\">`).',\n docsUrl: docs('third-party-dom-mutation'),\n };\n }\n return null;\n};\n\n// Class / style / generic attribute mismatch that no value rule explained.\n// This is where the `forceHide` class-toggle case lands, with the exact tokens.\nconst attributeMismatch: Classifier = (d) => {\n if (d.kind !== 'attribute' || !d.attribute) return null;\n const attr = d.attribute.toLowerCase();\n const server = d.server ?? '';\n const client = d.client ?? '';\n\n if (attr === 'class' || attr === 'classname') {\n const serverSet = new Set(server.split(/\\s+/).filter(Boolean));\n const clientSet = new Set(client.split(/\\s+/).filter(Boolean));\n const added = [...clientSet].filter((c) => !serverSet.has(c));\n const removed = [...serverSet].filter((c) => !clientSet.has(c));\n const parts: string[] = [];\n if (added.length) parts.push(`added on client: ${added.join(', ')}`);\n if (removed.length) parts.push(`removed on client: ${removed.join(', ')}`);\n const detail = parts.length ? ` (${parts.join('; ')})` : '';\n return {\n category: 'attribute-mismatch',\n confidence: 0.8,\n explanation:\n `The \\`class\\` differs between server and client${detail}. A class was ` +\n 'applied conditionally on the client — commonly a viewport, media-query, ' +\n 'theme, or feature-flag check that runs during the first render.',\n suggestion:\n 'Render the same className on the server and the first client paint. ' +\n 'Move client-only conditions into `useEffect`/a mounted flag, or drive ' +\n 'the visual change with CSS media queries instead of a JS class toggle.',\n docsUrl: docs('attribute-mismatch'),\n };\n }\n\n if (attr === 'style') {\n return {\n category: 'attribute-mismatch',\n confidence: 0.75,\n explanation:\n 'The inline `style` differs between server and client — an inline ' +\n 'style was computed from client-only state (viewport size, theme, ' +\n 'scroll position) during render.',\n suggestion:\n 'Compute the style after mount (`useEffect`) so the first client render ' +\n 'matches the server, or move it to a CSS class / media query.',\n docsUrl: docs('attribute-mismatch'),\n };\n }\n\n return {\n category: 'attribute-mismatch',\n confidence: 0.6,\n explanation:\n `The \\`${d.attribute}\\` attribute differs between server (\\`${server}\\`) ` +\n `and client (\\`${client}\\`) — its value was derived from something that ` +\n 'differs between the server and the first client render.',\n suggestion:\n 'Make the attribute deterministic across server and client, or set it ' +\n 'after mount so the first client render matches the server HTML.',\n docsUrl: docs('attribute-mismatch'),\n };\n};\n\nexport const BUILT_IN_RULES: readonly Classifier[] = [\n nonDeterministic,\n dateTime,\n localeFormat,\n // Third-party runs before browser-only/viewport so an injected iframe is\n // labelled correctly instead of \"browser-only API\" or \"viewport branching\".\n thirdPartyDomMutation,\n browserOnlyApi,\n viewportBranching,\n invalidNesting,\n whitespaceMinification,\n // Catch-all for class/style/generic attribute diffs — after the specific\n // rules so extension attributes and content values are handled first.\n attributeMismatch,\n];\n\nexport const UNKNOWN_CAUSE: Cause = {\n category: 'unknown',\n confidence: 0,\n explanation:\n 'A hydration mismatch was detected but could not be matched to a known ' +\n 'cause. Inspect the server vs client values above.',\n suggestion:\n 'Compare the server and client values. Common causes are ' +\n 'non-deterministic values, dates/locales, and browser-only APIs used ' +\n 'during render.',\n docsUrl: docs('unknown'),\n};\n","import type { Cause, Classifier, Divergence } from '../types';\nimport { BUILT_IN_RULES, UNKNOWN_CAUSE } from './rules';\n\nexport const CONFIDENCE_THRESHOLD = 0.5;\n\nexport interface ClassifyOptions {\n extra?: readonly Classifier[];\n threshold?: number;\n}\n\nexport function classify(\n divergence: Divergence,\n options: ClassifyOptions = {},\n): Cause {\n const threshold = options.threshold ?? CONFIDENCE_THRESHOLD;\n const rules: readonly Classifier[] = [\n ...(options.extra ?? []),\n ...BUILT_IN_RULES,\n ];\n\n for (const rule of rules) {\n let result: Cause | null = null;\n try {\n result = rule(divergence);\n } catch {\n result = null;\n }\n if (result && result.confidence >= threshold) {\n return result;\n }\n }\n return UNKNOWN_CAUSE;\n}\n\nexport { BUILT_IN_RULES, UNKNOWN_CAUSE } from './rules';\n","import { classify, type ClassifyOptions } from './classify';\nimport type {\n Cause,\n DetectionContext,\n Divergence,\n HydrationReport,\n} from './types';\n\nexport type ReportSink = (report: HydrationReport) => void;\n\nlet counter = 0;\n\nfunction nextId(): string {\n counter += 1;\n return `wh_${Date.now().toString(36)}_${counter}`;\n}\n\nfunction truncate(value: string | null, max = 300): string | null {\n if (value == null) return null;\n return value.length > max ? `${value.slice(0, max)}…` : value;\n}\n\nexport function buildReport(\n divergence: Divergence,\n cause: Cause,\n context: DetectionContext = {},\n): HydrationReport {\n return {\n id: nextId(),\n timestamp: Date.now(),\n component: context.component,\n componentStack: context.componentStack,\n location: context.location,\n node: {\n path: divergence.path,\n tagName: divergence.tagName,\n attribute: divergence.attribute,\n kind: divergence.kind,\n },\n server: truncate(divergence.server),\n client: truncate(divergence.client),\n cause,\n raw: context.reactMessage\n ? { reactMessage: context.reactMessage }\n : undefined,\n };\n}\n\n// Deduplicate by the *values* of the mismatch, not the DOM path. The same\n// mismatch is often reported twice — once from React's console message (path\n// `body`) and once from the DOM diff (a precise selector path) — and those must\n// collapse into one report.\nexport function signatureOf(report: HydrationReport): string {\n return [\n report.node.kind,\n report.node.attribute ?? '',\n report.cause.category,\n report.server ?? '',\n report.client ?? '',\n ].join('|');\n}\n\nexport interface CollectorOptions extends ClassifyOptions {\n maxReports?: number;\n ignore?: (divergence: Divergence) => boolean;\n}\n\nexport class ReportCollector {\n private readonly seen = new Set<string>();\n private readonly sinks = new Set<ReportSink>();\n private readonly reports: HydrationReport[] = [];\n private readonly maxReports: number;\n private readonly options: CollectorOptions;\n\n constructor(options: CollectorOptions = {}) {\n this.options = options;\n this.maxReports = options.maxReports ?? 25;\n }\n\n addSink(sink: ReportSink): () => void {\n this.sinks.add(sink);\n return () => this.sinks.delete(sink);\n }\n\n getReports(): readonly HydrationReport[] {\n return this.reports;\n }\n\n get isFull(): boolean {\n return this.reports.length >= this.maxReports;\n }\n\n report(\n divergence: Divergence,\n context: DetectionContext = {},\n ): HydrationReport | null {\n if (this.isFull) return null;\n if (this.options.ignore?.(divergence)) return null;\n\n const cause = classify(divergence, {\n extra: this.options.extra,\n threshold: this.options.threshold,\n });\n const report = buildReport(divergence, cause, context);\n const signature = signatureOf(report);\n if (this.seen.has(signature)) return null;\n\n this.seen.add(signature);\n this.reports.push(report);\n for (const sink of this.sinks) {\n try {\n sink(report);\n } catch {\n /* a failing sink must not stop the others */\n }\n }\n return report;\n }\n\n reset(): void {\n this.seen.clear();\n this.reports.length = 0;\n }\n}\n","import type { Divergence } from './types';\n\nexport function isHydrationMessage(message: string): boolean {\n return (\n /hydrat/i.test(message) ||\n /did(?:n't| not) match/i.test(message) ||\n /won't be patched up/i.test(message) ||\n /hydration-mismatch/i.test(message) ||\n /server (?:HTML|rendered)/i.test(message) ||\n /validateDOMNesting/i.test(message) ||\n /Text content does not match/i.test(message)\n );\n}\n\nfunction stringify(v: unknown): string {\n return typeof v === 'string' ? v : String(v);\n}\n\nexport function formatConsoleArgs(args: readonly unknown[]): string {\n if (args.length === 0) return '';\n const [first, ...rest] = args;\n if (typeof first === 'string' && /%[sco]/.test(first)) {\n let i = 0;\n const expanded = first.replace(/%[sco]/g, () => stringify(rest[i++] ?? ''));\n const leftover = rest.slice(i).map(stringify).filter(Boolean);\n return [expanded, ...leftover].join('\\n').trim();\n }\n return args.map(stringify).join(' ');\n}\n\n// Next.js / React internal components we never want to name as the culprit.\nfunction isInternalComponent(name: string): boolean {\n return (\n /^(Inner|Outer|Segment|Client|Server|Redirect|Error|Loading|HTTPAccess|RenderFrom|ScrollAndFocus|Metadata|Outlet|ViewTransition|NotFound|Hot|DevRoot|App)$/.test(\n name,\n ) ||\n /^(Inner|Outer|Segment|Client|Server|Redirect|Error|Loading|HTTPAccess|RenderFrom|ScrollAndFocus|Metadata|Outlet|ViewTransition|NotFound|Hot|DevRoot)[A-Z]/.test(\n name,\n ) ||\n /(Boundary|Router|Handler|Provider|Context|Root|Node)$/.test(name) ||\n name === 'Fragment' ||\n name === 'Suspense'\n );\n}\n\n/** The nearest user component named in a React hydration diff tree. */\nexport function extractComponentFromMessage(\n message: string,\n): string | undefined {\n const names: string[] = [];\n const re = /<([A-Z][A-Za-z0-9_]*)\\b/g;\n let m: RegExpExecArray | null;\n while ((m = re.exec(message)) !== null) {\n const name = m[1];\n if (name && !isInternalComponent(name)) names.push(name);\n }\n return names.length ? names[names.length - 1] : undefined;\n}\n\nconst ATTR_RE = /^([\\w:-]+)=(?:\"([\\s\\S]*)\"|\\{([\\s\\S]*)\\})$/;\n\n/**\n * Modern React (18.3+/19) prints hydration mismatches as a JSX diff tree with\n * `+` (client) and `-` (server) lines. This extracts the changed attribute or\n * text and both values.\n */\nfunction parseModernDiff(message: string): Divergence | null {\n const plus: string[] = [];\n const minus: string[] = [];\n for (const raw of message.split('\\n')) {\n const line = raw.trim();\n const p = /^\\+\\s+(.+)$/.exec(line);\n const mn = /^-\\s+(.+)$/.exec(line);\n if (p && p[1]) plus.push(p[1].trim());\n else if (mn && mn[1]) minus.push(mn[1].trim());\n }\n if (plus.length === 0 && minus.length === 0) return null;\n\n // Prefer a matching attribute pair (same attribute on + and -).\n for (const p of plus) {\n const pm = ATTR_RE.exec(p);\n if (!pm) continue;\n const name = pm[1];\n const clientValue = pm[2] ?? pm[3] ?? '';\n const matched = minus.find((mm) => {\n const parsed = ATTR_RE.exec(mm);\n return parsed && parsed[1] === name;\n });\n if (matched) {\n const parsed = ATTR_RE.exec(matched);\n const serverValue = parsed ? (parsed[2] ?? parsed[3] ?? '') : '';\n return {\n kind: 'attribute',\n path: 'body',\n attribute: name,\n server: serverValue,\n client: clientValue,\n reactMessage: message,\n };\n }\n }\n\n // Otherwise a text/content change: pick the non-attribute lines.\n const client = plus.find((p) => !ATTR_RE.test(p)) ?? null;\n const server = minus.find((m) => !ATTR_RE.test(m)) ?? null;\n if (client !== null || server !== null) {\n return {\n kind: 'text',\n path: 'body',\n server,\n client,\n reactMessage: message,\n };\n }\n return null;\n}\n\nexport function parseHydrationMessage(message: string): Divergence | null {\n if (!isHydrationMessage(message)) return null;\n\n // Invalid nesting is reported as its own message in every React version.\n const nesting =\n /<(\\w+)>\\s*cannot (?:appear as a|be a|contain a) (?:child|descendant)/i.exec(\n message,\n );\n if (nesting || /validateDOMNesting/i.test(message)) {\n const pair =\n /<(\\w+)>\\s*cannot (?:appear as a|be a) (?:child|descendant) of <?(\\w+)>?/i.exec(\n message,\n );\n return {\n kind: 'structure',\n path: 'body',\n tagName: pair ? pair[1]?.toUpperCase() : undefined,\n parentTagName: pair ? pair[2]?.toUpperCase() : undefined,\n server: null,\n client: null,\n reactMessage: message,\n };\n }\n\n // Modern diff-tree format (React 18.3+/19).\n const modern = parseModernDiff(message);\n if (modern) return modern;\n\n // Legacy explicit formats (React <18.3).\n const text =\n /Text content (?:did not match|does not match)[^:]*Server:\\s*\"?(.*?)\"?\\s+Client:\\s*\"?(.*?)\"?\\s*$/i.exec(\n message,\n );\n if (text) {\n return {\n kind: 'text',\n path: 'body',\n server: text[1] ?? null,\n client: text[2] ?? null,\n reactMessage: message,\n };\n }\n\n const prop =\n /Prop [`'\"]([^`'\"]+)[`'\"] did not match\\.?\\s*Server:\\s*\"?(.*?)\"?\\s+Client:\\s*\"?(.*?)\"?\\s*$/i.exec(\n message,\n );\n if (prop) {\n return {\n kind: 'attribute',\n path: 'body',\n attribute: prop[1],\n server: prop[2] ?? null,\n client: prop[3] ?? null,\n reactMessage: message,\n };\n }\n\n const expected =\n /Expected server HTML to contain a matching <(\\w+)>(?: in <(\\w+)>)?/i.exec(\n message,\n );\n if (expected) {\n return {\n kind: 'node-added',\n path: 'body',\n tagName: expected[1]?.toUpperCase(),\n parentTagName: expected[2]?.toUpperCase(),\n server: null,\n client: `<${expected[1]?.toLowerCase()}>`,\n reactMessage: message,\n };\n }\n const notExpected =\n /Did not expect server HTML to contain(?: the text node)?(?: a)? <?(\\w+)>?/i.exec(\n message,\n );\n if (notExpected) {\n return {\n kind: 'node-removed',\n path: 'body',\n tagName: notExpected[1]?.toUpperCase(),\n server: `<${notExpected[1]?.toLowerCase()}>`,\n client: null,\n reactMessage: message,\n };\n }\n\n return {\n kind: 'structure',\n path: 'body',\n server: null,\n client: null,\n reactMessage: message,\n };\n}\n","import { diffSnapshotAgainstDom } from './diff';\nimport {\n extractComponentFromMessage,\n parseHydrationMessage,\n} from './react-message';\nimport { getServerHtmlForRoot } from './snapshot';\nimport type { DetectionContext, Divergence } from './types';\nimport type { ReportCollector } from './report';\n\nexport function inspectRoot(\n root: Element,\n collector: ReportCollector,\n context: DetectionContext = {},\n enrich?: (divergence: Divergence) => DetectionContext,\n): boolean {\n const serverHtml = getServerHtmlForRoot(root);\n if (serverHtml == null) return false;\n const divergence = diffSnapshotAgainstDom(serverHtml, root);\n if (!divergence) return false;\n if (context.reactMessage && !divergence.reactMessage) {\n divergence.reactMessage = context.reactMessage;\n }\n const enriched = enrich ? enrich(divergence) : {};\n return collector.report(divergence, { ...context, ...enriched }) != null;\n}\n\nexport function reportFromMessage(\n message: string,\n collector: ReportCollector,\n context: DetectionContext = {},\n): boolean {\n const divergence = parseHydrationMessage(message);\n if (!divergence) return false;\n return (\n collector.report(divergence, {\n ...context,\n component: extractComponentFromMessage(message) ?? context.component,\n reactMessage: message,\n }) != null\n );\n}\n"]}
|