/*
|
|
MIT License http://www.opensource.org/licenses/mit-license.php
|
|
Author Tobias Koppers @sokra
|
|
*/
|
|
var htmlMinifier = require("html-minifier");
|
|
var attrParse = require("./lib/attributesParser");
|
|
var loaderUtils = require("loader-utils");
|
|
var url = require("url");
|
|
var assign = require("object-assign");
|
|
var compile = require("es6-templates").compile;
|
|
|
|
function randomIdent() {
|
|
return "xxxHTMLLINKxxx" + Math.random() + Math.random() + "xxx";
|
|
}
|
|
|
|
function getLoaderConfig(context) {
|
|
var query = loaderUtils.getOptions(context) || {};
|
|
var configKey = query.config || 'htmlLoader';
|
|
var config = context.options && context.options.hasOwnProperty(configKey) ? context.options[configKey] : {};
|
|
|
|
delete query.config;
|
|
|
|
return assign(query, config);
|
|
}
|
|
|
|
module.exports = function(content) {
|
|
this.cacheable && this.cacheable();
|
|
var config = getLoaderConfig(this);
|
|
var attributes = ["img:src"];
|
|
if(config.attrs !== undefined) {
|
|
if(typeof config.attrs === "string")
|
|
attributes = config.attrs.split(" ");
|
|
else if(Array.isArray(config.attrs))
|
|
attributes = config.attrs;
|
|
else if(config.attrs === false)
|
|
attributes = [];
|
|
else
|
|
throw new Error("Invalid value to config parameter attrs");
|
|
}
|
|
var root = config.root;
|
|
var links = attrParse(content, function(tag, attr) {
|
|
var res = attributes.find(function(a) {
|
|
if (a.charAt(0) === ':') {
|
|
return attr === a.slice(1);
|
|
} else {
|
|
return (tag + ":" + attr) === a;
|
|
}
|
|
});
|
|
return !!res;
|
|
});
|
|
links.reverse();
|
|
var data = {};
|
|
content = [content];
|
|
links.forEach(function(link) {
|
|
if(!loaderUtils.isUrlRequest(link.value, root)) return;
|
|
|
|
if (link.value.indexOf('mailto:') > -1 ) return;
|
|
|
|
var uri = url.parse(link.value);
|
|
if (uri.hash !== null && uri.hash !== undefined) {
|
|
uri.hash = null;
|
|
link.value = uri.format();
|
|
link.length = link.value.length;
|
|
}
|
|
|
|
do {
|
|
var ident = randomIdent();
|
|
} while(data[ident]);
|
|
data[ident] = link.value;
|
|
var x = content.pop();
|
|
content.push(x.substr(link.start + link.length));
|
|
content.push(ident);
|
|
content.push(x.substr(0, link.start));
|
|
});
|
|
content.reverse();
|
|
content = content.join("");
|
|
|
|
if (config.interpolate === 'require'){
|
|
|
|
var reg = /\$\{require\([^)]*\)\}/g;
|
|
var result;
|
|
var reqList = [];
|
|
while(result = reg.exec(content)){
|
|
reqList.push({
|
|
length : result[0].length,
|
|
start : result.index,
|
|
value : result[0]
|
|
})
|
|
}
|
|
reqList.reverse();
|
|
content = [content];
|
|
reqList.forEach(function(link) {
|
|
var x = content.pop();
|
|
do {
|
|
var ident = randomIdent();
|
|
} while(data[ident]);
|
|
data[ident] = link.value.substring(11,link.length - 3)
|
|
content.push(x.substr(link.start + link.length));
|
|
content.push(ident);
|
|
content.push(x.substr(0, link.start));
|
|
});
|
|
content.reverse();
|
|
content = content.join("");
|
|
}
|
|
|
|
if(typeof config.minimize === "boolean" ? config.minimize : this.minimize) {
|
|
var minimizeOptions = assign({}, config);
|
|
|
|
[
|
|
"removeComments",
|
|
"removeCommentsFromCDATA",
|
|
"removeCDATASectionsFromCDATA",
|
|
"collapseWhitespace",
|
|
"conservativeCollapse",
|
|
"removeAttributeQuotes",
|
|
"useShortDoctype",
|
|
"keepClosingSlash",
|
|
"minifyJS",
|
|
"minifyCSS",
|
|
"removeScriptTypeAttributes",
|
|
"removeStyleTypeAttributes",
|
|
].forEach(function(name) {
|
|
if(typeof minimizeOptions[name] === "undefined") {
|
|
minimizeOptions[name] = true;
|
|
}
|
|
});
|
|
|
|
content = htmlMinifier.minify(content, minimizeOptions);
|
|
}
|
|
|
|
if(config.interpolate && config.interpolate !== 'require') {
|
|
// Double escape quotes so that they are not unescaped completely in the template string
|
|
content = content.replace(/\\"/g, "\\\\\"");
|
|
content = content.replace(/\\'/g, "\\\\\'");
|
|
content = compile('`' + content + '`').code;
|
|
} else {
|
|
content = JSON.stringify(content);
|
|
}
|
|
|
|
var exportsString = "module.exports = ";
|
|
if (config.exportAsDefault) {
|
|
exportsString = "exports.default = ";
|
|
|
|
} else if (config.exportAsEs6Default) {
|
|
exportsString = "export default ";
|
|
}
|
|
|
|
return exportsString + content.replace(/xxxHTMLLINKxxx[0-9\.]+xxx/g, function(match) {
|
|
if(!data[match]) return match;
|
|
|
|
var urlToRequest;
|
|
|
|
if (config.interpolate === 'require') {
|
|
urlToRequest = data[match];
|
|
} else {
|
|
urlToRequest = loaderUtils.urlToRequest(data[match], root);
|
|
}
|
|
|
|
return '" + require(' + JSON.stringify(urlToRequest) + ') + "';
|
|
}) + ";";
|
|
|
|
}
|