better formatting
This commit is contained in:
parent
fac3689440
commit
a9e5d76bbb
2 changed files with 90 additions and 25 deletions
95
index.ts
95
index.ts
|
|
@ -10,20 +10,42 @@ export interface TailwindOptions {
|
||||||
content?: string[];
|
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 candidates = new Set<string>();
|
||||||
const visit = async (dir: string): Promise<void> => {
|
const visit = async (dir: string): Promise<void> => {
|
||||||
for (const entry of await readdir(dir, { withFileTypes: true })) {
|
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);
|
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 (!SCANNED_EXTENSIONS.has(extname(entry.name))) continue;
|
||||||
if (paths && !paths.some((value) => path.includes(value))) continue;
|
if (paths && !paths.some((value) => path.includes(value))) continue;
|
||||||
const source = await readFile(path, "utf8");
|
const source = await readFile(path, "utf8");
|
||||||
for (const match of source.matchAll(/(?:class|className)\s*=\s*["'`]([^"'`]+)["'`]/g)) {
|
for (const match of source.matchAll(
|
||||||
for (const value of (match[1] ?? "").split(/\s+/)) if (value) candidates.add(value);
|
/(?: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];
|
return [...candidates];
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function compileTailwind(css: string, candidates: string[] = []): Promise<string> {
|
export async function compileTailwind(
|
||||||
const tailwindCss = join(dirname(fileURLToPath(import.meta.resolve("tailwindcss/package.json"))), "index.css");
|
css: string,
|
||||||
|
candidates: string[] = [],
|
||||||
|
): Promise<string> {
|
||||||
|
const tailwindCss = join(
|
||||||
|
dirname(fileURLToPath(import.meta.resolve("tailwindcss/package.json"))),
|
||||||
|
"index.css",
|
||||||
|
);
|
||||||
const compiler = await compile(css, {
|
const compiler = await compile(css, {
|
||||||
base: process.cwd(),
|
base: process.cwd(),
|
||||||
loadStylesheet: async (id) => {
|
loadStylesheet: async (id) => {
|
||||||
if (!["tailwindcss", "tailwindcss/theme.css", "tailwindcss/utilities.css"].includes(id)) throw new Error(`Unsupported Tailwind stylesheet "${id}"`);
|
if (
|
||||||
const path = id === "tailwindcss" ? tailwindCss : join(dirname(tailwindCss), id.split("/")[1]!);
|
![
|
||||||
return { path, base: process.cwd(), content: await readFile(path, "utf8") };
|
"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);
|
return compiler.build(candidates);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function tailwindIntegration(options: TailwindOptions = {}): Integration {
|
export function tailwindIntegration(
|
||||||
|
options: TailwindOptions = {},
|
||||||
|
): Integration {
|
||||||
const route = options.route ?? "/_muddle/tailwind.css";
|
const route = options.route ?? "/_muddle/tailwind.css";
|
||||||
const source = options.css ?? '@import "tailwindcss";';
|
const source = options.css ?? '@import "tailwindcss";';
|
||||||
return {
|
return {
|
||||||
name: "tailwind",
|
name: "tailwind",
|
||||||
async setup(context: IntegrationContext) {
|
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", {
|
context.loader("tailwind", {
|
||||||
name: "tailwind",
|
name: "tailwind",
|
||||||
extensions: [".tailwind.css"],
|
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",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue