Visitar URL original
fix(html): offer a deferred `style` list already at its shortest · webpack/webpack@eb38865 · GitHub
Skip to content

Commit eb38865

Browse files
fix(html): offer a deferred style list already at its shortest
A list the built-in leaves as it found it — `margin:0 auto`, which cannot go unquoted either — is one `_writeAttribute` declines, and the attribute then took the source path without deferring, so no renderer was ever asked about it. The synchronous path asks whatever the built-in made of it, and now this one does too, with the source standing until an answer arrives. Co-authored-by: aryanraj45 <143009186+aryanraj45@users.noreply.github.com>
1 parent 280a466 commit eb38865

4 files changed

Lines changed: 63 additions & 34 deletions

File tree

‎.changeset/017-html-attribute-switches.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
"webpack": minor
33
---
44

5-
Add `normalizeUrlAttributes`, widen boolean collapsing, and honour `sortTokenLists` and a deferred `style` answer.
5+
Add `normalizeUrlAttributes`, widen boolean collapsing, free `sortTokenLists`.

‎lib/html/syntax.js‎

Lines changed: 38 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -11084,39 +11084,45 @@ const _minifyOpenTag = (path, open) => {
1108411084
? writeStyle(declarations !== null ? declarations : value)
1108511085
: _writeAttribute(attributeName, value, rawValue, spellable);
1108611086

11087+
// Offered whatever the built-in made of it: a list already at its
11088+
// shortest is one `_writeAttribute` declines, not one to ask nobody about.
11089+
if (isStyle && _deferEmbeddedSource !== undefined) {
11090+
// Declining leaves the attribute as written, delimiter and all — an
11091+
// answer nothing beats is the renderer keeping what it was given.
11092+
const delimiter = open[valueStart - tagStart - 1];
11093+
const asWritten = ` ${attributeName}=${delimiter}${rawValue}${delimiter}`;
11094+
// What stands until an answer arrives, and the tag ending it commits
11095+
// to: the built-in's text where it beat the source, else the source.
11096+
const standing = written !== null ? written.text : asWritten;
11097+
const standingTail = written !== null && written.unquotedTail;
11098+
11099+
// The list is deferred, not the shape around it: the tag ending is
11100+
// read back before an answer arrives, so one changing it is declined.
11101+
out += _deferEmbedded(
11102+
// Decoded when the source spelled it with references, since that
11103+
// is the list itself rather than one attribute's spelling.
11104+
spellable !== null ? spellable : rawValue,
11105+
CSS_TYPE,
11106+
(rendered) => {
11107+
if (typeof rendered !== "string") return standing;
11108+
11109+
const answered = writeStyle(rendered);
11110+
// Declining ends the value quoted: this is the branch the
11111+
// source spelled with a delimiter.
11112+
const tail = answered !== null && answered.unquotedTail;
11113+
11114+
if (tailIsRead && tail !== standingTail) return standing;
11115+
11116+
return answered !== null ? answered.text : asWritten;
11117+
},
11118+
BLOCK_CONTENTS
11119+
);
11120+
unquotedTail = standingTail;
11121+
consumedEnd = valueEnd;
11122+
continue;
11123+
}
1108711124
if (written !== null) {
11088-
if (isStyle && _deferEmbeddedSource !== undefined) {
11089-
// Declining leaves the attribute as written, delimiter and all — an
11090-
// answer nothing beats is the renderer keeping what it was given.
11091-
const delimiter = open[valueStart - tagStart - 1];
11092-
const asWritten = ` ${attributeName}=${delimiter}${rawValue}${delimiter}`;
11093-
11094-
// The list is deferred, not the shape around it: the tag ending is
11095-
// read back before an answer arrives, so one changing it is declined.
11096-
out += _deferEmbedded(
11097-
// Decoded when the source spelled it with references, since that
11098-
// is the list itself rather than one attribute's spelling.
11099-
spellable !== null ? spellable : rawValue,
11100-
CSS_TYPE,
11101-
(rendered) => {
11102-
if (typeof rendered !== "string") return written.text;
11103-
11104-
const answered = writeStyle(rendered);
11105-
// Declining ends the value quoted: this is the branch the
11106-
// source spelled with a delimiter.
11107-
const tail = answered !== null && answered.unquotedTail;
11108-
11109-
if (tailIsRead && tail !== written.unquotedTail) {
11110-
return written.text;
11111-
}
11112-
11113-
return answered !== null ? answered.text : asWritten;
11114-
},
11115-
BLOCK_CONTENTS
11116-
);
11117-
} else {
11118-
out += written.text;
11119-
}
11125+
out += written.text;
1112011126
unquotedTail = written.unquotedTail;
1112111127
consumedEnd = valueEnd;
1112211128
continue;

‎schemas/WebpackOptions.check.js‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎test/HtmlSyntax.unittest.js‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9308,6 +9308,29 @@ describe("SourceProcessor — attribute rewrites as switches", () => {
93089308
expect(code).toBe("<p style=color:blue>x");
93099309
});
93109310

9311+
it("offers a list already at its shortest", async () => {
9312+
// The built-in makes `margin:0 auto` of it and it cannot go unquoted, so
9313+
// nothing beats the source — which is no reason to ask nobody.
9314+
/** @type {string[]} */
9315+
const offered = [];
9316+
const code = await deferredStyle(
9317+
'<p style="margin:0 auto">x</p>',
9318+
(source) => {
9319+
offered.push(source);
9320+
return "color:blue";
9321+
}
9322+
);
9323+
9324+
expect(offered).toEqual(["margin:0 auto"]);
9325+
expect(code).toBe("<p style=color:blue>x");
9326+
});
9327+
9328+
it("keeps a shortest list no renderer answers for", async () => {
9329+
expect(
9330+
await deferredStyle('<p style="margin:0 auto">x</p>', () => undefined)
9331+
).toBe('<p style="margin:0 auto">x');
9332+
});
9333+
93119334
it("minifies one a deferred renderer declines", async () => {
93129335
expect(
93139336
await deferredStyle('<p style="color: #ff0000 ;">x</p>', () => undefined)

0 commit comments

Comments
 (0)