html-loader
Advanced tools
Comparing version 5.0.0 to 5.1.0
@@ -16,3 +16,3 @@ "use strict"; | ||
var _options = _interopRequireDefault(require("./options.json")); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } | ||
async function loader(content) { | ||
@@ -29,4 +29,12 @@ const rawOptions = this.getOptions(_options.default); | ||
const replacements = []; | ||
let isSupportAbsoluteURL = false; | ||
// TODO enable by default in the next major release | ||
if (this._compilation && this._compilation.options && this._compilation.options.experiments && this._compilation.options.experiments.buildHttp) { | ||
isSupportAbsoluteURL = true; | ||
} | ||
if (options.sources) { | ||
plugins.push((0, _plugins.sourcesPlugin)({ | ||
isSupportAbsoluteURL, | ||
isSupportDataURL: options.esModule, | ||
sources: options.sources, | ||
@@ -46,3 +54,3 @@ resourcePath: this.resourcePath, | ||
} | ||
const { | ||
let { | ||
html | ||
@@ -53,6 +61,18 @@ } = await (0, _utils.pluginRunner)(plugins).process(content); | ||
} | ||
const importCode = (0, _utils.getImportCode)(html, this, imports, options); | ||
const moduleCode = (0, _utils.getModuleCode)(html, replacements, options); | ||
const isTemplateLiteralSupported = (0, _utils.supportTemplateLiteral)(this); | ||
html = (isTemplateLiteralSupported ? (0, _utils.convertToTemplateLiteral)(html) : JSON.stringify(html) | ||
// Invalid in JavaScript but valid HTML | ||
).replace(/[\u2028\u2029]/g, str => str === "\u2029" ? "\\u2029" : "\\u2028"); | ||
if (options.postprocessor) { | ||
// eslint-disable-next-line no-param-reassign | ||
html = await options.postprocessor(html, this); | ||
} | ||
const importCode = (0, _utils.getImportCode)(html, imports, options); | ||
const moduleCode = (0, _utils.getModuleCode)(html, replacements, this, { | ||
esModule: options.esModule, | ||
isTemplateLiteralSupported | ||
}); | ||
const exportCode = (0, _utils.getExportCode)(html, options); | ||
return `${importCode}${moduleCode}${exportCode}`; | ||
} |
@@ -48,2 +48,7 @@ { | ||
}, | ||
"postprocessor": { | ||
"instanceof": "Function", | ||
"description": "Allows post-processing of content before handling.", | ||
"link": "https://github.com/webpack-contrib/html-loader#postprocessor" | ||
}, | ||
"sources": { | ||
@@ -50,0 +55,0 @@ "anyOf": [ |
@@ -20,2 +20,2 @@ "use strict"; | ||
var _minimizerPlugin = _interopRequireDefault(require("./minimizer-plugin")); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } |
@@ -9,2 +9,4 @@ "use strict"; | ||
var _utils = require("../utils"); | ||
const DOUBLE_QUOTE = '"'.charCodeAt(0); | ||
const SINGLE_QUOTE = "'".charCodeAt(0); | ||
var _default = options => function process(html) { | ||
@@ -54,3 +56,3 @@ const sources = []; | ||
const attributeAndValue = html.slice(sourceCodeLocation.attrs[name].startOffset, sourceCodeLocation.attrs[name].endOffset); | ||
const isValueQuoted = attributeAndValue[attributeAndValue.length - 1] === '"' || attributeAndValue[attributeAndValue.length - 1] === "'"; | ||
const isValueQuoted = attributeAndValue.charCodeAt(attributeAndValue.length - 1) === DOUBLE_QUOTE || attributeAndValue.charCodeAt(attributeAndValue.length - 1) === SINGLE_QUOTE; | ||
const valueStartOffset = sourceCodeLocation.attrs[name].startOffset + attributeAndValue.indexOf(attribute.value); | ||
@@ -77,2 +79,4 @@ const valueEndOffset = sourceCodeLocation.attrs[name].endOffset - (isValueQuoted ? 1 : 0); | ||
value: attribute.value, | ||
isSupportAbsoluteURL: options.isSupportAbsoluteURL, | ||
isSupportDataURL: options.isSupportDataURL, | ||
isValueQuoted, | ||
@@ -112,4 +116,2 @@ valueEndOffset, | ||
isValueQuoted, | ||
format, | ||
runtime, | ||
startOffset, | ||
@@ -135,3 +137,2 @@ endOffset | ||
options.imports.push({ | ||
format, | ||
importName, | ||
@@ -154,4 +155,3 @@ request | ||
hash, | ||
isValueQuoted, | ||
runtime | ||
isValueQuoted | ||
}); | ||
@@ -158,0 +158,0 @@ } |
"use strict"; | ||
module.exports = function (url, options) { | ||
if (!options) { | ||
// eslint-disable-next-line no-param-reassign | ||
options = {}; | ||
} | ||
module.exports = function (url, maybeNeedQuotes) { | ||
if (!url) { | ||
@@ -13,8 +9,4 @@ return url; | ||
// eslint-disable-next-line no-underscore-dangle, no-param-reassign | ||
url = String(url.__esModule ? url.default : url); | ||
if (options.hash) { | ||
// eslint-disable-next-line no-param-reassign | ||
url += options.hash; | ||
} | ||
if (options.maybeNeedQuotes && /[\t\n\f\r "'=<>`]/.test(url)) { | ||
url = String(url); | ||
if (maybeNeedQuotes && /[\t\n\f\r "'=<>`]/.test(url)) { | ||
return "\"".concat(url, "\""); | ||
@@ -21,0 +13,0 @@ } |
@@ -7,2 +7,3 @@ "use strict"; | ||
exports.c0ControlCodesExclude = c0ControlCodesExclude; | ||
exports.convertToTemplateLiteral = convertToTemplateLiteral; | ||
exports.defaultMinimizerOptions = void 0; | ||
@@ -13,3 +14,3 @@ exports.getExportCode = getExportCode; | ||
exports.getModuleCode = getModuleCode; | ||
exports.isUrlRequestable = isUrlRequestable; | ||
exports.isURLRequestable = isURLRequestable; | ||
exports.normalizeOptions = normalizeOptions; | ||
@@ -22,2 +23,3 @@ exports.parseSrc = parseSrc; | ||
exports.srcsetType = srcsetType; | ||
exports.supportTemplateLiteral = supportTemplateLiteral; | ||
exports.traverse = traverse; | ||
@@ -27,15 +29,20 @@ exports.webpackIgnoreCommentRegexp = void 0; | ||
var _HtmlSourceError = _interopRequireDefault(require("./HtmlSourceError")); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } | ||
const HORIZONTAL_TAB = "\u0009".charCodeAt(0); | ||
const NEWLINE = "\u000A".charCodeAt(0); | ||
const FORM_FEED = "\u000C".charCodeAt(0); | ||
const CARRIAGE_RETURN = "\u000D".charCodeAt(0); | ||
const SPACE = "\u0020".charCodeAt(0); | ||
function isASCIIWhitespace(character) { | ||
return ( | ||
// Horizontal tab | ||
character === "\u0009" || | ||
character === HORIZONTAL_TAB || | ||
// New line | ||
character === "\u000A" || | ||
character === NEWLINE || | ||
// Form feed | ||
character === "\u000C" || | ||
character === FORM_FEED || | ||
// Carriage return | ||
character === "\u000D" || | ||
character === CARRIAGE_RETURN || | ||
// Space | ||
character === "\u0020" | ||
character === SPACE | ||
); | ||
@@ -53,2 +60,8 @@ } | ||
const regexNonNegativeInteger = /^\d+$/; | ||
const COMMA = ",".charCodeAt(0); | ||
const LEFT_PARENTHESIS = "(".charCodeAt(0); | ||
const RIGHT_PARENTHESIS = ")".charCodeAt(0); | ||
const SMALL_LETTER_W = "w".charCodeAt(0); | ||
const SMALL_LETTER_X = "x".charCodeAt(0); | ||
const SMALL_LETTER_H = "h".charCodeAt(0); | ||
@@ -117,3 +130,3 @@ // ( Positive or negative or unsigned integers or decimals, without or without exponents. | ||
// more than one character, that is a parse error. | ||
if (url.slice(-1) === ",") { | ||
if (url.charCodeAt(url.length - 1) === COMMA) { | ||
url = url.replace(regexTrailingCommas, ""); | ||
@@ -149,3 +162,3 @@ | ||
// 8.4. Let c be the character at position. | ||
c = input.charAt(position); | ||
c = input.charCodeAt(position); | ||
@@ -175,3 +188,3 @@ // Do the following depending on the value of state. | ||
// labeled descriptor parser. | ||
else if (c === ",") { | ||
else if (c === COMMA) { | ||
position += 1; | ||
@@ -186,4 +199,4 @@ if (currentDescriptor) { | ||
// Append c to current descriptor. Set state to in parens. | ||
else if (c === "\u0028") { | ||
currentDescriptor += c; | ||
else if (c === LEFT_PARENTHESIS) { | ||
currentDescriptor += input.charAt(position); | ||
state = "in parens"; | ||
@@ -194,3 +207,3 @@ } | ||
// descriptors. Jump to the step labeled descriptor parser. | ||
else if (c === "") { | ||
else if (isNaN(c)) { | ||
if (currentDescriptor) { | ||
@@ -205,3 +218,3 @@ descriptors.push(currentDescriptor); | ||
} else { | ||
currentDescriptor += c; | ||
currentDescriptor += input.charAt(position); | ||
} | ||
@@ -213,4 +226,4 @@ } | ||
// Append c to current descriptor. Set state to in descriptor. | ||
if (c === ")") { | ||
currentDescriptor += c; | ||
if (c === RIGHT_PARENTHESIS) { | ||
currentDescriptor += input.charAt(position); | ||
state = "in descriptor"; | ||
@@ -221,3 +234,3 @@ } | ||
// descriptor parser. | ||
else if (c === "") { | ||
else if (isNaN(c)) { | ||
descriptors.push(currentDescriptor); | ||
@@ -230,3 +243,3 @@ parseDescriptors(); | ||
else { | ||
currentDescriptor += c; | ||
currentDescriptor += input.charAt(position); | ||
} | ||
@@ -241,3 +254,3 @@ } | ||
// EOF: Jump to the step labeled descriptor parser. | ||
else if (c === "") { | ||
else if (isNaN(c)) { | ||
parseDescriptors(); | ||
@@ -286,3 +299,3 @@ return; | ||
desc = descriptors[i]; | ||
lastChar = desc[desc.length - 1]; | ||
lastChar = desc[desc.length - 1].charCodeAt(0); | ||
value = desc.substring(0, desc.length - 1); | ||
@@ -294,3 +307,3 @@ intVal = parseInt(value, 10); | ||
// a U+0077 LATIN SMALL LETTER W character | ||
if (regexNonNegativeInteger.test(value) && lastChar === "w") { | ||
if (regexNonNegativeInteger.test(value) && lastChar === SMALL_LETTER_W) { | ||
// If width and density are not both absent, then let error be yes. | ||
@@ -312,3 +325,3 @@ if (w || d) { | ||
// a U+0078 LATIN SMALL LETTER X character | ||
else if (regexFloatingPoint.test(value) && lastChar === "x") { | ||
else if (regexFloatingPoint.test(value) && lastChar === SMALL_LETTER_X) { | ||
// If width, density and future-compat-h are not all absent, then let error | ||
@@ -331,3 +344,3 @@ // be yes. | ||
// a U+0068 LATIN SMALL LETTER H character | ||
else if (regexNonNegativeInteger.test(value) && lastChar === "h") { | ||
else if (regexNonNegativeInteger.test(value) && lastChar === SMALL_LETTER_H) { | ||
// If height and density are not both absent, then let error be yes. | ||
@@ -387,3 +400,3 @@ if (h || d) { | ||
let start = 0; | ||
for (; start < input.length && isASCIIWhitespace(input[start]); start++); | ||
for (; start < input.length && isASCIIWhitespace(input.charCodeAt(start)); start++); | ||
if (start === input.length) { | ||
@@ -393,3 +406,3 @@ throw new Error("Must be non-empty"); | ||
let end = input.length - 1; | ||
for (; end > -1 && isASCIIWhitespace(input[end]); end--); | ||
for (; end > -1 && isASCIIWhitespace(input.charCodeAt(end)); end--); | ||
end += 1; | ||
@@ -409,3 +422,9 @@ let value = input; | ||
const WINDOWS_ABS_PATH_REGEXP = /^[a-zA-Z]:[\\/]|^\\\\/; | ||
function isUrlRequestable(url) { | ||
function isDataUrl(url) { | ||
if (/^data:/i.test(url)) { | ||
return true; | ||
} | ||
return false; | ||
} | ||
function isURLRequestable(url, options = {}) { | ||
// Protocol-relative URLs | ||
@@ -420,5 +439,19 @@ if (/^\/\//.test(url)) { | ||
} | ||
if (isDataUrl(url) && options.isSupportDataURL) { | ||
try { | ||
decodeURIComponent(url); | ||
} catch (ignoreError) { | ||
return false; | ||
} | ||
return true; | ||
} | ||
if (/^file:/i.test(url)) { | ||
return true; | ||
} | ||
// Absolute URLs | ||
if (/^[a-z][a-z0-9+.-]*:/i.test(url) && !WINDOWS_ABS_PATH_REGEXP.test(url)) { | ||
if (/^https?:/i.test(url)) { | ||
return options.isSupportAbsoluteURL; | ||
} | ||
return false; | ||
@@ -435,5 +468,6 @@ } | ||
const RELATIVE_PATH_REGEXP = /^\.\.?[/\\]/; | ||
const SLASH = "/".charCodeAt(0); | ||
const absoluteToRequest = (context, maybeAbsolutePath) => { | ||
if (maybeAbsolutePath[0] === "/") { | ||
if (maybeAbsolutePath.length > 1 && maybeAbsolutePath[maybeAbsolutePath.length - 1] === "/") { | ||
if (maybeAbsolutePath.charCodeAt(0) === SLASH) { | ||
if (maybeAbsolutePath.length > 1 && maybeAbsolutePath.charCodeAt(maybeAbsolutePath.length - 1) === SLASH) { | ||
// this 'path' is actually a regexp generated by dynamic requires. | ||
@@ -475,6 +509,6 @@ // Don't treat it as an absolute path. | ||
const newRequest = isWindowsAbsolutePath ? decodeURI(request).replace(/[\t\n\r]/g, "") : decodeURI(request).replace(/[\t\n\r]/g, "").replace(/\\/g, "/"); | ||
if (isWindowsAbsolutePath || newRequest[0] === "/") { | ||
if (isWindowsAbsolutePath || newRequest.charCodeAt(0) === SLASH) { | ||
return newRequest; | ||
} | ||
if (/^file:/i.test(newRequest)) { | ||
if (/^[a-z]+:/i.test(newRequest)) { | ||
return newRequest; | ||
@@ -599,3 +633,6 @@ } | ||
} | ||
if (!isUrlRequestable(source.value)) { | ||
if (!isURLRequestable(source.value, { | ||
isSupportDataURL: options.isSupportDataURL, | ||
isSupportAbsoluteURL: options.isSupportAbsoluteURL | ||
})) { | ||
return []; | ||
@@ -628,3 +665,6 @@ } | ||
} | ||
if (!isUrlRequestable(source.value)) { | ||
if (!isURLRequestable(source.value, { | ||
isSupportDataURL: options.isSupportDataURL, | ||
isSupportAbsoluteURL: options.isSupportAbsoluteURL | ||
})) { | ||
return false; | ||
@@ -688,50 +728,2 @@ } | ||
} | ||
// function webpackImportType(options) { | ||
// let source; | ||
// | ||
// try { | ||
// source = trimASCIIWhitespace(options.value); | ||
// } catch (error) { | ||
// throw new HtmlSourceError( | ||
// `Bad value for attribute "${options.attribute}" on element "${options.tag}": ${error.message}`, | ||
// options.attributeStartOffset, | ||
// options.attributeEndOffset, | ||
// options.html | ||
// ); | ||
// } | ||
// | ||
// try { | ||
// source = c0ControlCodesExclude(source); | ||
// } catch (error) { | ||
// throw new HtmlSourceError( | ||
// `Bad value for attribute "${options.attribute}" on element "${options.tag}": ${error.message}`, | ||
// options.attributeStartOffset, | ||
// options.attributeEndOffset, | ||
// options.html | ||
// ); | ||
// } | ||
// | ||
// if (!isUrlRequestable(source.value)) { | ||
// return []; | ||
// } | ||
// | ||
// const { startOffset } = options.startTag; | ||
// let { endOffset } = options.startTag; | ||
// | ||
// if (options.endTag) { | ||
// ({ endOffset } = options.endTag); | ||
// } | ||
// | ||
// return [ | ||
// { | ||
// format: 'import', | ||
// runtime: false, | ||
// value: source.value, | ||
// startOffset, | ||
// endOffset, | ||
// }, | ||
// ]; | ||
// } | ||
const defaultSources = new Map([["audio", new Map([["src", { | ||
@@ -871,2 +863,3 @@ type: srcType | ||
preprocessor: rawOptions.preprocessor, | ||
postprocessor: rawOptions.postprocessor, | ||
sources: getSourcesOption(rawOptions), | ||
@@ -898,38 +891,36 @@ minimize: getMinimizeOption(rawOptions, loaderContext), | ||
} | ||
const GET_SOURCE_FROM_IMPORT_NAME = "___HTML_LOADER_GET_SOURCE_FROM_IMPORT___"; | ||
function getImportCode(html, loaderContext, imports, options) { | ||
function getImportCode(html, imports, options) { | ||
if (imports.length === 0) { | ||
return ""; | ||
} | ||
// TODO simplify in the next major release | ||
const getURLRuntime = require.resolve("./runtime/getUrl.js"); | ||
const context = loaderContext.context || loaderContext.rootContext; | ||
const fileURLToHelper = typeof loaderContext.utils !== "undefined" && typeof loaderContext.utils.contextify === "function" ? loaderContext.utils.contextify(context, getURLRuntime) : contextify(context, getURLRuntime); | ||
let code = options.esModule ? `import ${GET_SOURCE_FROM_IMPORT_NAME} from "${fileURLToHelper}";\n` : `var ${GET_SOURCE_FROM_IMPORT_NAME} = require("${fileURLToHelper}");\n`; | ||
let code = ""; | ||
for (const item of imports) { | ||
const { | ||
format, | ||
importName, | ||
request | ||
} = item; | ||
switch (format) { | ||
case "import": | ||
code += options.esModule ? `import ${importName} from ${JSON.stringify(request)};\n` : `var ${importName} = require(${JSON.stringify(request)});\n`; | ||
break; | ||
case "url": | ||
default: | ||
code += options.esModule ? `var ${importName} = new URL(${JSON.stringify(request)}, import.meta.url);\n` : `var ${importName} = require(${JSON.stringify(request)});\n`; | ||
} | ||
code += options.esModule ? `var ${importName} = new URL(${JSON.stringify(request)}, import.meta.url);\n` : `var ${importName} = require(${JSON.stringify(request)});\n`; | ||
} | ||
return `// Imports\n${code}`; | ||
} | ||
function getModuleCode(html, replacements) { | ||
let code = JSON.stringify(html) | ||
// Invalid in JavaScript but valid HTML | ||
.replace(/[\u2028\u2029]/g, str => str === "\u2029" ? "\\u2029" : "\\u2028"); | ||
let replacersCode = ""; | ||
const BACKSLASH = "\\".charCodeAt(0); | ||
const BACKTICK = "`".charCodeAt(0); | ||
const DOLLAR = "$".charCodeAt(0); | ||
function convertToTemplateLiteral(str) { | ||
let escapedString = ""; | ||
for (let i = 0; i < str.length; i++) { | ||
const code = str.charCodeAt(i); | ||
escapedString += code === BACKSLASH || code === BACKTICK || code === DOLLAR ? `\\${str[i]}` : str[i]; | ||
} | ||
return `\`${escapedString}\``; | ||
} | ||
const GET_SOURCE_FROM_IMPORT_NAME = "___HTML_LOADER_GET_SOURCE_FROM_IMPORT___"; | ||
function getModuleCode(html, replacements, loaderContext, options) { | ||
let code = html; | ||
const { | ||
isTemplateLiteralSupported | ||
} = options; | ||
let needHelperImport = false; | ||
for (const item of replacements) { | ||
const { | ||
runtime, | ||
importName, | ||
@@ -940,15 +931,20 @@ replacementName, | ||
} = item; | ||
if (typeof runtime === "undefined" || runtime === true) { | ||
const getUrlOptions = [].concat(hash ? [`hash: ${JSON.stringify(hash)}`] : []).concat(isValueQuoted ? [] : "maybeNeedQuotes: true"); | ||
const preparedOptions = getUrlOptions.length > 0 ? `, { ${getUrlOptions.join(", ")} }` : ""; | ||
replacersCode += `var ${replacementName} = ${GET_SOURCE_FROM_IMPORT_NAME}(${importName}${preparedOptions});\n`; | ||
code = code.replace(new RegExp(replacementName, "g"), () => `" + ${replacementName} + "`); | ||
} else { | ||
code = code.replace(new RegExp(replacementName, "g"), () => `" + ${importName} + "`); | ||
if (!isValueQuoted && !needHelperImport) { | ||
needHelperImport = true; | ||
} | ||
const name = !isValueQuoted ? `${GET_SOURCE_FROM_IMPORT_NAME}(${importName}${!isValueQuoted ? ", true" : ""})` : importName; | ||
code = code.replace(new RegExp(replacementName, "g"), () => isTemplateLiteralSupported ? `\${${name}}${typeof hash !== "undefined" ? hash : ""}` : `" + ${name}${typeof hash !== "undefined" ? ` + ${JSON.stringify(hash)}` : ""} + "`); | ||
} | ||
// Replaces "<script>" or "</script>" to "<" + "script>" or "<" + "/script>". | ||
code = code.replace(/<(\/?script)/g, (_, s) => `<" + "${s}`); | ||
return `// Module\n${replacersCode}var code = ${code};\n`; | ||
code = code.replace(/<(\/?script)/g, (_, s) => isTemplateLiteralSupported ? `\${"<" + "${s}"}` : `<" + "${s}`); | ||
code = `// Module\nvar code = ${code};\n`; | ||
if (needHelperImport) { | ||
// TODO simplify in the next major release | ||
const getURLRuntime = require.resolve("./runtime/getUrl.js"); | ||
const context = loaderContext.context || loaderContext.rootContext; | ||
const fileURLToHelper = typeof loaderContext.utils !== "undefined" && typeof loaderContext.utils.contextify === "function" ? loaderContext.utils.contextify(context, getURLRuntime) : contextify(context, getURLRuntime); | ||
code = options.esModule ? `import ${GET_SOURCE_FROM_IMPORT_NAME} from "${fileURLToHelper}";\n${code}` : `var ${GET_SOURCE_FROM_IMPORT_NAME} = require("${fileURLToHelper}");\n${code}`; | ||
} | ||
return code; | ||
} | ||
@@ -1016,2 +1012,23 @@ function getExportCode(html, options) { | ||
} | ||
function supportTemplateLiteral(loaderContext) { | ||
if (loaderContext.environment && loaderContext.environment.templateLiteral) { | ||
return true; | ||
} | ||
// TODO remove in the next major release | ||
if ( | ||
// eslint-disable-next-line no-underscore-dangle | ||
loaderContext._compilation && | ||
// eslint-disable-next-line no-underscore-dangle | ||
loaderContext._compilation.options && | ||
// eslint-disable-next-line no-underscore-dangle | ||
loaderContext._compilation.options.output && | ||
// eslint-disable-next-line no-underscore-dangle | ||
loaderContext._compilation.options.output.environment && | ||
// eslint-disable-next-line no-underscore-dangle | ||
loaderContext._compilation.options.output.environment.templateLiteral) { | ||
return true; | ||
} | ||
return false; | ||
} | ||
const webpackIgnoreCommentRegexp = exports.webpackIgnoreCommentRegexp = /webpackIgnore:(\s+)?(true|false)/; |
{ | ||
"name": "html-loader", | ||
"version": "5.0.0", | ||
"version": "5.1.0", | ||
"description": "Html loader module for webpack", | ||
@@ -53,15 +53,15 @@ "license": "MIT", | ||
"devDependencies": { | ||
"@babel/cli": "^7.23.4", | ||
"@babel/core": "^7.23.7", | ||
"@babel/preset-env": "^7.23.8", | ||
"@commitlint/cli": "^18.4.4", | ||
"@commitlint/config-conventional": "^18.4.4", | ||
"@babel/cli": "^7.24.7", | ||
"@babel/core": "^7.24.7", | ||
"@babel/preset-env": "^7.24.7", | ||
"@commitlint/cli": "^18.6.1", | ||
"@commitlint/config-conventional": "^18.6.2", | ||
"@webpack-contrib/eslint-config-webpack": "^3.0.0", | ||
"babel-jest": "^29.7.0", | ||
"cross-env": "^7.0.3", | ||
"cspell": "^8.3.2", | ||
"cspell": "^8.9.1", | ||
"del": "^7.1.0", | ||
"del-cli": "^5.1.0", | ||
"es-check": "^7.1.1", | ||
"eslint": "^8.56.0", | ||
"es-check": "^7.2.1", | ||
"eslint": "^8.57.0", | ||
"eslint-config-prettier": "^9.1.0", | ||
@@ -73,11 +73,11 @@ "eslint-plugin-import": "^2.29.1", | ||
"jest": "^29.7.0", | ||
"lint-staged": "^15.2.0", | ||
"memfs": "^4.6.0", | ||
"lint-staged": "^15.2.7", | ||
"memfs": "^4.9.3", | ||
"npm-run-all": "^4.1.5", | ||
"posthtml": "^0.16.6", | ||
"posthtml-webp": "^2.2.0", | ||
"prettier": "^3.2.2", | ||
"prettier": "^3.3.2", | ||
"standard-version": "^9.5.0", | ||
"unescape-unicode": "^0.2.0", | ||
"webpack": "^5.89.0" | ||
"webpack": "^5.92.1" | ||
}, | ||
@@ -84,0 +84,0 @@ "keywords": [ |
@@ -66,2 +66,3 @@ <div align="center"> | ||
- **[`preprocessor`](#preprocessor)** | ||
- **[`postprocessor`](#postprocessor)** | ||
- **[`minimize`](#minimize)** | ||
@@ -100,3 +101,3 @@ - **[`esModule`](#esmodule)** | ||
By default every loadable attribute (for example - `<img src="image.png">`) is imported (`const img = require('./image.png')` or `import img from "./image.png""`). | ||
By default every loadable attribute (for example - `<img src="image.png">`) is imported (`const img = require('./image.png')` or `new URL("./image.png", import.meta.url)`). | ||
You may need to specify loaders for images in your configuration (recommended [`asset modules`](https://webpack.js.org/guides/asset-modules/)). | ||
@@ -374,3 +375,3 @@ | ||
> **Note** | ||
> [!NOTE] | ||
> | ||
@@ -496,6 +497,3 @@ > source with a `tag` option takes precedence over source without. | ||
```ts | ||
type preprocessor = ( | ||
content: string | Buffer, | ||
loaderContext: LoaderContext, | ||
) => HTMLElement; | ||
type preprocessor = (content: string, loaderContext: LoaderContext) => string; | ||
``` | ||
@@ -507,3 +505,3 @@ | ||
> **Warning** | ||
> [!WARNING] | ||
> | ||
@@ -599,2 +597,88 @@ > You should always return valid HTML | ||
### `postprocessor` | ||
Type: | ||
```ts | ||
type postprocessor = (content: string, loaderContext: LoaderContext) => string; | ||
``` | ||
Default: `undefined` | ||
Allows post-processing of content after replacing all attributes (like `src`/`srcset`/etc). | ||
**file.html** | ||
```html | ||
<img src="image.png" /> | ||
<img src="<%= 'Hello ' + (1+1) %>" /> | ||
<img src="<%= require('./image.png') %>" /> | ||
<img src="<%= new URL('./image.png', import.meta.url) %>" /> | ||
<div><%= require('./gallery.html').default %></div> | ||
``` | ||
#### `function` | ||
You can set the `postprocessor` option as a `function` instance. | ||
**webpack.config.js** | ||
```js | ||
const Handlebars = require("handlebars"); | ||
module.exports = { | ||
module: { | ||
rules: [ | ||
{ | ||
test: /\.html$/i, | ||
loader: "html-loader", | ||
options: { | ||
postprocessor: (content, loaderContext) => { | ||
// When you environment supports template literals (using browserslist or options) we will generate code using them | ||
const isTemplateLiteralSupported = content[0] === "`"; | ||
return content | ||
.replace(/<%=/g, isTemplateLiteralSupported ? `\${` : '" +') | ||
.replace(/%>/g, isTemplateLiteralSupported ? "}" : '+ "'); | ||
}, | ||
}, | ||
}, | ||
], | ||
}, | ||
}; | ||
``` | ||
You can also set the `postprocessor` option as an asynchronous function instance. | ||
For example: | ||
**webpack.config.js** | ||
```js | ||
const Handlebars = require("handlebars"); | ||
module.exports = { | ||
module: { | ||
rules: [ | ||
{ | ||
test: /\.hbs$/i, | ||
loader: "html-loader", | ||
options: { | ||
postprocessor: async (content, loaderContext) => { | ||
const value = await getValue(); | ||
// When you environment supports template literals (using browserslist or options) we will generate code using them | ||
const isTemplateLiteralSupported = content[0] === "`"; | ||
return content | ||
.replace(/<%=/g, isTemplateLiteralSupported ? `\${` : '" +') | ||
.replace(/%>/g, isTemplateLiteralSupported ? "}" : '+ "') | ||
.replace("my-value", value); | ||
}, | ||
}, | ||
}, | ||
], | ||
}, | ||
}; | ||
``` | ||
### `minimize` | ||
@@ -601,0 +685,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
76784
13
1375
1165