167 lines
4.5 KiB
TypeScript
167 lines
4.5 KiB
TypeScript
import fs, { readdirSync } from 'fs';
|
||
import path from 'path';
|
||
import type { UserConfig, PluginOption } from 'vite';
|
||
import { themePreprocessorPlugin } from '@crami/vite-plugin-theme-preprocessor';
|
||
import { defaultsDeep } from 'lodash-es';
|
||
import colors from 'colors';
|
||
|
||
const ADDITIONALFILENAME = 'app.less';
|
||
const THEMEVARIABLESFILENAME = 'variables.less';
|
||
const PATHRESOLVETO = '../src/theme/';
|
||
const uuid = `.${new Date().getTime()}`;
|
||
|
||
type IThemeUserConfig = {
|
||
env: IThemeEnvConfig;
|
||
userConfig: UserConfig;
|
||
};
|
||
|
||
type IThemeConfig = {
|
||
additionalDataName: string;
|
||
themesName: string[];
|
||
defaultThemeName: string;
|
||
rootPath: string;
|
||
};
|
||
|
||
type IThemeLoadConfigOptions = {
|
||
defaultThemeName: string;
|
||
};
|
||
|
||
type IThemeEnvConfig = {
|
||
VITE_ENV_THEME_DEFAULT: string;
|
||
};
|
||
|
||
const loadConfig = (options: IThemeLoadConfigOptions) => {
|
||
const dirname = __dirname;
|
||
const { defaultThemeName } = options;
|
||
const config: IThemeConfig = {
|
||
additionalDataName: '',
|
||
themesName: [],
|
||
defaultThemeName: '',
|
||
rootPath: '',
|
||
};
|
||
|
||
const themeRootPath = path.resolve(dirname, PATHRESOLVETO);
|
||
let dir;
|
||
try {
|
||
dir = readdirSync(themeRootPath);
|
||
} catch (e) {
|
||
console.log(
|
||
colors.red.underline('project file directory not exist the "src/theme/default" folder!'),
|
||
);
|
||
return null;
|
||
}
|
||
|
||
if (dir.includes(ADDITIONALFILENAME)) {
|
||
config.additionalDataName = ADDITIONALFILENAME;
|
||
}
|
||
|
||
dir.forEach(name => {
|
||
const themePath = path.resolve(themeRootPath, `./${name}`);
|
||
const stats = fs.statSync(themePath);
|
||
|
||
if (stats.isDirectory()) {
|
||
const dir = readdirSync(themePath);
|
||
if (dir.includes(THEMEVARIABLESFILENAME)) {
|
||
config.themesName.push(name);
|
||
}
|
||
}
|
||
});
|
||
|
||
config.defaultThemeName = defaultThemeName || config.themesName[0] || 'default';
|
||
config.rootPath = themeRootPath;
|
||
|
||
return config;
|
||
};
|
||
|
||
const addCssAdditionalDataConfig = (themeConfig: IThemeConfig, userConfig: UserConfig) => {
|
||
const _config: UserConfig = {
|
||
css: {
|
||
preprocessorOptions: {
|
||
less: {
|
||
additionalData: (content, filePath) => {
|
||
const srcAppLess =
|
||
path.resolve(themeConfig.rootPath, '..').replace(/\\/g, '/') + '/app.less';
|
||
|
||
if (filePath === srcAppLess) {
|
||
const _content = `${content} \n @import "./theme/app.less";`;
|
||
return _content;
|
||
}
|
||
|
||
return content;
|
||
},
|
||
javascriptEnabled: true,
|
||
},
|
||
},
|
||
},
|
||
};
|
||
defaultsDeep(userConfig, _config);
|
||
};
|
||
|
||
interface IUserConfig extends UserConfig {
|
||
plugins: PluginOption[];
|
||
optimizeDeps: {
|
||
exclude: string[];
|
||
};
|
||
}
|
||
|
||
const addThemePreprocessorPluginConfig = (themeConfig: IThemeConfig, userConfig: UserConfig) => {
|
||
const pluginConfig: UserConfig = {
|
||
plugins: [],
|
||
optimizeDeps: {
|
||
exclude: [],
|
||
},
|
||
};
|
||
defaultsDeep(userConfig, pluginConfig);
|
||
|
||
const config = userConfig as IUserConfig;
|
||
|
||
config.plugins = [
|
||
...config.plugins,
|
||
themePreprocessorPlugin({
|
||
less: {
|
||
// 是否启用任意主题色模式,这里不启用
|
||
arbitraryMode: false,
|
||
// 提供多组变量文件
|
||
multipleScopeVars: themeConfig.themesName.map(name => {
|
||
const _path = path.resolve(themeConfig.rootPath, `./${name}/${THEMEVARIABLESFILENAME}`);
|
||
//console.log(_path);
|
||
return {
|
||
scopeName: name,
|
||
path: _path,
|
||
};
|
||
}),
|
||
defaultScopeName: themeConfig.defaultThemeName,
|
||
// 在生产模式是否抽取独立的主题css文件,extract为true以下属性有效
|
||
// !!!【注意】这里必须是true
|
||
extract: true,
|
||
customThemeCssFileName: scopeName => scopeName + uuid,
|
||
removeCssScopeName: true,
|
||
},
|
||
}),
|
||
];
|
||
|
||
config.optimizeDeps.exclude = [
|
||
...config.optimizeDeps.exclude,
|
||
//【注意】 排除 import { toggleTheme } from "@crami/vite-plugin-theme-preprocessor/dist/browser-utils"; 在vite的缓存依赖
|
||
// 否则会造成切换失效
|
||
'@crami/vite-plugin-theme-preprocessor/dist/browser-utils',
|
||
];
|
||
};
|
||
|
||
const addThemeConfig = (options: IThemeUserConfig) => {
|
||
const { env, userConfig } = options;
|
||
const { VITE_ENV_THEME_DEFAULT: defaultThemeName } = env;
|
||
const themeConfig = loadConfig({ defaultThemeName });
|
||
if (!themeConfig) {
|
||
return;
|
||
}
|
||
if (themeConfig.additionalDataName) {
|
||
addCssAdditionalDataConfig(themeConfig, userConfig);
|
||
}
|
||
if (themeConfig.themesName && themeConfig.themesName.length > 0) {
|
||
addThemePreprocessorPluginConfig(themeConfig, userConfig);
|
||
}
|
||
};
|
||
|
||
export { addThemeConfig };
|