Skip to content

Commit

Permalink
Add importPath and rootPath to support 2.x hybrid compatible elem…
Browse files Browse the repository at this point in the history
…ents.
  • Loading branch information
Steven Orvell committed Mar 3, 2017
1 parent 80c899f commit daaf460
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 10 deletions.
16 changes: 15 additions & 1 deletion src/lib/resolve-url.html
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,16 @@
(ownerDocument.body.__urlResolver = ownerDocument.createElement('a'));
}

/**
* Returns a path from a given `url`. The path includes the trailing
* `/` from the url.
* @param {string} url Input URL to transform
* @return {string} resolved path
*/
function pathFromUrl(url) {
return url.substring(0, url.lastIndexOf('/') + 1);
}

var CSS_URL_RX = /(url\()([^)]*)(\))/g;
var URL_ATTRS = {
'*': ['href', 'src', 'style', 'url'],
Expand All @@ -79,9 +89,13 @@
Polymer.ResolveUrl = {
resolveCss: resolveCss,
resolveAttrs: resolveAttrs,
resolveUrl: resolveUrl
resolveUrl: resolveUrl,
pathFromUrl: pathFromUrl
};

// NOTE: IE11 does not support baseURI
Polymer.rootPath = pathFromUrl(document.baseURI || window.location.href);

})();

</script>
15 changes: 14 additions & 1 deletion src/mini/template.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<link rel="import" href="../lib/resolve-url.html">
<script>

/**
Expand All @@ -25,8 +26,20 @@

_prepTemplate: function() {
// locate template using dom-module
var module;
if (this._template === undefined) {
this._template = Polymer.DomModule.import(this.is, 'template');
module = Polymer.DomModule.import(this.is);
this._template = module && module.querySelector('template');
}
if (!this._importPath) {
if (module) {
var assetPath = module.getAttribute('assetpath') || '';
var importURL = Polymer.ResolveUrl.resolveUrl(assetPath,
module.ownerDocument.baseURI);
this._importPath = Polymer.ResolveUrl.pathFromUrl(importURL);
} else {
this._importPath = '';
}
}
// stick finger in footgun
if (this._template && this._template.hasAttribute('is')) {
Expand Down
3 changes: 3 additions & 0 deletions src/standard/configure.html
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,9 @@

// Override polymer-mini thunk
_afterClientsReady: function() {
// set path properties
this.importPath = this._importPath;
this.rootPath = Polymer.rootPath;
// process static effects, e.g. computations that have only literal arguments
this._executeStaticEffects();
this._applyConfig(this._config, this._aboveConfig);
Expand Down
9 changes: 1 addition & 8 deletions src/standard/resolveUrl.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,7 @@
* @return {string} Rewritten URL relative to the import
*/
resolveUrl: function(url) {
// TODO(sorvell): do we want to put the module reference on the prototype?
var module = Polymer.DomModule.import(this.is);
var root = '';
if (module) {
var assetPath = module.getAttribute('assetpath') || '';
root = Polymer.ResolveUrl.resolveUrl(assetPath, module.ownerDocument.baseURI);
}
return Polymer.ResolveUrl.resolveUrl(url, root);
return Polymer.ResolveUrl.resolveUrl(url, this.importPath);
}

});
Expand Down
62 changes: 62 additions & 0 deletions test/unit/resolveurl.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,18 @@
<dom-module id="x-resolve">
</dom-module>

<dom-module id="x-late">
<template>
<style>
:host {
background: url('foo.png');
}
</style>
<img id="root" src$="[[rootPath]]foo.png">
<img id="import" src$="[[importPath]]foo.png">
</template>
</dom-module>

<script>
addEventListener('HTMLImportsLoaded', function() {
Polymer({is: 'x-resolve'});
Expand Down Expand Up @@ -81,6 +93,56 @@
var actual = el.resolveUrl('Beaker2.jpg');
assert.equal(actual, expected);
});

