chunk-FFGDY6HT.mjs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. import {
  2. __spreadProps,
  3. __spreadValues
  4. } from "./chunk-EX6ADWAR.mjs";
  5. // src/index.ts
  6. import { createUnplugin } from "unplugin";
  7. // src/core/options.ts
  8. import { getPackageInfo, isPackageExists } from "local-pkg";
  9. import createDebugger from "debug";
  10. var debug = createDebugger("unplugin-icons:options");
  11. async function resolveOptions(options) {
  12. const {
  13. scale = 1.2,
  14. defaultStyle = "",
  15. defaultClass = "",
  16. compiler = await guessCompiler(),
  17. jsx = guessJSX(),
  18. customCollections = {},
  19. iconCustomizer = () => {
  20. },
  21. transform,
  22. autoInstall = false
  23. } = options;
  24. const webComponents = Object.assign({
  25. autoDefine: false,
  26. iconPrefix: "icon"
  27. }, options.webComponents);
  28. debug("compiler", compiler);
  29. return {
  30. scale,
  31. defaultStyle,
  32. defaultClass,
  33. customCollections,
  34. iconCustomizer,
  35. compiler,
  36. jsx,
  37. webComponents,
  38. transform,
  39. autoInstall
  40. };
  41. }
  42. async function guessCompiler() {
  43. return await getVueVersion() || (isPackageExists("@svgr/core") ? "jsx" : "vue3");
  44. }
  45. function guessJSX() {
  46. if (isPackageExists("preact"))
  47. return "preact";
  48. return "react";
  49. }
  50. async function getVueVersion() {
  51. try {
  52. const result = await getPackageInfo("vue");
  53. if (!result)
  54. return null;
  55. return result.version.startsWith("2.") ? "vue2" : "vue3";
  56. } catch (e) {
  57. return null;
  58. }
  59. }
  60. // src/core/loader.ts
  61. import { loadNodeIcon } from "@iconify/utils/lib/loader/node-loader";
  62. // src/core/compilers/astro.ts
  63. var AstroCompiler = (svg) => {
  64. const svgWithProps = svg.replace("<svg", "<svg {...props}");
  65. return `---
  66. interface Props extends astroHTML.JSX.SVGAttributes {};
  67. const props = Astro.props;
  68. ---
  69. ${svgWithProps}`;
  70. };
  71. // src/core/compilers/jsx.ts
  72. import { importModule } from "local-pkg";
  73. import { camelize } from "@iconify/utils/lib/misc/strings";
  74. var JSXCompiler = async (svg, collection, icon, options) => {
  75. var _a;
  76. const svgrCore = await importModule("@svgr/core");
  77. const svgr = svgrCore.transform || (svgrCore.default ? (_a = svgrCore.default.transform) != null ? _a : svgrCore.default : svgrCore.default) || svgrCore;
  78. let res = await svgr(
  79. svg,
  80. {
  81. plugins: ["@svgr/plugin-jsx"]
  82. },
  83. { componentName: camelize(`${collection}-${icon}`) }
  84. );
  85. if (options.jsx !== "react")
  86. res = res.replace('import * as React from "react";', "");
  87. return res;
  88. };
  89. // src/core/compilers/marko.ts
  90. var MarkoCompiler = (svg) => {
  91. const openTagEnd = svg.indexOf(">", svg.indexOf("<svg "));
  92. const closeTagStart = svg.lastIndexOf("</svg");
  93. const openTag = `${svg.slice(0, openTagEnd)} ...input>`;
  94. const content = `$!{\`${escapeTemplateLiteral(svg.slice(openTagEnd + 1, closeTagStart))}\`}`;
  95. const closeTag = svg.slice(closeTagStart);
  96. return `${openTag}${content}${closeTag}`;
  97. };
  98. function escapeTemplateLiteral(str) {
  99. return str.replace(/\\.|[$`]/g, (m) => {
  100. switch (m) {
  101. case "$":
  102. return "&#36";
  103. case "`":
  104. return "&#96;";
  105. default:
  106. return m;
  107. }
  108. });
  109. }
  110. // src/core/compilers/none.ts
  111. var NoneCompiler = (svg) => {
  112. return svg;
  113. };
  114. // src/core/compilers/qwik.ts
  115. import { importModule as importModule2 } from "local-pkg";
  116. import { camelize as camelize2 } from "@iconify/utils/lib/misc/strings";
  117. var QwikCompiler = async (svg, collection, icon, options) => {
  118. const defaultOptions = {
  119. importSource: "@builder.io/qwik",
  120. runtime: "automatic",
  121. componentName: camelize2(`${collection}-${icon}`)
  122. };
  123. const mergedOptions = Object.assign({}, defaultOptions, options);
  124. const svgx = await importModule2("@svgx/core");
  125. const toJsxComponent = svgx.toJsxComponent;
  126. const res = toJsxComponent(svg, __spreadProps(__spreadValues({}, mergedOptions), {
  127. defaultExport: true
  128. }));
  129. return res;
  130. };
  131. // src/core/compilers/raw.ts
  132. var RawCompiler = (svg) => {
  133. return `export default ${JSON.stringify(svg)}`;
  134. };
  135. // src/core/compilers/solid.ts
  136. var SolidCompiler = (svg) => {
  137. const svgWithProps = svg.replace(/([{}])/g, "{'$1'}").replace(new RegExp("(?<=<svg[\\s\\S]*?)(>)", "i"), "{...props}>");
  138. return `export default (props = {}) => ${svgWithProps}`;
  139. };
  140. // src/core/compilers/svelte.ts
  141. var SvelteCompiler = (svg) => {
  142. const openTagEnd = svg.indexOf(">", svg.indexOf("<svg "));
  143. const closeTagStart = svg.lastIndexOf("</svg");
  144. const openTag = `${svg.slice(0, openTagEnd)} {...$$props}>`;
  145. const content = `{@html \`${escapeSvelte(svg.slice(openTagEnd + 1, closeTagStart))}\`}`;
  146. const closeTag = svg.slice(closeTagStart);
  147. return `${openTag}${content}${closeTag}`;
  148. };
  149. function escapeSvelte(str) {
  150. return str.replace(/{/g, "&#123;").replace(/}/g, "&#125;").replace(/`/g, "&#96;").replace(/\\([trn])/g, " ");
  151. }
  152. // src/core/compilers/vue2.ts
  153. import { importModule as importModule3 } from "local-pkg";
  154. // src/core/svgId.ts
  155. var randIdFn = "const __randId = () => Math.random().toString(36).substr(2, 10);";
  156. function handleSVGId(svg) {
  157. const hasID = /="url\(#/.test(svg);
  158. const idMap = {};
  159. let injectScripts = "";
  160. if (hasID) {
  161. svg = svg.replace(/\b([\w-]+?)="url\(#(.+?)\)"/g, (_, s, id) => {
  162. idMap[id] = `'${id}':'uicons-'+__randId()`;
  163. return `:${s}="'url(#'+idMap['${id}']+')'"`;
  164. }).replace(/\bid="(.+?)"/g, (full, id) => {
  165. if (idMap[id])
  166. return `:id="idMap['${id}']"`;
  167. return full;
  168. });
  169. injectScripts = `${randIdFn}const idMap = {${Object.values(idMap).join(",")}};`;
  170. }
  171. return {
  172. hasID,
  173. svg,
  174. injectScripts
  175. };
  176. }
  177. // src/core/compilers/vue2.ts
  178. var Vue2Compiler = async (svg, collection, icon) => {
  179. const { compile } = await importModule3("vue-template-compiler");
  180. const transpile = (await importModule3("vue-template-es2015-compiler")).default;
  181. const { injectScripts, svg: handled } = handleSVGId(svg);
  182. const { render } = compile(handled);
  183. const toFunction = (code2) => {
  184. return `function () {${code2}}`;
  185. };
  186. let code = transpile(`var __render__ = ${toFunction(render)}
  187. `, {});
  188. code = code.replace(/\s__(render|staticRenderFns)__\s/g, " $1 ");
  189. code += `
  190. /* vite-plugin-components disabled */
  191. export default {
  192. render: render,
  193. ${injectScripts ? `data() {${injectScripts};return { idMap }},` : ""}
  194. name: '${collection}-${icon}',
  195. }
  196. `;
  197. return code;
  198. };
  199. // src/core/compilers/vue3.ts
  200. import { importModule as importModule4 } from "local-pkg";
  201. var Vue3Compiler = async (svg, collection, icon) => {
  202. const { compileTemplate } = await importModule4("@vue/compiler-sfc");
  203. const { injectScripts, svg: handled } = handleSVGId(svg);
  204. let { code } = compileTemplate({
  205. source: handled,
  206. id: `${collection}:${icon}`,
  207. filename: `${collection}-${icon}.vue`
  208. });
  209. code = code.replace(/^export /gm, "");
  210. code += `
  211. export default { name: '${collection}-${icon}', render${injectScripts ? `, data() {${injectScripts};return { idMap }}` : ""} }`;
  212. code += "\n/* vite-plugin-components disabled */";
  213. return code;
  214. };
  215. // src/core/compilers/web-components.ts
  216. import { camelize as camelize3 } from "@iconify/utils/lib/misc/strings";
  217. var WebComponentsCompiler = (svg, collection, icon, { webComponents: options }) => {
  218. let id = `${collection}-${icon}`;
  219. if (options.iconPrefix)
  220. id = `${options.iconPrefix}-${id}`;
  221. const name = camelize3(id);
  222. let code = `export default class ${name} extends HTMLElement {`;
  223. if (options.shadow) {
  224. code += `constructor() {
  225. super()
  226. this.attachShadow({ mode: 'open' }).innerHTML = ${JSON.stringify(svg)}
  227. }`;
  228. } else {
  229. code += `connectedCallback() { this.innerHTML = ${JSON.stringify(svg)} }`;
  230. }
  231. code += "}";
  232. if (options.autoDefine)
  233. code += `
  234. customElements.define('${id}', ${name})`;
  235. return code;
  236. };
  237. // src/core/compilers/index.ts
  238. var compilers = {
  239. "astro": AstroCompiler,
  240. "jsx": JSXCompiler,
  241. "marko": MarkoCompiler,
  242. "none": NoneCompiler,
  243. "raw": RawCompiler,
  244. "solid": SolidCompiler,
  245. "svelte": SvelteCompiler,
  246. "vue2": Vue2Compiler,
  247. "vue3": Vue3Compiler,
  248. "web-components": WebComponentsCompiler,
  249. "qwik": QwikCompiler
  250. };
  251. // src/core/loader.ts
  252. var URL_PREFIXES = ["/~icons/", "~icons/", "virtual:icons/", "virtual/icons/"];
  253. var iconPathRE = new RegExp(`${URL_PREFIXES.map((v) => `^${v}`).join("|")}`);
  254. function isIconPath(path) {
  255. return iconPathRE.test(path);
  256. }
  257. function normalizeIconPath(path) {
  258. return path.replace(iconPathRE, URL_PREFIXES[0]);
  259. }
  260. function resolveIconsPath(path) {
  261. if (!isIconPath(path))
  262. return null;
  263. path = path.replace(iconPathRE, "");
  264. const query = {};
  265. const queryIndex = path.indexOf("?");
  266. if (queryIndex !== -1) {
  267. const queryRaw = path.slice(queryIndex + 1);
  268. path = path.slice(0, queryIndex);
  269. new URLSearchParams(queryRaw).forEach((value, key) => {
  270. if (key === "raw")
  271. query.raw = value === "" || value === "true" ? "true" : "false";
  272. else
  273. query[key] = value;
  274. });
  275. }
  276. path = path.replace(/\.\w+$/, "");
  277. const [collection, icon] = path.split("/");
  278. return {
  279. collection,
  280. icon,
  281. query
  282. };
  283. }
  284. async function generateComponent({ collection, icon, query }, options) {
  285. const warn = `${collection}/${icon}`;
  286. const {
  287. scale,
  288. defaultStyle,
  289. defaultClass,
  290. customCollections,
  291. iconCustomizer: providedIconCustomizer,
  292. transform,
  293. autoInstall = false
  294. } = options;
  295. const iconifyLoaderOptions = {
  296. addXmlNs: false,
  297. scale,
  298. customCollections,
  299. autoInstall,
  300. defaultClass,
  301. defaultStyle,
  302. // there is no need to warn since we throw an error below
  303. warn: void 0,
  304. customizations: {
  305. transform,
  306. async iconCustomizer(collection2, icon2, props) {
  307. await (providedIconCustomizer == null ? void 0 : providedIconCustomizer(collection2, icon2, props));
  308. Object.keys(query).forEach((p) => {
  309. const v = query[p];
  310. if (p !== "raw" && v !== void 0 && v !== null)
  311. props[p] = v;
  312. });
  313. }
  314. }
  315. };
  316. const svg = await loadNodeIcon(collection, icon, iconifyLoaderOptions);
  317. if (!svg)
  318. throw new Error(`Icon \`${warn}\` not found`);
  319. const _compiler = query.raw === "true" ? "raw" : options.compiler;
  320. if (_compiler) {
  321. const compiler = typeof _compiler === "string" ? compilers[_compiler] : await _compiler.compiler;
  322. if (compiler)
  323. return compiler(svg, collection, icon, options);
  324. }
  325. throw new Error(`Unknown compiler: ${_compiler}`);
  326. }
  327. async function generateComponentFromPath(path, options) {
  328. const resolved = resolveIconsPath(path);
  329. if (!resolved)
  330. return null;
  331. return generateComponent(resolved, options);
  332. }
  333. // src/index.ts
  334. var unplugin = createUnplugin((options = {}) => {
  335. const resolved = resolveOptions(options);
  336. return {
  337. name: "unplugin-icons",
  338. enforce: "pre",
  339. resolveId(id) {
  340. var _a;
  341. if (isIconPath(id)) {
  342. const res = normalizeIconPath(id).replace(/\.\w+$/i, "").replace(/^\//, "");
  343. const resolved2 = resolveIconsPath(res);
  344. const compiler = ((_a = resolved2 == null ? void 0 : resolved2.query) == null ? void 0 : _a.raw) === "true" ? "raw" : options.compiler;
  345. if (compiler && typeof compiler !== "string") {
  346. const ext = compiler.extension;
  347. if (ext)
  348. return `${res}.${ext.startsWith(".") ? ext.slice(1) : ext}`;
  349. } else {
  350. switch (compiler) {
  351. case "astro":
  352. return `${res}.astro`;
  353. case "jsx":
  354. return `${res}.jsx`;
  355. case "qwik":
  356. return `${res}.jsx`;
  357. case "marko":
  358. return `${res}.marko`;
  359. case "svelte":
  360. return `${res}.svelte`;
  361. case "solid":
  362. return `${res}.tsx`;
  363. }
  364. }
  365. return res;
  366. }
  367. return null;
  368. },
  369. loadInclude(id) {
  370. return isIconPath(id);
  371. },
  372. async load(id) {
  373. const config = await resolved;
  374. const code = await generateComponentFromPath(id, config) || null;
  375. if (code) {
  376. return {
  377. code,
  378. map: { version: 3, mappings: "", sources: [] }
  379. };
  380. }
  381. },
  382. rollup: {
  383. api: {
  384. config: options
  385. }
  386. }
  387. };
  388. });
  389. var src_default = unplugin;
  390. export {
  391. src_default
  392. };