fix(compiler-sfc): fix skipped srcset transform when using base option

Based on implementation from #4835 due to conflicts

fix #4819
close #4834, close #4835
This commit is contained in:
Evan You 2022-05-11 16:55:58 +08:00
parent 57bb37bd64
commit 41d255ba5d
3 changed files with 48 additions and 13 deletions

View File

@ -1,5 +1,23 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`compiler sfc: transform srcset srcset w/ explicit base option 1`] = `
"import { createElementVNode as _createElementVNode, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock } from \\"vue\\"
import _imports_0 from '@/logo.png'
const _hoisted_1 = _imports_0 + ', ' + _imports_0 + ' 2x'
const _hoisted_2 = _imports_0 + ' 1x, ' + \\"/foo/logo.png\\" + ' 2x'
const _hoisted_3 = /*#__PURE__*/_createElementVNode(\\"img\\", { srcset: _hoisted_1 }, null, -1 /* HOISTED */)
const _hoisted_4 = /*#__PURE__*/_createElementVNode(\\"img\\", { srcset: _hoisted_2 }, null, -1 /* HOISTED */)
export function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock(_Fragment, null, [
_hoisted_3,
_hoisted_4
], 64 /* STABLE_FRAGMENT */))
}"
`;
exports[`compiler sfc: transform srcset transform srcset 1`] = ` exports[`compiler sfc: transform srcset transform srcset 1`] = `
"import { createElementVNode as _createElementVNode, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock } from \\"vue\\" "import { createElementVNode as _createElementVNode, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock } from \\"vue\\"
import _imports_0 from './logo.png' import _imports_0 from './logo.png'

View File

@ -86,4 +86,16 @@ describe('compiler sfc: transform srcset', () => {
expect(code).toMatch(`_createStaticVNode`) expect(code).toMatch(`_createStaticVNode`)
expect(code).toMatchSnapshot() expect(code).toMatchSnapshot()
}) })
test('srcset w/ explicit base option', () => {
const code = compileWithSrcset(
`
<img srcset="@/logo.png, @/logo.png 2x"/>
<img srcset="@/logo.png 1x, ./logo.png 2x"/>
`,
{ base: '/foo/' },
{ hoistStatic: true }
).code
expect(code).toMatchSnapshot()
})
}) })

View File

@ -69,40 +69,45 @@ export const transformSrcset: NodeTransform = (
} }
} }
const hasQualifiedUrl = imageCandidates.some(({ url }) => { const shouldProcessUrl = (url: string) => {
return ( return (
!isExternalUrl(url) && !isExternalUrl(url) &&
!isDataUrl(url) && !isDataUrl(url) &&
(options.includeAbsolute || isRelativeUrl(url)) (options.includeAbsolute || isRelativeUrl(url))
) )
}) }
// When srcset does not contain any qualified URLs, skip transforming // When srcset does not contain any qualified URLs, skip transforming
if (!hasQualifiedUrl) { if (!imageCandidates.some(({ url }) => shouldProcessUrl(url))) {
return return
} }
if (options.base) { if (options.base) {
const base = options.base const base = options.base
const set: string[] = [] const set: string[] = []
imageCandidates.forEach(({ url, descriptor }) => { let needImportTransform = false
imageCandidates.forEach(candidate => {
let { url, descriptor } = candidate
descriptor = descriptor ? ` ${descriptor}` : `` descriptor = descriptor ? ` ${descriptor}` : ``
if (isRelativeUrl(url)) { if (url[0] === '.') {
set.push((path.posix || path).join(base, url) + descriptor) candidate.url = (path.posix || path).join(base, url)
set.push(candidate.url + descriptor)
} else if (shouldProcessUrl(url)) {
needImportTransform = true
} else { } else {
set.push(url + descriptor) set.push(url + descriptor)
} }
}) })
attr.value.content = set.join(', ')
return if (!needImportTransform) {
attr.value.content = set.join(', ')
return
}
} }
const compoundExpression = createCompoundExpression([], attr.loc) const compoundExpression = createCompoundExpression([], attr.loc)
imageCandidates.forEach(({ url, descriptor }, index) => { imageCandidates.forEach(({ url, descriptor }, index) => {
if ( if (shouldProcessUrl(url)) {
!isExternalUrl(url) &&
!isDataUrl(url) &&
(options.includeAbsolute || isRelativeUrl(url))
) {
const { path } = parseUrl(url) const { path } = parseUrl(url)
let exp: SimpleExpressionNode let exp: SimpleExpressionNode
if (path) { if (path) {