diff --git a/src/Asset.js b/src/Asset.js index 22e7429b7c1..6a06b9852b3 100644 --- a/src/Asset.js +++ b/src/Asset.js @@ -1,3 +1,4 @@ +const URL = require('url'); const path = require('path'); const fs = require('./utils/fs'); const objectHash = require('./utils/objectHash'); @@ -78,15 +79,18 @@ class Asset { from = this.name; } - let resolved = path.resolve(path.dirname(from), url).replace(/[?#].*$/, ''); + const parsed = URL.parse(url); + const resolved = path.resolve(path.dirname(from), parsed.pathname); this.addDependency( './' + path.relative(path.dirname(this.name), resolved), Object.assign({dynamic: true}, opts) ); - return this.options.parser + parsed.pathname = this.options.parser .getAsset(resolved, this.package, this.options) .generateBundleName(); + + return URL.format(parsed); } async getConfig(filenames) { diff --git a/src/utils/urlJoin.js b/src/utils/urlJoin.js index fe50ec26729..88a22c808b8 100644 --- a/src/utils/urlJoin.js +++ b/src/utils/urlJoin.js @@ -7,6 +7,9 @@ const path = require('path'); */ module.exports = function(publicURL, assetPath) { const url = URL.parse(publicURL, false, true); - url.pathname = path.posix.join(url.pathname, URL.parse(assetPath).pathname); + const assetUrl = URL.parse(assetPath); + url.pathname = path.posix.join(url.pathname, assetUrl.pathname); + url.search = assetUrl.search; + url.hash = assetUrl.hash; return URL.format(url); }; diff --git a/test/asset.js b/test/asset.js new file mode 100644 index 00000000000..5e52cdb4a18 --- /dev/null +++ b/test/asset.js @@ -0,0 +1,41 @@ +const {strictEqual} = require('assert'); +const Asset = require('../src/Asset'); + +describe('Asset', () => { + describe('addURLDependency', () => { + const bundleName = 'xyz'; + const options = { + rootDir: '/root/dir', + parser: { + getAsset: () => { + return { + generateBundleName: () => bundleName + }; + } + } + }; + const asset = new Asset('test', undefined, options); + + it('should ignore urls', () => { + const url = 'https://parceljs.org/assets.html'; + strictEqual(asset.addURLDependency(url), url); + }); + + it('should ignore empty string', () => { + strictEqual(asset.addURLDependency(''), ''); + }); + + it('should generate bundle name', () => { + strictEqual(asset.addURLDependency('foo'), bundleName); + }); + + it('should preserve query and hash', () => { + strictEqual(asset.addURLDependency('foo#bar'), `${bundleName}#bar`); + strictEqual(asset.addURLDependency('foo?bar'), `${bundleName}?bar`); + strictEqual( + asset.addURLDependency('foo?bar#baz'), + `${bundleName}?bar#baz` + ); + }); + }); +}); diff --git a/test/url-join.js b/test/url-join.js index aa64e9ae425..b891507a618 100644 --- a/test/url-join.js +++ b/test/url-join.js @@ -32,24 +32,24 @@ describe('Url Join', () => { it('should join a URL with a querystring', () => { assert.equal( - urlJoin('https://parceljs.org/foo?a=123', '/bar/a.js'), + urlJoin('https://parceljs.org/foo', '/bar/a.js?a=123'), 'https://parceljs.org/foo/bar/a.js?a=123' ); assert.equal( - urlJoin('https://parceljs.org/foo?a=123&b=456', '/bar/a.js'), + urlJoin('https://parceljs.org/foo', '/bar/a.js?a=123&b=456'), 'https://parceljs.org/foo/bar/a.js?a=123&b=456' ); }); it('should join a URL with a hash', () => { assert.equal( - urlJoin('https://parceljs.org/foo#hello', '/bar/a.js'), + urlJoin('https://parceljs.org/foo', '/bar/a.js#hello'), 'https://parceljs.org/foo/bar/a.js#hello' ); assert.equal( - urlJoin('https://parceljs.org/foo?a=123&b=456#hello', '/bar/a.js'), + urlJoin('https://parceljs.org/foo', '/bar/a.js?a=123&b=456#hello'), 'https://parceljs.org/foo/bar/a.js?a=123&b=456#hello' ); }); @@ -67,7 +67,7 @@ describe('Url Join', () => { it('should parse double slashes as host', () => { assert.equal( - urlJoin('//parceljs.org/foo?a=123&b=456#hello', 'bar/a.js'), + urlJoin('//parceljs.org/foo', 'bar/a.js?a=123&b=456#hello'), '//parceljs.org/foo/bar/a.js?a=123&b=456#hello' ); });