Skip to content

Commit f08dc1e

Browse files
committed
fix(review): rebase onto upstream/main and sync CI fixes
1 parent 5d819ff commit f08dc1e

1 file changed

Lines changed: 94 additions & 26 deletions

File tree

Lines changed: 94 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,109 @@
11
#!/usr/bin/env node
2+
// Asserts that utility classes used in the chat-panel HTML/JS are present in the compiled CSS.
3+
// Dependency-free script to prevent silent failures where the .vsix builds but lacks theme colors.
24

3-
/**
4-
* Verifies that the compiled chat-panel.css retains VS Code theme tokens.
5-
*
6-
* Tailwind v4 can silently strip custom CSS variables when purge detects
7-
* them as unused. This script ensures the built CSS still contains
8-
* --vscode-* property references so the webview can read them at runtime.
9-
*/
5+
import {readFileSync, existsSync} from 'node:fs';
6+
import {join, dirname} from 'node:path';
7+
import {fileURLToPath} from 'node:url';
108

11-
const fs = require('node:fs');
12-
const path = require('node:path');
9+
const here = dirname(fileURLToPath(import.meta.url));
10+
const pkgRoot = join(here, '..');
11+
const cssPath = join(pkgRoot, 'media', 'chat-panel.css');
12+
const htmlPath = join(pkgRoot, 'media', 'chat-panel.html');
13+
const jsPath = join(pkgRoot, 'media', 'chat-panel.js');
1314

14-
const CSS_PATH = path.resolve(__dirname, '..', 'media', 'chat-panel.css');
15-
16-
if (!fs.existsSync(CSS_PATH)) {
17-
console.error(`CSS file not found: ${CSS_PATH}`);
15+
if (!existsSync(cssPath)) {
16+
console.error(
17+
`verify-theme-css: ${cssPath} is missing. Run \`pnpm run build:vscode\` first.`,
18+
);
1819
process.exit(1);
1920
}
2021

21-
const css = fs.readFileSync(CSS_PATH, 'utf-8');
22+
// Extract vscode-* Tailwind classes (including variant prefixes like hover:).
23+
// 'vscode-…' must precede 'vscode' to avoid partial matches.
24+
const tailwindClass = /(?:[a-zA-Z-]+:)*[a-zA-Z][\w-]*-(?:vscode-[\w-]+|vscode)\b/g;
2225

23-
if (css.trim().length === 0) {
24-
console.error('chat-panel.css is empty');
25-
process.exit(1);
26+
const referenced = new Set();
27+
for (const path of [htmlPath, jsPath]) {
28+
if (!existsSync(path)) continue;
29+
const text = readFileSync(path, 'utf8');
30+
for (const match of text.match(tailwindClass) ?? []) {
31+
referenced.add(match);
32+
}
2633
}
2734

28-
const vscodeTokens = css.match(/--vscode-[\w-]+/g) || [];
29-
const uniqueTokens = [...new Set(vscodeTokens)];
35+
// Spot-check critical tokens whose absence would be visually obvious.
36+
const requiredTokens = [
37+
'bg-vscode-bg',
38+
'text-vscode-fg',
39+
'bg-vscode-input-bg',
40+
'border-vscode-input-border',
41+
'bg-vscode-button-bg',
42+
'text-vscode-button-fg',
43+
'border-vscode-border',
44+
];
3045

31-
if (uniqueTokens.length === 0) {
32-
console.error(
33-
'No --vscode-* theme tokens found in chat-panel.css. ' +
34-
'Tailwind may have stripped them during compilation.',
46+
const css = readFileSync(cssPath, 'utf8');
47+
48+
// Escape colons for variant selectors (e.g. .hover\:bg-vscode-foo).
49+
function compiledSelectorFor(token) {
50+
return token.replaceAll(':', '\\\\:');
51+
}
52+
53+
function compiledAsClass(token) {
54+
const selector = compiledSelectorFor(token);
55+
// nosemgrep: javascript.lang.security.audit.detect-non-literal-regexp.detect-non-literal-regexp
56+
return new RegExp(`\\.${selector}(?![\\w-])`).test(css);
57+
}
58+
59+
const missing = [...referenced].filter((cls) => !compiledAsClass(cls));
60+
61+
const missingRequired = requiredTokens.filter(
62+
// nosemgrep: javascript.lang.security.audit.detect-non-literal-regexp.detect-non-literal-regexp
63+
(token) => !new RegExp(`\\.${token}(?![\\w-])`).test(css),
64+
);
65+
66+
if (missing.length === 0 && missingRequired.length === 0) {
67+
const scanned = referenced.size;
68+
console.log(
69+
`verify-theme-css: ok — ${scanned} theme class(es) found in ${cssPath}`,
3570
);
36-
process.exit(1);
71+
process.exit(0);
3772
}
3873

39-
console.log(
40-
`OK: chat-panel.css contains ${uniqueTokens.length} VS Code theme tokens`,
74+
console.error(
75+
'verify-theme-css: the compiled CSS is missing theme utilities referenced',
4176
);
77+
console.error(' by the webview templates. The webview would render unthemed.');
78+
console.error('');
79+
80+
if (missingRequired.length > 0) {
81+
console.error('Required tokens that did not compile:');
82+
for (const token of missingRequired) {
83+
console.error(` - .${token}`);
84+
}
85+
console.error('');
86+
}
87+
88+
if (missing.length > 0) {
89+
const preview = missing.slice(0, 20);
90+
console.error(`Other missing classes (${missing.length} total, showing first ${preview.length}):`);
91+
for (const cls of preview) {
92+
console.error(` - .${cls}`);
93+
}
94+
if (missing.length > preview.length) {
95+
console.error(` ... and ${missing.length - preview.length} more`);
96+
}
97+
console.error('');
98+
}
99+
100+
console.error(
101+
'This usually means the Tailwind theme moved (e.g. tailwind.config.js no',
102+
);
103+
console.error(
104+
'longer being read by Tailwind v4) or @theme tokens were deleted. Check',
105+
);
106+
console.error('that src/styles.css declares every `--color-vscode-*` used by');
107+
console.error('media/chat-panel.{html,js}.');
108+
109+
process.exit(1);

0 commit comments

Comments
 (0)