html-rspack-plugin
Advanced tools
| /* This loader renders the template with lodash.template if no other loader was found */ | ||
| // @ts-nocheck | ||
| /** | ||
| * This is a minimal implementation of `lodash.template` | ||
| * Modified based on lodash v4.17.21 | ||
| * License: https://github.com/lodash/lodash/blob/main/LICENSE | ||
| */ | ||
| /** Used to match template delimiters. */ | ||
| const reEscape = /<%-([\s\S]+?)%>/g; | ||
| /** Used to match template delimiters. */ | ||
| const reEvaluate = /<%([\s\S]+?)%>/g; | ||
| /** Used to match template delimiters. */ | ||
| const reInterpolate = /<%=([\s\S]+?)%>/g; | ||
| /** Used to match empty string literals in compiled template source. */ | ||
| const reEmptyStringLeading = /\b__p \+= '';/g, | ||
| reEmptyStringMiddle = /\b(__p \+=) '' \+/g, | ||
| reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; | ||
| /** Used to match unescaped characters in compiled string literals. */ | ||
| const reUnescapedString = /['\n\r\u2028\u2029\\]/g; | ||
| /** Used to escape characters for inclusion in compiled string literals. */ | ||
| const stringEscapes = { | ||
| '\\': '\\', | ||
| "'": "'", | ||
| '\n': 'n', | ||
| '\r': 'r', | ||
| '\u2028': 'u2028', | ||
| '\u2029': 'u2029', | ||
| }; | ||
| const WITH_PLACEHOLDER = 'function __with_placeholder__'; | ||
| const escapeStringChar = (chr) => '\\' + stringEscapes[chr]; | ||
| function template(string) { | ||
| let isEscaping; | ||
| let isEvaluating; | ||
| let index = 0; | ||
| let source = "__p += '"; | ||
| // Compile the regexp to match each delimiter. | ||
| const reDelimiters = RegExp( | ||
| reEscape.source + | ||
| '|' + | ||
| reInterpolate.source + | ||
| '|' + | ||
| reEvaluate.source + | ||
| '|$', | ||
| 'g', | ||
| ); | ||
| string.replace( | ||
| reDelimiters, | ||
| function ( | ||
| match, | ||
| escapeValue, | ||
| interpolateValue, | ||
| evaluateValue, | ||
| offset, | ||
| ) { | ||
| // Escape characters that can't be included in string literals. | ||
| source += string | ||
| .slice(index, offset) | ||
| .replace(reUnescapedString, escapeStringChar); | ||
| // Replace delimiters with snippets. | ||
| if (escapeValue) { | ||
| isEscaping = true; | ||
| source += "' +\n__e(" + escapeValue + ") +\n'"; | ||
| } | ||
| if (evaluateValue) { | ||
| isEvaluating = true; | ||
| source += "';\n" + evaluateValue + ";\n__p += '"; | ||
| } | ||
| if (interpolateValue) { | ||
| source += | ||
| "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'"; | ||
| } | ||
| index = offset + match.length; | ||
| // The JS engine embedded in Adobe products needs `match` returned in | ||
| // order to produce the correct `offset` value. | ||
| return match; | ||
| }, | ||
| ); | ||
| source += "';\n"; | ||
| // Cleanup code by stripping empty strings. | ||
| source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source) | ||
| .replace(reEmptyStringMiddle, '$1') | ||
| .replace(reEmptyStringTrailing, '$1;'); | ||
| // Frame code as the function body. | ||
| source = | ||
| 'function(' + | ||
| 'data' + | ||
| ') {\n' + | ||
| "let __t, __p = ''" + | ||
| (isEscaping ? ', __e = lodashEscape' : '') + | ||
| (isEvaluating | ||
| ? ', __j = Array.prototype.join;\n' + | ||
| "function print() { __p += __j.call(arguments, '') }\n" | ||
| : ';\n') + | ||
| source + | ||
| 'return __p\n}'; | ||
| return { compiled: source, isEscaping }; | ||
| } | ||
| module.exports = function (source) { | ||
| const allLoadersButThisOne = this.loaders.filter( | ||
| (loader) => loader.normal !== module.exports, | ||
| ); | ||
| // This loader shouldn't kick in if there is any other loader | ||
| if (allLoadersButThisOne.length > 0) { | ||
| 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 lastHtmlRspackPluginLoader = | ||
| htmlWebpackPluginLoaders[htmlWebpackPluginLoaders.length - 1]; | ||
| if (this.loaders[this.loaderIndex] !== lastHtmlRspackPluginLoader) { | ||
| return source; | ||
| } | ||
| if (/\.(c|m)?js$/.test(this.resourcePath)) { | ||
| return source; | ||
| } | ||
| const escapeCode = `const htmlEscapes = { | ||
| "&": "&", | ||
| "<": "<", | ||
| ">": ">", | ||
| '"': """, | ||
| "'": "'", | ||
| }; | ||
| const escapeHtmlChar = (key) => htmlEscapes[key]; | ||
| const reUnescapedHtml = /[&<>"']/g, reHasUnescapedHtml = RegExp(reUnescapedHtml.source); | ||
| function lodashEscape(input) { | ||
| if (input === null || input === undefined) { | ||
| return ''; | ||
| } | ||
| const string = typeof input === 'string' ? input : String(input); | ||
| return string && reHasUnescapedHtml.test(string) | ||
| ? string.replace(reUnescapedHtml, escapeHtmlChar) | ||
| : string; | ||
| };`; | ||
| // The following part renders the template with lodash as a minimalistic loader | ||
| // The WITH_PLACEHOLDER will be replaced with `with` in the next step | ||
| // to make the code compatible with SWC strict mode | ||
| const { compiled, isEscaping } = template(source); | ||
| return ` | ||
| module.exports = function (templateParams) { ${WITH_PLACEHOLDER}(templateParams) { | ||
| ${isEscaping ? escapeCode : ''} | ||
| // Execute the lodash template | ||
| return (${compiled})(); | ||
| }}`; | ||
| }; |
+47
-44
@@ -130,3 +130,3 @@ // @ts-check | ||
| : // Replace '[name]' with entry name | ||
| (entryName) => userOptionFilename.replace(/\[name\]/g, entryName); | ||
| (entryName) => userOptionFilename.replace(/\[name\]/g, entryName); | ||
@@ -228,3 +228,3 @@ /** output filenames for the given entry names */ | ||
| if (template.indexOf('!') === -1) { | ||
| const loader = require.resolve('./loader.js'); | ||
| const loader = require.resolve('./htmlLoader.js'); | ||
| template = loader + '!' + path.resolve(context, template); | ||
@@ -373,14 +373,14 @@ } | ||
| ? // If a hard coded public path exists use it | ||
| webpackPublicPath | ||
| webpackPublicPath | ||
| : // If no public path was set get a relative url path | ||
| path | ||
| .relative( | ||
| path.resolve( | ||
| path | ||
| .relative( | ||
| path.resolve( | ||
| compilation.options.output.path, | ||
| path.dirname(filename), | ||
| ), | ||
| compilation.options.output.path, | ||
| path.dirname(filename), | ||
| ), | ||
| compilation.options.output.path, | ||
| ) | ||
| .split(path.sep) | ||
| .join('/'); | ||
| ) | ||
| .split(path.sep) | ||
| .join('/'); | ||
@@ -601,6 +601,6 @@ if (publicPath.length && publicPath.substr(-1, 1) !== '/') { | ||
| : Promise.reject( | ||
| new Error( | ||
| 'The loader "' + templateWithoutLoaders + '" didn\'t return html.', | ||
| ), | ||
| ); | ||
| new Error( | ||
| 'The loader "' + templateWithoutLoaders + '" didn\'t return html.', | ||
| ), | ||
| ); | ||
| } | ||
@@ -659,15 +659,15 @@ | ||
| ? // A custom function can overwrite the entire template parameter preparation | ||
| templateParameters | ||
| templateParameters | ||
| : // If the template parameters is an object merge it with the default values | ||
| (compilation, assetsInformationByGroups, assetTags, options) => | ||
| Object.assign( | ||
| {}, | ||
| templateParametersGenerator( | ||
| compilation, | ||
| assetsInformationByGroups, | ||
| assetTags, | ||
| options, | ||
| ), | ||
| templateParameters, | ||
| ); | ||
| (compilation, assetsInformationByGroups, assetTags, options) => | ||
| Object.assign( | ||
| {}, | ||
| templateParametersGenerator( | ||
| compilation, | ||
| assetsInformationByGroups, | ||
| assetTags, | ||
| options, | ||
| ), | ||
| templateParameters, | ||
| ); | ||
| const preparedAssetTags = { | ||
@@ -755,3 +755,3 @@ headTags: this.prepareAssetTagGroupForRendering(assetTags.headTags), | ||
| const bodyRegExp = /(<\/body\s*>)/i; | ||
| const doctypeRegExp = /<!doctype html>/i | ||
| const doctypeRegExp = /<!doctype html>/i; | ||
@@ -794,3 +794,6 @@ const metaViewportRegExp = /<meta[^>]+name=["']viewport["'][^>]*>/i; | ||
| if (doctypeRegExp.test(html)) { | ||
| html = html.replace(doctypeRegExp, (match) => match + '<head></head>'); | ||
| html = html.replace( | ||
| doctypeRegExp, | ||
| (match) => match + '<head></head>', | ||
| ); | ||
| } else { | ||
@@ -865,3 +868,3 @@ html = '<head></head>' + html; | ||
| const source = new compiler.webpack.sources.RawSource( | ||
| /** @type {string | Buffer} */(buf), | ||
| /** @type {string | Buffer} */ (buf), | ||
| false, | ||
@@ -880,3 +883,3 @@ ); | ||
| faviconPath, | ||
| /** @type {string} */(compilation.hash), | ||
| /** @type {string} */ (compilation.hash), | ||
| ); | ||
@@ -960,4 +963,4 @@ } | ||
| ? { | ||
| href: base, | ||
| } | ||
| href: base, | ||
| } | ||
| : base, | ||
@@ -988,5 +991,5 @@ }, | ||
| ? { | ||
| name: metaName, | ||
| content: metaTagContent, | ||
| } | ||
| name: metaName, | ||
| content: metaTagContent, | ||
| } | ||
| : metaTagContent; | ||
@@ -1230,4 +1233,4 @@ }) | ||
| this.options.inject === 'head' || | ||
| (this.options.inject !== 'body' && | ||
| this.options.scriptLoading !== 'blocking') | ||
| (this.options.inject !== 'body' && | ||
| this.options.scriptLoading !== 'blocking') | ||
| ? 'head' | ||
@@ -1297,7 +1300,7 @@ : 'body'; | ||
| : this.executeTemplate( | ||
| compilationResult, | ||
| assetsHookResult.assets, | ||
| { headTags: assetTags.headTags, bodyTags: assetTags.bodyTags }, | ||
| compilation, | ||
| ), | ||
| compilationResult, | ||
| assetsHookResult.assets, | ||
| { headTags: assetTags.headTags, bodyTags: assetTags.bodyTags }, | ||
| compilation, | ||
| ), | ||
| ); | ||
@@ -1304,0 +1307,0 @@ |
+1
-1
| { | ||
| "name": "html-rspack-plugin", | ||
| "version": "6.1.6", | ||
| "version": "6.1.7", | ||
| "license": "MIT", | ||
@@ -5,0 +5,0 @@ "description": "Simplifies creation of HTML files to serve your Rspack bundles", |
-166
| /* This loader renders the template with lodash.template if no other loader was found */ | ||
| // @ts-nocheck | ||
| /** | ||
| * This is a minimal implementation of `lodash.template` | ||
| * Modified based on lodash v4.17.21 | ||
| * License: https://github.com/lodash/lodash/blob/main/LICENSE | ||
| */ | ||
| /** Used to match template delimiters. */ | ||
| const reEscape = /<%-([\s\S]+?)%>/g; | ||
| /** Used to match template delimiters. */ | ||
| const reEvaluate = /<%([\s\S]+?)%>/g; | ||
| /** Used to match template delimiters. */ | ||
| const reInterpolate = /<%=([\s\S]+?)%>/g; | ||
| /** Used to match empty string literals in compiled template source. */ | ||
| const reEmptyStringLeading = /\b__p \+= '';/g, | ||
| reEmptyStringMiddle = /\b(__p \+=) '' \+/g, | ||
| reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; | ||
| /** Used to match unescaped characters in compiled string literals. */ | ||
| const reUnescapedString = /['\n\r\u2028\u2029\\]/g; | ||
| /** Used to escape characters for inclusion in compiled string literals. */ | ||
| const stringEscapes = { | ||
| '\\': '\\', | ||
| "'": "'", | ||
| '\n': 'n', | ||
| '\r': 'r', | ||
| '\u2028': 'u2028', | ||
| '\u2029': 'u2029', | ||
| }; | ||
| const WITH_PLACEHOLDER = 'function __with_placeholder__'; | ||
| const escapeStringChar = (chr) => '\\' + stringEscapes[chr]; | ||
| function template(string) { | ||
| let isEscaping; | ||
| let isEvaluating; | ||
| let index = 0; | ||
| let source = "__p += '"; | ||
| // Compile the regexp to match each delimiter. | ||
| const reDelimiters = RegExp( | ||
| reEscape.source + | ||
| '|' + | ||
| reInterpolate.source + | ||
| '|' + | ||
| reEvaluate.source + | ||
| '|$', | ||
| 'g', | ||
| ); | ||
| string.replace( | ||
| reDelimiters, | ||
| function ( | ||
| match, | ||
| escapeValue, | ||
| interpolateValue, | ||
| evaluateValue, | ||
| offset, | ||
| ) { | ||
| // Escape characters that can't be included in string literals. | ||
| source += string | ||
| .slice(index, offset) | ||
| .replace(reUnescapedString, escapeStringChar); | ||
| // Replace delimiters with snippets. | ||
| if (escapeValue) { | ||
| isEscaping = true; | ||
| source += "' +\n__e(" + escapeValue + ") +\n'"; | ||
| } | ||
| if (evaluateValue) { | ||
| isEvaluating = true; | ||
| source += "';\n" + evaluateValue + ";\n__p += '"; | ||
| } | ||
| if (interpolateValue) { | ||
| source += | ||
| "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'"; | ||
| } | ||
| index = offset + match.length; | ||
| // The JS engine embedded in Adobe products needs `match` returned in | ||
| // order to produce the correct `offset` value. | ||
| return match; | ||
| }, | ||
| ); | ||
| source += "';\n"; | ||
| // Cleanup code by stripping empty strings. | ||
| source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source) | ||
| .replace(reEmptyStringMiddle, '$1') | ||
| .replace(reEmptyStringTrailing, '$1;'); | ||
| // Frame code as the function body. | ||
| source = | ||
| 'function(' + | ||
| 'data' + | ||
| ') {\n' + | ||
| "let __t, __p = ''" + | ||
| (isEscaping ? ', __e = lodashEscape' : '') + | ||
| (isEvaluating | ||
| ? ', __j = Array.prototype.join;\n' + | ||
| "function print() { __p += __j.call(arguments, '') }\n" | ||
| : ';\n') + | ||
| source + | ||
| 'return __p\n}'; | ||
| return { compiled: source, isEscaping }; | ||
| } | ||
| module.exports = function (source) { | ||
| const allLoadersButThisOne = this.loaders.filter( | ||
| (loader) => loader.normal !== module.exports, | ||
| ); | ||
| // This loader shouldn't kick in if there is any other loader | ||
| if (allLoadersButThisOne.length > 0) { | ||
| 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 lastHtmlRspackPluginLoader = | ||
| htmlWebpackPluginLoaders[htmlWebpackPluginLoaders.length - 1]; | ||
| if (this.loaders[this.loaderIndex] !== lastHtmlRspackPluginLoader) { | ||
| return source; | ||
| } | ||
| if (/\.(c|m)?js$/.test(this.resourcePath)) { | ||
| return source; | ||
| } | ||
| const escapeCode = `const htmlEscapes = { | ||
| "&": "&", | ||
| "<": "<", | ||
| ">": ">", | ||
| '"': """, | ||
| "'": "'", | ||
| }; | ||
| const escapeHtmlChar = (key) => htmlEscapes[key]; | ||
| const reUnescapedHtml = /[&<>"']/g, reHasUnescapedHtml = RegExp(reUnescapedHtml.source); | ||
| function lodashEscape(input) { | ||
| if (input === null || input === undefined) { | ||
| return ''; | ||
| } | ||
| const string = typeof input === 'string' ? input : String(input); | ||
| return string && reHasUnescapedHtml.test(string) | ||
| ? string.replace(reUnescapedHtml, escapeHtmlChar) | ||
| : string; | ||
| };`; | ||
| // The following part renders the template with lodash as a minimalistic loader | ||
| // The WITH_PLACEHOLDER will be replaced with `with` in the next step | ||
| // to make the code compatible with SWC strict mode | ||
| const { compiled, isEscaping } = template(source); | ||
| return ` | ||
| module.exports = function (templateParams) { ${WITH_PLACEHOLDER}(templateParams) { | ||
| ${isEscaping ? escapeCode : ''} | ||
| // Execute the lodash template | ||
| return (${compiled})(); | ||
| }}`; | ||
| }; |
110087
0.12%2572
0.12%