-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
141 lines (121 loc) · 4.08 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
const FS = require("fs");
const Path = require("path");
const { pathToFileURL } = require("url");
const { compileString, Logger } = require("sass");
/**
* @type {(options:{
* theme: string;
* options?: {
* prefixCls?: string;
* variables?: {[key: string]: string | number};
* include?: string;
* };
* })=>any}
*
* @note 阅读 webpack 版本代码的理解
* 1. 解析 css 到对应 scss
* 2. 替换 scss 内容
* 3. 再构建成对应的 css
*/
module.exports = function ({ theme, options = {} }) {
return {
name: "semi-theme",
enforce: "post",
load(id) {
let filePath = normalizePath(id);
// https://github.com/DouyinFE/semi-design/blob/main/packages/semi-webpack/src/semi-webpack-plugin.ts#L83
if (
/@douyinfe\/semi-(ui|icons|foundation)\/lib\/.+\.css$/.test(filePath)
) {
let scssFilePath = filePath.replace(/\.css$/, ".scss");
// 目前只有 name
// https://github.com/DouyinFE/semi-design/blob/04d17a72846dfb5452801a556b6e01f9b0e8eb9d/packages/semi-webpack/src/semi-webpack-plugin.ts#L23
let semiSemiLoaderOptions = { name: theme };
return compileString(
// TODO (boen): 未解析 file query
loader(FS.readFileSync(scssFilePath).toString(), {
...semiSemiLoaderOptions,
...options,
variables: convertMapToString(options.variables || {}),
}),
{
importers: [
{
findFileUrl(url) {
if (url.startsWith("~")) {
return new URL(
url.substring(1),
pathToFileURL(
scssFilePath.match(/^(\S*\/node_modules\/)/)[0]
)
);
}
let filePath = Path.resolve(Path.dirname(scssFilePath), url);
if (FS.existsSync(filePath)) {
return pathToFileURL(filePath);
}
return null;
},
},
],
logger: Logger.silent,
}
).css;
}
},
};
};
// copy from https://github.com/DouyinFE/semi-design/blob/main/packages/semi-webpack/src/semi-theme-loader.ts
function loader(source, options) {
const theme = options.name || "@douyinfe/semi-theme-default";
// always inject
const scssVarStr = `@import "~${theme}/scss/index.scss";\n`;
// inject once
const cssVarStr = `@import "~${theme}/scss/global.scss";\n`;
const shouldInject = source.includes("semi-base");
let fileStr = source;
let componentVariables;
try {
componentVariables = resolve.sync(this.context, `${theme}/scss/local.scss`);
} catch (e) {}
if (options.include || options.variables || componentVariables) {
let localImport = "";
if (componentVariables) {
localImport += `\n@import "~${theme}/scss/local.scss";`;
}
if (options.include) {
localImport += `\n@import "${options.include}";`;
}
if (options.variables) {
localImport += `\n${options.variables}`;
}
try {
const regex =
/(@import '.\/variables.scss';?|@import ".\/variables.scss";?)/g;
const fileSplit = source.split(regex).filter((item) => Boolean(item));
if (fileSplit.length > 1) {
fileSplit.splice(fileSplit.length - 1, 0, localImport);
fileStr = fileSplit.join("");
}
} catch (error) {}
}
// inject prefix
const prefixCls = options.prefixCls || "semi";
const prefixClsStr = `$prefix: '${prefixCls}';\n`;
if (shouldInject) {
return `${cssVarStr}${scssVarStr}${prefixClsStr}${fileStr}`;
} else {
return `${scssVarStr}${prefixClsStr}${fileStr}`;
}
}
// copy from https://github.com/DouyinFE/semi-design/blob/main/packages/semi-webpack/src/semi-webpack-plugin.ts#L136
function convertMapToString(map) {
return Object.keys(map).reduce(function (prev, curr) {
return prev + `${curr}: ${map[curr]};\n`;
}, "");
}
function normalizePath(id) {
return Path.posix.normalize(
require("os").platform() === "win32" ? id.replace(/\\/g, "/") : id
);
}