1 |
|
2 |
|
3 |
|
4 |
|
5 | var htmlMinifier = require("html-minifier");
|
6 | var attrParse = require("./lib/attributesParser");
|
7 | var loaderUtils = require("loader-utils");
|
8 | var url = require("url");
|
9 | var assign = require("object-assign");
|
10 | var compile = require("es6-templates").compile;
|
11 |
|
12 | function randomIdent() {
|
13 | return "xxxHTMLLINKxxx" + Math.random() + Math.random() + "xxx";
|
14 | }
|
15 |
|
16 | function getLoaderConfig(context) {
|
17 | var query = loaderUtils.getOptions(context) || {};
|
18 | var configKey = query.config || 'htmlLoader';
|
19 | var config = context.options && context.options.hasOwnProperty(configKey) ? context.options[configKey] : {};
|
20 |
|
21 | delete query.config;
|
22 |
|
23 | return assign(query, config);
|
24 | }
|
25 |
|
26 | module.exports = function(content) {
|
27 | this.cacheable && this.cacheable();
|
28 | var config = getLoaderConfig(this);
|
29 | var attributes = ["img:src"];
|
30 | if(config.attrs !== undefined) {
|
31 | if(typeof config.attrs === "string")
|
32 | attributes = config.attrs.split(" ");
|
33 | else if(Array.isArray(config.attrs))
|
34 | attributes = config.attrs;
|
35 | else if(config.attrs === false)
|
36 | attributes = [];
|
37 | else
|
38 | throw new Error("Invalid value to config parameter attrs");
|
39 | }
|
40 | var root = config.root;
|
41 | var links = attrParse(content, function(tag, attr) {
|
42 | var res = attributes.find(function(a) {
|
43 | if (a.charAt(0) === ':') {
|
44 | return attr === a.slice(1);
|
45 | } else {
|
46 | return (tag + ":" + attr) === a;
|
47 | }
|
48 | });
|
49 | return !!res;
|
50 | });
|
51 | links.reverse();
|
52 | var data = {};
|
53 | content = [content];
|
54 | links.forEach(function(link) {
|
55 | if(!loaderUtils.isUrlRequest(link.value, root)) return;
|
56 |
|
57 | if (link.value.indexOf('mailto:') > -1 ) return;
|
58 |
|
59 | var uri = url.parse(link.value);
|
60 | if (uri.hash !== null && uri.hash !== undefined) {
|
61 | uri.hash = null;
|
62 | link.value = uri.format();
|
63 | link.length = link.value.length;
|
64 | }
|
65 |
|
66 | do {
|
67 | var ident = randomIdent();
|
68 | } while(data[ident]);
|
69 | data[ident] = link.value;
|
70 | var x = content.pop();
|
71 | content.push(x.substr(link.start + link.length));
|
72 | content.push(ident);
|
73 | content.push(x.substr(0, link.start));
|
74 | });
|
75 | content.reverse();
|
76 | content = content.join("");
|
77 |
|
78 | if (config.interpolate === 'require'){
|
79 |
|
80 | var reg = /\$\{require\([^)]*\)\}/g;
|
81 | var result;
|
82 | var reqList = [];
|
83 | while(result = reg.exec(content)){
|
84 | reqList.push({
|
85 | length : result[0].length,
|
86 | start : result.index,
|
87 | value : result[0]
|
88 | })
|
89 | }
|
90 | reqList.reverse();
|
91 | content = [content];
|
92 | reqList.forEach(function(link) {
|
93 | var x = content.pop();
|
94 | do {
|
95 | var ident = randomIdent();
|
96 | } while(data[ident]);
|
97 | data[ident] = link.value.substring(11,link.length - 3)
|
98 | content.push(x.substr(link.start + link.length));
|
99 | content.push(ident);
|
100 | content.push(x.substr(0, link.start));
|
101 | });
|
102 | content.reverse();
|
103 | content = content.join("");
|
104 | }
|
105 |
|
106 | if(typeof config.minimize === "boolean" ? config.minimize : this.minimize) {
|
107 | var minimizeOptions = assign({}, config);
|
108 |
|
109 | [
|
110 | "removeComments",
|
111 | "removeCommentsFromCDATA",
|
112 | "removeCDATASectionsFromCDATA",
|
113 | "collapseWhitespace",
|
114 | "conservativeCollapse",
|
115 | "removeAttributeQuotes",
|
116 | "useShortDoctype",
|
117 | "keepClosingSlash",
|
118 | "minifyJS",
|
119 | "minifyCSS",
|
120 | "removeScriptTypeAttributes",
|
121 | "removeStyleTypeAttributes",
|
122 | ].forEach(function(name) {
|
123 | if(typeof minimizeOptions[name] === "undefined") {
|
124 | minimizeOptions[name] = true;
|
125 | }
|
126 | });
|
127 |
|
128 | content = htmlMinifier.minify(content, minimizeOptions);
|
129 | }
|
130 |
|
131 | if(config.interpolate && config.interpolate !== 'require') {
|
132 |
|
133 | content = content.replace(/\\"/g, "\\\\\"");
|
134 | content = content.replace(/\\'/g, "\\\\\'");
|
135 | content = compile('`' + content + '`').code;
|
136 | } else {
|
137 | content = JSON.stringify(content);
|
138 | }
|
139 |
|
140 | var exportsString = "module.exports = ";
|
141 | if (config.exportAsDefault) {
|
142 | exportsString = "exports.default = ";
|
143 |
|
144 | } else if (config.exportAsEs6Default) {
|
145 | exportsString = "export default ";
|
146 | }
|
147 |
|
148 | return exportsString + content.replace(/xxxHTMLLINKxxx[0-9\.]+xxx/g, function(match) {
|
149 | if(!data[match]) return match;
|
150 |
|
151 | var urlToRequest;
|
152 |
|
153 | if (config.interpolate === 'require') {
|
154 | urlToRequest = data[match];
|
155 | } else {
|
156 | urlToRequest = loaderUtils.urlToRequest(data[match], root);
|
157 | }
|
158 |
|
159 | return '" + require(' + JSON.stringify(urlToRequest) + ') + "';
|
160 | }) + ";";
|
161 |
|
162 | }
|