@gesslar/sassy 0.19.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/README.md +605 -0
- package/UNLICENSE.txt +24 -0
- package/package.json +60 -0
- package/src/BuildCommand.js +183 -0
- package/src/Cache.js +73 -0
- package/src/Colour.js +414 -0
- package/src/Command.js +212 -0
- package/src/Compiler.js +310 -0
- package/src/Data.js +545 -0
- package/src/DirectoryObject.js +188 -0
- package/src/Evaluator.js +348 -0
- package/src/File.js +334 -0
- package/src/FileObject.js +226 -0
- package/src/LintCommand.js +498 -0
- package/src/ResolveCommand.js +433 -0
- package/src/Sass.js +165 -0
- package/src/Session.js +360 -0
- package/src/Term.js +175 -0
- package/src/Theme.js +289 -0
- package/src/ThemePool.js +139 -0
- package/src/ThemeToken.js +280 -0
- package/src/Type.js +206 -0
- package/src/Util.js +132 -0
- package/src/Valid.js +50 -0
- package/src/cli.js +155 -0
package/README.md
ADDED
|
@@ -0,0 +1,605 @@
|
|
|
1
|
+
# Sassy - SCSS-Style Theme Engine for VS Code
|
|
2
|
+
|
|
3
|
+
**Transform VS Code theme development from tedious to delightful.**
|
|
4
|
+
|
|
5
|
+
Stop wrestling with 800+ disconnected hex codes. Create beautiful,
|
|
6
|
+
maintainable themes with semantic variables, colour functions, and design
|
|
7
|
+
systems that actually make sense.
|
|
8
|
+
|
|
9
|
+
## The Problem
|
|
10
|
+
|
|
11
|
+
VS Code theme development is a nightmare:
|
|
12
|
+
|
|
13
|
+
- 800+ flat colour properties with zero relationships
|
|
14
|
+
- Want to adjust contrast? Hunt through dozens of files for related colours
|
|
15
|
+
- Copy-paste hex codes everywhere and pray nothing breaks
|
|
16
|
+
- No way to express design intent or maintain consistency
|
|
17
|
+
|
|
18
|
+
## The Solution
|
|
19
|
+
|
|
20
|
+
Write themes like a human, compile for VS Code:
|
|
21
|
+
|
|
22
|
+
**Before (traditional):**
|
|
23
|
+
|
|
24
|
+
```json
|
|
25
|
+
{
|
|
26
|
+
"editor.background": "#1e1e1e",
|
|
27
|
+
"editor.foreground": "#e6e6e6",
|
|
28
|
+
"statusBar.background": "#002e63",
|
|
29
|
+
"panel.background": "#1a1a1a"
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**After (Sassy):**
|
|
34
|
+
|
|
35
|
+
```yaml
|
|
36
|
+
vars:
|
|
37
|
+
accent: "#4b8ebd"
|
|
38
|
+
std:
|
|
39
|
+
fg: "#e6e6e6"
|
|
40
|
+
bg: "#1a1a1a"
|
|
41
|
+
bg.panel: lighten($(std.bg), 15)
|
|
42
|
+
bg.accent: darken($(accent), 15)
|
|
43
|
+
|
|
44
|
+
theme:
|
|
45
|
+
colors:
|
|
46
|
+
"editor.background": $(std.bg.panel)
|
|
47
|
+
"editor.foreground": $(std.fg)
|
|
48
|
+
"statusBar.background": $(std.bg.accent)
|
|
49
|
+
"panel.background": $(std.bg)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Now when you want to adjust contrast, change one variable and watch it
|
|
53
|
+
cascade through your entire theme.
|
|
54
|
+
|
|
55
|
+
## Quick Start
|
|
56
|
+
|
|
57
|
+
No installation needed - use with npx:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
# Create your first theme
|
|
61
|
+
npx @gesslar/sassy build my-theme.yaml
|
|
62
|
+
|
|
63
|
+
# Watch mode for development
|
|
64
|
+
npx @gesslar/sassy build my-theme.yaml --watch
|
|
65
|
+
|
|
66
|
+
# Custom output location
|
|
67
|
+
npx @gesslar/sassy build -o ./themes my-theme.yaml
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## CLI Usage
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
# Basic compilation
|
|
74
|
+
npx @gesslar/sassy build <theme-file>
|
|
75
|
+
|
|
76
|
+
# Multiple files at once
|
|
77
|
+
npx @gesslar/sassy build theme1.yaml theme2.yaml theme3.yaml
|
|
78
|
+
|
|
79
|
+
# Watch for changes (rebuilds automatically)
|
|
80
|
+
npx @gesslar/sassy build --watch my-theme.yaml
|
|
81
|
+
|
|
82
|
+
# Custom output directory
|
|
83
|
+
npx @gesslar/sassy build --output-dir ./my-themes my-theme.yaml
|
|
84
|
+
|
|
85
|
+
# See the compiled JSON without writing files
|
|
86
|
+
npx @gesslar/sassy build --dry-run my-theme.yaml
|
|
87
|
+
|
|
88
|
+
# Silent mode (only show errors)
|
|
89
|
+
npx @gesslar/sassy build --silent my-theme.yaml
|
|
90
|
+
|
|
91
|
+
# Debug mode (detailed error traces)
|
|
92
|
+
npx @gesslar/sassy build --nerd my-theme.yaml
|
|
93
|
+
|
|
94
|
+
# Lint themes for potential issues
|
|
95
|
+
npx @gesslar/sassy lint my-theme.yaml
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Build Command Options
|
|
99
|
+
|
|
100
|
+
| Option | Description |
|
|
101
|
+
|--------|-------------|
|
|
102
|
+
| `-w, --watch` | Watch files and rebuild on changes |
|
|
103
|
+
| `-o, --output-dir <dir>` | Specify output directory |
|
|
104
|
+
| `-n, --dry-run` | Print JSON to stdout instead of writing files |
|
|
105
|
+
| `-s, --silent` | Only show errors (useful for scripts) |
|
|
106
|
+
| `--nerd` | Verbose error mode with stack traces |
|
|
107
|
+
|
|
108
|
+
### Debugging Your Themes
|
|
109
|
+
|
|
110
|
+
**See what a color variable resolves to:**
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
npx @gesslar/sassy resolve --color editor.background my-theme.yaml
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
**Debug tokenColors syntax highlighting:**
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
npx @gesslar/sassy resolve --tokenColor keyword.control my-theme.yaml
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**Debug semantic token colors:**
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
npx @gesslar/sassy resolve --semanticTokenColor variable.readonly my-theme.yaml
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
This shows you the complete resolution chain for any theme property, displaying
|
|
129
|
+
each step of variable substitution and function evaluation with colour-coded
|
|
130
|
+
output.
|
|
131
|
+
|
|
132
|
+
### Resolve Command Options
|
|
133
|
+
|
|
134
|
+
| Option | Description |
|
|
135
|
+
|--------|-------------|
|
|
136
|
+
| `-c, --color <key>` | Resolve a specific color property to its final value |
|
|
137
|
+
| `-t, --tokenColor <scope>` | Resolve tokenColors for a specific scope |
|
|
138
|
+
| `-s, --semanticTokenColor <token>` | Resolve semantic token colors for a specific token type |
|
|
139
|
+
| `--nerd` | Show detailed error traces if resolution fails |
|
|
140
|
+
|
|
141
|
+
### Theme Validation and Linting
|
|
142
|
+
|
|
143
|
+
**Validate your theme for common issues:**
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
npx @gesslar/sassy lint my-theme.yaml
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
The lint command performs comprehensive validation of your theme files to catch
|
|
150
|
+
common issues that could cause unexpected behavior or poor maintainability.
|
|
151
|
+
|
|
152
|
+
### Lint Command Checks
|
|
153
|
+
|
|
154
|
+
The linter performs four types of validation:
|
|
155
|
+
|
|
156
|
+
#### 1. Duplicate Scopes
|
|
157
|
+
|
|
158
|
+
Detects when the same syntax scope appears in multiple tokenColors rules:
|
|
159
|
+
|
|
160
|
+
```yaml
|
|
161
|
+
# ❌ This will trigger a warning
|
|
162
|
+
theme:
|
|
163
|
+
tokenColors:
|
|
164
|
+
- name: "Keywords"
|
|
165
|
+
scope: "keyword.control, keyword.operator"
|
|
166
|
+
settings: { foreground: "$(accent)" }
|
|
167
|
+
- name: "Control Keywords"
|
|
168
|
+
scope: "keyword.control" # Duplicate!
|
|
169
|
+
settings: { foreground: "$(primary)" }
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
**Why this matters:** The second rule will never be applied since the first rule
|
|
173
|
+
already matches `keyword.control` tokens.
|
|
174
|
+
|
|
175
|
+
#### 2. Undefined Variables
|
|
176
|
+
|
|
177
|
+
Catches references to variables that don't exist:
|
|
178
|
+
|
|
179
|
+
```yaml
|
|
180
|
+
# ❌ This will trigger an error
|
|
181
|
+
theme:
|
|
182
|
+
tokenColors:
|
|
183
|
+
- name: "Comments"
|
|
184
|
+
scope: "comment"
|
|
185
|
+
settings: { foreground: "$(nonexistent.variable)" } # Error!
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
#### 3. Unused Variables
|
|
189
|
+
|
|
190
|
+
Identifies variables defined but never used in tokenColors:
|
|
191
|
+
|
|
192
|
+
```yaml
|
|
193
|
+
# ⚠️ This will trigger a warning if never used
|
|
194
|
+
vars:
|
|
195
|
+
scope:
|
|
196
|
+
unused_color: "#ff0000" # Warning if not referenced anywhere
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
**Note:** Only checks variables under `scope.*` since other variables might be
|
|
200
|
+
used in the colors section.
|
|
201
|
+
|
|
202
|
+
#### 4. Precedence Issues
|
|
203
|
+
|
|
204
|
+
Detects when broad scopes mask more specific ones due to rule ordering:
|
|
205
|
+
|
|
206
|
+
```yaml
|
|
207
|
+
# ❌ This will trigger a warning
|
|
208
|
+
theme:
|
|
209
|
+
tokenColors:
|
|
210
|
+
- name: "All Keywords"
|
|
211
|
+
scope: "keyword" # Broad scope
|
|
212
|
+
settings: { foreground: "$(primary)" }
|
|
213
|
+
- name: "Control Keywords"
|
|
214
|
+
scope: "keyword.control" # More specific, but will never match!
|
|
215
|
+
settings: { foreground: "$(accent)" }
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
**Why this matters:** The second rule will never be applied because the first
|
|
219
|
+
rule already matches all `keyword.*` tokens. Reorder rules from most specific
|
|
220
|
+
to least specific.
|
|
221
|
+
|
|
222
|
+
### Lint Command Options
|
|
223
|
+
|
|
224
|
+
| Option | Description |
|
|
225
|
+
|--------|-------------|
|
|
226
|
+
| `--nerd` | Show detailed error traces if linting fails |
|
|
227
|
+
|
|
228
|
+
## Basic Theme Structure
|
|
229
|
+
|
|
230
|
+
```yaml
|
|
231
|
+
# my-awesome-theme.yaml
|
|
232
|
+
config:
|
|
233
|
+
name: "My Awesome Theme"
|
|
234
|
+
type: dark
|
|
235
|
+
|
|
236
|
+
vars:
|
|
237
|
+
# Your colour palette
|
|
238
|
+
primary: "#4b8ebd"
|
|
239
|
+
success: "#4ab792"
|
|
240
|
+
error: "#b74a4a"
|
|
241
|
+
|
|
242
|
+
# Build semantic relationships
|
|
243
|
+
std:
|
|
244
|
+
fg: "#e6e6e6"
|
|
245
|
+
bg: "#1a1a1a"
|
|
246
|
+
accent: $(primary)
|
|
247
|
+
bg.accent: darken($(accent), 15)
|
|
248
|
+
|
|
249
|
+
theme:
|
|
250
|
+
colors:
|
|
251
|
+
# Editor
|
|
252
|
+
"editor.foreground": $(std.fg)
|
|
253
|
+
"editor.background": $(std.bg)
|
|
254
|
+
"editor.selectionBackground": $(std.bg.accent)
|
|
255
|
+
|
|
256
|
+
# UI
|
|
257
|
+
"statusBar.background": $(std.bg.accent)
|
|
258
|
+
"activityBar.background": $(std.bg)
|
|
259
|
+
"sideBar.background": $(std.bg)
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
## Unlimited Colour Freedom
|
|
263
|
+
|
|
264
|
+
Sassy is built on [Culori](https://culorijs.org/), a comprehensive colour
|
|
265
|
+
manipulation library. This means **if Culori supports it, Sassy supports
|
|
266
|
+
it automatically** - no configuration needed.
|
|
267
|
+
|
|
268
|
+
### Beyond the Built-ins
|
|
269
|
+
|
|
270
|
+
While Sassy provides common functions like `lighten()`, `darken()`, and
|
|
271
|
+
`mix()`, you have access to the entire spectrum of colour formats:
|
|
272
|
+
|
|
273
|
+
```yaml
|
|
274
|
+
vars:
|
|
275
|
+
# Use any colour space Culori understands
|
|
276
|
+
lab_colour: lab(50 20 -30) # LAB colour space
|
|
277
|
+
hwb_colour: hwb(180 30% 20%) # HWB (Hue-Whiteness-Blackness)
|
|
278
|
+
lch_colour: lch(70 40 180) # LCH colour space
|
|
279
|
+
p3_colour: color(display-p3 0.4 0.8 0.2) # Display P3 gamut
|
|
280
|
+
rec2020: color(rec2020 0.42 0.85 0.31) # Rec. 2020 colour space
|
|
281
|
+
|
|
282
|
+
# Mix and match freely
|
|
283
|
+
primary: oklch(0.6, 20, 220)
|
|
284
|
+
secondary: mix($(primary), lab(80 -20 40), 30)
|
|
285
|
+
accent: lighten(hwb(240 20% 10%), 15)
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
**The rule is simple:** Write any colour expression that Culori can parse, and
|
|
289
|
+
Sassy will handle it. No need to memorize function lists or check
|
|
290
|
+
compatibility - if it's a valid colour, it works.
|
|
291
|
+
|
|
292
|
+
> **Learn More:** Explore the full range of supported colour formats and
|
|
293
|
+
functions in the [Culori documentation](https://culorijs.org/).
|
|
294
|
+
|
|
295
|
+
## Colour Functions
|
|
296
|
+
|
|
297
|
+
Make colours that work together:
|
|
298
|
+
|
|
299
|
+
| Function | Example | Result |
|
|
300
|
+
|----------|---------|--------|
|
|
301
|
+
| `lighten(colour, %=0-100)` | `lighten($(bg), 25)` | 25% lighter background |
|
|
302
|
+
| `darken(colour, %=0-100)` | `darken($(accent), 30)` | 30% darker accent |
|
|
303
|
+
| || |
|
|
304
|
+
| `alpha(colour, alpha=0-1)` | `alpha($(brand), 0.5)` | Set exact transparency |
|
|
305
|
+
| `fade(colour, alpha=0-1)` | `fade($(accent), 0.5)` | Reduce opacity by 50% |
|
|
306
|
+
| `solidify(colour, alpha=0-1)` | `solidify($(bg.accent), 0.3)` | Increase opacity by 30% |
|
|
307
|
+
| || |
|
|
308
|
+
| `mix(colour1, colour2, %=0-100)` | `mix($(fg), $(accent), 20)` | Blend 20% accent |
|
|
309
|
+
| `mix(colour1, colour2)` | `mix($(fg), $(accent))` | Blend 50% accent |
|
|
310
|
+
| || |
|
|
311
|
+
| `invert(colour)` | `invert($(fg))` | Perfect opposite |
|
|
312
|
+
| || |
|
|
313
|
+
| `hsv(h=0-255, s=0-255, v=0-255)` | `hsv(50, 200, 180)` | HSV colour (hue 50, saturation 200, value 180) |
|
|
314
|
+
| `hsva(h=0-255, s=0-255, v=0-255, a=0-1)` | `hsva(50, 200, 180, 0.5)` | HSV with 50% opacity |
|
|
315
|
+
| || |
|
|
316
|
+
| `hsl(h=0-360, s=0-100, l=0-100)` | `hsl(200, 50, 40)` | HSL colour (200° hue, 50% saturation, 40% lightness) |
|
|
317
|
+
| `hsla(h=0-360, s=0-100, l=0-100, a=0-1)` | `hsla(200, 50, 40, 0.5)` | HSL with 50% opacity |
|
|
318
|
+
| || |
|
|
319
|
+
| `rgb(r=0-255, g=0-255, b=0-255)` | `rgb(139, 152, 255)` | RGB colour (139 red, 152 green, 255 blue) |
|
|
320
|
+
| `rgba(r=0-255, g=0-255, b=0-255, a=0-1)` | `rgba(139, 152, 255, 0.5)` | RGB with 50% opacity |
|
|
321
|
+
| || |
|
|
322
|
+
| `oklch(l=0-1, c=0-100, h=0-360)` | `oklch(0.7, 25, 180)` | OKLCH colour (70% lightness, 25 chroma, 180° hue) |
|
|
323
|
+
| `oklcha(l=0-1, c=0-100, h=0-360, a=0-1)` | `oklcha(0.5, 30, 45, 0.8)` | OKLCH with 80% opacity |
|
|
324
|
+
| || |
|
|
325
|
+
| `css(name)` | `css(tomato)` | CSS named colour (tomato, skyblue, etc.) |
|
|
326
|
+
| || |
|
|
327
|
+
|
|
328
|
+
> **Note:** In all of these functions, `colour` can be a raw hex (`#ff66cc`),
|
|
329
|
+
a variable (`$(accent)`), a CSS named colour (`css(tomato)`), or another colour
|
|
330
|
+
function (`rgba(255, 100, 200, 0.5)`, `darken($(bg), 20)`,
|
|
331
|
+
`oklcha(0.7, 25, 180, 0.8)`).
|
|
332
|
+
|
|
333
|
+
### CSS Named Colours
|
|
334
|
+
|
|
335
|
+
Use CSS colour names with the `css()` function:
|
|
336
|
+
|
|
337
|
+
```yaml
|
|
338
|
+
vars:
|
|
339
|
+
# CSS named colours
|
|
340
|
+
danger: css(crimson)
|
|
341
|
+
ocean: css(deepskyblue)
|
|
342
|
+
nature: css(forestgreen)
|
|
343
|
+
|
|
344
|
+
# Mix named colours with functions
|
|
345
|
+
muted_red: fade(css(tomato), 0.6)
|
|
346
|
+
light_blue: lighten(css(navy), 40)
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
> **Reference:** See the complete list of CSS named colours at [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/CSS/named-color) or [Wikipedia](https://en.wikipedia.org/wiki/Web_colors#HTML_color_names).
|
|
350
|
+
|
|
351
|
+
## Variable Reference
|
|
352
|
+
|
|
353
|
+
Use any of these syntaxes (they're identical):
|
|
354
|
+
|
|
355
|
+
```yaml
|
|
356
|
+
vars:
|
|
357
|
+
accent: "#4b8ebd"
|
|
358
|
+
|
|
359
|
+
# All equivalent:
|
|
360
|
+
variant1: $(accent) # Recommended
|
|
361
|
+
variant2: $accent # Short form
|
|
362
|
+
variant3: ${accent} # Braced form
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
## Theme Development Workflow
|
|
366
|
+
|
|
367
|
+
### 1. Create Your Theme File
|
|
368
|
+
|
|
369
|
+
```bash
|
|
370
|
+
# Create a new theme file
|
|
371
|
+
touch ocean-theme.yaml
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
### 2. Set Up Watch Mode
|
|
375
|
+
|
|
376
|
+
```bash
|
|
377
|
+
# Start watching for changes
|
|
378
|
+
npx @gesslar/sassy build --watch ocean-theme.yaml
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
### 3. Install Your Theme
|
|
382
|
+
|
|
383
|
+
After compilation, you'll get a `.color-theme.json` file:
|
|
384
|
+
|
|
385
|
+
1. **Copy to VS Code**: Place in `~/.vscode/extensions/my-themes/themes/`
|
|
386
|
+
2. **Or package as extension**: Use `yo code` to create a theme extension
|
|
387
|
+
3. **Test immediately**: Press `Ctrl+K Ctrl+T` in VS Code to switch themes
|
|
388
|
+
|
|
389
|
+
### 4. Iterate and Refine
|
|
390
|
+
|
|
391
|
+
With watch mode, every save triggers recompilation. VS Code will
|
|
392
|
+
automatically reload your theme changes.
|
|
393
|
+
|
|
394
|
+
### Output Files
|
|
395
|
+
|
|
396
|
+
Sassy generates standard VS Code theme files:
|
|
397
|
+
|
|
398
|
+
```bash
|
|
399
|
+
my-theme.yaml → my-theme.color-theme.json
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
The output file name is based on your input file, with `.color-theme.json`
|
|
403
|
+
extension.
|
|
404
|
+
|
|
405
|
+
## Advanced Features
|
|
406
|
+
|
|
407
|
+
### Modular Theme Design
|
|
408
|
+
|
|
409
|
+
Break your themes into reusable components using the import system:
|
|
410
|
+
|
|
411
|
+
```yaml
|
|
412
|
+
# colours.yaml
|
|
413
|
+
vars:
|
|
414
|
+
palette:
|
|
415
|
+
primary: "#4b8ebd"
|
|
416
|
+
success: "#4ab792"
|
|
417
|
+
error: "#b74a4a"
|
|
418
|
+
warning: "#b36b47"
|
|
419
|
+
|
|
420
|
+
---
|
|
421
|
+
|
|
422
|
+
# my-theme.yaml
|
|
423
|
+
config:
|
|
424
|
+
name: "My Theme"
|
|
425
|
+
type: dark
|
|
426
|
+
imports:
|
|
427
|
+
vars:
|
|
428
|
+
colors: "./colours.yaml"
|
|
429
|
+
|
|
430
|
+
vars:
|
|
431
|
+
# Use imported colours
|
|
432
|
+
accent: $(colors.palette.primary)
|
|
433
|
+
|
|
434
|
+
# Build your design system
|
|
435
|
+
std:
|
|
436
|
+
fg: "#e6e6e6"
|
|
437
|
+
bg: "#1a1a1a"
|
|
438
|
+
accent: $(accent)
|
|
439
|
+
bg.accent: darken($(accent), 15)
|
|
440
|
+
|
|
441
|
+
theme:
|
|
442
|
+
colors:
|
|
443
|
+
"editor.foreground": $(std.fg)
|
|
444
|
+
"editor.background": $(std.bg)
|
|
445
|
+
"statusBar.background": $(std.bg.accent)
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
### Import System
|
|
449
|
+
|
|
450
|
+
Sassy supports importing different types of theme components:
|
|
451
|
+
|
|
452
|
+
```yaml
|
|
453
|
+
config:
|
|
454
|
+
imports:
|
|
455
|
+
# Import variables (merged into your vars section)
|
|
456
|
+
vars:
|
|
457
|
+
colors: "./shared/colours.yaml"
|
|
458
|
+
# Can import multiple files
|
|
459
|
+
typography: ["./shared/fonts.yaml", "./shared/sizes.yaml"]
|
|
460
|
+
|
|
461
|
+
# Import global configuration
|
|
462
|
+
global:
|
|
463
|
+
base: "./shared/base-config.yaml"
|
|
464
|
+
|
|
465
|
+
# Import VS Code colour definitions
|
|
466
|
+
colors:
|
|
467
|
+
ui: "./shared/ui-colours.yaml"
|
|
468
|
+
|
|
469
|
+
# Import syntax highlighting rules
|
|
470
|
+
tokenColors:
|
|
471
|
+
syntax: "./shared/syntax.yaml"
|
|
472
|
+
|
|
473
|
+
# Import semantic token colours
|
|
474
|
+
semanticTokenColors:
|
|
475
|
+
semantic: "./shared/semantic.yaml"
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
**Import Format Options:**
|
|
479
|
+
|
|
480
|
+
- **Single file:** `"./path/to/file.yaml"`
|
|
481
|
+
- **Multiple files:** `["./file1.yaml", "./file2.yaml"]`
|
|
482
|
+
- **File types:** Both `.yaml` and `.json5` are supported
|
|
483
|
+
|
|
484
|
+
**Merge Order:**
|
|
485
|
+
|
|
486
|
+
The merge happens in a precise order with each level overriding the previous:
|
|
487
|
+
|
|
488
|
+
1. `global` imports (merged first)
|
|
489
|
+
2. `colors` imports
|
|
490
|
+
3. `tokenColors` imports
|
|
491
|
+
4. `semanticTokenColors` imports
|
|
492
|
+
5. Your theme file's own definitions (final override)
|
|
493
|
+
|
|
494
|
+
Within each section, if you import multiple files, they merge in array order.
|
|
495
|
+
This layered approach gives you fine-grained control over which definitions
|
|
496
|
+
take precedence.
|
|
497
|
+
|
|
498
|
+
### Watch Mode for Development
|
|
499
|
+
|
|
500
|
+
Perfect for theme development - see changes instantly:
|
|
501
|
+
|
|
502
|
+
```bash
|
|
503
|
+
npx @gesslar/sassy build my-theme.yaml --watch
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
Now edit your YAML file and watch VS Code update automatically!
|
|
507
|
+
|
|
508
|
+
## Tips for Great Themes
|
|
509
|
+
|
|
510
|
+
### Start with Meaning, Not Colours
|
|
511
|
+
|
|
512
|
+
```yaml
|
|
513
|
+
# ❌ Don't start with random colours
|
|
514
|
+
vars:
|
|
515
|
+
red: "#ff0000"
|
|
516
|
+
blue: "#0000ff"
|
|
517
|
+
|
|
518
|
+
# ✅ Start with semantic meaning
|
|
519
|
+
vars:
|
|
520
|
+
status:
|
|
521
|
+
error: "#b74a4a"
|
|
522
|
+
success: "#4ab792"
|
|
523
|
+
|
|
524
|
+
ui:
|
|
525
|
+
background: "#1a1a1a"
|
|
526
|
+
surface: lighten($(ui.background), 15)
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
### Use Mathematical Relationships
|
|
530
|
+
|
|
531
|
+
```yaml
|
|
532
|
+
# Colours that harmonize automatically
|
|
533
|
+
vars:
|
|
534
|
+
base: "#4b8ebd"
|
|
535
|
+
|
|
536
|
+
harmonies:
|
|
537
|
+
lighter: lighten($(base), 20)
|
|
538
|
+
darker: darken($(base), 20)
|
|
539
|
+
complement: mix($(base), invert($(base)), 50)
|
|
540
|
+
muted: mix($(base), "#808080", 30)
|
|
541
|
+
|
|
542
|
+
# OKLCH colours for perceptually uniform adjustments
|
|
543
|
+
oklch_palette:
|
|
544
|
+
primary: oklch(0.6, 20, 220) # Blue with controlled chroma
|
|
545
|
+
accent: oklch(0.7, 25, 45) # Warm orange complement
|
|
546
|
+
muted: oklch(0.5, 8, 220) # Desaturated blue
|
|
547
|
+
bright: oklcha(0.8, 30, 220, 0.9) # Bright blue with transparency
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
### Test with Real Code
|
|
551
|
+
|
|
552
|
+
Always test your themes with actual code files to see how syntax
|
|
553
|
+
highlighting looks with your colour choices.
|
|
554
|
+
|
|
555
|
+
## More Examples
|
|
556
|
+
|
|
557
|
+
Check out the `/examples` folder for complete theme files showing
|
|
558
|
+
different approaches and techniques.
|
|
559
|
+
|
|
560
|
+
## Troubleshooting
|
|
561
|
+
|
|
562
|
+
### Common Issues
|
|
563
|
+
|
|
564
|
+
**Theme not appearing in VS Code:**
|
|
565
|
+
|
|
566
|
+
- Check that the output file ends with `.color-theme.json`
|
|
567
|
+
- Verify the file is in your extensions themes folder
|
|
568
|
+
- Try reloading VS Code (`Ctrl+Shift+P` → "Developer: Reload Window")
|
|
569
|
+
|
|
570
|
+
**Compilation errors:**
|
|
571
|
+
|
|
572
|
+
```bash
|
|
573
|
+
# See detailed error information
|
|
574
|
+
npx @gesslar/sassy build --nerd my-theme.yaml
|
|
575
|
+
|
|
576
|
+
# Check what a specific variable resolves to
|
|
577
|
+
npx @gesslar/sassy resolve --token problematic.variable my-theme.yaml
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
**Variables not resolving:**
|
|
581
|
+
|
|
582
|
+
- Check variable names for typos
|
|
583
|
+
- Use the resolve command to trace dependency chains
|
|
584
|
+
- Look for circular references (variables referencing themselves)
|
|
585
|
+
|
|
586
|
+
**Watch mode not updating:**
|
|
587
|
+
|
|
588
|
+
- Check that files aren't being saved outside the watched directory
|
|
589
|
+
- Try restarting watch mode
|
|
590
|
+
- Verify file permissions
|
|
591
|
+
|
|
592
|
+
## Getting Help
|
|
593
|
+
|
|
594
|
+
- **Examples**: Complete theme files in the `/examples` directory
|
|
595
|
+
- **Issues**: Report bugs or request features on GitHub
|
|
596
|
+
- **Community**: Share your themes and get feedback
|
|
597
|
+
|
|
598
|
+
## License
|
|
599
|
+
|
|
600
|
+
**The Unlicense** - Use this however you want! The idea of copyrighting colour
|
|
601
|
+
arrangements is absurd.
|
|
602
|
+
|
|
603
|
+
---
|
|
604
|
+
|
|
605
|
+
*Make gorgeous themes that speak as boldly as you do.*
|
package/UNLICENSE.txt
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
This is free and unencumbered software released into the public domain.
|
|
2
|
+
|
|
3
|
+
Anyone is free to copy, modify, publish, use, compile, sell, or
|
|
4
|
+
distribute this software, either in source code form or as a compiled
|
|
5
|
+
binary, for any purpose, commercial or non-commercial, and by any
|
|
6
|
+
means.
|
|
7
|
+
|
|
8
|
+
In jurisdictions that recognize copyright laws, the author or authors
|
|
9
|
+
of this software dedicate any and all copyright interest in the
|
|
10
|
+
software to the public domain. We make this dedication for the benefit
|
|
11
|
+
of the public at large and to the detriment of our heirs and
|
|
12
|
+
successors. We intend this dedication to be an overt act of
|
|
13
|
+
relinquishment in perpetuity of all present and future rights to this
|
|
14
|
+
software under copyright law.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
19
|
+
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
20
|
+
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
21
|
+
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
|
23
|
+
|
|
24
|
+
For more information, please refer to <https://unlicense.org>
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@gesslar/sassy",
|
|
3
|
+
"version": "0.19.0",
|
|
4
|
+
"displayName": "Sassy",
|
|
5
|
+
"description": "Make gorgeous themes that speak as boldly as you do.",
|
|
6
|
+
"publisher": "gesslar",
|
|
7
|
+
"license": "Unlicense",
|
|
8
|
+
"type": "module",
|
|
9
|
+
"main": "src/cli.js",
|
|
10
|
+
"bin": "src/cli.js",
|
|
11
|
+
"files": [
|
|
12
|
+
"src/",
|
|
13
|
+
"UNLICENSE.txt"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"clean": "rm -rfv ./dist",
|
|
17
|
+
"build": "npm run clean && mkdir -pv ./dist && npm pack --pack-destination ./dist/",
|
|
18
|
+
"exec": "node ./src/cli.js",
|
|
19
|
+
"lint": "eslint src/",
|
|
20
|
+
"submit": "npm publish --access public",
|
|
21
|
+
"examples": "node ./examples/validator.js",
|
|
22
|
+
"test": "node -p \"require('fs').readFileSync('TESTING.txt', 'utf8')\""
|
|
23
|
+
},
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=20.0.0"
|
|
26
|
+
},
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "https://github.com/gesslar/sassy"
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"asmr",
|
|
33
|
+
"generator",
|
|
34
|
+
"huffing",
|
|
35
|
+
"json5",
|
|
36
|
+
"sniffsniffsniff",
|
|
37
|
+
"taylorswift",
|
|
38
|
+
"theme",
|
|
39
|
+
"vs code",
|
|
40
|
+
"vscode",
|
|
41
|
+
"yaml"
|
|
42
|
+
],
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@gesslar/colours": "^0.0.1",
|
|
45
|
+
"chokidar": "^4.0.3",
|
|
46
|
+
"color-support": "^1.1.3",
|
|
47
|
+
"commander": "^14.0.0",
|
|
48
|
+
"culori": "^4.0.2",
|
|
49
|
+
"globby": "^14.1.0",
|
|
50
|
+
"json5": "^2.2.3",
|
|
51
|
+
"yaml": "^2.8.1"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@stylistic/eslint-plugin": "^5.2.3",
|
|
55
|
+
"@typescript-eslint/eslint-plugin": "^8.33.0",
|
|
56
|
+
"@typescript-eslint/parser": "^8.33.0",
|
|
57
|
+
"eslint": "^9.28.0",
|
|
58
|
+
"eslint-plugin-jsdoc": "^50.6.17"
|
|
59
|
+
}
|
|
60
|
+
}
|