better formatting

This commit is contained in:
Hellings 2026-10-23 09:12:49 -04:00
parent fac3689440
commit a9e5d76bbb
2 changed files with 90 additions and 25 deletions

View file

@ -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<string[]> {
export async function tailwindCandidates(
root: string,
paths?: string[],
): Promise<string[]> {
const candidates = new Set<string>();
const visit = async (dir: string): Promise<void> => {
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<string> {
const tailwindCss = join(dirname(fileURLToPath(import.meta.resolve("tailwindcss/package.json"))), "index.css");
export async function compileTailwind(
css: string,
candidates: string[] = [],
): Promise<string> {
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",
},
}),
);
},
};
}

View file

@ -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"
}
}