vite-plugin-theme-css 0.1.0 → 0.3.0
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/README.md +9 -4
- package/dist/constants.d.ts +7 -0
- package/dist/index.cjs +78 -43
- package/dist/index.mjs +79 -42
- package/dist/plugin-dir.d.ts +3 -0
- package/dist/types.d.ts +2 -0
- package/dist/utils/sass-importer.d.ts +3 -0
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -76,14 +76,16 @@ export default defineConfig({
|
|
|
76
76
|
})
|
|
77
77
|
```
|
|
78
78
|
|
|
79
|
-
### 3.
|
|
79
|
+
### 3. CSS 变量(自动注入)
|
|
80
80
|
|
|
81
|
-
|
|
81
|
+
默认会在 HTML 里自动注入主题 CSS 变量,**无需**在入口手动写:
|
|
82
82
|
|
|
83
83
|
```ts
|
|
84
|
-
import 'virtual:theme-css/css'
|
|
84
|
+
import 'virtual:theme-css/css' // 可省略
|
|
85
85
|
```
|
|
86
86
|
|
|
87
|
+
若需关闭自动注入,可设置 `autoImportCss: false`,再自行在入口 import。
|
|
88
|
+
|
|
87
89
|
生成示例:
|
|
88
90
|
|
|
89
91
|
```css
|
|
@@ -173,8 +175,11 @@ themeCss({
|
|
|
173
175
|
syncHtmlDark: true,
|
|
174
176
|
|
|
175
177
|
/** 排除自动注入 SCSS helper 的文件 */
|
|
176
|
-
exclude: [/node_modules/]
|
|
178
|
+
exclude: [/node_modules/],
|
|
177
179
|
// 或: (filename) => filename.includes('legacy')
|
|
180
|
+
|
|
181
|
+
/** 是否自动在 HTML 注入 CSS 变量,默认 true */
|
|
182
|
+
autoImportCss: true
|
|
178
183
|
})
|
|
179
184
|
```
|
|
180
185
|
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const VIRTUAL_CSS_ID = "virtual:theme-css/css";
|
|
2
|
+
export declare const VIRTUAL_CSS_RESOLVED = "\0virtual:theme-css.css";
|
|
3
|
+
export declare const VIRTUAL_SCSS_ID = "virtual:theme-css/scss";
|
|
4
|
+
export declare const VIRTUAL_SCSS_RESOLVED = "\0virtual:theme-css.scss";
|
|
5
|
+
export declare const VIRTUAL_RUNTIME_ID = "@scope/theme-css";
|
|
6
|
+
export declare const VIRTUAL_RUNTIME_DATA_ID = "virtual:theme-css/runtime-data";
|
|
7
|
+
export declare const VIRTUAL_RUNTIME_DATA_RESOLVED = "\0virtual:theme-css/runtime-data";
|
package/dist/index.cjs
CHANGED
|
@@ -36,17 +36,26 @@ __export(src_exports, {
|
|
|
36
36
|
});
|
|
37
37
|
module.exports = __toCommonJS(src_exports);
|
|
38
38
|
var import_node_fs = require("fs");
|
|
39
|
-
var
|
|
40
|
-
var import_node_url = require("url");
|
|
39
|
+
var import_node_path2 = __toESM(require("path"), 1);
|
|
41
40
|
var import_node_module = require("module");
|
|
42
41
|
var import_jiti = require("jiti");
|
|
43
42
|
|
|
43
|
+
// src/constants.ts
|
|
44
|
+
var VIRTUAL_CSS_ID = "virtual:theme-css/css";
|
|
45
|
+
var VIRTUAL_CSS_RESOLVED = "\0virtual:theme-css.css";
|
|
46
|
+
var VIRTUAL_SCSS_ID = "virtual:theme-css/scss";
|
|
47
|
+
var VIRTUAL_SCSS_RESOLVED = "\0virtual:theme-css.scss";
|
|
48
|
+
var VIRTUAL_RUNTIME_ID = "@scope/theme-css";
|
|
49
|
+
var VIRTUAL_RUNTIME_DATA_ID = "virtual:theme-css/runtime-data";
|
|
50
|
+
var VIRTUAL_RUNTIME_DATA_RESOLVED = "\0virtual:theme-css/runtime-data";
|
|
51
|
+
|
|
44
52
|
// src/types.ts
|
|
45
53
|
var defaultOptions = {
|
|
46
54
|
config: "./theme.config.ts",
|
|
47
55
|
scssNamespace: "token",
|
|
48
56
|
syncHtmlDark: true,
|
|
49
|
-
exclude: []
|
|
57
|
+
exclude: [],
|
|
58
|
+
autoImportCss: true
|
|
50
59
|
};
|
|
51
60
|
|
|
52
61
|
// src/utils/flatten.ts
|
|
@@ -86,8 +95,8 @@ var generateThemeCss = (config) => {
|
|
|
86
95
|
return lines.join("\n");
|
|
87
96
|
};
|
|
88
97
|
|
|
89
|
-
// src/generate/scss/
|
|
90
|
-
var
|
|
98
|
+
// src/generate/scss/index.ts
|
|
99
|
+
var generateScssHelper = () => `// \u5185\u90E8\u5DE5\u5177\uFF1A\u62FC\u63A5\u591A\u4E2A key\r
|
|
91
100
|
@function _join-keys($keys...) {\r
|
|
92
101
|
$result: '';\r
|
|
93
102
|
@each $key in $keys {\r
|
|
@@ -118,9 +127,6 @@ var helper_default = `// \u5185\u90E8\u5DE5\u5177\uFF1A\u62FC\u63A5\u591A\u4E2A
|
|
|
118
127
|
}\r
|
|
119
128
|
`;
|
|
120
129
|
|
|
121
|
-
// src/generate/scss/index.ts
|
|
122
|
-
var generateScssHelper = () => helper_default;
|
|
123
|
-
|
|
124
130
|
// src/generate/js/index.ts
|
|
125
131
|
function generateJs(config, options) {
|
|
126
132
|
return `export const config = ${JSON.stringify(config, null, 2)}
|
|
@@ -128,6 +134,28 @@ export const options = ${JSON.stringify(options)}
|
|
|
128
134
|
`;
|
|
129
135
|
}
|
|
130
136
|
|
|
137
|
+
// src/utils/sass-importer.ts
|
|
138
|
+
var canonicalUrl = new URL(`${VIRTUAL_SCSS_ID}.scss`);
|
|
139
|
+
function createVirtualScssImporter(getContent) {
|
|
140
|
+
return {
|
|
141
|
+
canonicalize(url) {
|
|
142
|
+
if (url === VIRTUAL_SCSS_ID) return canonicalUrl;
|
|
143
|
+
return null;
|
|
144
|
+
},
|
|
145
|
+
load(canonical) {
|
|
146
|
+
if (canonical.href === canonicalUrl.href) {
|
|
147
|
+
return { contents: getContent(), syntax: "scss" };
|
|
148
|
+
}
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// src/plugin-dir.ts
|
|
155
|
+
var import_node_path = __toESM(require("path"), 1);
|
|
156
|
+
var pluginFilename = __filename;
|
|
157
|
+
var pluginDir = import_node_path.default.dirname(__filename);
|
|
158
|
+
|
|
131
159
|
// src/defineTheme.ts
|
|
132
160
|
function defineTheme(config) {
|
|
133
161
|
return config;
|
|
@@ -171,33 +199,21 @@ function createThemeRuntime(config, options = {}) {
|
|
|
171
199
|
}
|
|
172
200
|
|
|
173
201
|
// src/index.ts
|
|
174
|
-
var
|
|
175
|
-
var require2 = (0, import_node_module.createRequire)(import_meta.url);
|
|
202
|
+
var require2 = (0, import_node_module.createRequire)(pluginFilename);
|
|
176
203
|
var babelTransform = (0, import_node_module.createRequire)(require2.resolve("jiti/package.json"))("./dist/babel.cjs");
|
|
177
|
-
var VIRTUAL_CSS_ID = "virtual:theme-css/css";
|
|
178
|
-
var VIRTUAL_CSS_RESOLVED = "\0virtual:theme-css.css";
|
|
179
|
-
var VIRTUAL_SCSS_ID = "virtual:theme-css/scss";
|
|
180
|
-
var VIRTUAL_SCSS_RESOLVED = "\0virtual:theme-css.scss";
|
|
181
|
-
var VIRTUAL_RUNTIME_ID = "@scope/theme-css";
|
|
182
|
-
var VIRTUAL_RUNTIME_DATA_ID = "virtual:theme-css/runtime-data";
|
|
183
|
-
var VIRTUAL_RUNTIME_DATA_RESOLVED = "\0virtual:theme-css/runtime-data";
|
|
184
204
|
function resolveRuntimeEntryPath() {
|
|
185
|
-
const
|
|
186
|
-
const distEntry = import_node_path.default.join(here, "runtime-entry.mjs");
|
|
205
|
+
const distEntry = import_node_path2.default.join(pluginDir, "runtime-entry.mjs");
|
|
187
206
|
if ((0, import_node_fs.existsSync)(distEntry)) return distEntry;
|
|
188
|
-
return
|
|
207
|
+
return import_node_path2.default.join(pluginDir, "runtime", "virtual-entry.ts");
|
|
189
208
|
}
|
|
190
209
|
function themeCss(options = {}) {
|
|
191
210
|
const resolvedOptions = { ...defaultOptions, ...options };
|
|
192
|
-
const { config: configPath, scssNamespace, syncHtmlDark, exclude } = resolvedOptions;
|
|
193
|
-
let viteConfig;
|
|
194
|
-
let themeConfig;
|
|
211
|
+
const { config: configPath, scssNamespace, syncHtmlDark, exclude, autoImportCss } = resolvedOptions;
|
|
195
212
|
let cssContent = "";
|
|
196
|
-
let scssHelperContent = "";
|
|
197
213
|
let runtimeDataContent = "";
|
|
198
214
|
const runtimeEntryPath = resolveRuntimeEntryPath();
|
|
199
215
|
async function loadConfigAndGenerate() {
|
|
200
|
-
const jiti = (0, import_jiti.createJiti)(
|
|
216
|
+
const jiti = (0, import_jiti.createJiti)(pluginFilename, {
|
|
201
217
|
interopDefault: true,
|
|
202
218
|
transform: (opts) => {
|
|
203
219
|
let { source } = opts;
|
|
@@ -210,16 +226,14 @@ ${source}`;
|
|
|
210
226
|
return babelTransform({ ...opts, source });
|
|
211
227
|
}
|
|
212
228
|
});
|
|
213
|
-
const mod = await jiti.import(
|
|
214
|
-
themeConfig = mod.default;
|
|
229
|
+
const mod = await jiti.import(import_node_path2.default.resolve(configPath));
|
|
230
|
+
const themeConfig = mod.default;
|
|
215
231
|
cssContent = generateThemeCss(themeConfig);
|
|
216
|
-
scssHelperContent = generateScssHelper();
|
|
217
232
|
runtimeDataContent = generateJs(themeConfig, { syncHtmlDark });
|
|
218
233
|
}
|
|
219
234
|
return {
|
|
220
235
|
name: "vite-plugin-theme-css",
|
|
221
|
-
async configResolved(
|
|
222
|
-
viteConfig = config;
|
|
236
|
+
async configResolved() {
|
|
223
237
|
await loadConfigAndGenerate();
|
|
224
238
|
},
|
|
225
239
|
resolveId(id) {
|
|
@@ -241,52 +255,73 @@ ${source}`;
|
|
|
241
255
|
case VIRTUAL_CSS_RESOLVED:
|
|
242
256
|
return cssContent;
|
|
243
257
|
case VIRTUAL_SCSS_RESOLVED:
|
|
244
|
-
return
|
|
258
|
+
return generateScssHelper();
|
|
245
259
|
case VIRTUAL_RUNTIME_DATA_RESOLVED:
|
|
246
260
|
return runtimeDataContent;
|
|
247
261
|
default:
|
|
248
262
|
return null;
|
|
249
263
|
}
|
|
250
264
|
},
|
|
265
|
+
async transformIndexHtml(html) {
|
|
266
|
+
if (!autoImportCss || html.includes("data-theme-css-vars")) return;
|
|
267
|
+
if (!cssContent) await loadConfigAndGenerate();
|
|
268
|
+
return [
|
|
269
|
+
{
|
|
270
|
+
tag: "style",
|
|
271
|
+
attrs: { "data-theme-css-vars": "" },
|
|
272
|
+
children: cssContent,
|
|
273
|
+
injectTo: "head-prepend"
|
|
274
|
+
}
|
|
275
|
+
];
|
|
276
|
+
},
|
|
251
277
|
config(userConfig) {
|
|
252
278
|
const scssOptions = userConfig.css?.preprocessorOptions?.scss ?? {};
|
|
253
279
|
const userAdditionalData = scssOptions.additionalData;
|
|
254
280
|
const ourPrefix = `@use "${VIRTUAL_SCSS_ID}" as ${scssNamespace};
|
|
255
281
|
`;
|
|
256
|
-
const
|
|
257
|
-
if (
|
|
258
|
-
return
|
|
282
|
+
const applyUserAdditionalData = async (source, filename) => {
|
|
283
|
+
if (typeof userAdditionalData === "function") {
|
|
284
|
+
return userAdditionalData(source, filename);
|
|
285
|
+
}
|
|
286
|
+
if (userAdditionalData) {
|
|
287
|
+
return userAdditionalData + source;
|
|
259
288
|
}
|
|
260
|
-
|
|
289
|
+
return source;
|
|
290
|
+
};
|
|
291
|
+
const wrappedAdditionalData = async (source, filename) => {
|
|
292
|
+
const skipInject = filename.includes("virtual:theme-css") || (Array.isArray(exclude) ? exclude.some((rule) => {
|
|
261
293
|
if (typeof rule === "string") return filename.includes(rule);
|
|
262
294
|
if (rule instanceof RegExp) return rule.test(filename);
|
|
263
295
|
return false;
|
|
264
|
-
}) : typeof exclude === "function" ? exclude(filename) : false;
|
|
265
|
-
if (
|
|
266
|
-
return
|
|
296
|
+
}) : typeof exclude === "function" ? exclude(filename) : false);
|
|
297
|
+
if (skipInject) {
|
|
298
|
+
return applyUserAdditionalData(source, filename);
|
|
267
299
|
}
|
|
268
|
-
|
|
269
|
-
return ourPrefix + userContent;
|
|
300
|
+
return ourPrefix + await applyUserAdditionalData(source, filename);
|
|
270
301
|
};
|
|
302
|
+
const userImporters = Array.isArray(scssOptions.importers) ? scssOptions.importers : [];
|
|
271
303
|
return {
|
|
272
304
|
css: {
|
|
273
305
|
preprocessorOptions: {
|
|
274
306
|
scss: {
|
|
275
307
|
...scssOptions,
|
|
276
|
-
additionalData: wrappedAdditionalData
|
|
308
|
+
additionalData: wrappedAdditionalData,
|
|
309
|
+
importers: [
|
|
310
|
+
createVirtualScssImporter(generateScssHelper),
|
|
311
|
+
...userImporters
|
|
312
|
+
]
|
|
277
313
|
}
|
|
278
314
|
}
|
|
279
315
|
}
|
|
280
316
|
};
|
|
281
317
|
},
|
|
282
318
|
async handleHotUpdate(ctx) {
|
|
283
|
-
const configAbsPath =
|
|
319
|
+
const configAbsPath = import_node_path2.default.resolve(configPath);
|
|
284
320
|
if (ctx.file === configAbsPath) {
|
|
285
321
|
await loadConfigAndGenerate();
|
|
286
322
|
const moduleGraph = ctx.server.moduleGraph;
|
|
287
323
|
for (const id of [
|
|
288
324
|
VIRTUAL_CSS_RESOLVED,
|
|
289
|
-
VIRTUAL_SCSS_RESOLVED,
|
|
290
325
|
VIRTUAL_RUNTIME_DATA_RESOLVED,
|
|
291
326
|
runtimeEntryPath
|
|
292
327
|
]) {
|
package/dist/index.mjs
CHANGED
|
@@ -1,16 +1,25 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
import { existsSync } from "fs";
|
|
3
|
-
import
|
|
4
|
-
import { fileURLToPath } from "url";
|
|
3
|
+
import path2 from "path";
|
|
5
4
|
import { createRequire } from "module";
|
|
6
5
|
import { createJiti } from "jiti";
|
|
7
6
|
|
|
7
|
+
// src/constants.ts
|
|
8
|
+
var VIRTUAL_CSS_ID = "virtual:theme-css/css";
|
|
9
|
+
var VIRTUAL_CSS_RESOLVED = "\0virtual:theme-css.css";
|
|
10
|
+
var VIRTUAL_SCSS_ID = "virtual:theme-css/scss";
|
|
11
|
+
var VIRTUAL_SCSS_RESOLVED = "\0virtual:theme-css.scss";
|
|
12
|
+
var VIRTUAL_RUNTIME_ID = "@scope/theme-css";
|
|
13
|
+
var VIRTUAL_RUNTIME_DATA_ID = "virtual:theme-css/runtime-data";
|
|
14
|
+
var VIRTUAL_RUNTIME_DATA_RESOLVED = "\0virtual:theme-css/runtime-data";
|
|
15
|
+
|
|
8
16
|
// src/types.ts
|
|
9
17
|
var defaultOptions = {
|
|
10
18
|
config: "./theme.config.ts",
|
|
11
19
|
scssNamespace: "token",
|
|
12
20
|
syncHtmlDark: true,
|
|
13
|
-
exclude: []
|
|
21
|
+
exclude: [],
|
|
22
|
+
autoImportCss: true
|
|
14
23
|
};
|
|
15
24
|
|
|
16
25
|
// src/utils/flatten.ts
|
|
@@ -50,8 +59,8 @@ var generateThemeCss = (config) => {
|
|
|
50
59
|
return lines.join("\n");
|
|
51
60
|
};
|
|
52
61
|
|
|
53
|
-
// src/generate/scss/
|
|
54
|
-
var
|
|
62
|
+
// src/generate/scss/index.ts
|
|
63
|
+
var generateScssHelper = () => `// \u5185\u90E8\u5DE5\u5177\uFF1A\u62FC\u63A5\u591A\u4E2A key\r
|
|
55
64
|
@function _join-keys($keys...) {\r
|
|
56
65
|
$result: '';\r
|
|
57
66
|
@each $key in $keys {\r
|
|
@@ -82,9 +91,6 @@ var helper_default = `// \u5185\u90E8\u5DE5\u5177\uFF1A\u62FC\u63A5\u591A\u4E2A
|
|
|
82
91
|
}\r
|
|
83
92
|
`;
|
|
84
93
|
|
|
85
|
-
// src/generate/scss/index.ts
|
|
86
|
-
var generateScssHelper = () => helper_default;
|
|
87
|
-
|
|
88
94
|
// src/generate/js/index.ts
|
|
89
95
|
function generateJs(config, options) {
|
|
90
96
|
return `export const config = ${JSON.stringify(config, null, 2)}
|
|
@@ -92,6 +98,29 @@ export const options = ${JSON.stringify(options)}
|
|
|
92
98
|
`;
|
|
93
99
|
}
|
|
94
100
|
|
|
101
|
+
// src/utils/sass-importer.ts
|
|
102
|
+
var canonicalUrl = new URL(`${VIRTUAL_SCSS_ID}.scss`);
|
|
103
|
+
function createVirtualScssImporter(getContent) {
|
|
104
|
+
return {
|
|
105
|
+
canonicalize(url) {
|
|
106
|
+
if (url === VIRTUAL_SCSS_ID) return canonicalUrl;
|
|
107
|
+
return null;
|
|
108
|
+
},
|
|
109
|
+
load(canonical) {
|
|
110
|
+
if (canonical.href === canonicalUrl.href) {
|
|
111
|
+
return { contents: getContent(), syntax: "scss" };
|
|
112
|
+
}
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// src/plugin-dir.ts
|
|
119
|
+
import path from "path";
|
|
120
|
+
import { fileURLToPath } from "url";
|
|
121
|
+
var pluginFilename = fileURLToPath(import.meta.url);
|
|
122
|
+
var pluginDir = path.dirname(pluginFilename);
|
|
123
|
+
|
|
95
124
|
// src/defineTheme.ts
|
|
96
125
|
function defineTheme(config) {
|
|
97
126
|
return config;
|
|
@@ -135,32 +164,21 @@ function createThemeRuntime(config, options = {}) {
|
|
|
135
164
|
}
|
|
136
165
|
|
|
137
166
|
// src/index.ts
|
|
138
|
-
var require2 = createRequire(
|
|
167
|
+
var require2 = createRequire(pluginFilename);
|
|
139
168
|
var babelTransform = createRequire(require2.resolve("jiti/package.json"))("./dist/babel.cjs");
|
|
140
|
-
var VIRTUAL_CSS_ID = "virtual:theme-css/css";
|
|
141
|
-
var VIRTUAL_CSS_RESOLVED = "\0virtual:theme-css.css";
|
|
142
|
-
var VIRTUAL_SCSS_ID = "virtual:theme-css/scss";
|
|
143
|
-
var VIRTUAL_SCSS_RESOLVED = "\0virtual:theme-css.scss";
|
|
144
|
-
var VIRTUAL_RUNTIME_ID = "@scope/theme-css";
|
|
145
|
-
var VIRTUAL_RUNTIME_DATA_ID = "virtual:theme-css/runtime-data";
|
|
146
|
-
var VIRTUAL_RUNTIME_DATA_RESOLVED = "\0virtual:theme-css/runtime-data";
|
|
147
169
|
function resolveRuntimeEntryPath() {
|
|
148
|
-
const
|
|
149
|
-
const distEntry = path.join(here, "runtime-entry.mjs");
|
|
170
|
+
const distEntry = path2.join(pluginDir, "runtime-entry.mjs");
|
|
150
171
|
if (existsSync(distEntry)) return distEntry;
|
|
151
|
-
return
|
|
172
|
+
return path2.join(pluginDir, "runtime", "virtual-entry.ts");
|
|
152
173
|
}
|
|
153
174
|
function themeCss(options = {}) {
|
|
154
175
|
const resolvedOptions = { ...defaultOptions, ...options };
|
|
155
|
-
const { config: configPath, scssNamespace, syncHtmlDark, exclude } = resolvedOptions;
|
|
156
|
-
let viteConfig;
|
|
157
|
-
let themeConfig;
|
|
176
|
+
const { config: configPath, scssNamespace, syncHtmlDark, exclude, autoImportCss } = resolvedOptions;
|
|
158
177
|
let cssContent = "";
|
|
159
|
-
let scssHelperContent = "";
|
|
160
178
|
let runtimeDataContent = "";
|
|
161
179
|
const runtimeEntryPath = resolveRuntimeEntryPath();
|
|
162
180
|
async function loadConfigAndGenerate() {
|
|
163
|
-
const jiti = createJiti(
|
|
181
|
+
const jiti = createJiti(pluginFilename, {
|
|
164
182
|
interopDefault: true,
|
|
165
183
|
transform: (opts) => {
|
|
166
184
|
let { source } = opts;
|
|
@@ -173,16 +191,14 @@ ${source}`;
|
|
|
173
191
|
return babelTransform({ ...opts, source });
|
|
174
192
|
}
|
|
175
193
|
});
|
|
176
|
-
const mod = await jiti.import(
|
|
177
|
-
themeConfig = mod.default;
|
|
194
|
+
const mod = await jiti.import(path2.resolve(configPath));
|
|
195
|
+
const themeConfig = mod.default;
|
|
178
196
|
cssContent = generateThemeCss(themeConfig);
|
|
179
|
-
scssHelperContent = generateScssHelper();
|
|
180
197
|
runtimeDataContent = generateJs(themeConfig, { syncHtmlDark });
|
|
181
198
|
}
|
|
182
199
|
return {
|
|
183
200
|
name: "vite-plugin-theme-css",
|
|
184
|
-
async configResolved(
|
|
185
|
-
viteConfig = config;
|
|
201
|
+
async configResolved() {
|
|
186
202
|
await loadConfigAndGenerate();
|
|
187
203
|
},
|
|
188
204
|
resolveId(id) {
|
|
@@ -204,52 +220,73 @@ ${source}`;
|
|
|
204
220
|
case VIRTUAL_CSS_RESOLVED:
|
|
205
221
|
return cssContent;
|
|
206
222
|
case VIRTUAL_SCSS_RESOLVED:
|
|
207
|
-
return
|
|
223
|
+
return generateScssHelper();
|
|
208
224
|
case VIRTUAL_RUNTIME_DATA_RESOLVED:
|
|
209
225
|
return runtimeDataContent;
|
|
210
226
|
default:
|
|
211
227
|
return null;
|
|
212
228
|
}
|
|
213
229
|
},
|
|
230
|
+
async transformIndexHtml(html) {
|
|
231
|
+
if (!autoImportCss || html.includes("data-theme-css-vars")) return;
|
|
232
|
+
if (!cssContent) await loadConfigAndGenerate();
|
|
233
|
+
return [
|
|
234
|
+
{
|
|
235
|
+
tag: "style",
|
|
236
|
+
attrs: { "data-theme-css-vars": "" },
|
|
237
|
+
children: cssContent,
|
|
238
|
+
injectTo: "head-prepend"
|
|
239
|
+
}
|
|
240
|
+
];
|
|
241
|
+
},
|
|
214
242
|
config(userConfig) {
|
|
215
243
|
const scssOptions = userConfig.css?.preprocessorOptions?.scss ?? {};
|
|
216
244
|
const userAdditionalData = scssOptions.additionalData;
|
|
217
245
|
const ourPrefix = `@use "${VIRTUAL_SCSS_ID}" as ${scssNamespace};
|
|
218
246
|
`;
|
|
219
|
-
const
|
|
220
|
-
if (
|
|
221
|
-
return
|
|
247
|
+
const applyUserAdditionalData = async (source, filename) => {
|
|
248
|
+
if (typeof userAdditionalData === "function") {
|
|
249
|
+
return userAdditionalData(source, filename);
|
|
250
|
+
}
|
|
251
|
+
if (userAdditionalData) {
|
|
252
|
+
return userAdditionalData + source;
|
|
222
253
|
}
|
|
223
|
-
|
|
254
|
+
return source;
|
|
255
|
+
};
|
|
256
|
+
const wrappedAdditionalData = async (source, filename) => {
|
|
257
|
+
const skipInject = filename.includes("virtual:theme-css") || (Array.isArray(exclude) ? exclude.some((rule) => {
|
|
224
258
|
if (typeof rule === "string") return filename.includes(rule);
|
|
225
259
|
if (rule instanceof RegExp) return rule.test(filename);
|
|
226
260
|
return false;
|
|
227
|
-
}) : typeof exclude === "function" ? exclude(filename) : false;
|
|
228
|
-
if (
|
|
229
|
-
return
|
|
261
|
+
}) : typeof exclude === "function" ? exclude(filename) : false);
|
|
262
|
+
if (skipInject) {
|
|
263
|
+
return applyUserAdditionalData(source, filename);
|
|
230
264
|
}
|
|
231
|
-
|
|
232
|
-
return ourPrefix + userContent;
|
|
265
|
+
return ourPrefix + await applyUserAdditionalData(source, filename);
|
|
233
266
|
};
|
|
267
|
+
const userImporters = Array.isArray(scssOptions.importers) ? scssOptions.importers : [];
|
|
234
268
|
return {
|
|
235
269
|
css: {
|
|
236
270
|
preprocessorOptions: {
|
|
237
271
|
scss: {
|
|
238
272
|
...scssOptions,
|
|
239
|
-
additionalData: wrappedAdditionalData
|
|
273
|
+
additionalData: wrappedAdditionalData,
|
|
274
|
+
importers: [
|
|
275
|
+
createVirtualScssImporter(generateScssHelper),
|
|
276
|
+
...userImporters
|
|
277
|
+
]
|
|
240
278
|
}
|
|
241
279
|
}
|
|
242
280
|
}
|
|
243
281
|
};
|
|
244
282
|
},
|
|
245
283
|
async handleHotUpdate(ctx) {
|
|
246
|
-
const configAbsPath =
|
|
284
|
+
const configAbsPath = path2.resolve(configPath);
|
|
247
285
|
if (ctx.file === configAbsPath) {
|
|
248
286
|
await loadConfigAndGenerate();
|
|
249
287
|
const moduleGraph = ctx.server.moduleGraph;
|
|
250
288
|
for (const id of [
|
|
251
289
|
VIRTUAL_CSS_RESOLVED,
|
|
252
|
-
VIRTUAL_SCSS_RESOLVED,
|
|
253
290
|
VIRTUAL_RUNTIME_DATA_RESOLVED,
|
|
254
291
|
runtimeEntryPath
|
|
255
292
|
]) {
|
package/dist/types.d.ts
CHANGED
|
@@ -11,5 +11,7 @@ export interface ThemeCssOptions {
|
|
|
11
11
|
syncHtmlDark?: boolean;
|
|
12
12
|
/** 排除注入 SCSS helper 的文件规则 */
|
|
13
13
|
exclude?: (string | RegExp)[] | ((filename: string) => boolean);
|
|
14
|
+
/** 是否自动在 HTML 注入 CSS 变量,默认 true */
|
|
15
|
+
autoImportCss?: boolean;
|
|
14
16
|
}
|
|
15
17
|
export declare const defaultOptions: Required<ThemeCssOptions>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vite-plugin-theme-css",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Vite 插件:用一份主题配置生成 CSS 变量、SCSS helper 与 JS 运行时,支持多主题切换与热更新",
|
|
5
5
|
"author": "yuzinan <1589937631@qq.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -53,6 +53,7 @@
|
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
55
|
"@types/node": "^26.2.0",
|
|
56
|
+
"esbuild": "^0.28.2",
|
|
56
57
|
"prettier": "3.9.6",
|
|
57
58
|
"sass": "^1.103.0",
|
|
58
59
|
"tsup": "^8.5.1",
|
|
@@ -63,6 +64,7 @@
|
|
|
63
64
|
"scripts": {
|
|
64
65
|
"build": "tsup && tsc -p tsconfig.build.json",
|
|
65
66
|
"dev": "tsup --watch",
|
|
67
|
+
"play": "vite --config playground/vite.config.ts",
|
|
66
68
|
"test": "vitest",
|
|
67
69
|
"format": "prettier --write .",
|
|
68
70
|
"format:check": "prettier --check .",
|