0.1.5•Updated 6 months ago
import { walk } from "https://deno.land/std@0.224.0/fs/walk.ts";
import { join } from "jsr:@std/path";
const TAILWIND_CLASS_REGEX = /\b([\w\-:.\/\[#%\]\(\)\!]+)/g;
const classSet = new Set<string>();
async function extractClasses(filePath: string) {
const content = await Deno.readTextFile(filePath);
const matches = content.matchAll(TAILWIND_CLASS_REGEX);
for (const match of matches) {
classSet.add(match[1]);
}
}
const ui_path = join(Deno.cwd(), '/ui');
const classes_path = join(Deno.cwd(), '/classes');
for await (const entry of walk(ui_path, { exts: [".tsx", ".ts", ".jsx", ".js", ".html"] })) {
await extractClasses(entry.path);
}
for await (const entry of walk(classes_path, { exts: [".tsx", ".ts", ".jsx", ".js", ".html"] })) {
await extractClasses(entry.path);
}
const rules = Array.from(classSet).sort().filter(rule => {
if(rule.match(/^\d/)) return false;
if(rule.startsWith('.') || rule.endsWith('.')) return false;
if(rule.startsWith(':') || rule.endsWith(':')) return false;
if(rule.startsWith('-') || rule.endsWith('-')) return false;
if(rule.includes('!') && !rule.startsWith('!')) return false;
if(rule.includes('::') && !rule.match(/^::(before|after|placeholder|marker)/)) return false;
if(rule.includes('--')) return false;
if(rule.match(/\[\s*\]/)) return false;
if(rule.match(/\(\s*\)/)) return false;
if(rule.match(/^[-:.\/#%\[\]()!]+$/)) return false;
if((rule.match(/\[/g) || []).length !== (rule.match(/\]/g) || []).length) return false;
if((rule.match(/\(/g) || []).length !== (rule.match(/\)/g) || []).length) return false;
if((rule.match(/'/g) || []).length % 2 !== 0) return false;
if((rule.match(/"/g) || []).length % 2 !== 0) return false;
if(rule.match(/\w\.\w/) && !rule.match(/\[.*\w\.\w.*\]/)) return false;
if(!rule.match(/^(?:\w+\:)?[a-zA-Z][a-zA-Z0-9-]*(-\[.*\]|-[a-zA-Z0-9]+)?$/)) return false;
if(rule === rule.toUpperCase() && rule.match(/[A-Z]/)) return false;
if(!rule.match(/[a-zA-Z]/)) return false;
return true;
});
const required_classes = `// Generated by a build step in @viamedia/infinity-beyond
export const required_classes = () => <div className="${rules.join(' ')}" />;
`;
await Deno.writeTextFile("./dist/required-classes.tsx", required_classes);
console.log(`Required classes file generated with ${rules.length} classes`);