chore: update audit script - different resolutions

This commit is contained in:
2026-08-30 20:59:16 +05:00
parent 2d72848e8e
commit 87dbb200d9
10 changed files with 16316 additions and 135 deletions
+1 -1
View File
@@ -9,7 +9,7 @@
"build": "pnpm --dir web build", "build": "pnpm --dir web build",
"format": "pnpm --dir web format", "format": "pnpm --dir web format",
"html": "pnpm --dir refs build && node scripts/extract-static.mjs refs/.next/server/app refs-html", "html": "pnpm --dir refs build && node scripts/extract-static.mjs refs/.next/server/app refs-html",
"dom-audit": "pnpm --dir web refs-dom-audit" "cdp-audit": "pnpm --dir web refs-cdp-audit:responsive"
}, },
"keywords": [], "keywords": [],
"author": "Ku6epXBOCTuK", "author": "Ku6epXBOCTuK",
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+13 -93
View File
@@ -1,8 +1,8 @@
CDP visual audit CDP visual audit
2026-08-30T06:21:12.002Z 2026-08-30T09:31:56.937Z
viewport 1440x900, tolerance 1px, theme light viewport 1440x900, tolerance 1px, theme light
=== /preview/demo (vs demo.html) — 173 differences === === [1440x900] /preview/demo (vs demo.html) — 173 differences ===
body > main > header [topbar] body > main > header [topbar]
position: — → sticky position: — → sticky
@@ -13,8 +13,6 @@ body > main > header > a > span:nth-of-type(3) [version] "/ WORKSPACE"
color: #6d7883 [var(--muted)] → #1769d2 [var(--blue)] color: #6d7883 [var(--muted)] → #1769d2 [var(--blue)]
body > main > header > div > span > i [status-dot] body > main > header > div > span > i [status-dot]
w: 6 → 8 (+2px)
h: 6 → 8 (+2px)
width: 6px → 8px width: 6px → 8px
height: 6px → 8px height: 6px → 8px
box-shadow: — → 0 0 0 2px color-mix(in srgb, #25a96a 25%, transparent) [0 0 0 2px color-mix(in srgb, var(--success) 25%, transparent)] box-shadow: — → 0 0 0 2px color-mix(in srgb, #25a96a 25%, transparent) [0 0 0 2px color-mix(in srgb, var(--success) 25%, transparent)]
@@ -99,7 +97,6 @@ body > main > div > section:nth-of-type(2) > div:nth-of-type(2) [preview-stack]
min-width: 0px → — min-width: 0px → —
body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(1) [preview-tile] body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(1) [preview-tile]
w: 276.3 → 564.7 (+288.4px)
display: — → flex display: — → flex
flex-direction: — → column flex-direction: — → column
row-gap: — → 0.3rem row-gap: — → 0.3rem
@@ -112,7 +109,6 @@ body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-typ
min-width: 0px → — min-width: 0px → —
body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(1) > div:nth-of-type(1) [tile-canvas] body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(1) > div:nth-of-type(1) [tile-canvas]
w: 274.3 → 549.9 (+275.6px)
display: grid → — display: grid → —
align-items: center → — align-items: center → —
padding-top: 16px → — padding-top: 16px → —
@@ -127,9 +123,9 @@ body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-typ
background-size: 14px 14px → — background-size: 14px 14px → —
body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(1) > div:nth-of-type(1) > div [ph] body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(1) > div:nth-of-type(1) > div [ph]
w: 193.9 → 439.9 (+246px)
min-width: 0px → — min-width: 0px → —
max-width: 100% → — max-width: 100% → —
w: 193.9 → 439.9 (+246px)
body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(1) > div:nth-of-type(2) [tile-label] body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(1) > div:nth-of-type(2) [tile-label]
align-items: — → baseline align-items: — → baseline
@@ -152,7 +148,6 @@ body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-typ
text-align: right → — text-align: right → —
body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(2) [preview-tile] body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(2) [preview-tile]
w: 276.3 → 564.7 (+288.4px)
display: — → flex display: — → flex
flex-direction: — → column flex-direction: — → column
row-gap: — → 0.3rem row-gap: — → 0.3rem
@@ -165,7 +160,6 @@ body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-typ
min-width: 0px → — min-width: 0px → —
body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(1) [tile-canvas] body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(1) [tile-canvas]
w: 274.3 → 549.9 (+275.6px)
display: grid → — display: grid → —
align-items: center → — align-items: center → —
padding-top: 16px → — padding-top: 16px → —
@@ -180,9 +174,9 @@ body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-typ
background-size: 14px 14px → — background-size: 14px 14px → —
body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(1) > div [ph] body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(1) > div [ph]
w: 193.9 → 439.9 (+246px)
min-width: 0px → — min-width: 0px → —
max-width: 100% → — max-width: 100% → —
w: 193.9 → 439.9 (+246px)
body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(2) [tile-label] body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(2) [tile-label]
align-items: — → baseline align-items: — → baseline
@@ -205,7 +199,6 @@ body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-typ
text-align: right → — text-align: right → —
body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(3) [preview-tile] body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(3) [preview-tile]
w: 276.3 → 564.7 (+288.4px)
display: — → flex display: — → flex
flex-direction: — → column flex-direction: — → column
row-gap: — → 0.3rem row-gap: — → 0.3rem
@@ -218,7 +211,6 @@ body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-typ
min-width: 0px → — min-width: 0px → —
body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(3) > div:nth-of-type(1) [tile-canvas] body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(3) > div:nth-of-type(1) [tile-canvas]
w: 274.3 → 549.9 (+275.6px)
display: grid → — display: grid → —
align-items: center → — align-items: center → —
padding-top: 16px → — padding-top: 16px → —
@@ -233,9 +225,9 @@ body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-typ
background-size: 14px 14px → — background-size: 14px 14px → —
body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(3) > div:nth-of-type(1) > div [ph] body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(3) > div:nth-of-type(1) > div [ph]
w: 193.9 → 439.9 (+246px)
min-width: 0px → — min-width: 0px → —
max-width: 100% → — max-width: 100% → —
w: 193.9 → 439.9 (+246px)
body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(3) > div:nth-of-type(2) [tile-label] body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(3) > div:nth-of-type(2) [tile-label]
align-items: — → baseline align-items: — → baseline
@@ -258,7 +250,6 @@ body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-typ
text-align: right → — text-align: right → —
body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(4) [preview-tile] body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(4) [preview-tile]
w: 276.3 → 564.7 (+288.4px)
display: — → flex display: — → flex
flex-direction: — → column flex-direction: — → column
row-gap: — → 0.3rem row-gap: — → 0.3rem
@@ -271,7 +262,6 @@ body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-typ
min-width: 0px → — min-width: 0px → —
body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(4) > div:nth-of-type(1) [tile-canvas] body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(4) > div:nth-of-type(1) [tile-canvas]
w: 274.3 → 549.9 (+275.6px)
display: grid → — display: grid → —
align-items: center → — align-items: center → —
padding-top: 16px → — padding-top: 16px → —
@@ -286,9 +276,9 @@ body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-typ
background-size: 14px 14px → — background-size: 14px 14px → —
body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(4) > div:nth-of-type(1) > div [ph] body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(4) > div:nth-of-type(1) > div [ph]
w: 193.9 → 439.9 (+246px)
min-width: 0px → — min-width: 0px → —
max-width: 100% → — max-width: 100% → —
w: 193.9 → 439.9 (+246px)
body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(4) > div:nth-of-type(2) [tile-label] body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(4) > div:nth-of-type(2) [tile-label]
align-items: — → baseline align-items: — → baseline
@@ -311,7 +301,6 @@ body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-typ
text-align: right → — text-align: right → —
body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(5) [preview-tile] body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(5) [preview-tile]
w: 276.3 → 564.7 (+288.4px)
display: — → flex display: — → flex
flex-direction: — → column flex-direction: — → column
row-gap: — → 0.3rem row-gap: — → 0.3rem
@@ -324,7 +313,6 @@ body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-typ
min-width: 0px → — min-width: 0px → —
body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(5) > div:nth-of-type(1) [tile-canvas] body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(5) > div:nth-of-type(1) [tile-canvas]
w: 274.3 → 549.9 (+275.6px)
display: grid → — display: grid → —
align-items: center → — align-items: center → —
padding-top: 16px → — padding-top: 16px → —
@@ -339,9 +327,9 @@ body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-typ
background-size: 14px 14px → — background-size: 14px 14px → —
body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(5) > div:nth-of-type(1) > div [active ph] body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(5) > div:nth-of-type(1) > div [active ph]
w: 193.9 → 439.9 (+246px)
min-width: 0px → — min-width: 0px → —
max-width: 100% → — max-width: 100% → —
w: 193.9 → 439.9 (+246px)
body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(5) > div:nth-of-type(2) [tile-label] body > main > div > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(5) > div:nth-of-type(2) [tile-label]
align-items: — → baseline align-items: — → baseline
@@ -381,8 +369,6 @@ body > main > div > section:nth-of-type(2) > div:nth-of-type(1) > div:nth-of-typ
text-transform: — → uppercase text-transform: — → uppercase
body > main > div > section:nth-of-type(2) > div:nth-of-type(1) > div:nth-of-type(2) > button:nth-of-type(2) [download-btn] "Download result" body > main > div > section:nth-of-type(2) > div:nth-of-type(1) > div:nth-of-type(2) > button:nth-of-type(2) [download-btn] "Download result"
w: 478.1 → 191.2 (-286.9px)
h: 42 → 36 (-6px)
display: flex → inline-flex display: flex → inline-flex
justify-content: center → — justify-content: center → —
row-gap: 9px → 8px row-gap: 9px → 8px
@@ -406,7 +392,6 @@ body > main > div > section:nth-of-type(2) > div:nth-of-type(1) > div:nth-of-typ
letter-spacing: — → 0.04em letter-spacing: — → 0.04em
body > main > div > section:nth-of-type(2) > div:nth-of-type(1) > div:nth-of-type(2) > button:nth-of-type(1) [history-toggle] "Hide intermediate" body > main > div > section:nth-of-type(2) > div:nth-of-type(1) > div:nth-of-type(2) > button:nth-of-type(1) [history-toggle] "Hide intermediate"
w: 145.3 → 456.2 (+310.9px)
margin-top: 0px → 18px margin-top: 0px → 18px
margin-right: 0px → — margin-right: 0px → —
margin-bottom: 0px → — margin-bottom: 0px → —
@@ -483,8 +468,6 @@ body > main > div > section:nth-of-type(2) > div:nth-of-type(1) > div:nth-of-typ
line-height: — → 1.5 line-height: — → 1.5
body > main > div > section:nth-of-type(2) > div:nth-of-type(1) > div:nth-of-type(2) > button:nth-of-type(3) [icon-btn icon-btn--ghost] body > main > div > section:nth-of-type(2) > div:nth-of-type(1) > div:nth-of-type(2) > button:nth-of-type(3) [icon-btn icon-btn--ghost]
w: 29 → 32 (+3px)
h: 29 → 32 (+3px)
display: grid → inline-flex display: grid → inline-flex
justify-content: — → center justify-content: — → center
padding-top: 6px → — padding-top: 6px → —
@@ -608,7 +591,6 @@ body > main > div > section:nth-of-type(1) > div:nth-of-type(4) > article:nth-of
text-transform: — → uppercase text-transform: — → uppercase
body > main > div > section:nth-of-type(1) > div:nth-of-type(4) > article:nth-of-type(1) > div:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(1) > div [color-field] body > main > div > section:nth-of-type(1) > div:nth-of-type(4) > article:nth-of-type(1) > div:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(1) > div [color-field]
h: 32 → 27.2 (-4.8px)
row-gap: 8px → 0.4rem row-gap: 8px → 0.4rem
column-gap: 8px → 0.4rem column-gap: 8px → 0.4rem
padding-right: 8px → — padding-right: 8px → —
@@ -616,8 +598,6 @@ body > main > div > section:nth-of-type(1) > div:nth-of-type(4) > article:nth-of
height: 32px → — height: 32px → —
body > main > div > section:nth-of-type(1) > div:nth-of-type(4) > article:nth-of-type(1) > div:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(1) > div > span [swatch] body > main > div > section:nth-of-type(1) > div:nth-of-type(4) > article:nth-of-type(1) > div:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(1) > div > span [swatch]
w: 14 → 25.6 (+11.6px)
h: 14 → 25.6 (+11.6px)
width: 14px → 1.6rem width: 14px → 1.6rem
height: 14px → 1.6rem height: 14px → 1.6rem
@@ -655,9 +635,9 @@ body > main > div > section:nth-of-type(1) > div:nth-of-type(4) > article:nth-of
text-transform: — → uppercase text-transform: — → uppercase
body > main > div > section:nth-of-type(1) > div:nth-of-type(4) > article:nth-of-type(1) > div:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(2) > input body > main > div > section:nth-of-type(1) > div:nth-of-type(4) > article:nth-of-type(1) > div:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(2) > input
w: 155 → 190 (+35px)
font-size: inherit → 16px font-size: inherit → 16px
line-height: inherit → 1.5 line-height: inherit → 1.5
w: 155 → 190 (+35px)
body > main > div > section:nth-of-type(1) > div:nth-of-type(4) > article:nth-of-type(1) > div:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(3) [control-block] body > main > div > section:nth-of-type(1) > div:nth-of-type(4) > article:nth-of-type(1) > div:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(3) [control-block]
display: — → flex display: — → flex
@@ -896,9 +876,9 @@ body > main > div > section:nth-of-type(1) > div:nth-of-type(4) > article:nth-of
text-transform: — → uppercase text-transform: — → uppercase
body > main > div > section:nth-of-type(1) > div:nth-of-type(4) > article:nth-of-type(3) > div:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(1) > input body > main > div > section:nth-of-type(1) > div:nth-of-type(4) > article:nth-of-type(3) > div:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(1) > input
w: 273.1 → 301.1 (+28px)
font-size: inherit → 16px font-size: inherit → 16px
line-height: inherit → 1.5 line-height: inherit → 1.5
w: 273.1 → 301.1 (+28px)
body > main > div > section:nth-of-type(1) > div:nth-of-type(4) > article:nth-of-type(3) > div:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(2) [control-block] body > main > div > section:nth-of-type(1) > div:nth-of-type(4) > article:nth-of-type(3) > div:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(2) [control-block]
display: — → flex display: — → flex
@@ -916,7 +896,6 @@ body > main > div > section:nth-of-type(1) > div:nth-of-type(4) > article:nth-of
text-transform: — → uppercase text-transform: — → uppercase
body > main > div > section:nth-of-type(1) > div:nth-of-type(4) > article:nth-of-type(3) > div:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(2) > div [color-field] body > main > div > section:nth-of-type(1) > div:nth-of-type(4) > article:nth-of-type(3) > div:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(2) > div [color-field]
h: 32 → 27.2 (-4.8px)
row-gap: 8px → 0.4rem row-gap: 8px → 0.4rem
column-gap: 8px → 0.4rem column-gap: 8px → 0.4rem
padding-right: 8px → — padding-right: 8px → —
@@ -924,8 +903,6 @@ body > main > div > section:nth-of-type(1) > div:nth-of-type(4) > article:nth-of
height: 32px → — height: 32px → —
body > main > div > section:nth-of-type(1) > div:nth-of-type(4) > article:nth-of-type(3) > div:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(2) > div > span [dark swatch] body > main > div > section:nth-of-type(1) > div:nth-of-type(4) > article:nth-of-type(3) > div:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(2) > div > span [dark swatch]
w: 14 → 25.6 (+11.6px)
h: 14 → 25.6 (+11.6px)
width: 14px → 1.6rem width: 14px → 1.6rem
height: 14px → 1.6rem height: 14px → 1.6rem
@@ -1038,9 +1015,9 @@ body > main > div > section:nth-of-type(1) > div:nth-of-type(4) > article:nth-of
text-transform: — → uppercase text-transform: — → uppercase
body > main > div > section:nth-of-type(1) > div:nth-of-type(4) > article:nth-of-type(4) > div:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(1) > input body > main > div > section:nth-of-type(1) > div:nth-of-type(4) > article:nth-of-type(4) > div:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(1) > input
w: 273.1 → 301.1 (+28px)
font-size: inherit → 16px font-size: inherit → 16px
line-height: inherit → 1.5 line-height: inherit → 1.5
w: 273.1 → 301.1 (+28px)
body > main > div > section:nth-of-type(1) > div:nth-of-type(4) > article:nth-of-type(4) > div:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(2) [toggle-row] body > main > div > section:nth-of-type(1) > div:nth-of-type(4) > article:nth-of-type(4) > div:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(2) [toggle-row]
display: — → flex display: — → flex
@@ -1058,18 +1035,12 @@ body > main > div > section:nth-of-type(1) > div:nth-of-type(4) > article:nth-of
line-height: — → 1.5 line-height: — → 1.5
body > main > div > section:nth-of-type(1) > div:nth-of-type(4) > article:nth-of-type(4) > div:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(2) > button [on toggle] body > main > div > section:nth-of-type(1) > div:nth-of-type(4) > article:nth-of-type(4) > div:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(2) > button [on toggle]
w: 32 → 38.4 (+6.4px)
h: 18 → 20.8 (+2.8px)
width: 32px → 2.4rem width: 32px → 2.4rem
height: 18px → 1.3rem height: 18px → 1.3rem
font-size: inherit → 0.85rem font-size: inherit → 0.85rem
line-height: inherit → 1.5 line-height: inherit → 1.5
body > main > div > section:nth-of-type(1) > div:nth-of-type(4) > article:nth-of-type(4) > div:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(2) > button > i [toggle-knob] body > main > div > section:nth-of-type(1) > div:nth-of-type(4) > article:nth-of-type(4) > div:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(2) > button > i [toggle-knob]
x: 603.3 → 703.9 (+100.6px)
y: 1027.4 → 951.6 (-75.8px)
w: 0 → 16.8 (+16.8px)
h: 0 → 16.8 (+16.8px)
position: — → absolute position: — → absolute
top: — → 1px top: — → 1px
left: — → 1px left: — → 1px
@@ -1087,8 +1058,6 @@ body > main > div > section:nth-of-type(1) > div:nth-of-type(5) > button > svg
line-height: inherit → 1.5 line-height: inherit → 1.5
body > main > div > section:nth-of-type(1) > div:nth-of-type(5) > span > i [status-dot] body > main > div > section:nth-of-type(1) > div:nth-of-type(5) > span > i [status-dot]
w: 6 → 8 (+2px)
h: 6 → 8 (+2px)
width: 6px → 8px width: 6px → 8px
height: 6px → 8px height: 6px → 8px
box-shadow: — → 0 0 0 2px color-mix(in srgb, #25a96a 25%, transparent) [0 0 0 2px color-mix(in srgb, var(--success) 25%, transparent)] box-shadow: — → 0 0 0 2px color-mix(in srgb, #25a96a 25%, transparent) [0 0 0 2px color-mix(in srgb, var(--success) 25%, transparent)]
@@ -1150,7 +1119,7 @@ body >div
✗ present in reference, absent in project ✗ present in reference, absent in project
=== /preview/list-tools (vs list-tools.html) — 126 differences === === [1440x900] /preview/list-tools (vs list-tools.html) — 126 differences ===
body > main > header [topbar] body > main > header [topbar]
position: — → sticky position: — → sticky
@@ -1161,8 +1130,6 @@ body > main > header > a > span:nth-of-type(3) [version] "/ CATALOG"
color: #6d7883 [var(--muted)] → #1769d2 [var(--blue)] color: #6d7883 [var(--muted)] → #1769d2 [var(--blue)]
body > main > header > div > span > i [status-dot] body > main > header > div > span > i [status-dot]
w: 6 → 8 (+2px)
h: 6 → 8 (+2px)
width: 6px → 8px width: 6px → 8px
height: 6px → 8px height: 6px → 8px
box-shadow: — → 0 0 0 2px color-mix(in srgb, #25a96a 25%, transparent) [0 0 0 2px color-mix(in srgb, var(--success) 25%, transparent)] box-shadow: — → 0 0 0 2px color-mix(in srgb, #25a96a 25%, transparent) [0 0 0 2px color-mix(in srgb, var(--success) 25%, transparent)]
@@ -1299,7 +1266,6 @@ body > main > div > div:nth-of-type(2) [catalog-toolbar]
padding-bottom: 42px → 1.25rem padding-bottom: 42px → 1.25rem
body > main > div > div:nth-of-type(2) > label [catalog-search] body > main > div > div:nth-of-type(2) > label [catalog-search]
w: 420 → 202 (-218px)
display: flex → inline-flex display: flex → inline-flex
row-gap: 12px → 0.5rem row-gap: 12px → 0.5rem
column-gap: 12px → 0.5rem column-gap: 12px → 0.5rem
@@ -1310,7 +1276,6 @@ body > main > div > div:nth-of-type(2) > label [catalog-search]
width: min(420px, 100%) → — width: min(420px, 100%) → —
body > main > div > div:nth-of-type(2) > label > input body > main > div > div:nth-of-type(2) > label > input
w: 363.1 → 152 (-211.1px)
width: 100% → — width: 100% → —
border-top-width: 0px → medium border-top-width: 0px → medium
@@ -1836,7 +1801,7 @@ body >div
✗ present in reference, absent in project ✗ present in reference, absent in project
=== /preview/tools/linear-gradient-png (vs gradient.html) — 92 differences === === [1440x900] /preview/tools/linear-gradient-png (vs gradient.html) — 92 differences ===
body > main > header [topbar] body > main > header [topbar]
position: — → sticky position: — → sticky
@@ -1847,8 +1812,6 @@ body > main > header > a > span:nth-of-type(3) [version] "/ GRADIENT"
color: #6d7883 [var(--muted)] → #1769d2 [var(--blue)] color: #6d7883 [var(--muted)] → #1769d2 [var(--blue)]
body > main > header > div > span > i [status-dot] body > main > header > div > span > i [status-dot]
w: 6 → 8 (+2px)
h: 6 → 8 (+2px)
width: 6px → 8px width: 6px → 8px
height: 6px → 8px height: 6px → 8px
box-shadow: — → 0 0 0 2px color-mix(in srgb, #25a96a 25%, transparent) [0 0 0 2px color-mix(in srgb, var(--success) 25%, transparent)] box-shadow: — → 0 0 0 2px color-mix(in srgb, #25a96a 25%, transparent) [0 0 0 2px color-mix(in srgb, var(--success) 25%, transparent)]
@@ -1985,8 +1948,6 @@ body > main > div > div:nth-of-type(2) > span [tool-status] "LIVE PREVIEW"
line-height: — → 1.5 line-height: — → 1.5
body > main > div > div:nth-of-type(2) > span > i body > main > div > div:nth-of-type(2) > span > i
w: 6 → 0 (-6px)
h: 6 → 20 (+14px)
width: 6px → — width: 6px → —
height: 6px → — height: 6px → —
background-color: rgb(37, 169, 106) → — background-color: rgb(37, 169, 106) → —
@@ -2049,8 +2010,6 @@ body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-typ
letter-spacing: 0.1em → — letter-spacing: 0.1em → —
body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-type(2) > div [segmented wide] body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-type(2) > div [segmented wide]
w: 402.1 → 1440 (+1037.9px)
h: 32 → 25 (-7px)
display: flex → — display: flex → —
width: 100% → — width: 100% → —
height: 32px → — height: 32px → —
@@ -2095,7 +2054,6 @@ body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-typ
column-gap: 10px → — column-gap: 10px → —
body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-type(3) > div:nth-of-type(1) > div:nth-of-type(1) [color-field] body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-type(3) > div:nth-of-type(1) > div:nth-of-type(1) [color-field]
h: 32 → 25 (-7px)
display: flex → — display: flex → —
align-items: center → — align-items: center → —
row-gap: 8px → — row-gap: 8px → —
@@ -2105,8 +2063,6 @@ body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-typ
height: 32px → — height: 32px → —
body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-type(3) > div:nth-of-type(1) > div:nth-of-type(1) > span [swatch] body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-type(3) > div:nth-of-type(1) > div:nth-of-type(1) > span [swatch]
w: 14 → 0 (-14px)
h: 14 → 20 (+6px)
width: 14px → — width: 14px → —
height: 14px → — height: 14px → —
@@ -2123,7 +2079,6 @@ body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-typ
color: #6d7883 [var(--muted)] → #17212b [var(--foreground)] color: #6d7883 [var(--muted)] → #17212b [var(--foreground)]
body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-type(3) > div:nth-of-type(1) > div:nth-of-type(2) [color-field] body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-type(3) > div:nth-of-type(1) > div:nth-of-type(2) [color-field]
h: 32 → 25 (-7px)
display: flex → — display: flex → —
align-items: center → — align-items: center → —
row-gap: 8px → — row-gap: 8px → —
@@ -2133,8 +2088,6 @@ body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-typ
height: 32px → — height: 32px → —
body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-type(3) > div:nth-of-type(1) > div:nth-of-type(2) > span [swatch] body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-type(3) > div:nth-of-type(1) > div:nth-of-type(2) > span [swatch]
w: 14 → 0 (-14px)
h: 14 → 20 (+6px)
width: 14px → — width: 14px → —
height: 14px → — height: 14px → —
@@ -2148,7 +2101,6 @@ body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-typ
font-size: — → 16px font-size: — → 16px
body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-type(3) > div:nth-of-type(2) [gradient-bar] body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-type(3) > div:nth-of-type(2) [gradient-bar]
h: 14 → 0 (-14px)
margin-top: 14px → — margin-top: 14px → —
height: 14px → — height: 14px → —
@@ -2314,8 +2266,6 @@ body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-typ
line-height: — → 1.5 line-height: — → 1.5
body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-type(6) > span > i body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-type(6) > span > i
w: 6 → 0 (-6px)
h: 6 → 20 (+14px)
display: inline-block → — display: inline-block → —
width: 6px → — width: 6px → —
height: 6px → — height: 6px → —
@@ -2373,8 +2323,6 @@ body > main > div > div:nth-of-type(3) > section:nth-of-type(2) > div:nth-of-typ
font-size: — → 16px font-size: — → 16px
body > main > div > div:nth-of-type(3) > section:nth-of-type(2) > div:nth-of-type(1) > div:nth-of-type(2) > button:nth-of-type(2) [download-btn] "Download PNG" body > main > div > div:nth-of-type(3) > section:nth-of-type(2) > div:nth-of-type(1) > div:nth-of-type(2) > button:nth-of-type(2) [download-btn] "Download PNG"
w: 210.6 → 141.3 (-69.3px)
h: 42 → 25 (-17px)
display: flex → — display: flex → —
justify-content: center → — justify-content: center → —
align-items: center → — align-items: center → —
@@ -2419,8 +2367,6 @@ body > main > div > div:nth-of-type(3) > section:nth-of-type(2) > div:nth-of-typ
line-height: — → 1.5 line-height: — → 1.5
body > main > div > div:nth-of-type(3) > section:nth-of-type(2) > div:nth-of-type(2) > div > div [art-mark] "PNG" body > main > div > div:nth-of-type(3) > section:nth-of-type(2) > div:nth-of-type(2) > div > div [art-mark] "PNG"
w: 70 → 1440 (+1370px)
h: 70 → 24 (-46px)
display: grid → — display: grid → —
align-items: center → — align-items: center → —
margin-bottom: 12px → — margin-bottom: 12px → —
@@ -2521,7 +2467,7 @@ body >div
✗ present in reference, absent in project ✗ present in reference, absent in project
=== /preview/tools/remove-background-png (vs background-remover.html) — 100 differences === === [1440x900] /preview/tools/remove-background-png (vs background-remover.html) — 100 differences ===
body > main > header [topbar] body > main > header [topbar]
position: — → sticky position: — → sticky
@@ -2532,8 +2478,6 @@ body > main > header > a > span:nth-of-type(3) [version] "/ BACKGROUND REMOVER
color: #6d7883 [var(--muted)] → #1769d2 [var(--blue)] color: #6d7883 [var(--muted)] → #1769d2 [var(--blue)]
body > main > header > div > span > i [status-dot] body > main > header > div > span > i [status-dot]
w: 6 → 8 (+2px)
h: 6 → 8 (+2px)
width: 6px → 8px width: 6px → 8px
height: 6px → 8px height: 6px → 8px
box-shadow: — → 0 0 0 2px color-mix(in srgb, #25a96a 25%, transparent) [0 0 0 2px color-mix(in srgb, var(--success) 25%, transparent)] box-shadow: — → 0 0 0 2px color-mix(in srgb, #25a96a 25%, transparent) [0 0 0 2px color-mix(in srgb, var(--success) 25%, transparent)]
@@ -2670,8 +2614,6 @@ body > main > div > div:nth-of-type(2) > span [tool-status] "LIVE PREVIEW"
line-height: — → 1.5 line-height: — → 1.5
body > main > div > div:nth-of-type(2) > span > i body > main > div > div:nth-of-type(2) > span > i
w: 6 → 0 (-6px)
h: 6 → 20 (+14px)
width: 6px → — width: 6px → —
height: 6px → — height: 6px → —
background-color: rgb(37, 169, 106) → — background-color: rgb(37, 169, 106) → —
@@ -2734,7 +2676,6 @@ body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-typ
letter-spacing: 0.1em → — letter-spacing: 0.1em → —
body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-type(2) > div:nth-of-type(1) [color-field] body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-type(2) > div:nth-of-type(1) [color-field]
h: 32 → 28 (-4px)
display: flex → — display: flex → —
align-items: center → — align-items: center → —
row-gap: 8px → — row-gap: 8px → —
@@ -2744,8 +2685,6 @@ body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-typ
height: 32px → — height: 32px → —
body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-type(2) > div:nth-of-type(1) > span [swatch] body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-type(2) > div:nth-of-type(1) > span [swatch]
w: 14 → 0 (-14px)
h: 14 → 20 (+6px)
width: 14px → — width: 14px → —
height: 14px → — height: 14px → —
@@ -2759,7 +2698,6 @@ body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-typ
font-size: — → 16px font-size: — → 16px
body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-type(2) > div:nth-of-type(1) > input:nth-of-type(2) [native-color] body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-type(2) > div:nth-of-type(1) > input:nth-of-type(2) [native-color]
w: 151.7 → 50 (-101.7px)
padding-top: 0px → — padding-top: 0px → —
padding-right: 0px → — padding-right: 0px → —
padding-bottom: 0px → — padding-bottom: 0px → —
@@ -2785,8 +2723,6 @@ body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-typ
line-height: — → 1.5 line-height: — → 1.5
body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-type(2) > div:nth-of-type(2) > span body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-type(2) > div:nth-of-type(2) > span
w: 9 → 0 (-9px)
h: 9 → 20 (+11px)
width: 9px → — width: 9px → —
height: 9px → — height: 9px → —
color: #6d7883 [var(--muted)] → #17212b [var(--foreground)] color: #6d7883 [var(--muted)] → #17212b [var(--foreground)]
@@ -2867,8 +2803,6 @@ body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-typ
letter-spacing: 0.1em → — letter-spacing: 0.1em → —
body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-type(4) > label > b [on toggle] body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-type(4) > label > b [on toggle]
w: 32 → 0 (-32px)
h: 18 → 20 (+2px)
position: relative → — position: relative → —
width: 32px → — width: 32px → —
height: 18px → — height: 18px → —
@@ -2914,8 +2848,6 @@ body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-typ
letter-spacing: 0.1em → — letter-spacing: 0.1em → —
body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-type(5) > label > b [toggle] body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-type(5) > label > b [toggle]
w: 32 → 0 (-32px)
h: 18 → 20 (+2px)
position: relative → — position: relative → —
width: 32px → — width: 32px → —
height: 18px → — height: 18px → —
@@ -2974,8 +2906,6 @@ body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-typ
line-height: — → 1.5 line-height: — → 1.5
body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-type(6) > span > i body > main > div > div:nth-of-type(3) > section:nth-of-type(1) > div:nth-of-type(6) > span > i
w: 6 → 0 (-6px)
h: 6 → 20 (+14px)
display: inline-block → — display: inline-block → —
width: 6px → — width: 6px → —
height: 6px → — height: 6px → —
@@ -3036,8 +2966,6 @@ body > main > div > div:nth-of-type(3) > section:nth-of-type(2) > div:nth-of-typ
line-height: — → 1.5 line-height: — → 1.5
body > main > div > div:nth-of-type(3) > section:nth-of-type(2) > div:nth-of-type(1) > div:nth-of-type(2) > button [download-btn] "Download result" body > main > div > div:nth-of-type(3) > section:nth-of-type(2) > div:nth-of-type(1) > div:nth-of-type(2) > button [download-btn] "Download result"
w: 193.2 → 131.8 (-61.4px)
h: 42 → 25 (-17px)
display: flex → — display: flex → —
justify-content: center → — justify-content: center → —
align-items: center → — align-items: center → —
@@ -3101,8 +3029,6 @@ body > main > div > div:nth-of-type(3) > section:nth-of-type(2) > div:nth-of-typ
background-color: rgb(232, 238, 242) → — background-color: rgb(232, 238, 242) → —
body > main > div > div:nth-of-type(3) > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(1) > div:nth-of-type(2) > div [subject subject-source] body > main > div > div:nth-of-type(3) > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(1) > div:nth-of-type(2) > div [subject subject-source]
w: 315.1 → 1440 (+1124.9px)
h: 307.7 → 24 (-283.7px)
display: grid → — display: grid → —
align-items: center → — align-items: center → —
width: 74% → — width: 74% → —
@@ -3120,8 +3046,6 @@ body > main > div > div:nth-of-type(3) > section:nth-of-type(2) > div:nth-of-typ
line-height: — → 1.5 line-height: — → 1.5
body > main > div > div:nth-of-type(3) > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(1) > div:nth-of-type(2) > span [canvas-size] "1200 × 800" body > main > div > div:nth-of-type(3) > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(1) > div:nth-of-type(2) > span [canvas-size] "1200 × 800"
x: 875.2 → 0 (-875.2px)
y: 900.8 → 698.9 (-201.9px)
position: absolute → — position: absolute → —
right: 10px → — right: 10px → —
bottom: 9px → — bottom: 9px → —
@@ -3162,8 +3086,6 @@ body > main > div > div:nth-of-type(3) > section:nth-of-type(2) > div:nth-of-typ
min-height: clamp(360px, 30vw, 560px) → — min-height: clamp(360px, 30vw, 560px) → —
body > main > div > div:nth-of-type(3) > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(2) > div [subject] body > main > div > div:nth-of-type(3) > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(2) > div [subject]
w: 300.3 → 1440 (+1139.7px)
h: 292.4 → 24 (-268.4px)
display: grid → — display: grid → —
align-items: center → — align-items: center → —
width: 74% → — width: 74% → —
@@ -3180,8 +3102,6 @@ body > main > div > div:nth-of-type(3) > section:nth-of-type(2) > div:nth-of-typ
line-height: — → 1.5 line-height: — → 1.5
body > main > div > div:nth-of-type(3) > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(2) > span [canvas-size] "1200 × 800" body > main > div > div:nth-of-type(3) > section:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(2) > div:nth-of-type(2) > span [canvas-size] "1200 × 800"
x: 1300.9 → 0 (-1300.9px)
y: 900.8 → 770.9 (-129.9px)
position: absolute → — position: absolute → —
right: 10px → — right: 10px → —
bottom: 9px → — bottom: 9px → —
+2 -1
View File
@@ -13,7 +13,8 @@
"test": "vitest run", "test": "vitest run",
"format": "prettier --write .", "format": "prettier --write .",
"lint": "eslint .", "lint": "eslint .",
"refs-cdp-audit": "node scripts/audit-cdp.mjs http://localhost:3000/demo.html http://localhost:5173/preview/demo", "refs-cdp-audit": "node scripts/audit-cdp.mjs",
"refs-cdp-audit:responsive": "node scripts/audit-cdp-responsive.mjs",
"refs-css-audit": "node scripts/audit-css.mjs", "refs-css-audit": "node scripts/audit-css.mjs",
"refs-dom-audit": "node scripts/audit-dom.mjs" "refs-dom-audit": "node scripts/audit-dom.mjs"
}, },
+26
View File
@@ -0,0 +1,26 @@
// Runs audit-cdp.mjs across the commonly used desktop / tablet / phone
// resolutions. Same CLI options pass through, e.g.:
// node scripts/audit-cdp-responsive.mjs --route /preview/demo --viewport 390x844
import { spawnSync } from "node:child_process";
const VIEWPORTS = ["2560x1440", "1920x1080", "1440x900", "768x1024", "390x844"];
const args = [];
let viewportSeen = false;
for (let i = 0; i < process.argv.length; i++) {
const v = process.argv[i];
if (v === "--viewport") {
viewportSeen = true;
i++;
} else args.push(v);
}
if (!viewportSeen) args.push("--viewport", VIEWPORTS.join(","));
const r = spawnSync(process.execPath, ["scripts/audit-cdp.mjs", ...args.slice(2)], {
stdio: "inherit",
});
if (r.error) {
console.error(r.error.message);
process.exit(1);
}
process.exit(r.status ?? 1);
+86 -28
View File
@@ -20,7 +20,7 @@ import { writeFileSync, mkdirSync, readdirSync } from "node:fs";
import { resolve, join } from "node:path"; import { resolve, join } from "node:path";
const argv = (() => { const argv = (() => {
const a = {}; const a = { viewports: [] };
for (let i = 0; i < process.argv.length; i++) { for (let i = 0; i < process.argv.length; i++) {
const v = process.argv[i]; const v = process.argv[i];
if (v === "--no-serve") a.noServe = true; if (v === "--no-serve") a.noServe = true;
@@ -28,6 +28,10 @@ const argv = (() => {
else if (v === "--ref") a.ref = process.argv[++i]; else if (v === "--ref") a.ref = process.argv[++i];
else if (v === "--route") a.route = process.argv[++i]; else if (v === "--route") a.route = process.argv[++i];
else if (v === "--port") a.port = Number(process.argv[++i]); else if (v === "--port") a.port = Number(process.argv[++i]);
else if (v === "--viewport")
a.viewports.push(
...(process.argv[++i] ?? "").split(",").filter(Boolean),
);
} }
return a; return a;
})(); })();
@@ -37,6 +41,35 @@ const PORT = argv.port || 5179;
const REFS_DIR = resolve(WEB, "../refs-html"); const REFS_DIR = resolve(WEB, "../refs-html");
const PX_TOL = 1; const PX_TOL = 1;
// Requested viewports; repeatable/comma-separated "--viewport WxH".
// Deduplicated, preserves order. Defaults to 1440x900 when the flag is absent.
const viewports = (() => {
const raw = argv.viewports.length ? argv.viewports : ["1440x900"];
const out = [];
for (const s of raw) {
const m = /^(\d+)x(\d+)$/.exec(s.trim());
if (!m) {
console.error(`[cdp-audit] invalid viewport: ${s} (expected "WxH")`);
process.exit(1);
}
const vp = { width: +m[1], height: +m[2] };
if (!out.some((o) => o.width === vp.width && o.height === vp.height))
out.push(vp);
}
return out;
})();
const vpLabel = (vp) => `${vp.width}x${vp.height}`;
// Explicit --viewport means per-resolution files; default run keeps the
// backward-compatible single cdp-audit.txt name.
const perResFile = argv.viewports.length > 0;
const reportPath = (vp) =>
resolve(
WEB,
"audit",
perResFile ? `cdp-audit-${vpLabel(vp)}.txt` : "cdp-audit.txt",
);
const PROPS = [ const PROPS = [
"display", "display",
"position", "position",
@@ -98,13 +131,11 @@ const PROPS = [
// --- capture: open a page and snapshot its tree via getComputedStyle --- // --- capture: open a page and snapshot its tree via getComputedStyle ---
async function capture(browser, target) { async function capture(browser, target, viewport) {
const url = target.startsWith("http") const url = target.startsWith("http")
? target ? target
: "file:///" + target.replace(/\\/g, "/"); : "file:///" + target.replace(/\\/g, "/");
const page = await browser.newPage({ const page = await browser.newPage({ viewport });
viewport: { width: 1440, height: 900 },
});
await page.goto(url, { waitUntil: "networkidle" }); await page.goto(url, { waitUntil: "networkidle" });
await page.evaluate(async () => { await page.evaluate(async () => {
await document.fonts.ready; await document.fonts.ready;
@@ -663,14 +694,7 @@ function diffStyles(a, b) {
`render: node is rendered only on one side ` + `render: node is rendered only on one side ` +
`(no layout box — usually display:none on one side)`, `(no layout box — usually display:none on one side)`,
); );
if (a.box && b.box)
for (const k of ["x", "y", "w", "h"]) {
const d = +(b.box[k] - a.box[k]).toFixed(1);
if (Math.abs(d) > PX_TOL && !(flowDriven(a, k) && flowDriven(b, k)))
out.push(
`${k}: ${a.box[k]}${b.box[k]} (${d > 0 ? "+" : ""}${d}px)`,
);
}
// If a side is declared via CSS variables, append the raw declaration so // If a side is declared via CSS variables, append the raw declaration so
// the defining rule is easy to find (e.g. "color: var(--accent)"). // the defining rule is easy to find (e.g. "color: var(--accent)").
const fmtSide = (n, k) => { const fmtSide = (n, k) => {
@@ -680,6 +704,9 @@ function diffStyles(a, b) {
return `${res || "—"} [${r}]`; return `${res || "—"} [${r}]`;
return res; return res;
}; };
// Which style props were already reported as diffs — box axes governed by
// them are redundant then.
const styleDiffKeys = new Set();
for (const k of new Set([ for (const k of new Set([
...Object.keys(a.styles), ...Object.keys(a.styles),
...Object.keys(b.styles), ...Object.keys(b.styles),
@@ -697,8 +724,31 @@ function diffStyles(a, b) {
) )
continue; continue;
out.push(`${k}: ${fmtSide(a, k) || "—"}${fmtSide(b, k) || "—"}`); out.push(`${k}: ${fmtSide(a, k) || "—"}${fmtSide(b, k) || "—"}`);
styleDiffKeys.add(k);
} }
} }
// Box axes map to style props: w→width, h→height, x→left/right, y→top/bottom.
// If the corresponding style diff is already above, the geometry line is a
// duplicate — drop it. Keep geometry only for changes the styles don't
// explain (e.g. different border/padding with the same declared width).
if (a.box && b.box)
for (const k of ["x", "y", "w", "h"]) {
const gov =
k === "w"
? ["width"]
: k === "h"
? ["height"]
: k === "x"
? ["left", "right"]
: ["top", "bottom"];
if (gov.some((p) => styleDiffKeys.has(p))) continue;
const d = +(b.box[k] - a.box[k]).toFixed(1);
if (Math.abs(d) > PX_TOL && !(flowDriven(a, k) && flowDriven(b, k)))
out.push(
`${k}: ${a.box[k]}${b.box[k]} (${d > 0 ? "+" : ""}${d}px)`,
);
}
return out; return out;
} }
@@ -861,16 +911,16 @@ const waitFor = async (url, ms = 60000) => {
throw new Error("dev server not up: " + url); throw new Error("dev server not up: " + url);
}; };
async function auditOne(browser, target) { async function auditOne(browser, target, viewport) {
const oursUrl = argv.ours || `http://127.0.0.1:${PORT}${target.route}`; const oursUrl = argv.ours || `http://127.0.0.1:${PORT}${target.route}`;
const refUrl = resolve(REFS_DIR, target.ref); const refUrl = resolve(REFS_DIR, target.ref);
const ours = await capture(browser, oursUrl); const ours = await capture(browser, oursUrl, viewport);
const ref = await capture(browser, refUrl); const ref = await capture(browser, refUrl, viewport);
const report = []; const report = [];
compare(ref, ours, ["body"], report); compare(ref, ours, ["body"], report);
return { route: target.route, ref: target.ref, lines: report }; return { route: target.route, ref: target.ref, viewport, lines: report };
} }
async function main() { async function main() {
@@ -896,15 +946,19 @@ async function main() {
const browser = await chromium.launch(); const browser = await chromium.launch();
const reports = []; const reports = [];
try { try {
for (const vp of viewports) {
for (const target of targets) { for (const target of targets) {
try { try {
const rep = await auditOne(browser, target); const rep = await auditOne(browser, target, vp);
reports.push(rep); reports.push(rep);
console.log( console.log(
`[cdp-audit] ${rep.route} (vs ${rep.ref}): ${rep.lines.length} differences`, `[cdp-audit] [${vpLabel(vp)}] ${rep.route} (vs ${rep.ref}): ${rep.lines.length} differences`,
); );
} catch (e) { } catch (e) {
console.error(`[cdp-audit] ${target.route} failed: ${e.message}`); console.error(
`[cdp-audit] [${vpLabel(vp)}] ${target.route} failed: ${e.message}`,
);
}
} }
} }
} finally { } finally {
@@ -920,22 +974,26 @@ async function main() {
} }
} }
const outDir = resolve(WEB, "audit");
mkdirSync(outDir, { recursive: true });
for (const vp of viewports) {
const vReps = reports.filter(
(r) => r.viewport.width === vp.width && r.viewport.height === vp.height,
);
const header = const header =
`CDP visual audit\n${new Date().toISOString()}\n` + `CDP visual audit\n${new Date().toISOString()}\n` +
`viewport 1440x900, tolerance ${PX_TOL}px, theme light\n\n`; `viewport ${vpLabel(vp)}, tolerance ${PX_TOL}px, theme light\n\n`;
const body = reports const body = vReps
.map((r) => { .map((r) => {
const title = `=== ${r.route} (vs ${r.ref}) — ${r.lines.length} differences ===`; const title = `=== [${vpLabel(vp)}] ${r.route} (vs ${r.ref}) — ${r.lines.length} differences ===`;
if (!r.lines.length) return title + "\n ✅ no differences found"; if (!r.lines.length) return title + "\n ✅ no differences found";
return title + "\n\n" + r.lines.join("\n\n"); return title + "\n\n" + r.lines.join("\n\n");
}) })
.join("\n\n\n"); .join("\n\n\n");
const outPath = reportPath(vp);
const outDir = resolve(WEB, "audit");
mkdirSync(outDir, { recursive: true });
const outPath = resolve(outDir, "cdp-audit.txt");
writeFileSync(outPath, header + body + "\n", "utf8"); writeFileSync(outPath, header + body + "\n", "utf8");
console.log(`report: web/audit/cdp-audit.txt`); console.log(`report: ${outPath}`);
}
} }
main().catch((e) => { main().catch((e) => {