test('Hybrid: Urls in styles and attributes', function() {
var el = document.createElement('p-r-hybrid');
document.body.appendChild(el);
var rx = /sub\/foo\.z/;
var style = el._styles[0];
assert.match(style.textContent, rx, 'url not relative to main document');
assert.match(el.$.div.getAttribute('style'), rx, 'style url not relative to main document');
assert.match(el.$.img.src, rx, 'src url not relative to main document');
assert.match(el.$.a.href, rx, 'href url not relative to main document');
assert.match(el.$.import.getAttribute('url'), rx, 'url url not relative to main document');
assert.match(el.$.resolveUrl.getAttribute('url'), rx, 'url url not relative to main document');
assert.notMatch(el.$.root.getAttribute('url'), rx, 'url url not relative to main document');
assert.notMatch(el.$.rel.href, rx, 'relative href url not relative to main document');
assert.match(el.$.rel.href, /\?123$/, 'relative href does not preserve query string');
assert.equal(el.$.action.getAttribute('action'), 'foo.z', 'action attribute relativized for incorrect element type');
assert.match(el.$.formAction.action, rx, 'action attribute relativized for incorrect element type');
assert.equal(el.$.hash.getAttribute('href'), '#foo.z', 'hash-only url should not be resolved');
assert.equal(el.$.absolute.getAttribute('href'), '/foo.z', 'absolute urls should not be resolved');
assert.equal(el.$.protocol.getAttribute('href'), 'data:foo.z', 'urls with other protocols should not be resolved');
document.body.removeChild(el);
});

test('Hybrid: url changes via setting importPath/rootPath on element instance', function() {
var el = document.createElement('p-r-hybrid');
document.body.appendChild(el);
el.rootPath = 'instanceRoot/';
el.importPath = 'instanceImport/';
var matchRoot = /instanceRoot\//;
var matchImport = /instanceImport\//;
assert.match(el.$.div.getAttribute('style'), matchImport);
assert.match(el.$.import.getAttribute('url'), matchImport);
assert.match(el.$.root.getAttribute('url'), matchRoot);
document.body.removeChild(el);
});

test('Hybrid-url: changes via setting importPath/rootPath when defining element', function() {
Polymer.rootPath = 'defineRoot/';
Polymer({
is: 'x-late',
_importPath: 'defineImport/'
});
var el = document.createElement('x-late');
document.body.appendChild(el);
var matchRoot = /defineRoot\//i;
var matchImport = /defineImport\//i;
assert.match(el.$.import.getAttribute('src'), matchImport);
assert.match(el.$.root.getAttribute('src'), matchRoot);
document.body.removeChild(el);
});
});
</script>
</body>
Expand Down
25 changes: 25 additions & 0 deletions test/unit/sub/resolveurl-elements.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,31 @@
Polymer({is: 'p-r'});
</script>

<dom-module id="p-r-hybrid">
<template>
<style>
.logo {
background-image: url(foo.z);
}
</style>
<div id="div" class="logo" style$="background-image: url('[[importPath]]foo.z');"></div>
<img id="img" src$="[[importPath]]foo.z">
<a id="a" href$="[[importPath]]foo.z">Foo</a>
<zonk id="import" url$="[[importPath]]foo.z"></zonk>
<zonk id="resolveUrl" url$="[[resolveUrl('foo.z')]]"></zonk>
<zonk id="root" url$="[[rootPath]]foo.z"></zonk>
<a id="rel" href$="[[importPath]]../foo.z?123">Foo</a>
<a id="action" action="foo.z">Foo</a>
<form id="formAction" action$="[[importPath]]foo.z"></form>
<a id="hash" href="#foo.z">Foo</a>
<a id="absolute" href="/foo.z">Foo</a>
<a id="protocol" href="data:foo.z">Foo</a>
</template>
</dom-module>
<script>
Polymer({is: 'p-r-hybrid'});
</script>

<dom-module id="p-r-ap" assetpath="../../assets/"></dom-module>
<script>
Polymer({is: 'p-r-ap'});
Expand Down

0 comments on commit daaf460

Please sign in to comment.