UNPKG

@unvuetify/vite-styles-plugin

Version:
147 lines (144 loc) 5.22 kB
import fs from 'node:fs'; import fsp from 'node:fs/promises'; import process from 'node:process'; import { pathToFileURL } from 'node:url'; import { resolveVuetifyBase } from '@unvuetify/shared'; import { relative, isAbsolute } from 'pathe'; import path from 'upath'; import { version } from 'vite'; function VuetifyStylesVitePlugin(options = {}) { let configFile; const vuetifyBase = resolveVuetifyBase(); const noneFiles = /* @__PURE__ */ new Set(); let isNone = false; let cssVariables = false; let fileImport = false; const PREFIX = `${options.viteSSR ? "virtual:" : ""}vuetify-styles/`; const SSR_PREFIX = options.viteSSR ? `\0${PREFIX}` : `/@${PREFIX}`; const resolveCss = resolveCssFactory(); const api = options.registerApi ?? "modern-compiler"; const [major, minor, patch] = version.split(".").map((v) => v.includes("-") ? v.split("-")[0] : v).map((v) => Number.parseInt(v)); return { name: "@unvuetify:vite-styles-plugin", enforce: "pre", config(config) { if (!api) return null; if (api === "modern-compiler" || api === "legacy") { return { css: { preprocessorOptions: { sass: { api }, scss: { api } } } }; } if (config.css && !("preprocessorMaxWorkers" in config.css)) { return { css: { preprocessorOptions: { sass: { api }, scss: { api } } } }; } return { css: { preprocessorOptions: { sass: { api }, scss: { api } }, preprocessorMaxWorkers: true } }; }, configResolved(config) { if (config.plugins.findIndex((plugin) => plugin.name === "vuetify:styles") > -1) throw new Error(`The "vite-plugin-vuetify" styles plugin is incompatible with this plugin. Please remove "vite-plugin-vuetify" or set the styles to 'true' in your Vite configuration file.`); if (isObject(options.mode)) { cssVariables = true; fileImport = major > 5 || major === 5 && minor > 4 || major === 5 && minor === 4 && patch > 2; if (path.isAbsolute(options.mode.configFile)) configFile = path.resolve(options.mode.configFile); else configFile = path.resolve(path.join(config.root || process.cwd(), options.mode.configFile)); configFile = fileImport ? pathToFileURL(configFile).href : normalizePath(configFile); } else { isNone = options.mode === "none"; } }, async resolveId(source, importer, { custom, ssr }) { if (!options.mode) return void 0; if (source.startsWith(PREFIX) || source.startsWith(SSR_PREFIX)) { if (source.match(/\.s[ca]ss$/)) return source; const idx = source.indexOf("?"); return idx > -1 ? source.slice(0, idx) : source; } if (source === "vuetify/styles" || importer && source.endsWith(".css") && isSubdir(vuetifyBase, path.isAbsolute(source) ? source : importer)) { if (options.mode === "source") return this.resolve(await resolveCss(source), importer, { skipSelf: true, custom }); const resolution = await this.resolve(source, importer, { skipSelf: true, custom }); if (!resolution) return void 0; const target = await resolveCss(resolution.id); if (isNone) { noneFiles.add(target); return target; } return `${ssr ? SSR_PREFIX : PREFIX}${path.relative(vuetifyBase, target)}`; } return void 0; }, load(id) { if (!options.mode) return void 0; if (cssVariables) { const target = id.startsWith(PREFIX) ? path.resolve(vuetifyBase, id.slice(PREFIX.length)) : id.startsWith(SSR_PREFIX) ? path.resolve(vuetifyBase, id.slice(SSR_PREFIX.length)) : void 0; if (target) { const suffix = target.match(/\.scss/) ? ";\n" : "\n"; return { code: `@use "${configFile}"${suffix}@use "${fileImport ? pathToFileURL(target).href : normalizePath(target)}"${suffix}`, map: { mappings: "" } }; } } return isNone && noneFiles.has(id) ? "" : void 0; } }; } function resolveCssFactory() { const mappings = /* @__PURE__ */ new Map(); return async (source) => { let mapping = mappings.get(source); if (!mapping) { try { mapping = source.replace(/\.css$/, ".sass"); await fsp.access(mapping, fs.constants.R_OK); } catch (err) { if (!(err instanceof Error && "code" in err && err.code === "ENOENT")) throw err; mapping = source.replace(/\.css$/, ".scss"); } mappings.set(source, mapping); } return mapping; }; } function isObject(value) { return value !== null && typeof value === "object"; } function normalizePath(p) { p = path.normalize(p); return /^[a-z]:\//i.test(p) ? `/${p}` : p; } function isSubdir(root, test) { const relative$1 = relative(root, test); return relative$1 && !relative$1.startsWith("..") && !isAbsolute(relative$1); } export { VuetifyStylesVitePlugin };