html-minifier 5.0.1 → 5.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -3
- package/cli.js +2 -0
- package/dist/types/htmlminifier.d.ts.map +1 -1
- package/dist/types/lib/attributes.d.ts +3 -1
- package/dist/types/lib/attributes.d.ts.map +1 -1
- package/dist/types/lib/constants.d.ts.map +1 -1
- package/dist/types/lib/fragments.d.ts +13 -1
- package/dist/types/lib/fragments.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/htmlminifier.js +53 -44
- package/src/lib/attributes.js +31 -8
- package/src/lib/constants.js +3 -3
- package/src/lib/fragments.js +274 -1
package/README.md
CHANGED
|
@@ -600,7 +600,7 @@ The CLI’s `--verbose` and `--dry` modes print the same information to STDERR a
|
|
|
600
600
|
|
|
601
601
|
## Minification comparison
|
|
602
602
|
|
|
603
|
-
Please see [**the Minifier Benchmarks
|
|
603
|
+
Please see [**the Minifier Benchmarks Project**](https://j9t.github.io/minifier-benchmarks/) for details on how HTML Minifier compares to other minifiers. (The benchmarks are currently maintained by the author of HTML Minifier. Contributions, including from other minifier authors, are welcome.)
|
|
604
604
|
|
|
605
605
|
## Examples
|
|
606
606
|
|
|
@@ -717,6 +717,8 @@ HTML reads CRLF and CR line breaks as line feeds, so HM writes them so, too. Mar
|
|
|
717
717
|
|
|
718
718
|
By default, `ignoreCustomFragments` preserves `<?php … ?>`, `<?= … ?>`, `<? … ?>`, and `<% … %>` blocks (as well as XML declarations), so PHP, ERB, JSP, and ASP templates can be minified as part of a build, with the markup, CSS, and JavaScript around those blocks being minified as usual. For includes and other partials, add `partialMarkup`.
|
|
719
719
|
|
|
720
|
+
CSS and JavaScript are only left as written where a template block starts a rule or statement (`<?php if ($a): ?>` between two statements, `<?= $rules ?>` after a rule, or `<?= $code ?>` after `case 1:`, `default:`, or a label), as it may render as anything or as nothing, or where it sits in an `@charset`, `@import`, or `@namespace` statement that would otherwise be dropped with it (`@import <?= $url ?>;`). Template blocks within values (`color: <?= $color ?>`) are safe—here, the code around them is minified, so a block in code that minification removes (such as an unused rule or dead code) goes with that code. This detection is best-effort, as HTML Minifier doesn’t parse template code. To exempt anything it misses, use [`canMinifyCSS`](#css-minification) or [`canMinifyJS`](#javascript-minification).
|
|
721
|
+
|
|
720
722
|
Whitespace next to template blocks is collapsed but kept, as it may matter once the template renders. `trimCustomFragments` removes it where HTML Minifier would remove whitespace anyway, as between block-level elements: `<ul> <?php foreach ($items as $item): ?> <li>` loses it, `Hello <?= $name ?>!` keeps it. Tags keep the spacing of their source, and whitespace next to template blocks in attribute values, CSS, and JavaScript is always kept.
|
|
721
723
|
|
|
722
724
|
Where pages are rendered ahead of serving, as with static exports or full-page caches, you can also minify the rendered HTML instead, which makes this a non-issue.
|
|
@@ -842,7 +844,7 @@ npm i;
|
|
|
842
844
|
npm run backtest
|
|
843
845
|
```
|
|
844
846
|
|
|
845
|
-
The backtest tool tracks minification performance—output size (raw, Gzip, and Brotli) and processing time—across Git history. Results are saved in the backtest folder (results.json).
|
|
847
|
+
The backtest tool tracks minification performance—output size (raw, Gzip, and Brotli) and processing time—across Git history. Results are saved in the backtest folder (results.json). The corpus (backtest/sites.json) is shared with [the Minifier Benchmarks Project](https://github.com/j9t/minifier-benchmarks)—changing sites requires changing them in both repositories.
|
|
846
848
|
|
|
847
849
|
Parameters:
|
|
848
850
|
|
|
@@ -898,4 +900,4 @@ You might like some of my other work:
|
|
|
898
900
|
|
|
899
901
|
* Optimization tools: [hihtml](https://github.com/j9t/hihtml) · HTML Minifier · [ObsoHTML](https://github.com/j9t/obsohtml) · [CSS Dedup](https://github.com/j9t/css-dedup) · [Image Guard](https://github.com/j9t/image-guard) · [Compressor.js Next](https://github.com/j9t/compressorjs-next) · [.htaccess Punk](https://github.com/j9t/htaccess-punk)
|
|
900
902
|
* Defense tools: [IA Defensa](https://iadefensa.com/solutions/)
|
|
901
|
-
* Resources for quality web development: [Articles](https://meiert.com/topics/development/) · [Books](https://meiert.com/topics/books/) (e.g., [_On Web Development_](https://meiert.com/blog/on-web-development-2/)) · [News](https://
|
|
903
|
+
* Resources for quality web development: [Articles](https://meiert.com/topics/development/) · [Books](https://meiert.com/topics/books/) (e.g., [_On Web Development_](https://meiert.com/blog/on-web-development-2/)) · [News](https://dxsrc.org/) · [Terminology](https://webglossary.info/)
|
package/cli.js
CHANGED
|
@@ -1083,6 +1083,8 @@ program.helpOption('-h, --help', 'Display help for command');
|
|
|
1083
1083
|
await reportAndWrite(capturedFiles.join(', '), originals.join(''), outputs.join(''));
|
|
1084
1084
|
process.exit(0);
|
|
1085
1085
|
} else { // Minifying input coming from STDIN
|
|
1086
|
+
if (process.stdin.isTTY && process.argv.length === 2) program.help();
|
|
1087
|
+
|
|
1086
1088
|
content = '';
|
|
1087
1089
|
process.stdin.setEncoding('utf8');
|
|
1088
1090
|
process.stdin.on('data', function (/** @type {string} */ data) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"htmlminifier.d.ts","sourceRoot":"","sources":["../../src/htmlminifier.js"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"htmlminifier.d.ts","sourceRoot":"","sources":["../../src/htmlminifier.js"],"names":[],"mappings":"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"}
|
|
@@ -73,15 +73,17 @@ declare function normalizeAttr(attr: HTMLAttribute, attrs: HTMLAttribute[], tag:
|
|
|
73
73
|
} | undefined;
|
|
74
74
|
/**
|
|
75
75
|
* @param {{name: string, value: string | undefined, attr: HTMLAttribute}} normalized
|
|
76
|
+
* @param {string} tag
|
|
76
77
|
* @param {string | boolean | undefined} hasUnarySlash
|
|
77
78
|
* @param {ProcessedOptions} options
|
|
78
79
|
* @param {boolean} isLast
|
|
79
80
|
* @param {string | undefined} uidAttr
|
|
81
|
+
* @param {string[]} markers - What custom fragment and `htmlmin:ignore` placeholders hold
|
|
80
82
|
*/
|
|
81
83
|
declare function buildAttr(normalized: {
|
|
82
84
|
name: string;
|
|
83
85
|
value: string | undefined;
|
|
84
86
|
attr: HTMLAttribute;
|
|
85
|
-
}, hasUnarySlash: string | boolean | undefined, options: ProcessedOptions, isLast: boolean, uidAttr: string | undefined): string;
|
|
87
|
+
}, tag: string, hasUnarySlash: string | boolean | undefined, options: ProcessedOptions, isLast: boolean, uidAttr: string | undefined, markers: string[]): string;
|
|
86
88
|
export { isIgnoredComment, isExecutableScript, isStyleElement, isMetaWithoutEffect, hasAttrName, normalizeAttr, buildAttr, deduplicateAttributes, replaceContentTypePragma };
|
|
87
89
|
//# sourceMappingURL=attributes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attributes.d.ts","sourceRoot":"","sources":["../../../src/lib/attributes.js"],"names":[],"mappings":"AAAA;;GAEG;AAoCC,OAAQ,KAAA,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAGjD,YAA0I,aAAa,GAA7I;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAE1I;AA8BD;;;GAGG;AACH,iBAAS,gBAAgB,CAAC,IAAI,EAHnB,MAGmB,EAAE,OAAO,EAF5B,gBAE4B,WAOtC;AAuCD;;;;;;;GAOG;AACH,iBAAS,qBAAqB,CAAC,KAAK,EAJzB,aAAa,EAIY,EAAE,aAAa,EAHxC,OAGwC,GAFtC,aAAa,EAAE,CAqB3B;AA4JD;;;GAGG;AACH,iBAAS,kBAAkB,CAAC,GAAG,EAHpB,MAGoB,EAAE,KAAK,EAF3B,aAAa,EAEc,WAUrC;AAOD;;;GAGG;AACH,iBAAS,cAAc,CAAC,GAAG,EAHhB,MAGgB,EAAE,KAAK,EAFvB,aAAa,EAEU,WAUjC;
|
|
1
|
+
{"version":3,"file":"attributes.d.ts","sourceRoot":"","sources":["../../../src/lib/attributes.js"],"names":[],"mappings":"AAAA;;GAEG;AAoCC,OAAQ,KAAA,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAGjD,YAA0I,aAAa,GAA7I;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAE1I;AA8BD;;;GAGG;AACH,iBAAS,gBAAgB,CAAC,IAAI,EAHnB,MAGmB,EAAE,OAAO,EAF5B,gBAE4B,WAOtC;AAuCD;;;;;;;GAOG;AACH,iBAAS,qBAAqB,CAAC,KAAK,EAJzB,aAAa,EAIY,EAAE,aAAa,EAHxC,OAGwC,GAFtC,aAAa,EAAE,CAqB3B;AA4JD;;;GAGG;AACH,iBAAS,kBAAkB,CAAC,GAAG,EAHpB,MAGoB,EAAE,KAAK,EAF3B,aAAa,EAEc,WAUrC;AAOD;;;GAGG;AACH,iBAAS,cAAc,CAAC,GAAG,EAHhB,MAGgB,EAAE,KAAK,EAFvB,aAAa,EAEU,WAUjC;AAkLD;;;;;GAKG;AACH,iBAAS,mBAAmB,CAAC,KAAK,EAHvB,aAAa,EAGU,EAAE,OAAO,EAFhC,MAAM,EAE0B,WAkB1C;AA0BD;;;;;GAKG;AACH,iBAAS,wBAAwB,CAAC,KAAK,EAH5B,aAAa,EAGe,EAAE,OAAO,EAFrC,MAAM,EAE+B,QAe/C;AAmDD;;;GAGG;AACH,iBAAS,WAAW,CAAC,IAAI,EAHd,MAGc,EAAE,KAAK,EAFrB,aAAa,EAEQ,WAO/B;AAmUD;;;;;;;;GAQG;AACH,iBAAS,aAAa,CAAC,IAAI,EARhB,aAQgB,EAAE,KAAK,EAPvB,aAAa,EAOU,EAAE,GAAG,EAN5B,MAM4B,EAAE,MAAM,EALpC,MAKoC,EAAE,OAAO,EAJ7C,gBAI6C,EAAE,UAAU,UAAA,EAAE,OAAO,AAF1E,CACF,EADU,MAAM,EAE4D;;;;;;;;cAkB5E;AAsED;;;;;;;;GAQG;AACH,iBAAS,SAAS,CAAC,UAAU,EARlB;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,IAAI,EAAE,aAAa,CAAA;CAQ3C,EAAE,GAAG,EAPvB,MAOuB,EAAE,aAAa,EANtC,MAAM,GAAG,OAAO,GAAG,SAMmB,EAAE,OAAO,EAL/C,gBAK+C,EAAE,MAAM,EAJvD,OAIuD,EAAE,OAAO,EAHhE,MAAM,GAAG,SAGuD,EAAE,OAAO,EAFzE,MAAM,EAEmE,UA0HnF;AAED,OAAO,EAEL,gBAAgB,EAChB,kBAAkB,EAClB,cAAc,EACd,mBAAmB,EACnB,WAAW,EAGX,aAAa,EACb,SAAS,EACT,qBAAqB,EACrB,wBAAwB,EACzB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/lib/constants.js"],"names":[],"mappings":"AAAA;;GAEG;AAEH,QAAA,MAAM,WAAW,QAAkB,CAAC;AACpC,QAAA,MAAM,SAAS,QAAkB,CAAC;AAClC,QAAA,MAAM,UAAU,QAAmB,CAAC;AACpC,QAAA,MAAM,cAAc,QAAqB,CAAC;AAC1C,QAAA,MAAM,cAAc,QAAsB,CAAC;AAC3C,QAAA,MAAM,qBAAqB,QAAuB,CAAC;AACnD,QAAA,MAAM,kBAAkB,QAAqB,CAAC;AAC9C,QAAA,MAAM,sBAAsB,QAAqB,CAAC;AAClD,QAAA,MAAM,sBAAsB,QAAc,CAAC;AAC3C,QAAA,MAAM,qBAAqB,QAAkB,CAAC;AAC9C,QAAA,MAAM,yBAAyB,QAA0B,CAAC;AAC1D,QAAA,MAAM,qBAAqB,QAAO,CAAC;AAEnC,QAAA,MAAM,KAAK,QAAQ,CAAC;AACpB,QAAA,MAAM,gBAAgB,QAAW,CAAC;AAIlC,QAAA,MAAM,kBAAkB,QAAiG,CAAC;AAG1H,QAAA,MAAM,qBAAqB,QAA8G,CAAC;AAC1I,QAAA,MAAM,YAAY,QAAO,CAAC;AAG1B,QAAA,MAAM,eAAe,QAA4D,CAAC;AAGlF,QAAA,MAAM,kBAAkB,QAAgB,CAAC;AACzC,QAAA,MAAM,kBAAkB,QAAgB,CAAC;AAKzC,QAAA,MAAM,qBAAqB,EAAc,MAAM,CAAC,MAAM,EAAE,MAAM,CAG3D,CAAC;AAGJ,QAAA,MAAM,gBAAgB,QAA4C,CAAC;AAKnE,QAAA,MAAM,UAAU,QAA+K,CAAC;AAChM,QAAA,MAAM,gBAAgB,QAAgB,CAAC;AACvC,QAAA,MAAM,mBAAmB,QAAkB,CAAC;AAC5C,QAAA,MAAM,UAAU,QAAO,CAAC;AACxB,QAAA,MAAM,gBAAgB,QAAkB,CAAC;AACzC,QAAA,MAAM,kBAAkB,QAE6B,CAAC;AAKtD,QAAA,MAAM,oCAAoC,
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/lib/constants.js"],"names":[],"mappings":"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"}
|
|
@@ -43,5 +43,17 @@ declare function toFragment(pattern: RegExp): DelimitedFragment | PatternFragmen
|
|
|
43
43
|
* @returns {string}
|
|
44
44
|
*/
|
|
45
45
|
declare function replaceCustomFragments(value: string, fragments: (DelimitedFragment | PatternFragment)[], replacer: (match: string) => string): string;
|
|
46
|
-
|
|
46
|
+
/**
|
|
47
|
+
* Whether minified CSS or JavaScript can stand in for its source. A fragment starting a
|
|
48
|
+
* statement or rule can render as anything, or as nothing, while engines read it as an
|
|
49
|
+
* identifier or selector and join it with the code around it, or drop it; a fragment in
|
|
50
|
+
* an at-rule Lightning CSS cannot read would go with that at-rule
|
|
51
|
+
* @param {string} source
|
|
52
|
+
* @param {unknown} output - Anything but a string, from a minifier of one’s own, passes
|
|
53
|
+
* @param {RegExp} placeholder - Global pattern matching one fragment placeholder
|
|
54
|
+
* @param {boolean} [isJS] - Whether the code is JavaScript rather than CSS
|
|
55
|
+
* @returns {boolean}
|
|
56
|
+
*/
|
|
57
|
+
declare function isMinifiedCodeSafe(source: string, output: unknown, placeholder: RegExp, isJS?: boolean): boolean;
|
|
58
|
+
export { toDelimitedFragment, toFragment, replaceCustomFragments, isMinifiedCodeSafe };
|
|
47
59
|
//# sourceMappingURL=fragments.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fragments.d.ts","sourceRoot":"","sources":["../../../src/lib/fragments.js"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;
|
|
1
|
+
{"version":3,"file":"fragments.d.ts","sourceRoot":"","sources":["../../../src/lib/fragments.js"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AA0BA,YAA4F,iBAAiB,GAAnG;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CAAC,CAI1F;AAAA,YAAoE,eAAe,GAAzE;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CAAC,CAGpE;AAmCD;;;;;GAKG;AACH,iBAAS,mBAAmB,CAAC,OAAO,EAJzB,MAIyB,GAHvB,iBAAiB,GAAG,IAAI,CAwBpC;AA8CD;;;;GAIG;AACH,iBAAS,UAAU,CAAC,OAAO,EAHhB,MAGgB,GAFd,iBAAiB,GAAG,eAAe,CAa/C;AAED;;;;;;;GAOG;AACH,iBAAS,sBAAsB,CAAC,KAAK,EAN1B,MAM0B,EAAE,SAAS,EALrC,CAAC,iBAAiB,GAAG,eAAe,CAAC,EAKA,EAAE,QAAQ,EAH/C,CAAC,KAAK,EAAE,MAAM,KAAK,MAG4B,GAF7C,MAAM,CA2KlB;AA2OD;;;;;;;;;;GAUG;AACH,iBAAS,kBAAkB,CAAC,MAAM,EANvB,MAMuB,EAAE,MAAM,EAL/B,OAK+B,EAAE,WAAW,EAJ5C,MAI4C,EAAE,IAAI,AAH1D,CACA,EADQ,OAG0D,GAFxD,OAAO,CAenB;AAED,OAAO,EACL,mBAAmB,EACnB,UAAU,EACV,sBAAsB,EACtB,kBAAkB,EACnB,CAAC"}
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
},
|
|
7
7
|
"bugs": "https://github.com/j9t/html-minifier/issues",
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"commander": "^15.
|
|
9
|
+
"commander": "^15.1.0",
|
|
10
10
|
"entities": "^9.0.0",
|
|
11
11
|
"lightningcss": "^1.33.0",
|
|
12
12
|
"svgo": "^4.1.0",
|
|
@@ -15,12 +15,12 @@
|
|
|
15
15
|
"description": "Highly effective, super-configurable, well-tested web page minifier",
|
|
16
16
|
"devDependencies": {
|
|
17
17
|
"@eslint/js": "^10.0.1",
|
|
18
|
-
"@swc/core": "^1.16.
|
|
18
|
+
"@swc/core": "^1.16.22",
|
|
19
19
|
"@types/node": "^26.6.6",
|
|
20
20
|
"eslint": "^10.14.0",
|
|
21
21
|
"globals": "^17.14.0",
|
|
22
22
|
"typescript": "^7.0.2",
|
|
23
|
-
"vite": "^8.3.
|
|
23
|
+
"vite": "^8.3.6"
|
|
24
24
|
},
|
|
25
25
|
"engines": {
|
|
26
26
|
"node": ">=22.13"
|
|
@@ -93,5 +93,5 @@
|
|
|
93
93
|
},
|
|
94
94
|
"type": "module",
|
|
95
95
|
"types": "dist/types/htmlminifier.d.ts",
|
|
96
|
-
"version": "5.0.
|
|
96
|
+
"version": "5.0.2"
|
|
97
97
|
}
|
package/src/htmlminifier.js
CHANGED
|
@@ -78,7 +78,7 @@ import {
|
|
|
78
78
|
} from './lib/content.js';
|
|
79
79
|
|
|
80
80
|
import { processOptions } from './lib/options.js';
|
|
81
|
-
import { toFragment, replaceCustomFragments } from './lib/fragments.js';
|
|
81
|
+
import { toFragment, replaceCustomFragments, isMinifiedCodeSafe } from './lib/fragments.js';
|
|
82
82
|
|
|
83
83
|
/** @import { ProcessedOptions } from './lib/options.js' */
|
|
84
84
|
|
|
@@ -1263,31 +1263,32 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
1263
1263
|
uidAttrLeadingPattern = new RegExp('^\\s*' + uidAttr + '(\\d+)' + uidAttr);
|
|
1264
1264
|
uidAttrExactPattern = new RegExp('^' + uidAttr + '(\\d+)' + uidAttr + '$');
|
|
1265
1265
|
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1266
|
+
const uidPlaceholderPattern = new RegExp(uidAttr + '\\d+' + uidAttr, 'g');
|
|
1267
|
+
|
|
1268
|
+
/**
|
|
1269
|
+
* @param {(text: string, ...args: any[]) => any} fn
|
|
1270
|
+
* @param {boolean} isJS
|
|
1271
|
+
* @returns {any}
|
|
1272
|
+
*/
|
|
1273
|
+
const wrapCodeMinifier = (fn, isJS) => (/** @type {string} */ text, /** @type {any[]} */ ...args) => {
|
|
1274
|
+
if (!text.includes(/** @type {string} */ (uidAttr))) return fn(text, ...args);
|
|
1275
|
+
|
|
1276
|
+
const source = text.replace(/** @type {RegExp} */ (uidPattern), function (/** @type {string} */ _match, /** @type {string} */ _prefix, /** @type {string} */ index) {
|
|
1277
|
+
const chunks = ignoredCustomMarkupChunks[+index];
|
|
1278
|
+
customMarkupInCode.add(+index);
|
|
1279
|
+
return (chunks?.[1] ?? '') + uidAttr + index + uidAttr + (chunks?.[2] ?? '');
|
|
1280
|
+
});
|
|
1281
|
+
const result = fn(source, ...args);
|
|
1282
|
+
const finish = (/** @type {string} */ output) => {
|
|
1283
|
+
if (isMinifiedCodeSafe(source, output, uidPlaceholderPattern, isJS)) return output;
|
|
1284
|
+
options.log('Keeping CSS or JavaScript as written, as minifying could break or lose a custom fragment');
|
|
1285
|
+
return source;
|
|
1286
|
+
};
|
|
1287
|
+
return isThenable(result) ? Promise.resolve(result).then(finish) : finish(result);
|
|
1288
|
+
};
|
|
1289
|
+
|
|
1290
|
+
if (options.minifyCSS !== identity) options.minifyCSS = wrapCodeMinifier(options.minifyCSS, false);
|
|
1291
|
+
if (options.minifyJS !== identity) options.minifyJS = wrapCodeMinifier(options.minifyJS, true);
|
|
1291
1292
|
}
|
|
1292
1293
|
|
|
1293
1294
|
const token = uidAttr + ignoredCustomMarkupChunks.length + uidAttr;
|
|
@@ -1620,11 +1621,14 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
1620
1621
|
// Nothing to the left of the text is in play here, so only its trailing run can
|
|
1621
1622
|
// change—unless preserved line breaks bring the leading run into play, too
|
|
1622
1623
|
const trailingOnly = !options.preserveLineBreaks;
|
|
1623
|
-
|
|
1624
|
+
let prevTag = '';
|
|
1625
|
+
let prevTagLower = '';
|
|
1626
|
+
for (; index > noTrimEndIndex && canTrimWhitespace(prevTagLower, prevTag, emptyAttrs); index--) {
|
|
1624
1627
|
const str = buffer[index] ?? '';
|
|
1625
1628
|
const endTagName = matchPlainEndTag(str);
|
|
1626
1629
|
if (endTagName !== null) {
|
|
1627
1630
|
prevTag = endTagName;
|
|
1631
|
+
prevTagLower = prevTag.toLowerCase();
|
|
1628
1632
|
continue;
|
|
1629
1633
|
}
|
|
1630
1634
|
// A tag ends the search, and so does text that survives collapsing. Text with no
|
|
@@ -2146,8 +2150,9 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
2146
2150
|
* @param {string | boolean | undefined} hasUnarySlash
|
|
2147
2151
|
* @param {boolean | undefined} optional
|
|
2148
2152
|
* @param {ProcessedOptions | null} restoreOptions - Context a unary tag pushed, or null
|
|
2153
|
+
* @param {ProcessedOptions} optionsTag - Context the element’s own attributes are in
|
|
2149
2154
|
*/
|
|
2150
|
-
function emitStartTag(normalizedAttrs, tag, unary, autoGenerated, fragmentJoinsTag, hasUnarySlash, optional, restoreOptions) {
|
|
2155
|
+
function emitStartTag(normalizedAttrs, tag, unary, autoGenerated, fragmentJoinsTag, hasUnarySlash, optional, restoreOptions, optionsTag) {
|
|
2151
2156
|
// Find the last kept attribute, then emit in order, with no intermediate array
|
|
2152
2157
|
let lastKeptIndex = -1;
|
|
2153
2158
|
for (let i = normalizedAttrs.length - 1; i >= 0; i--) {
|
|
@@ -2169,7 +2174,7 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
2169
2174
|
if (uidAttr && normalizedAttr.name.includes(uidAttr)) {
|
|
2170
2175
|
markTagFragments(normalizedAttr.name);
|
|
2171
2176
|
}
|
|
2172
|
-
tagText += buildAttr(normalizedAttr, hasUnarySlash,
|
|
2177
|
+
tagText += buildAttr(normalizedAttr, tag, hasUnarySlash, optionsTag, i === lastKeptIndex, uidAttr, markers);
|
|
2173
2178
|
}
|
|
2174
2179
|
}
|
|
2175
2180
|
} else {
|
|
@@ -2182,7 +2187,7 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
2182
2187
|
if (uidAttr && normalizedAttr.name.includes(uidAttr)) {
|
|
2183
2188
|
markTagFragments(normalizedAttr.name);
|
|
2184
2189
|
}
|
|
2185
|
-
const builtAttr = buildAttr(normalizedAttr, hasUnarySlash,
|
|
2190
|
+
const builtAttr = buildAttr(normalizedAttr, tag, hasUnarySlash, optionsTag, i === lastKeptIndex, uidAttr, markers);
|
|
2186
2191
|
// One entry with the tag name, so that no line break can come between them
|
|
2187
2192
|
if (i === 0 && fragmentJoinsTag) {
|
|
2188
2193
|
buffer[buffer.length - 1] += builtAttr;
|
|
@@ -2338,7 +2343,7 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
2338
2343
|
}
|
|
2339
2344
|
currentTag = tag;
|
|
2340
2345
|
charsPrevTag = tag;
|
|
2341
|
-
if (!inlineTextSet.has(tag)) {
|
|
2346
|
+
if (!inlineTextSet.has(lowerTag || tag)) {
|
|
2342
2347
|
currentChars = '';
|
|
2343
2348
|
}
|
|
2344
2349
|
hasChars = false;
|
|
@@ -2376,17 +2381,18 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
2376
2381
|
// Set whitespace flags for nested tags (e.g., `<code>` within a `<pre>`); verbatim
|
|
2377
2382
|
// whitespace is tracked without `collapseWhitespace` too, as `removeWhitespaceLine` spares it
|
|
2378
2383
|
if (options.collapseWhitespace && !stackNoTrimWhitespace.length) {
|
|
2379
|
-
squashTrailingWhitespace(tag);
|
|
2384
|
+
squashTrailingWhitespace(lowerTag || tag);
|
|
2380
2385
|
}
|
|
2381
|
-
if (options.collapseWhitespace && !unary && inlineElementsTransparent.has(tag)) {
|
|
2386
|
+
if (options.collapseWhitespace && !unary && inlineElementsTransparent.has(lowerTag || tag)) {
|
|
2382
2387
|
transparentDepth++;
|
|
2383
2388
|
}
|
|
2384
2389
|
if (!unary) {
|
|
2385
|
-
|
|
2390
|
+
const tagLower = lowerTag || tag;
|
|
2391
|
+
if (!canTrimWhitespace(tagLower, tagOut, attrs) || stackNoTrimWhitespace.length) {
|
|
2386
2392
|
stackNoTrimWhitespace.push(tag);
|
|
2387
|
-
if (
|
|
2393
|
+
if (tagLower === 'pre' || tagLower === 'textarea') preTextareaDepth++;
|
|
2388
2394
|
}
|
|
2389
|
-
if (options.collapseWhitespace && (!canCollapseWhitespace(
|
|
2395
|
+
if (options.collapseWhitespace && (!canCollapseWhitespace(tagLower, tagOut, attrs) || stackNoCollapseWhitespace.length)) {
|
|
2390
2396
|
stackNoCollapseWhitespace.push(tag);
|
|
2391
2397
|
}
|
|
2392
2398
|
}
|
|
@@ -2403,7 +2409,9 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
2403
2409
|
// SVGO reads the whole SVG block as XML, where an element closes itself or not, so
|
|
2404
2410
|
// every unary element in there is written with a slash
|
|
2405
2411
|
const needsXMLSlash = unary && Boolean(options.insideSVG) && Boolean(options.minifySVG);
|
|
2406
|
-
|
|
2412
|
+
// `foreignObject` and `annotation-xml` hold HTML, but are foreign elements themselves
|
|
2413
|
+
const optionsTag = useNameParentForTag ? optionsParent : options;
|
|
2414
|
+
const hasUnarySlash = needsXMLSlash || (unarySlash && optionsTag.keepClosingSlash);
|
|
2407
2415
|
|
|
2408
2416
|
bufferPush(openTag, true);
|
|
2409
2417
|
|
|
@@ -2450,10 +2458,10 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
2450
2458
|
const restoreOptions = unary && pushedContext ? optionsParent : null;
|
|
2451
2459
|
if (anyThenable) {
|
|
2452
2460
|
return Promise.all(attrResults).then(resolved => {
|
|
2453
|
-
emitStartTag(resolved, tag, unary, autoGenerated, fragmentJoinsTag, hasUnarySlash, optional, restoreOptions);
|
|
2461
|
+
emitStartTag(resolved, tag, unary, autoGenerated, fragmentJoinsTag, hasUnarySlash, optional, restoreOptions, optionsTag);
|
|
2454
2462
|
});
|
|
2455
2463
|
}
|
|
2456
|
-
emitStartTag(/** @type {Array<{name: string, value: string | undefined, attr: HTMLAttribute} | undefined>} */ (attrResults), tag, unary, autoGenerated, fragmentJoinsTag, hasUnarySlash, optional, restoreOptions);
|
|
2464
|
+
emitStartTag(/** @type {Array<{name: string, value: string | undefined, attr: HTMLAttribute} | undefined>} */ (attrResults), tag, unary, autoGenerated, fragmentJoinsTag, hasUnarySlash, optional, restoreOptions, optionsTag);
|
|
2457
2465
|
return undefined;
|
|
2458
2466
|
},
|
|
2459
2467
|
end: function (/** @type {string} */ tag, /** @type {HTMLAttribute[]} */ attrs, /** @type {boolean} */ autoGenerated, /** @type {string | undefined} */ rest, /** @type {boolean | undefined} */ holdsTable) {
|
|
@@ -2506,14 +2514,15 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
2506
2514
|
let closesNoTrim = false;
|
|
2507
2515
|
if (stackNoTrimWhitespace.length) {
|
|
2508
2516
|
if (tag === stackNoTrimWhitespace[stackNoTrimWhitespace.length - 1]) {
|
|
2509
|
-
|
|
2517
|
+
const tagLower = lowerTag || tag;
|
|
2518
|
+
if (tagLower === 'pre' || tagLower === 'textarea') preTextareaDepth--;
|
|
2510
2519
|
stackNoTrimWhitespace.pop();
|
|
2511
2520
|
closesNoTrim = !stackNoTrimWhitespace.length;
|
|
2512
2521
|
}
|
|
2513
2522
|
} else if (options.collapseWhitespace) {
|
|
2514
|
-
squashTrailingWhitespace('/' + tag);
|
|
2523
|
+
squashTrailingWhitespace('/' + (lowerTag || tag));
|
|
2515
2524
|
}
|
|
2516
|
-
if (transparentDepth && inlineElementsTransparent.has(tag)) {
|
|
2525
|
+
if (transparentDepth && inlineElementsTransparent.has(lowerTag || tag)) {
|
|
2517
2526
|
transparentDepth--;
|
|
2518
2527
|
}
|
|
2519
2528
|
let closesNoCollapse = false;
|
|
@@ -2584,7 +2593,7 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
2584
2593
|
bufferPush(endTagText, true);
|
|
2585
2594
|
}
|
|
2586
2595
|
charsPrevTag = '/' + tag;
|
|
2587
|
-
if (!inlineElements.has(tag)) {
|
|
2596
|
+
if (!inlineElements.has(lowerTag || tag)) {
|
|
2588
2597
|
currentChars = '';
|
|
2589
2598
|
} else if (isElementEmpty) {
|
|
2590
2599
|
currentChars += '|';
|
|
@@ -2597,7 +2606,7 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
2597
2606
|
bufferPush(endTagText, true);
|
|
2598
2607
|
}
|
|
2599
2608
|
charsPrevTag = '/' + tag;
|
|
2600
|
-
if (!inlineElements.has(tag)) {
|
|
2609
|
+
if (!inlineElements.has(lowerTag || tag)) {
|
|
2601
2610
|
currentChars = '';
|
|
2602
2611
|
} else if (isElementEmpty) {
|
|
2603
2612
|
currentChars += '|';
|
package/src/lib/attributes.js
CHANGED
|
@@ -342,21 +342,42 @@ function isStyleElement(tag, attrs) {
|
|
|
342
342
|
}
|
|
343
343
|
|
|
344
344
|
/**
|
|
345
|
-
* Whether an attribute collapses to its name;
|
|
346
|
-
*
|
|
345
|
+
* Whether an attribute collapses to its name; lower-cases the value only for the few names
|
|
346
|
+
* that depend on it
|
|
347
347
|
*
|
|
348
|
-
* @param {string}
|
|
348
|
+
* @param {string} name - In lowercase
|
|
349
349
|
* @param {string} attrValue
|
|
350
|
+
* @param {string} tag
|
|
351
|
+
* @param {string[]} markers - What custom fragment and `htmlmin:ignore` placeholders hold
|
|
350
352
|
*/
|
|
351
|
-
function collapsesToBooleanName(
|
|
352
|
-
const
|
|
353
|
-
if (
|
|
353
|
+
function collapsesToBooleanName(name, attrValue, tag, markers) {
|
|
354
|
+
const simple = isSimpleBoolean.has(name);
|
|
355
|
+
if (!simple && name !== 'hidden' && name !== 'draggable' && !collapsibleValues.has(name)) {
|
|
356
|
+
return false;
|
|
357
|
+
}
|
|
358
|
+
// Custom elements define what their attributes mean, and `marquee` counts its loops
|
|
359
|
+
if (tag.includes('-') || (name === 'loop' && tag.toLowerCase() === 'marquee')) {
|
|
360
|
+
return false;
|
|
361
|
+
}
|
|
362
|
+
// Template code and ignored markup are not the minifier’s to remove
|
|
363
|
+
if (markers.some(marker => attrValue.indexOf(marker) !== -1)) {
|
|
364
|
+
return false;
|
|
365
|
+
}
|
|
366
|
+
if (simple) {
|
|
354
367
|
return true;
|
|
355
368
|
}
|
|
356
369
|
const values = collapsibleValues.get(name);
|
|
357
370
|
if (values) {
|
|
358
371
|
return values.has(attrValue.toLowerCase());
|
|
359
372
|
}
|
|
373
|
+
// What a reference decodes to, the value as written doesn’t show
|
|
374
|
+
if ((name === 'hidden' || name === 'draggable') && attrValue.indexOf('&') !== -1) {
|
|
375
|
+
return false;
|
|
376
|
+
}
|
|
377
|
+
// Any other value means the hidden state, which the bare attribute does, too
|
|
378
|
+
if (name === 'hidden') {
|
|
379
|
+
return attrValue.toLowerCase() !== 'until-found';
|
|
380
|
+
}
|
|
360
381
|
return name === 'draggable' && !isBooleanValue.has(attrValue.toLowerCase());
|
|
361
382
|
}
|
|
362
383
|
|
|
@@ -1051,12 +1072,14 @@ function normalizeAttrFinish(attrName, attrNameOut, attrValue, attr, tag, tagOut
|
|
|
1051
1072
|
|
|
1052
1073
|
/**
|
|
1053
1074
|
* @param {{name: string, value: string | undefined, attr: HTMLAttribute}} normalized
|
|
1075
|
+
* @param {string} tag
|
|
1054
1076
|
* @param {string | boolean | undefined} hasUnarySlash
|
|
1055
1077
|
* @param {ProcessedOptions} options
|
|
1056
1078
|
* @param {boolean} isLast
|
|
1057
1079
|
* @param {string | undefined} uidAttr
|
|
1080
|
+
* @param {string[]} markers - What custom fragment and `htmlmin:ignore` placeholders hold
|
|
1058
1081
|
*/
|
|
1059
|
-
function buildAttr(normalized, hasUnarySlash, options, isLast, uidAttr) {
|
|
1082
|
+
function buildAttr(normalized, tag, hasUnarySlash, options, isLast, uidAttr, markers) {
|
|
1060
1083
|
const attrName = normalized.name;
|
|
1061
1084
|
let attrValue = normalized.value;
|
|
1062
1085
|
const attr = normalized.attr;
|
|
@@ -1070,7 +1093,7 @@ function buildAttr(normalized, hasUnarySlash, options, isLast, uidAttr) {
|
|
|
1070
1093
|
|
|
1071
1094
|
// An attribute written as its name alone skips the quoting work below
|
|
1072
1095
|
if (typeof attrValue === 'undefined' ||
|
|
1073
|
-
(options.collapseBooleanAttributes && collapsesToBooleanName(attrName, attrValue ?? '')) ||
|
|
1096
|
+
(options.collapseBooleanAttributes && !options.insideForeignContent && collapsesToBooleanName(options.namesAsWritten ? attrName.toLowerCase() : attrName, attrValue ?? '', tag, markers)) ||
|
|
1074
1097
|
(options.collapseEmptyAttributes && attrValue === '' && (attr.customAssign ?? '=') === '=')) {
|
|
1075
1098
|
return attr.customOpen + attrName + (isLast ? '' : ' ') + attr.customClose;
|
|
1076
1099
|
}
|
package/src/lib/constants.js
CHANGED
|
@@ -59,10 +59,10 @@ const RE_EMPTY_ATTRIBUTE = new RegExp(
|
|
|
59
59
|
// Inline element sets for whitespace handling
|
|
60
60
|
|
|
61
61
|
// Non-empty elements that will maintain whitespace around them
|
|
62
|
-
const inlineElementsToKeepWhitespaceAround = new Set(['a', 'abbr', 'acronym', 'audio', 'b', 'bdi', 'bdo', 'big', 'button', 'canvas', 'cite', 'code', 'data', 'del', 'dfn', 'em', 'embed', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'mark', 'math', 'meter', 'nobr', 'object', 'output', 'picture', 'progress', 'q', 'rb', 'rp', 'rt', 'rtc', 'ruby', 's', 'samp', 'select', 'selectedcontent', 'slot', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'svg', 'textarea', 'time', 'tt', 'u', 'var', 'video', 'wbr']);
|
|
62
|
+
const inlineElementsToKeepWhitespaceAround = new Set(['a', 'abbr', 'acronym', 'audio', 'b', 'bdi', 'bdo', 'big', 'button', 'canvas', 'cite', 'code', 'data', 'del', 'dfn', 'em', 'embed', 'font', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'mark', 'math', 'meter', 'nobr', 'object', 'output', 'picture', 'progress', 'q', 'rb', 'rp', 'rt', 'rtc', 'ruby', 's', 'samp', 'select', 'selectedcontent', 'slot', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'svg', 'textarea', 'textpath', 'time', 'tspan', 'tt', 'u', 'var', 'video', 'wbr']);
|
|
63
63
|
|
|
64
64
|
// Non-empty elements that will maintain whitespace within them
|
|
65
|
-
const inlineElementsToKeepWhitespaceWithin = new Set(['a', 'abbr', 'acronym', 'b', 'big', 'data', 'del', 'em', 'font', 'i', 'ins', 'kbd', 'map', 'mark', 'nobr', 's', 'samp', 'slot', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'time', 'tt', 'u', 'var']);
|
|
65
|
+
const inlineElementsToKeepWhitespaceWithin = new Set(['a', 'abbr', 'acronym', 'b', 'big', 'data', 'del', 'em', 'font', 'i', 'ins', 'kbd', 'map', 'mark', 'nobr', 's', 'samp', 'slot', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'textpath', 'time', 'tspan', 'tt', 'u', 'var']);
|
|
66
66
|
|
|
67
67
|
// Text-level elements that keep whitespace between them and other elements under
|
|
68
68
|
// `collapseInlineTagWhitespace`
|
|
@@ -259,7 +259,7 @@ const keepScriptsMimetypes = new Set([
|
|
|
259
259
|
|
|
260
260
|
// Boolean attribute sets
|
|
261
261
|
|
|
262
|
-
const isSimpleBoolean = new Set(['allowfullscreen', 'async', 'autofocus', 'autoplay', 'checked', 'compact', 'controls', 'declare', 'default', '
|
|
262
|
+
const isSimpleBoolean = new Set(['allowfullscreen', 'alpha', 'async', 'autofocus', 'autoplay', 'checked', 'compact', 'controls', 'declare', 'default', 'defer', 'disabled', 'formnovalidate', 'headingreset', 'inert', 'ismap', 'itemscope', 'loop', 'multiple', 'muted', 'nohref', 'nomodule', 'noresize', 'noshade', 'novalidate', 'nowrap', 'open', 'playsinline', 'readonly', 'required', 'reversed', 'scoped', 'seamless', 'selected', 'shadowrootclonable', 'shadowrootcustomelementregistry', 'shadowrootdelegatesfocus', 'shadowrootserializable', 'sortable', 'truespeed', 'typemustmatch']);
|
|
263
263
|
|
|
264
264
|
const isBooleanValue = new Set(['true', 'false']);
|
|
265
265
|
|
package/src/lib/fragments.js
CHANGED
|
@@ -11,6 +11,19 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
const RE_WHITESPACE = /\s/;
|
|
14
|
+
const RE_NAME_CHAR = /[\w$-]/;
|
|
15
|
+
|
|
16
|
+
// Run on at most the eight characters ending in the word
|
|
17
|
+
const RE_BLOCK_KEYWORD = /(?:^|[^\w$.])(?:do|else|finally|try)$/;
|
|
18
|
+
|
|
19
|
+
// The last character before a `/` that starts a regular expression, not a division
|
|
20
|
+
const RE_BEFORE_REGEX = /[(,=:[!&|?{};+*%<>~^}-]/;
|
|
21
|
+
|
|
22
|
+
// Run on at most the eleven characters ending in the word
|
|
23
|
+
const RE_BEFORE_REGEX_KEYWORD = /(?:^|[^\w$.])(?:await|case|delete|do|else|in|instanceof|new|of|return|throw|typeof|void|yield)$/;
|
|
24
|
+
|
|
25
|
+
// Run on at most the eleven characters from the `@`
|
|
26
|
+
const RE_DROPPABLE_AT_RULE = /^@(?:charset|import|namespace)(?![\w-])/i;
|
|
14
27
|
|
|
15
28
|
// Any-character and negated-class bodies; without the `s` flag, `.` is itself a
|
|
16
29
|
// negated class, excluding line terminators
|
|
@@ -333,8 +346,268 @@ function replaceCustomFragments(value, fragments, replacer) {
|
|
|
333
346
|
return copied === 0 ? value : out + value.slice(copied);
|
|
334
347
|
}
|
|
335
348
|
|
|
349
|
+
/**
|
|
350
|
+
* Index past the regular expression starting at the `/` at an index
|
|
351
|
+
* @param {string} source
|
|
352
|
+
* @param {number} index
|
|
353
|
+
* @returns {number} The index itself when the line ends before the expression does
|
|
354
|
+
*/
|
|
355
|
+
function skipRegex(source, index) {
|
|
356
|
+
let inClass = false;
|
|
357
|
+
for (let position = index + 1; position < source.length; position++) {
|
|
358
|
+
const current = source[position];
|
|
359
|
+
if (current === '\n' || current === '\r') return index;
|
|
360
|
+
if (current === '\\') position++;
|
|
361
|
+
else if (current === '[') inClass = true;
|
|
362
|
+
else if (current === ']') inClass = false;
|
|
363
|
+
else if (current === '/' && !inClass) return position + 1;
|
|
364
|
+
}
|
|
365
|
+
return index;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Index past the comment, string, or regular expression starting at an index
|
|
370
|
+
* @param {string} source
|
|
371
|
+
* @param {number} index
|
|
372
|
+
* @param {boolean} isJS
|
|
373
|
+
* @returns {number} The index itself when none starts there
|
|
374
|
+
*/
|
|
375
|
+
function skipCommentOrString(source, index, isJS) {
|
|
376
|
+
const char = source[index];
|
|
377
|
+
const next = source[index + 1];
|
|
378
|
+
|
|
379
|
+
if (char === '/' && next === '*') {
|
|
380
|
+
const end = source.indexOf('*/', index + 2);
|
|
381
|
+
return end === -1 ? source.length : end + 2;
|
|
382
|
+
}
|
|
383
|
+
if (isJS && char === '/' && next === '/') {
|
|
384
|
+
const end = source.indexOf('\n', index + 2);
|
|
385
|
+
return end === -1 ? source.length : end;
|
|
386
|
+
}
|
|
387
|
+
if (isJS && char === '/') return isRegexStart(source, index) ? skipRegex(source, index) : index;
|
|
388
|
+
if (char !== '"' && char !== '\'' && !(isJS && char === '`')) return index;
|
|
389
|
+
|
|
390
|
+
for (let position = index + 1; position < source.length; position++) {
|
|
391
|
+
const current = source[position];
|
|
392
|
+
if (current === '\\') position++;
|
|
393
|
+
else if (current === char) return position + 1;
|
|
394
|
+
else if (current === '\n' && char !== '`') return position;
|
|
395
|
+
}
|
|
396
|
+
return source.length;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Index of the last non-whitespace character before an index
|
|
401
|
+
* @param {string} source
|
|
402
|
+
* @param {number} index
|
|
403
|
+
* @returns {number} -1 when there is none
|
|
404
|
+
*/
|
|
405
|
+
function findPreviousToken(source, index) {
|
|
406
|
+
let position = index - 1;
|
|
407
|
+
while (position >= 0 && RE_WHITESPACE.test(source[position] ?? '')) position--;
|
|
408
|
+
return position;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* Whether a `/` starts a regular expression rather than a division, going by what precedes
|
|
413
|
+
* it; after a `)`, which `if (a) /b/.test(c)` leaves open, it’s read as a division
|
|
414
|
+
* @param {string} source
|
|
415
|
+
* @param {number} slash
|
|
416
|
+
* @returns {boolean}
|
|
417
|
+
*/
|
|
418
|
+
function isRegexStart(source, slash) {
|
|
419
|
+
const before = findPreviousToken(source, slash);
|
|
420
|
+
if (before === -1) return true;
|
|
421
|
+
|
|
422
|
+
const char = source[before] ?? '';
|
|
423
|
+
// `++` and `--` can only end an operand here, as a literal cannot be incremented
|
|
424
|
+
if ((char === '+' || char === '-') && source[before - 1] === char) return false;
|
|
425
|
+
return RE_BEFORE_REGEX.test(char) || RE_BEFORE_REGEX_KEYWORD.test(source.slice(Math.max(before - 10, 0), before + 1));
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* Whether a block keyword ends at an index
|
|
430
|
+
* @param {string} source
|
|
431
|
+
* @param {number} index
|
|
432
|
+
* @returns {boolean}
|
|
433
|
+
*/
|
|
434
|
+
function isBlockKeywordEnd(source, index) {
|
|
435
|
+
return RE_BLOCK_KEYWORD.test(source.slice(Math.max(index - 7, 0), index + 1));
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* Whether a `{` opens a block rather than an object literal
|
|
440
|
+
* @param {string} source
|
|
441
|
+
* @param {number} brace
|
|
442
|
+
* @returns {boolean}
|
|
443
|
+
*/
|
|
444
|
+
function isBlockBrace(source, brace) {
|
|
445
|
+
const before = findPreviousToken(source, brace);
|
|
446
|
+
if (before === -1) return true;
|
|
447
|
+
|
|
448
|
+
const char = source[before] ?? '';
|
|
449
|
+
if (char === ';' || char === '{' || char === '}' || char === ')') return true;
|
|
450
|
+
if (char === '>') return source[before - 1] === '=';
|
|
451
|
+
return isBlockKeywordEnd(source, before);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* Whether a colon ends a statement label or `default`, going by what precedes the name.
|
|
456
|
+
* Two expressions cannot follow each other, so a name after one of these tokens cannot
|
|
457
|
+
* be the middle of a ternary
|
|
458
|
+
* @param {string} source
|
|
459
|
+
* @param {number} colon
|
|
460
|
+
* @returns {boolean}
|
|
461
|
+
*/
|
|
462
|
+
function isLabelColon(source, colon) {
|
|
463
|
+
const end = findPreviousToken(source, colon);
|
|
464
|
+
let start = end;
|
|
465
|
+
while (start >= 0 && RE_NAME_CHAR.test(source[start] ?? '')) start--;
|
|
466
|
+
if (start === end) return false;
|
|
467
|
+
|
|
468
|
+
const before = findPreviousToken(source, start + 1);
|
|
469
|
+
const char = source[before];
|
|
470
|
+
// After `:`, any other name may be a nested ternary’s branch
|
|
471
|
+
if (char === ':') return source.slice(start + 1, end + 1) === 'default';
|
|
472
|
+
return before === -1 || char === ';' || char === '}' || char === ')' || (char === '{' && isBlockBrace(source, before));
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
/**
|
|
476
|
+
* Whether the `case` keyword starts at an index, rather than a name or property holding it
|
|
477
|
+
* @param {string} source
|
|
478
|
+
* @param {number} index
|
|
479
|
+
* @returns {boolean}
|
|
480
|
+
*/
|
|
481
|
+
function isCaseKeyword(source, index) {
|
|
482
|
+
if (!source.startsWith('case', index) || RE_NAME_CHAR.test(source[index + 4] ?? '')) return false;
|
|
483
|
+
|
|
484
|
+
const before = source[index - 1] ?? '';
|
|
485
|
+
if (before === '.' || RE_NAME_CHAR.test(before)) return false;
|
|
486
|
+
|
|
487
|
+
let after = index + 4;
|
|
488
|
+
while (RE_WHITESPACE.test(source[after] ?? '')) after++;
|
|
489
|
+
return source[after] !== ':';
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/**
|
|
493
|
+
* Indexes of the colons after which a JavaScript statement starts
|
|
494
|
+
* @param {string} source
|
|
495
|
+
* @returns {Set<number>}
|
|
496
|
+
*/
|
|
497
|
+
function findStatementColons(source) {
|
|
498
|
+
const colons = new Set();
|
|
499
|
+
// Unpaired `?` in the current `case` expression, -1 outside of one
|
|
500
|
+
let ternaries = -1;
|
|
501
|
+
|
|
502
|
+
for (let i = 0; i < source.length; i++) {
|
|
503
|
+
const end = skipCommentOrString(source, i, true);
|
|
504
|
+
if (end > i) {
|
|
505
|
+
i = end - 1;
|
|
506
|
+
continue;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
const char = source[i];
|
|
510
|
+
if (ternaries === -1) {
|
|
511
|
+
if (char === ':') {
|
|
512
|
+
if (isLabelColon(source, i)) colons.add(i);
|
|
513
|
+
} else if (char === 'c' && isCaseKeyword(source, i)) {
|
|
514
|
+
ternaries = 0;
|
|
515
|
+
i += 3;
|
|
516
|
+
}
|
|
517
|
+
} else if (char === '?') {
|
|
518
|
+
// `?.` and `??` have no `:` to pair with
|
|
519
|
+
if (source[i + 1] === '.' || source[i + 1] === '?') i++;
|
|
520
|
+
else ternaries++;
|
|
521
|
+
} else if (char === ':') {
|
|
522
|
+
if (ternaries === 0) colons.add(i);
|
|
523
|
+
ternaries--;
|
|
524
|
+
} else if (char === ';' || char === '{' || char === '}') {
|
|
525
|
+
ternaries = -1;
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
return colons;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
/**
|
|
533
|
+
* Placeholders within `@charset`, `@import`, and `@namespace` statements, which
|
|
534
|
+
* Lightning CSS drops whole where it cannot read them, and `@charset` always
|
|
535
|
+
* @param {string} source
|
|
536
|
+
* @param {RegExp} placeholder
|
|
537
|
+
* @returns {string[]}
|
|
538
|
+
*/
|
|
539
|
+
function findDroppableAtRulePlaceholders(source, placeholder) {
|
|
540
|
+
const tokens = [];
|
|
541
|
+
let start = -1;
|
|
542
|
+
|
|
543
|
+
for (let i = 0; i <= source.length; i++) {
|
|
544
|
+
const end = skipCommentOrString(source, i, false);
|
|
545
|
+
if (end > i) {
|
|
546
|
+
i = end - 1;
|
|
547
|
+
continue;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
const char = source[i];
|
|
551
|
+
if (start === -1) {
|
|
552
|
+
if (char === '@' && RE_DROPPABLE_AT_RULE.test(source.slice(i, i + 11))) start = i;
|
|
553
|
+
} else if (char === ';' || char === '{' || char === '}' || char === undefined) {
|
|
554
|
+
for (const match of source.slice(start, i).matchAll(placeholder)) tokens.push(match[0]);
|
|
555
|
+
start = -1;
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
return tokens;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
/**
|
|
563
|
+
* Whether what comes before an index allows a statement or rule to start there
|
|
564
|
+
* @param {string} source
|
|
565
|
+
* @param {number} index
|
|
566
|
+
* @param {Set<number>} colons - Colons after which a statement starts
|
|
567
|
+
* @param {boolean} isJS
|
|
568
|
+
* @returns {boolean}
|
|
569
|
+
*/
|
|
570
|
+
function isCodeStart(source, index, colons, isJS) {
|
|
571
|
+
let position = index;
|
|
572
|
+
while (position > 0) {
|
|
573
|
+
const char = source[--position] ?? '';
|
|
574
|
+
if (char === '\n' || char === '\r' || char === ';' || char === '{' || char === '}') return true;
|
|
575
|
+
if (!RE_WHITESPACE.test(char)) {
|
|
576
|
+
return char === ')' || (char === '/' && source[position - 1] === '*') || colons.has(position) || (isJS && isBlockKeywordEnd(source, position));
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
return true;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
/**
|
|
583
|
+
* Whether minified CSS or JavaScript can stand in for its source. A fragment starting a
|
|
584
|
+
* statement or rule can render as anything, or as nothing, while engines read it as an
|
|
585
|
+
* identifier or selector and join it with the code around it, or drop it; a fragment in
|
|
586
|
+
* an at-rule Lightning CSS cannot read would go with that at-rule
|
|
587
|
+
* @param {string} source
|
|
588
|
+
* @param {unknown} output - Anything but a string, from a minifier of one’s own, passes
|
|
589
|
+
* @param {RegExp} placeholder - Global pattern matching one fragment placeholder
|
|
590
|
+
* @param {boolean} [isJS] - Whether the code is JavaScript rather than CSS
|
|
591
|
+
* @returns {boolean}
|
|
592
|
+
*/
|
|
593
|
+
function isMinifiedCodeSafe(source, output, placeholder, isJS = false) {
|
|
594
|
+
if (typeof output !== 'string' || output === source) return true;
|
|
595
|
+
|
|
596
|
+
const matches = [...source.matchAll(placeholder)];
|
|
597
|
+
if (!matches.length) return true;
|
|
598
|
+
|
|
599
|
+
const colons = isJS ? findStatementColons(source) : new Set();
|
|
600
|
+
const starts = matches.filter(match => isCodeStart(source, match.index, colons, isJS));
|
|
601
|
+
const kept = new Set(Array.from(output.matchAll(placeholder), match => match[0]));
|
|
602
|
+
|
|
603
|
+
// Output of nothing but fragments only holds up where no label or `case` went with the code
|
|
604
|
+
if (starts.length && (colons.size || output.replace(placeholder, '').trim() || !starts.every(match => kept.has(match[0])))) return false;
|
|
605
|
+
return isJS || !source.includes('@') || findDroppableAtRulePlaceholders(source, placeholder).every(token => kept.has(token));
|
|
606
|
+
}
|
|
607
|
+
|
|
336
608
|
export {
|
|
337
609
|
toDelimitedFragment,
|
|
338
610
|
toFragment,
|
|
339
|
-
replaceCustomFragments
|
|
611
|
+
replaceCustomFragments,
|
|
612
|
+
isMinifiedCodeSafe
|
|
340
613
|
};
|