index.mjs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
  2. get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
  3. }) : x)(function(x) {
  4. if (typeof require !== "undefined")
  5. return require.apply(this, arguments);
  6. throw new Error('Dynamic require of "' + x + '" is not supported');
  7. });
  8. // src/index.ts
  9. import { createFilter } from "@rollup/pluginutils";
  10. import * as changeCase from "change-case";
  11. import { init, parse } from "es-module-lexer";
  12. import MagicString from "magic-string";
  13. import path2 from "path";
  14. import fs2 from "fs";
  15. import Debug from "debug";
  16. // src/utils.ts
  17. import path from "path";
  18. import { normalizePath } from "vite";
  19. import fs from "fs";
  20. import { createRequire } from "module";
  21. function resolveNodeModules(libName, ...dir) {
  22. const esRequire = createRequire(import.meta.url);
  23. let modulePath = "";
  24. try {
  25. modulePath = normalizePath(esRequire.resolve(libName));
  26. } catch (error) {
  27. modulePath = normalizePath(__require.resolve(libName));
  28. }
  29. const lastIndex = modulePath.lastIndexOf(libName);
  30. return normalizePath(path.resolve(modulePath.substring(0, lastIndex), ...dir));
  31. }
  32. function resolvePnp(module) {
  33. try {
  34. return normalizePath(__require.resolve(module));
  35. } catch (error) {
  36. return "";
  37. }
  38. }
  39. var isPnp = !!process.versions.pnp;
  40. function isRegExp(value) {
  41. return Object.prototype.toString.call(value) === "[object RegExp]";
  42. }
  43. function fileExists(f) {
  44. try {
  45. fs.accessSync(f, fs.constants.W_OK);
  46. return true;
  47. } catch (error) {
  48. return false;
  49. }
  50. }
  51. // src/resolve/antd.ts
  52. function AntdResolve() {
  53. return {
  54. libraryName: "antd",
  55. esModule: true,
  56. resolveStyle: (name) => {
  57. return `antd/es/${name}/style/index`;
  58. }
  59. };
  60. }
  61. // src/resolve/antdv.ts
  62. function AndDesignVueResolve() {
  63. return {
  64. ensureStyleFile: true,
  65. libraryName: "ant-design-vue",
  66. esModule: true,
  67. resolveStyle: (name) => {
  68. return `ant-design-vue/es/${name}/style/index`;
  69. }
  70. };
  71. }
  72. // src/resolve/elementPlus.ts
  73. function ElementPlusResolve() {
  74. return {
  75. libraryName: "element-plus",
  76. ensureStyleFile: true,
  77. esModule: true,
  78. resolveStyle: (name) => {
  79. return `element-plus/theme-chalk/${name}.css`;
  80. },
  81. resolveComponent: (name) => {
  82. return `element-plus/es/components/${name.replace(/^el-/, "")}/index.mjs`;
  83. },
  84. base: "element-plus/theme-chalk/base.css"
  85. };
  86. }
  87. // src/resolve/vant.ts
  88. function VantResolve() {
  89. return {
  90. libraryName: "vant",
  91. esModule: true,
  92. resolveStyle: (name) => {
  93. return `vant/es/${name}/style`;
  94. }
  95. };
  96. }
  97. // src/resolve/nutui.ts
  98. function NutuiResolve() {
  99. return {
  100. libraryName: "@nutui/nutui",
  101. libraryNameChangeCase: "pascalCase",
  102. resolveStyle: (name) => {
  103. return `@nutui/nutui/dist/packages/${name}/index.scss`;
  104. }
  105. };
  106. }
  107. // src/resolve/vxeTable.ts
  108. function VxeTableResolve() {
  109. return {
  110. ensureStyleFile: true,
  111. libraryName: "vxe-table",
  112. esModule: true,
  113. resolveStyle: (name) => {
  114. return `vxe-table/es/${name}/style.css`;
  115. }
  116. };
  117. }
  118. // src/index.ts
  119. var debug = Debug("vite-plugin-style-import");
  120. var ensureFileExts = [".css", ".js", ".scss", ".less", ".styl"];
  121. var asRE = /\s+as\s+\w+,?/g;
  122. var isFn = (value) => value != null && Object.prototype.toString.call(value) === "[object Function]";
  123. var src_default = (options) => {
  124. const {
  125. include = ["**/*.vue", "**/*.ts", "**/*.js", "**/*.tsx", "**/*.jsx"],
  126. exclude = "node_modules/**",
  127. resolves = []
  128. } = options;
  129. let { libs = [] } = options;
  130. libs = [...libs, ...resolves];
  131. const filter = createFilter(include, exclude);
  132. let needSourcemap = false;
  133. let isBuild = false;
  134. let external;
  135. debug("plugin options:", options);
  136. return {
  137. name: "vite:style-import",
  138. enforce: "post",
  139. configResolved(resolvedConfig) {
  140. var _a, _b, _c;
  141. needSourcemap = !!resolvedConfig.build.sourcemap;
  142. isBuild = resolvedConfig.isProduction || resolvedConfig.command === "build";
  143. external = (_c = (_b = (_a = resolvedConfig == null ? void 0 : resolvedConfig.build) == null ? void 0 : _a.rollupOptions) == null ? void 0 : _b.external) != null ? _c : void 0;
  144. debug("plugin config:", resolvedConfig);
  145. },
  146. async transform(code, id) {
  147. if (!code || !filter(id) || !needTransform(code, libs)) {
  148. return null;
  149. }
  150. await init;
  151. let imports = [];
  152. try {
  153. imports = parse(code)[0];
  154. debug("imports:", imports);
  155. } catch (e) {
  156. debug("imports-error:", e);
  157. }
  158. if (!imports.length) {
  159. return null;
  160. }
  161. let s;
  162. const str = () => s || (s = new MagicString(code));
  163. for (let index = 0; index < imports.length; index++) {
  164. const { n, se, ss } = imports[index];
  165. if (!n)
  166. continue;
  167. const lib = getLib(n, libs, external);
  168. if (!lib)
  169. continue;
  170. const isResolveComponent = isBuild && !!lib.resolveComponent;
  171. const importStr = code.slice(ss, se);
  172. let importVariables = transformImportVar(importStr);
  173. importVariables = filterImportVariables(importVariables, lib.importTest);
  174. const importCssStrList = await transformComponentCss(lib, importVariables);
  175. let compStrList = [];
  176. let compNameList = [];
  177. if (isResolveComponent) {
  178. const { componentStrList, componentNameList } = transformComponent(lib, importVariables);
  179. compStrList = componentStrList;
  180. compNameList = componentNameList;
  181. }
  182. debug("prepend import css str:", importCssStrList.join(""));
  183. debug("prepend import component str:", compStrList.join(""));
  184. const { base = "" } = lib;
  185. let baseImporter = base ? `
  186. import '${base}'` : "";
  187. if (str().toString().includes(base)) {
  188. baseImporter = "";
  189. }
  190. const endIndex = se + 1;
  191. if (isResolveComponent && compNameList.some((item) => importVariables.includes(item))) {
  192. if (lib.libraryName === "element-plus") {
  193. str().remove(ss, endIndex);
  194. } else {
  195. const importStr2 = str().slice(ss, endIndex);
  196. const [resultStr, uncssList] = await removeAlreadyName(importStr2, lib);
  197. if (resultStr) {
  198. str().overwrite(ss, endIndex, resultStr);
  199. } else {
  200. str().remove(ss, endIndex);
  201. }
  202. if (uncssList.length) {
  203. compStrList = compStrList.filter((item) => !uncssList.some((imp) => item.startsWith(`import ${imp}`)));
  204. }
  205. }
  206. }
  207. str().prependRight(endIndex, `${baseImporter}
  208. ${compStrList.join("")}${importCssStrList.join("")}`);
  209. }
  210. return {
  211. map: needSourcemap ? str().generateMap({ hires: true }) : null,
  212. code: str().toString()
  213. };
  214. }
  215. };
  216. };
  217. function filterImportVariables(importVars, reg) {
  218. if (!reg) {
  219. return importVars;
  220. }
  221. return importVars.filter((item) => reg.test(item));
  222. }
  223. async function removeAlreadyName(importStr, lib) {
  224. let result = importStr;
  225. const { libraryNameChangeCase = "paramCase", resolveStyle, libraryName } = lib;
  226. const exportStr = importStr.replace(asRE, ",").replace("import", "export").replace(asRE, ",");
  227. await init;
  228. const importComponents = parse(exportStr)[1];
  229. const hasCssList = [];
  230. const unCssList = [];
  231. importComponents.filter((comp) => {
  232. const name = getChangeCaseFileName(comp, libraryNameChangeCase);
  233. const importStr2 = resolveStyle == null ? void 0 : resolveStyle(name);
  234. if (importStr2) {
  235. const cssFile = resolveNodeModules(libraryName, importStr2);
  236. if (fs2.existsSync(cssFile)) {
  237. hasCssList.push(comp);
  238. } else {
  239. unCssList.push(comp);
  240. }
  241. } else {
  242. unCssList.push(comp);
  243. }
  244. });
  245. hasCssList.forEach((item) => {
  246. result = result.replace(new RegExp(`\\s?${item}\\s?,?`), "");
  247. });
  248. if (parse(result.replace("import", "export"))[1].length === 0) {
  249. result = "";
  250. }
  251. return [result, unCssList];
  252. }
  253. async function transformComponentCss(lib, importVariables) {
  254. const {
  255. libraryName,
  256. resolveStyle,
  257. esModule,
  258. libraryNameChangeCase = "paramCase",
  259. ensureStyleFile = false
  260. } = lib;
  261. if (!isFn(resolveStyle) || !libraryName) {
  262. return [];
  263. }
  264. const set = /* @__PURE__ */ new Set();
  265. for (let index = 0; index < importVariables.length; index++) {
  266. const name = getChangeCaseFileName(importVariables[index], libraryNameChangeCase);
  267. let importStr = resolveStyle(name);
  268. if (!importStr) {
  269. continue;
  270. }
  271. let isAdd = true;
  272. if (isPnp) {
  273. importStr = resolvePnp(importStr);
  274. isAdd = !!importStr;
  275. } else {
  276. if (esModule) {
  277. importStr = resolveNodeModules(libraryName, importStr);
  278. }
  279. if (ensureStyleFile) {
  280. isAdd = ensureFileExists(libraryName, importStr, esModule);
  281. }
  282. }
  283. isAdd && set.add(`import '${importStr}';
  284. `);
  285. }
  286. debug("import css sets:", set.toString());
  287. return Array.from(set);
  288. }
  289. function transformComponent(lib, importVariables) {
  290. const {
  291. libraryName,
  292. resolveComponent,
  293. libraryNameChangeCase = "paramCase",
  294. transformComponentImportName
  295. } = lib;
  296. if (!isFn(resolveComponent) || !libraryName) {
  297. return {
  298. componentStrList: [],
  299. componentNameList: []
  300. };
  301. }
  302. const componentNameSet = /* @__PURE__ */ new Set();
  303. const componentStrSet = /* @__PURE__ */ new Set();
  304. for (let index = 0; index < importVariables.length; index++) {
  305. const libName = importVariables[index];
  306. const name = getChangeCaseFileName(importVariables[index], libraryNameChangeCase);
  307. const importStr = resolveComponent(name);
  308. const importLibName = isFn(transformComponentImportName) && transformComponentImportName(libName) || libName;
  309. componentStrSet.add(`import ${importLibName} from '${importStr}';
  310. `);
  311. componentNameSet.add(libName);
  312. }
  313. debug("import component set:", componentStrSet.toString());
  314. return {
  315. componentStrList: Array.from(componentStrSet),
  316. componentNameList: Array.from(componentNameSet)
  317. };
  318. }
  319. function transformImportVar(importStr) {
  320. if (!importStr) {
  321. return [];
  322. }
  323. const exportStr = importStr.replace("import", "export").replace(asRE, ",");
  324. let importVariables = [];
  325. try {
  326. importVariables = parse(exportStr)[1];
  327. debug("importVariables:", importVariables);
  328. } catch (error) {
  329. debug("transformImportVar:", error);
  330. }
  331. return importVariables;
  332. }
  333. function ensureFileExists(libraryName, importStr, esModule = false) {
  334. const extName = path2.extname(importStr);
  335. if (!extName) {
  336. return tryEnsureFile(libraryName, importStr, esModule);
  337. }
  338. if (esModule) {
  339. return fileExists(importStr);
  340. }
  341. return true;
  342. }
  343. function tryEnsureFile(libraryName, filePath, esModule = false) {
  344. const filePathList = ensureFileExts.map((item) => {
  345. const p = `${filePath}${item}`;
  346. return esModule ? p : resolveNodeModules(libraryName, p);
  347. });
  348. return filePathList.some((item) => fileExists(item));
  349. }
  350. function getLib(libraryName, libs, external) {
  351. let libList = libs;
  352. if (external) {
  353. const isString = typeof external === "string";
  354. const isRE = isRegExp(external);
  355. if (isString) {
  356. libList = libList.filter((item) => item.libraryName !== external);
  357. } else if (isRE) {
  358. libList = libList.filter((item) => !external.test(item.libraryName));
  359. } else if (Array.isArray(external)) {
  360. libList = libList.filter((item) => {
  361. return !external.some((val) => {
  362. if (typeof val === "string") {
  363. return val === item.libraryName;
  364. }
  365. return val.test(item.libraryName);
  366. });
  367. });
  368. }
  369. }
  370. return libList.find((item) => item.libraryName === libraryName);
  371. }
  372. function getChangeCaseFileName(importedName, libraryNameChangeCase) {
  373. try {
  374. return changeCase[libraryNameChangeCase](importedName);
  375. } catch (error) {
  376. return importedName;
  377. }
  378. }
  379. function needTransform(code, libs) {
  380. return !libs.every(({ libraryName }) => {
  381. return !new RegExp(`('${libraryName}')|("${libraryName}")`).test(code);
  382. });
  383. }
  384. export {
  385. AndDesignVueResolve,
  386. AntdResolve,
  387. ElementPlusResolve,
  388. NutuiResolve,
  389. VantResolve,
  390. VxeTableResolve,
  391. src_default as default,
  392. getChangeCaseFileName,
  393. transformImportVar
  394. };