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.
Files changed (101) hide show
  1. package/CHANGELOG.md +81 -0
  2. package/LICENSE +2 -3
  3. package/README.md +238 -105
  4. package/dist/cli/commands/build.d.ts +3 -0
  5. package/dist/cli/commands/build.d.ts.map +1 -0
  6. package/dist/cli/commands/compile.d.ts +3 -0
  7. package/dist/cli/commands/compile.d.ts.map +1 -0
  8. package/dist/cli/commands/init.d.ts +5 -0
  9. package/dist/cli/commands/init.d.ts.map +1 -0
  10. package/dist/cli/commands/timeline.d.ts +2 -0
  11. package/dist/cli/commands/timeline.d.ts.map +1 -0
  12. package/dist/cli/commands/watch.d.ts +6 -0
  13. package/dist/cli/commands/watch.d.ts.map +1 -0
  14. package/dist/cli/index.d.ts +2 -0
  15. package/dist/cli/index.d.ts.map +1 -0
  16. package/dist/cli/index.js +5960 -0
  17. package/dist/cli/types.d.ts +51 -0
  18. package/dist/cli/types.d.ts.map +1 -0
  19. package/dist/cli/utils/config-loader.d.ts +8 -0
  20. package/dist/cli/utils/config-loader.d.ts.map +1 -0
  21. package/dist/cli/utils/file-utils.d.ts +9 -0
  22. package/dist/cli/utils/file-utils.d.ts.map +1 -0
  23. package/dist/cli/utils/logger.d.ts +17 -0
  24. package/dist/cli/utils/logger.d.ts.map +1 -0
  25. package/dist/compiler/atomic-optimizer.d.ts +76 -0
  26. package/dist/compiler/atomic-optimizer.d.ts.map +1 -0
  27. package/dist/compiler/btt.d.ts +138 -0
  28. package/dist/compiler/btt.d.ts.map +1 -0
  29. package/dist/compiler/cache-manager.d.ts +20 -0
  30. package/dist/compiler/cache-manager.d.ts.map +1 -0
  31. package/dist/compiler/commonProps.d.ts +2 -0
  32. package/dist/compiler/commonProps.d.ts.map +1 -0
  33. package/dist/compiler/index.d.ts +12 -0
  34. package/dist/compiler/index.d.ts.map +1 -0
  35. package/dist/compiler/index.js +5177 -0
  36. package/dist/compiler/prefixer.d.ts +42 -0
  37. package/dist/compiler/prefixer.d.ts.map +1 -0
  38. package/dist/compiler/theme-contract.d.ts +61 -0
  39. package/dist/compiler/theme-contract.d.ts.map +1 -0
  40. package/dist/compiler/tokens.d.ts +52 -0
  41. package/dist/compiler/tokens.d.ts.map +1 -0
  42. package/dist/compiler/types.d.ts +57 -0
  43. package/dist/compiler/types.d.ts.map +1 -0
  44. package/dist/core/compiler.d.ts +32 -0
  45. package/dist/core/compiler.d.ts.map +1 -0
  46. package/dist/core/constants.d.ts +129 -0
  47. package/dist/core/constants.d.ts.map +1 -0
  48. package/dist/core/index.d.ts +4 -0
  49. package/dist/core/index.d.ts.map +1 -0
  50. package/dist/core/types.d.ts +88 -0
  51. package/dist/core/types.d.ts.map +1 -0
  52. package/dist/core/utils.d.ts +37 -0
  53. package/dist/core/utils.d.ts.map +1 -0
  54. package/dist/index.d.ts +13 -0
  55. package/dist/index.d.ts.map +1 -0
  56. package/dist/index.js +5667 -0
  57. package/dist/plugins/vite.d.ts +11 -0
  58. package/dist/plugins/vite.d.ts.map +1 -0
  59. package/dist/plugins/vite.js +25839 -0
  60. package/dist/plugins/webpack.d.ts +45 -0
  61. package/dist/plugins/webpack.d.ts.map +1 -0
  62. package/dist/plugins/webpack.js +107 -0
  63. package/dist/runtime/hmr.d.ts +3 -0
  64. package/dist/runtime/hmr.d.ts.map +1 -0
  65. package/dist/runtime/index.d.ts +15 -0
  66. package/dist/runtime/index.d.ts.map +1 -0
  67. package/dist/runtime/index.js +552 -0
  68. package/dist/runtime/injector.d.ts +85 -0
  69. package/dist/runtime/injector.d.ts.map +1 -0
  70. package/dist/runtime/react.d.ts +54 -0
  71. package/dist/runtime/react.d.ts.map +1 -0
  72. package/dist/runtime/react.js +270 -0
  73. package/dist/runtime/types.d.ts +45 -0
  74. package/dist/runtime/types.d.ts.map +1 -0
  75. package/dist/runtime/utils.d.ts +62 -0
  76. package/dist/runtime/utils.d.ts.map +1 -0
  77. package/dist/runtime/vue.d.ts +52 -0
  78. package/dist/runtime/vue.d.ts.map +1 -0
  79. package/dist/runtime/vue.js +232 -0
  80. package/package.json +90 -119
  81. package/browser/commonProps.js +0 -14
  82. package/browser/index.js +0 -3
  83. package/browser/react-hooks.js +0 -162
  84. package/browser/rtt.js +0 -400
  85. package/browser/vue-composables.js +0 -200
  86. package/node/atomic-optimizer.js +0 -526
  87. package/node/btt.js +0 -1009
  88. package/node/cache-manager.js +0 -56
  89. package/node/chaincss.js +0 -642
  90. package/node/index.js +0 -2
  91. package/node/loaders/chaincss-loader.js +0 -62
  92. package/node/plugins/next-plugin.js +0 -120
  93. package/node/plugins/vite-plugin.js +0 -383
  94. package/node/plugins/webpack-plugin.js +0 -41
  95. package/node/prefixer.js +0 -237
  96. package/node/strVal.js +0 -92
  97. package/node/theme-validator.js +0 -32
  98. package/shared/theme-contract.js +0 -98
  99. package/shared/tokens.cjs +0 -256
  100. package/shared/tokens.mjs +0 -320
  101. package/types.d.ts +0 -325
@@ -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
@@ -1,2 +0,0 @@
1
- const {$,run,compile,chain,tokens,createTokens} = require('./btt');
2
- module.exports = {$,run,compile,chain,tokens,createTokens};