roast-my-design-system 4.2.3 → 4.2.5

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/bin/roast.mjs CHANGED
@@ -106,7 +106,7 @@ function run(script, args, env) {
106
106
  }
107
107
  const say = (s) => { if (!asJson) console.log(s); };
108
108
 
109
- say(`roast-my-design-system ${VERSION} · read-only scan, nothing leaves your machine\n`);
109
+ say(`roast-my-design-system ${VERSION} · read-only scan, nothing leaves your machine`);
110
110
  // the harvest goes to a temp dir this wrapper deletes right after; tell the
111
111
  // script so it does not print a path that will be gone seconds later
112
112
  run('harvest/index.mjs', [target, '--out', harvestPath,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "roast-my-design-system",
3
- "version": "4.2.3",
3
+ "version": "4.2.5",
4
4
  "description": "Your AI can write the UI. This makes sure it writes your UI. A deterministic scanner counts every colour, spacing value and duplicate component, scores you 0-100 against 34 public repos, scopes the scan with .roastignore, injects agent rules with --apply.",
5
5
  "keywords": [
6
6
  "design-system",
@@ -1324,5 +1324,5 @@ if (summaryPath) {
1324
1324
 
1325
1325
  console.log(`✓ Diagnosis for ${repoName}`);
1326
1326
  if (healthScore !== null) console.log(` score: ${healthScore}/100`);
1327
- console.log(` verdict: ${verdict}`);
1328
- console.log(` → ${outPath}`);
1327
+ console.log(`\n Verdict: ${verdict}`);
1328
+ console.log(` Your free report is here → ${outPath}`);
@@ -171,8 +171,8 @@ const top = (list, n = 5) => list.some((e) => e.count > 1)
171
171
  ? ` top: ${list.slice(0, n).map((e) => `${showVal(e.value)} ×${e.count}`).join(', ')}`
172
172
  : (list.length ? ', none repeated' : '');
173
173
 
174
- console.log(`\nHarvest: ${profile.name ?? target}`);
175
- console.log(` framework: ${profile.framework}${profile.typescript ? ' + TS' : ''} design system: ${profile.designSystem.kind}${profile.designSystem.name ? ` (${profile.designSystem.name})` : ''} styling: ${profile.stylingDeps.join(', ') || 'none detected'}`);
174
+ console.log(`Harvest: ${profile.name ?? target}`);
175
+ console.log(` framework: ${profile.framework}${profile.typescript ? ' + TS' : ''} design system: ${profile.designSystem.kind}${profile.designSystem.name ? ` (${profile.designSystem.name})` : ''} styling: ${profile.stylingDeps.join(', ') || 'none detected'}`);
176
176
  console.log(` files: ${files.code.length} code, ${files.styles.length} style`);
177
177
  if (exclusions.patterns.length) {
178
178
  // Same voice as the report header: source named once, slashes on folders,
@@ -197,7 +197,7 @@ console.log(` context files: ${context.map((c) => c.file).join(', ') || 'none'}
197
197
  // The npx wrapper writes the harvest to a temp dir it deletes right after;
198
198
  // pointing the user at a path that will not exist is noise there.
199
199
  if (process.env.ROAST_EPHEMERAL_OUT === '1') {
200
- console.log(`\n scanned in ${harvest.tookMs}ms\n`);
200
+ console.log(`\n scanned in ${harvest.tookMs}ms`);
201
201
  } else {
202
- console.log(`\n → ${outPath} (${harvest.tookMs}ms)\n`);
202
+ console.log(`\n → ${outPath} (${harvest.tookMs}ms)`);
203
203
  }
@@ -160,10 +160,19 @@ export function profileRepo(root, files) {
160
160
  const knownLib = KNOWN_LIBRARIES.find((d) => deps[d.pkg]);
161
161
  const homegrown = files.code.filter((f) => /(^|\/)components\//.test(f) && !/\/components\/ui\//.test(f) && /\.(tsx|jsx)$/.test(f));
162
162
 
163
+ // A design system does not have to arrive through npm. A stylesheet defining
164
+ // a real set of CSS custom properties IS one — arguably the purest form —
165
+ // and calling it "none" undersells exactly the discipline the ideal asks for.
166
+ const tokenDefs = files.styles.slice(0, 8).reduce((sum, f) => {
167
+ const css = read(join(root, f));
168
+ return sum + (css ? (css.match(/--[A-Za-z0-9_-]+\s*:/g) ?? []).length : 0);
169
+ }, 0);
170
+
163
171
  let designSystem;
164
172
  if (isShadcn) designSystem = { kind: 'shadcn', name: 'shadcn/ui', confidence: 'high' };
165
173
  else if (knownLib) designSystem = { kind: 'library', name: knownLib.name, pkg: knownLib.pkg, confidence: 'high' };
166
174
  else if (homegrown.length >= 3) designSystem = { kind: 'custom', name: 'custom (unrecognized)', confidence: 'low' };
175
+ else if (tokenDefs >= 5) designSystem = { kind: 'custom', name: 'CSS tokens', confidence: 'medium' };
167
176
  else designSystem = { kind: 'none', confidence: 'high' };
168
177
 
169
178
  // Import alias from tsconfig paths or components.json
@@ -175,7 +184,10 @@ export function profileRepo(root, files) {
175
184
  if (key) alias = key.replace('/*', '');
176
185
  }
177
186
 
178
- const styling = STYLING_DEPS.filter((s) => deps[s.pkg]).map((s) => s.label);
187
+ // No toolchain in package.json does not mean no styling: if the walk found
188
+ // real stylesheets, plain CSS is what is there — say so, not "none detected".
189
+ let styling = STYLING_DEPS.filter((s) => deps[s.pkg]).map((s) => s.label);
190
+ if (!styling.length && files.styles.length) styling = ['plain CSS'];
179
191
 
180
192
  // The git remote is a far better identity than package.json's name field
181
193
  // ("chatbot" vs "vercel/ai-chatbot"). Parsed from .git/config, no git exec.
@@ -1,4 +1,4 @@
1
1
  // Single version constant for the engine — imported by diagnose (report
2
2
  // footer) and rules (generated-by line). This is the bump spot that used to
3
3
  // live as a const inside diagnose/index.mjs.
4
- export const VERSION = '4.2.3';
4
+ export const VERSION = '4.2.5';