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
package/node/prefixer.js DELETED
@@ -1,237 +0,0 @@
1
- let postcss, browserslist, caniuse, autoprefixer;
2
- try {
3
- postcss = require('postcss');
4
- browserslist = require('browserslist');
5
- caniuse = require('caniuse-db/fulldata-json/data-2.0.json');
6
- } catch (err) {
7
- }
8
- try {
9
- autoprefixer = require('autoprefixer');
10
- } catch (err) {
11
- }
12
- class ChainCSSPrefixer {
13
- constructor(config = {}) {
14
- this.config = {
15
- browsers: config.browsers || ['> 0.5%', 'last 2 versions', 'not dead'],
16
- enabled: config.enabled !== false,
17
- mode: config.mode || 'auto',
18
- sourceMap: config.sourceMap !== false, // Enable source maps by default
19
- sourceMapInline: config.sourceMapInline || false,
20
- ...config
21
- };
22
- this.hasBuiltInDeps = !!(postcss && browserslist && caniuse);
23
- this.hasAutoprefixer = !!autoprefixer;
24
- this.prefixerMode = this.determineMode();
25
- this.caniuseData = caniuse ? caniuse.data : null;
26
- this.commonProperties = this.getCommonProperties();
27
- this.specialValues = {
28
- 'display': ['flex', 'inline-flex', 'grid', 'inline-grid'],
29
- 'background-clip': ['text'],
30
- 'position': ['sticky']
31
- };
32
- this.browserPrefixMap = {
33
- 'chrome': 'webkit', 'safari': 'webkit', 'firefox': 'moz',
34
- 'ie': 'ms', 'edge': 'webkit', 'ios_saf': 'webkit',
35
- 'and_chr': 'webkit', 'android': 'webkit', 'opera': 'webkit',
36
- 'op_mob': 'webkit', 'samsung': 'webkit', 'and_ff': 'moz'
37
- };
38
- this.targetBrowsers = null;
39
- }
40
- determineMode() {
41
- if (this.config.mode === 'full' && !this.hasAutoprefixer) {
42
- console.warn('Full mode requested but autoprefixer not installed. Falling back to lightweight mode.');
43
- console.warn(' To use full mode: npm install autoprefixer postcss caniuse-db browserslist\n');
44
- return 'lightweight';
45
- }
46
- if (this.config.mode === 'lightweight') {
47
- return 'lightweight';
48
- }
49
- if (this.config.mode === 'full' && this.hasAutoprefixer) {
50
- return 'full';
51
- }
52
- if (this.config.mode === 'auto') {
53
- return this.hasAutoprefixer ? 'full' : 'lightweight';
54
- }
55
- return 'lightweight';
56
- }
57
- async process(cssString, options = {}) {
58
- if (!this.config.enabled) {
59
- return { css: cssString, map: null };
60
- }
61
- try {
62
- const mapOptions = {
63
- inline: this.config.sourceMapInline,
64
- annotation: false,
65
- sourcesContent: true
66
- };
67
- if (this.prefixerMode === 'full') {
68
- return await this.processWithAutoprefixer(cssString, options, mapOptions);
69
- }
70
- return await this.processWithBuiltIn(cssString, options, mapOptions);
71
- } catch (err) {
72
- console.error('Prefixer error:', err.message);
73
- return { css: cssString, map: null };
74
- }
75
- }
76
- async processWithAutoprefixer(cssString, options, mapOptions) {
77
- const from = options.from || 'input.css';
78
- const to = options.to || 'output.css';
79
- const result = await postcss([
80
- autoprefixer({ overrideBrowserslist: this.config.browsers })
81
- ]).process(cssString, {
82
- from,
83
- to,
84
- map: this.config.sourceMap ? mapOptions : false
85
- });
86
- return {
87
- css: result.css,
88
- map: result.map ? result.map.toString() : null
89
- };
90
- }
91
- async processWithBuiltIn(cssString, options, mapOptions) {
92
- if (!this.hasBuiltInDeps) {
93
- return { css: cssString, map: null };
94
- }
95
- this.targetBrowsers = browserslist(this.config.browsers);
96
- const from = options.from || 'input.css';
97
- const to = options.to || 'output.css';
98
- const result = await postcss([
99
- this.createBuiltInPlugin()
100
- ]).process(cssString, {
101
- from,
102
- to,
103
- map: this.config.sourceMap ? mapOptions : false
104
- });
105
- return {
106
- css: result.css,
107
- map: result.map ? result.map.toString() : null
108
- };
109
- }
110
- createBuiltInPlugin() {
111
- return (root) => {
112
- root.walkDecls(decl => {
113
- this.processBuiltInDeclaration(decl);
114
- });
115
- };
116
- }
117
- processBuiltInDeclaration(decl) {
118
- const { prop, value } = decl;
119
- if (this.commonProperties.includes(prop)) {
120
- this.addPrefixesFromCaniuse(decl);
121
- }
122
- if (this.specialValues[prop]?.includes(value)) {
123
- this.addSpecialValuePrefixes(decl);
124
- }
125
- }
126
- addPrefixesFromCaniuse(decl) {
127
- if (!this.caniuseData) return;
128
- const feature = this.findFeature(decl.prop);
129
- if (!feature) return;
130
- const prefixes = new Set();
131
- this.targetBrowsers.forEach(browser => {
132
- const [id, versionStr] = browser.split(' ');
133
- const version = parseFloat(versionStr.split('-')[0]);
134
- const stats = feature.stats[id];
135
- if (stats) {
136
- const versions = Object.keys(stats)
137
- .map(v => parseFloat(v.split('-')[0]))
138
- .filter(v => !isNaN(v))
139
- .sort((a, b) => a - b);
140
- const closestVersion = versions.find(v => v <= version) || versions[0];
141
- if (closestVersion) {
142
- const support = stats[closestVersion.toString()];
143
- if (support && support.includes('x')) {
144
- const prefix = this.browserPrefixMap[id.split('-')[0]];
145
- if (prefix) prefixes.add(prefix);
146
- }
147
- }
148
- }
149
- });
150
-
151
- prefixes.forEach(prefix => {
152
- decl.cloneBefore({
153
- prop: `-${prefix}-${decl.prop}`,
154
- value: decl.value
155
- });
156
- });
157
- }
158
- addSpecialValuePrefixes(decl) {
159
- const { prop, value } = decl;
160
- if (prop === 'display') {
161
- if (value === 'flex' || value === 'inline-flex') {
162
- decl.cloneBefore({ prop: 'display', value: `-webkit-${value}` });
163
- decl.cloneBefore({
164
- prop: 'display',
165
- value: value === 'flex' ? '-ms-flexbox' : '-ms-inline-flexbox'
166
- });
167
- }
168
- if (value === 'grid' || value === 'inline-grid') {
169
- decl.cloneBefore({
170
- prop: 'display',
171
- value: value === 'grid' ? '-ms-grid' : '-ms-inline-grid'
172
- });
173
- }
174
- }
175
- if (prop === 'background-clip' && value === 'text') {
176
- decl.cloneBefore({ prop: '-webkit-background-clip', value: 'text' });
177
- }
178
- if (prop === 'position' && value === 'sticky') {
179
- decl.cloneBefore({ prop: 'position', value: '-webkit-sticky' });
180
- }
181
- }
182
-
183
- findFeature(property) {
184
- if (!this.caniuseData) return null;
185
- const featureMap = {
186
- 'transform': 'transforms2d',
187
- 'transform-origin': 'transforms2d',
188
- 'transform-style': 'transforms3d',
189
- 'perspective': 'transforms3d',
190
- 'backface-visibility': 'transforms3d',
191
- 'transition': 'css-transitions',
192
- 'animation': 'css-animation',
193
- 'backdrop-filter': 'backdrop-filter',
194
- 'filter': 'css-filters',
195
- 'user-select': 'user-select-none',
196
- 'appearance': 'css-appearance',
197
- 'mask-image': 'css-masks',
198
- 'box-shadow': 'css-boxshadow',
199
- 'border-radius': 'border-radius',
200
- 'text-fill-color': 'text-stroke',
201
- 'text-stroke': 'text-stroke',
202
- 'background-clip': 'background-img-opts',
203
- 'flex': 'flexbox',
204
- 'flex-grow': 'flexbox',
205
- 'flex-shrink': 'flexbox',
206
- 'flex-basis': 'flexbox',
207
- 'justify-content': 'flexbox',
208
- 'align-items': 'flexbox',
209
- 'grid': 'css-grid',
210
- 'grid-template': 'css-grid',
211
- 'grid-column': 'css-grid',
212
- 'grid-row': 'css-grid'
213
- };
214
- const featureId = featureMap[property];
215
- return featureId ? this.caniuseData[featureId] : null;
216
- }
217
- getCommonProperties() {
218
- return [
219
- 'transform', 'transform-origin', 'transform-style',
220
- 'transition', 'transition-property', 'transition-duration', 'transition-timing-function',
221
- 'animation', 'animation-name', 'animation-duration', 'animation-timing-function',
222
- 'animation-delay', 'animation-iteration-count', 'animation-direction',
223
- 'animation-fill-mode', 'animation-play-state',
224
- 'backdrop-filter', 'filter',
225
- 'user-select', 'appearance',
226
- 'text-fill-color', 'text-stroke', 'text-stroke-color', 'text-stroke-width',
227
- 'background-clip',
228
- 'mask-image', 'mask-clip', 'mask-composite', 'mask-origin',
229
- 'mask-position', 'mask-repeat', 'mask-size',
230
- 'box-shadow', 'border-radius', 'box-sizing',
231
- 'display', 'flex', 'flex-grow', 'flex-shrink', 'flex-basis',
232
- 'justify-content', 'align-items', 'align-self', 'align-content',
233
- 'grid', 'grid-template', 'grid-column', 'grid-row'
234
- ];
235
- }
236
- }
237
- module.exports = ChainCSSPrefixer;
package/node/strVal.js DELETED
@@ -1,92 +0,0 @@
1
- const strVal = {
2
- userConf: `// ChainCSS Configuration
3
- // Generated: ${new Date().toISOString()}
4
-
5
- module.exports = {
6
- atomic: {
7
- enabled: true, // Enable atomic CSS optimization
8
- threshold: 3, // Minimum usage count for atomic conversion
9
- naming: 'hash', // 'hash' (c_3b82f6) or 'readable' (bg-blue-500)
10
- cache: true, // Cache atomic classes between builds
11
- cachePath: './.chaincss-cache',
12
- minify: true, // Minify CSS output
13
- mode: 'hybrid', // 'atomic' | 'standard' | 'hybrid'
14
- alwaysAtomic: [], // Force these properties to be atomic
15
- neverAtomic: [ // Never make these properties atomic
16
- 'content', 'animation', 'transition', 'keyframes',
17
- 'counterIncrement', 'counterReset'
18
- ],
19
- outputStrategy: 'component-first',
20
- frameworkOutput: {
21
- react: false, // Generate React hooks
22
- vue: false, // Generate Vue composables
23
- vanilla: true // Generate vanilla JS class map
24
- },
25
- preserveSelectors: false, // Keep original selector names in comments
26
- verbose: true // Show detailed atomic optimization stats
27
- },
28
- prefixer: {
29
- enabled: true,
30
- mode: 'auto', // 'auto' | 'always' | 'never'
31
- browsers: ['> 0.5%', 'last 2 versions', 'not dead'],
32
- sourceMap: true,
33
- sourceMapInline: false
34
- }
35
- };
36
- `,
37
- cli_opt_guide: `
38
- ChainCSS - JavaScript-powered CSS preprocessor
39
-
40
- Usage:
41
- chaincss <inputFile> <outputFile> [options]
42
-
43
- Options:
44
- --watch Watch for changes and auto-recompile
45
- --no-prefix Disable automatic prefixing
46
- --prefixer-mode <mode> Set prefixer mode (auto|lightweight|full)
47
- --browsers <list> Browser support list (comma-separated)
48
- --no-source-map Disable source maps
49
- --source-map-inline Use inline source maps
50
-
51
- # Atomic CSS Optimization
52
- --atomic Enable atomic CSS optimization
53
- --atomic-mode <mode> Atomic mode: atomic, standard, hybrid (default: hybrid)
54
- --atomic-naming <scheme> Naming scheme: hash, readable (default: hash)
55
- --atomic-verbose Show detailed atomic optimization stats
56
- --preserve-selectors Keep original selector names in comments
57
- --no-atomic-cache Disable atomic CSS cache
58
-
59
- # Output Control
60
- --no-minify Disable CSS minification
61
-
62
- # Help
63
- --help, -h Show this help message
64
- --version, -v Show version number
65
-
66
- Examples:
67
- # Basic compilation
68
- chaincss style.jcss dist/
69
-
70
- # Watch mode for development
71
- chaincss style.jcss dist/ --watch
72
-
73
- # Atomic CSS optimization
74
- chaincss style.jcss dist/ --atomic
75
-
76
- # With custom naming scheme
77
- chaincss style.jcss dist/ --atomic --atomic-naming readable
78
-
79
- # Verbose output for debugging
80
- chaincss style.jcss dist/ --atomic --atomic-verbose
81
-
82
- # Custom browser support
83
- chaincss style.jcss dist/ --browsers "> 1%, last 2 versions, not dead"
84
-
85
- Notes:
86
- - Atomic CSS optimization reduces CSS size by reusing common style patterns
87
- - Use --watch during development for instant updates
88
- - Use --atomic for production builds to optimize CSS bundle size
89
- `
90
- }
91
-
92
- module.exports = strVal;
@@ -1,32 +0,0 @@
1
- import fs from 'fs';
2
- import path from 'path';
3
-
4
- export function validateThemeFiles(configPath) {
5
- const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
6
-
7
- if (!config.themes) return;
8
-
9
- const { contract, themes } = config;
10
-
11
- console.log('\nValidating Theme Contract...\n');
12
-
13
- const errors = [];
14
-
15
- themes.forEach((theme, index) => {
16
- const themeName = theme.name || `theme-${index}`;
17
- try {
18
- validateTheme(contract, theme.values);
19
- console.log(`${themeName}: Valid`);
20
- } catch (err) {
21
- errors.push(`${themeName}: ${err.message}`);
22
- }
23
- });
24
-
25
- if (errors.length > 0) {
26
- console.error('\nTheme Contract Validation Failed:\n');
27
- errors.forEach(err => console.error(err));
28
- process.exit(1);
29
- }
30
-
31
- console.log('\nAll themes valid!\n');
32
- }
@@ -1,98 +0,0 @@
1
- export function createThemeContract(contractShape) {
2
- // Store the contract for validation
3
- const contract = contractShape;
4
-
5
- // Create a proxy that validates token access
6
- const contractProxy = new Proxy(contract, {
7
- get(target, prop) {
8
- if (prop === '__isContract') return true;
9
- if (prop === '__validate') return (theme) => validateTheme(contract, theme);
10
- return target[prop];
11
- }
12
- });
13
-
14
- return contractProxy;
15
- }
16
-
17
- export function validateTheme(contract, theme, path = '') {
18
- const errors = [];
19
-
20
- function validate(contractPart, themePart, currentPath) {
21
- if (typeof contractPart === 'object' && contractPart !== null) {
22
- // Check if theme has all required keys
23
- const requiredKeys = Object.keys(contractPart);
24
- const themeKeys = Object.keys(themePart || {});
25
-
26
- requiredKeys.forEach(key => {
27
- const newPath = currentPath ? `${currentPath}.${key}` : key;
28
-
29
- if (!themePart || !themePart.hasOwnProperty(key)) {
30
- errors.push(` Missing required token: "${newPath}"`);
31
- } else {
32
- validate(contractPart[key], themePart[key], newPath);
33
- }
34
- });
35
-
36
- // Warn about extra keys (optional, could be allowed)
37
- themeKeys.forEach(key => {
38
- if (!contractPart.hasOwnProperty(key)) {
39
- const newPath = currentPath ? `${currentPath}.${key}` : key;
40
- console.warn(` Extra token not in contract: "${newPath}"`);
41
- }
42
- });
43
- } else {
44
- // Leaf node - just check type (optional)
45
- if (typeof themePart !== 'string') {
46
- errors.push(` Token "${currentPath}" must be a string, got ${typeof themePart}`);
47
- }
48
- }
49
- }
50
-
51
- validate(contract, theme, path);
52
-
53
- if (errors.length > 0) {
54
- throw new Error(`Theme Contract Validation Failed:\n${errors.join('\n')}`);
55
- }
56
-
57
- return true;
58
- }
59
-
60
- export function createTheme(contract, themeValues) {
61
- // Validate at creation time
62
- if (contract.__isContract) {
63
- contract.__validate(themeValues);
64
- } else {
65
- validateTheme(contract, themeValues);
66
- }
67
-
68
- // Create the actual theme tokens
69
- const tokens = {};
70
-
71
- function buildTokens(contractPart, themePart, target, path = '') {
72
- Object.keys(contractPart).forEach(key => {
73
- const newPath = path ? `${path}.${key}` : key;
74
-
75
- if (typeof contractPart[key] === 'object' && contractPart[key] !== null) {
76
- target[key] = {};
77
- buildTokens(contractPart[key], themePart[key] || {}, target[key], newPath);
78
- } else {
79
- target[key] = themePart[key];
80
- }
81
- });
82
- }
83
-
84
- buildTokens(contract, themeValues, tokens);
85
-
86
- // Add getter method
87
- tokens.get = (path) => {
88
- const parts = path.split('.');
89
- let current = tokens;
90
- for (const part of parts) {
91
- if (current === undefined) return undefined;
92
- current = current[part];
93
- }
94
- return current;
95
- };
96
-
97
- return tokens;
98
- }