micro-app/packages/icpx-organization/build/theme-config.ts

167 lines
4.5 KiB
TypeScript
Raw Normal View History

2023-05-30 19:27:03 +08:00
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 };