Index: pkg/html_import/lib/src/HTMLImports.js |
diff --git a/pkg/html_import/lib/src/HTMLImports.js b/pkg/html_import/lib/src/HTMLImports.js |
deleted file mode 100644 |
index a77e7165e762204c44d3b7fa8cd4b8af8e325c26..0000000000000000000000000000000000000000 |
--- a/pkg/html_import/lib/src/HTMLImports.js |
+++ /dev/null |
@@ -1,423 +0,0 @@ |
-/* |
- * Copyright 2013 The Polymer Authors. All rights reserved. |
- * Use of this source code is governed by a BSD-style |
- * license that can be found in the LICENSE file. |
- */ |
- |
-(function(scope) { |
- |
-if (!scope) { |
- scope = window.HTMLImports = {flags:{}}; |
-} |
- |
-// imports |
- |
-var xhr = scope.xhr; |
- |
-// importer |
- |
-var IMPORT_LINK_TYPE = 'import'; |
-var STYLE_LINK_TYPE = 'stylesheet'; |
- |
-// highlander object represents a primary document (the argument to 'load') |
-// at the root of a tree of documents |
- |
-// for any document, importer: |
-// - loads any linked documents (with deduping), modifies paths and feeds them back into importer |
-// - loads text of external script tags |
-// - loads text of external style tags inside of <element>, modifies paths |
- |
-// when importer 'modifies paths' in a document, this includes |
-// - href/src/action in node attributes |
-// - paths in inline stylesheets |
-// - all content inside templates |
- |
-// linked style sheets in an import have their own path fixed up when their containing import modifies paths |
-// linked style sheets in an <element> are loaded, and the content gets path fixups |
-// inline style sheets get path fixups when their containing import modifies paths |
- |
-var loader; |
- |
-var importer = { |
- documents: {}, |
- cache: {}, |
- preloadSelectors: [ |
- 'link[rel=' + IMPORT_LINK_TYPE + ']', |
- 'element link[rel=' + STYLE_LINK_TYPE + ']', |
- 'template', |
- 'script[src]:not([type])', |
- 'script[src][type="text/javascript"]' |
- ].join(','), |
- loader: function(inNext) { |
- // construct a loader instance |
- loader = new Loader(importer.loaded, inNext); |
- // alias the loader cache (for debugging) |
- loader.cache = importer.cache; |
- return loader; |
- }, |
- load: function(inDocument, inNext) { |
- // construct a loader instance |
- loader = importer.loader(inNext); |
- // add nodes from document into loader queue |
- importer.preload(inDocument); |
- }, |
- preload: function(inDocument) { |
- // all preloadable nodes in inDocument |
- var nodes = inDocument.querySelectorAll(importer.preloadSelectors); |
- // from the main document, only load imports |
- // TODO(sjmiles): do this by altering the selector list instead |
- nodes = this.filterMainDocumentNodes(inDocument, nodes); |
- // extra link nodes from templates, filter templates out of the nodes list |
- nodes = this.extractTemplateNodes(nodes); |
- // add these nodes to loader's queue |
- loader.addNodes(nodes); |
- }, |
- filterMainDocumentNodes: function(inDocument, nodes) { |
- if (inDocument === document) { |
- nodes = Array.prototype.filter.call(nodes, function(n) { |
- return !isScript(n); |
- }); |
- } |
- return nodes; |
- }, |
- extractTemplateNodes: function(nodes) { |
- var extra = []; |
- nodes = Array.prototype.filter.call(nodes, function(n) { |
- if (n.localName === 'template') { |
- if (n.content) { |
- var l$ = n.content.querySelectorAll('link[rel=' + STYLE_LINK_TYPE + |
- ']'); |
- if (l$.length) { |
- extra = extra.concat(Array.prototype.slice.call(l$, 0)); |
- } |
- } |
- return false; |
- } |
- return true; |
- }); |
- if (extra.length) { |
- nodes = nodes.concat(extra); |
- } |
- return nodes; |
- }, |
- loaded: function(url, elt, resource) { |
- if (isDocumentLink(elt)) { |
- var document = importer.documents[url]; |
- // if we've never seen a document at this url |
- if (!document) { |
- // generate an HTMLDocument from data |
- document = makeDocument(resource, url); |
- // resolve resource paths relative to host document |
- path.resolvePathsInHTML(document); |
- // cache document |
- importer.documents[url] = document; |
- // add nodes from this document to the loader queue |
- importer.preload(document); |
- } |
- // store import record |
- elt.import = { |
- href: url, |
- ownerNode: elt, |
- content: document |
- }; |
- // store document resource |
- elt.content = resource = document; |
- } |
- // store generic resource |
- // TODO(sorvell): fails for nodes inside <template>.content |
- // see https://code.google.com/p/chromium/issues/detail?id=249381. |
- elt.__resource = resource; |
- // css path fixups |
- if (isStylesheetLink(elt)) { |
- path.resolvePathsInStylesheet(elt); |
- } |
- } |
-}; |
- |
-function isDocumentLink(elt) { |
- return isLinkRel(elt, IMPORT_LINK_TYPE); |
-} |
- |
-function isStylesheetLink(elt) { |
- return isLinkRel(elt, STYLE_LINK_TYPE); |
-} |
- |
-function isLinkRel(elt, rel) { |
- return elt.localName === 'link' && elt.getAttribute('rel') === rel; |
-} |
- |
-function isScript(elt) { |
- return elt.localName === 'script'; |
-} |
- |
-function makeDocument(resource, url) { |
- // create a new HTML document |
- var doc = resource; |
- if (!(doc instanceof Document)) { |
- doc = document.implementation.createHTMLDocument(IMPORT_LINK_TYPE); |
- // install html |
- doc.body.innerHTML = resource; |
- } |
- // cache the new document's source url |
- doc._URL = url; |
- // establish a relative path via <base> |
- var base = doc.createElement('base'); |
- base.setAttribute('href', document.baseURI); |
- doc.head.appendChild(base); |
- // TODO(sorvell): MDV Polyfill intrusion: boostrap template polyfill |
- if (window.HTMLTemplateElement && HTMLTemplateElement.bootstrap) { |
- HTMLTemplateElement.bootstrap(doc); |
- } |
- return doc; |
-} |
- |
-var Loader = function(inOnLoad, inOnComplete) { |
- this.onload = inOnLoad; |
- this.oncomplete = inOnComplete; |
- this.inflight = 0; |
- this.pending = {}; |
- this.cache = {}; |
-}; |
- |
-Loader.prototype = { |
- addNodes: function(inNodes) { |
- // number of transactions to complete |
- this.inflight += inNodes.length; |
- // commence transactions |
- forEach(inNodes, this.require, this); |
- // anything to do? |
- this.checkDone(); |
- }, |
- require: function(inElt) { |
- var url = path.nodeUrl(inElt); |
- // TODO(sjmiles): ad-hoc |
- inElt.__nodeUrl = url; |
- // deduplication |
- if (!this.dedupe(url, inElt)) { |
- // fetch this resource |
- this.fetch(url, inElt); |
- } |
- }, |
- dedupe: function(inUrl, inElt) { |
- if (this.pending[inUrl]) { |
- // add to list of nodes waiting for inUrl |
- this.pending[inUrl].push(inElt); |
- // don't need fetch |
- return true; |
- } |
- if (this.cache[inUrl]) { |
- // complete load using cache data |
- this.onload(inUrl, inElt, loader.cache[inUrl]); |
- // finished this transaction |
- this.tail(); |
- // don't need fetch |
- return true; |
- } |
- // first node waiting for inUrl |
- this.pending[inUrl] = [inElt]; |
- // need fetch (not a dupe) |
- return false; |
- }, |
- fetch: function(url, elt) { |
- var receiveXhr = function(err, resource) { |
- this.receive(url, elt, err, resource); |
- }.bind(this); |
- xhr.load(url, receiveXhr); |
- // TODO(sorvell): blocked on |
- // https://code.google.com/p/chromium/issues/detail?id=257221 |
- // xhr'ing for a document makes scripts in imports runnable; otherwise |
- // they are not; however, it requires that we have doctype=html in |
- // the import which is unacceptable. This is only needed on Chrome |
- // to avoid the bug above. |
- /* |
- if (isDocumentLink(elt)) { |
- xhr.loadDocument(url, receiveXhr); |
- } else { |
- xhr.load(url, receiveXhr); |
- } |
- */ |
- }, |
- receive: function(inUrl, inElt, inErr, inResource) { |
- if (!inErr) { |
- loader.cache[inUrl] = inResource; |
- } |
- loader.pending[inUrl].forEach(function(e) { |
- if (!inErr) { |
- this.onload(inUrl, e, inResource); |
- } |
- this.tail(); |
- }, this); |
- loader.pending[inUrl] = null; |
- }, |
- tail: function() { |
- --this.inflight; |
- this.checkDone(); |
- }, |
- checkDone: function() { |
- if (!this.inflight) { |
- this.oncomplete(); |
- } |
- } |
-}; |
- |
-var URL_ATTRS = ['href', 'src', 'action']; |
-var URL_ATTRS_SELECTOR = '[' + URL_ATTRS.join('],[') + ']'; |
-var URL_TEMPLATE_SEARCH = '{{.*}}'; |
- |
-var path = { |
- nodeUrl: function(inNode) { |
- return path.resolveUrl(path.getDocumentUrl(document), path.hrefOrSrc(inNode)); |
- }, |
- hrefOrSrc: function(inNode) { |
- return inNode.getAttribute("href") || inNode.getAttribute("src"); |
- }, |
- documentUrlFromNode: function(inNode) { |
- return path.getDocumentUrl(inNode.ownerDocument || inNode); |
- }, |
- getDocumentUrl: function(inDocument) { |
- var url = inDocument && |
- // TODO(sjmiles): ShadowDOMPolyfill intrusion |
- (inDocument._URL || (inDocument.impl && inDocument.impl._URL) |
- || inDocument.baseURI || inDocument.URL) |
- || ''; |
- // take only the left side if there is a # |
- return url.split('#')[0]; |
- }, |
- resolveUrl: function(inBaseUrl, inUrl, inRelativeToDocument) { |
- if (this.isAbsUrl(inUrl)) { |
- return inUrl; |
- } |
- var url = this.compressUrl(this.urlToPath(inBaseUrl) + inUrl); |
- if (inRelativeToDocument) { |
- url = path.makeRelPath(path.getDocumentUrl(document), url); |
- } |
- return url; |
- }, |
- isAbsUrl: function(inUrl) { |
- return /(^data:)|(^http[s]?:)|(^\/)/.test(inUrl); |
- }, |
- urlToPath: function(inBaseUrl) { |
- var parts = inBaseUrl.split("/"); |
- parts.pop(); |
- parts.push(''); |
- return parts.join("/"); |
- }, |
- compressUrl: function(inUrl) { |
- var parts = inUrl.split("/"); |
- for (var i=0, p; i<parts.length; i++) { |
- p = parts[i]; |
- if (p === "..") { |
- parts.splice(i-1, 2); |
- i -= 2; |
- } |
- } |
- return parts.join("/"); |
- }, |
- // make a relative path from source to target |
- makeRelPath: function(inSource, inTarget) { |
- var s, t; |
- s = this.compressUrl(inSource).split("/"); |
- t = this.compressUrl(inTarget).split("/"); |
- while (s.length && s[0] === t[0]){ |
- s.shift(); |
- t.shift(); |
- } |
- for(var i = 0, l = s.length-1; i < l; i++) { |
- t.unshift(".."); |
- } |
- var r = t.join("/"); |
- return r; |
- }, |
- resolvePathsInHTML: function(root, url) { |
- url = url || path.documentUrlFromNode(root) |
- path.resolveAttributes(root, url); |
- path.resolveStyleElts(root, url); |
- // handle template.content |
- var templates = root.querySelectorAll('template'); |
- if (templates) { |
- forEach(templates, function(t) { |
- if (t.content) { |
- path.resolvePathsInHTML(t.content, url); |
- } |
- }); |
- } |
- }, |
- resolvePathsInStylesheet: function(inSheet) { |
- var docUrl = path.nodeUrl(inSheet); |
- inSheet.__resource = path.resolveCssText(inSheet.__resource, docUrl); |
- }, |
- resolveStyleElts: function(inRoot, inUrl) { |
- var styles = inRoot.querySelectorAll('style'); |
- if (styles) { |
- forEach(styles, function(style) { |
- style.textContent = path.resolveCssText(style.textContent, inUrl); |
- }); |
- } |
- }, |
- resolveCssText: function(inCssText, inBaseUrl) { |
- return inCssText.replace(/url\([^)]*\)/g, function(inMatch) { |
- // find the url path, ignore quotes in url string |
- var urlPath = inMatch.replace(/["']/g, "").slice(4, -1); |
- urlPath = path.resolveUrl(inBaseUrl, urlPath, true); |
- return "url(" + urlPath + ")"; |
- }); |
- }, |
- resolveAttributes: function(inRoot, inUrl) { |
- // search for attributes that host urls |
- var nodes = inRoot && inRoot.querySelectorAll(URL_ATTRS_SELECTOR); |
- if (nodes) { |
- forEach(nodes, function(n) { |
- this.resolveNodeAttributes(n, inUrl); |
- }, this); |
- } |
- }, |
- resolveNodeAttributes: function(inNode, inUrl) { |
- URL_ATTRS.forEach(function(v) { |
- var attr = inNode.attributes[v]; |
- if (attr && attr.value && |
- (attr.value.search(URL_TEMPLATE_SEARCH) < 0)) { |
- var urlPath = path.resolveUrl(inUrl, attr.value, true); |
- attr.value = urlPath; |
- } |
- }); |
- } |
-}; |
- |
-xhr = xhr || { |
- async: true, |
- ok: function(inRequest) { |
- return (inRequest.status >= 200 && inRequest.status < 300) |
- || (inRequest.status === 304) |
- || (inRequest.status === 0); |
- }, |
- load: function(url, next, nextContext) { |
- var request = new XMLHttpRequest(); |
- if (scope.flags.debug || scope.flags.bust) { |
- url += '?' + Math.random(); |
- } |
- request.open('GET', url, xhr.async); |
- request.addEventListener('readystatechange', function(e) { |
- if (request.readyState === 4) { |
- next.call(nextContext, !xhr.ok(request) && request, |
- request.response, url); |
- } |
- }); |
- request.send(); |
- return request; |
- }, |
- loadDocument: function(url, next, nextContext) { |
- this.load(url, next, nextContext).responseType = 'document'; |
- } |
-}; |
- |
-var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach); |
- |
-// exports |
- |
-scope.path = path; |
-scope.xhr = xhr; |
-scope.importer = importer; |
-scope.getDocumentUrl = path.getDocumentUrl; |
-scope.IMPORT_LINK_TYPE = IMPORT_LINK_TYPE; |
- |
-})(window.HTMLImports); |