UNPKG

vulcanize

Version:

Process Web Components into one output file

166 lines (152 loc) 5.81 kB
/** * @license * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt * 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 */ // jshint node:true 'use strict'; var path = require('path'); // use path.posix on Node > 0.12+, path-posix on 0.10 var pathPosix = path.posix || require('path-posix'); var url = require('url'); var dom5 = require('dom5'); var matchers = require('./matchers'); var constants = require('./constants'); var PathResolver = function PathResolver(abspath) { if (abspath) { this.abspath = abspath; } }; PathResolver.prototype = { isTemplatedUrl: function isTemplatedUrl(href) { return href.search(constants.URL_TEMPLATE) >= 0; }, resolvePaths: function resolvePaths(importDoc, importUrl, mainDocUrl, polymer2) { // rewrite URLs in element attributes var nodes = dom5.queryAll(importDoc, matchers.urlAttrs); var attrValue; for (var i = 0, node; i < nodes.length; i++) { node = nodes[i]; for (var j = 0, attr; j < constants.URL_ATTR.length; j++) { attr = constants.URL_ATTR[j]; attrValue = dom5.getAttribute(node, attr); // When the path is an empty string value the intent is to represent // in URL-speak "the same path that the current document is at". // We'll set it to '.' which better represents this intent to the // rewrite methods. if (attrValue === '') { attrValue = '.'; } if (attrValue && !this.isTemplatedUrl(attrValue)) { var relUrl; if (attr === 'style') { relUrl = this.rewriteURL(importUrl, mainDocUrl, attrValue); } else { relUrl = this.rewriteRelPath(importUrl, mainDocUrl, attrValue); if (attr === 'assetpath' && relUrl.length > 0 && relUrl.slice(-1) !== '/') { relUrl += '/'; } } dom5.setAttribute(node, attr, relUrl); } } } // rewrite URLs in stylesheets unless they're inside a <dom-module> var styleNodes = polymer2 ? dom5.queryAll(importDoc, dom5.predicates.AND( dom5.predicates.NOT( dom5.predicates.parentMatches( dom5.predicates.hasTagName('dom-module'))), matchers.CSS)) : dom5.queryAll(importDoc, matchers.CSS); for (i = 0, node; i < styleNodes.length; i++) { node = styleNodes[i]; var styleText = dom5.getTextContent(node); styleText = this.rewriteURL(importUrl, mainDocUrl, styleText); dom5.setTextContent(node, styleText); } // add assetpath to dom-modules in importDoc var domModules = dom5.queryAll(importDoc, matchers.domModule); for (i = 0, node; i < domModules.length; i++) { node = domModules[i]; var assetPathUrl = this.rewriteRelPath(importUrl, mainDocUrl, ''); assetPathUrl = pathPosix.dirname(assetPathUrl) + '/'; dom5.setAttribute(node, 'assetpath', assetPathUrl); } }, isAbsoluteUrl: function isAbsoluteUrl(href) { return constants.ABS_URL.test(href); }, rewriteRelPath: function rewriteRelPath(importUrl, mainDocUrl, relUrl) { if (this.isAbsoluteUrl(relUrl)) { return relUrl; } var absUrl = url.resolve(importUrl, relUrl); if (this.abspath) { return url.resolve('/', absUrl); } var parsedFrom = url.parse(mainDocUrl); var parsedTo = url.parse(absUrl); if (parsedFrom.protocol === parsedTo.protocol && parsedFrom.host === parsedTo.host) { var pathname = pathPosix.relative(pathPosix.dirname(parsedFrom.pathname), parsedTo.pathname); return url.format({ pathname: pathname, search: parsedTo.search, hash: parsedTo.hash }); } return absUrl; }, rewriteURL: function rewriteURL(importUrl, mainDocUrl, cssText) { return cssText.replace(constants.URL, function(match) { var path = match.replace(/["']/g, "").slice(4, -1); path = this.rewriteRelPath(importUrl, mainDocUrl, path); return 'url("' + path + '")'; }.bind(this)); }, // remove effects of <base> acid: function acid(doc, docUrl, polymer2) { var base = dom5.query(doc, matchers.base); if (base) { var baseUrl = dom5.getAttribute(base, 'href'); var baseTarget = dom5.getAttribute(base, 'target'); dom5.remove(base); if (baseUrl) { if (baseUrl.slice(-1) === '/') { baseUrl = baseUrl.slice(0, -1); } var docBaseUrl = url.resolve(docUrl, baseUrl + '/.index.html'); this.resolvePaths(doc, docBaseUrl, docUrl, polymer2); } if (baseTarget) { var elementsNeedTarget = dom5.queryAll(doc, matchers.targetMatcher); elementsNeedTarget.forEach(function(el) { dom5.setAttribute(el, 'target', baseTarget); }); } } }, pathToUrl: function pathToUrl(filePath) { var absolutePath = path.resolve(filePath); if (process.platform === 'win32') { // encode C:\foo\ as C:/foo/ return absolutePath.split('\\').join('/'); } else { return absolutePath; } }, urlToPath: function urlToPath(uri) { var parsed = url.parse(uri); if (process.platform === 'win32') { return parsed.protocol + parsed.pathname.split('/').join('\\'); } else { return (parsed.protocol || '') + parsed.pathname; } } }; module.exports = PathResolver;