vite-plugin-style-import
Version:
A plug-in that imports component library styles on demand
314 lines (299 loc) • 9.2 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
const pluginutils = require('@rollup/pluginutils');
const changeCase = require('change-case');
const esModuleLexer = require('es-module-lexer');
const MagicString = require('magic-string');
const path = require('pathe');
const consola = require('consola');
const vite = require('vite');
const fs = require('fs-extra');
const module$1 = require('module');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e["default"] : e; }
function _interopNamespace(e) {
if (e && e.__esModule) return e;
const n = Object.create(null);
if (e) {
for (const k in e) {
n[k] = e[k];
}
}
n["default"] = e;
return n;
}
const changeCase__namespace = /*#__PURE__*/_interopNamespace(changeCase);
const MagicString__default = /*#__PURE__*/_interopDefaultLegacy(MagicString);
const path__default = /*#__PURE__*/_interopDefaultLegacy(path);
const consola__default = /*#__PURE__*/_interopDefaultLegacy(consola);
const fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
function resolveNodeModules(libName, ...dir) {
const esRequire = module$1.createRequire((typeof document === 'undefined' ? new (require('u' + 'rl').URL)('file:' + __filename).href : (document.currentScript && document.currentScript.src || new URL('index.cjs', document.baseURI).href)));
let modulePath = "";
try {
modulePath = vite.normalizePath(esRequire.resolve(libName));
} catch (error) {
modulePath = vite.normalizePath(require.resolve(libName));
}
const lastIndex = modulePath.lastIndexOf(libName);
return vite.normalizePath(path__default.resolve(modulePath.substring(0, lastIndex), ...dir));
}
function resolvePnp(module) {
try {
return vite.normalizePath(require.resolve(module));
} catch (error) {
return "";
}
}
const isPnp = !!process.versions.pnp;
function isRegExp(value) {
return Object.prototype.toString.call(value) === "[object RegExp]";
}
function fileExists(f) {
try {
fs__default.accessSync(f, fs__default.constants.W_OK);
return true;
} catch (error) {
return false;
}
}
function isFunction(value) {
return value != null && Object.prototype.toString.call(value) === "[object Function]";
}
function AntdResolve() {
return {
libraryName: "antd",
esModule: true,
resolveStyle: (name) => {
return `antd/es/${name}/style/index`;
}
};
}
function AndDesignVueResolve() {
return {
ensureStyleFile: true,
libraryName: "ant-design-vue",
esModule: true,
resolveStyle: (name) => {
return `ant-design-vue/es/${name}/style/index`;
}
};
}
function ElementPlusResolve() {
return {
libraryName: "element-plus",
ensureStyleFile: true,
esModule: true,
resolveStyle: (name) => {
return `element-plus/theme-chalk/${name}.css`;
},
base: "element-plus/theme-chalk/base.css"
};
}
function VantResolve() {
return {
libraryName: "vant",
esModule: true,
resolveStyle: (name) => {
return `vant/es/${name}/style`;
}
};
}
function NutuiResolve() {
return {
libraryName: "@nutui/nutui",
libraryNameChangeCase: "pascalCase",
resolveStyle: (name) => {
return `@nutui/nutui/dist/packages/${name}/index.scss`;
}
};
}
function VxeTableResolve() {
return {
ensureStyleFile: true,
libraryName: "vxe-table",
esModule: true,
resolveStyle: (name) => {
return `vxe-table/es/${name}/style.css`;
}
};
}
const ensureFileExts = [".css", ".js", ".scss", ".less", ".styl"];
const asRE = /\s+as\s+\w+,?/g;
consola__default.wrapConsole();
function createStyleImportPlugin(options) {
const {
include = ["**/*.vue", "**/*.ts", "**/*.js", "**/*.tsx", "**/*.jsx"],
exclude = "node_modules/**",
resolves = []
} = options;
let { libs = [] } = options;
libs = [...libs, ...resolves];
const filter = pluginutils.createFilter(include, exclude);
let needSourcemap = false;
let external;
return {
name: "vite:style-import",
enforce: "post",
configResolved(resolvedConfig) {
needSourcemap = !!resolvedConfig.build.sourcemap;
external = resolvedConfig?.build?.rollupOptions?.external ?? void 0;
},
async transform(code, id) {
if (!code || !filter(id) || !needTransform(code, libs)) {
return null;
}
await esModuleLexer.init;
let imports = [];
try {
imports = esModuleLexer.parse(code)[0];
} catch (e) {
consola__default.error(e);
}
if (!imports.length) {
return null;
}
let s;
const str = () => s || (s = new MagicString__default(code));
for (let index = 0; index < imports.length; index++) {
const { n, se, ss } = imports[index];
if (!n)
continue;
const lib = getLib(n, libs, external);
if (!lib)
continue;
const importStr = code.slice(ss, se);
let importVariables = transformImportVar(importStr);
importVariables = filterImportVariables(importVariables, lib.importTest);
const importCssStrList = await transformComponentCss(lib, importVariables);
const compStrList = [];
const { base = "" } = lib;
let baseImporter = base ? `
import '${base}'` : "";
if (str().toString().includes(base)) {
baseImporter = "";
}
const endIndex = se + 1;
str().prependRight(endIndex, `${baseImporter}
${compStrList.join("")}${importCssStrList.join("")}`);
}
return {
map: needSourcemap ? str().generateMap({ hires: true }) : null,
code: str().toString()
};
}
};
}
function filterImportVariables(importVars, reg) {
if (!reg) {
return importVars;
}
return importVars.filter((item) => reg.test(item));
}
async function transformComponentCss(lib, importVariables) {
const {
libraryName,
resolveStyle,
esModule,
libraryNameChangeCase = "paramCase",
ensureStyleFile = false
} = lib;
if (!isFunction(resolveStyle) || !libraryName) {
return [];
}
const set = /* @__PURE__ */ new Set();
for (let index = 0; index < importVariables.length; index++) {
const name = getChangeCaseFileName(importVariables[index], libraryNameChangeCase);
let importStr = resolveStyle(name);
if (!importStr) {
continue;
}
let isAdd = true;
if (isPnp) {
importStr = resolvePnp(importStr);
isAdd = !!importStr;
} else {
if (esModule) {
importStr = resolveNodeModules(libraryName, importStr);
}
if (ensureStyleFile) {
isAdd = ensureFileExists(libraryName, importStr, esModule);
}
}
isAdd && set.add(`import '${importStr}';
`);
}
return Array.from(set);
}
function transformImportVar(importStr) {
if (!importStr) {
return [];
}
const exportStr = importStr.replace("import", "export").replace(asRE, ",");
let importVariables = [];
try {
importVariables = esModuleLexer.parse(exportStr)[1];
} catch (error) {
consola__default.error(error);
}
return importVariables;
}
function ensureFileExists(libraryName, importStr, esModule = false) {
const extName = path__default.extname(importStr);
if (!extName) {
return tryEnsureFile(libraryName, importStr, esModule);
}
if (esModule) {
return fileExists(importStr);
}
return true;
}
function tryEnsureFile(libraryName, filePath, esModule = false) {
const filePathList = ensureFileExts.map((item) => {
const p = `${filePath}${item}`;
return esModule ? p : resolveNodeModules(libraryName, p);
});
return filePathList.some((item) => fileExists(item));
}
function getLib(libraryName, libs, external) {
let libList = libs;
if (external) {
const isString = typeof external === "string";
const isRE = isRegExp(external);
if (isString) {
libList = libList.filter((item) => item.libraryName !== external);
} else if (isRE) {
libList = libList.filter((item) => !external.test(item.libraryName));
} else if (Array.isArray(external)) {
libList = libList.filter((item) => {
return !external.some((val) => {
if (typeof val === "string") {
return val === item.libraryName;
}
return val.test(item.libraryName);
});
});
}
}
return libList.find((item) => item.libraryName === libraryName);
}
function getChangeCaseFileName(importedName, libraryNameChangeCase) {
try {
return changeCase__namespace[libraryNameChangeCase](importedName);
} catch (error) {
return importedName;
}
}
function needTransform(code, libs) {
return !libs.every(({ libraryName }) => {
return !new RegExp(`('${libraryName}')|("${libraryName}")`).test(code);
});
}
exports.AndDesignVueResolve = AndDesignVueResolve;
exports.AntdResolve = AntdResolve;
exports.ElementPlusResolve = ElementPlusResolve;
exports.NutuiResolve = NutuiResolve;
exports.VantResolve = VantResolve;
exports.VxeTableResolve = VxeTableResolve;
exports.createStyleImportPlugin = createStyleImportPlugin;
exports.getChangeCaseFileName = getChangeCaseFileName;
exports.transformImportVar = transformImportVar;