chaincss 1.13.3 → 2.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/CHANGELOG.md +81 -0
- package/LICENSE +2 -3
- package/README.md +238 -105
- package/dist/cli/commands/build.d.ts +3 -0
- package/dist/cli/commands/build.d.ts.map +1 -0
- package/dist/cli/commands/compile.d.ts +3 -0
- package/dist/cli/commands/compile.d.ts.map +1 -0
- package/dist/cli/commands/init.d.ts +5 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/timeline.d.ts +2 -0
- package/dist/cli/commands/timeline.d.ts.map +1 -0
- package/dist/cli/commands/watch.d.ts +6 -0
- package/dist/cli/commands/watch.d.ts.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +5960 -0
- package/dist/cli/types.d.ts +51 -0
- package/dist/cli/types.d.ts.map +1 -0
- package/dist/cli/utils/config-loader.d.ts +8 -0
- package/dist/cli/utils/config-loader.d.ts.map +1 -0
- package/dist/cli/utils/file-utils.d.ts +9 -0
- package/dist/cli/utils/file-utils.d.ts.map +1 -0
- package/dist/cli/utils/logger.d.ts +17 -0
- package/dist/cli/utils/logger.d.ts.map +1 -0
- package/dist/compiler/atomic-optimizer.d.ts +76 -0
- package/dist/compiler/atomic-optimizer.d.ts.map +1 -0
- package/dist/compiler/btt.d.ts +138 -0
- package/dist/compiler/btt.d.ts.map +1 -0
- package/dist/compiler/cache-manager.d.ts +20 -0
- package/dist/compiler/cache-manager.d.ts.map +1 -0
- package/dist/compiler/commonProps.d.ts +2 -0
- package/dist/compiler/commonProps.d.ts.map +1 -0
- package/dist/compiler/index.d.ts +12 -0
- package/dist/compiler/index.d.ts.map +1 -0
- package/dist/compiler/index.js +5177 -0
- package/dist/compiler/prefixer.d.ts +42 -0
- package/dist/compiler/prefixer.d.ts.map +1 -0
- package/dist/compiler/theme-contract.d.ts +61 -0
- package/dist/compiler/theme-contract.d.ts.map +1 -0
- package/dist/compiler/tokens.d.ts +52 -0
- package/dist/compiler/tokens.d.ts.map +1 -0
- package/dist/compiler/types.d.ts +57 -0
- package/dist/compiler/types.d.ts.map +1 -0
- package/dist/core/compiler.d.ts +32 -0
- package/dist/core/compiler.d.ts.map +1 -0
- package/dist/core/constants.d.ts +129 -0
- package/dist/core/constants.d.ts.map +1 -0
- package/dist/core/index.d.ts +4 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/types.d.ts +88 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/utils.d.ts +37 -0
- package/dist/core/utils.d.ts.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5667 -0
- package/dist/plugins/vite.d.ts +11 -0
- package/dist/plugins/vite.d.ts.map +1 -0
- package/dist/plugins/vite.js +25839 -0
- package/dist/plugins/webpack.d.ts +45 -0
- package/dist/plugins/webpack.d.ts.map +1 -0
- package/dist/plugins/webpack.js +107 -0
- package/dist/runtime/hmr.d.ts +3 -0
- package/dist/runtime/hmr.d.ts.map +1 -0
- package/dist/runtime/index.d.ts +15 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +552 -0
- package/dist/runtime/injector.d.ts +85 -0
- package/dist/runtime/injector.d.ts.map +1 -0
- package/dist/runtime/react.d.ts +54 -0
- package/dist/runtime/react.d.ts.map +1 -0
- package/dist/runtime/react.js +270 -0
- package/dist/runtime/types.d.ts +45 -0
- package/dist/runtime/types.d.ts.map +1 -0
- package/dist/runtime/utils.d.ts +62 -0
- package/dist/runtime/utils.d.ts.map +1 -0
- package/dist/runtime/vue.d.ts +52 -0
- package/dist/runtime/vue.d.ts.map +1 -0
- package/dist/runtime/vue.js +232 -0
- package/package.json +90 -119
- package/browser/commonProps.js +0 -14
- package/browser/index.js +0 -3
- package/browser/react-hooks.js +0 -162
- package/browser/rtt.js +0 -400
- package/browser/vue-composables.js +0 -200
- package/node/atomic-optimizer.js +0 -526
- package/node/btt.js +0 -1009
- package/node/cache-manager.js +0 -56
- package/node/chaincss.js +0 -642
- package/node/index.js +0 -2
- package/node/loaders/chaincss-loader.js +0 -62
- package/node/plugins/next-plugin.js +0 -120
- package/node/plugins/vite-plugin.js +0 -383
- package/node/plugins/webpack-plugin.js +0 -41
- package/node/prefixer.js +0 -237
- package/node/strVal.js +0 -92
- package/node/theme-validator.js +0 -32
- package/shared/theme-contract.js +0 -98
- package/shared/tokens.cjs +0 -256
- package/shared/tokens.mjs +0 -320
- package/types.d.ts +0 -325
package/node/cache-manager.js
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
const fs = require('fs');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
class CacheManager {
|
|
4
|
-
constructor(cachePath = './.chaincss-cache') {
|
|
5
|
-
this.cachePath = path.resolve(process.cwd(), cachePath);
|
|
6
|
-
this.cacheDir = path.dirname(this.cachePath);
|
|
7
|
-
this.cache = {};
|
|
8
|
-
this.load();
|
|
9
|
-
}
|
|
10
|
-
load() {
|
|
11
|
-
try {
|
|
12
|
-
if (fs.existsSync(this.cachePath)) {
|
|
13
|
-
const data = fs.readFileSync(this.cachePath, 'utf8');
|
|
14
|
-
this.cache = JSON.parse(data);
|
|
15
|
-
//console.log(`Loaded cache from ${this.cachePath}`);
|
|
16
|
-
} else {
|
|
17
|
-
// Ensure cache directory exists
|
|
18
|
-
if (!fs.existsSync(this.cacheDir)) {
|
|
19
|
-
fs.mkdirSync(this.cacheDir, { recursive: true });
|
|
20
|
-
}
|
|
21
|
-
this.cache = {
|
|
22
|
-
version: '1.0',
|
|
23
|
-
created: new Date().toISOString(),
|
|
24
|
-
atomic: {},
|
|
25
|
-
usage: {}
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
} catch (error) {
|
|
29
|
-
console.warn('Could not load cache, starting fresh:', error.message);
|
|
30
|
-
this.cache = {};
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
get(key) {
|
|
34
|
-
return this.cache[key];
|
|
35
|
-
}
|
|
36
|
-
set(key, value) {
|
|
37
|
-
this.cache[key] = value;
|
|
38
|
-
}
|
|
39
|
-
save() {
|
|
40
|
-
try {
|
|
41
|
-
const data = JSON.stringify(this.cache, null, 2);
|
|
42
|
-
fs.writeFileSync(this.cachePath, data, 'utf8');
|
|
43
|
-
//console.log(`Saved cache to ${this.cachePath}`);
|
|
44
|
-
} catch (error) {
|
|
45
|
-
console.warn('Could not save cache:', error.message);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
clear() {
|
|
49
|
-
this.cache = {};
|
|
50
|
-
if (fs.existsSync(this.cachePath)) {
|
|
51
|
-
fs.unlinkSync(this.cachePath);
|
|
52
|
-
}
|
|
53
|
-
console.log('Cache cleared');
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
module.exports = { CacheManager };
|
package/node/chaincss.js
DELETED
|
@@ -1,642 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
const path = require('path');
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
const Module = require('module');
|
|
5
|
-
const chokidar = require('chokidar');
|
|
6
|
-
const CleanCSS = require('clean-css');
|
|
7
|
-
const { $, run, compile: originalCompile, chain, setAtomicOptimizer, createTokens, responsive, tokens } = require('./btt');
|
|
8
|
-
const ChainCSSPrefixer = require('./prefixer.js');
|
|
9
|
-
const strVal = require('./strVal.js');
|
|
10
|
-
const { AtomicOptimizer } = require('./atomic-optimizer');
|
|
11
|
-
const { CacheManager } = require('./cache-manager');
|
|
12
|
-
|
|
13
|
-
const fileCache = new Map();
|
|
14
|
-
const compiledCache = new Map();
|
|
15
|
-
let atomicOptimizer = null;
|
|
16
|
-
|
|
17
|
-
let config = {
|
|
18
|
-
atomic: {
|
|
19
|
-
enabled: false,
|
|
20
|
-
threshold: 2,
|
|
21
|
-
naming: 'hash',
|
|
22
|
-
cache: true,
|
|
23
|
-
cachePath: './.chaincss-cache',
|
|
24
|
-
minify: true,
|
|
25
|
-
mode: 'hybrid',
|
|
26
|
-
alwaysAtomic: [],
|
|
27
|
-
neverAtomic: ['content', 'animation', 'transition', 'keyframes', 'counterIncrement', 'counterReset'],
|
|
28
|
-
frameworkOutput: {
|
|
29
|
-
react: false,
|
|
30
|
-
vue: false,
|
|
31
|
-
vanilla: true
|
|
32
|
-
},
|
|
33
|
-
preserveSelectors: false,
|
|
34
|
-
verbose: false
|
|
35
|
-
},
|
|
36
|
-
prefixer: {
|
|
37
|
-
enabled: true,
|
|
38
|
-
mode: 'auto',
|
|
39
|
-
browsers: ['> 0.5%', 'last 2 versions', 'not dead'],
|
|
40
|
-
sourceMap: true,
|
|
41
|
-
sourceMapInline: false
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
let prefixer = new ChainCSSPrefixer(config.prefixer);
|
|
46
|
-
|
|
47
|
-
function deft_to_userConf(target, source) {
|
|
48
|
-
// Handle arrays specially
|
|
49
|
-
if (Array.isArray(source)) {
|
|
50
|
-
return source; // Return array as-is, don't merge
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const result = { ...target };
|
|
54
|
-
for (const key in source) {
|
|
55
|
-
if (source[key] instanceof Object && !Array.isArray(source[key]) && key in target) {
|
|
56
|
-
result[key] = deft_to_userConf(target[key], source[key]);
|
|
57
|
-
} else {
|
|
58
|
-
result[key] = source[key];
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
return result;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const ensureConfigExists = () => {
|
|
65
|
-
const configPath = path.join(process.cwd(), 'chaincss.config.cjs');
|
|
66
|
-
const configExists = fs.existsSync(configPath);
|
|
67
|
-
if (!configExists && !process.env.CHAINCSS_SKIP_CONFIG) {
|
|
68
|
-
fs.writeFileSync(configPath, strVal.userConf);
|
|
69
|
-
console.log('-- Successfully created config file: ./chaincss.config.cjs\n');
|
|
70
|
-
}
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
const loadUserConfig = () => {
|
|
74
|
-
const configPath = path.join(process.cwd(), 'chaincss.config.cjs');
|
|
75
|
-
if (fs.existsSync(configPath)) {
|
|
76
|
-
try {
|
|
77
|
-
const userConfig = require(configPath);
|
|
78
|
-
|
|
79
|
-
// Deep merge that preserves arrays
|
|
80
|
-
function deepMerge(target, source) {
|
|
81
|
-
const result = { ...target };
|
|
82
|
-
for (const key in source) {
|
|
83
|
-
if (Array.isArray(source[key])) {
|
|
84
|
-
result[key] = [...source[key]]; // Copy array
|
|
85
|
-
} else if (source[key] instanceof Object && key in target) {
|
|
86
|
-
result[key] = deepMerge(target[key], source[key]);
|
|
87
|
-
} else {
|
|
88
|
-
result[key] = source[key];
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
return result;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
config = deepMerge(config, userConfig);
|
|
95
|
-
|
|
96
|
-
// Ensure atomic arrays are arrays
|
|
97
|
-
if (config.atomic) {
|
|
98
|
-
if (!Array.isArray(config.atomic.alwaysAtomic)) {
|
|
99
|
-
config.atomic.alwaysAtomic = [];
|
|
100
|
-
}
|
|
101
|
-
if (!Array.isArray(config.atomic.neverAtomic)) {
|
|
102
|
-
config.atomic.neverAtomic = [];
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// Validate prefixer browsers
|
|
107
|
-
if (config.prefixer) {
|
|
108
|
-
if (typeof config.prefixer.browsers === 'string') {
|
|
109
|
-
config.prefixer.browsers = config.prefixer.browsers.split(',').map(b => b.trim());
|
|
110
|
-
}
|
|
111
|
-
if (!Array.isArray(config.prefixer.browsers)) {
|
|
112
|
-
config.prefixer.browsers = ['> 0.5%', 'last 2 versions', 'not dead'];
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
} catch (err) {
|
|
116
|
-
console.log('-- Error loading config:', err.message, '\n');
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
const initAtomicOptimizer = () => {
|
|
122
|
-
if (config.atomic.enabled) {
|
|
123
|
-
//if (config.atomic.verbose) {
|
|
124
|
-
//console.log('--Initializing Atomic Optimizer with config:', JSON.stringify(config.atomic, null, 2));
|
|
125
|
-
//}
|
|
126
|
-
|
|
127
|
-
atomicOptimizer = new AtomicOptimizer(config.atomic);
|
|
128
|
-
|
|
129
|
-
// Inject the configured atomic optimizer into btt
|
|
130
|
-
setAtomicOptimizer(atomicOptimizer);
|
|
131
|
-
}
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
const initPrefixer = () => {
|
|
135
|
-
prefixer = new ChainCSSPrefixer(config.prefixer);
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
function parseArgs(args) {
|
|
139
|
-
const result = {
|
|
140
|
-
inputFile: null,
|
|
141
|
-
outputFile: null,
|
|
142
|
-
watchMode: false,
|
|
143
|
-
noPrefix: false,
|
|
144
|
-
browsers: null,
|
|
145
|
-
prefixerMode: null,
|
|
146
|
-
sourceMap: null,
|
|
147
|
-
sourceMapInline: false,
|
|
148
|
-
atomic: false,
|
|
149
|
-
atomicMode: null,
|
|
150
|
-
atomicNaming: null,
|
|
151
|
-
atomicVerbose: false,
|
|
152
|
-
preserveSelectors: false
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
for (let i = 0; i < args.length; i++) {
|
|
156
|
-
const arg = args[i];
|
|
157
|
-
|
|
158
|
-
if (arg === '--watch') {
|
|
159
|
-
result.watchMode = true;
|
|
160
|
-
} else if (arg === '--no-prefix') {
|
|
161
|
-
result.noPrefix = true;
|
|
162
|
-
} else if (arg === '--prefixer-mode' && args[i + 1]) {
|
|
163
|
-
result.prefixerMode = args[i + 1];
|
|
164
|
-
i++;
|
|
165
|
-
} else if (arg === '--browsers' && args[i + 1]) {
|
|
166
|
-
result.browsers = args[i + 1].split(',').map(b => b.trim());
|
|
167
|
-
i++;
|
|
168
|
-
} else if (arg === '--no-source-map') {
|
|
169
|
-
result.sourceMap = false;
|
|
170
|
-
} else if (arg === '--source-map-inline') {
|
|
171
|
-
result.sourceMapInline = true;
|
|
172
|
-
} else if (arg === '--atomic') {
|
|
173
|
-
result.atomic = true;
|
|
174
|
-
} else if (arg === '--atomic-mode' && args[i + 1]) {
|
|
175
|
-
result.atomicMode = args[i + 1];
|
|
176
|
-
i++;
|
|
177
|
-
} else if (arg === '--atomic-naming' && args[i + 1]) {
|
|
178
|
-
result.atomicNaming = args[i + 1];
|
|
179
|
-
i++;
|
|
180
|
-
} else if (arg === '--atomic-verbose') {
|
|
181
|
-
result.atomicVerbose = true;
|
|
182
|
-
} else if (arg === '--preserve-selectors') {
|
|
183
|
-
result.preserveSelectors = true;
|
|
184
|
-
} else if (!result.inputFile) {
|
|
185
|
-
result.inputFile = arg;
|
|
186
|
-
} else if (!result.outputFile) {
|
|
187
|
-
result.outputFile = arg;
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
return result;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
const applyCliOptions = (cliOptions) => {
|
|
194
|
-
if (cliOptions.sourceMap !== null) {
|
|
195
|
-
config.prefixer.sourceMap = cliOptions.sourceMap;
|
|
196
|
-
}
|
|
197
|
-
if (cliOptions.sourceMapInline) {
|
|
198
|
-
config.prefixer.sourceMapInline = true;
|
|
199
|
-
}
|
|
200
|
-
if (cliOptions.prefixerMode) {
|
|
201
|
-
config.prefixer.mode = cliOptions.prefixerMode;
|
|
202
|
-
}
|
|
203
|
-
if (cliOptions.noPrefix) {
|
|
204
|
-
config.prefixer.enabled = false;
|
|
205
|
-
}
|
|
206
|
-
if (cliOptions.browsers) {
|
|
207
|
-
config.prefixer.browsers = cliOptions.browsers;
|
|
208
|
-
}
|
|
209
|
-
if (cliOptions.atomic) {
|
|
210
|
-
config.atomic.enabled = true;
|
|
211
|
-
}
|
|
212
|
-
if (cliOptions.atomicMode && ['atomic', 'standard', 'hybrid'].includes(cliOptions.atomicMode)) {
|
|
213
|
-
config.atomic.mode = cliOptions.atomicMode;
|
|
214
|
-
}
|
|
215
|
-
if (cliOptions.atomicNaming && ['hash', 'readable'].includes(cliOptions.atomicNaming)) {
|
|
216
|
-
config.atomic.naming = cliOptions.atomicNaming;
|
|
217
|
-
}
|
|
218
|
-
if (cliOptions.atomicVerbose) {
|
|
219
|
-
config.atomic.verbose = true;
|
|
220
|
-
}
|
|
221
|
-
if (cliOptions.preserveSelectors) {
|
|
222
|
-
config.atomic.preserveSelectors = true;
|
|
223
|
-
}
|
|
224
|
-
};
|
|
225
|
-
|
|
226
|
-
function watch(inputFile, outputFile) {
|
|
227
|
-
chokidar.watch(inputFile).on('change', async () => {
|
|
228
|
-
try {
|
|
229
|
-
await processor(inputFile, outputFile);
|
|
230
|
-
} catch (err) {
|
|
231
|
-
console.error('Error during watch processing:', err);
|
|
232
|
-
}
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
const compile = (obj) => {
|
|
237
|
-
originalCompile(obj);
|
|
238
|
-
let css = chain.cssOutput || '';
|
|
239
|
-
if (atomicOptimizer && config.atomic.enabled) {
|
|
240
|
-
const result = atomicOptimizer.optimize(obj);
|
|
241
|
-
css = result.css;
|
|
242
|
-
chain.cssOutput = css;
|
|
243
|
-
chain.classMap = result.map;
|
|
244
|
-
chain.atomicStats = result.stats;
|
|
245
|
-
}
|
|
246
|
-
return css;
|
|
247
|
-
};
|
|
248
|
-
|
|
249
|
-
const transpilerModule = {
|
|
250
|
-
$,
|
|
251
|
-
run,
|
|
252
|
-
compile: originalCompile,
|
|
253
|
-
chain
|
|
254
|
-
};
|
|
255
|
-
|
|
256
|
-
// Native module-based JCSS file processor
|
|
257
|
-
const processJCSSFile = (filePath) => {
|
|
258
|
-
const abs = path.resolve(filePath);
|
|
259
|
-
|
|
260
|
-
if (fileCache.has(abs)) return fileCache.get(abs);
|
|
261
|
-
|
|
262
|
-
if (!fs.existsSync(abs)) {
|
|
263
|
-
throw new Error(`File not found: ${abs}`);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
const content = fs.readFileSync(abs, 'utf8');
|
|
267
|
-
const dirname = path.dirname(abs);
|
|
268
|
-
|
|
269
|
-
const m = new Module(abs, module.parent);
|
|
270
|
-
m.filename = abs;
|
|
271
|
-
m.paths = Module._nodeModulePaths(dirname);
|
|
272
|
-
|
|
273
|
-
const get = (relativePath) => processJCSSFile(path.resolve(dirname, relativePath));
|
|
274
|
-
|
|
275
|
-
let compiledFn = compiledCache.get(abs);
|
|
276
|
-
if (!compiledFn) {
|
|
277
|
-
compiledFn = new Function(
|
|
278
|
-
'exports',
|
|
279
|
-
'require',
|
|
280
|
-
'module',
|
|
281
|
-
'__filename',
|
|
282
|
-
'__dirname',
|
|
283
|
-
'$',
|
|
284
|
-
'run',
|
|
285
|
-
'compile',
|
|
286
|
-
'chain',
|
|
287
|
-
'get',
|
|
288
|
-
'createTokens',
|
|
289
|
-
'responsive',
|
|
290
|
-
'tokens',
|
|
291
|
-
content
|
|
292
|
-
);
|
|
293
|
-
compiledCache.set(abs, compiledFn);
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
try {
|
|
297
|
-
compiledFn(
|
|
298
|
-
m.exports,
|
|
299
|
-
require,
|
|
300
|
-
m,
|
|
301
|
-
abs,
|
|
302
|
-
dirname,
|
|
303
|
-
$,
|
|
304
|
-
run,
|
|
305
|
-
originalCompile,
|
|
306
|
-
chain,
|
|
307
|
-
get,
|
|
308
|
-
createTokens,
|
|
309
|
-
responsive,
|
|
310
|
-
tokens
|
|
311
|
-
);
|
|
312
|
-
} catch (err) {
|
|
313
|
-
console.error(`Error processing ${abs}:`, err.message);
|
|
314
|
-
throw err;
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
fileCache.set(abs, m.exports);
|
|
318
|
-
return m.exports;
|
|
319
|
-
};
|
|
320
|
-
|
|
321
|
-
const processScript = (scriptBlock, filename) => {
|
|
322
|
-
const dirname = path.dirname(filename);
|
|
323
|
-
const get = (relativePath) => processJCSSFile(path.resolve(dirname, relativePath));
|
|
324
|
-
|
|
325
|
-
chain.cssOutput = '';
|
|
326
|
-
|
|
327
|
-
let compiledFn = compiledCache.get(`script:${filename}`);
|
|
328
|
-
if (!compiledFn) {
|
|
329
|
-
compiledFn = new Function(
|
|
330
|
-
'$',
|
|
331
|
-
'run',
|
|
332
|
-
'compile',
|
|
333
|
-
'chain',
|
|
334
|
-
'get',
|
|
335
|
-
'createTokens',
|
|
336
|
-
'responsive',
|
|
337
|
-
'tokens',
|
|
338
|
-
'__filename',
|
|
339
|
-
'__dirname',
|
|
340
|
-
scriptBlock
|
|
341
|
-
);
|
|
342
|
-
compiledCache.set(`script:${filename}`, compiledFn);
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
try {
|
|
346
|
-
compiledFn($, run, originalCompile, chain, get, createTokens, responsive, tokens, filename, dirname);
|
|
347
|
-
} catch (err) {
|
|
348
|
-
console.error(`Error processing script in ${filename}:`, err.message);
|
|
349
|
-
throw err;
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
return chain.cssOutput || '';
|
|
353
|
-
};
|
|
354
|
-
|
|
355
|
-
const processJavascriptBlocks = (content, inputpath) => {
|
|
356
|
-
const blocks = content.split(/<@([\s\S]*?)@>/gm);
|
|
357
|
-
let outputCSS = '';
|
|
358
|
-
|
|
359
|
-
for (let i = 0; i < blocks.length; i++) {
|
|
360
|
-
if (i % 2 === 0) {
|
|
361
|
-
outputCSS += blocks[i];
|
|
362
|
-
} else {
|
|
363
|
-
const scriptBlock = blocks[i];
|
|
364
|
-
if (scriptBlock && scriptBlock.trim()) {
|
|
365
|
-
try {
|
|
366
|
-
const blockCSS = processScript(scriptBlock, inputpath);
|
|
367
|
-
if (typeof blockCSS !== 'object' && typeof blockCSS !== 'undefined') {
|
|
368
|
-
outputCSS += blockCSS;
|
|
369
|
-
}
|
|
370
|
-
} catch (err) {
|
|
371
|
-
console.error(`Error processing script block:`, err.stack);
|
|
372
|
-
throw err;
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
return outputCSS.trim();
|
|
378
|
-
};
|
|
379
|
-
|
|
380
|
-
const validateCSS = (css) => {
|
|
381
|
-
const openBraces = (css.match(/{/g) || []).length;
|
|
382
|
-
const closeBraces = (css.match(/}/g) || []).length;
|
|
383
|
-
if (openBraces !== closeBraces) {
|
|
384
|
-
console.error(`CSS syntax error: Unclosed blocks (${openBraces} opening vs ${closeBraces} closing braces)`);
|
|
385
|
-
return false;
|
|
386
|
-
}
|
|
387
|
-
return true;
|
|
388
|
-
};
|
|
389
|
-
|
|
390
|
-
const processAndMinifyCss = async (css, inputFile, outputFile) => {
|
|
391
|
-
if (!validateCSS(css)) {
|
|
392
|
-
throw new Error('Invalid CSS syntax - check for missing braces');
|
|
393
|
-
}
|
|
394
|
-
let processedCss = css;
|
|
395
|
-
let sourceMapFromPrefixer = null;
|
|
396
|
-
if (config.prefixer.enabled) {
|
|
397
|
-
try {
|
|
398
|
-
const result = await prefixer.process(css, {
|
|
399
|
-
from: inputFile,
|
|
400
|
-
to: outputFile,
|
|
401
|
-
map: config.prefixer.sourceMap !== false
|
|
402
|
-
});
|
|
403
|
-
processedCss = result.css;
|
|
404
|
-
sourceMapFromPrefixer = result.map;
|
|
405
|
-
} catch (err) {
|
|
406
|
-
console.error('Prefixer error:', err.message);
|
|
407
|
-
processedCss = css;
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
const minifyOptions = {
|
|
411
|
-
sourceMap: config.prefixer.sourceMap === true,
|
|
412
|
-
sourceMapInlineSources: true
|
|
413
|
-
};
|
|
414
|
-
const output = new CleanCSS(minifyOptions).minify(processedCss);
|
|
415
|
-
if (output.errors.length > 0) {
|
|
416
|
-
console.error('CSS Minification Errors:', output.errors);
|
|
417
|
-
return { css: null, map: null };
|
|
418
|
-
}
|
|
419
|
-
let finalCss = output.styles;
|
|
420
|
-
let finalSourceMap = output.sourceMap ? JSON.stringify(output.sourceMap) : sourceMapFromPrefixer;
|
|
421
|
-
if (finalSourceMap && !config.prefixer.sourceMapInline) {
|
|
422
|
-
const mapFileName = path.basename(`${outputFile}.map`);
|
|
423
|
-
finalCss += `\n/*# sourceMappingURL=${mapFileName} */`;
|
|
424
|
-
}
|
|
425
|
-
return { css: finalCss, map: finalSourceMap };
|
|
426
|
-
};
|
|
427
|
-
|
|
428
|
-
const writeFrameworkOutput = (outputDir, result) => {
|
|
429
|
-
const frameworkOutputs = [];
|
|
430
|
-
|
|
431
|
-
if (config.atomic.frameworkOutput.react && result.frameworkOutput) {
|
|
432
|
-
const reactPath = path.join(outputDir, 'atomic.react.js');
|
|
433
|
-
fs.writeFileSync(reactPath, result.frameworkOutput, 'utf8');
|
|
434
|
-
frameworkOutputs.push(`React: ${reactPath}`);
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
if (config.atomic.frameworkOutput.vue && result.frameworkOutput) {
|
|
438
|
-
const vuePath = path.join(outputDir, 'atomic.vue.js');
|
|
439
|
-
fs.writeFileSync(vuePath, result.frameworkOutput, 'utf8');
|
|
440
|
-
frameworkOutputs.push(`Vue: ${vuePath}`);
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
if (frameworkOutputs.length > 0) {
|
|
444
|
-
console.log(`Framework outputs: ${frameworkOutputs.join(', ')}`);
|
|
445
|
-
}
|
|
446
|
-
};
|
|
447
|
-
|
|
448
|
-
const processor = async (inputFile, outputFile) => {
|
|
449
|
-
try {
|
|
450
|
-
const input = path.resolve(inputFile);
|
|
451
|
-
const outputDir = path.resolve(outputFile);
|
|
452
|
-
if (!fs.existsSync(outputDir)) {
|
|
453
|
-
fs.mkdirSync(outputDir, { recursive: true });
|
|
454
|
-
}
|
|
455
|
-
const content = fs.readFileSync(input, 'utf8');
|
|
456
|
-
const processedCSS = processJavascriptBlocks(content, input);
|
|
457
|
-
if (!validateCSS(processedCSS)) {
|
|
458
|
-
throw new Error('Invalid CSS syntax');
|
|
459
|
-
}
|
|
460
|
-
const stylePath = path.join(outputDir, 'global.css');
|
|
461
|
-
const result = await processAndMinifyCss(processedCSS, input, stylePath);
|
|
462
|
-
|
|
463
|
-
if (result.css) {
|
|
464
|
-
fs.writeFileSync(stylePath, result.css, 'utf8');
|
|
465
|
-
if (result.map) {
|
|
466
|
-
const mapFile = `${stylePath}.map`;
|
|
467
|
-
fs.writeFileSync(mapFile, result.map, 'utf8');
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
// ========== ATOMIC CLASS MAP GENERATION ==========
|
|
471
|
-
// ALWAYS generate atomic files when atomic optimizer is enabled
|
|
472
|
-
if (atomicOptimizer && config.atomic.enabled) {
|
|
473
|
-
|
|
474
|
-
// Get atomic classes from the optimizer
|
|
475
|
-
const atomicClasses = atomicOptimizer.getAllAtomicClasses();
|
|
476
|
-
const atomicClassMap = {};
|
|
477
|
-
|
|
478
|
-
// Build class map from component map
|
|
479
|
-
if (atomicOptimizer.componentMap) {
|
|
480
|
-
for (const [selector, data] of atomicOptimizer.componentMap) {
|
|
481
|
-
if (data.atomicClasses && data.atomicClasses.length > 0) {
|
|
482
|
-
atomicClassMap[selector] = data.atomicClasses.join(' ');
|
|
483
|
-
}
|
|
484
|
-
if (data.hoverAtomicClasses && data.hoverAtomicClasses.length > 0) {
|
|
485
|
-
atomicClassMap[`${selector}:hover`] = data.hoverAtomicClasses.join(' ');
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
// Write map.json
|
|
491
|
-
const mapJsonPath = path.join(outputDir, 'global.map.json');
|
|
492
|
-
const mapData = {
|
|
493
|
-
version: '2.0.0',
|
|
494
|
-
generated: new Date().toISOString(),
|
|
495
|
-
input: inputFile,
|
|
496
|
-
output: stylePath,
|
|
497
|
-
atomicEnabled: true,
|
|
498
|
-
mode: config.atomic.mode,
|
|
499
|
-
naming: config.atomic.naming,
|
|
500
|
-
outputStrategy: config.atomic.outputStrategy,
|
|
501
|
-
threshold: config.atomic.threshold,
|
|
502
|
-
classMap: atomicClassMap,
|
|
503
|
-
atomicClasses: atomicClasses.map(a => ({ className: a.className, prop: a.prop, value: a.value })),
|
|
504
|
-
stats: chain.atomicStats || atomicOptimizer.getStats()
|
|
505
|
-
};
|
|
506
|
-
fs.writeFileSync(mapJsonPath, JSON.stringify(mapData, null, 2), 'utf8');
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
// Write JS module
|
|
510
|
-
const jsPath = path.join(outputDir, 'global.classes.js');
|
|
511
|
-
let jsContent = `/**
|
|
512
|
-
* ChainCSS Atomic Class Map
|
|
513
|
-
* Generated: ${new Date().toISOString()}
|
|
514
|
-
* Mode: ${config.atomic.mode}
|
|
515
|
-
* Output Strategy: ${config.atomic.outputStrategy}
|
|
516
|
-
* Naming: ${config.atomic.naming}
|
|
517
|
-
* Threshold: ${config.atomic.threshold}
|
|
518
|
-
*/
|
|
519
|
-
|
|
520
|
-
export const classMap = ${JSON.stringify(atomicClassMap, null, 2)};
|
|
521
|
-
|
|
522
|
-
export const atomicClasses = ${JSON.stringify(atomicClasses.map(a => a.className), null, 2)};
|
|
523
|
-
|
|
524
|
-
export const getClass = (selector) => classMap[selector] || '';
|
|
525
|
-
|
|
526
|
-
export const getAtomicClass = (prop, value) => {
|
|
527
|
-
const atomic = atomicClasses.find(a => a.prop === prop && a.value === value);
|
|
528
|
-
return atomic ? atomic.className : null;
|
|
529
|
-
};
|
|
530
|
-
|
|
531
|
-
export const getAllClasses = () => Object.values(classMap).join(' ');
|
|
532
|
-
|
|
533
|
-
export const applyClasses = (element, selector) => {
|
|
534
|
-
if (!element) return;
|
|
535
|
-
const classes = getClass(selector);
|
|
536
|
-
if (classes) {
|
|
537
|
-
element.className = classes;
|
|
538
|
-
}
|
|
539
|
-
return classes;
|
|
540
|
-
};
|
|
541
|
-
|
|
542
|
-
export default classMap;
|
|
543
|
-
`;
|
|
544
|
-
|
|
545
|
-
fs.writeFileSync(jsPath, jsContent, 'utf8');
|
|
546
|
-
|
|
547
|
-
// Write TypeScript definitions
|
|
548
|
-
const dtsPath = path.join(outputDir, 'global.classes.d.ts');
|
|
549
|
-
const dtsContent = `/**
|
|
550
|
-
* ChainCSS Atomic Class Map Type Definitions
|
|
551
|
-
* Generated: ${new Date().toISOString()}
|
|
552
|
-
*/
|
|
553
|
-
|
|
554
|
-
export interface AtomicClass {
|
|
555
|
-
className: string;
|
|
556
|
-
prop: string;
|
|
557
|
-
value: string;
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
export const classMap: Record<string, string>;
|
|
561
|
-
export const atomicClasses: string[];
|
|
562
|
-
export const getClass: (selector: string) => string;
|
|
563
|
-
export const getAtomicClass: (prop: string, value: string) => string | null;
|
|
564
|
-
export const getAllClasses: () => string;
|
|
565
|
-
export const applyClasses: (element: HTMLElement | null, selector: string) => string | undefined;
|
|
566
|
-
|
|
567
|
-
declare const _default: Record<string, string>;
|
|
568
|
-
export default _default;
|
|
569
|
-
`;
|
|
570
|
-
fs.writeFileSync(dtsPath, dtsContent, 'utf8');
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
// Update manifest
|
|
574
|
-
const manifestPath = path.join(outputDir, 'chaincss-manifest.json');
|
|
575
|
-
let manifest = {};
|
|
576
|
-
if (fs.existsSync(manifestPath)) {
|
|
577
|
-
try {
|
|
578
|
-
manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
|
|
579
|
-
} catch (e) {}
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
manifest[path.basename(stylePath)] = {
|
|
583
|
-
version: '2.0.0',
|
|
584
|
-
css: path.basename(stylePath),
|
|
585
|
-
map: path.basename(mapJsonPath),
|
|
586
|
-
js: path.basename(jsPath),
|
|
587
|
-
dts: path.basename(dtsPath),
|
|
588
|
-
generated: new Date().toISOString(),
|
|
589
|
-
input: inputFile,
|
|
590
|
-
mode: config.atomic.mode,
|
|
591
|
-
outputStrategy: config.atomic.outputStrategy,
|
|
592
|
-
naming: config.atomic.naming,
|
|
593
|
-
threshold: config.atomic.threshold,
|
|
594
|
-
atomicClassesCount: atomicClasses.length,
|
|
595
|
-
stats: chain.atomicStats || atomicOptimizer.getStats()
|
|
596
|
-
};
|
|
597
|
-
|
|
598
|
-
fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2), 'utf8');
|
|
599
|
-
}
|
|
600
|
-
}
|
|
601
|
-
} catch (err) {
|
|
602
|
-
console.error(`Failed to process ${inputFile}:`, err.message);
|
|
603
|
-
throw err;
|
|
604
|
-
}
|
|
605
|
-
};
|
|
606
|
-
|
|
607
|
-
if (require.main === module) {
|
|
608
|
-
ensureConfigExists();
|
|
609
|
-
loadUserConfig();
|
|
610
|
-
const args = process.argv.slice(2);
|
|
611
|
-
const cliOptions = parseArgs(args);
|
|
612
|
-
if (!cliOptions.inputFile || !cliOptions.outputFile) {
|
|
613
|
-
console.log(strVal.cli_opt_guide);
|
|
614
|
-
process.exit(1);
|
|
615
|
-
}
|
|
616
|
-
applyCliOptions(cliOptions);
|
|
617
|
-
initAtomicOptimizer();
|
|
618
|
-
initPrefixer();
|
|
619
|
-
(async () => {
|
|
620
|
-
try {
|
|
621
|
-
await processor(cliOptions.inputFile, cliOptions.outputFile);
|
|
622
|
-
if (cliOptions.watchMode) {
|
|
623
|
-
console.log('-- Watching for changes...\n');
|
|
624
|
-
watch(cliOptions.inputFile, cliOptions.outputFile);
|
|
625
|
-
}
|
|
626
|
-
} catch (err) {
|
|
627
|
-
console.error('Fatal error:', err);
|
|
628
|
-
process.exit(1);
|
|
629
|
-
}
|
|
630
|
-
})();
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
module.exports = {
|
|
634
|
-
processor,
|
|
635
|
-
watch,
|
|
636
|
-
$,
|
|
637
|
-
run,
|
|
638
|
-
compile,
|
|
639
|
-
chain,
|
|
640
|
-
atomicOptimizer,
|
|
641
|
-
config
|
|
642
|
-
};
|
package/node/index.js
DELETED