Skip to content

Commit

Permalink
Swap to tailwind safelisting
Browse files Browse the repository at this point in the history
  • Loading branch information
benjaminpreiss committed Jan 31, 2024
1 parent 98e369f commit a969acd
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 29 deletions.
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -25,6 +25,7 @@
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-svelte": "^2.35.1",
"install": "^0.13.0",
"lodash.difference": "^4.5.0",
"postcss": "^8.4.33",
"prettier": "^3.1.1",
"prettier-plugin-svelte": "^3.1.2",
Expand Down
7 changes: 7 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 1 addition & 24 deletions postcss.config.js
@@ -1,29 +1,6 @@
import tailwindcss from 'tailwindcss';
import autoprefixer from 'autoprefixer';
import { getSafelist } from './getSafelist.js';

/*
Reads comments in svelte file and safelists accordingly.
E.g.: `// dynamic-safelist: 'bg'`
*/
function processSvelte(code, path) {
if (!path.includes('.svelte')) return [];
return [...code.matchAll(new RegExp(`(?<=dynamic-safelist\\().+(?=\\))`, 'gm'))].map((m) => {
return eval(m[0]);
});
}

console.log('loading postcss config...');

export default {
plugins: [
tailwindcss({
safelist: await getSafelist('./some-config-file.ts', processSvelte),
content: ['./src/**/*.{html,js,svelte,ts}'],
theme: {
extend: {}
}
}),
autoprefixer
]
plugins: [tailwindcss, autoprefixer]
};
2 changes: 1 addition & 1 deletion src/routes/+page.svelte
Expand Up @@ -3,7 +3,7 @@
import welcome from '$lib/images/svelte-welcome.webp';
import welcome_fallback from '$lib/images/svelte-welcome.png';
// dynamic-safelist('bg-' + 'green-500')
// dynamic-safelist('bg-' + 'green-600')
</script>

<svelte:head>
Expand Down
1 change: 1 addition & 0 deletions tailwind.config.ts
Expand Up @@ -2,6 +2,7 @@ import type { Config } from 'tailwindcss';

export default {
content: ['./src/**/*.{html,js,svelte,ts}'],
safelist: global.safelist,
theme: {
extend: {}
},
Expand Down
73 changes: 69 additions & 4 deletions vite.config.ts
@@ -1,12 +1,77 @@
import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vitest/config';
import ViteRestart from 'vite-plugin-restart';
import fs from 'node:fs/promises';
import fg from 'fast-glob';
import { resolve } from 'node:path';
import uniq from 'lodash.uniq';
import difference from 'lodash.difference';

const configFileName = 'some-config-file.ts';
const safelist = new Map<string, string[]>();

async function updateSafelist(path: string, processFile: (code: string, path: string) => string[]) {
// read file
const code = await fs.readFile(path, { encoding: 'utf8' });
// process file to get safelist
const processed = processFile(code, path);
// push only new values to safelist
safelist.set(path, processed);
return uniq([...safelist.values()].flatMap((v) => v)) as string[];
}

function processSvelte(code: string, path: string): string[] {
if (!path.includes('.svelte')) return [];
return [...code.matchAll(new RegExp(`(?<=dynamic-safelist\\().+(?=\\))`, 'gm'))].map((m) => {
return (0, eval)(m[0]);
});
}

async function reloadTailwind() {
const fileContent = await fs.readFile(resolve(process.cwd(), './tailwind.config.ts'), {
encoding: 'utf8'
});
await fs.writeFile(resolve(process.cwd(), './tailwind.config.ts'), fileContent);
}

export default defineConfig({
plugins: [
ViteRestart({
reload: ['postcss.config.js']
}),
{
name: 'dynamic-safelist',
enforce: 'pre',
async configureServer(server) {
// TODO: What should I do with this?
const stream = fg.globStream(['src/**/*.svelte'], { dot: true, absolute: true });
for await (const entry of stream) {
// pushes new tw classes to safelist
global.safelist = await updateSafelist(entry, processSvelte);
}

server.watcher.add(['src/**/*.svelte', `./${configFileName}`]);
server.watcher.on('add', handleFileChange);
server.watcher.on('change', handleFileChange);
server.watcher.on('unlink', unlinkFile);

async function handleFileChange(path: string) {
if (path.includes(configFileName)) {
console.log(`Config file ${configFileName} changed. Restarting vite...`);
server.restart();
}
if (path.endsWith('.svelte')) {
const newSafelist = await updateSafelist(path, processSvelte);
if (difference(newSafelist, global.safelist ?? []).length > 0) {
global.safelist = newSafelist;
console.log(`Safelist has changed. Restarting vite...`);
await reloadTailwind();
}
}
}

async function unlinkFile(path: string) {
if (path.endsWith('.svelte')) safelist.delete(path);
await reloadTailwind();
}
}
},
sveltekit()
],
test: {
Expand Down

0 comments on commit a969acd

Please sign in to comment.