Skip to content

Commit 615fbd8

Browse files
committed
feat(remove-selector): support postcss@7
1 parent 8c391dd commit 615fbd8

File tree

6 files changed

+167
-62
lines changed

6 files changed

+167
-62
lines changed

packages/postcss-plugin-remove-selector/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
},
2525
"dependencies": {},
2626
"peerDependencies": {
27-
"postcss": "^8.0.0"
27+
"postcss": "^7.0.0 || ^8.0.0"
2828
},
2929
"publishConfig": {
3030
"access": "public",
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
export * from './plugin';
22
export { TDESIGN_ICON_REMOVE_SELECTOR } from './tdesign-uniapp-icon';
3+
4+
export { postCssPluginRemoveSelector as default } from './plugin';
Lines changed: 71 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,86 @@
11
import { shouldHandleFile, shouldRemoveRule } from './helper';
22

3-
import type { Options, PostCSSPlugin } from './types';
3+
import type { Options } from './types';
44

5-
export type { Options, FileConfig, ShouldRemoveRuleOptions, PostCSSPlugin } from './types';
5+
export type { Options, FileConfig, ShouldRemoveRuleOptions } from './types';
66
export { shouldHandleFile, shouldRemoveRule, extractIconName } from './helper';
77

8+
const PLUGIN_NAME = 'postcss-plugin-remove-selector';
9+
10+
/**
11+
* 核心处理逻辑,PostCSS 7 / 8 共用
12+
*/
13+
function processRoot(root: any, result: any, opts: Options) {
14+
const { list = [], debug = false } = opts;
15+
const fileName = result.opts?.from || '';
16+
const found = shouldHandleFile(list, fileName);
17+
18+
if (!found) {
19+
return;
20+
}
21+
22+
const { exclude = [], include = [], selectorPattern } = found;
23+
if (debug) {
24+
console.log('[postcss-plugin-remove-selector] handling:', fileName);
25+
}
26+
27+
let removedCount = 0;
28+
29+
root.walkRules((rule: any) => {
30+
if (shouldRemoveRule({
31+
selectorPattern,
32+
exclude,
33+
include,
34+
selector: rule.selector,
35+
})) {
36+
rule.remove();
37+
removedCount += 1;
38+
}
39+
});
40+
41+
if (debug) {
42+
console.log(`[postcss-plugin-remove-selector] removed ${removedCount} rules from:`, fileName);
43+
}
44+
}
45+
846
/**
947
* PostCSS 插件:移除指定的 CSS 选择器
1048
* 用于图标样式减包等场景
1149
*
50+
* 同时兼容 PostCSS 7 和 PostCSS 8:
51+
* - PostCSS 8:使用标准 Creator 函数格式 + postcss: true 标记
52+
* - PostCSS 7:回退到 postcss.plugin() 注册方式
53+
*
1254
* @param opts 配置项
1355
* @returns PostCSS 插件
1456
*/
15-
export function postCssPluginRemoveSelector(opts: Options = { list: [] }): PostCSSPlugin & { postcss: true } {
16-
const { list = [], debug = false } = opts;
17-
18-
const plugin: PostCSSPlugin & { postcss: true } = {
19-
postcssPlugin: 'postcss-plugin-remove-selector',
20-
postcss: true,
21-
Once(root, { result }) {
22-
const fileName = result.opts?.from || '';
23-
const found = shouldHandleFile(list, fileName);
24-
25-
if (!found) {
26-
return;
27-
}
28-
29-
const { exclude = [], include = [], selectorPattern } = found;
30-
if (debug) {
31-
console.log('[postcss-plugin-remove-selector] handling:', fileName);
32-
}
33-
34-
let removedCount = 0;
35-
36-
root.walkRules((rule) => {
37-
if (shouldRemoveRule({
38-
selectorPattern,
39-
exclude,
40-
include,
41-
selector: rule.selector,
42-
})) {
43-
rule.remove();
44-
removedCount += 1;
45-
}
46-
});
47-
48-
if (debug) {
49-
console.log(`[postcss-plugin-remove-selector] removed ${removedCount} rules from:`, fileName);
50-
}
57+
const postCssPluginRemoveSelector: any = (opts: Options = { list: [] }) =>
58+
// PostCSS 8 格式
59+
({
60+
postcssPlugin: PLUGIN_NAME,
61+
Once(root: any, { result }: any) {
62+
processRoot(root, result, opts);
5163
},
52-
};
64+
})
65+
;
5366

54-
return plugin;
67+
// 标记为 PostCSS 8 插件
68+
postCssPluginRemoveSelector.postcss = true as const;
69+
70+
// PostCSS 7 兼容:通过 postcss.plugin() 注册
71+
try {
72+
// eslint-disable-next-line @typescript-eslint/no-require-imports
73+
const postcss = require('postcss');
74+
if (postcss && typeof postcss.plugin === 'function') {
75+
postCssPluginRemoveSelector.postcss7 = postcss.plugin(
76+
PLUGIN_NAME,
77+
(opts: Options = { list: [] }) => (root: any, result: any) => {
78+
processRoot(root, result, opts);
79+
},
80+
);
81+
}
82+
} catch (e) {
83+
// postcss 未安装或不支持 postcss.plugin,忽略
5584
}
85+
86+
export { postCssPluginRemoveSelector };

packages/postcss-plugin-remove-selector/src/types.ts

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import type { Root, Result } from 'postcss';
2-
31
/**
42
* 单个文件匹配配置
53
*/
@@ -38,10 +36,4 @@ export interface ShouldRemoveRuleOptions {
3836
selector: string;
3937
}
4038

41-
/**
42-
* PostCSS 插件返回类型
43-
*/
44-
export interface PostCSSPlugin {
45-
postcssPlugin: string;
46-
Once(root: Root, helpers: { result: Result }): void;
47-
}
39+

packages/postcss-plugin-remove-selector/tests/__snapshots__/remote-selector.spec.js.snap

Lines changed: 68 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,19 @@
22

33
exports[`empty options 1`] = `
44
"
5-
.press-icon-plus-arrow-down:before {
5+
.t-icon-arrow-down:before {
66
content: 'e65e';
77
}
88
9-
.press-icon-plus-arrow-up:before {
9+
.t-icon-arrow-up:before {
1010
content: 'e65f';
1111
}
1212
13-
.press-icon-plus-invitation:before {
13+
.t-icon-invitation:before {
1414
content: 'e6d6';
1515
}
1616
17-
.press-icon-plus-like-o:before {
17+
.t-icon-like-o:before {
1818
content: 'e6d7';
1919
}
2020
@@ -26,11 +26,11 @@ exports[`empty options 1`] = `
2626

2727
exports[`exclude 1`] = `
2828
"
29-
.press-icon-plus-arrow-down:before {
29+
.t-icon-arrow-down:before {
3030
content: 'e65e';
3131
}
3232
33-
.press-icon-plus-arrow-up:before {
33+
.t-icon-arrow-up:before {
3434
content: 'e65f';
3535
}
3636
@@ -42,23 +42,51 @@ exports[`exclude 1`] = `
4242

4343
exports[`file is regexp 1`] = `
4444
"
45-
.press-icon-plus-arrow-down:before {
45+
.t-icon-arrow-down:before {
4646
content: 'e65e';
4747
}
4848
49-
.press-icon-plus-arrow-up:before {
49+
.t-icon-arrow-up:before {
5050
content: 'e65f';
5151
}
52+
53+
#someId {
54+
color: red;
55+
}
56+
"
57+
`;
58+
59+
exports[`file not matched - should not modify css 1`] = `
60+
"
61+
.t-icon-arrow-down:before {
62+
content: 'e65e';
63+
}
64+
65+
.t-icon-arrow-up:before {
66+
content: 'e65f';
67+
}
68+
69+
.t-icon-invitation:before {
70+
content: 'e6d6';
71+
}
72+
73+
.t-icon-like-o:before {
74+
content: 'e6d7';
75+
}
76+
77+
#someId {
78+
color: red;
79+
}
5280
"
5381
`;
5482

5583
exports[`include & exclude 1`] = `
5684
"
57-
.press-icon-plus-arrow-down:before {
85+
.t-icon-arrow-down:before {
5886
content: 'e65e';
5987
}
6088
61-
.press-icon-plus-arrow-up:before {
89+
.t-icon-arrow-up:before {
6290
content: 'e65f';
6391
}
6492
@@ -70,12 +98,40 @@ exports[`include & exclude 1`] = `
7098

7199
exports[`include 1`] = `
72100
"
73-
.press-icon-plus-arrow-down:before {
101+
.t-icon-arrow-down:before {
74102
content: 'e65e';
75103
}
76104
77-
.press-icon-plus-arrow-up:before {
105+
.t-icon-arrow-up:before {
78106
content: 'e65f';
79107
}
108+
109+
#someId {
110+
color: red;
111+
}
112+
"
113+
`;
114+
115+
exports[`no selectorPattern - should not remove non-icon rules 1`] = `
116+
"
117+
.t-icon-arrow-down:before {
118+
content: 'e65e';
119+
}
120+
"
121+
`;
122+
123+
exports[`postcss7 fallback - should work with postcss.plugin style 1`] = `
124+
"
125+
.t-icon-arrow-down:before {
126+
content: 'e65e';
127+
}
128+
129+
.t-icon-arrow-up:before {
130+
content: 'e65f';
131+
}
132+
133+
#someId {
134+
color: red;
135+
}
80136
"
81137
`;

packages/postcss-plugin-remove-selector/tests/remote-selector.spec.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,27 @@ test('file not matched - should not modify css', async () => {
115115
expect(result.css).toMatchSnapshot();
116116
expect(result.warnings()).toHaveLength(0);
117117
});
118+
119+
120+
test('postcss7 fallback - should work with postcss.plugin style', async () => {
121+
// 当 postcss.plugin 可用时,postcss7 属性应该被设置
122+
if (postCssPluginRemoveSelector.postcss7) {
123+
const plugin = postCssPluginRemoveSelector.postcss7({
124+
list: [{
125+
file: 'abc',
126+
exclude: ['invitation', 'like-o'],
127+
selectorPattern: /^\.t-icon-[\w-]+:before$/,
128+
}],
129+
});
130+
const result = await postcss([plugin]).process(input, { from: 'abc' });
131+
132+
// eslint-disable-next-line jest/no-conditional-expect
133+
expect(result.css).toMatchSnapshot();
134+
// eslint-disable-next-line jest/no-conditional-expect
135+
expect(result.warnings()).toHaveLength(0);
136+
} else {
137+
// 如果当前环境是 PostCSS 8,postcss.plugin 不存在,跳过
138+
// eslint-disable-next-line jest/no-conditional-expect
139+
expect(true).toBe(true);
140+
}
141+
});

0 commit comments

Comments
 (0)