Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions src/plugins/sources-plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import {
webpackIgnoreCommentRegexp,
} from "../utils";

const DOUBLE_QUOTE = '"'.charCodeAt(0);
const SINGLE_QUOTE = "'".charCodeAt(0);

export default (options) =>
function process(html) {
const sources = [];
Expand Down Expand Up @@ -71,8 +74,10 @@ export default (options) =>
sourceCodeLocation.attrs[name].endOffset,
);
const isValueQuoted =
attributeAndValue[attributeAndValue.length - 1] === '"' ||
attributeAndValue[attributeAndValue.length - 1] === "'";
attributeAndValue.charCodeAt(attributeAndValue.length - 1) ===
DOUBLE_QUOTE ||
attributeAndValue.charCodeAt(attributeAndValue.length - 1) ===
SINGLE_QUOTE;
const valueStartOffset =
sourceCodeLocation.attrs[name].startOffset +
attributeAndValue.indexOf(attribute.value);
Expand Down
76 changes: 48 additions & 28 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,24 @@ import path from "path";

import HtmlSourceError from "./HtmlSourceError";

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
);
}

Expand All @@ -26,6 +32,12 @@ const regexLeadingCommasOrSpaces = /^[, \t\n\r\u000c]+/;
const regexLeadingNotSpaces = /^[^ \t\n\r\u000c]+/;
const regexTrailingCommas = /[,]+$/;
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);

