diff --git a/lib/vulcan.js b/lib/vulcan.js index 39c56111..c3cadb8c 100644 --- a/lib/vulcan.js +++ b/lib/vulcan.js @@ -10,19 +10,24 @@ var cleancss = require('clean-css'); var fs = require('fs'); var path = require('path'); var uglify = require('uglify-js'); +var url = require('url'); var constants = require('./constants.js'); var optparser = require('./optparser.js'); var pathresolver = require('./pathresolver'); -var import_buffer = []; var read = {}; var options = {}; - // validate options with boolean return function setOptions(optHash, callback) { - optparser.processOptions(optHash, callback); + optparser.processOptions(optHash, function(err, o) { + if (err) { + return callback(err); + } + options = o; + callback(); + }); } function exclude(regexes, href) { @@ -49,14 +54,6 @@ function setTextContent(node, text) { node[0].children[0].data = text; } -function readDocument(docname) { - if (options.verbose) { - console.log('Reading:', docname); - } - var content = fs.readFileSync(docname, 'utf8'); - return cheerio.load(content); -} - // inline relative linked stylesheets into '); // clone attributes styleDoc('style').attr(this.attr()); @@ -77,7 +74,7 @@ function inlineSheets($, inputPath, outputPath) { } function inlineScripts($, dir) { - $(JS_SRC).each(function() { + $(constants.JS_SRC).each(function() { var src = this.attr('src'); if (src && !excludeScript(src)) { var filepath = path.resolve(dir, src); @@ -87,6 +84,10 @@ function inlineScripts($, dir) { }); } +function readDocument(filename) { + return cheerio.load(fs.readFileSync(filename, 'utf8')); +} + function concat(filename) { if (!read[filename]) { read[filename] = true; @@ -94,8 +95,8 @@ function concat(filename) { var dir = path.dirname(filename); processImports($, dir); inlineSheets($, dir, options.outputDir); - resolvePaths($, dir, options.outputDir); - import_buffer.push($.html()); + pathresolver.resolvePaths($, dir, options.outputDir); + return $.html(); } else { if (options.verbose) { console.log('Dependency deduplicated'); @@ -104,53 +105,23 @@ function concat(filename) { } function processImports($, prefix) { - $(IMPORTS).each(function() { + $(constants.IMPORTS).each(function() { var href = this.attr('href'); if (excludeImport(href)) { // rewrite href to be deduplicated later - this.attr('href', rewriteRelPath(prefix, options.outputDir, href)); - imports_before_polymer.push(this); + this.attr('href', pathresolver.rewriteRelPath(prefix, options.outputDir, href)); } else { - concat(path.resolve(prefix, href)); + this.replaceWith(concat(path.resolve(prefix, href))); } - }).remove(); + }); } function findScriptLocation($) { - var pos = $(POLYFILLS).last().parent(); - if (!pos.length) { - pos = $('body').last(); - } - if (!pos.length) { - pos = $.root(); - } - return pos; -} - -function insertImport($, importText) { - // before polymer script in
- var pos = $('head ' + POLYFILLS).last(); - var operation = 'after'; - if (!pos.length) { - // at the bottom of head - pos = $('head').last(); - operation = 'append'; - } - if (!pos.length) { - // at the top of top document - pos = $.root(); - operation = 'prepend'; - } - pos[operation](importText); -} - -function insertInlinedImports($, importText) { var pos = $('body').last(); - var operation = 'prepend'; if (!pos.length) { pos = $.root(); } - pos[operation](importText); + return pos; } // arguments are (index, node), where index is unnecessary @@ -167,21 +138,20 @@ function removeCommentsAndWhitespace($) { $.root().contents().filter(isCommentOrEmptyTextNode).remove(); $('head').contents().filter(isCommentOrEmptyTextNode).remove(); $('body').contents().filter(isCommentOrEmptyTextNode).remove(); - $(JS).each(function() { + $(constants.JS).each(function() { if (!this.attr('src')) { var content = this.html(); var ast = uglify.parse(content); this.replaceWith(''); } }); - $(CSS).each(function() { + $(constants.CSS).each(function() { setTextContent(this, new cleancss().minify(this.text())); }); } function handleMainDocument() { // reset shared buffers - import_buffer = []; imports_before_polymer = []; read = {}; var $ = readDocument(options.input); @@ -190,8 +160,7 @@ function handleMainDocument() { if (options.inline) { inlineSheets($, dir, options.outputDir); } - resolvePaths($, dir, options.outputDir); - var output = import_buffer.join(EOL); + pathresolver.resolvePaths($, dir, options.outputDir); // strip scripts into a separate file if (options.csp) { @@ -218,12 +187,7 @@ function handleMainDocument() { }; // CSPify main page - $(JS).each(fn).remove(); - - // CSPify imports - var tempoutput = cheerio.load(output); - tempoutput(JS).each(fn).remove(); - output = tempoutput.html(); + $(constants.JS).each(fn).remove(); // join scripts with ';' to prevent breakages due to EOF semicolon insertion var script_name = path.basename(options.output, '.html') + '.js'; @@ -232,9 +196,7 @@ function handleMainDocument() { findScriptLocation($).append(EOL + scripts_after_polymer.join(EOL) + EOL); } - imports_before_polymer = deduplicateImports(imports_before_polymer); - insertImport($, imports_before_polymer.join(EOL) + EOL); - insertInlinedImports($, output); + deduplicateImports($); if (!options.csp && options.inline) { inlineScripts($, options.outputDir); } @@ -245,20 +207,20 @@ function handleMainDocument() { fs.writeFileSync(options.output, outhtml, 'utf8'); } -function deduplicateImports(importArray) { +function deduplicateImports($) { var imports = {}; - return importArray.filter(function(im) { - var href = im.attr('href'); + $(constants.IMPORTS).each(function() { + var href = this.attr('href'); // TODO(dfreedm): allow a user defined base url? var abs = url.resolve('http://', href); if (!imports[abs]) { imports[abs] = true; - return true; - } else if(options.verbose) { - console.log('Import Dependency deduplicated'); + } else { + if(options.verbose) { + console.log('Import Dependency deduplicated'); + } + this.remove(); } - }).map(function(im) { - return cheerio.html(im); }); }