index.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  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. function randomIdent() {
  12. return "xxxHTMLLINKxxx" + Math.random() + Math.random() + "xxx";
  13. }
  14. function getLoaderConfig(context) {
  15. var query = loaderUtils.getOptions(context) || {};
  16. var configKey = query.config || 'htmlLoader';
  17. var config = context.options && context.options.hasOwnProperty(configKey) ? context.options[configKey] : {};
  18. delete query.config;
  19. return assign(query, config);
  20. }
  21. module.exports = function(content) {
  22. this.cacheable && this.cacheable();
  23. var config = getLoaderConfig(this);
  24. var attributes = ["img:src"];
  25. if(config.attrs !== undefined) {
  26. if(typeof config.attrs === "string")
  27. attributes = config.attrs.split(" ");
  28. else if(Array.isArray(config.attrs))
  29. attributes = config.attrs;
  30. else if(config.attrs === false)
  31. attributes = [];
  32. else
  33. throw new Error("Invalid value to config parameter attrs");
  34. }
  35. var root = config.root;
  36. var links = attrParse(content, function(tag, attr) {
  37. return attributes.indexOf(tag + ":" + attr) >= 0;
  38. });
  39. links.reverse();
  40. var data = {};
  41. content = [content];
  42. links.forEach(function(link) {
  43. if(!loaderUtils.isUrlRequest(link.value, root)) return;
  44. var uri = url.parse(link.value);
  45. if (uri.hash !== null && uri.hash !== undefined) {
  46. uri.hash = null;
  47. link.value = uri.format();
  48. link.length = link.value.length;
  49. }
  50. do {
  51. var ident = randomIdent();
  52. } while(data[ident]);
  53. data[ident] = link.value;
  54. var x = content.pop();
  55. content.push(x.substr(link.start + link.length));
  56. content.push(ident);
  57. content.push(x.substr(0, link.start));
  58. });
  59. content.reverse();
  60. content = content.join("");
  61. if (config.interpolate === 'require'){
  62. var reg = /\$\{require\([^)]*\)\}/g;
  63. var result;
  64. var reqList = [];
  65. while(result = reg.exec(content)){
  66. reqList.push({
  67. length : result[0].length,
  68. start : result.index,
  69. value : result[0]
  70. })
  71. }
  72. reqList.reverse();
  73. content = [content];
  74. reqList.forEach(function(link) {
  75. var x = content.pop();
  76. do {
  77. var ident = randomIdent();
  78. } while(data[ident]);
  79. data[ident] = link.value.substring(11,link.length - 3)
  80. content.push(x.substr(link.start + link.length));
  81. content.push(ident);
  82. content.push(x.substr(0, link.start));
  83. });
  84. content.reverse();
  85. content = content.join("");
  86. }
  87. if(typeof config.minimize === "boolean" ? config.minimize : this.minimize) {
  88. var minimizeOptions = assign({}, config);
  89. [
  90. "removeComments",
  91. "removeCommentsFromCDATA",
  92. "removeCDATASectionsFromCDATA",
  93. "collapseWhitespace",
  94. "conservativeCollapse",
  95. "removeAttributeQuotes",
  96. "useShortDoctype",
  97. "keepClosingSlash",
  98. "minifyJS",
  99. "minifyCSS",
  100. "removeScriptTypeAttributes",
  101. "removeStyleTypeAttributes",
  102. ].forEach(function(name) {
  103. if(typeof minimizeOptions[name] === "undefined") {
  104. minimizeOptions[name] = true;
  105. }
  106. });
  107. content = htmlMinifier.minify(content, minimizeOptions);
  108. }
  109. if(config.interpolate && config.interpolate !== 'require') {
  110. content = compile('`' + content + '`').code;
  111. } else {
  112. content = JSON.stringify(content);
  113. }
  114. var exportsString = "module.exports = ";
  115. if (config.exportAsDefault) {
  116. exportsString = "exports.default = ";
  117. } else if (config.exportAsEs6Default) {
  118. exportsString = "export default ";
  119. }
  120. return exportsString + content.replace(/xxxHTMLLINKxxx[0-9\.]+xxx/g, function(match) {
  121. if(!data[match]) return match;
  122. return '" + require(' + JSON.stringify(loaderUtils.urlToRequest(data[match], root)) + ') + "';
  123. }) + ";";
  124. }