feat(settings): redesign file naming as a two-column workbench

The three-column layout left the editor 270px wide at 1280 and broke resolved paths mid-word.
Draw the pattern one folder per line, preview it against long-name books, and list only what
missing metadata changes. Add resolvePlaceholders to the shared resolver to report fallbacks.
This commit is contained in:
neon
2026-10-01 02:46:15 +00:00
parent 2855dbb8a3
commit 4701412ef2
30 changed files with 2544 additions and 758 deletions
+24 -4
View File
@@ -131,9 +131,20 @@ function checkAllPlaceholdersPresent(block: string, values: Record<string, strin
});
}
export function replacePlaceholders(pattern: string, values: Record<string, string>): string {
export interface PlaceholderResolution {
text: string;
/** An optional group could not fill its primary side and used its `|fallback`. */
usedFallback: boolean;
/** An optional group with no fallback could not be filled and resolved to nothing. */
droppedOptional: boolean;
}
/** replacePlaceholders, also reporting which optional-group branch each group took. */
export function resolvePlaceholders(pattern: string, values: Record<string, string>): PlaceholderResolution {
let usedFallback = false;
let droppedOptional = false;
// Handle optional blocks with else clause: <primary|fallback>
pattern = pattern.replace(/<([^<>]+)>/g, (_, blockContent: string) => {
const resolved = pattern.replace(/<([^<>]+)>/g, (_, blockContent: string) => {
const pipeIndex = blockContent.indexOf("|");
const primary = pipeIndex >= 0 ? blockContent.substring(0, pipeIndex) : blockContent;
const fallback = pipeIndex >= 0 ? blockContent.substring(pipeIndex + 1) : null;
@@ -141,10 +152,19 @@ export function replacePlaceholders(pattern: string, values: Record<string, stri
if (checkAllPlaceholdersPresent(primary, values)) {
return resolveModifierPlaceholders(primary, values);
}
return fallback != null ? resolveModifierPlaceholders(fallback, values) : "";
if (fallback != null) {
usedFallback = true;
return resolveModifierPlaceholders(fallback, values);
}
droppedOptional = true;
return "";
});
return resolveModifierPlaceholders(pattern, values).trim();
return { text: resolveModifierPlaceholders(resolved, values).trim(), usedFallback, droppedOptional };
}
export function replacePlaceholders(pattern: string, values: Record<string, string>): string {
return resolvePlaceholders(pattern, values).text;
}
export function validatePattern(pattern: string): boolean {