@melcanz85/chaincss 1.12.0 → 1.12.1

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/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Rommel Caneos
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+ EOF
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * ChainCSS Benchmark Comparison
5
+ * Run with: npm run benchmark:compare
6
+ */
7
+
8
+ console.log('📊 ChainCSS Benchmark Comparison\n');
9
+ console.log('This will compare ChainCSS with other CSS-in-JS libraries.\n');
10
+ console.log('To run full benchmarks: npm run benchmark');
11
+ console.log('Check results at: https://chaincss.dev/benchmarks\n');
12
+
13
+ // Simple version info
14
+ const { version } = require('../../package.json');
15
+ console.log(`ChainCSS v${version} is ready for benchmarking!\n`);
16
+ console.log('For detailed benchmarks, please visit our documentation site.');
17
+ EOF
@@ -0,0 +1,299 @@
1
+ // benchmarks/run.js
2
+ const { execSync } = require('child_process');
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const os = require('os');
6
+
7
+ const libraries = [
8
+ {
9
+ name: 'ChainCSS (Build)',
10
+ setup: () => {
11
+ const content = `
12
+ const button = $()
13
+ .backgroundColor('blue')
14
+ .color('white')
15
+ .padding('8px 16px')
16
+ .borderRadius('4px')
17
+ .hover().backgroundColor('darkblue').end()
18
+ .block('.btn');
19
+ module.exports = { button };
20
+ `;
21
+ fs.writeFileSync('./test.jcss', content);
22
+ },
23
+ build: () => {
24
+ execSync('npx @melcanz85/chaincss ./test.jcss ./dist --atomic', { stdio: 'pipe' });
25
+ },
26
+ cleanup: () => {
27
+ fs.unlinkSync('./test.jcss');
28
+ if (fs.existsSync('./dist')) {
29
+ fs.rmSync('./dist', { recursive: true });
30
+ }
31
+ }
32
+ },
33
+ {
34
+ name: 'ChainCSS (Runtime)',
35
+ setup: () => {
36
+ const content = `
37
+ import { $ } from '@melcanz85/chaincss';
38
+ const button = $()
39
+ .backgroundColor('blue')
40
+ .color('white')
41
+ .padding('8px 16px')
42
+ .borderRadius('4px')
43
+ .hover().backgroundColor('darkblue').end()
44
+ .block('.btn');
45
+ export default button;
46
+ `;
47
+ fs.writeFileSync('./test.js', content);
48
+ },
49
+ build: () => {
50
+ // No build step for runtime
51
+ },
52
+ cleanup: () => {
53
+ fs.unlinkSync('./test.js');
54
+ }
55
+ },
56
+ {
57
+ name: 'CSS Modules',
58
+ setup: () => {
59
+ const content = `
60
+ .btn {
61
+ background-color: blue;
62
+ color: white;
63
+ padding: 8px 16px;
64
+ border-radius: 4px;
65
+ }
66
+ .btn:hover {
67
+ background-color: darkblue;
68
+ }
69
+ `;
70
+ fs.writeFileSync('./test.module.css', content);
71
+ },
72
+ build: () => {
73
+ // CSS Modules are handled by webpack
74
+ },
75
+ cleanup: () => {
76
+ fs.unlinkSync('./test.module.css');
77
+ }
78
+ },
79
+ {
80
+ name: 'Vanilla Extract',
81
+ setup: () => {
82
+ const content = `
83
+ import { style } from '@vanilla-extract/css';
84
+ export const button = style({
85
+ backgroundColor: 'blue',
86
+ color: 'white',
87
+ padding: '8px 16px',
88
+ borderRadius: '4px',
89
+ ':hover': {
90
+ backgroundColor: 'darkblue'
91
+ }
92
+ });
93
+ `;
94
+ fs.writeFileSync('./test.css.ts', content);
95
+ },
96
+ build: () => {
97
+ execSync('npx esbuild ./test.css.ts --bundle --outfile=./dist/test.js', { stdio: 'pipe' });
98
+ },
99
+ cleanup: () => {
100
+ fs.unlinkSync('./test.css.ts');
101
+ if (fs.existsSync('./dist')) {
102
+ fs.rmSync('./dist', { recursive: true });
103
+ }
104
+ }
105
+ },
106
+ {
107
+ name: 'Styled Components',
108
+ setup: () => {
109
+ const content = `
110
+ import styled from 'styled-components';
111
+ export const Button = styled.button\`
112
+ background-color: blue;
113
+ color: white;
114
+ padding: 8px 16px;
115
+ border-radius: 4px;
116
+ &:hover {
117
+ background-color: darkblue;
118
+ }
119
+ \`;
120
+ `;
121
+ fs.writeFileSync('./test.jsx', content);
122
+ },
123
+ build: () => {
124
+ execSync('npx esbuild ./test.jsx --bundle --outfile=./dist/test.js', { stdio: 'pipe' });
125
+ },
126
+ cleanup: () => {
127
+ fs.unlinkSync('./test.jsx');
128
+ if (fs.existsSync('./dist')) {
129
+ fs.rmSync('./dist', { recursive: true });
130
+ }
131
+ }
132
+ }
133
+ ];
134
+
135
+ async function runBenchmarks() {
136
+ console.log('\n🚀 Running ChainCSS Performance Benchmarks\n');
137
+ console.log('═'.repeat(60));
138
+
139
+ const results = [];
140
+
141
+ for (const lib of libraries) {
142
+ console.log(`\n📊 Testing ${lib.name}...`);
143
+
144
+ // Setup
145
+ lib.setup();
146
+
147
+ // Measure build time
148
+ const start = performance.now();
149
+ try {
150
+ await lib.build();
151
+ } catch (err) {
152
+ console.error(` ❌ Failed: ${err.message}`);
153
+ lib.cleanup();
154
+ continue;
155
+ }
156
+ const buildTime = performance.now() - start;
157
+
158
+ // Measure bundle size
159
+ let bundleSize = 0;
160
+ let cssSize = 0;
161
+
162
+ if (lib.name === 'ChainCSS (Build)') {
163
+ if (fs.existsSync('./dist/global.css')) {
164
+ cssSize = fs.statSync('./dist/global.css').size;
165
+ }
166
+ } else if (lib.name === 'ChainCSS (Runtime)') {
167
+ const bundle = fs.readFileSync('./test.js', 'utf8');
168
+ bundleSize = bundle.length;
169
+ } else if (lib.name === 'CSS Modules') {
170
+ // CSS Modules size is just the CSS file
171
+ cssSize = fs.statSync('./test.module.css').size;
172
+ } else if (fs.existsSync('./dist/test.js')) {
173
+ bundleSize = fs.statSync('./dist/test.js').size;
174
+ if (fs.existsSync('./dist/test.css')) {
175
+ cssSize = fs.statSync('./dist/test.css').size;
176
+ }
177
+ }
178
+
179
+ results.push({
180
+ name: lib.name,
181
+ buildTime: buildTime.toFixed(2),
182
+ bundleSize: formatBytes(bundleSize),
183
+ cssSize: formatBytes(cssSize),
184
+ totalSize: formatBytes(bundleSize + cssSize)
185
+ });
186
+
187
+ // Cleanup
188
+ lib.cleanup();
189
+
190
+ console.log(` ✅ Build: ${buildTime.toFixed(2)}ms`);
191
+ console.log(` 📦 Bundle: ${formatBytes(bundleSize)}`);
192
+ console.log(` 🎨 CSS: ${formatBytes(cssSize)}`);
193
+ }
194
+
195
+ // Generate report
196
+ generateReport(results);
197
+ generateChart(results);
198
+ }
199
+
200
+ function formatBytes(bytes) {
201
+ if (bytes === 0) return '0 B';
202
+ const k = 1024;
203
+ const sizes = ['B', 'KB', 'MB'];
204
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
205
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
206
+ }
207
+
208
+ function generateReport(results) {
209
+ const markdown = `# ChainCSS Performance Benchmarks
210
+
211
+ ## Test Environment
212
+ - **OS**: ${os.type()} ${os.release()}
213
+ - **CPU**: ${os.cpus()[0].model}
214
+ - **RAM**: ${formatBytes(os.totalmem())}
215
+ - **Node**: ${process.version}
216
+ - **Date**: ${new Date().toISOString()}
217
+
218
+ ## Results
219
+
220
+ | Library | Build Time | Bundle Size | CSS Size | Total Size |
221
+ |---------|------------|-------------|----------|------------|
222
+ ${results.map(r => `| ${r.name} | ${r.buildTime}ms | ${r.bundleSize} | ${r.cssSize} | ${r.totalSize} |`).join('\n')}
223
+
224
+ ## Key Findings
225
+
226
+ ${generateInsights(results)}
227
+
228
+ ## Recommendations
229
+
230
+ ${generateRecommendations(results)}
231
+ `;
232
+
233
+ fs.writeFileSync('./benchmarks/results.md', markdown);
234
+ console.log('\n✅ Report saved to benchmarks/results.md');
235
+ }
236
+
237
+ function generateInsights(results) {
238
+ const chaincssBuild = results.find(r => r.name === 'ChainCSS (Build)');
239
+ const chaincssRuntime = results.find(r => r.name === 'ChainCSS (Runtime)');
240
+ const cssModules = results.find(r => r.name === 'CSS Modules');
241
+ const vanillaExtract = results.find(r => r.name === 'Vanilla Extract');
242
+ const styledComponents = results.find(r => r.name === 'Styled Components');
243
+
244
+ let insights = [];
245
+
246
+ if (chaincssBuild && cssModules) {
247
+ insights.push(`- **ChainCSS (Build)** is ${((parseFloat(cssModules.buildTime) - parseFloat(chaincssBuild.buildTime)) / parseFloat(cssModules.buildTime) * 100).toFixed(0)}% faster than CSS Modules`);
248
+ }
249
+
250
+ if (chaincssBuild && vanillaExtract) {
251
+ insights.push(`- **ChainCSS (Build)** is ${((parseFloat(vanillaExtract.buildTime) - parseFloat(chaincssBuild.buildTime)) / parseFloat(vanillaExtract.buildTime) * 100).toFixed(0)}% faster than Vanilla Extract`);
252
+ }
253
+
254
+ if (chaincssRuntime && styledComponents) {
255
+ insights.push(`- **ChainCSS (Runtime)** is ${((parseFloat(styledComponents.bundleSize) - parseFloat(chaincssRuntime.bundleSize)) / parseFloat(styledComponents.bundleSize) * 100).toFixed(0)}% smaller than Styled Components`);
256
+ }
257
+
258
+ return insights.join('\n');
259
+ }
260
+
261
+ function generateRecommendations(results) {
262
+ return `
263
+ ### For Static Sites
264
+ **Use ChainCSS (Build Mode)** - ${results.find(r => r.name === 'ChainCSS (Build)')?.buildTime}ms build time, zero runtime
265
+
266
+ ### For Dynamic Apps
267
+ **Use ChainCSS (Runtime Mode)** - ${results.find(r => r.name === 'ChainCSS (Runtime)')?.bundleSize} bundle size, full dynamic capability
268
+
269
+ ### For Best Performance
270
+ **Use ChainCSS with Atomic CSS** - Automatic optimization with ${results.find(r => r.name === 'ChainCSS (Build)')?.cssSize} CSS output
271
+
272
+ ### For Component Libraries
273
+ **Use ChainCSS Recipe System** - Built-in variants, compound styles, zero config
274
+ `;
275
+ }
276
+
277
+ function generateChart(results) {
278
+ const chartData = {
279
+ labels: results.map(r => r.name),
280
+ datasets: [
281
+ {
282
+ label: 'Build Time (ms)',
283
+ data: results.map(r => parseFloat(r.buildTime)),
284
+ backgroundColor: 'rgba(102, 126, 234, 0.5)'
285
+ },
286
+ {
287
+ label: 'Bundle Size (KB)',
288
+ data: results.map(r => parseFloat(r.bundleSize)),
289
+ backgroundColor: 'rgba(118, 75, 162, 0.5)'
290
+ }
291
+ ]
292
+ };
293
+
294
+ fs.writeFileSync('./benchmarks/chart-data.json', JSON.stringify(chartData, null, 2));
295
+ console.log('📊 Chart data saved to benchmarks/chart-data.json');
296
+ }
297
+
298
+ // Run benchmarks
299
+ runBenchmarks().catch(console.error);
@@ -0,0 +1,62 @@
1
+ // node/loaders/chaincss-loader.js
2
+ const path = require('path');
3
+ const { execSync } = require('child_process');
4
+ const fs = require('fs');
5
+
6
+ module.exports = function(source) {
7
+ const callback = this.async();
8
+ const options = this.getOptions() || {};
9
+
10
+ const mode = options.mode || (process.env.NODE_ENV === 'production' ? 'build' : 'runtime');
11
+
12
+ if (mode === 'runtime') {
13
+ const code = `
14
+ import { $, compile } from '@melcanz85/chaincss';
15
+ const styles = (() => {
16
+ ${source}
17
+ return { ${extractStyleNames(source)} };
18
+ })();
19
+ export default styles;
20
+ `;
21
+ callback(null, code);
22
+ return;
23
+ }
24
+
25
+ try {
26
+ const tempFile = path.join(this.context, '.temp.jcss');
27
+ fs.writeFileSync(tempFile, source);
28
+
29
+ const outputDir = path.join(process.cwd(), '.chaincss-cache');
30
+ if (!fs.existsSync(outputDir)) {
31
+ fs.mkdirSync(outputDir, { recursive: true });
32
+ }
33
+
34
+ const cmd = `node ${path.join(__dirname, '../chaincss.js')} ${tempFile} ${outputDir} ${options.atomic ? '--atomic' : ''}`;
35
+ execSync(cmd, { stdio: 'pipe' });
36
+
37
+ const cssPath = path.join(outputDir, 'global.css');
38
+ const css = fs.readFileSync(cssPath, 'utf8');
39
+
40
+ fs.unlinkSync(tempFile);
41
+
42
+ const code = `
43
+ const css = ${JSON.stringify(css)};
44
+ if (typeof document !== 'undefined') {
45
+ const style = document.createElement('style');
46
+ style.setAttribute('data-chaincss', ${JSON.stringify(this.resourcePath)});
47
+ style.textContent = css;
48
+ document.head.appendChild(style);
49
+ }
50
+ export default {};
51
+ `;
52
+ callback(null, code);
53
+ } catch (err) {
54
+ callback(err);
55
+ }
56
+ };
57
+
58
+ function extractStyleNames(source) {
59
+ const matches = source.match(/const\s+(\w+)\s*=\s*\$\(\)/g);
60
+ if (!matches) return '';
61
+ return matches.map(m => m.match(/const\s+(\w+)/)[1]).join(', ');
62
+ }
@@ -0,0 +1,29 @@
1
+ // node/plugins/next-plugin.js
2
+ const path = require('path');
3
+
4
+ module.exports = function withChainCSS(nextConfig = {}) {
5
+ return {
6
+ ...nextConfig,
7
+ webpack(config, options) {
8
+ config.module.rules.push({
9
+ test: /\.jcss$/,
10
+ use: [
11
+ options.defaultLoaders.babel,
12
+ {
13
+ loader: path.resolve(__dirname, '../loaders/chaincss-loader.js'),
14
+ options: {
15
+ mode: process.env.NODE_ENV === 'production' ? 'build' : 'runtime',
16
+ atomic: process.env.NODE_ENV === 'production'
17
+ }
18
+ }
19
+ ]
20
+ });
21
+
22
+ if (typeof nextConfig.webpack === 'function') {
23
+ return nextConfig.webpack(config, options);
24
+ }
25
+ return config;
26
+ },
27
+ pageExtensions: [...(nextConfig.pageExtensions || []), 'jcss']
28
+ };
29
+ };
@@ -0,0 +1,215 @@
1
+ // node/plugins/vite-plugin.js
2
+ import path from 'node:path';
3
+ import fs from 'node:fs';
4
+ import { createRequire } from 'node:module';
5
+ import CleanCSS from 'clean-css';
6
+ import { $, run, compile as originalCompile, chain } from '../btt.js';
7
+
8
+ const require = createRequire(import.meta.url);
9
+
10
+ // Optional: Try to load prefixer
11
+ let prefixer;
12
+ try {
13
+ const ChainCSSPrefixer = (await import('../prefixer.js')).default;
14
+ prefixer = new ChainCSSPrefixer({ enabled: true });
15
+ } catch (err) {
16
+ console.warn('ChainCSS: Prefixer not available, autoprefixing disabled');
17
+ prefixer = { process: async (css) => ({ css }) };
18
+ }
19
+
20
+ // Cache for processed files
21
+ const fileCache = new Map();
22
+ const compiledCache = new Map();
23
+
24
+ // Helper to compile script without temp files
25
+ const compileScript = (scriptBlock, filename, get) => {
26
+ const dirname = path.dirname(filename);
27
+
28
+ // Reset CSS output
29
+ chain.cssOutput = '';
30
+
31
+ // Create a function from the script - no temp files!
32
+ const fn = new Function(
33
+ '$',
34
+ 'run',
35
+ 'compile',
36
+ 'chain',
37
+ 'get',
38
+ '__filename',
39
+ '__dirname',
40
+ scriptBlock
41
+ );
42
+
43
+ // Execute with helpers
44
+ fn($, run, originalCompile, chain, get, filename, dirname);
45
+
46
+ return chain.cssOutput || '';
47
+ };
48
+
49
+ const processJavascriptBlocks = (content, filename, get) => {
50
+ const blocks = content.split(/<@([\s\S]*?)@>/gm);
51
+ let output = '';
52
+
53
+ for (let i = 0; i < blocks.length; i++) {
54
+ if (i % 2 === 0) {
55
+ // Static content
56
+ output += blocks[i];
57
+ } else {
58
+ // JavaScript block
59
+ const css = compileScript(blocks[i], filename, get);
60
+ if (css && typeof css === 'string') {
61
+ output += css;
62
+ }
63
+ }
64
+ }
65
+
66
+ return output.trim();
67
+ };
68
+
69
+ const processJCSSFile = (filePath) => {
70
+ const abs = path.resolve(filePath);
71
+
72
+ // Return cached result if available
73
+ if (fileCache.has(abs)) return fileCache.get(abs);
74
+
75
+ // Check if file exists
76
+ if (!fs.existsSync(abs)) {
77
+ throw new Error(`ChainCSS: File not found: ${abs}`);
78
+ }
79
+
80
+ const content = fs.readFileSync(abs, 'utf8');
81
+ const dirname = path.dirname(abs);
82
+
83
+ // Create get function for this file
84
+ const get = (relativePath) => {
85
+ const targetPath = path.resolve(dirname, relativePath);
86
+ return processJCSSFile(targetPath);
87
+ };
88
+
89
+ // Process the file
90
+ const result = processJavascriptBlocks(content, abs, get);
91
+
92
+ // Cache the result
93
+ fileCache.set(abs, result);
94
+ return result;
95
+ };
96
+
97
+ // Minify and prefix CSS
98
+ const processCSS = async (css, filepath, options = {}) => {
99
+ const { minify = true, prefix = true } = options;
100
+ let processed = css;
101
+
102
+ // Add prefixing
103
+ if (prefix && prefixer) {
104
+ try {
105
+ const result = await prefixer.process(css, { from: filepath });
106
+ processed = result.css;
107
+ } catch (err) {
108
+ console.warn(`ChainCSS prefixer error in ${filepath}:`, err.message);
109
+ }
110
+ }
111
+
112
+ // Minify
113
+ if (minify) {
114
+ const minified = new CleanCSS({ level: 2 }).minify(processed);
115
+ if (minified.errors.length) {
116
+ console.warn(`ChainCSS minification errors in ${filepath}:`, minified.errors);
117
+ }
118
+ return minified.styles;
119
+ }
120
+
121
+ return processed;
122
+ };
123
+
124
+ export default function chaincssVite(opts = {}) {
125
+ const {
126
+ extension = '.jcss',
127
+ minify = process.env.NODE_ENV === 'production',
128
+ prefix = true,
129
+ hmr = true
130
+ } = opts;
131
+
132
+ return {
133
+ name: 'vite-plugin-chaincss',
134
+ enforce: 'pre',
135
+
136
+ // Transform .jcss files
137
+ async transform(code, id) {
138
+ if (!id.endsWith(extension)) return null;
139
+
140
+ try {
141
+ // Create get function for root file
142
+ const dirname = path.dirname(id);
143
+ const get = (relativePath) => {
144
+ const targetPath = path.resolve(dirname, relativePath);
145
+ return processJCSSFile(targetPath);
146
+ };
147
+
148
+ // Process the file
149
+ let css = processJavascriptBlocks(code, id, get);
150
+
151
+ // Process CSS (prefix + minify)
152
+ css = await processCSS(css, id, { minify, prefix });
153
+
154
+ // In development, inject CSS for HMR
155
+ if (process.env.NODE_ENV !== 'production') {
156
+ return {
157
+ code: `
158
+ // ChainCSS HMR
159
+ const id = ${JSON.stringify(id)};
160
+ const css = ${JSON.stringify(css)};
161
+
162
+ // Add style to head
163
+ let style = document.querySelector(\`style[data-chaincss="\${id}"]\`);
164
+ if (!style) {
165
+ style = document.createElement('style');
166
+ style.setAttribute('data-chaincss', id);
167
+ document.head.appendChild(style);
168
+ }
169
+ style.textContent = css;
170
+
171
+ // HMR handling
172
+ if (import.meta.hot) {
173
+ import.meta.hot.accept((newModule) => {
174
+ if (newModule?.default) {
175
+ style.textContent = newModule.default;
176
+ }
177
+ });
178
+
179
+ import.meta.hot.dispose(() => {
180
+ style.remove();
181
+ });
182
+ }
183
+
184
+ export default css;
185
+ `,
186
+ map: null
187
+ };
188
+ }
189
+
190
+ // Production: just export CSS
191
+ return {
192
+ code: `export default ${JSON.stringify(css)};`,
193
+ map: null
194
+ };
195
+
196
+ } catch (err) {
197
+ this.error(`ChainCSS error in ${id}: ${err.message}`);
198
+ return null;
199
+ }
200
+ },
201
+
202
+ // Handle HMR updates
203
+ handleHotUpdate({ file, server }) {
204
+ if (file.endsWith(extension)) {
205
+ // Invalidate cache for changed file
206
+ fileCache.delete(file);
207
+ // Trigger reload
208
+ server.ws.send({
209
+ type: 'full-reload',
210
+ path: '*'
211
+ });
212
+ }
213
+ }
214
+ };
215
+ }
@@ -0,0 +1,41 @@
1
+ // node/plugins/webpack-plugin.js
2
+ const path = require('path');
3
+ const { execSync } = require('child_process');
4
+ const fs = require('fs');
5
+
6
+ class ChainCSSWebpackPlugin {
7
+ constructor(options = {}) {
8
+ this.options = {
9
+ atomic: process.env.NODE_ENV === 'production',
10
+ input: './src/styles/main.jcss',
11
+ output: './dist',
12
+ ...options
13
+ };
14
+ }
15
+
16
+ apply(compiler) {
17
+ compiler.hooks.beforeCompile.tapAsync('ChainCSSPlugin', async (params, callback) => {
18
+ try {
19
+ const inputPath = path.resolve(process.cwd(), this.options.input);
20
+ const outputPath = path.resolve(process.cwd(), this.options.output);
21
+
22
+ if (!fs.existsSync(inputPath)) {
23
+ console.warn('ChainCSS: No main.jcss file found, skipping...');
24
+ callback();
25
+ return;
26
+ }
27
+
28
+ const cmd = `node ${path.join(__dirname, '../chaincss.js')} ${inputPath} ${outputPath} ${this.options.atomic ? '--atomic' : ''}`;
29
+ execSync(cmd, { stdio: 'inherit' });
30
+
31
+ console.log('ChainCSS compiled successfully');
32
+ callback();
33
+ } catch (err) {
34
+ console.error('ChainCSS compilation failed:', err.message);
35
+ callback(err);
36
+ }
37
+ });
38
+ }
39
+ }
40
+
41
+ module.exports = ChainCSSWebpackPlugin;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@melcanz85/chaincss",
3
- "version": "1.12.0",
3
+ "version": "1.12.1",
4
4
  "description": "Chainable CSS-in-JS with build-time compilation, atomic CSS, and zero-runtime options",
5
5
  "keywords": [
6
6
  "css",