chaincss 1.13.2 → 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 +239 -114
  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 -109
  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 -370
  85. package/node/atomic-optimizer.js +0 -391
  86. package/node/btt.js +0 -962
  87. package/node/cache-manager.js +0 -56
  88. package/node/chaincss.js +0 -489
  89. package/node/css-properties.json +0 -633
  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 -106
  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 -277
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 install this devDenpendecies: "npm install -D 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,106 +0,0 @@
1
- const strVal = {
2
- userConf: `// Project Configuration
3
- module.exports = {
4
- atomic: {
5
- enabled: true,
6
- threshold: 3,
7
- naming: 'hash',
8
- cache: true,
9
- cachePath: './.chaincss-cache',
10
- minify: true
11
- },
12
- prefixer: {
13
- mode: 'auto',
14
- browsers: ['> 0.5%', 'last 2 versions', 'not dead'],
15
- enabled: true,
16
- sourceMap: true,
17
- sourceMapInline: false
18
- }
19
- };
20
- `,
21
- cli_opt_guide: `
22
- ChainCSS - JavaScript-powered CSS preprocessor
23
-
24
- Usage:
25
- chaincss <inputFile> <outputFile> [options]
26
-
27
- Options:
28
- --watch Watch for changes and auto-recompile
29
- --no-prefix Disable automatic prefixing
30
- --prefixer-mode <mode> Set prefixer mode (auto|lightweight|full)
31
- --browsers <list> Browser support list (comma-separated)
32
- --no-source-map Disable source maps
33
- --source-map-inline Use inline source maps
34
-
35
- # Atomic CSS Optimization
36
- --atomic Enable atomic CSS optimization
37
- --threshold <number> Minimum usage count for atomic classes (default: 3)
38
- --atomic-naming <type> Atomic class naming (hash|readable) (default: hash)
39
- --no-atomic-cache Disable atomic CSS cache
40
-
41
- # Performance & Debug
42
- --verbose Enable verbose logging
43
- --debug Enable debug mode with detailed output
44
- --tree-shake Remove unused CSS classes (dead code elimination)
45
-
46
- # Output Control
47
- --minify Minify CSS output (default: true in production)
48
- --no-minify Disable CSS minification
49
- --out-dir <dir> Output directory (default: same as outputFile dir)
50
- --manifest Generate build manifest file
51
-
52
- # Configuration
53
- --config <path> Path to config file (default: chaincss.config.cjs)
54
- --no-config Ignore config file, use CLI options only
55
-
56
- # Theme Validation
57
- --validate-themes Validate theme contracts during build
58
-
59
- # Help
60
- --help, -h Show this help message
61
- --version, -v Show version number
62
-
63
- Examples:
64
- # Basic compilation
65
- chaincss style.jcss style.css
66
-
67
- # Watch mode for development
68
- chaincss style.jcss style.css --watch
69
-
70
- # Atomic CSS optimization
71
- chaincss style.jcss style.css --atomic
72
-
73
- # With custom threshold for atomic classes
74
- chaincss style.jcss style.css --atomic --threshold 5
75
-
76
- # Full production build with all optimizations
77
- chaincss style.jcss style.css --atomic --minify --tree-shake --source-map
78
-
79
- # Custom browser support
80
- chaincss style.jcss style.css --browsers "> 1%, last 2 versions, not dead"
81
-
82
- # Full autoprefixer mode
83
- chaincss style.jcss style.css --prefixer-mode full
84
-
85
- # Validate themes during build
86
- chaincss style.jcss style.css --validate-themes
87
-
88
- # Debug mode with verbose output
89
- chaincss style.jcss style.css --debug --verbose
90
-
91
- # Disable prefixing (for modern browsers only)
92
- chaincss style.jcss style.css --no-prefix
93
-
94
- # With custom config file
95
- chaincss style.jcss style.css --config ./my-chaincss.config.cjs
96
-
97
- Notes:
98
- - Atomic CSS optimization reduces CSS size by reusing common style patterns
99
- - Tree shaking removes unused CSS classes from final bundle
100
- - Theme validation ensures all themes have required tokens
101
- - Use --watch during development for instant updates
102
- - Use --atomic --minify --tree-shake for production builds
103
- `
104
- }
105
-
106
- 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('\nšŸŽØ Validating 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('\nāœ… All 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
- }