From da82083df62922c60c5e29f3a78f92ea855ddb3a Mon Sep 17 00:00:00 2001 From: Haoqun Jiang Date: Sun, 16 Mar 2025 20:29:54 +0800 Subject: [PATCH] refactor: a bit of cleanup for better readability --- .../src/template/transformAssetUrl.ts | 171 ++++++++++-------- 1 file changed, 92 insertions(+), 79 deletions(-) diff --git a/packages/compiler-sfc/src/template/transformAssetUrl.ts b/packages/compiler-sfc/src/template/transformAssetUrl.ts index 56540ef1d..ee409d5c8 100644 --- a/packages/compiler-sfc/src/template/transformAssetUrl.ts +++ b/packages/compiler-sfc/src/template/transformAssetUrl.ts @@ -153,97 +153,110 @@ export const transformAssetUrl: NodeTransform = ( } } +/** + * Resolves or registers an import for the given source path + * @param source - Path to resolve import for + * @param loc - Source location + * @param context - Transform context + * @returns Object containing import name and expression + */ +function resolveOrRegisterImport( + source: string, + loc: SourceLocation, + context: TransformContext, +): { + name: string + exp: SimpleExpressionNode +} { + const existingIndex = context.imports.findIndex(i => i.path === source) + if (existingIndex > -1) { + return { + name: `_imports_${existingIndex}`, + exp: context.imports[existingIndex].exp as SimpleExpressionNode, + } + } + + const name = `_imports_${context.imports.length}` + const exp = createSimpleExpression( + name, + false, + loc, + ConstantTypes.CAN_STRINGIFY, + ) + + // We need to ensure the path is not encoded (to %2F), + // so we decode it back in case it is encoded + context.imports.push({ + exp, + path: decodeURIComponent(source), + }) + + return { name, exp } +} + +/** + * Transforms asset URLs into import expressions or string literals + */ function getImportsExpressionExp( path: string | null, hash: string | null, loc: SourceLocation, context: TransformContext, ): ExpressionNode { - if (path) { - let name: string - let exp: SimpleExpressionNode - const existingIndex = context.imports.findIndex(i => i.path === path) - if (existingIndex > -1) { - name = `_imports_${existingIndex}` - exp = context.imports[existingIndex].exp as SimpleExpressionNode - } else { - name = `_imports_${context.imports.length}` - exp = createSimpleExpression( - name, - false, - loc, - ConstantTypes.CAN_STRINGIFY, - ) + // Neither path nor hash - return empty string + if (!path && !hash) { + return createSimpleExpression(`''`, false, loc, ConstantTypes.CAN_STRINGIFY) + } - // We need to ensure the path is not encoded (to %2F), - // so we decode it back in case it is encoded - context.imports.push({ - exp, - path: decodeURIComponent(path), - }) - } + // Only hash without path - treat hash as the import source (likely a subpath import) + if (!path && hash) { + const { exp } = resolveOrRegisterImport(hash, loc, context) + return exp + } - if (!hash) { - return exp - } + // Only path without hash - straightforward import + if (path && !hash) { + const { exp } = resolveOrRegisterImport(path, loc, context) + return exp + } - const hashExp = `${name} + '${hash}'` - const finalExp = createSimpleExpression( - hashExp, + // At this point, we know we have both path and hash components + const { name } = resolveOrRegisterImport(path!, loc, context) + + // Combine path import with hash + const hashExp = `${name} + '${hash}'` + const finalExp = createSimpleExpression( + hashExp, + false, + loc, + ConstantTypes.CAN_STRINGIFY, + ) + + // No hoisting needed + if (!context.hoistStatic) { + return finalExp + } + + // Check for existing hoisted expression + const existingHoistIndex = context.hoists.findIndex(h => { + return ( + h && + h.type === NodeTypes.SIMPLE_EXPRESSION && + !h.isStatic && + h.content === hashExp + ) + }) + + // Return existing hoisted expression if found + if (existingHoistIndex > -1) { + return createSimpleExpression( + `_hoisted_${existingHoistIndex + 1}`, false, loc, ConstantTypes.CAN_STRINGIFY, ) - - if (!context.hoistStatic) { - return finalExp - } - - const existingHoistIndex = context.hoists.findIndex(h => { - return ( - h && - h.type === NodeTypes.SIMPLE_EXPRESSION && - !h.isStatic && - h.content === hashExp - ) - }) - if (existingHoistIndex > -1) { - return createSimpleExpression( - `_hoisted_${existingHoistIndex + 1}`, - false, - loc, - ConstantTypes.CAN_STRINGIFY, - ) - } - return context.hoist(finalExp) - } else if (hash) { - // Hash without path, e.g. subpath import - let name: string - let exp: SimpleExpressionNode - const existingIndex = context.imports.findIndex(i => i.path === hash) - - if (existingIndex > -1) { - name = `_imports_${existingIndex}` - exp = context.imports[existingIndex].exp as SimpleExpressionNode - } else { - name = `_imports_${context.imports.length}` - exp = createSimpleExpression( - name, - false, - loc, - ConstantTypes.CAN_STRINGIFY, - ) - - // We need to ensure the path is not encoded (to %2F), - // so we decode it back in case it is encoded - context.imports.push({ - exp, - path: decodeURIComponent(hash), - }) - } - - return exp - } else { - return createSimpleExpression(`''`, false, loc, ConstantTypes.CAN_STRINGIFY) } + + // Hoist the expression and return the hoisted expression + return context.hoist(finalExp) }