html-minifier-next 4.3.1 → 4.4.0
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 +6 -5
- package/cli.js +2 -1
- package/dist/htmlminifier.cjs +15 -1
- package/dist/htmlminifier.esm.bundle.js +15 -1
- package/dist/types/htmlminifier.d.ts +10 -0
- package/dist/types/htmlminifier.d.ts.map +1 -1
- package/dist/types/htmlparser.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/htmlminifier.js +10 -1
- package/src/htmlparser.js +5 -0
package/README.md
CHANGED
|
@@ -134,6 +134,7 @@ Options can be used in config files (camelCase) or via CLI flags (kebab-case wit
|
|
|
134
134
|
| `minifyJS`<br>`--minify-js` | Minify JavaScript in `script` elements and event attributes (uses [Terser](https://github.com/terser/terser)) | `false` (could be `true`, `Object`, `Function(text, inline)`) |
|
|
135
135
|
| `minifyURLs`<br>`--minify-urls` | Minify URLs in various attributes (uses [relateurl](https://github.com/stevenvachon/relateurl)) | `false` (could be `String`, `Object`, `Function(text)`, `async Function(text)`) |
|
|
136
136
|
| `noNewlinesBeforeTagClose`<br>`--no-newlines-before-tag-close` | Never add a newline before a tag that closes an element | `false` |
|
|
137
|
+
| `partialMarkup`<br>`--partial-markup` | Treat input as a partial HTML fragment, preserving stray end tags (closing tags without opening tags) and preventing auto-closing of unclosed tags at end of input | `false` |
|
|
137
138
|
| `preserveLineBreaks`<br>`--preserve-line-breaks` | Always collapse to 1 line break (never remove it entirely) when whitespace between tags includes a line break—use with `collapseWhitespace: true` | `false` |
|
|
138
139
|
| `preventAttributesEscaping`<br>`--prevent-attributes-escaping` | Prevents the escaping of the values of attributes | `false` |
|
|
139
140
|
| `processConditionalComments`<br>`--process-conditional-comments` | Process contents of conditional comments through minifier | `false` |
|
|
@@ -288,21 +289,21 @@ If you have chunks of markup you would like preserved, you can wrap them with `<
|
|
|
288
289
|
|
|
289
290
|
### Minifying JSON-LD
|
|
290
291
|
|
|
291
|
-
You can minify `script` elements with JSON-LD by setting `{ processScripts: ['application/ld+json'] }`. Note that this minification is rudimentary; it’s mainly useful for removing newlines and excessive whitespace.
|
|
292
|
+
You can minify `script` elements with JSON-LD by setting `{ processScripts: ['application/ld+json'] }`. Note that this minification is rudimentary; it’s mainly useful for removing newlines and excessive whitespace.
|
|
292
293
|
|
|
293
294
|
### Preserving SVG elements
|
|
294
295
|
|
|
295
296
|
SVG elements are automatically recognized, and when they are minified, both case-sensitivity and closing-slashes are preserved, regardless of the minification settings used for the rest of the file.
|
|
296
297
|
|
|
297
|
-
### Working with invalid markup
|
|
298
|
+
### Working with invalid or partial markup
|
|
298
299
|
|
|
299
|
-
HTML Minifier Next
|
|
300
|
+
By default, HTML Minifier Next parses markup into a complete tree structure, then modifies it (removing anything that was specified for removal, ignoring anything that was specified to be ignored, etc.), then creates markup from that tree and returns it.
|
|
300
301
|
|
|
301
302
|
_Input markup (e.g., `<p id="">foo`) → Internal representation of markup in a form of tree (e.g., `{ tag: "p", attr: "id", children: ["foo"] }`) → Transformation of internal representation (e.g., removal of `id` attribute) → Output of resulting markup (e.g., `<p>foo</p>`)_
|
|
302
303
|
|
|
303
|
-
|
|
304
|
+
For partial HTML fragments (such as template includes, SSI fragments, or closing tags without opening tags), use the `partialMarkup: true` option. This preserves stray end tags (closing tags without corresponding opening tags) and prevents auto-closing of unclosed tags at the end of input. Note that normal HTML auto-closing rules still apply during parsing—for example, a closing parent tag will still auto-close its unclosed child elements.
|
|
304
305
|
|
|
305
|
-
To validate HTML markup, use [the W3C validator](https://validator.w3.org/) or one of [several validator packages](https://meiert.com/blog/html-validator-packages/).
|
|
306
|
+
To validate complete HTML markup, use [the W3C validator](https://validator.w3.org/) or one of [several validator packages](https://meiert.com/blog/html-validator-packages/).
|
|
306
307
|
|
|
307
308
|
## Security
|
|
308
309
|
|
package/cli.js
CHANGED
|
@@ -140,7 +140,8 @@ const mainOptions = {
|
|
|
140
140
|
minifyJS: ['Minify JavaScript in “script” elements and event attributes (uses Terser)', parseJSON],
|
|
141
141
|
minifyURLs: ['Minify URLs in various attributes (uses relateurl)', parseJSON],
|
|
142
142
|
noNewlinesBeforeTagClose: 'Never add a newline before a tag that closes an element',
|
|
143
|
-
|
|
143
|
+
partialMarkup: 'Treat input as a partial HTML fragment, preserving stray end tags and unclosed tags',
|
|
144
|
+
preserveLineBreaks: 'Always collapse to 1 line break (never remove it entirely) when whitespace between tags includes a line break—use with "collapseWhitespace=true"',
|
|
144
145
|
preventAttributesEscaping: 'Prevents the escaping of the values of attributes',
|
|
145
146
|
processConditionalComments: 'Process contents of conditional comments through minifier',
|
|
146
147
|
processScripts: ['Array of strings corresponding to types of “script” elements to process through minifier (e.g., “text/ng-template”, “text/x-handlebars-template”, etc.)', parseJSONArray],
|
package/dist/htmlminifier.cjs
CHANGED
|
@@ -453,6 +453,11 @@ class HTMLParser {
|
|
|
453
453
|
// Remove the open elements from the stack
|
|
454
454
|
stack.length = pos;
|
|
455
455
|
lastTag = pos && stack[pos - 1].tag;
|
|
456
|
+
} else if (handler.partialMarkup && tagName) {
|
|
457
|
+
// In partial markup mode, preserve stray end tags
|
|
458
|
+
if (handler.end) {
|
|
459
|
+
handler.end(tagName, [], false);
|
|
460
|
+
}
|
|
456
461
|
} else if (tagName.toLowerCase() === 'br') {
|
|
457
462
|
if (handler.start) {
|
|
458
463
|
await handler.start(tagName, [], true, '');
|
|
@@ -1642,7 +1647,7 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
1642
1647
|
}
|
|
1643
1648
|
|
|
1644
1649
|
const parser = new HTMLParser(value, {
|
|
1645
|
-
partialMarkup,
|
|
1650
|
+
partialMarkup: partialMarkup ?? options.partialMarkup,
|
|
1646
1651
|
continueOnParseError: options.continueOnParseError,
|
|
1647
1652
|
customAttrAssign: options.customAttrAssign,
|
|
1648
1653
|
customAttrSurround: options.customAttrSurround,
|
|
@@ -2226,6 +2231,15 @@ var htmlminifier = { minify };
|
|
|
2226
2231
|
*
|
|
2227
2232
|
* Default: `false`
|
|
2228
2233
|
*
|
|
2234
|
+
* @prop {boolean} [partialMarkup]
|
|
2235
|
+
* When true, treat input as a partial HTML fragment rather than a complete
|
|
2236
|
+
* document. This preserves stray end tags (closing tags without corresponding
|
|
2237
|
+
* opening tags) and prevents auto-closing of unclosed tags at the end of input.
|
|
2238
|
+
* Useful for minifying template fragments, SSI includes, or other partial HTML
|
|
2239
|
+
* that will be combined with other fragments.
|
|
2240
|
+
*
|
|
2241
|
+
* Default: `false`
|
|
2242
|
+
*
|
|
2229
2243
|
* @prop {boolean} [preserveLineBreaks]
|
|
2230
2244
|
* Preserve a single line break at the start/end of text nodes when
|
|
2231
2245
|
* collapsing/trimming whitespace.
|
|
@@ -39506,6 +39506,11 @@ class HTMLParser {
|
|
|
39506
39506
|
// Remove the open elements from the stack
|
|
39507
39507
|
stack.length = pos;
|
|
39508
39508
|
lastTag = pos && stack[pos - 1].tag;
|
|
39509
|
+
} else if (handler.partialMarkup && tagName) {
|
|
39510
|
+
// In partial markup mode, preserve stray end tags
|
|
39511
|
+
if (handler.end) {
|
|
39512
|
+
handler.end(tagName, [], false);
|
|
39513
|
+
}
|
|
39509
39514
|
} else if (tagName.toLowerCase() === 'br') {
|
|
39510
39515
|
if (handler.start) {
|
|
39511
39516
|
await handler.start(tagName, [], true, '');
|
|
@@ -40695,7 +40700,7 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
40695
40700
|
}
|
|
40696
40701
|
|
|
40697
40702
|
const parser = new HTMLParser(value, {
|
|
40698
|
-
partialMarkup,
|
|
40703
|
+
partialMarkup: partialMarkup ?? options.partialMarkup,
|
|
40699
40704
|
continueOnParseError: options.continueOnParseError,
|
|
40700
40705
|
customAttrAssign: options.customAttrAssign,
|
|
40701
40706
|
customAttrSurround: options.customAttrSurround,
|
|
@@ -41279,6 +41284,15 @@ var htmlminifier = { minify };
|
|
|
41279
41284
|
*
|
|
41280
41285
|
* Default: `false`
|
|
41281
41286
|
*
|
|
41287
|
+
* @prop {boolean} [partialMarkup]
|
|
41288
|
+
* When true, treat input as a partial HTML fragment rather than a complete
|
|
41289
|
+
* document. This preserves stray end tags (closing tags without corresponding
|
|
41290
|
+
* opening tags) and prevents auto-closing of unclosed tags at the end of input.
|
|
41291
|
+
* Useful for minifying template fragments, SSI includes, or other partial HTML
|
|
41292
|
+
* that will be combined with other fragments.
|
|
41293
|
+
*
|
|
41294
|
+
* Default: `false`
|
|
41295
|
+
*
|
|
41282
41296
|
* @prop {boolean} [preserveLineBreaks]
|
|
41283
41297
|
* Preserve a single line break at the start/end of text nodes when
|
|
41284
41298
|
* collapsing/trimming whitespace.
|
|
@@ -241,6 +241,16 @@ export type MinifierOptions = {
|
|
|
241
241
|
* Default: `false`
|
|
242
242
|
*/
|
|
243
243
|
noNewlinesBeforeTagClose?: boolean;
|
|
244
|
+
/**
|
|
245
|
+
* When true, treat input as a partial HTML fragment rather than a complete
|
|
246
|
+
* document. This preserves stray end tags (closing tags without corresponding
|
|
247
|
+
* opening tags) and prevents auto-closing of unclosed tags at the end of input.
|
|
248
|
+
* Useful for minifying template fragments, SSI includes, or other partial HTML
|
|
249
|
+
* that will be combined with other fragments.
|
|
250
|
+
*
|
|
251
|
+
* Default: `false`
|
|
252
|
+
*/
|
|
253
|
+
partialMarkup?: boolean;
|
|
244
254
|
/**
|
|
245
255
|
* Preserve a single line break at the start/end of text nodes when
|
|
246
256
|
* collapsing/trimming whitespace.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"htmlminifier.d.ts","sourceRoot":"","sources":["../../src/htmlminifier.js"],"names":[],"mappings":"AAs8CO,8BAJI,MAAM,YACN,eAAe,GACb,OAAO,CAAC,MAAM,CAAC,CAQ3B;;;;;;;;;UAQS,MAAM;YACN,MAAM;YACN,MAAM;mBACN,MAAM;iBACN,MAAM;kBACN,MAAM;;;;;;;;;;;;;4BAQN,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,EAAE,qBAAqB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,KAAK,OAAO;;;;;;;wBAMjG,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,SAAS,EAAE,iBAAiB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,KAAK,OAAO;;;;;;;;oBAMhH,OAAO;;;;;;;;gCAOP,OAAO;;;;;;;;kCAOP,OAAO;;;;;;;;yBAOP,OAAO;;;;;;;;2BAOP,OAAO;;;;;;;;4BAOP,OAAO;;;;;;;2BAOP,OAAO;;;;;;;;uBAMP,MAAM,EAAE;;;;;;yBAOR,MAAM;;;;;;yBAKN,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE;;;;;;;4BAKlB,MAAM,EAAE;;;;;;;oCAMR,MAAM;;;;;;;qBAMN,OAAO;;;;;;;YAMP,OAAO;;;;;;;;2BAMP,MAAM,EAAE;;;;;;;;;4BAOR,MAAM,EAAE;;;;;;;+BAQR,OAAO;;;;;;;2BAMP,SAAS,CAAC,MAAM,CAAC;;;;;;uBAMjB,OAAO;;;;;;;;UAKP,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI;;;;;;;;qBAO1B,MAAM;;;;;;;oBAON,MAAM;;;;;;;;;;gBAMN,OAAO,GAAG,OAAO,CAAC,OAAO,cAAc,EAAE,gBAAgB,CAAC,OAAO,cAAc,EAAE,aAAa,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;;;;;;;;;;eAS9J,OAAO,GAAG,OAAO,QAAQ,EAAE,aAAa,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;;;;;;;;;;iBASzG,OAAO,GAAG,MAAM,GAAG,OAAO,WAAW,EAAE,OAAO,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;;;;;;;;WAS7F,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM;;;;;;;+BAOxB,OAAO;;;;;;;;
|
|
1
|
+
{"version":3,"file":"htmlminifier.d.ts","sourceRoot":"","sources":["../../src/htmlminifier.js"],"names":[],"mappings":"AAs8CO,8BAJI,MAAM,YACN,eAAe,GACb,OAAO,CAAC,MAAM,CAAC,CAQ3B;;;;;;;;;UAQS,MAAM;YACN,MAAM;YACN,MAAM;mBACN,MAAM;iBACN,MAAM;kBACN,MAAM;;;;;;;;;;;;;4BAQN,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,EAAE,qBAAqB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,KAAK,OAAO;;;;;;;wBAMjG,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,SAAS,EAAE,iBAAiB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,KAAK,OAAO;;;;;;;;oBAMhH,OAAO;;;;;;;;gCAOP,OAAO;;;;;;;;kCAOP,OAAO;;;;;;;;yBAOP,OAAO;;;;;;;;2BAOP,OAAO;;;;;;;;4BAOP,OAAO;;;;;;;2BAOP,OAAO;;;;;;;;uBAMP,MAAM,EAAE;;;;;;yBAOR,MAAM;;;;;;yBAKN,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE;;;;;;;4BAKlB,MAAM,EAAE;;;;;;;oCAMR,MAAM;;;;;;;qBAMN,OAAO;;;;;;;YAMP,OAAO;;;;;;;;2BAMP,MAAM,EAAE;;;;;;;;;4BAOR,MAAM,EAAE;;;;;;;+BAQR,OAAO;;;;;;;2BAMP,SAAS,CAAC,MAAM,CAAC;;;;;;uBAMjB,OAAO;;;;;;;;UAKP,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI;;;;;;;;qBAO1B,MAAM;;;;;;;oBAON,MAAM;;;;;;;;;;gBAMN,OAAO,GAAG,OAAO,CAAC,OAAO,cAAc,EAAE,gBAAgB,CAAC,OAAO,cAAc,EAAE,aAAa,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;;;;;;;;;;eAS9J,OAAO,GAAG,OAAO,QAAQ,EAAE,aAAa,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;;;;;;;;;;iBASzG,OAAO,GAAG,MAAM,GAAG,OAAO,WAAW,EAAE,OAAO,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;;;;;;;;WAS7F,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM;;;;;;;+BAOxB,OAAO;;;;;;;;;;oBAMP,OAAO;;;;;;;;yBASP,OAAO;;;;;;;gCAOP,OAAO;;;;;;;;iCAMP,OAAO;;;;;;;;;;qBAOP,MAAM,EAAE;;;;;;;qBASR,IAAI,GAAG,GAAG;;;;;;;4BAMV,OAAO;;;;;;;;qBAMP,OAAO;;;;;;;;;4BAOP,OAAO,GAAG,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;;;;;;;;0BAQtD,OAAO;;;;;;;;yBAOP,OAAO;;;;;;;;gCAOP,OAAO;;;;;;;iCAOP,OAAO;;;;;;;oCAMP,OAAO;;;;;;;;;;0BAMP,OAAO;;;;;;;;;qBASP,OAAO,GAAG,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,IAAI,CAAC;;;;;;;;;oBAQzD,OAAO,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;;;;;;;;0BAQrC,OAAO;;;;;;;sBAOP,OAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"htmlparser.d.ts","sourceRoot":"","sources":["../../src/htmlparser.js"],"names":[],"mappings":"AAgDA,4BAAoE;AAyDpE;IACE,qCAGC;IAFC,UAAgB;IAChB,aAAsB;IAGxB,
|
|
1
|
+
{"version":3,"file":"htmlparser.d.ts","sourceRoot":"","sources":["../../src/htmlparser.js"],"names":[],"mappings":"AAgDA,4BAAoE;AAyDpE;IACE,qCAGC;IAFC,UAAgB;IAChB,aAAsB;IAGxB,uBAgWC;CACF"}
|
package/package.json
CHANGED
package/src/htmlminifier.js
CHANGED
|
@@ -1112,7 +1112,7 @@ async function minifyHTML(value, options, partialMarkup) {
|
|
|
1112
1112
|
}
|
|
1113
1113
|
|
|
1114
1114
|
const parser = new HTMLParser(value, {
|
|
1115
|
-
partialMarkup,
|
|
1115
|
+
partialMarkup: partialMarkup ?? options.partialMarkup,
|
|
1116
1116
|
continueOnParseError: options.continueOnParseError,
|
|
1117
1117
|
customAttrAssign: options.customAttrAssign,
|
|
1118
1118
|
customAttrSurround: options.customAttrSurround,
|
|
@@ -1696,6 +1696,15 @@ export default { minify };
|
|
|
1696
1696
|
*
|
|
1697
1697
|
* Default: `false`
|
|
1698
1698
|
*
|
|
1699
|
+
* @prop {boolean} [partialMarkup]
|
|
1700
|
+
* When true, treat input as a partial HTML fragment rather than a complete
|
|
1701
|
+
* document. This preserves stray end tags (closing tags without corresponding
|
|
1702
|
+
* opening tags) and prevents auto-closing of unclosed tags at the end of input.
|
|
1703
|
+
* Useful for minifying template fragments, SSI includes, or other partial HTML
|
|
1704
|
+
* that will be combined with other fragments.
|
|
1705
|
+
*
|
|
1706
|
+
* Default: `false`
|
|
1707
|
+
*
|
|
1699
1708
|
* @prop {boolean} [preserveLineBreaks]
|
|
1700
1709
|
* Preserve a single line break at the start/end of text nodes when
|
|
1701
1710
|
* collapsing/trimming whitespace.
|
package/src/htmlparser.js
CHANGED
|
@@ -443,6 +443,11 @@ export class HTMLParser {
|
|
|
443
443
|
// Remove the open elements from the stack
|
|
444
444
|
stack.length = pos;
|
|
445
445
|
lastTag = pos && stack[pos - 1].tag;
|
|
446
|
+
} else if (handler.partialMarkup && tagName) {
|
|
447
|
+
// In partial markup mode, preserve stray end tags
|
|
448
|
+
if (handler.end) {
|
|
449
|
+
handler.end(tagName, [], false);
|
|
450
|
+
}
|
|
446
451
|
} else if (tagName.toLowerCase() === 'br') {
|
|
447
452
|
if (handler.start) {
|
|
448
453
|
await handler.start(tagName, [], true, '');
|