Resolve external canvas asset references

This commit is contained in:
Codex
2026-05-11 21:09:57 +08:00
parent 1d76cca082
commit 91cba60e5e

View File

@@ -319,6 +319,12 @@ function getExternalAssetKey(value?: unknown) {
return '';
}
function looksLikeExternalAssetPath(value: string) {
return value.includes('/assets/')
|| value.startsWith('assets/')
|| /\.(png|jpe?g|webp|gif|avif)$/i.test(value);
}
function getAssetLookupKeys(pathOrName: string) {
const normalized = pathOrName.replace(/\\/g, '/').replace(/^\.?\//, '');
const name = normalized.split('/').pop() || normalized;
@@ -335,25 +341,75 @@ function getAssetLookupKeys(pathOrName: string) {
].filter(Boolean)));
}
function collectExternalAssetReferenceKeys(value: unknown) {
const keys = new Set<string>();
if (typeof value === 'string' && value) {
const assetKey = getExternalAssetKey(value);
if (assetKey) keys.add(assetKey);
if (looksLikeExternalAssetPath(value)) {
getAssetLookupKeys(value).forEach(key => keys.add(key));
}
} else if (value && typeof value === 'object' && !Array.isArray(value)) {
const input = value as Record<string, unknown>;
[
input.assetId,
input.asset_id,
input.fileId,
input.file_id,
input.imageAssetId,
input.image_asset_id,
input.path,
input.filePath,
input.file_path,
input.name,
input.fileName,
input.filename,
input.url,
input.src,
input.fullUrl,
input.thumbUrl,
].forEach(item => {
collectExternalAssetReferenceKeys(item).forEach(key => keys.add(key));
});
}
return keys;
}
function resolveExternalAssetUrl(value: unknown, assetMap?: ExternalAssetMap) {
if (typeof value !== 'string' || !value) return '';
const assetKey = getExternalAssetKey(value);
return assetKey ? assetMap?.get(assetKey)?.url || '' : value;
if (typeof value === 'string') {
if (!value) return '';
const assetKey = getExternalAssetKey(value);
if (assetKey) return assetMap?.get(assetKey)?.url || '';
for (const key of getAssetLookupKeys(value)) {
const resolved = assetMap?.get(key)?.url;
if (resolved) return resolved;
}
return value;
}
if (value && typeof value === 'object' && !Array.isArray(value)) {
const input = value as Record<string, unknown>;
const directUrl = firstString(input.url, input.src, input.fullUrl, input.thumbUrl);
if (directUrl) return resolveExternalAssetUrl(directUrl, assetMap);
for (const key of collectExternalAssetReferenceKeys(input)) {
const resolved = assetMap?.get(key)?.url;
if (resolved) return resolved;
}
}
return '';
}
function collectExternalAssetKeys(value: unknown, keys = new Set<string>()) {
if (typeof value === 'string') {
const key = getExternalAssetKey(value);
if (key) keys.add(key);
if (typeof value === 'string' || (value && typeof value === 'object' && !Array.isArray(value))) {
collectExternalAssetReferenceKeys(value).forEach(key => keys.add(key));
if (typeof value !== 'string') {
Object.values(value as Record<string, unknown>).forEach(item => collectExternalAssetKeys(item, keys));
}
return keys;
}
if (Array.isArray(value)) {
value.forEach(item => collectExternalAssetKeys(item, keys));
return keys;
}
if (value && typeof value === 'object') {
Object.values(value as Record<string, unknown>).forEach(item => collectExternalAssetKeys(item, keys));
}
return keys;
}
@@ -376,7 +432,12 @@ function getImportCanvasCandidate(payload: unknown) {
function normalizeExternalNodeType(type: string, node: Record<string, unknown>, settings: Record<string, unknown>): CanvasNodeType {
const normalized = type.toLowerCase().replace(/[_\s-]+/g, '');
const hasImageContent = !!firstString(node.content, node.imageUrl, node.url, node.src);
const data = asRecord(node.data);
const hasImageContent = !!(
firstString(node.content, node.imageUrl, node.url, node.src, data.imageUrl, data.url, settings.imageUrl, settings.url)
|| collectExternalAssetReferenceKeys(node.content).size > 0
|| collectExternalAssetReferenceKeys(data.imageUrl).size > 0
);
const hasPrompt = !!firstString(node.prompt, settings.prompt);
if (normalized.includes('img2img') || normalized.includes('imagetoimage')) return 'img2img';
if (normalized.includes('text2img') || normalized.includes('txt2img') || normalized.includes('texttoimage')) return 'text2img';
@@ -449,17 +510,15 @@ function convertExternalCanvasProject(value: unknown, assetMap?: ExternalAssetMa
updatedAt: createdAt,
};
}
const contentUrl = resolveExternalAssetUrl(node.content || node.imageUrl || node.url || node.src || data.imageUrl || data.url, assetMap);
const thumbnailUrl = resolveExternalAssetUrl(node.thumbnailUrl || node.thumbnail || data.thumbnailUrl, assetMap);
const contentUrl = resolveExternalAssetUrl(node.content || node.imageUrl || node.url || node.src || data.imageUrl || data.url || settings.imageUrl || settings.url, assetMap);
const thumbnailUrl = resolveExternalAssetUrl(node.thumbnailUrl || node.thumbnail || data.thumbnailUrl || settings.thumbnailUrl || settings.thumbnail, assetMap);
const generatedImages = Array.isArray(settings.generatedImages) ? settings.generatedImages : [];
const outputImages = generatedImages
.map((item) => item && typeof item === 'object' ? item as Record<string, unknown> : null)
.map((item) => {
if (!item) return '';
const assetId = typeof item.assetId === 'string' ? item.assetId : '';
return assetId
? assetMap?.get(assetId)?.url || resolveExternalAssetUrl(item.fullUrl || item.thumbUrl, assetMap)
: resolveExternalAssetUrl(item.fullUrl || item.thumbUrl, assetMap);
if (typeof item === 'string') return resolveExternalAssetUrl(item, assetMap);
if (!item || typeof item !== 'object') return '';
const image = item as Record<string, unknown>;
return resolveExternalAssetUrl(image.fullUrl || image.url || image.src || image.thumbUrl || image.assetId || image, assetMap);
})
.filter(Boolean);
const imageUrl = outputImages[0] || contentUrl || thumbnailUrl;