fix(compiler-sfc): transformAssetUrl should ignore inline data url (#1431)
This commit is contained in:
		
							parent
							
								
									37a5952c09
								
							
						
					
					
						commit
						90c285c5c8
					
				| @ -32,7 +32,8 @@ export function render(_ctx, _cache) { | |||||||
|     _createVNode(\\"img\\", { src: _imports_1 }), |     _createVNode(\\"img\\", { src: _imports_1 }), | ||||||
|     _createVNode(\\"img\\", { src: _imports_1 }), |     _createVNode(\\"img\\", { src: _imports_1 }), | ||||||
|     _createVNode(\\"img\\", { src: \\"http://example.com/fixtures/logo.png\\" }), |     _createVNode(\\"img\\", { src: \\"http://example.com/fixtures/logo.png\\" }), | ||||||
|     _createVNode(\\"img\\", { src: \\"/fixtures/logo.png\\" }) |     _createVNode(\\"img\\", { src: \\"/fixtures/logo.png\\" }), | ||||||
|  |     _createVNode(\\"img\\", { src: \\"data:image/png;base64,i\\" }) | ||||||
|   ], 64 /* STABLE_FRAGMENT */)) |   ], 64 /* STABLE_FRAGMENT */)) | ||||||
| }" | }" | ||||||
| `; | `; | ||||||
|  | |||||||
| @ -55,6 +55,10 @@ export function render(_ctx, _cache) { | |||||||
|     _createVNode(\\"img\\", { |     _createVNode(\\"img\\", { | ||||||
|       src: \\"/logo.png\\", |       src: \\"/logo.png\\", | ||||||
|       srcset: _hoisted_8 |       srcset: _hoisted_8 | ||||||
|  |     }), | ||||||
|  |     _createVNode(\\"img\\", { | ||||||
|  |       src: \\"data:image/png;base64,i\\", | ||||||
|  |       srcset: \\"data:image/png;base64,i 1x, data:image/png;base64,i 2x\\" | ||||||
|     }) |     }) | ||||||
|   ], 64 /* STABLE_FRAGMENT */)) |   ], 64 /* STABLE_FRAGMENT */)) | ||||||
| }" | }" | ||||||
| @ -104,6 +108,10 @@ export function render(_ctx, _cache) { | |||||||
|     _createVNode(\\"img\\", { |     _createVNode(\\"img\\", { | ||||||
|       src: \\"/logo.png\\", |       src: \\"/logo.png\\", | ||||||
|       srcset: \\"/logo.png, /foo/logo.png 2x\\" |       srcset: \\"/logo.png, /foo/logo.png 2x\\" | ||||||
|  |     }), | ||||||
|  |     _createVNode(\\"img\\", { | ||||||
|  |       src: \\"data:image/png;base64,i\\", | ||||||
|  |       srcset: \\"data:image/png;base64,i 1x, data:image/png;base64,i 2x\\" | ||||||
|     }) |     }) | ||||||
|   ], 64 /* STABLE_FRAGMENT */)) |   ], 64 /* STABLE_FRAGMENT */)) | ||||||
| }" | }" | ||||||
| @ -125,6 +133,7 @@ const _hoisted_7 = _imports_0 + ', ' + _imports_0 + '2x, ' + _imports_0 + '3x' | |||||||
| const _hoisted_8 = _imports_1 + ', ' + _imports_1 + '2x' | const _hoisted_8 = _imports_1 + ', ' + _imports_1 + '2x' | ||||||
| const _hoisted_9 = \\"https://example.com/logo.png\\" + ', ' + \\"https://example.com/logo.png\\" + '2x' | const _hoisted_9 = \\"https://example.com/logo.png\\" + ', ' + \\"https://example.com/logo.png\\" + '2x' | ||||||
| const _hoisted_10 = _imports_1 + ', ' + _imports_0 + '2x' | const _hoisted_10 = _imports_1 + ', ' + _imports_0 + '2x' | ||||||
|  | const _hoisted_11 = \\"data:image/png;base64,i\\" + '1x, ' + \\"data:image/png;base64,i\\" + '2x' | ||||||
| 
 | 
 | ||||||
