diff --git a/CHANGELOG.md b/CHANGELOG.md index d8dd04c7..93aa781b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [5.3.0](https://github.com/jantimon/html-webpack-plugin/compare/v5.2.0...v5.3.0) (2021-03-07) + + +### Features + +* allow to modify the interpolation options in webpack config ([d654f5b](https://github.com/jantimon/html-webpack-plugin/commit/d654f5b90022304335b372d424ff4c08d3a9d341)) +* drop loader-utils dependency ([41d7a50](https://github.com/jantimon/html-webpack-plugin/commit/41d7a50516aefd1af2704e3837d5d41351c6199b)) + ## [5.2.0](https://github.com/jantimon/html-webpack-plugin/compare/v5.1.0...v5.2.0) (2021-02-19) diff --git a/examples/pug-loader/dist/webpack-5/bundle.js b/examples/pug-loader/dist/webpack-5/bundle.js index 4b3da8a7..73b20e76 100644 --- a/examples/pug-loader/dist/webpack-5/bundle.js +++ b/examples/pug-loader/dist/webpack-5/bundle.js @@ -16,7 +16,15 @@ __webpack_require__.r(__webpack_exports__); var pug = __webpack_require__(79); -function template(locals) {var pug_html = "", pug_mixins = {}, pug_interp;;var locals_for_with = (locals || {});(function (time) {pug_html = pug_html + "\u003C!-- this partial is used for frontend and backend--\u003E\u003Cdiv class=\"time\"\u003E \u003Cb\u003ECurrent time\u003C\u002Fb\u003E\u003Cp\u003E" + (pug.escape(null == (pug_interp = time.toISOString()) ? "" : pug_interp)) + "\u003C\u002Fp\u003E\u003C\u002Fdiv\u003E\u003Cimg src=\"#{require('.\u002Flogo.png')}\"\u003E";}.call(this,"time" in locals_for_with?locals_for_with.time:typeof time!=="undefined"?time:undefined));;return pug_html;}; +function template(locals) {var pug_html = "", pug_mixins = {}, pug_interp;; + var locals_for_with = (locals || {}); + + (function (time) { + pug_html = pug_html + "\u003C!-- this partial is used for frontend and backend--\u003E\u003Cdiv class=\"time\"\u003E \u003Cb\u003ECurrent time\u003C\u002Fb\u003E\u003Cp\u003E" + (pug.escape(null == (pug_interp = time.toISOString()) ? "" : pug_interp)) + "\u003C\u002Fp\u003E\u003C\u002Fdiv\u003E\u003Cimg src=\"#{require('.\u002Flogo.png')}\"\u003E"; + }.call(this, "time" in locals_for_with ? + locals_for_with.time : + typeof time !== 'undefined' ? time : undefined)); + ;;return pug_html;}; module.exports = template; /***/ }), @@ -67,7 +75,7 @@ function pug_merge(a, b) { } return a; -}; +} /** * Process array, object, or string as a string of classes delimited by a space. @@ -88,7 +96,10 @@ function pug_merge(a, b) { */ exports.classes = pug_classes; function pug_classes_array(val, escaping) { - var classString = '', className, padding = '', escapeEnabled = Array.isArray(escaping); + var classString = '', + className, + padding = '', + escapeEnabled = Array.isArray(escaping); for (var i = 0; i < val.length; i++) { className = pug_classes(val[i]); if (!className) continue; @@ -99,7 +110,8 @@ function pug_classes_array(val, escaping) { return classString; } function pug_classes_object(val) { - var classString = '', padding = ''; + var classString = '', + padding = ''; for (var key in val) { if (key && val[key] && pug_has_own_property.call(val, key)) { classString = classString + padding + key; @@ -140,7 +152,7 @@ function pug_style(val) { } else { return val + ''; } -}; +} /** * Render the given attribute. @@ -153,25 +165,32 @@ function pug_style(val) { */ exports.attr = pug_attr; function pug_attr(key, val, escaped, terse) { - if (val === false || val == null || !val && (key === 'class' || key === 'style')) { + if ( + val === false || + val == null || + (!val && (key === 'class' || key === 'style')) + ) { return ''; } if (val === true) { return ' ' + (terse ? key : key + '="' + key + '"'); } var type = typeof val; - if ((type === 'object' || type === 'function') && typeof val.toJSON === 'function') { + if ( + (type === 'object' || type === 'function') && + typeof val.toJSON === 'function' + ) { val = val.toJSON(); } if (typeof val !== 'string') { val = JSON.stringify(val); if (!escaped && val.indexOf('"') !== -1) { - return ' ' + key + '=\'' + val.replace(/'/g, ''') + '\''; + return ' ' + key + "='" + val.replace(/'/g, ''') + "'"; } } if (escaped) val = pug_escape(val); return ' ' + key + '="' + val + '"'; -}; +} /** * Render the given attributes object. @@ -181,7 +200,7 @@ function pug_attr(key, val, escaped, terse) { * @return {String} */ exports.attrs = pug_attrs; -function pug_attrs(obj, terse){ +function pug_attrs(obj, terse) { var attrs = ''; for (var key in obj) { @@ -201,7 +220,7 @@ function pug_attrs(obj, terse){ } return attrs; -}; +} /** * Escape the given string of `html`. @@ -213,7 +232,7 @@ function pug_attrs(obj, terse){ var pug_match_html = /["&<>]/; exports.escape = pug_escape; -function pug_escape(_html){ +function pug_escape(_html) { var html = '' + _html; var regexResult = pug_match_html.exec(html); if (!regexResult) return _html; @@ -222,11 +241,20 @@ function pug_escape(_html){ var i, lastIndex, escape; for (i = regexResult.index, lastIndex = 0; i < html.length; i++) { switch (html.charCodeAt(i)) { - case 34: escape = '"'; break; - case 38: escape = '&'; break; - case 60: escape = '<'; break; - case 62: escape = '>'; break; - default: continue; + case 34: + escape = '"'; + break; + case 38: + escape = '&'; + break; + case 60: + escape = '<'; + break; + case 62: + escape = '>'; + break; + default: + continue; } if (lastIndex !== i) result += html.substring(lastIndex, i); lastIndex = i + 1; @@ -234,7 +262,7 @@ function pug_escape(_html){ } if (lastIndex !== i) return result + html.substring(lastIndex, i); else return result; -}; +} /** * Re-throw the given `err` in context to the @@ -248,37 +276,49 @@ function pug_escape(_html){ */ exports.rethrow = pug_rethrow; -function pug_rethrow(err, filename, lineno, str){ +function pug_rethrow(err, filename, lineno, str) { if (!(err instanceof Error)) throw err; if ((typeof window != 'undefined' || !filename) && !str) { err.message += ' on line ' + lineno; throw err; } + var context, lines, start, end; try { - str = str || __webpack_require__(993).readFileSync(filename, 'utf8') + str = str || __webpack_require__(993).readFileSync(filename, {encoding: 'utf8'}); + context = 3; + lines = str.split('\n'); + start = Math.max(lineno - context, 0); + end = Math.min(lines.length, lineno + context); } catch (ex) { - pug_rethrow(err, null, lineno) + err.message += + ' - could not read from ' + filename + ' (' + ex.message + ')'; + pug_rethrow(err, null, lineno); + return; } - var context = 3 - , lines = str.split('\n') - , start = Math.max(lineno - context, 0) - , end = Math.min(lines.length, lineno + context); // Error context - var context = lines.slice(start, end).map(function(line, i){ - var curr = i + start + 1; - return (curr == lineno ? ' > ' : ' ') - + curr - + '| ' - + line; - }).join('\n'); + context = lines + .slice(start, end) + .map(function(line, i) { + var curr = i + start + 1; + return (curr == lineno ? ' > ' : ' ') + curr + '| ' + line; + }) + .join('\n'); // Alter exception message err.path = filename; - err.message = (filename || 'Pug') + ':' + lineno - + '\n' + context + '\n\n' + err.message; + try { + err.message = + (filename || 'Pug') + + ':' + + lineno + + '\n' + + context + + '\n\n' + + err.message; + } catch (e) {} throw err; -}; +} /***/ }), diff --git a/lib/loader.js b/lib/loader.js index bd17fe88..ef8d2abd 100644 --- a/lib/loader.js +++ b/lib/loader.js @@ -2,20 +2,26 @@ // @ts-nocheck 'use strict'; const _ = require('lodash'); -const loaderUtils = require('loader-utils'); module.exports = function (source) { // Get templating options - const options = this.query !== '' ? loaderUtils.getOptions(this) : {}; + const options = this.getOptions(); const force = options.force || false; - const allLoadersButThisOne = this.loaders.filter(function (loader) { - return loader.normal !== module.exports; - }); + const allLoadersButThisOne = this.loaders.filter((loader) => loader.normal !== module.exports); + // This loader shouldn't kick in if there is any other loader (unless it's explicitly enforced) if (allLoadersButThisOne.length > 0 && !force) { return source; } + + // Allow only one html-webpack-plugin loader to allow loader options in the webpack config + const htmlWebpackPluginLoaders = this.loaders.filter((loader) => loader.normal === module.exports); + const lastHtmlWebpackPluginLoader = htmlWebpackPluginLoaders[htmlWebpackPluginLoaders.length - 1]; + if (this.loaders[this.loaderIndex] !== lastHtmlWebpackPluginLoader) { + return source; + } + // Skip .js files (unless it's explicitly enforced) if (/\.js$/.test(this.resourcePath) && !force) { return source; @@ -23,7 +29,7 @@ module.exports = function (source) { // The following part renders the template with lodash as a minimalistic loader // - const template = _.template(source, _.defaults(options, { interpolate: /<%=([\s\S]+?)%>/g, variable: 'data' })); + const template = _.template(source, { interpolate: /<%=([\s\S]+?)%>/g, variable: 'data', ...options }); // Use __non_webpack_require__ to enforce using the native nodejs require // during template execution return 'var _ = __non_webpack_require__(' + JSON.stringify(require.resolve('lodash')) + ');' + diff --git a/package.json b/package.json index cef91243..c814d399 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "html-webpack-plugin", - "version": "5.2.0", + "version": "5.3.0", "license": "MIT", "description": "Simplifies creation of HTML files to serve your webpack bundles", "author": "Jan Nicklas (https://github.com/jantimon)", @@ -34,10 +34,10 @@ "css-loader": "5.0.1", "cz-conventional-changelog": "2.1.0", "dir-compare": "1.7.2", - "html-loader": "2.0.0", + "html-loader": "2.1.1", "jest": "26.5.3", "mini-css-extract-plugin": "1.0.0", - "pug": "2.0.3", + "pug": "3.0.2", "pug-loader": "2.4.0", "raw-loader": "4.0.2", "rimraf": "2.6.3", @@ -52,7 +52,6 @@ "dependencies": { "@types/html-minifier-terser": "^5.0.0", "html-minifier-terser": "^5.0.1", - "loader-utils": "^2.0.0", "lodash": "^4.17.20", "pretty-error": "^2.1.1", "tapable": "^2.0.0" diff --git a/spec/basic.spec.js b/spec/basic.spec.js index 3cb646d5..572d7740 100644 --- a/spec/basic.spec.js +++ b/spec/basic.spec.js @@ -2750,4 +2750,36 @@ describe('HtmlWebpackPlugin', () => { ] }, [''], null, done); }); + + it('allows to set custom loader interpolation settings', done => { + testHtmlPlugin({ + mode: 'production', + entry: { + app: path.join(__dirname, 'fixtures/index.js') + }, + output: { + path: OUTPUT_DIR, + filename: '[name]_bundle.js' + }, + module: { + rules: [ + { + test: /\.html$/, + loader: require.resolve('../lib/loader.js'), + options: { + interpolate: /\{%=([\s\S]+?)%\}/g + } + } + ] + }, + plugins: [ + new HtmlWebpackPlugin({ + title: 'Interpolation Demo', + template: path.join(__dirname, 'fixtures/interpolation.html') + }) + ] + }, ['Interpolation Demo'], null, () => { + done(); + }); + }); }); diff --git a/spec/fixtures/legacy.html b/spec/fixtures/interpolation.html similarity index 58% rename from spec/fixtures/legacy.html rename to spec/fixtures/interpolation.html index 3611c961..5647aec2 100644 --- a/spec/fixtures/legacy.html +++ b/spec/fixtures/interpolation.html @@ -2,10 +2,9 @@ - Test + {%= htmlWebpackPlugin.options.title %}

Some unique text

- diff --git a/typings.d.ts b/typings.d.ts index 02817eb6..8aabd5cc 100644 --- a/typings.d.ts +++ b/typings.d.ts @@ -94,7 +94,7 @@ declare namespace HtmlWebpackPlugin { * blocking will result in * defer will result in * - * @default 'blocking' + * @default 'defer' */ scriptLoading?: "blocking" | "defer"; /**