@cfp-studio/iframe 18.3.0 → 18.4.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cfp-studio/iframe",
3
- "version": "18.3.0",
3
+ "version": "18.4.0",
4
4
  "license": "MIT",
5
5
  "files": [
6
6
  "dist",
@@ -10,7 +10,7 @@
10
10
  "main": "./dist/index.mjs",
11
11
  "types": "./dist/index.d.mts",
12
12
  "dependencies": {
13
- "@cfp-studio/fiber-reader": "0.2.0"
13
+ "@cfp-studio/fiber-reader": "0.3.0"
14
14
  },
15
15
  "devDependencies": {
16
16
  "assert-never": "1.4.0",
@@ -20,6 +20,7 @@ import {
20
20
  type RuntimeNode,
21
21
  type RuntimeNodeDetail,
22
22
  type RuntimeSnapshot,
23
+ defaultStyleKeys,
23
24
  summarizeComputedStyle,
24
25
  type RuntimeSourceLocation,
25
26
  } from "@cfp-studio/fiber-reader";
@@ -332,6 +333,41 @@ function walk(element: Element | null, parentId: string | undefined, path: strin
332
333
  return truncated;
333
334
  }
334
335
 
336
+ /**
337
+ * 初始值基线缓存:tag → 参考元素的 computed style 摘要。
338
+ *
339
+ * 参考元素放在 shadow root 里(作者样式匹配不到影子树内部),并显式 `all: initial`,
340
+ * 因此拿到的是**纯 CSS 初始值**:不继承页面、也不被任何作者规则命中。
341
+ */
342
+ const baselineCache = new Map<string, Record<string, string>>();
343
+ let baselineHost: HTMLElement | undefined;
344
+
345
+ function measureBaseline(tagName: string): Record<string, string> {
346
+ const tag = tagName.toLowerCase();
347
+ const cached = baselineCache.get(tag);
348
+ if (cached) {
349
+ return cached;
350
+ }
351
+ if (!baselineHost) {
352
+ baselineHost = document.createElement("div");
353
+ baselineHost.setAttribute("aria-hidden", "true");
354
+ baselineHost.style.cssText =
355
+ "position:absolute;left:-9999px;top:0;width:0;height:0;overflow:hidden;visibility:hidden;pointer-events:none;";
356
+ document.body.appendChild(baselineHost);
357
+ }
358
+ const root = baselineHost.shadowRoot ?? baselineHost.attachShadow({ mode: "open" });
359
+ root.replaceChildren();
360
+ const reference = document.createElement(tag);
361
+ // `all: initial` 让参考元素回到 **CSS 初始值**(不继承宿主、也不被作者规则命中):
362
+ // 否则作者写 `div { letter-spacing: 2px }` 时,参考元素会通过继承拿到同一个值,
363
+ // 把用户真正设置的属性误判成默认值。
364
+ reference.style.all = "initial";
365
+ root.appendChild(reference);
366
+ const summary = summarizeComputedStyle(window.getComputedStyle(reference));
367
+ baselineCache.set(tag, summary);
368
+ return summary;
369
+ }
370
+
335
371
  function collectRuntimeNodeDetail(runtimeNodeId: string): RuntimeNodeDetail | undefined {
336
372
  const element = nodeElements.get(runtimeNodeId);
337
373
  if (!element) {
@@ -345,6 +381,7 @@ function collectRuntimeNodeDetail(runtimeNodeId: string): RuntimeNodeDetail | un
345
381
  }
346
382
  const text = (element.textContent ?? "").replace(/\s+/g, " ").trim();
347
383
  const outerHTML = element.outerHTML;
384
+ const computedStyle = summarizeComputedStyle(window.getComputedStyle(element));
348
385
  return {
349
386
  runtimeNodeId,
350
387
  bounds: { x: rect.x, y: rect.y, width: rect.width, height: rect.height },
@@ -355,7 +392,8 @@ function collectRuntimeNodeDetail(runtimeNodeId: string): RuntimeNodeDetail | un
355
392
  scrollY: window.scrollY,
356
393
  devicePixelRatio: window.devicePixelRatio,
357
394
  },
358
- computedStyle: summarizeComputedStyle(window.getComputedStyle(element)),
395
+ computedStyle,
396
+ computedStyleDefaults: defaultStyleKeys(computedStyle, measureBaseline(element.tagName)),
359
397
  dom: {
360
398
  tag: element.tagName.toLowerCase(),
361
399
  id: element.id || undefined,
@@ -408,6 +446,8 @@ function publishComputedStyle(subscription: ComputedStyleSubscription): void {
408
446
  kind: "cfp-computed-style",
409
447
  runtimeNodeId: subscription.runtimeNodeId,
410
448
  computedStyle,
449
+ computedStyleDefaults:
450
+ element && computedStyle ? defaultStyleKeys(computedStyle, measureBaseline(element.tagName)) : [],
411
451
  capturedAt: Date.now(),
412
452
  });
413
453
  }