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.
Files changed (159) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/CODE_OF_CONDUCT.md +21 -0
  3. package/CONTRIBUTING.md +28 -0
  4. package/README.md +455 -226
  5. package/demo/demo/node_modules/caniuse-db/fulldata-json/data-2.0.json +1 -0
  6. package/demo/index.html +16 -0
  7. package/demo/package.json +20 -0
  8. package/demo/src/App.tsx +117 -0
  9. package/demo/src/chaincss-barrel.ts +9 -0
  10. package/demo/src/main.tsx +8 -0
  11. package/demo/src/styles.chain.ts +300 -0
  12. package/demo/vite.config.ts +46 -0
  13. package/dist/cli/commands/build.d.ts +0 -1
  14. package/dist/cli/commands/cache.d.ts +1 -0
  15. package/dist/cli/commands/init.d.ts +6 -3
  16. package/dist/cli/commands/timeline.d.ts +0 -1
  17. package/dist/cli/commands/watch.d.ts +0 -1
  18. package/dist/cli/index.d.ts +0 -1
  19. package/dist/cli/index.js +3213 -5296
  20. package/dist/cli/types.d.ts +51 -20
  21. package/dist/cli/utils/config-loader.d.ts +0 -1
  22. package/dist/cli/utils/file-utils.d.ts +27 -3
  23. package/dist/cli/utils/logger.d.ts +0 -1
  24. package/dist/compiler/Chain.d.ts +215 -0
  25. package/dist/compiler/animations.d.ts +76 -0
  26. package/dist/compiler/atomic-optimizer.d.ts +47 -12
  27. package/dist/compiler/breakpoints.d.ts +46 -0
  28. package/dist/compiler/btt.d.ts +36 -60
  29. package/dist/compiler/cache-manager.d.ts +58 -4
  30. package/dist/compiler/commonProps.d.ts +0 -1
  31. package/dist/compiler/content-addressable-cache.d.ts +78 -0
  32. package/dist/compiler/helpers.d.ts +54 -0
  33. package/dist/compiler/index.d.ts +16 -9
  34. package/dist/compiler/index.js +4450 -4316
  35. package/dist/compiler/prefixer.d.ts +17 -1
  36. package/dist/compiler/shorthands.d.ts +28 -0
  37. package/dist/compiler/suggestions.d.ts +43 -0
  38. package/dist/compiler/theme-contract.d.ts +16 -27
  39. package/dist/compiler/token-resolver.d.ts +69 -0
  40. package/dist/compiler/tokens.d.ts +33 -8
  41. package/dist/core/auto-detector.d.ts +34 -0
  42. package/dist/core/common-utils.d.ts +97 -0
  43. package/dist/core/compiler.d.ts +63 -23
  44. package/dist/core/constants.d.ts +137 -36
  45. package/dist/core/smart-chain.d.ts +3 -0
  46. package/dist/core/types.d.ts +122 -15
  47. package/dist/core/utils.d.ts +134 -17
  48. package/dist/index.d.ts +52 -8
  49. package/dist/index.js +7090 -5578
  50. package/dist/plugins/vite.d.ts +7 -5
  51. package/dist/plugins/vite.js +2964 -25641
  52. package/dist/plugins/webpack.d.ts +24 -1
  53. package/dist/plugins/webpack.js +209 -72
  54. package/dist/runtime/Chain.d.ts +32 -0
  55. package/dist/runtime/auto-hooks.d.ts +11 -0
  56. package/dist/runtime/hmr.d.ts +22 -2
  57. package/dist/runtime/index.d.ts +3 -2
  58. package/dist/runtime/index.js +3648 -301
  59. package/dist/runtime/injector.d.ts +39 -72
  60. package/dist/runtime/react.d.ts +17 -12
  61. package/dist/runtime/svelte.d.ts +15 -0
  62. package/dist/runtime/types.d.ts +126 -4
  63. package/dist/runtime/utils.d.ts +0 -1
  64. package/dist/runtime/vue.d.ts +34 -14
  65. package/package.json +59 -66
  66. package/src/cli/commands/build.ts +133 -0
  67. package/src/cli/commands/cache.ts +371 -0
  68. package/src/cli/commands/init.ts +230 -0
  69. package/src/cli/commands/timeline.ts +435 -0
  70. package/src/cli/commands/watch.ts +211 -0
  71. package/src/cli/index.ts +226 -0
  72. package/src/cli/types.ts +100 -0
  73. package/src/cli/utils/config-loader.ts +174 -0
  74. package/src/cli/utils/file-utils.ts +139 -0
  75. package/src/cli/utils/logger.ts +74 -0
  76. package/src/compiler/Chain.ts +831 -0
  77. package/src/compiler/animations.ts +517 -0
  78. package/src/compiler/atomic-optimizer.ts +786 -0
  79. package/src/compiler/breakpoints.ts +347 -0
  80. package/src/compiler/btt.ts +1147 -0
  81. package/src/compiler/cache-manager.ts +446 -0
  82. package/src/compiler/commonProps.ts +18 -0
  83. package/src/compiler/content-addressable-cache.ts +478 -0
  84. package/src/compiler/helpers.ts +407 -0
  85. package/src/compiler/index.ts +72 -0
  86. package/src/compiler/prefixer.ts +724 -0
  87. package/src/compiler/shorthands.ts +558 -0
  88. package/src/compiler/suggestions.ts +436 -0
  89. package/src/compiler/theme-contract.ts +197 -0
  90. package/src/compiler/token-resolver.ts +241 -0
  91. package/src/compiler/tokens.ts +612 -0
  92. package/src/core/auto-detector.ts +187 -0
  93. package/src/core/common-utils.ts +423 -0
  94. package/src/core/compiler.ts +835 -0
  95. package/src/core/constants.ts +424 -0
  96. package/src/core/index.ts +107 -0
  97. package/src/core/smart-chain.ts +163 -0
  98. package/src/core/types.ts +257 -0
  99. package/src/core/utils.ts +598 -0
  100. package/src/index.ts +208 -0
  101. package/src/plugins/vite.d.ts +316 -0
  102. package/src/plugins/vite.ts +424 -0
  103. package/src/plugins/webpack.d.ts +289 -0
  104. package/src/plugins/webpack.ts +416 -0
  105. package/src/runtime/Chain.ts +242 -0
  106. package/src/runtime/auto-hooks.tsx +127 -0
  107. package/src/runtime/auto-vue.ts +72 -0
  108. package/src/runtime/hmr.ts +212 -0
  109. package/src/runtime/index.ts +82 -0
  110. package/src/runtime/injector.ts +273 -0
  111. package/src/runtime/react.tsx +269 -0
  112. package/src/runtime/svelte.ts +15 -0
  113. package/src/runtime/types.ts +256 -0
  114. package/src/runtime/utils.ts +128 -0
  115. package/src/runtime/vite-env.d.ts +120 -0
  116. package/src/runtime/vue.ts +231 -0
  117. package/tsconfig.build.json +41 -0
  118. package/tsconfig.json +25 -0
  119. package/tsconfig.runtimes.json +18 -0
  120. package/dist/cli/cli.cjs +0 -7
  121. package/dist/cli/commands/build.d.ts.map +0 -1
  122. package/dist/cli/commands/compile.d.ts +0 -3
  123. package/dist/cli/commands/compile.d.ts.map +0 -1
  124. package/dist/cli/commands/init.d.ts.map +0 -1
  125. package/dist/cli/commands/timeline.d.ts.map +0 -1
  126. package/dist/cli/commands/watch.d.ts.map +0 -1
  127. package/dist/cli/index.d.ts.map +0 -1
  128. package/dist/cli/types.d.ts.map +0 -1
  129. package/dist/cli/utils/config-loader.d.ts.map +0 -1
  130. package/dist/cli/utils/file-utils.d.ts.map +0 -1
  131. package/dist/cli/utils/logger.d.ts.map +0 -1
  132. package/dist/compiler/atomic-optimizer.d.ts.map +0 -1
  133. package/dist/compiler/btt.d.ts.map +0 -1
  134. package/dist/compiler/cache-manager.d.ts.map +0 -1
  135. package/dist/compiler/commonProps.d.ts.map +0 -1
  136. package/dist/compiler/index.d.ts.map +0 -1
  137. package/dist/compiler/prefixer.d.ts.map +0 -1
  138. package/dist/compiler/theme-contract.d.ts.map +0 -1
  139. package/dist/compiler/tokens.d.ts.map +0 -1
  140. package/dist/compiler/types.d.ts +0 -57
  141. package/dist/compiler/types.d.ts.map +0 -1
  142. package/dist/core/compiler.d.ts.map +0 -1
  143. package/dist/core/constants.d.ts.map +0 -1
  144. package/dist/core/index.d.ts +0 -4
  145. package/dist/core/index.d.ts.map +0 -1
  146. package/dist/core/types.d.ts.map +0 -1
  147. package/dist/core/utils.d.ts.map +0 -1
  148. package/dist/index.d.ts.map +0 -1
  149. package/dist/plugins/vite.d.ts.map +0 -1
  150. package/dist/plugins/webpack.d.ts.map +0 -1
  151. package/dist/runtime/hmr.d.ts.map +0 -1
  152. package/dist/runtime/index.d.ts.map +0 -1
  153. package/dist/runtime/injector.d.ts.map +0 -1
  154. package/dist/runtime/react.d.ts.map +0 -1
  155. package/dist/runtime/react.js +0 -324
  156. package/dist/runtime/types.d.ts.map +0 -1
  157. package/dist/runtime/utils.d.ts.map +0 -1
  158. package/dist/runtime/vue.d.ts.map +0 -1
  159. package/dist/runtime/vue.js +0 -286
