@gesslar/sassy 0.20.2 → 0.21.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +12 -8
- package/src/BuildCommand.js +8 -9
- package/src/Cache.js +1 -0
- package/src/Colour.js +8 -2
- package/src/Command.js +93 -32
- package/src/Compiler.js +62 -36
- package/src/Data.js +26 -16
- package/src/Evaluator.js +60 -7
- package/src/File.js +14 -2
- package/src/LintCommand.js +421 -185
- package/src/ResolveCommand.js +60 -29
- package/src/Sass.js +2 -1
- package/src/Session.js +202 -36
- package/src/Term.js +7 -7
- package/src/Theme.js +394 -54
- package/src/ThemePool.js +1 -1
- package/src/ThemeToken.js +1 -0
- package/src/Type.js +11 -10
- package/src/Util.js +2 -2
- package/src/Valid.js +1 -1
- package/src/cli.js +28 -15
package/src/Theme.js
CHANGED
|
@@ -21,6 +21,21 @@ import FileObject from "./FileObject.js"
|
|
|
21
21
|
import Term from "./Term.js"
|
|
22
22
|
import ThemePool from "./ThemePool.js"
|
|
23
23
|
import Util from "./Util.js"
|
|
24
|
+
import Cache from "./Cache.js"
|
|
25
|
+
|
|
26
|
+
const outputFileExtension = "color-theme.json"
|
|
27
|
+
const obviouslyASentinelYouCantMissSoShutUpAboutIt = "kakadoodoo"
|
|
28
|
+
|
|
29
|
+
// Symbol enums for magic values
|
|
30
|
+
const WriteStatus = {
|
|
31
|
+
DRY_RUN: Symbol("dry-run"),
|
|
32
|
+
SKIPPED: Symbol("skipped"),
|
|
33
|
+
WRITTEN: Symbol("written")
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const PropertyKey = {
|
|
37
|
+
CONFIG: Symbol("config")
|
|
38
|
+
}
|
|
24
39
|
|
|
25
40
|
/**
|
|
26
41
|
* Theme class: manages the lifecycle of a theme compilation unit.
|
|
@@ -30,7 +45,13 @@ export default class Theme {
|
|
|
30
45
|
#sourceFile = null
|
|
31
46
|
#source = null
|
|
32
47
|
#options = null
|
|
33
|
-
|
|
48
|
+
/**
|
|
49
|
+
* The dependencies of this theme.
|
|
50
|
+
*
|
|
51
|
+
* @type {Set<Dependency>}
|
|
52
|
+
* @private
|
|
53
|
+
*/
|
|
54
|
+
#dependencies = new Set()
|
|
34
55
|
#lookup = null
|
|
35
56
|
#pool = null
|
|
36
57
|
#cache = null
|
|
@@ -54,7 +75,7 @@ export default class Theme {
|
|
|
54
75
|
constructor(themeFile, cwd, options) {
|
|
55
76
|
this.#sourceFile = themeFile
|
|
56
77
|
this.#name = themeFile.module
|
|
57
|
-
this.#outputFileName = `${this.#name}
|
|
78
|
+
this.#outputFileName = `${this.#name}.${outputFileExtension}`
|
|
58
79
|
this.#options = options
|
|
59
80
|
this.#cwd = cwd
|
|
60
81
|
}
|
|
@@ -71,75 +92,228 @@ export default class Theme {
|
|
|
71
92
|
this.#pool = null
|
|
72
93
|
}
|
|
73
94
|
|
|
74
|
-
|
|
95
|
+
/**
|
|
96
|
+
* Gets the current working directory.
|
|
97
|
+
*
|
|
98
|
+
* @returns {DirectoryObject} The current working directory
|
|
99
|
+
*/
|
|
100
|
+
getCwd() {
|
|
75
101
|
return this.#cwd
|
|
76
102
|
}
|
|
77
103
|
|
|
78
|
-
|
|
104
|
+
/**
|
|
105
|
+
* Gets the compilation options.
|
|
106
|
+
*
|
|
107
|
+
* @returns {object} The compilation options object
|
|
108
|
+
*/
|
|
109
|
+
getOptions() {
|
|
79
110
|
return this.#options
|
|
80
111
|
}
|
|
81
112
|
|
|
82
|
-
|
|
83
|
-
|
|
113
|
+
/**
|
|
114
|
+
* Gets a specific compilation option.
|
|
115
|
+
*
|
|
116
|
+
* @param {string} option - The option name to retrieve
|
|
117
|
+
* @returns {unknown} The option value or undefined if not set
|
|
118
|
+
*/
|
|
119
|
+
getOption(option) {
|
|
120
|
+
return this.#options?.[option] ?? undefined
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Sets the cache instance for theme compilation.
|
|
125
|
+
*
|
|
126
|
+
* @param {Cache} cache - The cache instance to use for file operations
|
|
127
|
+
* @returns {this} Returns this instance for method chaining
|
|
128
|
+
*/
|
|
129
|
+
setCache(cache) {
|
|
130
|
+
if(!this.#cache)
|
|
84
131
|
this.#cache=cache
|
|
132
|
+
|
|
133
|
+
return this
|
|
85
134
|
}
|
|
86
135
|
|
|
87
|
-
|
|
136
|
+
/**
|
|
137
|
+
* Gets the cache instance.
|
|
138
|
+
*
|
|
139
|
+
* @returns {Cache|null} The cache instance or null if not set
|
|
140
|
+
*/
|
|
141
|
+
getCache() {
|
|
88
142
|
return this.#cache
|
|
89
143
|
}
|
|
90
144
|
|
|
91
|
-
|
|
145
|
+
/**
|
|
146
|
+
* Gets the theme name.
|
|
147
|
+
*
|
|
148
|
+
* @returns {string} The theme name derived from the source file
|
|
149
|
+
*/
|
|
150
|
+
getName() {
|
|
92
151
|
return this.#name
|
|
93
152
|
}
|
|
94
153
|
|
|
154
|
+
/**
|
|
155
|
+
* Gets the output file name for the compiled theme.
|
|
156
|
+
*
|
|
157
|
+
* @returns {string} The output file name with extension
|
|
158
|
+
*/
|
|
159
|
+
getOutputFileName() {
|
|
160
|
+
return this.#outputFileName
|
|
161
|
+
}
|
|
162
|
+
|
|
95
163
|
/**
|
|
96
164
|
* Gets the source file object.
|
|
97
165
|
*
|
|
98
166
|
* @returns {FileObject} The source theme file
|
|
99
167
|
*/
|
|
100
|
-
|
|
168
|
+
getSourceFile() {
|
|
101
169
|
return this.#sourceFile
|
|
102
170
|
}
|
|
103
171
|
|
|
172
|
+
/**
|
|
173
|
+
* Sets the compiled theme output object and updates derived JSON and hash.
|
|
174
|
+
*
|
|
175
|
+
* @param {object} data - The compiled theme output object
|
|
176
|
+
* @returns {this} Returns this instance for method chaining
|
|
177
|
+
*/
|
|
178
|
+
setOutput(data) {
|
|
179
|
+
this.#output = data
|
|
180
|
+
this.#outputJson = JSON.stringify(data, null, 2) + "\n"
|
|
181
|
+
this.#outputHash = Util.hashOf(this.#outputJson)
|
|
182
|
+
|
|
183
|
+
return this
|
|
184
|
+
}
|
|
185
|
+
|
|
104
186
|
/**
|
|
105
187
|
* Gets the compiled theme output object.
|
|
106
188
|
*
|
|
107
189
|
* @returns {object|null} The compiled theme output
|
|
108
190
|
*/
|
|
109
|
-
|
|
191
|
+
getOutput() {
|
|
110
192
|
return this.#output
|
|
111
193
|
}
|
|
112
194
|
|
|
113
195
|
/**
|
|
114
|
-
*
|
|
196
|
+
* Checks if the source has colors defined.
|
|
115
197
|
*
|
|
116
|
-
* @
|
|
198
|
+
* @returns {boolean} True if source has theme colors
|
|
117
199
|
*/
|
|
118
|
-
|
|
119
|
-
this.#
|
|
120
|
-
this.#outputJson = JSON.stringify(data, null, 2) + "\n"
|
|
121
|
-
this.#outputHash = Util.hashOf(this.#outputJson)
|
|
200
|
+
sourceHasColors() {
|
|
201
|
+
return !!this.#source?.theme?.colors
|
|
122
202
|
}
|
|
123
203
|
|
|
124
204
|
/**
|
|
125
|
-
*
|
|
205
|
+
* Checks if the source has token colors defined.
|
|
126
206
|
*
|
|
127
|
-
* @returns {
|
|
207
|
+
* @returns {boolean} True if source has theme token colors
|
|
128
208
|
*/
|
|
129
|
-
|
|
209
|
+
sourceHasTokenColors() {
|
|
210
|
+
return !!this.#source?.theme?.tokenColors
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Checks if the source has semantic token colors defined.
|
|
215
|
+
*
|
|
216
|
+
* @returns {boolean} True if source has theme semantic token colors
|
|
217
|
+
*/
|
|
218
|
+
sourceHasSemanticTokenColors() {
|
|
219
|
+
return !!this.#source?.theme?.semanticTokenColors
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Checks if the source has theme configuration.
|
|
224
|
+
*
|
|
225
|
+
* @returns {boolean} True if source has theme data
|
|
226
|
+
*/
|
|
227
|
+
sourceHasTheme() {
|
|
228
|
+
return !!this.#source?.theme
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Checks if the source has variables.
|
|
233
|
+
*
|
|
234
|
+
* @returns {boolean} True if source has vars section
|
|
235
|
+
*/
|
|
236
|
+
sourceHasVars() {
|
|
237
|
+
return !!this.#source?.vars
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Checks if the source has config section.
|
|
242
|
+
*
|
|
243
|
+
* @returns {boolean} True if source has config
|
|
244
|
+
*/
|
|
245
|
+
sourceHasConfig() {
|
|
246
|
+
return !!this.#source?.config
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Gets the source colors data.
|
|
251
|
+
*
|
|
252
|
+
* @returns {object|null} The colors object or null if not defined
|
|
253
|
+
*/
|
|
254
|
+
getSourceColors() {
|
|
255
|
+
if(!this.sourceHasColors())
|
|
256
|
+
return null
|
|
257
|
+
|
|
258
|
+
return this.#source.theme.colors
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Gets the source token colors data.
|
|
263
|
+
*
|
|
264
|
+
* @returns {Array|null} The token colors array or null if not defined
|
|
265
|
+
*/
|
|
266
|
+
getSourceTokenColors() {
|
|
267
|
+
if(!this.sourceHasTokenColors())
|
|
268
|
+
return null
|
|
269
|
+
|
|
270
|
+
return this.#source.theme.tokenColors
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Gets the source semantic token colors data.
|
|
275
|
+
*
|
|
276
|
+
* @returns {object|null} The semantic token colors object or null if not defined
|
|
277
|
+
*/
|
|
278
|
+
getSourceSemanticTokenColors() {
|
|
279
|
+
if(!this.sourceHasSemanticTokenColors())
|
|
280
|
+
return null
|
|
281
|
+
|
|
282
|
+
return this.#source.theme.semanticTokenColors
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Gets the set of file dependencies.
|
|
287
|
+
*
|
|
288
|
+
* @returns {Set<Dependency>} Set of dependency files
|
|
289
|
+
*/
|
|
290
|
+
getDependencies() {
|
|
130
291
|
return this.#dependencies
|
|
131
292
|
}
|
|
132
293
|
|
|
133
294
|
/**
|
|
134
|
-
*
|
|
295
|
+
* Adds a dependency to the theme with its source data.
|
|
135
296
|
*
|
|
136
|
-
* @param {FileObject
|
|
297
|
+
* @param {FileObject} file - The dependency file object
|
|
298
|
+
* @param {object} source - The parsed source data from the file
|
|
299
|
+
* @returns {this} Returns this instance for method chaining
|
|
137
300
|
*/
|
|
138
|
-
|
|
139
|
-
this.#dependencies
|
|
301
|
+
addDependency(file, source) {
|
|
302
|
+
this.#dependencies.add(
|
|
303
|
+
new Dependency()
|
|
304
|
+
.setSourceFile(file)
|
|
305
|
+
.setSource(source))
|
|
140
306
|
|
|
141
|
-
|
|
142
|
-
|
|
307
|
+
return this
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Checks if the theme has any dependencies.
|
|
312
|
+
*
|
|
313
|
+
* @returns {boolean} True if theme has dependencies
|
|
314
|
+
*/
|
|
315
|
+
hasDependencies() {
|
|
316
|
+
return this.#dependencies.size > 0
|
|
143
317
|
}
|
|
144
318
|
|
|
145
319
|
/**
|
|
@@ -147,7 +321,7 @@ export default class Theme {
|
|
|
147
321
|
*
|
|
148
322
|
* @returns {object|null} The parsed source data
|
|
149
323
|
*/
|
|
150
|
-
|
|
324
|
+
getSource() {
|
|
151
325
|
return this.#source
|
|
152
326
|
}
|
|
153
327
|
|
|
@@ -156,7 +330,7 @@ export default class Theme {
|
|
|
156
330
|
*
|
|
157
331
|
* @returns {object|null} The lookup data object
|
|
158
332
|
*/
|
|
159
|
-
|
|
333
|
+
getLookup() {
|
|
160
334
|
return this.#lookup
|
|
161
335
|
}
|
|
162
336
|
|
|
@@ -164,9 +338,12 @@ export default class Theme {
|
|
|
164
338
|
* Sets the variable lookup data for theme compilation.
|
|
165
339
|
*
|
|
166
340
|
* @param {object} data - The lookup data object
|
|
341
|
+
* @returns {this} Returns this instance for method chaining
|
|
167
342
|
*/
|
|
168
|
-
|
|
343
|
+
setLookup(data) {
|
|
169
344
|
this.#lookup = data
|
|
345
|
+
|
|
346
|
+
return this
|
|
170
347
|
}
|
|
171
348
|
|
|
172
349
|
/**
|
|
@@ -175,7 +352,7 @@ export default class Theme {
|
|
|
175
352
|
*
|
|
176
353
|
* @returns {ThemePool|null} The pool for this theme.
|
|
177
354
|
*/
|
|
178
|
-
|
|
355
|
+
getPool() {
|
|
179
356
|
return this.#pool
|
|
180
357
|
}
|
|
181
358
|
|
|
@@ -186,13 +363,14 @@ export default class Theme {
|
|
|
186
363
|
* @see reset
|
|
187
364
|
*
|
|
188
365
|
* @param {ThemePool} pool - The pool to assign to this theme
|
|
189
|
-
* @throws If there is already a pool.
|
|
366
|
+
* @throws {Error} If there is already a pool.
|
|
367
|
+
* @returns {this} Returns this instance for method chaining
|
|
190
368
|
*/
|
|
191
|
-
|
|
192
|
-
if(this.#pool)
|
|
193
|
-
|
|
369
|
+
setPool(pool) {
|
|
370
|
+
if(!this.#pool)
|
|
371
|
+
this.#pool = pool
|
|
194
372
|
|
|
195
|
-
this
|
|
373
|
+
return this
|
|
196
374
|
}
|
|
197
375
|
|
|
198
376
|
/**
|
|
@@ -204,36 +382,115 @@ export default class Theme {
|
|
|
204
382
|
return this.#pool instanceof ThemePool
|
|
205
383
|
}
|
|
206
384
|
|
|
385
|
+
/**
|
|
386
|
+
* Checks if the theme has compiled output.
|
|
387
|
+
*
|
|
388
|
+
* @returns {boolean} True if theme has been compiled
|
|
389
|
+
*/
|
|
390
|
+
hasOutput() {
|
|
391
|
+
return this.#output !== null
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* Checks if the theme has loaded source data.
|
|
396
|
+
*
|
|
397
|
+
* @returns {boolean} True if source data is available
|
|
398
|
+
*/
|
|
399
|
+
hasSource() {
|
|
400
|
+
return this.#source !== null
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Checks if the theme has a cache instance.
|
|
405
|
+
*
|
|
406
|
+
* @returns {boolean} True if cache is available
|
|
407
|
+
*/
|
|
408
|
+
hasCache() {
|
|
409
|
+
return this.#cache !== null
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Checks if the theme has lookup data.
|
|
414
|
+
*
|
|
415
|
+
* @returns {boolean} True if lookup data exists
|
|
416
|
+
*/
|
|
417
|
+
hasLookup() {
|
|
418
|
+
return this.#lookup !== null
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Checks if the theme is ready to be compiled.
|
|
423
|
+
* Requires source data and cache to be available.
|
|
424
|
+
*
|
|
425
|
+
* @returns {boolean} True if theme can be compiled
|
|
426
|
+
*/
|
|
427
|
+
isReady() {
|
|
428
|
+
return this.hasSource() && this.hasCache()
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* Checks if the theme has been fully compiled.
|
|
433
|
+
* Requires output, pool, and lookup data to be present.
|
|
434
|
+
*
|
|
435
|
+
* @returns {boolean} True if theme is fully compiled
|
|
436
|
+
*/
|
|
437
|
+
isCompiled() {
|
|
438
|
+
return this.hasOutput() && this.hasPool() && this.hasLookup()
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* Checks if the theme can be built/compiled.
|
|
443
|
+
* Same as isReady() but with more semantic naming.
|
|
444
|
+
*
|
|
445
|
+
* @returns {boolean} True if build can proceed
|
|
446
|
+
*/
|
|
447
|
+
canBuild() {
|
|
448
|
+
return this.isReady()
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* Checks if the theme can be written to output.
|
|
453
|
+
* Requires the theme to be compiled.
|
|
454
|
+
*
|
|
455
|
+
* @returns {boolean} True if write can proceed
|
|
456
|
+
*/
|
|
457
|
+
canWrite() {
|
|
458
|
+
return this.hasOutput()
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Checks if the theme is in a valid state for operation.
|
|
463
|
+
* Basic validation that core properties are set.
|
|
464
|
+
*
|
|
465
|
+
* @returns {boolean} True if theme state is valid
|
|
466
|
+
*/
|
|
467
|
+
isValid() {
|
|
468
|
+
return this.#sourceFile !== null && this.#name !== null
|
|
469
|
+
}
|
|
470
|
+
|
|
207
471
|
/**
|
|
208
472
|
* Loads and parses the theme source file.
|
|
209
473
|
* Validates that the source contains required configuration.
|
|
474
|
+
* Skips loading if no cache is available (extension use case).
|
|
210
475
|
*
|
|
211
476
|
* @returns {Promise<this>} Returns this instance for method chaining
|
|
212
477
|
* @throws {Sass} If source file lacks required 'config' property
|
|
213
478
|
*/
|
|
214
479
|
async load() {
|
|
480
|
+
// Skip loading if no cache (extension use case)
|
|
481
|
+
if(!this.#cache)
|
|
482
|
+
return this
|
|
483
|
+
|
|
215
484
|
const source = await this.#cache.loadCachedData(this.#sourceFile)
|
|
216
485
|
|
|
217
|
-
if(!source.
|
|
486
|
+
if(!source[PropertyKey.CONFIG.description])
|
|
218
487
|
throw Sass.new(
|
|
219
|
-
`Source file does not contain '
|
|
488
|
+
`Source file does not contain '${PropertyKey.CONFIG.description}' property: ${this.#sourceFile.path}`
|
|
220
489
|
)
|
|
221
490
|
|
|
222
491
|
this.#source = source
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* Adds a file dependency to the theme.
|
|
227
|
-
*
|
|
228
|
-
* @param {FileObject} file - The file to add as a dependency
|
|
229
|
-
* @returns {this} Returns this instance for method chaining
|
|
230
|
-
* @throws {Sass} If the file parameter is not a valid file
|
|
231
|
-
*/
|
|
232
|
-
addDependency(file) {
|
|
233
|
-
if(!file.isFile)
|
|
234
|
-
throw Sass.new("File must be a dependency.")
|
|
235
492
|
|
|
236
|
-
this.#
|
|
493
|
+
this.addDependency(this.#sourceFile, new Map(Object.entries(this.#source)))
|
|
237
494
|
|
|
238
495
|
return this
|
|
239
496
|
}
|
|
@@ -242,11 +499,14 @@ export default class Theme {
|
|
|
242
499
|
* Builds the theme by compiling source data into final output.
|
|
243
500
|
* Main entry point for theme compilation process.
|
|
244
501
|
*
|
|
245
|
-
* @returns {Promise<
|
|
502
|
+
* @returns {Promise<this>} Returns this instance for method chaining
|
|
246
503
|
*/
|
|
247
504
|
async build() {
|
|
248
505
|
const compiler = new Compiler()
|
|
506
|
+
|
|
249
507
|
await compiler.compile(this)
|
|
508
|
+
|
|
509
|
+
return this
|
|
250
510
|
}
|
|
251
511
|
|
|
252
512
|
/**
|
|
@@ -264,7 +524,7 @@ export default class Theme {
|
|
|
264
524
|
if(this.#options.dryRun) {
|
|
265
525
|
Term.log(this.#outputJson)
|
|
266
526
|
|
|
267
|
-
return {status:
|
|
527
|
+
return {status: WriteStatus.DRY_RUN, file}
|
|
268
528
|
}
|
|
269
529
|
|
|
270
530
|
// Skip identical bytes
|
|
@@ -272,10 +532,10 @@ export default class Theme {
|
|
|
272
532
|
const nextHash = this.#outputHash
|
|
273
533
|
const lastHash = await file.exists
|
|
274
534
|
? Util.hashOf(await File.readFile(file))
|
|
275
|
-
:
|
|
535
|
+
: obviouslyASentinelYouCantMissSoShutUpAboutIt
|
|
276
536
|
|
|
277
537
|
if(lastHash === nextHash)
|
|
278
|
-
return {status:
|
|
538
|
+
return {status: WriteStatus.SKIPPED, file}
|
|
279
539
|
}
|
|
280
540
|
|
|
281
541
|
// Real write (timed)
|
|
@@ -284,6 +544,86 @@ export default class Theme {
|
|
|
284
544
|
|
|
285
545
|
await File.writeFile(file, output)
|
|
286
546
|
|
|
287
|
-
return {status:
|
|
547
|
+
return {status: WriteStatus.WRITTEN, bytes: output.length, file}
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
/**
|
|
552
|
+
* Dependency class represents a theme file dependency.
|
|
553
|
+
* Manages the relationship between a file reference and its parsed source data.
|
|
554
|
+
*/
|
|
555
|
+
export class Dependency {
|
|
556
|
+
#sourceFile = null
|
|
557
|
+
#source = null
|
|
558
|
+
|
|
559
|
+
/**
|
|
560
|
+
* Sets the file object for this dependency.
|
|
561
|
+
*
|
|
562
|
+
* @param {FileObject} file - The file object of this dependency.
|
|
563
|
+
* @returns {this} This.
|
|
564
|
+
*/
|
|
565
|
+
setSourceFile(file) {
|
|
566
|
+
if(!this.#sourceFile)
|
|
567
|
+
this.#sourceFile = file
|
|
568
|
+
|
|
569
|
+
return this
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
/**
|
|
573
|
+
* Get the file object for this depenency.
|
|
574
|
+
*
|
|
575
|
+
* @returns {FileObject} The file object of this dependency.
|
|
576
|
+
*/
|
|
577
|
+
getSourceFile() {
|
|
578
|
+
return this.#sourceFile
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
/**
|
|
582
|
+
* Sets the source object for this dependency.
|
|
583
|
+
*
|
|
584
|
+
* @param {object} source - The parsed JSON from the file after loading.
|
|
585
|
+
* @returns {this} This.
|
|
586
|
+
*/
|
|
587
|
+
setSource(source) {
|
|
588
|
+
if(!this.#source)
|
|
589
|
+
this.#source = source
|
|
590
|
+
|
|
591
|
+
return this
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
/**
|
|
595
|
+
* Gets the parsed source data for this dependency.
|
|
596
|
+
*
|
|
597
|
+
* @returns {object|null} The parsed source data
|
|
598
|
+
*/
|
|
599
|
+
getSource() {
|
|
600
|
+
return this.#source
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
/**
|
|
604
|
+
* Checks if the dependency has a source file.
|
|
605
|
+
*
|
|
606
|
+
* @returns {boolean} True if source file is set
|
|
607
|
+
*/
|
|
608
|
+
hasSourceFile() {
|
|
609
|
+
return this.#sourceFile !== null
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
/**
|
|
613
|
+
* Checks if the dependency has parsed source data.
|
|
614
|
+
*
|
|
615
|
+
* @returns {boolean} True if source data is available
|
|
616
|
+
*/
|
|
617
|
+
hasSource() {
|
|
618
|
+
return this.#source !== null
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
/**
|
|
622
|
+
* Checks if the dependency is fully initialized.
|
|
623
|
+
*
|
|
624
|
+
* @returns {boolean} True if both file and source are set
|
|
625
|
+
*/
|
|
626
|
+
isComplete() {
|
|
627
|
+
return this.hasSourceFile() && this.hasSource()
|
|
288
628
|
}
|
|
289
629
|
}
|
package/src/ThemePool.js
CHANGED
package/src/ThemeToken.js
CHANGED
package/src/Type.js
CHANGED
|
@@ -60,7 +60,7 @@ export default class TypeSpec {
|
|
|
60
60
|
/**
|
|
61
61
|
* Executes a provided function once for each type specification.
|
|
62
62
|
*
|
|
63
|
-
* @param {
|
|
63
|
+
* @param {function(unknown): void} callback - Function to execute for each spec
|
|
64
64
|
*/
|
|
65
65
|
forEach(callback) {
|
|
66
66
|
this.#specs.forEach(callback)
|
|
@@ -69,7 +69,7 @@ export default class TypeSpec {
|
|
|
69
69
|
/**
|
|
70
70
|
* Tests whether all type specifications pass the provided test function.
|
|
71
71
|
*
|
|
72
|
-
* @param {
|
|
72
|
+
* @param {function(unknown): boolean} callback - Function to test each spec
|
|
73
73
|
* @returns {boolean} True if all specs pass the test
|
|
74
74
|
*/
|
|
75
75
|
every(callback) {
|
|
@@ -79,7 +79,7 @@ export default class TypeSpec {
|
|
|
79
79
|
/**
|
|
80
80
|
* Tests whether at least one type specification passes the provided test function.
|
|
81
81
|
*
|
|
82
|
-
* @param {
|
|
82
|
+
* @param {function(unknown): boolean} callback - Function to test each spec
|
|
83
83
|
* @returns {boolean} True if at least one spec passes the test
|
|
84
84
|
*/
|
|
85
85
|
some(callback) {
|
|
@@ -89,7 +89,7 @@ export default class TypeSpec {
|
|
|
89
89
|
/**
|
|
90
90
|
* Creates a new array with all type specifications that pass the provided test function.
|
|
91
91
|
*
|
|
92
|
-
* @param {
|
|
92
|
+
* @param {function(unknown): boolean} callback - Function to test each spec
|
|
93
93
|
* @returns {Array} New array with filtered specs
|
|
94
94
|
*/
|
|
95
95
|
filter(callback) {
|
|
@@ -99,7 +99,7 @@ export default class TypeSpec {
|
|
|
99
99
|
/**
|
|
100
100
|
* Creates a new array populated with the results of calling the provided function on every spec.
|
|
101
101
|
*
|
|
102
|
-
* @param {
|
|
102
|
+
* @param {function(unknown): unknown} callback - Function to call on each spec
|
|
103
103
|
* @returns {Array} New array with mapped values
|
|
104
104
|
*/
|
|
105
105
|
map(callback) {
|
|
@@ -109,9 +109,9 @@ export default class TypeSpec {
|
|
|
109
109
|
/**
|
|
110
110
|
* Executes a reducer function on each spec, resulting in a single output value.
|
|
111
111
|
*
|
|
112
|
-
* @param {
|
|
113
|
-
* @param {
|
|
114
|
-
* @returns {
|
|
112
|
+
* @param {function(unknown, unknown): unknown} callback - Function to execute on each spec
|
|
113
|
+
* @param {unknown} initialValue - Initial value for the accumulator
|
|
114
|
+
* @returns {unknown} The final accumulated value
|
|
115
115
|
*/
|
|
116
116
|
reduce(callback, initialValue) {
|
|
117
117
|
return this.#specs.reduce(callback, initialValue)
|
|
@@ -120,7 +120,7 @@ export default class TypeSpec {
|
|
|
120
120
|
/**
|
|
121
121
|
* Returns the first type specification that satisfies the provided testing function.
|
|
122
122
|
*
|
|
123
|
-
* @param {
|
|
123
|
+
* @param {function(unknown): boolean} callback - Function to test each spec
|
|
124
124
|
* @returns {object|undefined} The first spec that matches, or undefined
|
|
125
125
|
*/
|
|
126
126
|
find(callback) {
|
|
@@ -131,7 +131,7 @@ export default class TypeSpec {
|
|
|
131
131
|
* Tests whether a value matches any of the type specifications.
|
|
132
132
|
* Handles array types, union types, and empty value validation.
|
|
133
133
|
*
|
|
134
|
-
* @param {
|
|
134
|
+
* @param {unknown} value - The value to test against the type specifications
|
|
135
135
|
* @param {object} options - Validation options
|
|
136
136
|
* @param {boolean} options.allowEmpty - Whether empty values are allowed
|
|
137
137
|
* @returns {boolean} True if the value matches any type specification
|
|
@@ -191,6 +191,7 @@ export default class TypeSpec {
|
|
|
191
191
|
|
|
192
192
|
this.#specs = parts.map(part => {
|
|
193
193
|
const typeMatches = /(\w+)(\[\])?/.exec(part)
|
|
194
|
+
|
|
194
195
|
if(!typeMatches || typeMatches.length !== 3)
|
|
195
196
|
throw Sass.new(`Invalid type: ${part}`)
|
|
196
197
|
|