@gesslar/sassy 0.21.0 → 0.21.3
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 +10 -5
- package/src/BuildCommand.js +1 -2
- package/src/Colour.js +1 -3
- package/src/Command.js +1 -3
- package/src/Compiler.js +1 -6
- package/src/Evaluator.js +53 -4
- package/src/LintCommand.js +216 -259
- package/src/ResolveCommand.js +17 -6
- package/src/Session.js +4 -5
- package/src/Theme.js +19 -10
- package/src/ThemePool.js +1 -1
- package/src/ThemeToken.js +1 -1
- package/src/cli.js +3 -6
- package/src/index.js +40 -0
- package/src/Cache.js +0 -74
- package/src/Data.js +0 -533
- package/src/DirectoryObject.js +0 -188
- package/src/File.js +0 -346
- package/src/FileObject.js +0 -226
- package/src/Sass.js +0 -166
- package/src/Term.js +0 -175
- package/src/Type.js +0 -207
- package/src/Util.js +0 -132
- package/src/Valid.js +0 -50
package/src/ResolveCommand.js
CHANGED
|
@@ -2,13 +2,10 @@ import c from "@gesslar/colours"
|
|
|
2
2
|
// import colorSupport from "color-support"
|
|
3
3
|
|
|
4
4
|
import Command from "./Command.js"
|
|
5
|
-
import Sass from "
|
|
5
|
+
import {Sass, Term, Util, Data} from "@gesslar/toolkit"
|
|
6
6
|
import Colour from "./Colour.js"
|
|
7
7
|
import Evaluator from "./Evaluator.js"
|
|
8
|
-
import Term from "./Term.js"
|
|
9
8
|
import Theme from "./Theme.js"
|
|
10
|
-
import Util from "./Util.js"
|
|
11
|
-
import Data from "./Data.js"
|
|
12
9
|
|
|
13
10
|
// ansiColors.enabled = colorSupport.hasBasic
|
|
14
11
|
|
|
@@ -87,6 +84,14 @@ export default class ResolveCommand extends Command {
|
|
|
87
84
|
* @param {object} theme - The compiled theme object with pool
|
|
88
85
|
* @param {string} colorName - The color key to resolve
|
|
89
86
|
* @returns {void}
|
|
87
|
+
* @example
|
|
88
|
+
* // Resolve a color variable from a compiled theme
|
|
89
|
+
* await resolveCommand.resolveColor(theme, 'colors.primary');
|
|
90
|
+
* // Output:
|
|
91
|
+
* // colors.primary:
|
|
92
|
+
* // $(vars.accent)
|
|
93
|
+
* // → #3366cc
|
|
94
|
+
* // Resolution: #3366cc
|
|
90
95
|
*/
|
|
91
96
|
async resolveColor(theme, colorName) {
|
|
92
97
|
const pool = theme.getPool()
|
|
@@ -243,6 +248,7 @@ export default class ResolveCommand extends Command {
|
|
|
243
248
|
|
|
244
249
|
// Temporarily replace tokenColors with semanticTokenColors for resolution
|
|
245
250
|
const themeOutput = theme.getOutput()
|
|
251
|
+
|
|
246
252
|
if(themeOutput?.semanticTokenColors) {
|
|
247
253
|
themeOutput.tokenColors = themeOutput.semanticTokenColors
|
|
248
254
|
}
|
|
@@ -426,7 +432,12 @@ export default class ResolveCommand extends Command {
|
|
|
426
432
|
}
|
|
427
433
|
|
|
428
434
|
if(this.#func.test(value)) {
|
|
429
|
-
const
|
|
435
|
+
const result = Evaluator.extractFunctionCall(value)
|
|
436
|
+
|
|
437
|
+
if(!result)
|
|
438
|
+
return [c`{leaf}${value}{/}`, "literal"]
|
|
439
|
+
|
|
440
|
+
const {func, args} = result
|
|
430
441
|
|
|
431
442
|
return [
|
|
432
443
|
c`{func}${func}{/}{parens}${"("}{/}{leaf}${args}{/}{parens}${")"}{/}`,
|
|
@@ -435,9 +446,9 @@ export default class ResolveCommand extends Command {
|
|
|
435
446
|
}
|
|
436
447
|
|
|
437
448
|
if(this.#sub.test(value)) {
|
|
449
|
+
const varValue = Evaluator.extractVariableName(value) || value
|
|
438
450
|
const {parens,none,braces} = Evaluator.sub.exec(value)?.groups || {}
|
|
439
451
|
const style = (braces && ["{","}"]) || (parens && ["(",")"]) || (none && ["",""])
|
|
440
|
-
const varValue = braces || parens || none || value
|
|
441
452
|
|
|
442
453
|
return [
|
|
443
454
|
c`{func}{/}{parens}${style[0]}{/}{leaf}${varValue}{/}{parens}${style[1]}{/}`,
|
package/src/Session.js
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import chokidar from "chokidar"
|
|
2
2
|
|
|
3
3
|
import Command from "./Command.js"
|
|
4
|
-
import Sass from "
|
|
5
|
-
import File from "./File.js"
|
|
6
|
-
import Term from "./Term.js"
|
|
4
|
+
import {Sass, File, Term, Util} from "@gesslar/toolkit"
|
|
7
5
|
import Theme from "./Theme.js"
|
|
8
|
-
import Util from "./Util.js"
|
|
9
6
|
|
|
10
7
|
/**
|
|
11
8
|
* @typedef {object} SessionOptions
|
|
@@ -481,7 +478,9 @@ export default class Session {
|
|
|
481
478
|
if(this.#watcher)
|
|
482
479
|
await this.#watcher.close()
|
|
483
480
|
|
|
484
|
-
const dependencies = Array.from(this.#theme
|
|
481
|
+
const dependencies = Array.from(this.#theme
|
|
482
|
+
.getDependencies())
|
|
483
|
+
.map(d => d.getSourceFile().path)
|
|
485
484
|
|
|
486
485
|
this.#watcher = chokidar.watch(dependencies, {
|
|
487
486
|
// Prevent watching own output files
|
package/src/Theme.js
CHANGED
|
@@ -13,14 +13,9 @@
|
|
|
13
13
|
* - Write output files, supporting dry-run and hash-based skip
|
|
14
14
|
* - Support watch mode for live theme development
|
|
15
15
|
*/
|
|
16
|
-
import Sass from "
|
|
16
|
+
import {Sass, DirectoryObject, File, FileObject, Term, Util, Cache} from "@gesslar/toolkit"
|
|
17
17
|
import Compiler from "./Compiler.js"
|
|
18
|
-
import DirectoryObject from "./DirectoryObject.js"
|
|
19
|
-
import File from "./File.js"
|
|
20
|
-
import FileObject from "./FileObject.js"
|
|
21
|
-
import Term from "./Term.js"
|
|
22
18
|
import ThemePool from "./ThemePool.js"
|
|
23
|
-
import Util from "./Util.js"
|
|
24
19
|
|
|
25
20
|
const outputFileExtension = "color-theme.json"
|
|
26
21
|
const obviouslyASentinelYouCantMissSoShutUpAboutIt = "kakadoodoo"
|
|
@@ -113,7 +108,7 @@ export default class Theme {
|
|
|
113
108
|
* Gets a specific compilation option.
|
|
114
109
|
*
|
|
115
110
|
* @param {string} option - The option name to retrieve
|
|
116
|
-
* @returns {
|
|
111
|
+
* @returns {unknown} The option value or undefined if not set
|
|
117
112
|
*/
|
|
118
113
|
getOption(option) {
|
|
119
114
|
return this.#options?.[option] ?? undefined
|
|
@@ -282,9 +277,9 @@ export default class Theme {
|
|
|
282
277
|
}
|
|
283
278
|
|
|
284
279
|
/**
|
|
285
|
-
* Gets the
|
|
280
|
+
* Gets the set of file dependencies.
|
|
286
281
|
*
|
|
287
|
-
* @returns {Set<Dependency>}
|
|
282
|
+
* @returns {Set<Dependency>} Set of dependency files
|
|
288
283
|
*/
|
|
289
284
|
getDependencies() {
|
|
290
285
|
return this.#dependencies
|
|
@@ -306,6 +301,11 @@ export default class Theme {
|
|
|
306
301
|
return this
|
|
307
302
|
}
|
|
308
303
|
|
|
304
|
+
/**
|
|
305
|
+
* Checks if the theme has any dependencies.
|
|
306
|
+
*
|
|
307
|
+
* @returns {boolean} True if theme has dependencies
|
|
308
|
+
*/
|
|
309
309
|
hasDependencies() {
|
|
310
310
|
return this.#dependencies.size > 0
|
|
311
311
|
}
|
|
@@ -484,7 +484,7 @@ export default class Theme {
|
|
|
484
484
|
|
|
485
485
|
this.#source = source
|
|
486
486
|
|
|
487
|
-
this.addDependency(this.#sourceFile, this.#source)
|
|
487
|
+
this.addDependency(this.#sourceFile, new Map(Object.entries(this.#source)))
|
|
488
488
|
|
|
489
489
|
return this
|
|
490
490
|
}
|
|
@@ -542,6 +542,10 @@ export default class Theme {
|
|
|
542
542
|
}
|
|
543
543
|
}
|
|
544
544
|
|
|
545
|
+
/**
|
|
546
|
+
* Dependency class represents a theme file dependency.
|
|
547
|
+
* Manages the relationship between a file reference and its parsed source data.
|
|
548
|
+
*/
|
|
545
549
|
export class Dependency {
|
|
546
550
|
#sourceFile = null
|
|
547
551
|
#source = null
|
|
@@ -581,6 +585,11 @@ export class Dependency {
|
|
|
581
585
|
return this
|
|
582
586
|
}
|
|
583
587
|
|
|
588
|
+
/**
|
|
589
|
+
* Gets the parsed source data for this dependency.
|
|
590
|
+
*
|
|
591
|
+
* @returns {object|null} The parsed source data
|
|
592
|
+
*/
|
|
584
593
|
getSource() {
|
|
585
594
|
return this.#source
|
|
586
595
|
}
|
package/src/ThemePool.js
CHANGED
package/src/ThemeToken.js
CHANGED
package/src/cli.js
CHANGED
|
@@ -36,14 +36,10 @@ import process from "node:process"
|
|
|
36
36
|
import url from "node:url"
|
|
37
37
|
import c from "@gesslar/colours"
|
|
38
38
|
|
|
39
|
-
import Cache from "
|
|
40
|
-
import Sass from "./Sass.js"
|
|
39
|
+
import {Cache, Sass, DirectoryObject, FileObject, Term} from "@gesslar/toolkit"
|
|
41
40
|
import BuildCommand from "./BuildCommand.js"
|
|
42
|
-
import DirectoryObject from "./DirectoryObject.js"
|
|
43
|
-
import FileObject from "./FileObject.js"
|
|
44
41
|
import LintCommand from "./LintCommand.js"
|
|
45
42
|
import ResolveCommand from "./ResolveCommand.js"
|
|
46
|
-
import Term from "./Term.js"
|
|
47
43
|
|
|
48
44
|
/**
|
|
49
45
|
* Main application entry point.
|
|
@@ -111,9 +107,10 @@ void (async function main() {
|
|
|
111
107
|
.version(pkgJson.version)
|
|
112
108
|
|
|
113
109
|
const commands = [BuildCommand, ResolveCommand, LintCommand]
|
|
114
|
-
|
|
110
|
+
|
|
115
111
|
for(const CommandClass of commands) {
|
|
116
112
|
const command = new CommandClass({cwd, packageJson: pkgJson})
|
|
113
|
+
|
|
117
114
|
command.setCache(cache)
|
|
118
115
|
await command.buildCli(program)
|
|
119
116
|
command.addCliOptions(alwaysAvailable, false)
|
package/src/index.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file API entry point for @gesslar/sassy
|
|
3
|
+
*
|
|
4
|
+
* Exports classes and utilities for programmatic use by other npm packages.
|
|
5
|
+
*
|
|
6
|
+
* This allows other projects to import and use Sassy's functionality
|
|
7
|
+
* programmatically.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* // Import specific classes
|
|
11
|
+
* import { Theme, LintCommand, Compiler } from '@gesslar/sassy'
|
|
12
|
+
*
|
|
13
|
+
* // Import everything
|
|
14
|
+
* import * as Sassy from '@gesslar/sassy'
|
|
15
|
+
*
|
|
16
|
+
* // Create and use a Theme programmatically
|
|
17
|
+
* const theme = new Theme(fileObject)
|
|
18
|
+
* await theme.load('./my-theme.json5')
|
|
19
|
+
* await theme.build()
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
// Core theme functionality
|
|
23
|
+
export {default as Theme} from "./Theme.js"
|
|
24
|
+
export {default as Compiler} from "./Compiler.js"
|
|
25
|
+
export {default as Evaluator} from "./Evaluator.js"
|
|
26
|
+
|
|
27
|
+
// Command classes for programmatic access
|
|
28
|
+
export {default as Command} from "./Command.js"
|
|
29
|
+
export {default as BuildCommand} from "./BuildCommand.js"
|
|
30
|
+
export {default as LintCommand} from "./LintCommand.js"
|
|
31
|
+
export {default as ResolveCommand} from "./ResolveCommand.js"
|
|
32
|
+
|
|
33
|
+
// Data handling and utilities
|
|
34
|
+
export {default as Session} from "./Session.js"
|
|
35
|
+
|
|
36
|
+
// Color utilities
|
|
37
|
+
export {default as Colour} from "./Colour.js"
|
|
38
|
+
|
|
39
|
+
// Note: CLI functionality remains in cli.js and is accessible via the 'sassy'
|
|
40
|
+
// command when installed globally or via npx
|
package/src/Cache.js
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import Sass from "./Sass.js"
|
|
2
|
-
import File from "./File.js"
|
|
3
|
-
import FileObject from "./FileObject.js"
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* File system cache for theme compilation data with automatic invalidation.
|
|
7
|
-
* Provides intelligent caching of parsed JSON5/YAML files with mtime-based
|
|
8
|
-
* cache invalidation to optimize parallel theme compilation performance.
|
|
9
|
-
*
|
|
10
|
-
* The cache eliminates redundant file reads and parsing when multiple themes
|
|
11
|
-
* import the same dependency files, while ensuring data freshness through
|
|
12
|
-
* modification time checking.
|
|
13
|
-
*/
|
|
14
|
-
export default class Cache {
|
|
15
|
-
/** @type {Map<string, Date>} Map of file paths to last modification times */
|
|
16
|
-
#modifiedTimes = new Map()
|
|
17
|
-
/** @type {Map<string, object>} Map of file paths to parsed file data */
|
|
18
|
-
#dataCache = new Map()
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Removes cached data for a specific file from both time and data maps.
|
|
22
|
-
* Used when files are modified or when cache consistency needs to be
|
|
23
|
-
* maintained.
|
|
24
|
-
*
|
|
25
|
-
* @private
|
|
26
|
-
* @param {FileObject} file - The file object to remove from cache
|
|
27
|
-
* @returns {void}
|
|
28
|
-
*/
|
|
29
|
-
#cleanup(file) {
|
|
30
|
-
this.#modifiedTimes.delete(file.path)
|
|
31
|
-
this.#dataCache.delete(file.path)
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Loads and caches parsed file data with automatic invalidation based on
|
|
36
|
-
* modification time.
|
|
37
|
-
*
|
|
38
|
-
* Implements a sophisticated caching strategy that checks file modification
|
|
39
|
-
* times to determine whether cached data is still valid, ensuring data
|
|
40
|
-
* freshness while optimizing performance for repeated file access during
|
|
41
|
-
* parallel theme compilation.
|
|
42
|
-
*
|
|
43
|
-
* @param {FileObject} fileObject - The file object to load and cache
|
|
44
|
-
* @returns {Promise<object>} The parsed file data (JSON5 or YAML)
|
|
45
|
-
* @throws {Sass} If the file cannot be found or accessed
|
|
46
|
-
*/
|
|
47
|
-
async loadCachedData(fileObject) {
|
|
48
|
-
const lastModified = await File.fileModified(fileObject)
|
|
49
|
-
|
|
50
|
-
if(lastModified === null)
|
|
51
|
-
throw Sass.new(`Unable to find file '${fileObject.path}'`)
|
|
52
|
-
|
|
53
|
-
if(this.#modifiedTimes.has(fileObject.path)) {
|
|
54
|
-
const lastCached = this.#modifiedTimes.get(fileObject.path)
|
|
55
|
-
|
|
56
|
-
if(lastModified > lastCached) {
|
|
57
|
-
this.#cleanup(fileObject)
|
|
58
|
-
} else {
|
|
59
|
-
if(!(this.#dataCache.has(fileObject.path)))
|
|
60
|
-
this.#cleanup(fileObject)
|
|
61
|
-
else {
|
|
62
|
-
return this.#dataCache.get(fileObject.path)
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const data = await File.loadDataFile(fileObject)
|
|
68
|
-
|
|
69
|
-
this.#modifiedTimes.set(fileObject.path, lastModified)
|
|
70
|
-
this.#dataCache.set(fileObject.path, data)
|
|
71
|
-
|
|
72
|
-
return data
|
|
73
|
-
}
|
|
74
|
-
}
|