formalconf 2.0.14 → 2.0.16
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/dist/formalconf.js +399 -66
- package/package.json +1 -1
package/dist/formalconf.js
CHANGED
|
@@ -336,6 +336,9 @@ var BUNDLED_TEMPLATES_DIR = join(ROOT_DIR, "templates");
|
|
|
336
336
|
var BUNDLED_MANIFEST_PATH = join(BUNDLED_TEMPLATES_DIR, "templates.json");
|
|
337
337
|
var GTK_DIR = join(CONFIG_DIR, "gtk");
|
|
338
338
|
var COLLOID_DIR = join(GTK_DIR, "colloid-gtk-theme");
|
|
339
|
+
var QT_DIR = join(CONFIG_DIR, "qt");
|
|
340
|
+
var KVANTUM_CONFIG_DIR = join(HOME_DIR, ".config", "Kvantum");
|
|
341
|
+
var KVANTUM_THEME_DIR = join(KVANTUM_CONFIG_DIR, "FormalConf");
|
|
339
342
|
async function ensureDir2(path) {
|
|
340
343
|
await ensureDir(path);
|
|
341
344
|
}
|
|
@@ -467,7 +470,7 @@ function StatusIndicator({
|
|
|
467
470
|
// package.json
|
|
468
471
|
var package_default = {
|
|
469
472
|
name: "formalconf",
|
|
470
|
-
version: "2.0.
|
|
473
|
+
version: "2.0.16",
|
|
471
474
|
description: "Dotfiles management TUI for macOS and Linux - config management, package sync, and theme switching",
|
|
472
475
|
type: "module",
|
|
473
476
|
main: "./dist/formalconf.js",
|
|
@@ -4666,13 +4669,13 @@ function useThemeGrid({
|
|
|
4666
4669
|
import { parseArgs as parseArgs4 } from "util";
|
|
4667
4670
|
import {
|
|
4668
4671
|
readdirSync as readdirSync9,
|
|
4669
|
-
existsSync as
|
|
4672
|
+
existsSync as existsSync14,
|
|
4670
4673
|
rmSync,
|
|
4671
4674
|
symlinkSync,
|
|
4672
4675
|
unlinkSync as unlinkSync2,
|
|
4673
|
-
copyFileSync
|
|
4676
|
+
copyFileSync as copyFileSync2
|
|
4674
4677
|
} from "fs";
|
|
4675
|
-
import { join as
|
|
4678
|
+
import { join as join13, basename as basename4 } from "path";
|
|
4676
4679
|
|
|
4677
4680
|
// src/lib/theme-parser.ts
|
|
4678
4681
|
init_runtime();
|
|
@@ -5121,9 +5124,304 @@ ${instructions}`
|
|
|
5121
5124
|
themeName: installedThemeName
|
|
5122
5125
|
};
|
|
5123
5126
|
}
|
|
5127
|
+
// src/lib/qt/kvantum.ts
|
|
5128
|
+
import { existsSync as existsSync8, copyFileSync } from "fs";
|
|
5129
|
+
import { join as join7 } from "path";
|
|
5130
|
+
init_runtime();
|
|
5131
|
+
|
|
5132
|
+
// src/lib/qt/palette.ts
|
|
5133
|
+
function hexToRgb2(hex) {
|
|
5134
|
+
const clean = hex.replace("#", "");
|
|
5135
|
+
return {
|
|
5136
|
+
r: parseInt(clean.substring(0, 2), 16),
|
|
5137
|
+
g: parseInt(clean.substring(2, 4), 16),
|
|
5138
|
+
b: parseInt(clean.substring(4, 6), 16)
|
|
5139
|
+
};
|
|
5140
|
+
}
|
|
5141
|
+
function rgbToHex2(r, g, b) {
|
|
5142
|
+
const toHex = (n) => Math.round(Math.max(0, Math.min(255, n))).toString(16).padStart(2, "0");
|
|
5143
|
+
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
|
|
5144
|
+
}
|
|
5145
|
+
function darken2(hex, percent) {
|
|
5146
|
+
const { r, g, b } = hexToRgb2(hex);
|
|
5147
|
+
const factor = 1 - percent / 100;
|
|
5148
|
+
return rgbToHex2(r * factor, g * factor, b * factor);
|
|
5149
|
+
}
|
|
5150
|
+
function lighten2(hex, percent) {
|
|
5151
|
+
const { r, g, b } = hexToRgb2(hex);
|
|
5152
|
+
const factor = percent / 100;
|
|
5153
|
+
return rgbToHex2(r + (255 - r) * factor, g + (255 - g) * factor, b + (255 - b) * factor);
|
|
5154
|
+
}
|
|
5155
|
+
function createKvantumPalette(palette, mode) {
|
|
5156
|
+
const isDark = mode === "dark";
|
|
5157
|
+
const accent = palette.accent || palette.color4;
|
|
5158
|
+
const altBase = isDark ? lighten2(palette.background, 8) : darken2(palette.background, 5);
|
|
5159
|
+
const button = isDark ? lighten2(palette.background, 15) : darken2(palette.background, 10);
|
|
5160
|
+
const light = isDark ? lighten2(palette.background, 25) : palette.foreground;
|
|
5161
|
+
const dark = isDark ? darken2(palette.background, 15) : darken2(palette.background, 20);
|
|
5162
|
+
const highlightText = isDark ? palette.background : palette.foreground;
|
|
5163
|
+
return {
|
|
5164
|
+
window: palette.background,
|
|
5165
|
+
base: palette.background,
|
|
5166
|
+
altBase,
|
|
5167
|
+
button,
|
|
5168
|
+
light,
|
|
5169
|
+
dark,
|
|
5170
|
+
highlight: accent,
|
|
5171
|
+
text: palette.foreground,
|
|
5172
|
+
windowText: palette.foreground,
|
|
5173
|
+
buttonText: palette.foreground,
|
|
5174
|
+
highlightText,
|
|
5175
|
+
link: palette.color4,
|
|
5176
|
+
linkVisited: palette.color5
|
|
5177
|
+
};
|
|
5178
|
+
}
|
|
5179
|
+
function generateKvantumConfig(palette, mode, baseTheme) {
|
|
5180
|
+
const kv = createKvantumPalette(palette, mode);
|
|
5181
|
+
const inheritFrom = baseTheme || (mode === "dark" ? "KvFlat" : "KvFlatLight");
|
|
5182
|
+
const textDimmed = mode === "dark" ? `${kv.text}c8` : `${kv.text}b4`;
|
|
5183
|
+
const textMoreDimmed = mode === "dark" ? `${kv.text}8c` : `${kv.text}78`;
|
|
5184
|
+
return `[%General]
|
|
5185
|
+
author=FormalConf
|
|
5186
|
+
comment=Auto-generated theme from FormalConf
|
|
5187
|
+
inherits=${inheritFrom}
|
|
5188
|
+
|
|
5189
|
+
[GeneralColors]
|
|
5190
|
+
window.color=${kv.window}
|
|
5191
|
+
inactive.window.color=${kv.window}
|
|
5192
|
+
base.color=${kv.base}
|
|
5193
|
+
inactive.base.color=${kv.base}
|
|
5194
|
+
alt.base.color=${kv.altBase}
|
|
5195
|
+
inactive.alt.base.color=${kv.altBase}
|
|
5196
|
+
button.color=${kv.button}
|
|
5197
|
+
light.color=${kv.light}
|
|
5198
|
+
mid.light.color=${kv.light}
|
|
5199
|
+
dark.color=${kv.dark}
|
|
5200
|
+
mid.color=${kv.altBase}
|
|
5201
|
+
highlight.color=${kv.highlight}
|
|
5202
|
+
inactive.highlight.color=${kv.highlight}
|
|
5203
|
+
text.color=${kv.text}
|
|
5204
|
+
inactive.text.color=${textDimmed}
|
|
5205
|
+
window.text.color=${kv.windowText}
|
|
5206
|
+
inactive.window.text.color=${textMoreDimmed}
|
|
5207
|
+
button.text.color=${kv.buttonText}
|
|
5208
|
+
disabled.text.color=${textMoreDimmed}
|
|
5209
|
+
tooltip.text.color=${kv.text}
|
|
5210
|
+
highlight.text.color=${kv.highlightText}
|
|
5211
|
+
link.color=${kv.link}
|
|
5212
|
+
link.visited.color=${kv.linkVisited}
|
|
5213
|
+
progress.indicator.text.color=${kv.highlightText}
|
|
5214
|
+
|
|
5215
|
+
[Hacks]
|
|
5216
|
+
transparent_dolphin_view=false
|
|
5217
|
+
blur_translucent=true
|
|
5218
|
+
respect_darkness=true
|
|
5219
|
+
|
|
5220
|
+
[PanelButtonCommand]
|
|
5221
|
+
text.normal.color=${kv.text}
|
|
5222
|
+
text.normal.inactive.color=${textMoreDimmed}
|
|
5223
|
+
text.focus.color=${kv.text}
|
|
5224
|
+
text.press.color=${kv.text}
|
|
5225
|
+
text.toggle.color=${kv.text}
|
|
5226
|
+
text.toggle.inactive.color=${textMoreDimmed}
|
|
5227
|
+
|
|
5228
|
+
[Toolbar]
|
|
5229
|
+
text.normal.color=${kv.text}
|
|
5230
|
+
text.focus.color=${kv.text}
|
|
5231
|
+
|
|
5232
|
+
[MenuBar]
|
|
5233
|
+
text.normal.color=${kv.text}
|
|
5234
|
+
|
|
5235
|
+
[MenuBarItem]
|
|
5236
|
+
text.normal.color=${kv.text}
|
|
5237
|
+
text.focus.color=${kv.highlight}
|
|
5238
|
+
|
|
5239
|
+
[MenuItem]
|
|
5240
|
+
text.normal.color=${kv.text}
|
|
5241
|
+
text.focus.color=${kv.text}
|
|
5242
|
+
|
|
5243
|
+
[ItemView]
|
|
5244
|
+
text.normal.color=${kv.text}
|
|
5245
|
+
text.normal.inactive.color=${textDimmed}
|
|
5246
|
+
text.focus.color=${kv.text}
|
|
5247
|
+
text.press.color=${kv.text}
|
|
5248
|
+
text.toggle.color=${kv.text}
|
|
5249
|
+
text.toggle.inactive.color=${textDimmed}
|
|
5250
|
+
|
|
5251
|
+
[Tab]
|
|
5252
|
+
text.normal.color=${textMoreDimmed}
|
|
5253
|
+
text.normal.inactive.color=${textMoreDimmed}
|
|
5254
|
+
text.focus.color=${textDimmed}
|
|
5255
|
+
text.toggle.color=${kv.text}
|
|
5256
|
+
|
|
5257
|
+
[ToolboxTab]
|
|
5258
|
+
text.normal.color=${textDimmed}
|
|
5259
|
+
text.normal.inactive.color=${textMoreDimmed}
|
|
5260
|
+
text.press.color=${kv.text}
|
|
5261
|
+
text.focus.color=${kv.text}
|
|
5262
|
+
|
|
5263
|
+
[HeaderSection]
|
|
5264
|
+
text.normal.color=${textMoreDimmed}
|
|
5265
|
+
text.normal.inactive.color=${textMoreDimmed}
|
|
5266
|
+
text.focus.color=${textDimmed}
|
|
5267
|
+
text.toggle.color=${kv.text}
|
|
5268
|
+
|
|
5269
|
+
[Progressbar]
|
|
5270
|
+
text.normal.color=${textMoreDimmed}
|
|
5271
|
+
text.normal.inactive.color=${textMoreDimmed}
|
|
5272
|
+
text.focus.color=${kv.text}
|
|
5273
|
+
text.press.color=${kv.text}
|
|
5274
|
+
text.toggle.color=${kv.text}
|
|
5275
|
+
|
|
5276
|
+
[TitleBar]
|
|
5277
|
+
text.normal.color=${textMoreDimmed}
|
|
5278
|
+
text.focus.color=${kv.text}
|
|
5279
|
+
|
|
5280
|
+
[GroupBox]
|
|
5281
|
+
text.normal.color=${kv.text}
|
|
5282
|
+
text.press.color=${kv.text}
|
|
5283
|
+
text.focus.color=${kv.text}
|
|
5284
|
+
|
|
5285
|
+
[Dock]
|
|
5286
|
+
text.normal.color=${kv.text}
|
|
5287
|
+
|
|
5288
|
+
[DockTitle]
|
|
5289
|
+
text.normal.color=${kv.text}
|
|
5290
|
+
text.focus.color=${kv.text}
|
|
5291
|
+
|
|
5292
|
+
[RadioButton]
|
|
5293
|
+
text.normal.color=${kv.text}
|
|
5294
|
+
text.focus.color=${kv.text}
|
|
5295
|
+
|
|
5296
|
+
[CheckBox]
|
|
5297
|
+
text.normal.color=${kv.text}
|
|
5298
|
+
text.focus.color=${kv.text}
|
|
5299
|
+
|
|
5300
|
+
[LineEdit]
|
|
5301
|
+
text.normal.color=${kv.text}
|
|
5302
|
+
|
|
5303
|
+
[IndicatorSpinBox]
|
|
5304
|
+
text.normal.color=${kv.text}
|
|
5305
|
+
|
|
5306
|
+
[Menu]
|
|
5307
|
+
text.normal.color=${kv.text}
|
|
5308
|
+
`;
|
|
5309
|
+
}
|
|
5310
|
+
|
|
5311
|
+
// src/lib/qt/kvantum.ts
|
|
5312
|
+
var SYSTEM_KVANTUM_DIR = "/usr/share/Kvantum";
|
|
5313
|
+
var SETUP_SHOWN_FILE = join7(QT_DIR, ".setup-shown");
|
|
5314
|
+
async function checkQtDependencies() {
|
|
5315
|
+
const [kvantum, qt5ct, qt6ct] = await Promise.all([
|
|
5316
|
+
commandExists("kvantummanager"),
|
|
5317
|
+
commandExists("qt5ct"),
|
|
5318
|
+
commandExists("qt6ct")
|
|
5319
|
+
]);
|
|
5320
|
+
const missing = [];
|
|
5321
|
+
if (!kvantum)
|
|
5322
|
+
missing.push("kvantum");
|
|
5323
|
+
return { kvantum, qt5ct, qt6ct, missing };
|
|
5324
|
+
}
|
|
5325
|
+
async function hasShownSetupReminder() {
|
|
5326
|
+
return existsSync8(SETUP_SHOWN_FILE);
|
|
5327
|
+
}
|
|
5328
|
+
async function markSetupReminderShown() {
|
|
5329
|
+
await ensureDir2(QT_DIR);
|
|
5330
|
+
await writeFile(SETUP_SHOWN_FILE, new Date().toISOString());
|
|
5331
|
+
}
|
|
5332
|
+
function getBaseTheme(mode) {
|
|
5333
|
+
return mode === "dark" ? "KvFlat" : "KvFlatLight";
|
|
5334
|
+
}
|
|
5335
|
+
function copyBaseThemeSvg(baseTheme) {
|
|
5336
|
+
const sourceSvg = join7(SYSTEM_KVANTUM_DIR, baseTheme, `${baseTheme}.svg`);
|
|
5337
|
+
const targetSvg = join7(KVANTUM_THEME_DIR, "FormalConf.svg");
|
|
5338
|
+
if (existsSync8(sourceSvg)) {
|
|
5339
|
+
copyFileSync(sourceSvg, targetSvg);
|
|
5340
|
+
return true;
|
|
5341
|
+
}
|
|
5342
|
+
return false;
|
|
5343
|
+
}
|
|
5344
|
+
async function writeKvantumTheme(theme, mode) {
|
|
5345
|
+
const palette = mode === "dark" ? theme.dark : theme.light;
|
|
5346
|
+
if (!palette) {
|
|
5347
|
+
throw new Error(`Theme does not have a ${mode} palette`);
|
|
5348
|
+
}
|
|
5349
|
+
await ensureDir2(KVANTUM_THEME_DIR);
|
|
5350
|
+
const baseTheme = getBaseTheme(mode);
|
|
5351
|
+
copyBaseThemeSvg(baseTheme);
|
|
5352
|
+
const config = generateKvantumConfig(palette, mode, baseTheme);
|
|
5353
|
+
const configPath = join7(KVANTUM_THEME_DIR, "FormalConf.kvconfig");
|
|
5354
|
+
await writeFile(configPath, config);
|
|
5355
|
+
}
|
|
5356
|
+
async function writeKvantumGlobalConfig() {
|
|
5357
|
+
await ensureDir2(KVANTUM_CONFIG_DIR);
|
|
5358
|
+
const globalConfig = `[General]
|
|
5359
|
+
theme=FormalConf
|
|
5360
|
+
`;
|
|
5361
|
+
const configPath = join7(KVANTUM_CONFIG_DIR, "kvantum.kvconfig");
|
|
5362
|
+
await writeFile(configPath, globalConfig);
|
|
5363
|
+
}
|
|
5364
|
+
async function applyQtTheme(theme, mode) {
|
|
5365
|
+
if (getOS() !== "linux") {
|
|
5366
|
+
return {
|
|
5367
|
+
success: true,
|
|
5368
|
+
themeName: "",
|
|
5369
|
+
skipped: true,
|
|
5370
|
+
skipReason: "QT theming only available on Linux"
|
|
5371
|
+
};
|
|
5372
|
+
}
|
|
5373
|
+
const palette = mode === "dark" ? theme.dark : theme.light;
|
|
5374
|
+
if (!palette) {
|
|
5375
|
+
return {
|
|
5376
|
+
success: false,
|
|
5377
|
+
themeName: "",
|
|
5378
|
+
error: `Theme does not have a ${mode} palette`
|
|
5379
|
+
};
|
|
5380
|
+
}
|
|
5381
|
+
const deps = await checkQtDependencies();
|
|
5382
|
+
if (!deps.kvantum) {
|
|
5383
|
+
return {
|
|
5384
|
+
success: true,
|
|
5385
|
+
themeName: "",
|
|
5386
|
+
skipped: true,
|
|
5387
|
+
skipReason: "Kvantum not installed (install kvantum for QT theming)"
|
|
5388
|
+
};
|
|
5389
|
+
}
|
|
5390
|
+
try {
|
|
5391
|
+
await writeKvantumTheme(theme, mode);
|
|
5392
|
+
await writeKvantumGlobalConfig();
|
|
5393
|
+
const shownBefore = await hasShownSetupReminder();
|
|
5394
|
+
return {
|
|
5395
|
+
success: true,
|
|
5396
|
+
themeName: "FormalConf (Kvantum)",
|
|
5397
|
+
...!shownBefore && {
|
|
5398
|
+
error: undefined
|
|
5399
|
+
}
|
|
5400
|
+
};
|
|
5401
|
+
} catch (err) {
|
|
5402
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
5403
|
+
return {
|
|
5404
|
+
success: false,
|
|
5405
|
+
themeName: "",
|
|
5406
|
+
error: `Failed to write Kvantum theme: ${message}`
|
|
5407
|
+
};
|
|
5408
|
+
}
|
|
5409
|
+
}
|
|
5410
|
+
function getQtSetupReminder() {
|
|
5411
|
+
return `Note: Add to your shell profile for QT apps to use Kvantum:
|
|
5412
|
+
export QT_QPA_PLATFORMTHEME=kvantum`;
|
|
5413
|
+
}
|
|
5414
|
+
async function getAndMarkSetupReminder() {
|
|
5415
|
+
const shown = await hasShownSetupReminder();
|
|
5416
|
+
if (shown) {
|
|
5417
|
+
return null;
|
|
5418
|
+
}
|
|
5419
|
+
await markSetupReminderShown();
|
|
5420
|
+
return getQtSetupReminder();
|
|
5421
|
+
}
|
|
5124
5422
|
// src/lib/theme-config.ts
|
|
5125
5423
|
import { hostname } from "os";
|
|
5126
|
-
import { existsSync as
|
|
5424
|
+
import { existsSync as existsSync9, readFileSync, writeFileSync } from "fs";
|
|
5127
5425
|
var DEFAULT_CONFIG = {
|
|
5128
5426
|
version: 1,
|
|
5129
5427
|
defaultTheme: null,
|
|
@@ -5133,7 +5431,7 @@ function getDeviceHostname() {
|
|
|
5133
5431
|
return hostname();
|
|
5134
5432
|
}
|
|
5135
5433
|
function loadThemeConfig() {
|
|
5136
|
-
if (!
|
|
5434
|
+
if (!existsSync9(THEME_CONFIG_PATH)) {
|
|
5137
5435
|
return { ...DEFAULT_CONFIG, devices: {} };
|
|
5138
5436
|
}
|
|
5139
5437
|
try {
|
|
@@ -5199,8 +5497,8 @@ function getDefaultTheme() {
|
|
|
5199
5497
|
|
|
5200
5498
|
// src/lib/theme-v2/loader.ts
|
|
5201
5499
|
init_runtime();
|
|
5202
|
-
import { existsSync as
|
|
5203
|
-
import { join as
|
|
5500
|
+
import { existsSync as existsSync10, readdirSync as readdirSync5 } from "fs";
|
|
5501
|
+
import { join as join8, basename as basename2 } from "path";
|
|
5204
5502
|
|
|
5205
5503
|
// src/lib/theme-v2/color.ts
|
|
5206
5504
|
function isValidHex(hex) {
|
|
@@ -5218,7 +5516,7 @@ function normalizeHex(hex) {
|
|
|
5218
5516
|
}
|
|
5219
5517
|
return hex.toUpperCase();
|
|
5220
5518
|
}
|
|
5221
|
-
function
|
|
5519
|
+
function hexToRgb3(hex) {
|
|
5222
5520
|
const normalized = normalizeHex(hex);
|
|
5223
5521
|
if (!isValidHex(normalized)) {
|
|
5224
5522
|
throw new Error(`Invalid hex color: ${hex}`);
|
|
@@ -5230,7 +5528,7 @@ function hexToRgb2(hex) {
|
|
|
5230
5528
|
}
|
|
5231
5529
|
function hexToColorVariable(hex) {
|
|
5232
5530
|
const normalized = normalizeHex(hex);
|
|
5233
|
-
const { r, g, b } =
|
|
5531
|
+
const { r, g, b } = hexToRgb3(normalized);
|
|
5234
5532
|
return {
|
|
5235
5533
|
hex: normalized,
|
|
5236
5534
|
strip: normalized.slice(1),
|
|
@@ -5479,7 +5777,7 @@ ${validationErrors}`);
|
|
|
5479
5777
|
}
|
|
5480
5778
|
}
|
|
5481
5779
|
async function loadThemeJson(themePath) {
|
|
5482
|
-
if (!
|
|
5780
|
+
if (!existsSync10(themePath)) {
|
|
5483
5781
|
throw new ThemeLoadError(themePath, "file not found");
|
|
5484
5782
|
}
|
|
5485
5783
|
let content;
|
|
@@ -5509,14 +5807,14 @@ function getAvailableModes(theme) {
|
|
|
5509
5807
|
return modes;
|
|
5510
5808
|
}
|
|
5511
5809
|
async function listJsonThemes() {
|
|
5512
|
-
if (!
|
|
5810
|
+
if (!existsSync10(THEMES_DIR)) {
|
|
5513
5811
|
return [];
|
|
5514
5812
|
}
|
|
5515
5813
|
const entries = readdirSync5(THEMES_DIR, { withFileTypes: true });
|
|
5516
5814
|
const themes = [];
|
|
5517
5815
|
for (const entry of entries) {
|
|
5518
5816
|
if (entry.isFile() && entry.name.endsWith(".json")) {
|
|
5519
|
-
const path =
|
|
5817
|
+
const path = join8(THEMES_DIR, entry.name);
|
|
5520
5818
|
try {
|
|
5521
5819
|
const theme = await loadThemeJson(path);
|
|
5522
5820
|
themes.push({
|
|
@@ -5535,7 +5833,7 @@ async function listJsonThemes() {
|
|
|
5535
5833
|
|
|
5536
5834
|
// src/lib/template-engine/engine.ts
|
|
5537
5835
|
init_runtime();
|
|
5538
|
-
import { join as
|
|
5836
|
+
import { join as join10 } from "path";
|
|
5539
5837
|
|
|
5540
5838
|
// src/lib/template-engine/modifiers.ts
|
|
5541
5839
|
var VALID_MODIFIERS = [
|
|
@@ -5629,6 +5927,11 @@ function getContextValue(context, variableName, modifier) {
|
|
|
5629
5927
|
const value = context.theme[key];
|
|
5630
5928
|
return value !== undefined ? String(value) : undefined;
|
|
5631
5929
|
}
|
|
5930
|
+
if (variableName.startsWith("gtk.")) {
|
|
5931
|
+
const key = variableName.slice(4);
|
|
5932
|
+
const value = context.gtk[key];
|
|
5933
|
+
return value !== undefined ? String(value) : undefined;
|
|
5934
|
+
}
|
|
5632
5935
|
if (variableName === "mode") {
|
|
5633
5936
|
return context.mode;
|
|
5634
5937
|
}
|
|
@@ -5668,14 +5971,14 @@ function renderDualModeTemplate(template, contexts) {
|
|
|
5668
5971
|
|
|
5669
5972
|
// src/lib/template-engine/versioning.ts
|
|
5670
5973
|
init_runtime();
|
|
5671
|
-
import { existsSync as
|
|
5672
|
-
import { join as
|
|
5974
|
+
import { existsSync as existsSync11, readdirSync as readdirSync6 } from "fs";
|
|
5975
|
+
import { join as join9 } from "path";
|
|
5673
5976
|
var DEFAULT_MANIFEST = {
|
|
5674
5977
|
version: 1,
|
|
5675
5978
|
templates: {}
|
|
5676
5979
|
};
|
|
5677
5980
|
async function loadTemplatesManifest() {
|
|
5678
|
-
if (!
|
|
5981
|
+
if (!existsSync11(TEMPLATES_MANIFEST_PATH)) {
|
|
5679
5982
|
return { ...DEFAULT_MANIFEST };
|
|
5680
5983
|
}
|
|
5681
5984
|
try {
|
|
@@ -5690,7 +5993,7 @@ async function saveTemplatesManifest(manifest) {
|
|
|
5690
5993
|
await writeFile(TEMPLATES_MANIFEST_PATH, JSON.stringify(manifest, null, 2));
|
|
5691
5994
|
}
|
|
5692
5995
|
async function loadBundledManifest() {
|
|
5693
|
-
if (!
|
|
5996
|
+
if (!existsSync11(BUNDLED_MANIFEST_PATH)) {
|
|
5694
5997
|
return { version: 1, templates: {} };
|
|
5695
5998
|
}
|
|
5696
5999
|
try {
|
|
@@ -5741,13 +6044,13 @@ async function installTemplate(templateName) {
|
|
|
5741
6044
|
if (!bundledMeta) {
|
|
5742
6045
|
throw new Error(`Template '${templateName}' not found in bundled templates`);
|
|
5743
6046
|
}
|
|
5744
|
-
const sourcePath =
|
|
5745
|
-
if (!
|
|
6047
|
+
const sourcePath = join9(BUNDLED_TEMPLATES_DIR, templateName);
|
|
6048
|
+
if (!existsSync11(sourcePath)) {
|
|
5746
6049
|
throw new Error(`Template file not found: ${sourcePath}`);
|
|
5747
6050
|
}
|
|
5748
6051
|
await ensureDir2(TEMPLATES_DIR);
|
|
5749
6052
|
const content = await readText(sourcePath);
|
|
5750
|
-
const destPath =
|
|
6053
|
+
const destPath = join9(TEMPLATES_DIR, templateName);
|
|
5751
6054
|
await writeFile(destPath, content);
|
|
5752
6055
|
const manifest = await loadTemplatesManifest();
|
|
5753
6056
|
manifest.templates[templateName] = {
|
|
@@ -5809,7 +6112,7 @@ function getOutputFilename(templateName) {
|
|
|
5809
6112
|
return output;
|
|
5810
6113
|
}
|
|
5811
6114
|
async function listInstalledTemplates() {
|
|
5812
|
-
if (!
|
|
6115
|
+
if (!existsSync11(TEMPLATES_DIR)) {
|
|
5813
6116
|
return [];
|
|
5814
6117
|
}
|
|
5815
6118
|
const entries = readdirSync6(TEMPLATES_DIR, { withFileTypes: true });
|
|
@@ -5818,7 +6121,7 @@ async function listInstalledTemplates() {
|
|
|
5818
6121
|
if (entry.isFile() && entry.name.endsWith(".template")) {
|
|
5819
6122
|
templates.push({
|
|
5820
6123
|
name: entry.name,
|
|
5821
|
-
path:
|
|
6124
|
+
path: join9(TEMPLATES_DIR, entry.name),
|
|
5822
6125
|
outputName: getOutputFilename(entry.name),
|
|
5823
6126
|
type: getTemplateType(entry.name),
|
|
5824
6127
|
partialMode: getPartialMode(entry.name)
|
|
@@ -5921,6 +6224,13 @@ function buildThemeMetadata(theme, mode) {
|
|
|
5921
6224
|
mode
|
|
5922
6225
|
};
|
|
5923
6226
|
}
|
|
6227
|
+
function buildGtkMetadata(theme, mode) {
|
|
6228
|
+
const themeName = theme.title.toLowerCase().replace(/\s+/g, "-");
|
|
6229
|
+
const modeCapitalized = mode === "dark" ? "Dark" : "Light";
|
|
6230
|
+
return {
|
|
6231
|
+
theme: `formalconf-${themeName}-${modeCapitalized}`
|
|
6232
|
+
};
|
|
6233
|
+
}
|
|
5924
6234
|
function buildTemplateContext(theme, palette, mode) {
|
|
5925
6235
|
return {
|
|
5926
6236
|
color0: hexToColorVariable(palette.color0),
|
|
@@ -5947,6 +6257,7 @@ function buildTemplateContext(theme, palette, mode) {
|
|
|
5947
6257
|
accent: hexToColorVariableOrDefault(palette.accent, palette.color4),
|
|
5948
6258
|
border: hexToColorVariableOrDefault(palette.border, palette.color0),
|
|
5949
6259
|
theme: buildThemeMetadata(theme, mode),
|
|
6260
|
+
gtk: buildGtkMetadata(theme, mode),
|
|
5950
6261
|
mode
|
|
5951
6262
|
};
|
|
5952
6263
|
}
|
|
@@ -5992,7 +6303,7 @@ async function renderTemplateFile(templateFile, theme, mode) {
|
|
|
5992
6303
|
return {
|
|
5993
6304
|
template: templateFile,
|
|
5994
6305
|
content,
|
|
5995
|
-
outputPath:
|
|
6306
|
+
outputPath: join10(GENERATED_DIR, templateFile.outputName)
|
|
5996
6307
|
};
|
|
5997
6308
|
}
|
|
5998
6309
|
async function renderAllTemplates(theme, mode) {
|
|
@@ -6026,7 +6337,7 @@ async function generateNeovimConfigFile(theme, mode) {
|
|
|
6026
6337
|
return null;
|
|
6027
6338
|
}
|
|
6028
6339
|
const content = generateNeovimConfig(theme, mode);
|
|
6029
|
-
const outputPath =
|
|
6340
|
+
const outputPath = join10(GENERATED_DIR, "neovim.lua");
|
|
6030
6341
|
await writeFile(outputPath, content);
|
|
6031
6342
|
return {
|
|
6032
6343
|
template: {
|
|
@@ -6051,8 +6362,8 @@ async function generateThemeConfigs(theme, mode) {
|
|
|
6051
6362
|
|
|
6052
6363
|
// src/lib/migration/extractor.ts
|
|
6053
6364
|
init_runtime();
|
|
6054
|
-
import { existsSync as
|
|
6055
|
-
import { join as
|
|
6365
|
+
import { existsSync as existsSync12, readdirSync as readdirSync7 } from "fs";
|
|
6366
|
+
import { join as join11 } from "path";
|
|
6056
6367
|
function normalizeHex2(hex) {
|
|
6057
6368
|
hex = hex.replace(/^(#|0x)/i, "");
|
|
6058
6369
|
if (hex.length === 3) {
|
|
@@ -6193,7 +6504,7 @@ async function extractFromGhostty(path) {
|
|
|
6193
6504
|
return { colors: colors5, source: "ghostty" };
|
|
6194
6505
|
}
|
|
6195
6506
|
async function extractColors(filePath) {
|
|
6196
|
-
if (!
|
|
6507
|
+
if (!existsSync12(filePath)) {
|
|
6197
6508
|
return null;
|
|
6198
6509
|
}
|
|
6199
6510
|
const filename = filePath.toLowerCase();
|
|
@@ -6215,7 +6526,7 @@ async function extractColors(filePath) {
|
|
|
6215
6526
|
return null;
|
|
6216
6527
|
}
|
|
6217
6528
|
async function extractFromLegacyTheme(themePath) {
|
|
6218
|
-
if (!
|
|
6529
|
+
if (!existsSync12(themePath)) {
|
|
6219
6530
|
return null;
|
|
6220
6531
|
}
|
|
6221
6532
|
const files = readdirSync7(themePath, { withFileTypes: true });
|
|
@@ -6227,12 +6538,12 @@ async function extractFromLegacyTheme(themePath) {
|
|
|
6227
6538
|
for (const preferred of preferredFiles) {
|
|
6228
6539
|
const match = files.find((f) => f.name.toLowerCase() === preferred.toLowerCase());
|
|
6229
6540
|
if (match) {
|
|
6230
|
-
return extractColors(
|
|
6541
|
+
return extractColors(join11(themePath, match.name));
|
|
6231
6542
|
}
|
|
6232
6543
|
}
|
|
6233
6544
|
for (const file of files) {
|
|
6234
6545
|
if (file.isFile() && (file.name.endsWith(".conf") || file.name.endsWith(".toml"))) {
|
|
6235
|
-
const result = await extractColors(
|
|
6546
|
+
const result = await extractColors(join11(themePath, file.name));
|
|
6236
6547
|
if (result && Object.keys(result.colors).length > 0) {
|
|
6237
6548
|
return result;
|
|
6238
6549
|
}
|
|
@@ -6321,19 +6632,19 @@ function generateThemeJson(name, colors5, options = {}) {
|
|
|
6321
6632
|
init_runtime();
|
|
6322
6633
|
|
|
6323
6634
|
// src/lib/wallpaper.ts
|
|
6324
|
-
import { existsSync as
|
|
6325
|
-
import { join as
|
|
6635
|
+
import { existsSync as existsSync13, readdirSync as readdirSync8, unlinkSync } from "fs";
|
|
6636
|
+
import { join as join12 } from "path";
|
|
6326
6637
|
init_runtime();
|
|
6327
6638
|
var DEFAULT_TIMEOUT_MS = 30000;
|
|
6328
6639
|
var MAX_FILE_SIZE = 50 * 1024 * 1024;
|
|
6329
6640
|
function clearBackgroundsDir() {
|
|
6330
|
-
if (!
|
|
6641
|
+
if (!existsSync13(BACKGROUNDS_TARGET_DIR)) {
|
|
6331
6642
|
return;
|
|
6332
6643
|
}
|
|
6333
6644
|
const entries = readdirSync8(BACKGROUNDS_TARGET_DIR, { withFileTypes: true });
|
|
6334
6645
|
for (const entry of entries) {
|
|
6335
6646
|
if (entry.isFile() || entry.isSymbolicLink()) {
|
|
6336
|
-
unlinkSync(
|
|
6647
|
+
unlinkSync(join12(BACKGROUNDS_TARGET_DIR, entry.name));
|
|
6337
6648
|
}
|
|
6338
6649
|
}
|
|
6339
6650
|
}
|
|
@@ -6397,7 +6708,7 @@ async function downloadWallpaper(url, filename, timeoutMs = DEFAULT_TIMEOUT_MS)
|
|
|
6397
6708
|
};
|
|
6398
6709
|
}
|
|
6399
6710
|
const ext = getExtension(url, contentType);
|
|
6400
|
-
const outputPath =
|
|
6711
|
+
const outputPath = join12(BACKGROUNDS_TARGET_DIR, `${filename}.${ext}`);
|
|
6401
6712
|
await writeBuffer(outputPath, arrayBuffer);
|
|
6402
6713
|
return { success: true, path: outputPath };
|
|
6403
6714
|
} catch (err) {
|
|
@@ -6454,11 +6765,11 @@ async function listAllThemes() {
|
|
|
6454
6765
|
});
|
|
6455
6766
|
}
|
|
6456
6767
|
}
|
|
6457
|
-
if (
|
|
6768
|
+
if (existsSync14(THEMES_DIR)) {
|
|
6458
6769
|
const entries = readdirSync9(THEMES_DIR, { withFileTypes: true });
|
|
6459
6770
|
for (const entry of entries) {
|
|
6460
6771
|
if (entry.isDirectory()) {
|
|
6461
|
-
const themePath =
|
|
6772
|
+
const themePath = join13(THEMES_DIR, entry.name);
|
|
6462
6773
|
const theme = await parseTheme(themePath, entry.name);
|
|
6463
6774
|
themes.push({
|
|
6464
6775
|
displayName: theme.name,
|
|
@@ -6475,10 +6786,10 @@ async function listAllThemes() {
|
|
|
6475
6786
|
return themes;
|
|
6476
6787
|
}
|
|
6477
6788
|
function clearDirectory(dir) {
|
|
6478
|
-
if (
|
|
6789
|
+
if (existsSync14(dir)) {
|
|
6479
6790
|
const entries = readdirSync9(dir, { withFileTypes: true });
|
|
6480
6791
|
for (const entry of entries) {
|
|
6481
|
-
const fullPath =
|
|
6792
|
+
const fullPath = join13(dir, entry.name);
|
|
6482
6793
|
if (entry.isSymbolicLink() || entry.isFile()) {
|
|
6483
6794
|
unlinkSync2(fullPath);
|
|
6484
6795
|
} else if (entry.isDirectory()) {
|
|
@@ -6488,7 +6799,7 @@ function clearDirectory(dir) {
|
|
|
6488
6799
|
}
|
|
6489
6800
|
}
|
|
6490
6801
|
function createSymlink(source, target) {
|
|
6491
|
-
if (
|
|
6802
|
+
if (existsSync14(target)) {
|
|
6492
6803
|
unlinkSync2(target);
|
|
6493
6804
|
}
|
|
6494
6805
|
symlinkSync(source, target);
|
|
@@ -6512,20 +6823,20 @@ async function applyJsonTheme(themePath, mode, saveMapping, identifier) {
|
|
|
6512
6823
|
await installAllTemplates();
|
|
6513
6824
|
}
|
|
6514
6825
|
clearDirectory(THEME_TARGET_DIR);
|
|
6515
|
-
if (
|
|
6826
|
+
if (existsSync14(BACKGROUNDS_TARGET_DIR)) {
|
|
6516
6827
|
rmSync(BACKGROUNDS_TARGET_DIR, { recursive: true, force: true });
|
|
6517
6828
|
}
|
|
6518
6829
|
const results = await generateThemeConfigs(theme, mode);
|
|
6519
|
-
const ghosttyThemesDir =
|
|
6830
|
+
const ghosttyThemesDir = join13(HOME_DIR, ".config", "ghostty", "themes");
|
|
6520
6831
|
for (const result of results) {
|
|
6521
6832
|
const filename = basename4(result.outputPath);
|
|
6522
6833
|
if (filename === "formalconf-dark" || filename === "formalconf-light") {
|
|
6523
6834
|
await ensureDir2(ghosttyThemesDir);
|
|
6524
|
-
const targetPath2 =
|
|
6525
|
-
|
|
6835
|
+
const targetPath2 = join13(ghosttyThemesDir, filename);
|
|
6836
|
+
copyFileSync2(result.outputPath, targetPath2);
|
|
6526
6837
|
}
|
|
6527
|
-
const targetPath =
|
|
6528
|
-
|
|
6838
|
+
const targetPath = join13(THEME_TARGET_DIR, filename);
|
|
6839
|
+
copyFileSync2(result.outputPath, targetPath);
|
|
6529
6840
|
}
|
|
6530
6841
|
let wallpaperPaths = [];
|
|
6531
6842
|
let wallpaperErrors = [];
|
|
@@ -6538,6 +6849,10 @@ async function applyJsonTheme(themePath, mode, saveMapping, identifier) {
|
|
|
6538
6849
|
if (getOS() === "linux") {
|
|
6539
6850
|
gtkResult = await applyGtkTheme(theme, mode);
|
|
6540
6851
|
}
|
|
6852
|
+
let qtResult = null;
|
|
6853
|
+
if (getOS() === "linux") {
|
|
6854
|
+
qtResult = await applyQtTheme(theme, mode);
|
|
6855
|
+
}
|
|
6541
6856
|
if (saveMapping) {
|
|
6542
6857
|
await setDeviceTheme(identifier);
|
|
6543
6858
|
}
|
|
@@ -6573,6 +6888,21 @@ GTK theme: ${gtkResult.themeName}`;
|
|
|
6573
6888
|
Warning: GTK theme failed - ${gtkResult.error}`;
|
|
6574
6889
|
}
|
|
6575
6890
|
}
|
|
6891
|
+
if (qtResult && !qtResult.skipped) {
|
|
6892
|
+
if (qtResult.success) {
|
|
6893
|
+
output += `
|
|
6894
|
+
QT theme: ${qtResult.themeName}`;
|
|
6895
|
+
const setupReminder = await getAndMarkSetupReminder();
|
|
6896
|
+
if (setupReminder) {
|
|
6897
|
+
output += `
|
|
6898
|
+
|
|
6899
|
+
${setupReminder}`;
|
|
6900
|
+
}
|
|
6901
|
+
} else {
|
|
6902
|
+
output += `
|
|
6903
|
+
Warning: QT theme failed - ${qtResult.error}`;
|
|
6904
|
+
}
|
|
6905
|
+
}
|
|
6576
6906
|
const hookEnv = {
|
|
6577
6907
|
FORMALCONF_THEME: identifier,
|
|
6578
6908
|
FORMALCONF_THEME_MODE: mode,
|
|
@@ -6584,6 +6914,9 @@ GTK theme: ${gtkResult.themeName}`;
|
|
|
6584
6914
|
if (gtkResult?.success && gtkResult.themeName) {
|
|
6585
6915
|
hookEnv.FORMALCONF_GTK_THEME = gtkResult.themeName;
|
|
6586
6916
|
}
|
|
6917
|
+
if (qtResult?.success && qtResult.themeName) {
|
|
6918
|
+
hookEnv.FORMALCONF_QT_THEME = qtResult.themeName;
|
|
6919
|
+
}
|
|
6587
6920
|
const hookSummary = await runHooks("theme-change", hookEnv);
|
|
6588
6921
|
if (hookSummary.executed > 0) {
|
|
6589
6922
|
output += `
|
|
@@ -6598,27 +6931,27 @@ Hooks: ${hookSummary.succeeded}/${hookSummary.executed} succeeded`;
|
|
|
6598
6931
|
return { output, success: true };
|
|
6599
6932
|
}
|
|
6600
6933
|
async function applyLegacyTheme(themeName, saveMapping) {
|
|
6601
|
-
const themeDir =
|
|
6602
|
-
if (!
|
|
6934
|
+
const themeDir = join13(THEMES_DIR, themeName);
|
|
6935
|
+
if (!existsSync14(themeDir)) {
|
|
6603
6936
|
return { output: `Theme '${themeName}' not found`, success: false };
|
|
6604
6937
|
}
|
|
6605
6938
|
await ensureConfigDir();
|
|
6606
6939
|
await ensureDir2(THEME_TARGET_DIR);
|
|
6607
6940
|
const theme = await parseTheme(themeDir, themeName);
|
|
6608
6941
|
clearDirectory(THEME_TARGET_DIR);
|
|
6609
|
-
if (
|
|
6942
|
+
if (existsSync14(BACKGROUNDS_TARGET_DIR)) {
|
|
6610
6943
|
rmSync(BACKGROUNDS_TARGET_DIR, { recursive: true, force: true });
|
|
6611
6944
|
}
|
|
6612
6945
|
const entries = readdirSync9(themeDir, { withFileTypes: true });
|
|
6613
6946
|
for (const entry of entries) {
|
|
6614
|
-
const source =
|
|
6947
|
+
const source = join13(themeDir, entry.name);
|
|
6615
6948
|
if (entry.isFile() && entry.name !== "theme.yaml" && entry.name !== "light.mode") {
|
|
6616
|
-
const target =
|
|
6949
|
+
const target = join13(THEME_TARGET_DIR, entry.name);
|
|
6617
6950
|
createSymlink(source, target);
|
|
6618
6951
|
}
|
|
6619
6952
|
}
|
|
6620
6953
|
if (theme.hasBackgrounds) {
|
|
6621
|
-
const backgroundsSource =
|
|
6954
|
+
const backgroundsSource = join13(themeDir, "backgrounds");
|
|
6622
6955
|
createSymlink(backgroundsSource, BACKGROUNDS_TARGET_DIR);
|
|
6623
6956
|
}
|
|
6624
6957
|
if (saveMapping) {
|
|
@@ -6658,12 +6991,12 @@ Hooks: ${hookSummary.succeeded}/${hookSummary.executed} succeeded`;
|
|
|
6658
6991
|
}
|
|
6659
6992
|
async function applyTheme(themeIdentifier, saveMapping = false) {
|
|
6660
6993
|
const { name, mode } = parseThemeIdentifier(themeIdentifier);
|
|
6661
|
-
const jsonPath =
|
|
6662
|
-
if (
|
|
6994
|
+
const jsonPath = join13(THEMES_DIR, `${name}.json`);
|
|
6995
|
+
if (existsSync14(jsonPath) && mode) {
|
|
6663
6996
|
return applyJsonTheme(jsonPath, mode, saveMapping, themeIdentifier);
|
|
6664
6997
|
}
|
|
6665
|
-
const legacyPath =
|
|
6666
|
-
if (
|
|
6998
|
+
const legacyPath = join13(THEMES_DIR, name);
|
|
6999
|
+
if (existsSync14(legacyPath)) {
|
|
6667
7000
|
return applyLegacyTheme(name, saveMapping);
|
|
6668
7001
|
}
|
|
6669
7002
|
const allThemes = await listAllThemes();
|
|
@@ -6682,8 +7015,8 @@ Did you mean:`;
|
|
|
6682
7015
|
}
|
|
6683
7016
|
async function showThemeInfo(themeIdentifier) {
|
|
6684
7017
|
const { name, mode } = parseThemeIdentifier(themeIdentifier);
|
|
6685
|
-
const jsonPath =
|
|
6686
|
-
if (
|
|
7018
|
+
const jsonPath = join13(THEMES_DIR, `${name}.json`);
|
|
7019
|
+
if (existsSync14(jsonPath)) {
|
|
6687
7020
|
const theme2 = await loadThemeJson(jsonPath);
|
|
6688
7021
|
const modes = getAvailableModes(theme2);
|
|
6689
7022
|
console.log(`
|
|
@@ -6723,8 +7056,8 @@ ${colors5.green}Wallpapers:${colors5.reset}`);
|
|
|
6723
7056
|
}
|
|
6724
7057
|
return;
|
|
6725
7058
|
}
|
|
6726
|
-
const themeDir =
|
|
6727
|
-
if (!
|
|
7059
|
+
const themeDir = join13(THEMES_DIR, name);
|
|
7060
|
+
if (!existsSync14(themeDir)) {
|
|
6728
7061
|
console.error(`${colors5.red}Error: Theme '${themeIdentifier}' not found${colors5.reset}`);
|
|
6729
7062
|
process.exit(1);
|
|
6730
7063
|
}
|
|
@@ -6833,8 +7166,8 @@ To add themes:`);
|
|
|
6833
7166
|
}
|
|
6834
7167
|
}
|
|
6835
7168
|
async function migrateTheme(themeName) {
|
|
6836
|
-
const legacyPath =
|
|
6837
|
-
if (!
|
|
7169
|
+
const legacyPath = join13(THEMES_DIR, themeName);
|
|
7170
|
+
if (!existsSync14(legacyPath)) {
|
|
6838
7171
|
console.error(`${colors5.red}Error: Legacy theme '${themeName}' not found${colors5.reset}`);
|
|
6839
7172
|
process.exit(1);
|
|
6840
7173
|
}
|
|
@@ -6851,13 +7184,13 @@ async function migrateTheme(themeName) {
|
|
|
6851
7184
|
console.log(`${colors5.yellow}Warning: Missing colors will be filled with defaults:${colors5.reset}`);
|
|
6852
7185
|
console.log(` ${missing.join(", ")}`);
|
|
6853
7186
|
}
|
|
6854
|
-
const isLight =
|
|
7187
|
+
const isLight = existsSync14(join13(legacyPath, "light.mode"));
|
|
6855
7188
|
const themeJson = generateThemeJson(themeName, result.colors, {
|
|
6856
7189
|
description: `Migrated from legacy theme`,
|
|
6857
7190
|
isLight
|
|
6858
7191
|
});
|
|
6859
|
-
const outputPath =
|
|
6860
|
-
if (
|
|
7192
|
+
const outputPath = join13(THEMES_DIR, `${themeName}.json`);
|
|
7193
|
+
if (existsSync14(outputPath)) {
|
|
6861
7194
|
console.error(`${colors5.red}Error: JSON theme '${themeName}.json' already exists${colors5.reset}`);
|
|
6862
7195
|
console.error(`Delete or rename it first, then try again.`);
|
|
6863
7196
|
process.exit(1);
|
package/package.json
CHANGED