@hanzo/design 0.4.5 → 0.4.6

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": "@hanzo/design",
3
- "version": "0.4.5",
3
+ "version": "0.4.6",
4
4
  "packageManager": "pnpm@11.17.0",
5
5
  "description": "Hanzo Design System \u2014 monochrome, dark-default tokens + components + brand assets, the single source of truth for every Hanzo surface. CSS + typed programmatic tokens.",
6
6
  "license": "BSD-3-Clause",
@@ -59,6 +59,47 @@ const pass = (msg) => console.log(` ok ${msg}`)
59
59
  : pass(`all ${urls.length} asset url()s resolve from the package root`)
60
60
  }
61
61
 
62
+ // ── 1a. the bundles must PARSE ───────────────────────────────────────────
63
+ // 0.4.2 and 0.4.3 shipped a stray `*/` in styles.css AND tailwind.css: an
64
+ // edit added prose to the end of a comment that was already closed, so a
65
+ // paragraph of English sat in the stylesheet as raw CSS, terminated by a
66
+ // second `*/`. Browsers recover from that — they skip to the next thing that
67
+ // looks like a rule and carry on — so the whole kit rendered correctly in
68
+ // Chromium at three widths in both themes, and every screenshot looked right.
69
+ // PostCSS does not recover. It throws, which means those two versions could
70
+ // not be built against by any Vite/Next/Tailwind consumer at all.
71
+ //
72
+ // The lesson is specific: RENDERING IS NOT PARSING. A visual check cannot see
73
+ // this class of defect, because the browser's error recovery is what hides it.
74
+ // So it is checked structurally, here, on the artifacts a consumer receives.
75
+ //
76
+ // Done by hand rather than with postcss because the defect is lexical and the
77
+ // scan is fifteen lines — CSS comments do not nest, so one left-to-right pass
78
+ // that skips comment bodies finds every stray terminator and every unclosed
79
+ // opener. A parser dependency would be a heavier answer to a smaller question.
80
+ {
81
+ for (const f of ['styles.css', 'tailwind.css']) {
82
+ const s = read(join(root, f))
83
+ let i = 0, opened = 0, strays = [], unterminated = null
84
+ while (i < s.length - 1) {
85
+ if (s[i] === '/' && s[i + 1] === '*') {
86
+ opened++
87
+ const j = s.indexOf('*/', i + 2)
88
+ if (j < 0) { unterminated = s.slice(0, i).split('\n').length; break }
89
+ i = j + 2
90
+ continue
91
+ }
92
+ if (s[i] === '*' && s[i + 1] === '/') { strays.push(s.slice(0, i).split('\n').length); i += 2; continue }
93
+ i++
94
+ }
95
+ const braces = [...s].reduce((n, c) => n + (c === '{') - (c === '}'), 0)
96
+ if (unterminated !== null) fail(`${f}: unterminated /* at line ${unterminated}`)
97
+ else if (strays.length) fail(`${f}: stray */ outside any comment at line ${strays.join(', ')} — a consumer's PostCSS build throws here`)
98
+ else if (braces !== 0) fail(`${f}: ${Math.abs(braces)} unbalanced ${braces > 0 ? '{' : '}'}`)
99
+ else pass(`${f} is lexically sound — ${opened} comments closed, braces balanced`)
100
+ }
101
+ }
102
+
62
103
  // ── 1b. the Tailwind bridge is complete and self-contained ───────────────
63
104
  // An app should write ONE import and get working utilities. Each thing checked
64
105
  // here failed silently in production before it was checked: a missing slot