diff --git a/index.ts b/index.ts index 0b5eaeb..8a949d3 100644 --- a/index.ts +++ b/index.ts @@ -10,20 +10,42 @@ export interface TailwindOptions { content?: string[]; } -const SCANNED_EXTENSIONS = new Set([".ts", ".tsx", ".js", ".jsx", ".html", ".spug", ".mdx"]); +const SCANNED_EXTENSIONS = new Set([ + ".ts", + ".tsx", + ".js", + ".jsx", + ".html", + ".spug", + ".mdx", +]); -export async function tailwindCandidates(root: string, paths?: string[]): Promise { +export async function tailwindCandidates( + root: string, + paths?: string[], +): Promise { const candidates = new Set(); const visit = async (dir: string): Promise => { for (const entry of await readdir(dir, { withFileTypes: true })) { - if (entry.name === "node_modules" || entry.name === "dist" || entry.name.startsWith(".")) continue; + if ( + entry.name === "node_modules" || + entry.name === "dist" || + entry.name.startsWith(".") + ) + continue; const path = join(dir, entry.name); - if (entry.isDirectory()) { await visit(path); continue; } + if (entry.isDirectory()) { + await visit(path); + continue; + } if (!SCANNED_EXTENSIONS.has(extname(entry.name))) continue; if (paths && !paths.some((value) => path.includes(value))) continue; const source = await readFile(path, "utf8"); - for (const match of source.matchAll(/(?:class|className)\s*=\s*["'`]([^"'`]+)["'`]/g)) { - for (const value of (match[1] ?? "").split(/\s+/)) if (value) candidates.add(value); + for (const match of source.matchAll( + /(?:class|className)\s*=\s*["'`]([^"'`]+)["'`]/g, + )) { + for (const value of (match[1] ?? "").split(/\s+/)) + if (value) candidates.add(value); } } }; @@ -31,32 +53,75 @@ export async function tailwindCandidates(root: string, paths?: string[]): Promis return [...candidates]; } -export async function compileTailwind(css: string, candidates: string[] = []): Promise { - const tailwindCss = join(dirname(fileURLToPath(import.meta.resolve("tailwindcss/package.json"))), "index.css"); +export async function compileTailwind( + css: string, + candidates: string[] = [], +): Promise { + const tailwindCss = join( + dirname(fileURLToPath(import.meta.resolve("tailwindcss/package.json"))), + "index.css", + ); const compiler = await compile(css, { base: process.cwd(), loadStylesheet: async (id) => { - if (!["tailwindcss", "tailwindcss/theme.css", "tailwindcss/utilities.css"].includes(id)) throw new Error(`Unsupported Tailwind stylesheet "${id}"`); - const path = id === "tailwindcss" ? tailwindCss : join(dirname(tailwindCss), id.split("/")[1]!); - return { path, base: process.cwd(), content: await readFile(path, "utf8") }; + if ( + ![ + "tailwindcss", + "tailwindcss/theme.css", + "tailwindcss/utilities.css", + ].includes(id) + ) + throw new Error(`Unsupported Tailwind stylesheet "${id}"`); + const path = + id === "tailwindcss" + ? tailwindCss + : join(dirname(tailwindCss), id.split("/")[1]!); + return { + path, + base: process.cwd(), + content: await readFile(path, "utf8"), + }; }, }); return compiler.build(candidates); } -export function tailwindIntegration(options: TailwindOptions = {}): Integration { +export function tailwindIntegration( + options: TailwindOptions = {}, +): Integration { const route = options.route ?? "/_muddle/tailwind.css"; const source = options.css ?? '@import "tailwindcss";'; return { name: "tailwind", async setup(context: IntegrationContext) { - const build = () => tailwindCandidates(context.config.root, options.content).then((candidates) => compileTailwind(source, candidates)); + const build = () => + tailwindCandidates(context.config.root, options.content).then( + (candidates) => compileTailwind(source, candidates), + ); context.loader("tailwind", { name: "tailwind", extensions: [".tailwind.css"], - async load(file) { return { data: {}, content: await compileTailwind(file.source, await tailwindCandidates(context.config.root, options.content)) }; }, + async load(file) { + return { + data: {}, + content: await compileTailwind( + file.source, + await tailwindCandidates(context.config.root, options.content), + ), + }; + }, }); - context.route("GET", route, async () => new Response(await build(), { headers: { "content-type": "text/css; charset=utf-8", "cache-control": "public, max-age=60" } })); + context.route( + "GET", + route, + async () => + new Response(await build(), { + headers: { + "content-type": "text/css; charset=utf-8", + "cache-control": "public, max-age=60", + }, + }), + ); }, }; } diff --git a/package.json b/package.json index b3bb253..a26ecf9 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,12 @@ { - "name": "@muddle/tailwind", - "type": "module", - "exports": "./index.ts", - "version": "0.1.0", - "peerDependencies": { - "muddle": "*" - }, - "dependencies": { - "tailwindcss": "^4.3.3" - } + "name": "@muddle/tailwind", + "type": "module", + "exports": "./index.ts", + "version": "0.1.0", + "peerDependencies": { + "muddle": "*" + }, + "dependencies": { + "tailwindcss": "^4.3.3" + } }