formalconf 2.0.16 → 2.0.17
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 +67 -145
- package/package.json +1 -1
package/dist/formalconf.js
CHANGED
|
@@ -470,7 +470,7 @@ function StatusIndicator({
|
|
|
470
470
|
// package.json
|
|
471
471
|
var package_default = {
|
|
472
472
|
name: "formalconf",
|
|
473
|
-
version: "2.0.
|
|
473
|
+
version: "2.0.17",
|
|
474
474
|
description: "Dotfiles management TUI for macOS and Linux - config management, package sync, and theme switching",
|
|
475
475
|
type: "module",
|
|
476
476
|
main: "./dist/formalconf.js",
|
|
@@ -5921,6 +5921,25 @@ var COLOR_VARIABLES = [
|
|
|
5921
5921
|
function isColorVariable(name) {
|
|
5922
5922
|
return COLOR_VARIABLES.includes(name);
|
|
5923
5923
|
}
|
|
5924
|
+
function getNestedValue(obj, path) {
|
|
5925
|
+
return path.split(".").reduce((acc, key) => {
|
|
5926
|
+
if (acc && typeof acc === "object" && key in acc) {
|
|
5927
|
+
return acc[key];
|
|
5928
|
+
}
|
|
5929
|
+
return;
|
|
5930
|
+
}, obj);
|
|
5931
|
+
}
|
|
5932
|
+
function processConditionals(template, context) {
|
|
5933
|
+
template = template.replace(/\{\{#if\s+(\S+)\}\}([\s\S]*?)\{\{\/if\}\}/g, (_, variable, content) => {
|
|
5934
|
+
const value = getNestedValue(context, variable);
|
|
5935
|
+
return value ? content : "";
|
|
5936
|
+
});
|
|
5937
|
+
template = template.replace(/\{\{#unless\s+(\S+)\}\}([\s\S]*?)\{\{\/unless\}\}/g, (_, variable, content) => {
|
|
5938
|
+
const value = getNestedValue(context, variable);
|
|
5939
|
+
return !value ? content : "";
|
|
5940
|
+
});
|
|
5941
|
+
return template;
|
|
5942
|
+
}
|
|
5924
5943
|
function getContextValue(context, variableName, modifier) {
|
|
5925
5944
|
if (variableName.startsWith("theme.")) {
|
|
5926
5945
|
const key = variableName.slice(6);
|
|
@@ -5932,6 +5951,13 @@ function getContextValue(context, variableName, modifier) {
|
|
|
5932
5951
|
const value = context.gtk[key];
|
|
5933
5952
|
return value !== undefined ? String(value) : undefined;
|
|
5934
5953
|
}
|
|
5954
|
+
if (variableName.startsWith("neovim.")) {
|
|
5955
|
+
if (!context.neovim)
|
|
5956
|
+
return;
|
|
5957
|
+
const key = variableName.slice(7);
|
|
5958
|
+
const value = context.neovim[key];
|
|
5959
|
+
return value !== undefined ? String(value) : undefined;
|
|
5960
|
+
}
|
|
5935
5961
|
if (variableName === "mode") {
|
|
5936
5962
|
return context.mode;
|
|
5937
5963
|
}
|
|
@@ -5942,7 +5968,8 @@ function getContextValue(context, variableName, modifier) {
|
|
|
5942
5968
|
return;
|
|
5943
5969
|
}
|
|
5944
5970
|
function renderTemplate(template, context) {
|
|
5945
|
-
|
|
5971
|
+
let result = processConditionals(template, context);
|
|
5972
|
+
result = result.replace(VARIABLE_REGEX, (match, variable) => {
|
|
5946
5973
|
const { name, modifier } = parseVariableReference(variable);
|
|
5947
5974
|
const value = getContextValue(context, name, modifier);
|
|
5948
5975
|
if (value === undefined) {
|
|
@@ -5950,9 +5977,11 @@ function renderTemplate(template, context) {
|
|
|
5950
5977
|
}
|
|
5951
5978
|
return value;
|
|
5952
5979
|
});
|
|
5980
|
+
return result;
|
|
5953
5981
|
}
|
|
5954
5982
|
function renderDualModeTemplate(template, contexts) {
|
|
5955
|
-
let result = template
|
|
5983
|
+
let result = processConditionals(template, contexts);
|
|
5984
|
+
result = result.replace(/\{\{dark\.([a-zA-Z0-9_.]+)\}\}/g, (match, variable) => {
|
|
5956
5985
|
const { name, modifier } = parseVariableReference(variable);
|
|
5957
5986
|
const value = getContextValue(contexts.dark, name, modifier);
|
|
5958
5987
|
return value ?? match;
|
|
@@ -6066,10 +6095,11 @@ async function installAllTemplates() {
|
|
|
6066
6095
|
await installTemplate(name);
|
|
6067
6096
|
}
|
|
6068
6097
|
}
|
|
6069
|
-
function getTemplateType(filename) {
|
|
6070
|
-
const
|
|
6071
|
-
|
|
6072
|
-
|
|
6098
|
+
async function getTemplateType(filename) {
|
|
6099
|
+
const manifest = await loadBundledManifest();
|
|
6100
|
+
const meta = manifest.templates[filename];
|
|
6101
|
+
if (meta?.mode) {
|
|
6102
|
+
return meta.mode;
|
|
6073
6103
|
}
|
|
6074
6104
|
if (filename.includes("-dark.") || filename.includes("-light.")) {
|
|
6075
6105
|
return "partial";
|
|
@@ -6083,33 +6113,18 @@ function getPartialMode(filename) {
|
|
|
6083
6113
|
return "light";
|
|
6084
6114
|
return;
|
|
6085
6115
|
}
|
|
6086
|
-
function getOutputFilename(templateName) {
|
|
6087
|
-
|
|
6088
|
-
|
|
6089
|
-
|
|
6090
|
-
|
|
6091
|
-
if (templateName.startsWith("kitty-light")) {
|
|
6092
|
-
return "light-theme.auto.conf";
|
|
6093
|
-
}
|
|
6094
|
-
if (templateName.startsWith("waybar-dark")) {
|
|
6095
|
-
return "style-dark.css";
|
|
6096
|
-
}
|
|
6097
|
-
if (templateName.startsWith("waybar-light")) {
|
|
6098
|
-
return "style-light.css";
|
|
6116
|
+
async function getOutputFilename(templateName) {
|
|
6117
|
+
const manifest = await loadBundledManifest();
|
|
6118
|
+
const meta = manifest.templates[templateName];
|
|
6119
|
+
if (meta?.output) {
|
|
6120
|
+
return meta.output;
|
|
6099
6121
|
}
|
|
6100
|
-
|
|
6101
|
-
|
|
6102
|
-
|
|
6103
|
-
|
|
6104
|
-
|
|
6105
|
-
|
|
6106
|
-
if (templateName.startsWith("btop-dark")) {
|
|
6107
|
-
return "formalconf-dark.theme";
|
|
6108
|
-
}
|
|
6109
|
-
if (templateName.startsWith("btop-light")) {
|
|
6110
|
-
return "formalconf-light.theme";
|
|
6111
|
-
}
|
|
6112
|
-
return output;
|
|
6122
|
+
return templateName.replace(/\.template$/, "");
|
|
6123
|
+
}
|
|
6124
|
+
async function getTemplateTargets(templateName) {
|
|
6125
|
+
const manifest = await loadBundledManifest();
|
|
6126
|
+
const meta = manifest.templates[templateName];
|
|
6127
|
+
return meta?.targets ?? [];
|
|
6113
6128
|
}
|
|
6114
6129
|
async function listInstalledTemplates() {
|
|
6115
6130
|
if (!existsSync11(TEMPLATES_DIR)) {
|
|
@@ -6122,97 +6137,16 @@ async function listInstalledTemplates() {
|
|
|
6122
6137
|
templates.push({
|
|
6123
6138
|
name: entry.name,
|
|
6124
6139
|
path: join9(TEMPLATES_DIR, entry.name),
|
|
6125
|
-
outputName: getOutputFilename(entry.name),
|
|
6126
|
-
type: getTemplateType(entry.name),
|
|
6127
|
-
partialMode: getPartialMode(entry.name)
|
|
6140
|
+
outputName: await getOutputFilename(entry.name),
|
|
6141
|
+
type: await getTemplateType(entry.name),
|
|
6142
|
+
partialMode: getPartialMode(entry.name),
|
|
6143
|
+
targets: await getTemplateTargets(entry.name)
|
|
6128
6144
|
});
|
|
6129
6145
|
}
|
|
6130
6146
|
}
|
|
6131
6147
|
return templates;
|
|
6132
6148
|
}
|
|
6133
6149
|
|
|
6134
|
-
// src/lib/neovim/generator.ts
|
|
6135
|
-
function toLua(value, indent = 2) {
|
|
6136
|
-
const spaces = " ".repeat(indent);
|
|
6137
|
-
if (value === null || value === undefined) {
|
|
6138
|
-
return "nil";
|
|
6139
|
-
}
|
|
6140
|
-
if (typeof value === "boolean") {
|
|
6141
|
-
return value ? "true" : "false";
|
|
6142
|
-
}
|
|
6143
|
-
if (typeof value === "number") {
|
|
6144
|
-
return String(value);
|
|
6145
|
-
}
|
|
6146
|
-
if (typeof value === "string") {
|
|
6147
|
-
const escaped = value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
|
|
6148
|
-
return `"${escaped}"`;
|
|
6149
|
-
}
|
|
6150
|
-
if (Array.isArray(value)) {
|
|
6151
|
-
if (value.length === 0) {
|
|
6152
|
-
return "{}";
|
|
6153
|
-
}
|
|
6154
|
-
const items = value.map((v) => `${spaces}${toLua(v, indent + 2)}`);
|
|
6155
|
-
return `{
|
|
6156
|
-
${items.join(`,
|
|
6157
|
-
`)}
|
|
6158
|
-
${" ".repeat(indent - 2)}}`;
|
|
6159
|
-
}
|
|
6160
|
-
if (typeof value === "object") {
|
|
6161
|
-
const entries = Object.entries(value);
|
|
6162
|
-
if (entries.length === 0) {
|
|
6163
|
-
return "{}";
|
|
6164
|
-
}
|
|
6165
|
-
const items = entries.map(([k, v]) => {
|
|
6166
|
-
const key = /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(k) ? k : `["${k}"]`;
|
|
6167
|
-
return `${spaces}${key} = ${toLua(v, indent + 2)}`;
|
|
6168
|
-
});
|
|
6169
|
-
return `{
|
|
6170
|
-
${items.join(`,
|
|
6171
|
-
`)}
|
|
6172
|
-
${" ".repeat(indent - 2)}}`;
|
|
6173
|
-
}
|
|
6174
|
-
return "nil";
|
|
6175
|
-
}
|
|
6176
|
-
function generateOptsSection(opts) {
|
|
6177
|
-
if (!opts || Object.keys(opts).length === 0) {
|
|
6178
|
-
return "";
|
|
6179
|
-
}
|
|
6180
|
-
return ` opts = ${toLua(opts, 6)},`;
|
|
6181
|
-
}
|
|
6182
|
-
function generateNeovimConfig(theme, mode) {
|
|
6183
|
-
if (!theme.neovim) {
|
|
6184
|
-
return "";
|
|
6185
|
-
}
|
|
6186
|
-
const { repo, colorscheme, light_colorscheme, opts } = theme.neovim;
|
|
6187
|
-
const effectiveColorscheme = mode === "light" && light_colorscheme ? light_colorscheme : colorscheme;
|
|
6188
|
-
const optsSection = generateOptsSection(opts);
|
|
6189
|
-
const hasDualMode = light_colorscheme && light_colorscheme !== colorscheme;
|
|
6190
|
-
const lines = [
|
|
6191
|
-
`-- ${theme.title} (${mode}) - Generated by FormalConf`,
|
|
6192
|
-
`-- Neovim colorscheme configuration for LazyVim`,
|
|
6193
|
-
``,
|
|
6194
|
-
`return {`,
|
|
6195
|
-
` {`,
|
|
6196
|
-
` "${repo}",`,
|
|
6197
|
-
` name = "${theme.title.toLowerCase().replace(/\s+/g, "-")}",`,
|
|
6198
|
-
` priority = 1000,`
|
|
6199
|
-
];
|
|
6200
|
-
if (optsSection) {
|
|
6201
|
-
lines.push(optsSection);
|
|
6202
|
-
}
|
|
6203
|
-
lines.push(` },`, ` {`, ` "LazyVim/LazyVim",`, ` opts = {`, ` colorscheme = "${effectiveColorscheme}",`, ` },`, ` },`);
|
|
6204
|
-
if (hasDualMode) {
|
|
6205
|
-
lines.push(` {`, ` "f-person/auto-dark-mode.nvim",`, ` opts = {`, ` update_background = false,`, ` set_dark_mode = function()`, ` vim.cmd("colorscheme ${colorscheme}")`, ` end,`, ` set_light_mode = function()`, ` vim.cmd("colorscheme ${light_colorscheme}")`, ` end,`, ` },`, ` },`);
|
|
6206
|
-
}
|
|
6207
|
-
lines.push(`}`);
|
|
6208
|
-
return lines.join(`
|
|
6209
|
-
`) + `
|
|
6210
|
-
`;
|
|
6211
|
-
}
|
|
6212
|
-
function hasNeovimConfig(theme) {
|
|
6213
|
-
return !!theme.neovim?.repo && !!theme.neovim?.colorscheme;
|
|
6214
|
-
}
|
|
6215
|
-
|
|
6216
6150
|
// src/lib/template-engine/engine.ts
|
|
6217
6151
|
function buildThemeMetadata(theme, mode) {
|
|
6218
6152
|
return {
|
|
@@ -6232,7 +6166,7 @@ function buildGtkMetadata(theme, mode) {
|
|
|
6232
6166
|
};
|
|
6233
6167
|
}
|
|
6234
6168
|
function buildTemplateContext(theme, palette, mode) {
|
|
6235
|
-
|
|
6169
|
+
const context = {
|
|
6236
6170
|
color0: hexToColorVariable(palette.color0),
|
|
6237
6171
|
color1: hexToColorVariable(palette.color1),
|
|
6238
6172
|
color2: hexToColorVariable(palette.color2),
|
|
@@ -6260,6 +6194,15 @@ function buildTemplateContext(theme, palette, mode) {
|
|
|
6260
6194
|
gtk: buildGtkMetadata(theme, mode),
|
|
6261
6195
|
mode
|
|
6262
6196
|
};
|
|
6197
|
+
if (theme.neovim) {
|
|
6198
|
+
context.neovim = {
|
|
6199
|
+
repo: theme.neovim.repo,
|
|
6200
|
+
colorscheme: theme.neovim.colorscheme,
|
|
6201
|
+
light_colorscheme: theme.neovim.light_colorscheme,
|
|
6202
|
+
opts: theme.neovim.opts
|
|
6203
|
+
};
|
|
6204
|
+
}
|
|
6205
|
+
return context;
|
|
6263
6206
|
}
|
|
6264
6207
|
function buildDualModeContext(theme) {
|
|
6265
6208
|
if (!theme.dark || !theme.light) {
|
|
@@ -6332,31 +6275,9 @@ async function writeRenderedTemplates(results) {
|
|
|
6332
6275
|
await writeFile(result.outputPath, result.content);
|
|
6333
6276
|
}
|
|
6334
6277
|
}
|
|
6335
|
-
async function generateNeovimConfigFile(theme, mode) {
|
|
6336
|
-
if (!hasNeovimConfig(theme)) {
|
|
6337
|
-
return null;
|
|
6338
|
-
}
|
|
6339
|
-
const content = generateNeovimConfig(theme, mode);
|
|
6340
|
-
const outputPath = join10(GENERATED_DIR, "neovim.lua");
|
|
6341
|
-
await writeFile(outputPath, content);
|
|
6342
|
-
return {
|
|
6343
|
-
template: {
|
|
6344
|
-
name: "neovim.lua",
|
|
6345
|
-
path: "",
|
|
6346
|
-
outputName: "neovim.lua",
|
|
6347
|
-
type: "single"
|
|
6348
|
-
},
|
|
6349
|
-
content,
|
|
6350
|
-
outputPath
|
|
6351
|
-
};
|
|
6352
|
-
}
|
|
6353
6278
|
async function generateThemeConfigs(theme, mode) {
|
|
6354
6279
|
const results = await renderAllTemplates(theme, mode);
|
|
6355
6280
|
await writeRenderedTemplates(results);
|
|
6356
|
-
const neovimResult = await generateNeovimConfigFile(theme, mode);
|
|
6357
|
-
if (neovimResult) {
|
|
6358
|
-
results.push(neovimResult);
|
|
6359
|
-
}
|
|
6360
6281
|
return results;
|
|
6361
6282
|
}
|
|
6362
6283
|
|
|
@@ -6827,12 +6748,13 @@ async function applyJsonTheme(themePath, mode, saveMapping, identifier) {
|
|
|
6827
6748
|
rmSync(BACKGROUNDS_TARGET_DIR, { recursive: true, force: true });
|
|
6828
6749
|
}
|
|
6829
6750
|
const results = await generateThemeConfigs(theme, mode);
|
|
6830
|
-
const ghosttyThemesDir = join13(HOME_DIR, ".config", "ghostty", "themes");
|
|
6831
6751
|
for (const result of results) {
|
|
6832
6752
|
const filename = basename4(result.outputPath);
|
|
6833
|
-
|
|
6834
|
-
|
|
6835
|
-
const
|
|
6753
|
+
const templateTargets = result.template.targets ?? [];
|
|
6754
|
+
for (const target of templateTargets) {
|
|
6755
|
+
const expandedTarget = target.replace(/^~/, HOME_DIR);
|
|
6756
|
+
await ensureDir2(expandedTarget);
|
|
6757
|
+
const targetPath2 = join13(expandedTarget, filename);
|
|
6836
6758
|
copyFileSync2(result.outputPath, targetPath2);
|
|
6837
6759
|
}
|
|
6838
6760
|
const targetPath = join13(THEME_TARGET_DIR, filename);
|
package/package.json
CHANGED