// ( Positive or negative or unsigned integers or decimals, without or without exponents.
// Must include at least one digit.
Expand Down Expand Up @@ -93,7 +105,7 @@ export function parseSrcset(input) {
// 8. If url ends with a U+002C COMMA character (,), follow these sub steps:
// (1). Remove all trailing U+002C COMMA characters from url. If this removed
// more than one character, that is a parse error.
if (url.slice(-1) === ",") {
if (url.charCodeAt(url.length - 1) === COMMA) {
url = url.replace(regexTrailingCommas, "");

// (Jump ahead to step 9 to skip tokenization and just push the candidate).
Expand Down Expand Up @@ -124,7 +136,7 @@ export function parseSrcset(input) {
// eslint-disable-next-line no-constant-condition
while (true) {
// 8.4. Let c be the character at position.
c = input.charAt(position);
c = input.charCodeAt(position);

// Do the following depending on the value of state.
// For the purpose of this step, "EOF" is a special character representing
Expand All @@ -149,7 +161,7 @@ export function parseSrcset(input) {
// Advance position to the next character in input. If current descriptor
// is not empty, append current descriptor to descriptors. Jump to the step
// labeled descriptor parser.
else if (c === ",") {
else if (c === COMMA) {
position += 1;

if (currentDescriptor) {
Expand All @@ -162,14 +174,14 @@ export function parseSrcset(input) {
}
// U+0028 LEFT PARENTHESIS (()
// 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";
}
// EOF
// If current descriptor is not empty, append current descriptor to
// descriptors. Jump to the step labeled descriptor parser.
else if (c === "") {
else if (isNaN(c)) {
if (currentDescriptor) {
descriptors.push(currentDescriptor);
}
Expand All @@ -181,29 +193,29 @@ export function parseSrcset(input) {
// Anything else
// Append c to current descriptor.
} else {
currentDescriptor += c;
currentDescriptor += input.charAt(position);
}
}
// In parens
else if (state === "in parens") {
// U+0029 RIGHT PARENTHESIS ())
// 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";
}
// EOF
// Append current descriptor to descriptors. Jump to the step labeled
// descriptor parser.
else if (c === "") {
else if (isNaN(c)) {
descriptors.push(currentDescriptor);
parseDescriptors();
return;
}
// Anything else
// Append c to current descriptor.
else {
currentDescriptor += c;
currentDescriptor += input.charAt(position);
}
}
// After descriptor
Expand All @@ -213,7 +225,7 @@ export function parseSrcset(input) {
// Space character: Stay in this state.
}
// EOF: Jump to the step labeled descriptor parser.
else if (c === "") {
else if (isNaN(c)) {
parseDescriptors();
return;
}
Expand Down Expand Up @@ -258,14 +270,14 @@ export function parseSrcset(input) {
for (i = 0; i < descriptors.length; i++) {
desc = descriptors[i];

lastChar = desc[desc.length - 1];
lastChar = desc[desc.length - 1].charCodeAt(0);
value = desc.substring(0, desc.length - 1);
intVal = parseInt(value, 10);
floatVal = parseFloat(value);

// If the descriptor consists of a valid non-negative integer followed by
// 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.
if (w || d) {
pError = true;
Expand All @@ -282,7 +294,7 @@ export function parseSrcset(input) {
}
// If the descriptor consists of a valid floating-point number followed by
// 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
// be yes.
if (w || d || h) {
Expand All @@ -300,7 +312,10 @@ export function parseSrcset(input) {
}
// If the descriptor consists of a valid non-negative integer followed by
// 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.
if (h || d) {
pError = true;
Expand Down Expand Up @@ -354,14 +369,18 @@ export function parseSrc(input) {
}

let start = 0;
for (; start < input.length && isASCIIWhitespace(input[start]); start++);
for (
;
start < input.length && isASCIIWhitespace(input.charCodeAt(start));
start++
);

if (start === input.length) {
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;

let value = input;
Expand Down Expand Up @@ -430,12 +449,13 @@ export function isURLRequestable(url, options = {}) {

const WINDOWS_PATH_SEPARATOR_REGEXP = /\\/g;
const RELATIVE_PATH_REGEXP = /^\.\.?[/\\]/;
const SLASH = "/".charCodeAt(0);

const absoluteToRequest = (context, maybeAbsolutePath) => {
if (maybeAbsolutePath[0] === "/") {
if (maybeAbsolutePath.charCodeAt(0) === SLASH) {
if (
maybeAbsolutePath.length > 1 &&
maybeAbsolutePath[maybeAbsolutePath.length - 1] === "/"
maybeAbsolutePath.charCodeAt(maybeAbsolutePath.length - 1) === SLASH
) {
// this 'path' is actually a regexp generated by dynamic requires.
// Don't treat it as an absolute path.
Expand Down Expand Up @@ -505,7 +525,7 @@ export function requestify(context, request) {
.replace(/[\t\n\r]/g, "")
.replace(/\\/g, "/");

if (isWindowsAbsolutePath || newRequest[0] === "/") {
if (isWindowsAbsolutePath || newRequest.charCodeAt(0) === SLASH) {
return newRequest;
}

Expand Down Expand Up @@ -1240,7 +1260,7 @@ export function getImportCode(html, loaderContext, imports, options) {
return `// Imports\n${code}`;
}

const SLASH = "\\".charCodeAt(0);
const BACKSLASH = "\\".charCodeAt(0);
const BACKTICK = "`".charCodeAt(0);
const DOLLAR = "$".charCodeAt(0);

Expand All @@ -1251,7 +1271,7 @@ export function convertToTemplateLiteral(str) {
const code = str.charCodeAt(i);

escapedString +=
code === SLASH || code === BACKTICK || code === DOLLAR
code === BACKSLASH || code === BACKTICK || code === DOLLAR
? `\\${str[i]}`
: str[i];
}
Expand Down
30 changes: 30 additions & 0 deletions test/__snapshots__/esModule-option.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ var ___HTML_LOADER_IMPORT_23___ = new URL("./video.mp4", import.meta.url);
var ___HTML_LOADER_IMPORT_24___ = new URL("./nested/image3.png", import.meta.url);
var ___HTML_LOADER_IMPORT_25___ = new URL("/nested/image3.png", import.meta.url);
var ___HTML_LOADER_IMPORT_26___ = new URL("./noscript.png", import.meta.url);
var ___HTML_LOADER_IMPORT_27___ = new URL("./😀abc.png", import.meta.url);
// Module
var ___HTML_LOADER_REPLACEMENT_0___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_0___);
var ___HTML_LOADER_REPLACEMENT_1___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_0___, { maybeNeedQuotes: true });
Expand Down Expand Up @@ -69,6 +70,7 @@ var ___HTML_LOADER_REPLACEMENT_32___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(
var ___HTML_LOADER_REPLACEMENT_33___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_24___);
var ___HTML_LOADER_REPLACEMENT_34___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_25___);
var ___HTML_LOADER_REPLACEMENT_35___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_26___);
var ___HTML_LOADER_REPLACEMENT_36___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_27___);
var code = \`<!doctype html>

<h1>My First Heading</h1>
Expand Down Expand Up @@ -518,6 +520,10 @@ alt" />
</noscript>

<img src="https://raw.githubusercontent.com/webpack-contrib/html-loader/master/test/fixtures/image.png">
<img src="\${___HTML_LOADER_REPLACEMENT_36___}" alt="Smiley face">
<img src="\${___HTML_LOADER_REPLACEMENT_36___}" alt="Smiley face">
<img srcset="\${___HTML_LOADER_REPLACEMENT_36___} 480w, \${___HTML_LOADER_REPLACEMENT_0___} 800w" sizes="(max-width: 600px) 480px, 800px" src="\${___HTML_LOADER_REPLACEMENT_0___}" alt="Elva dressed as a fairy">
<img srcset="\${___HTML_LOADER_REPLACEMENT_0___} 480w, \${___HTML_LOADER_REPLACEMENT_36___} 800w" sizes="(max-width: 600px) 480px, 800px" src="\${___HTML_LOADER_REPLACEMENT_0___}" alt="Elva dressed as a fairy">
\`;
// Exports
export default code;"
Expand Down Expand Up @@ -973,6 +979,10 @@ alt" />
</noscript>

<img src="https://raw.githubusercontent.com/webpack-contrib/html-loader/master/test/fixtures/image.png">
<img src="replaced_file_protocol_/webpack/public/path/%F0%9F%98%80abc.png" alt="Smiley face">
<img src="replaced_file_protocol_/webpack/public/path/%F0%9F%98%80abc.png" alt="Smiley face">
<img srcset="replaced_file_protocol_/webpack/public/path/%F0%9F%98%80abc.png 480w, replaced_file_protocol_/webpack/public/path/image.png 800w" sizes="(max-width: 600px) 480px, 800px" src="replaced_file_protocol_/webpack/public/path/image.png" alt="Elva dressed as a fairy">
<img srcset="replaced_file_protocol_/webpack/public/path/image.png 480w, replaced_file_protocol_/webpack/public/path/%F0%9F%98%80abc.png 800w" sizes="(max-width: 600px) 480px, 800px" src="replaced_file_protocol_/webpack/public/path/image.png" alt="Elva dressed as a fairy">
"
`;

Expand Down Expand Up @@ -1008,6 +1018,7 @@ var ___HTML_LOADER_IMPORT_21___ = require("./video.mp4");
var ___HTML_LOADER_IMPORT_22___ = require("./nested/image3.png");
var ___HTML_LOADER_IMPORT_23___ = require("/nested/image3.png");
var ___HTML_LOADER_IMPORT_24___ = require("./noscript.png");
var ___HTML_LOADER_IMPORT_25___ = require("./😀abc.png");
// Module
var ___HTML_LOADER_REPLACEMENT_0___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_0___);
var ___HTML_LOADER_REPLACEMENT_1___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_0___, { maybeNeedQuotes: true });
Expand Down Expand Up @@ -1043,6 +1054,7 @@ var ___HTML_LOADER_REPLACEMENT_30___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(
var ___HTML_LOADER_REPLACEMENT_31___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_22___);
var ___HTML_LOADER_REPLACEMENT_32___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_23___);
var ___HTML_LOADER_REPLACEMENT_33___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_24___);
var ___HTML_LOADER_REPLACEMENT_34___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_25___);
var code = \`<!doctype html>

<h1>My First Heading</h1>
Expand Down Expand Up @@ -1495,6 +1507,10 @@ ANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4
</noscript>

<img src="https://raw.githubusercontent.com/webpack-contrib/html-loader/master/test/fixtures/image.png">
<img src="\${___HTML_LOADER_REPLACEMENT_34___}" alt="Smiley face">
<img src="\${___HTML_LOADER_REPLACEMENT_34___}" alt="Smiley face">
<img srcset="\${___HTML_LOADER_REPLACEMENT_34___} 480w, \${___HTML_LOADER_REPLACEMENT_0___} 800w" sizes="(max-width: 600px) 480px, 800px" src="\${___HTML_LOADER_REPLACEMENT_0___}" alt="Elva dressed as a fairy">
<img srcset="\${___HTML_LOADER_REPLACEMENT_0___} 480w, \${___HTML_LOADER_REPLACEMENT_34___} 800w" sizes="(max-width: 600px) 480px, 800px" src="\${___HTML_LOADER_REPLACEMENT_0___}" alt="Elva dressed as a fairy">
\`;
// Exports
module.exports = code;"
Expand Down Expand Up @@ -1953,6 +1969,10 @@ ANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4
</noscript>

<img src="https://raw.githubusercontent.com/webpack-contrib/html-loader/master/test/fixtures/image.png">
<img src="/webpack/public/path/😀abc.png" alt="Smiley face">
<img src="/webpack/public/path/😀abc.png" alt="Smiley face">
<img srcset="/webpack/public/path/😀abc.png 480w, /webpack/public/path/image.png 800w" sizes="(max-width: 600px) 480px, 800px" src="/webpack/public/path/image.png" alt="Elva dressed as a fairy">
<img srcset="/webpack/public/path/image.png 480w, /webpack/public/path/😀abc.png 800w" sizes="(max-width: 600px) 480px, 800px" src="/webpack/public/path/image.png" alt="Elva dressed as a fairy">
"
`;

Expand Down Expand Up @@ -1990,6 +2010,7 @@ var ___HTML_LOADER_IMPORT_23___ = new URL("./video.mp4", import.meta.url);
var ___HTML_LOADER_IMPORT_24___ = new URL("./nested/image3.png", import.meta.url);
var ___HTML_LOADER_IMPORT_25___ = new URL("/nested/image3.png", import.meta.url);
var ___HTML_LOADER_IMPORT_26___ = new URL("./noscript.png", import.meta.url);
var ___HTML_LOADER_IMPORT_27___ = new URL("./😀abc.png", import.meta.url);
// Module
var ___HTML_LOADER_REPLACEMENT_0___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_0___);
var ___HTML_LOADER_REPLACEMENT_1___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_0___, { maybeNeedQuotes: true });
Expand Down Expand Up @@ -2027,6 +2048,7 @@ var ___HTML_LOADER_REPLACEMENT_32___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(
var ___HTML_LOADER_REPLACEMENT_33___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_24___);
var ___HTML_LOADER_REPLACEMENT_34___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_25___);
var ___HTML_LOADER_REPLACEMENT_35___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_26___);
var ___HTML_LOADER_REPLACEMENT_36___ = ___HTML_LOADER_GET_SOURCE_FROM_IMPORT___(___HTML_LOADER_IMPORT_27___);
var code = \`<!doctype html>

<h1>My First Heading</h1>
Expand Down Expand Up @@ -2476,6 +2498,10 @@ alt" />
</noscript>

<img src="https://raw.githubusercontent.com/webpack-contrib/html-loader/master/test/fixtures/image.png">
<img src="\${___HTML_LOADER_REPLACEMENT_36___}" alt="Smiley face">
<img src="\${___HTML_LOADER_REPLACEMENT_36___}" alt="Smiley face">
<img srcset="\${___HTML_LOADER_REPLACEMENT_36___} 480w, \${___HTML_LOADER_REPLACEMENT_0___} 800w" sizes="(max-width: 600px) 480px, 800px" src="\${___HTML_LOADER_REPLACEMENT_0___}" alt="Elva dressed as a fairy">
<img srcset="\${___HTML_LOADER_REPLACEMENT_0___} 480w, \${___HTML_LOADER_REPLACEMENT_36___} 800w" sizes="(max-width: 600px) 480px, 800px" src="\${___HTML_LOADER_REPLACEMENT_0___}" alt="Elva dressed as a fairy">
\`;
// Exports
export default code;"
Expand Down Expand Up @@ -2931,6 +2957,10 @@ alt" />
</noscript>

<img src="https://raw.githubusercontent.com/webpack-contrib/html-loader/master/test/fixtures/image.png">
<img src="replaced_file_protocol_/webpack/public/path/%F0%9F%98%80abc.png" alt="Smiley face">
<img src="replaced_file_protocol_/webpack/public/path/%F0%9F%98%80abc.png" alt="Smiley face">
<img srcset="replaced_file_protocol_/webpack/public/path/%F0%9F%98%80abc.png 480w, replaced_file_protocol_/webpack/public/path/image.png 800w" sizes="(max-width: 600px) 480px, 800px" src="replaced_file_protocol_/webpack/public/path/image.png" alt="Elva dressed as a fairy">
<img srcset="replaced_file_protocol_/webpack/public/path/image.png 480w, replaced_file_protocol_/webpack/public/path/%F0%9F%98%80abc.png 800w" sizes="(max-width: 600px) 480px, 800px" src="replaced_file_protocol_/webpack/public/path/image.png" alt="Elva dressed as a fairy">
"
`;

Expand Down
Loading