UNPKG

storybook-addon-stencil

Version:
86 lines (85 loc) 3.78 kB
import { transpile } from "@stencil/core/compiler"; import { readFile } from "fs/promises"; import path from "path"; import { compile } from 'sass'; /** * Check if an URL is an import from node_modules made with the stencil `~` prefix. * @param url The URL to check. */ const isCssNodeModule = (url) => url.startsWith("~"); export default function stencilSassPlugin(options = {}) { const importMap = new Map(); return { name: "vite:stencil-sass", resolveId(importPath, importer) { if (importPath.match(/\.scss\.js\?tag=/)) { const [fileName, ...args] = importPath.split("?"); const filePath = path.resolve(path.dirname(importer), fileName); return `${filePath}?${args.join("?")}`; } }, async load(id) { if (!id.includes(".scss")) { return; } const [baseFileName, queryParamsString] = id.split("?"); const fileName = baseFileName.replace(".scss.js", ".scss"); let code = await readFile(fileName, "utf-8"); const importStatements = code.match(/@import ['"](.*)['"].*;/g) ?? []; for (const importStatement of importStatements) { const [, importPath] = importStatement.match(/@import ['"](.*)['"]/); // handle imports from node_modules if (isCssNodeModule(importPath)) { const fixedImport = importStatement.replace(importPath, path.resolve(process.cwd(), "node_modules", importPath.slice(1))); code = code.replace(importStatement, fixedImport); } } if (id.match(/\.scss\.js\?tag=/)) { const res = compile(baseFileName); console.log(res); debugger; // Transpile the css file let { code: transpiled, imports } = await transpile(code, { ...options, sourceMap: "inline", target: "es2017", file: `${fileName}?${queryParamsString}`, styleImportData: null, style: null, }); code = transpiled; imports.forEach((input) => { code = code.replace(path.basename(input.path), path.basename(input.path) + "?inline"); const list = new Set(importMap.get(input.path)); list.add(id); importMap.set(path.resolve(path.dirname(id), input.path), list); }); } return { code }; }, /** * Handle hot updates for CSS files of the Stencil components. */ handleHotUpdate({ file, server, timestamp }) { if (!file.includes(".css")) { return []; } const invalidatedModules = new Set(); const cssFiles = importMap.get(file) || new Set(); // invalidate all importers of the css file that triggered the update cssFiles.forEach((cssFile) => { const module = server.moduleGraph.getModuleById(cssFile); if (!module) { return; } server.moduleGraph.invalidateModule(module, invalidatedModules, timestamp, true); }); // module of the css file that triggered the update const mod = [...server.moduleGraph.idToModuleMap.entries()].find(([k]) => k.includes(file))?.[1]; if (mod) { server.moduleGraph.invalidateModule(mod, invalidatedModules, timestamp, true); } return [...invalidatedModules]; }, }; }