santycss 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/santy-animations.css +519 -0
- package/dist/santy-components.css +680 -0
- package/dist/santy-core.css +11336 -0
- package/dist/santy.css +12538 -0
- package/dist/santy.min.css +1 -0
- package/index.js +50 -0
- package/lib/animations.js +539 -0
- package/lib/purge-core.js +223 -0
- package/package.json +65 -0
- package/postcss/index.js +79 -0
- package/purge.js +98 -0
- package/santy-jit.js +841 -0
- package/vite-plugin-santycss.js +128 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
/**
|
|
3
|
+
* vite-plugin-santycss
|
|
4
|
+
*
|
|
5
|
+
* Vite plugin — purges unused SantyCSS classes at build time.
|
|
6
|
+
* In dev mode it serves the full santy.css for instant class availability.
|
|
7
|
+
* In build mode it purges and inlines only used classes.
|
|
8
|
+
*
|
|
9
|
+
* Usage in vite.config.js:
|
|
10
|
+
*
|
|
11
|
+
* import santycss from './vite-plugin-santycss.js';
|
|
12
|
+
*
|
|
13
|
+
* export default {
|
|
14
|
+
* plugins: [
|
|
15
|
+
* santycss({
|
|
16
|
+
* content: ['./src/**\/*.{html,jsx,tsx,vue,svelte}'],
|
|
17
|
+
* safelist: ['make-hidden', 'animate-spin'],
|
|
18
|
+
* })
|
|
19
|
+
* ]
|
|
20
|
+
* };
|
|
21
|
+
*
|
|
22
|
+
* Usage in vite.config.ts (with types):
|
|
23
|
+
*
|
|
24
|
+
* import santycss from './vite-plugin-santycss.js';
|
|
25
|
+
* // same as above
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
const path = require('path');
|
|
29
|
+
const fs = require('fs');
|
|
30
|
+
|
|
31
|
+
function loadCore() {
|
|
32
|
+
return require('./lib/purge-core');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function expandGlobs(patterns) {
|
|
36
|
+
const { walkDir, EXTS } = loadCore();
|
|
37
|
+
const files = [];
|
|
38
|
+
for (const pattern of patterns) {
|
|
39
|
+
if (fs.existsSync(pattern) && fs.statSync(pattern).isFile()) {
|
|
40
|
+
files.push(pattern);
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
if (!pattern.includes('*')) {
|
|
44
|
+
walkDir(pattern, files);
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
const parts = pattern.split(/[/\\]/);
|
|
48
|
+
const starIdx = parts.findIndex(p => p.includes('*'));
|
|
49
|
+
const baseDir = parts.slice(0, starIdx).join('/') || '.';
|
|
50
|
+
const extMatch = pattern.match(/\.\w+$/);
|
|
51
|
+
const exts = extMatch ? [extMatch[0]] : EXTS;
|
|
52
|
+
const all = [];
|
|
53
|
+
walkDir(baseDir, all);
|
|
54
|
+
all.filter(f => exts.includes(path.extname(f).toLowerCase())).forEach(f => files.push(f));
|
|
55
|
+
}
|
|
56
|
+
return [...new Set(files)];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
module.exports = function santycssVitePlugin(opts = {}) {
|
|
60
|
+
const {
|
|
61
|
+
content = [],
|
|
62
|
+
safelist = [],
|
|
63
|
+
cssFile = path.resolve(__dirname, 'santy.css'),
|
|
64
|
+
devMode = 'full', // 'full' = serve full CSS in dev | 'purge' = always purge
|
|
65
|
+
} = opts;
|
|
66
|
+
|
|
67
|
+
let isBuild = false;
|
|
68
|
+
let fullCSS = '';
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
name: 'vite-plugin-santycss',
|
|
72
|
+
enforce: 'pre',
|
|
73
|
+
|
|
74
|
+
configResolved(config) {
|
|
75
|
+
isBuild = config.command === 'build';
|
|
76
|
+
if (fs.existsSync(cssFile)) {
|
|
77
|
+
fullCSS = fs.readFileSync(cssFile, 'utf8');
|
|
78
|
+
} else {
|
|
79
|
+
config.logger.warn(`[santycss] Cannot find ${cssFile}. Run: node build.js`);
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
// Intercept import of santy.css and serve the correct version
|
|
84
|
+
resolveId(id) {
|
|
85
|
+
if (id.endsWith('santy.css')) return '\0virtual:santy.css';
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
load(id) {
|
|
89
|
+
if (id !== '\0virtual:santy.css') return;
|
|
90
|
+
|
|
91
|
+
if (!isBuild && devMode === 'full') {
|
|
92
|
+
// Dev: serve full CSS — every class available instantly
|
|
93
|
+
return `/* SantyCSS — full (dev) */\n${fullCSS}`;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Build (or devMode=purge): scan and purge
|
|
97
|
+
const { purge } = loadCore();
|
|
98
|
+
const files = expandGlobs(Array.isArray(content) ? content : [content]);
|
|
99
|
+
|
|
100
|
+
if (files.length === 0) {
|
|
101
|
+
console.warn('[santycss] No content files found. Serving full CSS.');
|
|
102
|
+
return fullCSS;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const { css: purgedCSS, stats } = purge({
|
|
106
|
+
css: fullCSS,
|
|
107
|
+
content: files,
|
|
108
|
+
safelist,
|
|
109
|
+
minifyOutput: true,
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
const pct = (((stats.originalSize - stats.outputSize) / stats.originalSize) * 100).toFixed(1);
|
|
113
|
+
console.log(`\n [santycss] Purged: ${(stats.originalSize/1024).toFixed(1)} KB → ${(stats.outputSize/1024).toFixed(1)} KB (${pct}% smaller)\n`);
|
|
114
|
+
|
|
115
|
+
return `/* SantyCSS — purged */\n${purgedCSS}`;
|
|
116
|
+
},
|
|
117
|
+
|
|
118
|
+
// Hot reload: when a source file changes in dev, trigger CSS reload
|
|
119
|
+
handleHotUpdate({ file, server }) {
|
|
120
|
+
const { EXTS } = loadCore();
|
|
121
|
+
if (EXTS.includes(path.extname(file))) {
|
|
122
|
+
const mod = server.moduleGraph.getModuleById('\0virtual:santy.css');
|
|
123
|
+
if (mod) server.moduleGraph.invalidateModule(mod);
|
|
124
|
+
server.ws.send({ type: 'full-reload' });
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
};
|