@@ -0,0 +1,446 @@
1
+ // chaincss/src/compiler/cache-manager.ts
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+ import crypto from 'crypto';
5
+
6
+ export interface CacheData {
7
+ version: string;
8
+ created: string;
9
+ updated: string;
10
+ atomic: Record<string, any>;
11
+ usage: Record<string, any>;
12
+ componentMap: Record<string, any>;
13
+ stats: {
14
+ totalStyles: number;
15
+ atomicStyles: number;
16
+ cacheHits: number;
17
+ cacheMisses: number;
18
+ };
19
+ [key: string]: any;
20
+ }
21
+
22
+ export interface CacheOptions {
23
+ maxAge?: number; // Maximum age in milliseconds
24
+ maxSize?: number; // Maximum cache size in bytes
25
+ compress?: boolean; // Compress cache data
26
+ autoSave?: boolean; // Auto-save on changes
27
+ saveInterval?: number; // Auto-save interval in ms
28
+ }
29
+
30
+ export class CacheManager {
31
+ cachePath: string;
32
+ cacheDir: string;
33
+ cache: CacheData | Record<string, any>;
34
+ private dirty: boolean = false;
35
+ private saveTimer: NodeJS.Timeout | null = null;
36
+ private stats = {
37
+ hits: 0,
38
+ misses: 0,
39
+ writes: 0,
40
+ reads: 0
41
+ };
42
+ private options: Required<CacheOptions>;
43
+
44
+ constructor(cachePath: string = './.chaincss-cache', options: CacheOptions = {}) {
45
+ this.options = {
46
+ maxAge: options.maxAge || 7 * 24 * 60 * 60 * 1000, // 7 days default
47
+ maxSize: options.maxSize || 100 * 1024 * 1024, // 100MB default
48
+ compress: options.compress || false,
49
+ autoSave: options.autoSave !== false,
50
+ saveInterval: options.saveInterval || 5000 // 5 seconds
51
+ };
52
+
53
+ this.cachePath = path.resolve(process.cwd(), cachePath);
54
+ this.cacheDir = path.dirname(this.cachePath);
55
+ this.cache = {};
56
+ this.load();
57
+
58
+ // Setup auto-save if enabled
59
+ if (this.options.autoSave) {
60
+ this.startAutoSave();
61
+ }
62
+ }
63
+
64
+ private startAutoSave(): void {
65
+ if (this.saveTimer) clearInterval(this.saveTimer);
66
+ this.saveTimer = setInterval(() => {
67
+ if (this.dirty) {
68
+ this.save();
69
+ }
70
+ }, this.options.saveInterval);
71
+
72
+ // Ensure timer doesn't keep process alive
73
+ if (this.saveTimer.unref) {
74
+ this.saveTimer.unref();
75
+ }
76
+ }
77
+
78
+ private stopAutoSave(): void {
79
+ if (this.saveTimer) {
80
+ clearInterval(this.saveTimer);
81
+ this.saveTimer = null;
82
+ }
83
+ }
84
+
85
+ load(): void {
86
+ try {
87
+ if (fs.existsSync(this.cachePath)) {
88
+ let data = fs.readFileSync(this.cachePath, 'utf8');
89
+
90
+ // Decompress if needed
91
+ if (this.options.compress && this.isCompressed(data)) {
92
+ data = this.decompress(data);
93
+ }
94
+
95
+ this.cache = JSON.parse(data);
96
+
97
+ // Check if cache is expired
98
+ if (this.isExpired()) {
99
+ console.log('Cache expired, clearing...');
100
+ this.clear();
101
+ this.cache = this.getDefaultCache();
102
+ }
103
+
104
+ // Check cache size
105
+ this.checkAndPrune();
106
+ } else {
107
+ // Ensure cache directory exists
108
+ if (!fs.existsSync(this.cacheDir)) {
109
+ fs.mkdirSync(this.cacheDir, { recursive: true });
110
+ }
111
+ this.cache = this.getDefaultCache();
112
+ }
113
+ } catch (error) {
114
+ console.warn('Could not load cache, starting fresh:', (error as Error).message);
115
+ this.cache = this.getDefaultCache();
116
+ }
117
+ }
118
+
119
+ private getDefaultCache(): CacheData {
120
+ return {
121
+ version: '2.0.0',
122
+ created: new Date().toISOString(),
123
+ updated: new Date().toISOString(),
124
+ atomic: {},
125
+ usage: {},
126
+ componentMap: {},
127
+ stats: {
128
+ totalStyles: 0,
129
+ atomicStyles: 0,
130
+ cacheHits: 0,
131
+ cacheMisses: 0
132
+ }
133
+ };
134
+ }
135
+
136
+ private isExpired(): boolean {
137
+ const created = this.cache.created ? new Date(this.cache.created).getTime() : 0;
138
+ const now = Date.now();
139
+ return (now - created) > this.options.maxAge;
140
+ }
141
+
142
+ private checkAndPrune(): void {
143
+ try {
144
+ const stats = fs.statSync(this.cachePath);
145
+ if (stats.size > this.options.maxSize) {
146
+ console.log(`Cache size (${stats.size} bytes) exceeds limit (${this.options.maxSize} bytes), pruning...`);
147
+ this.prune();
148
+ }
149
+ } catch (error) {
150
+ // File might not exist yet
151
+ }
152
+ }
153
+
154
+ private isCompressed(data: string): boolean {
155
+ // Check if data looks like compressed (base64 encoded)
156
+ return data.startsWith('COMPRESSED:');
157
+ }
158
+
159
+ private compress(data: string): string {
160
+ // Simple compression - could be enhanced with zlib
161
+ const compressed = Buffer.from(data).toString('base64');
162
+ return `COMPRESSED:${compressed}`;
163
+ }
164
+
165
+ private decompress(data: string): string {
166
+ if (data.startsWith('COMPRESSED:')) {
167
+ const compressed = data.substring(11);
168
+ return Buffer.from(compressed, 'base64').toString();
169
+ }
170
+ return data;
171
+ }
172
+
173
+ get(key: string): any {
174
+ this.stats.reads++;
175
+
176
+ if (this.cache[key] !== undefined) {
177
+ // Check if this specific entry has expired
178
+ if (this.cache[key].expires && this.cache[key].expires < Date.now()) {
179
+ delete this.cache[key];
180
+ this.stats.misses++;
181
+ this.dirty = true;
182
+ return undefined;
183
+ }
184
+
185
+ this.stats.hits++;
186
+ if (this.cache.stats) {
187
+ this.cache.stats.cacheHits++;
188
+ }
189
+ return this.cache[key];
190
+ }
191
+
192
+ this.stats.misses++;
193
+ if (this.cache.stats) {
194
+ this.cache.stats.cacheMisses++;
195
+ }
196
+ return undefined;
197
+ }
198
+
199
+ set(key: string, value: any, ttl?: number): void {
200
+ const entry = {
201
+ ...value,
202
+ cachedAt: Date.now(),
203
+ expires: ttl ? Date.now() + ttl : undefined
204
+ };
205
+
206
+ this.cache[key] = entry;
207
+ this.dirty = true;
208
+ this.stats.writes++;
209
+
210
+ if (this.cache.stats && key !== 'stats') {
211
+ // Update stats if this is atomic or component data
212
+ if (key === 'atomic') {
213
+ this.cache.stats.atomicStyles = Object.keys(value).length;
214
+ }
215
+ }
216
+ }
217
+
218
+ has(key: string): boolean {
219
+ const value = this.get(key);
220
+ return value !== undefined;
221
+ }
222
+
223
+ delete(key: string): boolean {
224
+ if (this.cache[key] !== undefined) {
225
+ delete this.cache[key];
226
+ this.dirty = true;
227
+ return true;
228
+ }
229
+ return false;
230
+ }
231
+
232
+ clear(): void {
233
+ this.cache = this.getDefaultCache();
234
+ this.dirty = true;
235
+ this.stats = { hits: 0, misses: 0, writes: 0, reads: 0 };
236
+
237
+ if (fs.existsSync(this.cachePath)) {
238
+ try {
239
+ fs.unlinkSync(this.cachePath);
240
+ } catch (error) {
241
+ console.warn('Could not delete cache file:', (error as Error).message);
242
+ }
243
+ }
244
+
245
+ console.log('Cache cleared');
246
+ }
247
+
248
+ prune(): void {
249
+ const now = Date.now();
250
+ let prunedCount = 0;
251
+
252
+ for (const [key, value] of Object.entries(this.cache)) {
253
+ // Skip metadata keys
254
+ if (['version', 'created', 'updated', 'stats'].includes(key)) continue;
255
+
256
+ // Remove expired entries
257
+ if (value.expires && value.expires < now) {
258
+ delete this.cache[key];
259
+ prunedCount++;
260
+ }
261
+ }
262
+
263
+ // Update timestamp
264
+ this.cache.updated = new Date().toISOString();
265
+ this.dirty = true;
266
+
267
+ if (prunedCount > 0 && this.options.autoSave) {
268
+ console.log(`Pruned ${prunedCount} expired cache entries`);
269
+ }
270
+ }
271
+
272
+ save(): void {
273
+ if (!this.dirty) return;
274
+
275
+ try {
276
+ // Update metadata
277
+ this.cache.updated = new Date().toISOString();
278
+ if (this.cache.stats) {
279
+ this.cache.stats = { ...this.cache.stats, ...this.stats };
280
+ }
281
+
282
+ let data = JSON.stringify(this.cache, null, 2);
283
+
284
+ // Compress if enabled
285
+ if (this.options.compress && data.length > 1024) {
286
+ data = this.compress(data);
287
+ }
288
+
289
+ // Ensure directory exists
290
+ if (!fs.existsSync(this.cacheDir)) {
291
+ fs.mkdirSync(this.cacheDir, { recursive: true });
292
+ }
293
+
294
+ // Write to temp file first, then rename for atomicity
295
+ const tempPath = `${this.cachePath}.tmp`;
296
+ fs.writeFileSync(tempPath, data, 'utf8');
297
+ fs.renameSync(tempPath, this.cachePath);
298
+
299
+ this.dirty = false;
300
+ } catch (error) {
301
+ console.warn('Could not save cache:', (error as Error).message);
302
+ }
303
+ }
304
+
305
+ getStats(): {
306
+ hits: number;
307
+ misses: number;
308
+ reads: number;
309
+ writes: number;
310
+ hitRate: number;
311
+ size: number;
312
+ entryCount: number;
313
+ } {
314
+ const total = this.stats.hits + this.stats.misses;
315
+ const hitRate = total > 0 ? (this.stats.hits / total) * 100 : 0;
316
+
317
+ let size = 0;
318
+ try {
319
+ if (fs.existsSync(this.cachePath)) {
320
+ const stats = fs.statSync(this.cachePath);
321
+ size = stats.size;
322
+ }
323
+ } catch (error) {
324
+ // Ignore
325
+ }
326
+
327
+ const entryCount = Object.keys(this.cache).filter(k =>
328
+ !['version', 'created', 'updated', 'stats'].includes(k)
329
+ ).length;
330
+
331
+ return {
332
+ hits: this.stats.hits,
333
+ misses: this.stats.misses,
334
+ reads: this.stats.reads,
335
+ writes: this.stats.writes,
336
+ hitRate,
337
+ size,
338
+ entryCount
339
+ };
340
+ }
341
+
342
+ getCacheSize(): number {
343
+ try {
344
+ if (fs.existsSync(this.cachePath)) {
345
+ const stats = fs.statSync(this.cachePath);
346
+ return stats.size;
347
+ }
348
+ } catch (error) {
349
+ // Ignore
350
+ }
351
+ return 0;
352
+ }
353
+
354
+ getCacheAge(): number {
355
+ try {
356
+ if (fs.existsSync(this.cachePath)) {
357
+ const stats = fs.statSync(this.cachePath);
358
+ return Date.now() - stats.mtimeMs;
359
+ }
360
+ } catch (error) {
361
+ // Ignore
362
+ }
363
+ return 0;
364
+ }
365
+
366
+ getKeys(): string[] {
367
+ return Object.keys(this.cache).filter(k =>
368
+ !['version', 'created', 'updated', 'stats'].includes(k)
369
+ );
370
+ }
371
+
372
+ getSize(): number {
373
+ return this.getCacheSize();
374
+ }
375
+
376
+ isDirty(): boolean {
377
+ return this.dirty;
378
+ }
379
+
380
+ async flush(): Promise<void> {
381
+ if (this.dirty) {
382
+ this.save();
383
+ }
384
+ }
385
+
386
+ destroy(): void {
387
+ this.stopAutoSave();
388
+ this.clear();
389
+ }
390
+
391
+ // Get cache entry with metadata
392
+ getEntry(key: string): { value: any; cachedAt: number; expires?: number } | undefined {
393
+ const entry = this.cache[key];
394
+ if (entry && (!entry.expires || entry.expires > Date.now())) {
395
+ return {
396
+ value: entry.value !== undefined ? entry.value : entry,
397
+ cachedAt: entry.cachedAt,
398
+ expires: entry.expires
399
+ };
400
+ }
401
+ return undefined;
402
+ }
403
+
404
+ // Set cache entry with custom TTL in seconds
405
+ setWithTTL(key: string, value: any, ttlSeconds: number): void {
406
+ this.set(key, value, ttlSeconds * 1000);
407
+ }
408
+
409
+ // Bulk set multiple entries
410
+ setBulk(entries: Record<string, any>): void {
411
+ for (const [key, value] of Object.entries(entries)) {
412
+ this.set(key, value);
413
+ }
414
+ }
415
+
416
+ // Bulk get multiple entries
417
+ getBulk(keys: string[]): Record<string, any> {
418
+ const result: Record<string, any> = {};
419
+ for (const key of keys) {
420
+ const value = this.get(key);
421
+ if (value !== undefined) {
422
+ result[key] = value;
423
+ }
424
+ }
425
+ return result;
426
+ }
427
+
428
+ // Get or compute cache value
429
+ async getOrCompute<T>(
430
+ key: string,
431
+ compute: () => Promise<T>,
432
+ ttl?: number
433
+ ): Promise<T> {
434
+ const cached = this.get(key);
435
+ if (cached !== undefined) {
436
+ return cached;
437
+ }
438
+
439
+ const computed = await compute();
440
+ this.set(key, computed, ttl);
441
+ return computed;
442
+ }
443
+ }
444
+
445
+ // ESM Export
446
+ export { CacheManager as default };
@@ -0,0 +1,18 @@
1
+ // src/compiler/commonProps.ts
2
+ export const COMMON_CSS_PROPERTIES: string[] = [
3
+ 'align-content', 'align-items', 'align-self', 'animation', 'background',
4
+ 'background-clip', 'background-color', 'background-image', 'background-position',
5
+ 'background-repeat', 'background-size', 'border', 'border-bottom', 'border-color',
6
+ 'border-left', 'border-radius', 'border-right', 'border-style', 'border-top',
7
+ 'border-width', 'bottom', 'box-shadow', 'box-sizing', 'color', 'content',
8
+ 'cursor', 'display', 'flex', 'flex-direction', 'flex-grow', 'flex-shrink',
9
+ 'flex-wrap', 'float', 'font', 'font-family', 'font-size', 'font-weight',
10
+ 'gap', 'grid', 'grid-template-columns', 'grid-template-rows', 'height',
11
+ 'justify-content', 'left', 'letter-spacing', 'line-height', 'margin',
12
+ 'margin-bottom', 'margin-left', 'margin-right', 'margin-top', 'max-height',
13
+ 'max-width', 'min-height', 'min-width', 'opacity', 'outline', 'overflow',
14
+ 'padding', 'padding-bottom', 'padding-left', 'padding-right', 'padding-top',
15
+ 'position', 'right', 'text-align', 'text-decoration', 'text-transform',
16
+ 'top', 'transform', 'transition', 'transition-delay', 'transition-duration',
17
+ 'transition-property', 'transition-timing-function', 'width', 'z-index'
18
+ ];