diff --git a/lib/templateCompilerModules/assetUrl.ts b/lib/templateCompilerModules/assetUrl.ts index b74b059..c40d57c 100644 --- a/lib/templateCompilerModules/assetUrl.ts +++ b/lib/templateCompilerModules/assetUrl.ts @@ -26,16 +26,26 @@ export default (userOptions?: AssetURLOptions) => { } function transform(node: ASTNode, options: AssetURLOptions) { + if (node.__assetUrlTransformed) { + return + } for (const tag in options) { - if ((tag === '*' || node.tag === tag) && node.attrs) { - const attributes = options[tag] + if (tag === '*' || node.tag === tag) { + let attributes = options[tag] if (typeof attributes === 'string') { - node.attrs.some(attr => rewrite(attr, attributes)) - } else if (Array.isArray(attributes)) { - attributes.forEach(item => node.attrs.some(attr => rewrite(attr, item))) + attributes = [attributes] + } + if (node.staticStyle && attributes.indexOf('style') > -1) { + node.staticStyle = rewriteStaticStyle(node.staticStyle) + } + if (node.attrs) { + attributes.filter(attr => attr !== 'style').forEach(attrName => { + node.attrs.some(attr => rewrite(attr, attrName)) + }) } } } + node.__assetUrlTransformed = true } function rewrite(attr: Attr, name: string) { @@ -49,3 +59,41 @@ function rewrite(attr: Attr, name: string) { } return false } + +function rewriteStaticStyle(style: string): string { + const styleObj = JSON.parse(style) + + // A marker which won't appear in target string + let MARKER: string = Math.random() + .toString(16) + .slice(2, 10) + while (style.indexOf(MARKER) !== -1) { + MARKER = `$${MARKER}$` + } + let id = -1 + const expressions: string[] = [] + + let result: string = JSON.stringify(styleObj, (key, value) => { + if (typeof value !== 'string') { + return value + } + let transformed: string = value.replace( + /url\((['"])?(.*?)\1\)/g, + (_0, _1, url) => { + // outer quotes would be added later + return `url(' + ${urlToRequire(url)} + ')` + } + ) + if (transformed !== value) { + // add outer quotes + transformed = `'${transformed}'` + expressions.push(transformed) + id++ + return MARKER + id + } + return value + }) + const MARKER_RE = new RegExp(`"${MARKER}(\\d+)"`, 'g') + result = result.replace(MARKER_RE, (_, id) => expressions[id]) + return result +} diff --git a/lib/templateCompilerModules/utils.ts b/lib/templateCompilerModules/utils.ts index 893d8a4..780e2ed 100644 --- a/lib/templateCompilerModules/utils.ts +++ b/lib/templateCompilerModules/utils.ts @@ -6,6 +6,8 @@ export interface Attr { export interface ASTNode { tag: string attrs: Attr[] + staticStyle?: string + __assetUrlTransformed?: boolean } import { UrlWithStringQuery, parse as uriParse } from 'url' diff --git a/test/__snapshots__/compileTemplate.spec.ts.snap b/test/__snapshots__/compileTemplate.spec.ts.snap new file mode 100644 index 0000000..caf4f18 --- /dev/null +++ b/test/__snapshots__/compileTemplate.spec.ts.snap @@ -0,0 +1,33 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`supports uri fragment in static style transformed require 1`] = ` +"var render = function() { + var _vm = this + var _h = _vm.$createElement + var _c = _vm._self._c || _h + return _c(\\"div\\", [ + _c(\\"img\\", { attrs: { src: require(\\"./image.jpg\\") } }), + _c(\\"div\\", { + staticStyle: { + color: \\"yellow\\", + background: \\"#f00 url(\\" + require(\\"./image/bg0.jpg\\") + \\") repeat\\" + } + }), + _c(\\"div\\", { + staticStyle: { + background: + \\"url(\\" + + require(\\"./image/bg1.jpg\\") + + \\"), url(\\" + + require(\\"@/image/bg2.jpg\\") + + \\"), url(\\" + + \\"http://vuejs.org/logo.png\\" + + \\")\\" + } + }) + ]) +} +var staticRenderFns = [] +render._withStripped = true +" +`; diff --git a/test/compileTemplate.spec.ts b/test/compileTemplate.spec.ts index ccd52b4..61de1f6 100644 --- a/test/compileTemplate.spec.ts +++ b/test/compileTemplate.spec.ts @@ -101,6 +101,29 @@ test('when too short uri then empty require', () => { expect(result.code).toMatch(/href: require\(""\)/) }) +/** + * Support uri fragment in static style in transformed require + */ +test('supports uri fragment in static style transformed require', () => { + const source = + '