refactor(frontend): share path template formatting

This commit is contained in:
Dariusz L
2026-08-06 18:22:56 +02:00
parent 1aeec3eded
commit c164d8d676
3 changed files with 75 additions and 12 deletions
@@ -4038,6 +4038,70 @@ test('download subfolder and path template normalization apply the same segment
);
});
test('download path templates render metadata into the configured subfolder', () => {
const formatDownloadPathTemplate = eval(
`(${extractMethod(downloadTargetMethodsSource, 'formatDownloadPathTemplate')})`
);
const calculateDownloadPathTemplateSubfolder = eval(
`(${extractMethod(downloadTargetMethodsSource, 'calculateDownloadPathTemplateSubfolder')})`
);
const dialog = {
getDownloadPathTemplates() {
return { loras: '{base_model}/{author}/{first_tag}/{model_name}/{version_name}/{unknown}' };
},
normalizeDownloadCategory(value) {
return value;
},
formatDownloadPathTemplate,
normalizeDownloadPathValue(value) {
return String(value || '').replace(/\\/g, '/');
},
getBaseModelPathMappings() {
return { Pony: 'SDXL/Pony' };
},
resolveBaseModelPathMapping(value, mappings) {
return mappings[value] || value;
},
sanitizeDownloadPathValue(value, fallback) {
return value || fallback;
},
sanitizeDownloadPathSegment(value, fallback) {
return value || fallback;
},
getPriorityDownloadTag(tags) {
return tags?.[0] || '';
},
normalizeTemplateSubfolder(value) {
return String(value || '')
.split('/')
.filter(Boolean)
.join('/');
},
};
assert.equal(
calculateDownloadPathTemplateSubfolder.call(dialog, 'loras', {
base_model: 'Pony',
author: 'Creator',
tags: ['Style'],
model_name: 'Model',
version_name: 'v1',
}),
'SDXL/Pony/Creator/Style/Model/v1'
);
assert.equal(
formatDownloadPathTemplate.call(dialog, '{base_model}/{unknown}', {
'{base_model}': 'SDXL',
}),
'SDXL'
);
});
test('options path preview delegates token rendering to the shared template formatter', () => {
assert.match(optionsMethodsSource, /this\.formatDownloadPathTemplate\(template, replacements\)/);
assert.doesNotMatch(optionsMethodsSource, /formatted\.split\(token\)\.join\(value\)/);
});
test('download subfolder tooltip identifies a folder taken from the workflow model path', () => {
const getDownloadSubfolderSuggestionReason = eval(`(${extractMethod(downloadTargetMethodsSource, 'getDownloadSubfolderSuggestionReason')})`);
const dialog = {
+10 -6
View File
@@ -1218,6 +1218,15 @@ export const downloadTargetMethods = {
return list[0];
},
formatDownloadPathTemplate(template = '', replacements = {}) {
let formatted = this.normalizeDownloadPathValue(template);
Object.entries(replacements).forEach(([token, value]) => {
formatted = formatted.split(token).join(value);
});
formatted = formatted.replace(/\{[^{}]+\}/g, '');
return this.normalizeTemplateSubfolder(formatted);
},
getDownloadSourceContext(missing = {}, source = {}, { respectProvenanceBoundary = true } = {}) {
const sourceData = source && typeof source === 'object' ? source : {};
const isProvidedUrl = Boolean(
@@ -1482,12 +1491,7 @@ export const downloadTargetMethods = {
'{model_name}': this.sanitizeDownloadPathSegment(metadata.model_name || metadata.name || metadata.filename?.replace(/\.[^.]+$/, '') || 'Model', 'Model'),
'{version_name}': this.sanitizeDownloadPathSegment(metadata.version_name || metadata.versionName || metadata.version || '', '')
};
let formatted = template;
Object.entries(replacements).forEach(([token, value]) => {
formatted = formatted.split(token).join(value);
});
formatted = formatted.replace(/\{[^{}]+\}/g, '');
return this.normalizeTemplateSubfolder(formatted);
return this.formatDownloadPathTemplate(template, replacements);
},
isAutoFillSubfolderEnabled() {
+1 -6
View File
@@ -2926,12 +2926,7 @@ export const optionsMethods = {
'{model_name}': this.sanitizeDownloadPathSegment(pathPreviewMetadata.model_name, 'Model'),
'{version_name}': this.sanitizeDownloadPathSegment(pathPreviewMetadata.version_name, '')
};
let formatted = this.normalizeDownloadPathValue(template);
Object.entries(replacements).forEach(([token, value]) => {
formatted = formatted.split(token).join(value);
});
formatted = formatted.replace(/\{[^{}]+\}/g, '');
return this.normalizeTemplateSubfolder(formatted) || '(flat folder)';
return this.formatDownloadPathTemplate(template, replacements) || '(flat folder)';
};
const syncTemplateControl = (categoryKey) => {