| export function render(_ctx, _cache) { | export function render(_ctx, _cache) { | ||||||
|   return (_openBlock(), _createBlock(_Fragment, null, [ |   return (_openBlock(), _createBlock(_Fragment, null, [ | ||||||
| @ -167,6 +176,10 @@ export function render(_ctx, _cache) { | |||||||
|     _createVNode(\\"img\\", { |     _createVNode(\\"img\\", { | ||||||
|       src: \\"/logo.png\\", |       src: \\"/logo.png\\", | ||||||
|       srcset: _hoisted_10 |       srcset: _hoisted_10 | ||||||
|  |     }), | ||||||
|  |     _createVNode(\\"img\\", { | ||||||
|  |       src: \\"data:image/png;base64,i\\", | ||||||
|  |       srcset: _hoisted_11 | ||||||
|     }) |     }) | ||||||
|   ], 64 /* STABLE_FRAGMENT */)) |   ], 64 /* STABLE_FRAGMENT */)) | ||||||
| }" | }" | ||||||
|  | |||||||
| @ -30,6 +30,7 @@ describe('compiler sfc: transform asset url', () => { | |||||||
| 			<img src="~/fixtures/logo.png"/> | 			<img src="~/fixtures/logo.png"/> | ||||||
| 			<img src="http://example.com/fixtures/logo.png"/> | 			<img src="http://example.com/fixtures/logo.png"/> | ||||||
| 			<img src="/fixtures/logo.png"/> | 			<img src="/fixtures/logo.png"/> | ||||||
|  | 			<img src="data:image/png;base64,i"/> | ||||||
| 		`)
 | 		`)
 | ||||||
| 
 | 
 | ||||||
|     expect(result.code).toMatchSnapshot() |     expect(result.code).toMatchSnapshot() | ||||||
|  | |||||||
| @ -35,6 +35,7 @@ const src = ` | |||||||
| <img src="/logo.png" srcset="/logo.png, /logo.png 2x"/> | <img src="/logo.png" srcset="/logo.png, /logo.png 2x"/> | ||||||
| <img src="https://example.com/logo.png" srcset="https://example.com/logo.png, https://example.com/logo.png 2x"/> | <img src="https://example.com/logo.png" srcset="https://example.com/logo.png, https://example.com/logo.png 2x"/> | ||||||
| <img src="/logo.png" srcset="/logo.png, ./logo.png 2x"/> | <img src="/logo.png" srcset="/logo.png, ./logo.png 2x"/> | ||||||
|  | <img src="data:image/png;base64,i" srcset="data:image/png;base64,i 1x, data:image/png;base64,i 2x"/> | ||||||
| ` | ` | ||||||
| 
 | 
 | ||||||
| describe('compiler sfc: transform srcset', () => { | describe('compiler sfc: transform srcset', () => { | ||||||
|  | |||||||
| @ -1,6 +1,7 @@ | |||||||
| import { | import { | ||||||
|   isRelativeUrl, |   isRelativeUrl, | ||||||
|   isExternalUrl |   isExternalUrl, | ||||||
|  |   isDataUrl | ||||||
| } from '../../compiler-sfc/src/templateUtils' | } from '../../compiler-sfc/src/templateUtils' | ||||||
| 
 | 
 | ||||||
| describe('compiler sfc:templateUtils isRelativeUrl', () => { | describe('compiler sfc:templateUtils isRelativeUrl', () => { | ||||||
| @ -36,3 +37,17 @@ describe('compiler sfc:templateUtils isExternalUrl', () => { | |||||||
|     expect(result).toBe(true) |     expect(result).toBe(true) | ||||||
|   }) |   }) | ||||||
| }) | }) | ||||||
|  | 
 | ||||||
|  | describe('compiler sfc:templateUtils isDataUrl', () => { | ||||||
|  |   test('should return true w/ hasn`t media type and encode', () => { | ||||||
|  |     expect(isDataUrl('data:,i')).toBe(true) | ||||||
|  |   }) | ||||||
|  | 
 | ||||||
|  |   test('should return true w/ media type + encode', () => { | ||||||
|  |     expect(isDataUrl('data:image/png;base64,i')).toBe(true) | ||||||
|  |   }) | ||||||
|  | 
 | ||||||
|  |   test('should return true w/ media type + hasn`t encode', () => { | ||||||
|  |     expect(isDataUrl('data:image/png,i')).toBe(true) | ||||||
|  |   }) | ||||||
|  | }) | ||||||
|  | |||||||
| @ -7,7 +7,12 @@ import { | |||||||
|   SourceLocation, |   SourceLocation, | ||||||
|   TransformContext |   TransformContext | ||||||
| } from '@vue/compiler-core' | } from '@vue/compiler-core' | ||||||
| import { isRelativeUrl, parseUrl, isExternalUrl } from './templateUtils' | import { | ||||||
|  |   isRelativeUrl, | ||||||
|  |   parseUrl, | ||||||
|  |   isExternalUrl, | ||||||
|  |   isDataUrl | ||||||
|  | } from './templateUtils' | ||||||
| import { isArray } from '@vue/shared' | import { isArray } from '@vue/shared' | ||||||
| 
 | 
 | ||||||
