themebooth 0.2.0 → 0.3.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.
@@ -0,0 +1,689 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.validateCommand = validateCommand;
37
+ const fs = __importStar(require("fs/promises"));
38
+ const path = __importStar(require("path"));
39
+ const logger_1 = require("../utils/logger");
40
+ const manifest_1 = require("../core/manifest");
41
+ const validation_1 = require("../utils/validation");
42
+ const colors_1 = require("../core/colors");
43
+ const schemas_1 = require("../core/schemas");
44
+ const vscode_1 = require("../exporters/vscode");
45
+ const zed_1 = require("../exporters/zed");
46
+ const notepad_plus_1 = require("../exporters/notepad-plus");
47
+ async function validateCommand(manifestPath, options = {}) {
48
+ const resolvedPath = path.resolve(manifestPath || "./manifest.json");
49
+ try {
50
+ const content = await fs.readFile(resolvedPath, "utf-8");
51
+ const errors = [];
52
+ const warnings = [];
53
+ const conversions = [];
54
+ let manifest;
55
+ // Parse JSON
56
+ const parseResult = (0, validation_1.parseManifestJSON)(content);
57
+ if (!parseResult.success) {
58
+ if (options.ci) {
59
+ console.log(JSON.stringify({
60
+ valid: false,
61
+ errors: [parseResult.error],
62
+ warnings: [],
63
+ stats: getStats(undefined),
64
+ }, null, 2));
65
+ }
66
+ else {
67
+ logger_1.logger.error("manifest.json invalid (1 error)");
68
+ console.log(`\n ERROR [line ${parseResult.error.line}, col ${parseResult.error.column}]: ${parseResult.error.message}`);
69
+ if (parseResult.error.suggestion) {
70
+ console.log(` ${parseResult.error.suggestion}`);
71
+ }
72
+ }
73
+ process.exit(1);
74
+ }
75
+ // Pre-validate and normalize colors before schema validation
76
+ const preValidationData = JSON.parse(JSON.stringify(parseResult.data));
77
+ normalizeColorsInManifest(preValidationData, conversions);
78
+ // Validate schema
79
+ const schemaValidation = (0, manifest_1.validateManifest)(preValidationData);
80
+ if (!schemaValidation.success) {
81
+ schemaValidation.errors.forEach((err) => {
82
+ errors.push({
83
+ severity: "error",
84
+ field: err.field || "unknown",
85
+ message: err.message,
86
+ });
87
+ });
88
+ }
89
+ else {
90
+ manifest = schemaValidation.data;
91
+ // Validate colors with conversion
92
+ const colorErrors = validateColors(manifest, conversions);
93
+ errors.push(...colorErrors.errors);
94
+ warnings.push(...colorErrors.warnings);
95
+ // Validate variables
96
+ const varErrors = validateVariables(manifest);
97
+ errors.push(...varErrors.errors);
98
+ warnings.push(...varErrors.warnings);
99
+ // Validate computed colors
100
+ const computedErrors = validateComputedColors(manifest);
101
+ errors.push(...computedErrors);
102
+ // Validate tokens
103
+ const tokenErrors = validateTokens(manifest);
104
+ errors.push(...tokenErrors);
105
+ // Validate semantic tokens
106
+ const semanticErrors = validateSemanticTokens(manifest);
107
+ errors.push(...semanticErrors);
108
+ // Validate language tokens
109
+ const languageErrors = validateLanguageTokens(manifest);
110
+ errors.push(...languageErrors);
111
+ // Validate presets
112
+ const presetErrors = validatePresets(manifest);
113
+ errors.push(...presetErrors);
114
+ // Validate extends
115
+ if (manifest.extends) {
116
+ const extendsErrors = await validateExtends(manifest.extends, resolvedPath);
117
+ errors.push(...extendsErrors);
118
+ }
119
+ // Dry-run exporter validation
120
+ const exporterErrors = validateExporters(manifest);
121
+ errors.push(...exporterErrors);
122
+ }
123
+ // Generate output
124
+ if (options.ci) {
125
+ const output = {
126
+ valid: errors.length === 0,
127
+ errors,
128
+ warnings,
129
+ stats: getStats(manifest),
130
+ };
131
+ if (conversions.length > 0) {
132
+ output.conversions = conversions;
133
+ }
134
+ console.log(JSON.stringify(output, null, 2));
135
+ }
136
+ else {
137
+ printValidationResult(errors, warnings, manifest, conversions, options.fix);
138
+ }
139
+ // Apply fixes if requested
140
+ if (options.fix && conversions.length > 0) {
141
+ // preValidationData already has conversions applied
142
+ await fs.writeFile(resolvedPath, JSON.stringify(preValidationData, null, 2) + "\n");
143
+ if (!options.ci) {
144
+ logger_1.logger.success(`manifest.json fixed (${conversions.length} conversions)`);
145
+ conversions.forEach((c) => {
146
+ console.log(` • ${c.field}: ${c.from} → ${c.to}`);
147
+ });
148
+ console.log(` Written back to manifest.json`);
149
+ }
150
+ }
151
+ // Exit with appropriate code
152
+ if (errors.length > 0) {
153
+ process.exit(1);
154
+ }
155
+ else if (warnings.length > 0) {
156
+ process.exit(2);
157
+ }
158
+ }
159
+ catch (error) {
160
+ if (options.ci) {
161
+ console.log(JSON.stringify({
162
+ valid: false,
163
+ errors: [
164
+ {
165
+ severity: "error",
166
+ field: "manifest.json",
167
+ message: `Failed to read manifest: ${error instanceof Error ? error.message : String(error)}`,
168
+ },
169
+ ],
170
+ warnings: [],
171
+ stats: getStats(undefined),
172
+ }, null, 2));
173
+ }
174
+ else {
175
+ logger_1.logger.error(`Failed to read manifest: ${error instanceof Error ? error.message : String(error)}`);
176
+ }
177
+ process.exit(1);
178
+ }
179
+ }
180
+ function validateColors(manifest, conversions) {
181
+ const errors = [];
182
+ const warnings = [];
183
+ if (!manifest.colors)
184
+ return { errors, warnings };
185
+ Object.entries(manifest.colors).forEach(([key, value]) => {
186
+ if (value === null)
187
+ return;
188
+ // Skip variable references
189
+ if (value.startsWith("$")) {
190
+ return;
191
+ }
192
+ // Try to parse and normalize
193
+ const result = (0, colors_1.parseAndNormalizeColor)(value);
194
+ if (result) {
195
+ if (result.changes.length > 0) {
196
+ conversions.push({
197
+ line: 0, // TODO: get actual line number from source
198
+ field: `colors.${key}`,
199
+ from: value,
200
+ to: result.hex,
201
+ });
202
+ }
203
+ }
204
+ else {
205
+ const format = (0, colors_1.validateColorFormat)(value);
206
+ if (!format.valid) {
207
+ errors.push({
208
+ severity: "error",
209
+ field: `colors.${key}`,
210
+ message: `Invalid color format "${value}"`,
211
+ suggestion: format.suggestion || "Use #RRGGBB, rgb(r,g,b), or $variableName",
212
+ });
213
+ }
214
+ }
215
+ });
216
+ return { errors, warnings };
217
+ }
218
+ function validateVariables(manifest) {
219
+ const errors = [];
220
+ const warnings = [];
221
+ if (!manifest.variables)
222
+ return { errors, warnings };
223
+ // Check for circular dependencies
224
+ const visited = new Set();
225
+ const recStack = new Set();
226
+ const hasCycle = (varName) => {
227
+ visited.add(varName);
228
+ recStack.add(varName);
229
+ const refs = (0, schemas_1.extractVariableReferences)(String(manifest.variables[varName]));
230
+ for (const ref of refs) {
231
+ if (!visited.has(ref)) {
232
+ if (hasCycle(ref)) {
233
+ return true;
234
+ }
235
+ }
236
+ else if (recStack.has(ref)) {
237
+ return true;
238
+ }
239
+ }
240
+ recStack.delete(varName);
241
+ return false;
242
+ };
243
+ for (const varName of Object.keys(manifest.variables)) {
244
+ visited.clear();
245
+ recStack.clear();
246
+ if (hasCycle(varName)) {
247
+ errors.push({
248
+ severity: "error",
249
+ field: `variables.${varName}`,
250
+ message: `Circular variable dependency detected`,
251
+ suggestion: "Break the reference cycle in your variable definitions",
252
+ });
253
+ }
254
+ }
255
+ // Check for unused variables
256
+ const usedVars = new Set();
257
+ // Collect all references from colors
258
+ if (manifest.colors) {
259
+ Object.values(manifest.colors).forEach((val) => {
260
+ if (val) {
261
+ (0, schemas_1.extractVariableReferences)(String(val)).forEach((v) => usedVars.add(v));
262
+ }
263
+ });
264
+ }
265
+ // Collect from tokens
266
+ if (manifest.tokens) {
267
+ Object.values(manifest.tokens).forEach((settings) => {
268
+ Object.values(settings).forEach((val) => {
269
+ (0, schemas_1.extractVariableReferences)(String(val)).forEach((v) => usedVars.add(v));
270
+ });
271
+ });
272
+ }
273
+ // Collect from semantic tokens
274
+ if (manifest.semanticTokens) {
275
+ Object.values(manifest.semanticTokens).forEach((settings) => {
276
+ Object.values(settings).forEach((val) => {
277
+ (0, schemas_1.extractVariableReferences)(String(val)).forEach((v) => usedVars.add(v));
278
+ });
279
+ });
280
+ }
281
+ // Collect from language tokens
282
+ if (manifest.languageTokens) {
283
+ Object.values(manifest.languageTokens).forEach((langTokens) => {
284
+ Object.values(langTokens).forEach((settings) => {
285
+ Object.values(settings).forEach((val) => {
286
+ (0, schemas_1.extractVariableReferences)(String(val)).forEach((v) => usedVars.add(v));
287
+ });
288
+ });
289
+ });
290
+ }
291
+ // Collect from presets
292
+ if (manifest.presets) {
293
+ Object.values(manifest.presets).forEach((preset) => {
294
+ if (preset.variableOverrides) {
295
+ Object.values(preset.variableOverrides).forEach((val) => {
296
+ (0, schemas_1.extractVariableReferences)(String(val)).forEach((v) => usedVars.add(v));
297
+ });
298
+ }
299
+ });
300
+ }
301
+ // Check unused
302
+ for (const varName of Object.keys(manifest.variables)) {
303
+ if (!usedVars.has(varName)) {
304
+ warnings.push({
305
+ severity: "warning",
306
+ field: `variables.${varName}`,
307
+ message: `Unused variable $${varName}`,
308
+ suggestion: "Safe to remove if not needed",
309
+ });
310
+ }
311
+ }
312
+ return { errors, warnings };
313
+ }
314
+ function validateComputedColors(manifest) {
315
+ const errors = [];
316
+ if (!manifest.computed)
317
+ return errors;
318
+ Object.entries(manifest.computed).forEach(([name, entry]) => {
319
+ // Validate base
320
+ if (entry.base.startsWith("$")) {
321
+ if (!manifest.variables?.[entry.base.slice(1)]) {
322
+ errors.push({
323
+ severity: "error",
324
+ field: `computed.${name}`,
325
+ message: `Base variable ${entry.base} is undefined`,
326
+ });
327
+ }
328
+ }
329
+ else if (!(0, colors_1.parseAndNormalizeColor)(entry.base)) {
330
+ errors.push({
331
+ severity: "error",
332
+ field: `computed.${name}`,
333
+ message: `Base color ${entry.base} has invalid format`,
334
+ });
335
+ }
336
+ // Validate transform
337
+ if (!["darken", "lighten", "alpha"].includes(entry.transform)) {
338
+ errors.push({
339
+ severity: "error",
340
+ field: `computed.${name}`,
341
+ message: `Invalid transform "${entry.transform}". Use: darken, lighten, alpha`,
342
+ });
343
+ }
344
+ // Validate amount
345
+ if (entry.amount < 0 || entry.amount > 100) {
346
+ errors.push({
347
+ severity: "error",
348
+ field: `computed.${name}`,
349
+ message: `Amount must be 0-100, got ${entry.amount}`,
350
+ });
351
+ }
352
+ });
353
+ return errors;
354
+ }
355
+ function validateTokens(manifest) {
356
+ const errors = [];
357
+ if (!manifest.tokens)
358
+ return errors;
359
+ Object.entries(manifest.tokens).forEach(([scope, settings]) => {
360
+ validateTokenProperties(scope, settings, "tokens", errors);
361
+ });
362
+ return errors;
363
+ }
364
+ function validateSemanticTokens(manifest) {
365
+ const errors = [];
366
+ if (!manifest.semanticTokens)
367
+ return errors;
368
+ Object.entries(manifest.semanticTokens).forEach(([scope, settings]) => {
369
+ validateTokenProperties(scope, settings, "semanticTokens", errors);
370
+ });
371
+ return errors;
372
+ }
373
+ function validateLanguageTokens(manifest) {
374
+ const errors = [];
375
+ if (!manifest.languageTokens)
376
+ return errors;
377
+ Object.entries(manifest.languageTokens).forEach(([language, langTokens]) => {
378
+ Object.entries(langTokens).forEach(([scope, settings]) => {
379
+ validateTokenProperties(scope, settings, `languageTokens.${language}`, errors);
380
+ });
381
+ });
382
+ return errors;
383
+ }
384
+ function validateTokenProperties(scope, settings, prefix, errors) {
385
+ Object.entries(settings).forEach(([prop, value]) => {
386
+ const strVal = String(value);
387
+ // Check foreground/background colors
388
+ if ((prop === "foreground" || prop === "background") && !strVal.startsWith("$")) {
389
+ const result = (0, colors_1.parseAndNormalizeColor)(strVal);
390
+ if (!result) {
391
+ errors.push({
392
+ severity: "error",
393
+ field: `${prefix}.${scope}.${prop}`,
394
+ message: `Invalid color format "${strVal}"`,
395
+ });
396
+ }
397
+ }
398
+ // Check fontStyle - can be single or space-separated multiple
399
+ if (prop === "fontStyle" && strVal !== "") {
400
+ const styles = strVal.split(/\s+/);
401
+ const invalid = styles.filter((s) => !["bold", "italic", "underline"].includes(s));
402
+ if (invalid.length > 0) {
403
+ errors.push({
404
+ severity: "error",
405
+ field: `${prefix}.${scope}.${prop}`,
406
+ message: `Invalid fontStyle "${strVal}". Use: bold, italic, underline (can combine)`,
407
+ });
408
+ }
409
+ }
410
+ // Check fontWeight
411
+ if (prop === "fontWeight") {
412
+ const weight = parseInt(strVal, 10);
413
+ if (!["normal", "bold"].includes(strVal) &&
414
+ (isNaN(weight) || weight < 100 || weight > 900 || weight % 100 !== 0)) {
415
+ errors.push({
416
+ severity: "error",
417
+ field: `${prefix}.${scope}.${prop}`,
418
+ message: `Invalid fontWeight "${strVal}". Use: normal, bold, or 100-900`,
419
+ });
420
+ }
421
+ }
422
+ // Check opacity
423
+ if (prop === "opacity") {
424
+ const opacity = parseFloat(strVal);
425
+ if (isNaN(opacity) || opacity < 0 || opacity > 1) {
426
+ errors.push({
427
+ severity: "error",
428
+ field: `${prefix}.${scope}.${prop}`,
429
+ message: `Opacity must be 0-1, got ${strVal}`,
430
+ });
431
+ }
432
+ }
433
+ });
434
+ }
435
+ function validatePresets(manifest) {
436
+ const errors = [];
437
+ if (!manifest.presets)
438
+ return errors;
439
+ Object.entries(manifest.presets).forEach(([presetName, preset]) => {
440
+ // Validate variable overrides reference defined variables
441
+ if (preset.variableOverrides) {
442
+ Object.keys(preset.variableOverrides).forEach((varName) => {
443
+ if (!manifest.variables?.[varName]) {
444
+ errors.push({
445
+ severity: "error",
446
+ field: `presets.${presetName}`,
447
+ message: `Preset references undefined variable $${varName}`,
448
+ suggestion: `Define $${varName} in variables section`,
449
+ });
450
+ }
451
+ });
452
+ }
453
+ });
454
+ return errors;
455
+ }
456
+ async function validateExtends(extendsPath, manifestPath) {
457
+ const errors = [];
458
+ const resolvedExtends = path.resolve(path.dirname(manifestPath), extendsPath);
459
+ try {
460
+ await fs.stat(resolvedExtends);
461
+ }
462
+ catch {
463
+ errors.push({
464
+ severity: "error",
465
+ field: "extends",
466
+ message: `Extends file not found: ${extendsPath}`,
467
+ suggestion: `Check the path relative to manifest location`,
468
+ });
469
+ }
470
+ return errors;
471
+ }
472
+ function applyColorConversions(data, conversions) {
473
+ const result = JSON.parse(JSON.stringify(data));
474
+ conversions.forEach((conv) => {
475
+ const parts = conv.field.split(".");
476
+ let obj = result;
477
+ for (let i = 0; i < parts.length - 1; i++) {
478
+ obj = obj[parts[i]];
479
+ }
480
+ obj[parts[parts.length - 1]] = conv.to;
481
+ });
482
+ return result;
483
+ }
484
+ function getStats(manifest) {
485
+ return {
486
+ variables: Object.keys(manifest?.variables || {}).length,
487
+ colors: Object.keys(manifest?.colors || {}).length,
488
+ tokens: Object.keys(manifest?.tokens || {}).length,
489
+ semanticTokens: Object.keys(manifest?.semanticTokens || {}).length,
490
+ languageTokens: Object.keys(manifest?.languageTokens || {}).length,
491
+ presets: Object.keys(manifest?.presets || {}).length,
492
+ extends: !!manifest?.extends,
493
+ computed: Object.keys(manifest?.computed || {}).length,
494
+ colorConversions: 0,
495
+ };
496
+ }
497
+ function normalizeColorsInManifest(data, conversions) {
498
+ // Normalize variables
499
+ if (data.variables) {
500
+ Object.entries(data.variables).forEach(([key, value]) => {
501
+ if (typeof value === "string" && !value.startsWith("$")) {
502
+ const result = (0, colors_1.parseAndNormalizeColor)(value);
503
+ if (result && result.changes.length > 0) {
504
+ conversions.push({
505
+ line: 0,
506
+ field: `variables.${key}`,
507
+ from: value,
508
+ to: result.hex,
509
+ });
510
+ data.variables[key] = result.hex;
511
+ }
512
+ }
513
+ });
514
+ }
515
+ // Normalize colors
516
+ if (data.colors) {
517
+ Object.entries(data.colors).forEach(([key, value]) => {
518
+ if (value !== null && typeof value === "string" && !value.startsWith("$")) {
519
+ const result = (0, colors_1.parseAndNormalizeColor)(value);
520
+ if (result && result.changes.length > 0) {
521
+ conversions.push({
522
+ line: 0,
523
+ field: `colors.${key}`,
524
+ from: value,
525
+ to: result.hex,
526
+ });
527
+ data.colors[key] = result.hex;
528
+ }
529
+ }
530
+ });
531
+ }
532
+ // Normalize tokens
533
+ if (data.tokens) {
534
+ Object.entries(data.tokens).forEach(([scope, settings]) => {
535
+ Object.entries(settings).forEach(([prop, value]) => {
536
+ if (typeof value === "string" &&
537
+ (prop === "foreground" || prop === "background") &&
538
+ !value.startsWith("$")) {
539
+ const result = (0, colors_1.parseAndNormalizeColor)(value);
540
+ if (result && result.changes.length > 0) {
541
+ conversions.push({
542
+ line: 0,
543
+ field: `tokens.${scope}.${prop}`,
544
+ from: value,
545
+ to: result.hex,
546
+ });
547
+ data.tokens[scope][prop] = result.hex;
548
+ }
549
+ }
550
+ });
551
+ });
552
+ }
553
+ // Normalize semanticTokens
554
+ if (data.semanticTokens) {
555
+ Object.entries(data.semanticTokens).forEach(([scope, settings]) => {
556
+ Object.entries(settings).forEach(([prop, value]) => {
557
+ if (typeof value === "string" &&
558
+ (prop === "foreground" || prop === "background") &&
559
+ !value.startsWith("$")) {
560
+ const result = (0, colors_1.parseAndNormalizeColor)(value);
561
+ if (result && result.changes.length > 0) {
562
+ conversions.push({
563
+ line: 0,
564
+ field: `semanticTokens.${scope}.${prop}`,
565
+ from: value,
566
+ to: result.hex,
567
+ });
568
+ data.semanticTokens[scope][prop] = result.hex;
569
+ }
570
+ }
571
+ });
572
+ });
573
+ }
574
+ // Normalize languageTokens
575
+ if (data.languageTokens) {
576
+ Object.entries(data.languageTokens).forEach(([lang, langTokens]) => {
577
+ Object.entries(langTokens).forEach(([scope, settings]) => {
578
+ Object.entries(settings).forEach(([prop, value]) => {
579
+ if (typeof value === "string" &&
580
+ (prop === "foreground" || prop === "background") &&
581
+ !value.startsWith("$")) {
582
+ const result = (0, colors_1.parseAndNormalizeColor)(value);
583
+ if (result && result.changes.length > 0) {
584
+ conversions.push({
585
+ line: 0,
586
+ field: `languageTokens.${lang}.${scope}.${prop}`,
587
+ from: value,
588
+ to: result.hex,
589
+ });
590
+ data.languageTokens[lang][scope][prop] = result.hex;
591
+ }
592
+ }
593
+ });
594
+ });
595
+ });
596
+ }
597
+ // Normalize presets
598
+ if (data.presets) {
599
+ Object.entries(data.presets).forEach(([presetName, preset]) => {
600
+ if (preset.variableOverrides) {
601
+ Object.entries(preset.variableOverrides).forEach(([varName, value]) => {
602
+ if (typeof value === "string" && !value.startsWith("$")) {
603
+ const result = (0, colors_1.parseAndNormalizeColor)(value);
604
+ if (result && result.changes.length > 0) {
605
+ conversions.push({
606
+ line: 0,
607
+ field: `presets.${presetName}.variableOverrides.${varName}`,
608
+ from: value,
609
+ to: result.hex,
610
+ });
611
+ data.presets[presetName].variableOverrides[varName] = result.hex;
612
+ }
613
+ }
614
+ });
615
+ }
616
+ });
617
+ }
618
+ }
619
+ function validateExporters(manifest) {
620
+ const errors = [];
621
+ try {
622
+ (0, vscode_1.exportVSCode)(manifest);
623
+ }
624
+ catch (error) {
625
+ errors.push({
626
+ severity: "error",
627
+ field: "exporters.vscode",
628
+ message: `VS Code export failed: ${error instanceof Error ? error.message : String(error)}`,
629
+ });
630
+ }
631
+ try {
632
+ (0, zed_1.exportZed)(manifest);
633
+ }
634
+ catch (error) {
635
+ errors.push({
636
+ severity: "error",
637
+ field: "exporters.zed",
638
+ message: `Zed export failed: ${error instanceof Error ? error.message : String(error)}`,
639
+ });
640
+ }
641
+ try {
642
+ (0, notepad_plus_1.exportNotepadPlus)(manifest);
643
+ }
644
+ catch (error) {
645
+ errors.push({
646
+ severity: "error",
647
+ field: "exporters.notepad++",
648
+ message: `Notepad++ export failed: ${error instanceof Error ? error.message : String(error)}`,
649
+ });
650
+ }
651
+ return errors;
652
+ }
653
+ function printValidationResult(errors, warnings, manifest, conversions, isFixing) {
654
+ if (errors.length === 0 && warnings.length === 0) {
655
+ const stats = getStats(manifest);
656
+ logger_1.logger.success("manifest.json valid");
657
+ console.log(` • ${stats.variables} variables, ${stats.colors} colors, ${stats.tokens} tokens`);
658
+ if (stats.presets > 0)
659
+ console.log(` • ${stats.presets} presets`);
660
+ if (stats.computed > 0)
661
+ console.log(` • ${stats.computed} computed colors`);
662
+ if (conversions.length > 0) {
663
+ console.log(` • All colors converted: ${conversions.map((c) => `${c.from} → ${c.to}`).join(", ")}`);
664
+ }
665
+ console.log(` • No issues`);
666
+ }
667
+ else {
668
+ const errorCount = errors.length;
669
+ const warningCount = warnings.length;
670
+ logger_1.logger.error(`manifest.json invalid (${errorCount} error${errorCount !== 1 ? "s" : ""}, ${warningCount} warning${warningCount !== 1 ? "s" : ""})`);
671
+ console.log("");
672
+ errors.forEach((err) => {
673
+ console.log(` ERROR [${err.field}]: ${err.message}`);
674
+ if (err.suggestion) {
675
+ console.log(` ${err.suggestion}`);
676
+ }
677
+ });
678
+ if (warningCount > 0) {
679
+ console.log("");
680
+ }
681
+ warnings.forEach((warn) => {
682
+ console.log(` WARNING [${warn.field}]: ${warn.message}`);
683
+ if (warn.suggestion) {
684
+ console.log(` ${warn.suggestion}`);
685
+ }
686
+ });
687
+ }
688
+ }
689
+ //# sourceMappingURL=validate.js.map