refactor(frontend): share path template formatting
This commit is contained in:
@@ -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 = {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
Reference in New Issue
Block a user