| export interface AssetURLTagConfig { | export interface AssetURLTagConfig { | ||||||
| @ -99,6 +104,7 @@ export const transformAssetUrl: NodeTransform = ( | |||||||
|         !assetAttrs.includes(attr.name) || |         !assetAttrs.includes(attr.name) || | ||||||
|         !attr.value || |         !attr.value || | ||||||
|         isExternalUrl(attr.value.content) || |         isExternalUrl(attr.value.content) || | ||||||
|  |         isDataUrl(attr.value.content) || | ||||||
|         attr.value.content[0] === '#' || |         attr.value.content[0] === '#' || | ||||||
|         (!options.includeAbsolute && !isRelativeUrl(attr.value.content)) |         (!options.includeAbsolute && !isRelativeUrl(attr.value.content)) | ||||||
|       ) { |       ) { | ||||||
|  | |||||||
| @ -6,7 +6,12 @@ import { | |||||||
|   NodeTypes, |   NodeTypes, | ||||||
|   SimpleExpressionNode |   SimpleExpressionNode | ||||||
| } from '@vue/compiler-core' | } from '@vue/compiler-core' | ||||||
| import { isRelativeUrl, parseUrl, isExternalUrl } from './templateUtils' | import { | ||||||
|  |   isRelativeUrl, | ||||||
|  |   parseUrl, | ||||||
|  |   isExternalUrl, | ||||||
|  |   isDataUrl | ||||||
|  | } from './templateUtils' | ||||||
| import { | import { | ||||||
|   AssetURLOptions, |   AssetURLOptions, | ||||||
|   defaultAssetUrlOptions |   defaultAssetUrlOptions | ||||||
| @ -51,6 +56,15 @@ export const transformSrcset: NodeTransform = ( | |||||||
|             return { url, descriptor } |             return { url, descriptor } | ||||||
|           }) |           }) | ||||||
| 
 | 
 | ||||||
|  |           // for data url need recheck url
 | ||||||
|  |           for (let i = 0; i < imageCandidates.length; i++) { | ||||||
|  |             if (imageCandidates[i].url.trim().startsWith('data:')) { | ||||||
|  |               imageCandidates[i + 1].url = | ||||||
|  |                 imageCandidates[i].url + ',' + imageCandidates[i + 1].url | ||||||
|  |               imageCandidates.splice(i, 1) | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  | 
 | ||||||
|           // When srcset does not contain any relative URLs, skip transforming
 |           // When srcset does not contain any relative URLs, skip transforming
 | ||||||
|           if ( |           if ( | ||||||
|             !options.includeAbsolute && |             !options.includeAbsolute && | ||||||
| @ -78,6 +92,7 @@ export const transformSrcset: NodeTransform = ( | |||||||
|           imageCandidates.forEach(({ url, descriptor }, index) => { |           imageCandidates.forEach(({ url, descriptor }, index) => { | ||||||
|             if ( |             if ( | ||||||
|               !isExternalUrl(url) && |               !isExternalUrl(url) && | ||||||
|  |               !isDataUrl(url) && | ||||||
|               (options.includeAbsolute || isRelativeUrl(url)) |               (options.includeAbsolute || isRelativeUrl(url)) | ||||||
|             ) { |             ) { | ||||||
|               const { path } = parseUrl(url) |               const { path } = parseUrl(url) | ||||||
|  | |||||||
| @ -11,6 +11,11 @@ export function isExternalUrl(url: string): boolean { | |||||||
|   return externalRE.test(url) |   return externalRE.test(url) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | const dataUrlRE = /^\s*data:/i | ||||||
|  | export function isDataUrl(url: string): boolean { | ||||||
|  |   return dataUrlRE.test(url) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /** | /** | ||||||
|  * Parses string url into URL object. |  * Parses string url into URL object. | ||||||
|  */ |  */ | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user