Skip to content

Commit 3d1e9df

Browse files
authored
fix: extract missing styles (#25)
1 parent 376ec37 commit 3d1e9df

3 files changed

Lines changed: 87 additions & 0 deletions

File tree

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
"now-build": "npm run build"
3636
},
3737
"devDependencies": {
38+
"@adobe/css-tools": "^4.4.4",
3839
"@rc-component/father-plugin": "^1.0.0",
3940
"@testing-library/jest-dom": "^5.16.4",
4041
"@testing-library/react": "^13.0.0",

src/index.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ const ComponentCustomizeRender: Record<
4242
Space: (Space: any) => (
4343
<>
4444
<Space />
45+
<Space.Addon />
4546
<Space.Compact>
4647
<antd.Button />
4748
</Space.Compact>
@@ -51,6 +52,7 @@ const ComponentCustomizeRender: Record<
5152
<>
5253
<Modal />
5354
<Modal._InternalPanelDoNotUseOrYouWillBeFired />
55+
<Modal._InternalPanelDoNotUseOrYouWillBeFired type="confirm" />
5456
</>
5557
),
5658
message: (message: any) => {
@@ -67,6 +69,20 @@ const ComponentCustomizeRender: Record<
6769
<Layout.Sider />
6870
</>
6971
),
72+
Cascader: (Cascader: typeof antd.Cascader) => (
73+
<>
74+
<Cascader options={[]} />
75+
<Cascader.Panel options={[]} />
76+
</>
77+
),
78+
Input: (Input: typeof antd.Input) => (
79+
<>
80+
<Input />
81+
<Input.OTP />
82+
<Input.Search />
83+
<Input.TextArea />
84+
</>
85+
),
7086
};
7187

7288
interface NodeProps {

tests/coverage.test.tsx

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { StyleProvider } from '@ant-design/cssinjs';
2+
import { ConfigProvider } from 'antd';
3+
import type { CssStylesheetAST, CssAtRuleAST } from '@adobe/css-tools';
4+
import { parse, CssTypes } from '@adobe/css-tools';
5+
import { extractStyle } from '../src';
6+
import fs from 'fs';
7+
8+
function extractSelectors(ast: CssStylesheetAST): Set<string> {
9+
const selectors = new Set<string>();
10+
11+
function walk(rules: CssAtRuleAST[]) {
12+
for (const rule of rules) {
13+
switch (rule.type) {
14+
case CssTypes.rule:
15+
rule.selectors?.forEach(sel => selectors.add(sel));
16+
break;
17+
case CssTypes.media:
18+
case CssTypes.supports:
19+
case CssTypes.layer:
20+
if (rule.rules) walk(rule.rules);
21+
break;
22+
default:
23+
// Ignore other rule types (comments, keyframes, font-face, etc.)
24+
break;
25+
}
26+
}
27+
}
28+
29+
if (ast.stylesheet?.rules) {
30+
walk(ast.stylesheet.rules);
31+
}
32+
return selectors;
33+
}
34+
35+
describe('CSS Coverage', () => {
36+
it('should extract all antd selectors', () => {
37+
// Extract CSS with:
38+
// - hashPriority='high' to avoid :where() wrapper
39+
// - hashed: false to avoid hash class prefixes
40+
const extractedCss = extractStyle((node) => (
41+
<StyleProvider hashPriority="high">
42+
<ConfigProvider theme={{ hashed: false }}>
43+
{node}
44+
</ConfigProvider>
45+
</StyleProvider>
46+
));
47+
48+
const antdCssPath = require.resolve('antd/dist/antd.css');
49+
const antdCss = fs.readFileSync(antdCssPath, 'utf-8');
50+
51+
const antdAst = parse(antdCss);
52+
const extractedAst = parse(extractedCss);
53+
54+
const antdSelectors = extractSelectors(antdAst);
55+
const extractedSelectors = extractSelectors(extractedAst);
56+
57+
const missing = [...antdSelectors].filter(
58+
sel => !extractedSelectors.has(sel)
59+
);
60+
61+
const coverage = ((antdSelectors.size - missing.length) / antdSelectors.size * 100).toFixed(2);
62+
console.log(`CSS Coverage: ${coverage}% (${missing.length} missing of ${antdSelectors.size} selectors)`);
63+
64+
if (missing.length > 0) {
65+
console.log('Missing selectors:', JSON.stringify(missing, null, 2));
66+
}
67+
68+
expect(missing).toEqual([]);
69+
});
70+
});

0 commit comments

Comments
 (0)