chaincss 2.0.7 → 2.1.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 +30 -0
- package/CODE_OF_CONDUCT.md +21 -0
- package/CONTRIBUTING.md +28 -0
- package/README.md +455 -226
- package/demo/demo/node_modules/caniuse-db/fulldata-json/data-2.0.json +1 -0
- package/demo/index.html +16 -0
- package/demo/package.json +20 -0
- package/demo/src/App.tsx +117 -0
- package/demo/src/chaincss-barrel.ts +9 -0
- package/demo/src/main.tsx +8 -0
- package/demo/src/styles.chain.ts +300 -0
- package/demo/vite.config.ts +46 -0
- package/dist/cli/commands/build.d.ts +0 -1
- package/dist/cli/commands/cache.d.ts +1 -0
- package/dist/cli/commands/init.d.ts +6 -3
- package/dist/cli/commands/timeline.d.ts +0 -1
- package/dist/cli/commands/watch.d.ts +0 -1
- package/dist/cli/index.d.ts +0 -1
- package/dist/cli/index.js +3213 -5296
- package/dist/cli/types.d.ts +51 -20
- package/dist/cli/utils/config-loader.d.ts +0 -1
- package/dist/cli/utils/file-utils.d.ts +27 -3
- package/dist/cli/utils/logger.d.ts +0 -1
- package/dist/compiler/Chain.d.ts +215 -0
- package/dist/compiler/animations.d.ts +76 -0
- package/dist/compiler/atomic-optimizer.d.ts +47 -12
- package/dist/compiler/breakpoints.d.ts +46 -0
- package/dist/compiler/btt.d.ts +36 -60
- package/dist/compiler/cache-manager.d.ts +58 -4
- package/dist/compiler/commonProps.d.ts +0 -1
- package/dist/compiler/content-addressable-cache.d.ts +78 -0
- package/dist/compiler/helpers.d.ts +54 -0
- package/dist/compiler/index.d.ts +16 -9
- package/dist/compiler/index.js +4450 -4316
- package/dist/compiler/prefixer.d.ts +17 -1
- package/dist/compiler/shorthands.d.ts +28 -0
- package/dist/compiler/suggestions.d.ts +43 -0
- package/dist/compiler/theme-contract.d.ts +16 -27
- package/dist/compiler/token-resolver.d.ts +69 -0
- package/dist/compiler/tokens.d.ts +33 -8
- package/dist/core/auto-detector.d.ts +34 -0
- package/dist/core/common-utils.d.ts +97 -0
- package/dist/core/compiler.d.ts +63 -23
- package/dist/core/constants.d.ts +137 -36
- package/dist/core/smart-chain.d.ts +3 -0
- package/dist/core/types.d.ts +122 -15
- package/dist/core/utils.d.ts +134 -17
- package/dist/index.d.ts +52 -8
- package/dist/index.js +7090 -5578
- package/dist/plugins/vite.d.ts +7 -5
- package/dist/plugins/vite.js +2964 -25641
- package/dist/plugins/webpack.d.ts +24 -1
- package/dist/plugins/webpack.js +209 -72
- package/dist/runtime/Chain.d.ts +32 -0
- package/dist/runtime/auto-hooks.d.ts +11 -0
- package/dist/runtime/hmr.d.ts +22 -2
- package/dist/runtime/index.d.ts +3 -2
- package/dist/runtime/index.js +3648 -301
- package/dist/runtime/injector.d.ts +39 -72
- package/dist/runtime/react.d.ts +17 -12
- package/dist/runtime/svelte.d.ts +15 -0
- package/dist/runtime/types.d.ts +126 -4
- package/dist/runtime/utils.d.ts +0 -1
- package/dist/runtime/vue.d.ts +34 -14
- package/package.json +59 -66
- package/src/cli/commands/build.ts +133 -0
- package/src/cli/commands/cache.ts +371 -0
- package/src/cli/commands/init.ts +230 -0
- package/src/cli/commands/timeline.ts +435 -0
- package/src/cli/commands/watch.ts +211 -0
- package/src/cli/index.ts +226 -0
- package/src/cli/types.ts +100 -0
- package/src/cli/utils/config-loader.ts +174 -0
- package/src/cli/utils/file-utils.ts +139 -0
- package/src/cli/utils/logger.ts +74 -0
- package/src/compiler/Chain.ts +831 -0
- package/src/compiler/animations.ts +517 -0
- package/src/compiler/atomic-optimizer.ts +786 -0
- package/src/compiler/breakpoints.ts +347 -0
- package/src/compiler/btt.ts +1147 -0
- package/src/compiler/cache-manager.ts +446 -0
- package/src/compiler/commonProps.ts +18 -0
- package/src/compiler/content-addressable-cache.ts +478 -0
- package/src/compiler/helpers.ts +407 -0
- package/src/compiler/index.ts +72 -0
- package/src/compiler/prefixer.ts +724 -0
- package/src/compiler/shorthands.ts +558 -0
- package/src/compiler/suggestions.ts +436 -0
- package/src/compiler/theme-contract.ts +197 -0
- package/src/compiler/token-resolver.ts +241 -0
- package/src/compiler/tokens.ts +612 -0
- package/src/core/auto-detector.ts +187 -0
- package/src/core/common-utils.ts +423 -0
- package/src/core/compiler.ts +835 -0
- package/src/core/constants.ts +424 -0
- package/src/core/index.ts +107 -0
- package/src/core/smart-chain.ts +163 -0
- package/src/core/types.ts +257 -0
- package/src/core/utils.ts +598 -0
- package/src/index.ts +208 -0
- package/src/plugins/vite.d.ts +316 -0
- package/src/plugins/vite.ts +424 -0
- package/src/plugins/webpack.d.ts +289 -0
- package/src/plugins/webpack.ts +416 -0
- package/src/runtime/Chain.ts +242 -0
- package/src/runtime/auto-hooks.tsx +127 -0
- package/src/runtime/auto-vue.ts +72 -0
- package/src/runtime/hmr.ts +212 -0
- package/src/runtime/index.ts +82 -0
- package/src/runtime/injector.ts +273 -0
- package/src/runtime/react.tsx +269 -0
- package/src/runtime/svelte.ts +15 -0
- package/src/runtime/types.ts +256 -0
- package/src/runtime/utils.ts +128 -0
- package/src/runtime/vite-env.d.ts +120 -0
- package/src/runtime/vue.ts +231 -0
- package/tsconfig.build.json +41 -0
- package/tsconfig.json +25 -0
- package/tsconfig.runtimes.json +18 -0
- package/dist/cli/cli.cjs +0 -7
- package/dist/cli/commands/build.d.ts.map +0 -1
- package/dist/cli/commands/compile.d.ts +0 -3
- package/dist/cli/commands/compile.d.ts.map +0 -1
- package/dist/cli/commands/init.d.ts.map +0 -1
- package/dist/cli/commands/timeline.d.ts.map +0 -1
- package/dist/cli/commands/watch.d.ts.map +0 -1
- package/dist/cli/index.d.ts.map +0 -1
- package/dist/cli/types.d.ts.map +0 -1
- package/dist/cli/utils/config-loader.d.ts.map +0 -1
- package/dist/cli/utils/file-utils.d.ts.map +0 -1
- package/dist/cli/utils/logger.d.ts.map +0 -1
- package/dist/compiler/atomic-optimizer.d.ts.map +0 -1
- package/dist/compiler/btt.d.ts.map +0 -1
- package/dist/compiler/cache-manager.d.ts.map +0 -1
- package/dist/compiler/commonProps.d.ts.map +0 -1
- package/dist/compiler/index.d.ts.map +0 -1
- package/dist/compiler/prefixer.d.ts.map +0 -1
- package/dist/compiler/theme-contract.d.ts.map +0 -1
- package/dist/compiler/tokens.d.ts.map +0 -1
- package/dist/compiler/types.d.ts +0 -57
- package/dist/compiler/types.d.ts.map +0 -1
- package/dist/core/compiler.d.ts.map +0 -1
- package/dist/core/constants.d.ts.map +0 -1
- package/dist/core/index.d.ts +0 -4
- package/dist/core/index.d.ts.map +0 -1
- package/dist/core/types.d.ts.map +0 -1
- package/dist/core/utils.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/plugins/vite.d.ts.map +0 -1
- package/dist/plugins/webpack.d.ts.map +0 -1
- package/dist/runtime/hmr.d.ts.map +0 -1
- package/dist/runtime/index.d.ts.map +0 -1
- package/dist/runtime/injector.d.ts.map +0 -1
- package/dist/runtime/react.d.ts.map +0 -1
- package/dist/runtime/react.js +0 -324
- package/dist/runtime/types.d.ts.map +0 -1
- package/dist/runtime/utils.d.ts.map +0 -1
- package/dist/runtime/vue.d.ts.map +0 -1
- package/dist/runtime/vue.js +0 -286
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
// chaincss/src/core/constants.ts
|
|
2
|
+
/**
|
|
3
|
+
* ChainCSS Constants
|
|
4
|
+
* Shared constants used across the codebase
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { ChainCSSConfig } from './types.js';
|
|
8
|
+
|
|
9
|
+
// Version
|
|
10
|
+
export const VERSION = '2.0.0';
|
|
11
|
+
|
|
12
|
+
// Default CSS properties that should never be atomic
|
|
13
|
+
export const NEVER_ATOMIC_PROPERTIES = [
|
|
14
|
+
'content',
|
|
15
|
+
'animation',
|
|
16
|
+
'animation-name',
|
|
17
|
+
'animation-duration',
|
|
18
|
+
'animation-timing-function',
|
|
19
|
+
'animation-delay',
|
|
20
|
+
'animation-iteration-count',
|
|
21
|
+
'animation-direction',
|
|
22
|
+
'animation-fill-mode',
|
|
23
|
+
'animation-play-state',
|
|
24
|
+
'transition',
|
|
25
|
+
'transition-property',
|
|
26
|
+
'transition-duration',
|
|
27
|
+
'transition-timing-function',
|
|
28
|
+
'transition-delay',
|
|
29
|
+
'keyframes',
|
|
30
|
+
'counter-increment',
|
|
31
|
+
'counter-reset',
|
|
32
|
+
'counter-set',
|
|
33
|
+
'list-style',
|
|
34
|
+
'list-style-type',
|
|
35
|
+
'list-style-position',
|
|
36
|
+
'list-style-image',
|
|
37
|
+
// Critical properties that should never be atomic
|
|
38
|
+
'will-change',
|
|
39
|
+
'backface-visibility',
|
|
40
|
+
'perspective',
|
|
41
|
+
'transform-style',
|
|
42
|
+
'mix-blend-mode',
|
|
43
|
+
'isolation',
|
|
44
|
+
'contain',
|
|
45
|
+
'content-visibility',
|
|
46
|
+
'clip-path',
|
|
47
|
+
'mask',
|
|
48
|
+
'filter',
|
|
49
|
+
'backdrop-filter'
|
|
50
|
+
];
|
|
51
|
+
|
|
52
|
+
// Default CSS properties that should always be atomic (high reuse)
|
|
53
|
+
export const ALWAYS_ATOMIC_PROPERTIES = [
|
|
54
|
+
'display',
|
|
55
|
+
'position',
|
|
56
|
+
'margin',
|
|
57
|
+
'margin-top',
|
|
58
|
+
'margin-right',
|
|
59
|
+
'margin-bottom',
|
|
60
|
+
'margin-left',
|
|
61
|
+
'padding',
|
|
62
|
+
'padding-top',
|
|
63
|
+
'padding-right',
|
|
64
|
+
'padding-bottom',
|
|
65
|
+
'padding-left',
|
|
66
|
+
'color',
|
|
67
|
+
'background-color',
|
|
68
|
+
'background',
|
|
69
|
+
'border',
|
|
70
|
+
'border-radius',
|
|
71
|
+
'width',
|
|
72
|
+
'height',
|
|
73
|
+
'max-width',
|
|
74
|
+
'max-height',
|
|
75
|
+
'min-width',
|
|
76
|
+
'min-height',
|
|
77
|
+
'font-size',
|
|
78
|
+
'font-weight',
|
|
79
|
+
'text-align',
|
|
80
|
+
'cursor',
|
|
81
|
+
'opacity',
|
|
82
|
+
'z-index',
|
|
83
|
+
'overflow',
|
|
84
|
+
'flex',
|
|
85
|
+
'grid',
|
|
86
|
+
'gap'
|
|
87
|
+
];
|
|
88
|
+
|
|
89
|
+
// Default browsers for autoprefixer
|
|
90
|
+
export const DEFAULT_BROWSERS = [
|
|
91
|
+
'> 0.5%',
|
|
92
|
+
'last 2 versions',
|
|
93
|
+
'not dead',
|
|
94
|
+
'Firefox ESR',
|
|
95
|
+
'not ie < 11'
|
|
96
|
+
];
|
|
97
|
+
|
|
98
|
+
// File extensions to process
|
|
99
|
+
export const SUPPORTED_EXTENSIONS = ['.chain.js', '.chain.ts'];
|
|
100
|
+
|
|
101
|
+
// Output file names
|
|
102
|
+
export const DEFAULT_CSS_FILENAME = 'styles.css';
|
|
103
|
+
export const DEFAULT_CLASS_MAP_FILENAME = 'class-map.json';
|
|
104
|
+
export const DEFAULT_TYPES_FILENAME = 'classes.d.ts';
|
|
105
|
+
|
|
106
|
+
// Cache configuration
|
|
107
|
+
export const DEFAULT_CACHE_PATH = './.chaincss-cache';
|
|
108
|
+
export const CACHE_VERSION = '2.0.0';
|
|
109
|
+
|
|
110
|
+
// Atomic optimizer thresholds
|
|
111
|
+
export const DEFAULT_ATOMIC_THRESHOLD = 2;
|
|
112
|
+
export const MIN_ATOMIC_THRESHOLD = 2;
|
|
113
|
+
export const MAX_ATOMIC_THRESHOLD = 10;
|
|
114
|
+
|
|
115
|
+
// Class name naming schemes
|
|
116
|
+
export const NAMING_SCHEMES = ['hash', 'readable'] as const;
|
|
117
|
+
export type NamingScheme = typeof NAMING_SCHEMES[number];
|
|
118
|
+
|
|
119
|
+
// Atomic optimizer modes
|
|
120
|
+
export const ATOMIC_MODES = ['standard', 'atomic', 'hybrid'] as const;
|
|
121
|
+
export type AtomicMode = typeof ATOMIC_MODES[number];
|
|
122
|
+
|
|
123
|
+
// Output strategies
|
|
124
|
+
export const OUTPUT_STRATEGIES = ['component-first', 'utility-first'] as const;
|
|
125
|
+
export type OutputStrategy = typeof OUTPUT_STRATEGIES[number];
|
|
126
|
+
|
|
127
|
+
// Prefixer modes
|
|
128
|
+
export const PREFIXER_MODES = ['auto', 'full', 'lightweight'] as const;
|
|
129
|
+
export type PrefixerMode = typeof PREFIXER_MODES[number];
|
|
130
|
+
|
|
131
|
+
// CLI exit codes
|
|
132
|
+
export const EXIT_CODES = {
|
|
133
|
+
SUCCESS: 0,
|
|
134
|
+
ERROR: 1,
|
|
135
|
+
INVALID_ARGS: 2,
|
|
136
|
+
FILE_NOT_FOUND: 3,
|
|
137
|
+
COMPILE_ERROR: 4
|
|
138
|
+
} as const;
|
|
139
|
+
|
|
140
|
+
// Log levels
|
|
141
|
+
export const LOG_LEVELS = {
|
|
142
|
+
DEBUG: 0,
|
|
143
|
+
INFO: 1,
|
|
144
|
+
SUCCESS: 2,
|
|
145
|
+
WARN: 3,
|
|
146
|
+
ERROR: 4,
|
|
147
|
+
SILENT: 5
|
|
148
|
+
} as const;
|
|
149
|
+
|
|
150
|
+
// Regex patterns
|
|
151
|
+
export const PATTERNS = {
|
|
152
|
+
CSS_PROPERTY: /^[a-z][a-z-]*$/,
|
|
153
|
+
SELECTOR: /^[.#][a-zA-Z][a-zA-Z0-9_-]*$/,
|
|
154
|
+
MEDIA_QUERY: /^@media\s+/,
|
|
155
|
+
KEYFRAMES: /^@keyframes\s+/,
|
|
156
|
+
TOKEN_REFERENCE: /\$([a-zA-Z0-9.-]+)/g,
|
|
157
|
+
HOVER_STATE: /:hover$/,
|
|
158
|
+
PSEUDO_CLASS: /:[a-z-]+(\([^)]+\))?$/,
|
|
159
|
+
CSS_VARIABLE: /^--[a-zA-Z][a-zA-Z0-9-]*$/,
|
|
160
|
+
SHORTHAND_PROPERTY: /^(m|p|b|bg|d|pos|w|h|max-w|max-h|min-w|min-h|rounded|border|flex|grid|gap|inset)$/,
|
|
161
|
+
URL_REFERENCE: /url\(['"]?([^'"()]+)['"]?\)/g,
|
|
162
|
+
IMPORT_STATEMENT: /@import\s+['"]([^'"]+)['"]/g,
|
|
163
|
+
FONT_FACE: /@font-face\s*\{/g,
|
|
164
|
+
STYLE_OBJECT: /(?:chain|\$)\(({[\s\S]*?})\)/g,
|
|
165
|
+
CHAIN_METHOD: /\.([a-zA-Z]+)\(([^)]*)\)/g,
|
|
166
|
+
HEX_COLOR: /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/,
|
|
167
|
+
RGB_COLOR: /^rgb\((\d{1,3},\s*\d{1,3},\s*\d{1,3})\)$/,
|
|
168
|
+
RGBA_COLOR: /^rgba\((\d{1,3},\s*\d{1,3},\s*\d{1,3},\s*(0|1|0?\.\d+))\)$/,
|
|
169
|
+
HSL_COLOR: /^hsl\((\d{1,3},\s*\d{1,3}%,\s*\d{1,3}%)\)$/
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
// Error messages
|
|
173
|
+
export const ERROR_MESSAGES = {
|
|
174
|
+
FILE_NOT_FOUND: (file: string) => `File not found: ${file}`,
|
|
175
|
+
INVALID_CONFIG: (error: string) => `Invalid configuration: ${error}`,
|
|
176
|
+
COMPILE_FAILED: (file: string, error: string) => `Failed to compile ${file}: ${error}`,
|
|
177
|
+
INVALID_SELECTOR: (selector: string) => `Invalid selector: ${selector}`,
|
|
178
|
+
INVALID_PROPERTY: (prop: string) => `Invalid CSS property: ${prop}`,
|
|
179
|
+
NO_INPUT_FILES: 'No input files found matching the patterns',
|
|
180
|
+
WATCH_FAILED: (error: string) => `Failed to start watch mode: ${error}`
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
// Success messages
|
|
184
|
+
export const SUCCESS_MESSAGES = {
|
|
185
|
+
COMPILE_SUCCESS: (count: number, time: number) => `Compiled ${count} file(s) in ${time}ms`,
|
|
186
|
+
INIT_SUCCESS: (configPath: string) => `Initialized ChainCSS config at ${configPath}`,
|
|
187
|
+
WATCH_STARTED: 'Watching for changes... (press Ctrl+C to stop)'
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
// Default responsive breakpoints
|
|
191
|
+
export const DEFAULT_BREAKPOINTS = {
|
|
192
|
+
sm: '(max-width: 640px)',
|
|
193
|
+
md: '(min-width: 641px) and (max-width: 768px)',
|
|
194
|
+
lg: '(min-width: 769px) and (max-width: 1024px)',
|
|
195
|
+
xl: '(min-width: 1025px)',
|
|
196
|
+
'2xl': '(min-width: 1280px)',
|
|
197
|
+
mobile: '(max-width: 768px)',
|
|
198
|
+
tablet: '(min-width: 769px) and (max-width: 1024px)',
|
|
199
|
+
desktop: '(min-width: 1025px)',
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
// Performance optimization constants
|
|
203
|
+
export const PERFORMANCE = {
|
|
204
|
+
MAX_CONCURRENT_COMPILATIONS: 10,
|
|
205
|
+
BATCH_SIZE: 20,
|
|
206
|
+
CACHE_PRUNE_INTERVAL_MS: 3600000, // 1 hour
|
|
207
|
+
CACHE_MAX_ENTRIES: 1000,
|
|
208
|
+
MAX_MEMORY_USAGE_MB: 512,
|
|
209
|
+
GC_THRESHOLD_MB: 400,
|
|
210
|
+
COMPILE_TIMEOUT: 30000,
|
|
211
|
+
FILE_WATCH_TIMEOUT: 5000,
|
|
212
|
+
DEBOUNCE_WRITE_MS: 100,
|
|
213
|
+
THROTTLE_COMPILE_MS: 50
|
|
214
|
+
} as const;
|
|
215
|
+
|
|
216
|
+
// Framework-specific configurations
|
|
217
|
+
export const FRAMEWORK_CONFIGS = {
|
|
218
|
+
react: {
|
|
219
|
+
extension: '.jsx',
|
|
220
|
+
componentTemplate: 'React.FC',
|
|
221
|
+
importReact: true,
|
|
222
|
+
cssInJs: false
|
|
223
|
+
},
|
|
224
|
+
vue: {
|
|
225
|
+
extension: '.vue',
|
|
226
|
+
componentTemplate: 'defineComponent',
|
|
227
|
+
importReact: false,
|
|
228
|
+
cssInJs: true
|
|
229
|
+
},
|
|
230
|
+
svelte: {
|
|
231
|
+
extension: '.svelte',
|
|
232
|
+
componentTemplate: 'script',
|
|
233
|
+
importReact: false,
|
|
234
|
+
cssInJs: true
|
|
235
|
+
},
|
|
236
|
+
solid: {
|
|
237
|
+
extension: '.jsx',
|
|
238
|
+
componentTemplate: 'Component',
|
|
239
|
+
importReact: false,
|
|
240
|
+
cssInJs: false
|
|
241
|
+
},
|
|
242
|
+
angular: {
|
|
243
|
+
extension: '.ts',
|
|
244
|
+
componentTemplate: 'Component',
|
|
245
|
+
importReact: false,
|
|
246
|
+
cssInJs: true
|
|
247
|
+
}
|
|
248
|
+
} as const;
|
|
249
|
+
|
|
250
|
+
export type Framework = keyof typeof FRAMEWORK_CONFIGS;
|
|
251
|
+
|
|
252
|
+
// Environment presets
|
|
253
|
+
export const ENVIRONMENT_PRESETS = {
|
|
254
|
+
development: {
|
|
255
|
+
atomic: {
|
|
256
|
+
naming: 'readable' as NamingScheme,
|
|
257
|
+
minify: false,
|
|
258
|
+
verbose: true,
|
|
259
|
+
cache: true
|
|
260
|
+
},
|
|
261
|
+
output: {
|
|
262
|
+
minify: false,
|
|
263
|
+
sourceComments: true
|
|
264
|
+
},
|
|
265
|
+
debug: true,
|
|
266
|
+
timeline: true,
|
|
267
|
+
sourceComments: true,
|
|
268
|
+
verbose: true
|
|
269
|
+
},
|
|
270
|
+
production: {
|
|
271
|
+
atomic: {
|
|
272
|
+
naming: 'hash' as NamingScheme,
|
|
273
|
+
minify: true,
|
|
274
|
+
verbose: false,
|
|
275
|
+
cache: true
|
|
276
|
+
},
|
|
277
|
+
output: {
|
|
278
|
+
minify: true,
|
|
279
|
+
sourceComments: false
|
|
280
|
+
},
|
|
281
|
+
debug: false,
|
|
282
|
+
timeline: false,
|
|
283
|
+
sourceComments: false,
|
|
284
|
+
verbose: false
|
|
285
|
+
},
|
|
286
|
+
test: {
|
|
287
|
+
atomic: {
|
|
288
|
+
naming: 'readable' as NamingScheme,
|
|
289
|
+
minify: false,
|
|
290
|
+
verbose: false,
|
|
291
|
+
cache: false
|
|
292
|
+
},
|
|
293
|
+
output: {
|
|
294
|
+
minify: false,
|
|
295
|
+
sourceComments: true
|
|
296
|
+
},
|
|
297
|
+
debug: true,
|
|
298
|
+
timeline: true,
|
|
299
|
+
sourceComments: true,
|
|
300
|
+
verbose: false
|
|
301
|
+
}
|
|
302
|
+
} as const;
|
|
303
|
+
|
|
304
|
+
// Validation rules
|
|
305
|
+
export const VALIDATION = {
|
|
306
|
+
MAX_SELECTOR_LENGTH: 100,
|
|
307
|
+
MAX_STYLE_RULES: 10000,
|
|
308
|
+
MAX_NESTING_DEPTH: 10,
|
|
309
|
+
CLASS_NAME: {
|
|
310
|
+
MIN_LENGTH: 1,
|
|
311
|
+
MAX_LENGTH: 50,
|
|
312
|
+
PATTERN: /^[a-zA-Z][a-zA-Z0-9_-]*$/,
|
|
313
|
+
RESERVED: ['chain', 'css', 'style', 'global', 'atomic']
|
|
314
|
+
},
|
|
315
|
+
PROPERTY_VALUE: {
|
|
316
|
+
MAX_LENGTH: 5000,
|
|
317
|
+
ALLOWED_UNITS: ['px', 'rem', 'em', '%', 'vw', 'vh', 'deg', 'rad', 'ms', 's']
|
|
318
|
+
},
|
|
319
|
+
BREAKPOINT: {
|
|
320
|
+
MIN_VALUE: 0,
|
|
321
|
+
MAX_VALUE: 10000,
|
|
322
|
+
ALLOWED_UNITS: ['px', 'rem', 'em', 'vw']
|
|
323
|
+
}
|
|
324
|
+
} as const;
|
|
325
|
+
|
|
326
|
+
// Memory management
|
|
327
|
+
export const MEMORY = {
|
|
328
|
+
CACHE_PRUNE_SIZE: 100 * 1024 * 1024, // 100MB
|
|
329
|
+
MAX_STRING_BUFFER: 10 * 1024 * 1024, // 10MB
|
|
330
|
+
BATCH_SIZE: 100,
|
|
331
|
+
CLEANUP_INTERVAL_MS: 300000, // 5 minutes
|
|
332
|
+
CACHE_CHECK_INTERVAL_MS: 60000, // 1 minute
|
|
333
|
+
MEMORY_CHECK_INTERVAL_MS: 30000 // 30 seconds
|
|
334
|
+
} as const;
|
|
335
|
+
|
|
336
|
+
// Default config values
|
|
337
|
+
export const DEFAULT_CONFIG: ChainCSSConfig = {
|
|
338
|
+
inputs: ['src/**/*.chain.{js,ts}', 'src/**/*.tsx'],
|
|
339
|
+
tokens: {
|
|
340
|
+
enabled: true,
|
|
341
|
+
prefix: 'chain'
|
|
342
|
+
},
|
|
343
|
+
atomic: {
|
|
344
|
+
enabled: true,
|
|
345
|
+
threshold: 2,
|
|
346
|
+
naming: (process.env.NODE_ENV === 'production' ? 'hash' : 'readable') as NamingScheme,
|
|
347
|
+
cache: true,
|
|
348
|
+
cachePath: DEFAULT_CACHE_PATH,
|
|
349
|
+
minify: true,
|
|
350
|
+
mode: 'hybrid' as AtomicMode,
|
|
351
|
+
outputStrategy: 'component-first' as OutputStrategy,
|
|
352
|
+
alwaysAtomic: ALWAYS_ATOMIC_PROPERTIES,
|
|
353
|
+
neverAtomic: NEVER_ATOMIC_PROPERTIES,
|
|
354
|
+
verbose: false
|
|
355
|
+
},
|
|
356
|
+
prefixer: {
|
|
357
|
+
enabled: true,
|
|
358
|
+
mode: 'auto' as PrefixerMode,
|
|
359
|
+
browsers: DEFAULT_BROWSERS,
|
|
360
|
+
sourceMap: true,
|
|
361
|
+
sourceMapInline: false
|
|
362
|
+
},
|
|
363
|
+
output: {
|
|
364
|
+
cssFile: DEFAULT_CSS_FILENAME,
|
|
365
|
+
classMapFile: DEFAULT_CLASS_MAP_FILENAME,
|
|
366
|
+
typesFile: DEFAULT_TYPES_FILENAME,
|
|
367
|
+
minify: true,
|
|
368
|
+
generateGlobalCSS: true
|
|
369
|
+
},
|
|
370
|
+
cachePath: DEFAULT_CACHE_PATH,
|
|
371
|
+
cacheEnabled: true,
|
|
372
|
+
persistentCachePath: './.chaincss/persistent-cache',
|
|
373
|
+
cacheMaxAgeDays: 30,
|
|
374
|
+
cacheMaxSizeMB: 500,
|
|
375
|
+
debug: false,
|
|
376
|
+
sourceComments: true,
|
|
377
|
+
timeline: false,
|
|
378
|
+
framework: 'auto',
|
|
379
|
+
namespace: 'chain',
|
|
380
|
+
verbose: false
|
|
381
|
+
};
|
|
382
|
+
|
|
383
|
+
// Runtime constants
|
|
384
|
+
export const RUNTIME = {
|
|
385
|
+
STYLE_ID_PREFIX: 'chaincss-runtime',
|
|
386
|
+
CLASS_NAME_PREFIX: 'c',
|
|
387
|
+
HASH_LENGTH: 6,
|
|
388
|
+
MAX_CACHE_SIZE: 100,
|
|
389
|
+
INJECTION_DELAY: 16 // ~1 frame at 60fps
|
|
390
|
+
};
|
|
391
|
+
|
|
392
|
+
// Development-only constants
|
|
393
|
+
export const DEV = {
|
|
394
|
+
HOT_RELOAD_PORT: 3000,
|
|
395
|
+
DEBOUNCE_DELAY: 100,
|
|
396
|
+
LOG_PREFIX: '[ChainCSS]'
|
|
397
|
+
};
|
|
398
|
+
|
|
399
|
+
// Production constants
|
|
400
|
+
export const PROD = {
|
|
401
|
+
COMPRESSION_LEVEL: 6,
|
|
402
|
+
SOURCE_MAP_COMMENT: '/*# sourceMappingURL=styles.css.map */'
|
|
403
|
+
};
|
|
404
|
+
|
|
405
|
+
// Type guard functions
|
|
406
|
+
export function isNamingScheme(value: unknown): value is NamingScheme {
|
|
407
|
+
return typeof value === 'string' && NAMING_SCHEMES.includes(value as any);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
export function isAtomicMode(value: unknown): value is AtomicMode {
|
|
411
|
+
return typeof value === 'string' && ATOMIC_MODES.includes(value as any);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
export function isOutputStrategy(value: unknown): value is OutputStrategy {
|
|
415
|
+
return typeof value === 'string' && OUTPUT_STRATEGIES.includes(value as any);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
export function isPrefixerMode(value: unknown): value is PrefixerMode {
|
|
419
|
+
return typeof value === 'string' && PREFIXER_MODES.includes(value as any);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
export function isFramework(value: unknown): value is Framework {
|
|
423
|
+
return typeof value === 'string' && value in FRAMEWORK_CONFIGS;
|
|
424
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// src/core/index.ts
|
|
2
|
+
|
|
3
|
+
// Core compiler
|
|
4
|
+
export { ChainCSSCompiler, compileChainCSS } from './compiler.js';
|
|
5
|
+
|
|
6
|
+
// Types
|
|
7
|
+
export type {
|
|
8
|
+
ChainCSSConfig,
|
|
9
|
+
CompileResult,
|
|
10
|
+
StyleDefinition,
|
|
11
|
+
AtomicClass,
|
|
12
|
+
AtRule,
|
|
13
|
+
NestedRule,
|
|
14
|
+
ThemeBlock,
|
|
15
|
+
ChainCSSPlugin
|
|
16
|
+
} from './types.js';
|
|
17
|
+
|
|
18
|
+
// Constants
|
|
19
|
+
export {
|
|
20
|
+
VERSION,
|
|
21
|
+
DEFAULT_CONFIG,
|
|
22
|
+
DEFAULT_BREAKPOINTS,
|
|
23
|
+
NEVER_ATOMIC_PROPERTIES,
|
|
24
|
+
ALWAYS_ATOMIC_PROPERTIES,
|
|
25
|
+
NAMING_SCHEMES,
|
|
26
|
+
ATOMIC_MODES,
|
|
27
|
+
OUTPUT_STRATEGIES,
|
|
28
|
+
PREFIXER_MODES,
|
|
29
|
+
EXIT_CODES,
|
|
30
|
+
LOG_LEVELS,
|
|
31
|
+
PERFORMANCE,
|
|
32
|
+
MEMORY,
|
|
33
|
+
VALIDATION
|
|
34
|
+
} from './constants.js';
|
|
35
|
+
|
|
36
|
+
// Utilities (all of them)
|
|
37
|
+
export {
|
|
38
|
+
// Hashing & naming
|
|
39
|
+
hashString,
|
|
40
|
+
generateClassName,
|
|
41
|
+
generateAtomicClassName,
|
|
42
|
+
generateComponentClassName,
|
|
43
|
+
|
|
44
|
+
// String conversion
|
|
45
|
+
kebabCase,
|
|
46
|
+
camelCase,
|
|
47
|
+
pascalCase,
|
|
48
|
+
snakeCase,
|
|
49
|
+
|
|
50
|
+
// Formatting
|
|
51
|
+
formatCSS,
|
|
52
|
+
formatJS,
|
|
53
|
+
truncate,
|
|
54
|
+
indent,
|
|
55
|
+
stripIndent,
|
|
56
|
+
|
|
57
|
+
// Object manipulation
|
|
58
|
+
deepMerge,
|
|
59
|
+
deepClone,
|
|
60
|
+
deepEqual,
|
|
61
|
+
pick,
|
|
62
|
+
omit,
|
|
63
|
+
|
|
64
|
+
// Arrays
|
|
65
|
+
unique,
|
|
66
|
+
chunk,
|
|
67
|
+
groupBy,
|
|
68
|
+
|
|
69
|
+
// Performance
|
|
70
|
+
debounce,
|
|
71
|
+
throttle,
|
|
72
|
+
|
|
73
|
+
// Error handling
|
|
74
|
+
ChainCSSError,
|
|
75
|
+
tryOrWarn,
|
|
76
|
+
tryOrThrow,
|
|
77
|
+
|
|
78
|
+
// Logging
|
|
79
|
+
setLogLevel,
|
|
80
|
+
logDebug,
|
|
81
|
+
logInfo,
|
|
82
|
+
logWarn,
|
|
83
|
+
logError,
|
|
84
|
+
|
|
85
|
+
// Memory
|
|
86
|
+
getMemoryUsage,
|
|
87
|
+
formatBytes,
|
|
88
|
+
|
|
89
|
+
// Validation
|
|
90
|
+
isValidSelector,
|
|
91
|
+
isValidClassName,
|
|
92
|
+
isValidCSSProperty
|
|
93
|
+
} from './utils.js';
|
|
94
|
+
|
|
95
|
+
// Common utilities (shared with runtime)
|
|
96
|
+
export {
|
|
97
|
+
processStyleObject,
|
|
98
|
+
extractCSS,
|
|
99
|
+
extractHoverCSS,
|
|
100
|
+
mergeStyles,
|
|
101
|
+
isValidCSSLength,
|
|
102
|
+
isValidCSSColor,
|
|
103
|
+
escapeSelector,
|
|
104
|
+
cleanClassName,
|
|
105
|
+
sortClassNames
|
|
106
|
+
} from './common-utils.js';
|
|
107
|
+
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
// src/core/smart-chain.ts
|
|
2
|
+
|
|
3
|
+
import { chain as buildChainFunction } from '../compiler/Chain.js';
|
|
4
|
+
import { RuntimeChain } from '../runtime/Chain.js';
|
|
5
|
+
import { autoDetector, type AnalysisResult } from './auto-detector.js';
|
|
6
|
+
|
|
7
|
+
interface SmartCall {
|
|
8
|
+
prop: string;
|
|
9
|
+
value: any;
|
|
10
|
+
args: any[];
|
|
11
|
+
index: number;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
class SmartChainProxy {
|
|
15
|
+
private calls: SmartCall[] = [];
|
|
16
|
+
private callIndex = 0;
|
|
17
|
+
private useTokens: boolean;
|
|
18
|
+
private readonly MAX_CALLS = 500; // Safety cap
|
|
19
|
+
|
|
20
|
+
constructor(useTokens: boolean = true) {
|
|
21
|
+
this.useTokens = useTokens;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
private recordCall(prop: string, ...args: any[]): this {
|
|
25
|
+
// Safety: prevent unbounded growth
|
|
26
|
+
if (this.calls.length >= this.MAX_CALLS) {
|
|
27
|
+
console.warn('⚠️ ChainCSS: Smart chain call limit reached. Consider using build chain for static styles.');
|
|
28
|
+
return this;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
this.calls.push({
|
|
32
|
+
prop,
|
|
33
|
+
value: args[0],
|
|
34
|
+
args,
|
|
35
|
+
index: this.callIndex++
|
|
36
|
+
});
|
|
37
|
+
return this;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
private processHybrid(analysis: AnalysisResult, selectors: string[]): any {
|
|
41
|
+
const buildInstance = buildChainFunction(this.useTokens);
|
|
42
|
+
const runtimeInstance = new RuntimeChain(this.useTokens).proxy;
|
|
43
|
+
|
|
44
|
+
// Apply static parts to build mode
|
|
45
|
+
for (const part of analysis.staticParts) {
|
|
46
|
+
const call = this.calls[part.index];
|
|
47
|
+
if (call && (buildInstance as any)[call.prop]) {
|
|
48
|
+
(buildInstance as any)[call.prop](...call.args);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Apply dynamic and runtime-only parts to runtime mode
|
|
53
|
+
const allDynamic = [...analysis.dynamicParts, ...analysis.runtimeOnlyParts];
|
|
54
|
+
for (const part of allDynamic) {
|
|
55
|
+
const call = this.calls[part.index];
|
|
56
|
+
if (call && (runtimeInstance as any)[call.prop]) {
|
|
57
|
+
(runtimeInstance as any)[call.prop](...call.args);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const buildResult = buildInstance.$el(...selectors);
|
|
62
|
+
const runtimeResult = runtimeInstance.$el(...selectors);
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
...(typeof buildResult === 'object' ? buildResult : {}),
|
|
66
|
+
...(typeof runtimeResult === 'object' ? runtimeResult : {}),
|
|
67
|
+
__buildClasses: buildResult,
|
|
68
|
+
__runtimeClasses: runtimeResult,
|
|
69
|
+
__isHybrid: true
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
private processPureBuild(selectors: string[]): any {
|
|
74
|
+
const buildInstance = buildChainFunction(this.useTokens);
|
|
75
|
+
|
|
76
|
+
for (const call of this.calls) {
|
|
77
|
+
if ((buildInstance as any)[call.prop]) {
|
|
78
|
+
(buildInstance as any)[call.prop](...call.args);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return buildInstance.$el(...selectors);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
private processPureRuntime(selectors: string[]): any {
|
|
86
|
+
const runtimeInstance = new RuntimeChain(this.useTokens).proxy;
|
|
87
|
+
|
|
88
|
+
for (const call of this.calls) {
|
|
89
|
+
if ((runtimeInstance as any)[call.prop]) {
|
|
90
|
+
(runtimeInstance as any)[call.prop](...call.args);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return runtimeInstance.$el(...selectors);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
$el(...selectors: string[]): any {
|
|
98
|
+
if (this.calls.length === 0) {
|
|
99
|
+
return {};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const callsWithIndex = this.calls.map((call, idx) => ({
|
|
103
|
+
prop: call.prop,
|
|
104
|
+
value: call.value,
|
|
105
|
+
index: idx
|
|
106
|
+
}));
|
|
107
|
+
|
|
108
|
+
const analysis = autoDetector.analyzeChain(callsWithIndex);
|
|
109
|
+
|
|
110
|
+
// Safety check: prevent recursion if a smart chain is passed to another smart chain
|
|
111
|
+
if (this.calls[0]?.prop === '__isSmartChain') {
|
|
112
|
+
return this.processPureRuntime(selectors);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
let result: any;
|
|
116
|
+
switch (analysis.mode) {
|
|
117
|
+
case 'hybrid':
|
|
118
|
+
result = this.processHybrid(analysis, selectors);
|
|
119
|
+
break;
|
|
120
|
+
case 'runtime':
|
|
121
|
+
result = this.processPureRuntime(selectors);
|
|
122
|
+
break;
|
|
123
|
+
case 'build':
|
|
124
|
+
default:
|
|
125
|
+
result = this.processPureBuild(selectors);
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Clear calls after finalizing to free memory
|
|
130
|
+
this.calls = [];
|
|
131
|
+
this.callIndex = 0;
|
|
132
|
+
|
|
133
|
+
return result;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
getProxy(): any {
|
|
137
|
+
const proxy = new Proxy(this, {
|
|
138
|
+
get(target, prop: string) {
|
|
139
|
+
// Special markers for detection
|
|
140
|
+
if (prop === '__isSmartChain') return true;
|
|
141
|
+
if (prop === '$el') return target.$el.bind(target);
|
|
142
|
+
if (prop === 'then') return undefined; // Prevent Promise resolution issues
|
|
143
|
+
|
|
144
|
+
// For any other property, record the call and return the proxy
|
|
145
|
+
return (...args: any[]) => {
|
|
146
|
+
target.recordCall(prop, ...args);
|
|
147
|
+
return proxy;
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
return proxy;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export function smartChain(useTokens: boolean = true): any {
|
|
157
|
+
const proxy = new SmartChainProxy(useTokens);
|
|
158
|
+
return proxy.getProxy();
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Legacy support functions
|
|
162
|
+
export const buildChain = (useTokens?: boolean) => buildChainFunction(useTokens);
|
|
163
|
+
export const runtimeChain = (useTokens?: boolean) => new RuntimeChain(useTokens || true).proxy;
|