html-minifier-next 1.1.4 → 1.2.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/LICENSE CHANGED
@@ -4,7 +4,7 @@ Copyright 2010–2019 Juriy “kangax” Zaytsev
4
4
 
5
5
  Copyright Terser
6
6
 
7
- Copyright Jens Oliver Meiert
7
+ Copyright 2025 Jens Oliver Meiert
8
8
 
9
9
  Permission is hereby granted, free of charge, to any person obtaining a copy
10
10
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -50,25 +50,26 @@ For lint-like capabilities take a look at [HTMLLint](https://github.com/kangax/h
50
50
 
51
51
  ## Minification comparison
52
52
 
53
- How does HTMLMinifier compare to other solutions—[HTML Minifier from Will Peavy](http://www.willpeavy.com/minifier/) (1st result in [Google search for “html minifier”](https://www.google.com/#q=html+minifier)) as well as [htmlcompressor.com](http://htmlcompressor.com) and [minimize](https://github.com/Swaagie/minimize)?
53
+ How does HTMLMinifier compare to other solutions, like [minimize](https://github.com/Swaagie/minimize) or [htmlcompressor.com](http://htmlcompressor.com/)?
54
54
 
55
55
  | Site | Original size (KB) | HTMLMinifier | minimize | htmlcompressor.com |
56
56
  | --- | --- | --- | --- | --- |
57
- | [Amazon](https://www.amazon.com/) | 695 | **625** | 682 | n/a |
58
- | [BBC](https://www.bbc.co.uk/) | 655 | **602** | 649 | n/a |
59
- | [ECMAScript](https://tc39.es/ecma262/) | 7197 | **6353** | 6573 | n/a |
60
- | [EFF](https://www.eff.org/) | 60 | **51** | 54 | n/a |
61
- | [Eloquent JavaScript](https://eloquentjavascript.net/) | 6 | **5** | 6 | n/a |
62
- | [FAZ](https://www.faz.net/aktuell/) | 1793 | **1667** | 1705 | n/a |
63
- | [Frontend Dogma](https://frontenddogma.com/) | 116 | **112** | 125 | n/a |
64
- | [Google](https://www.google.com/) | 51 | **46** | 51 | n/a |
65
- | [HTMLMinifier](https://github.com/kangax/html-minifier) | 366 | **245** | 343 | n/a |
66
- | [Mastodon](https://mastodon.social/explore) | 37 | **27** | 36 | n/a |
67
- | [NBC](https://www.nbc.com/) | 1022 | **932** | 1010 | n/a |
68
- | [New York Times](https://www.nytimes.com/) | 951 | **809** | 939 | n/a |
69
- | [United Nations](https://www.un.org/) | 9 | **7** | 8 | n/a |
70
- | [W3C](https://www.w3.org/) | 51 | **36** | 42 | n/a |
71
- | [Wikipedia](https://en.wikipedia.org/wiki/Main_Page) | 114 | **100** | 107 | n/a |
57
+ | [A List Apart](https://alistapart.com/) | 64 | **54** | 59 | 57 |
58
+ | [Amazon](https://www.amazon.com/) | 206 | **195** | 203 | 200 |
59
+ | [BBC](https://www.bbc.co.uk/) | 767 | **703** | 761 | n/a |
60
+ | [CSS-Tricks](https://css-tricks.com/) | 166 | **124** | 152 | 148 |
61
+ | [ECMAScript](https://tc39.es/ecma262/) | 7204 | **6361** | 6581 | n/a |
62
+ | [EFF](https://www.eff.org/) | 57 | **48** | 52 | 52 |
63
+ | [FAZ](https://www.faz.net/aktuell/) | 1767 | **1641** | 1679 | n/a |
64
+ | [Frontend Dogma](https://frontenddogma.com/) | 119 | **114** | 128 | 118 |
65
+ | [Google](https://www.google.com/) | 51 | **46** | 50 | 50 |
66
+ | [HTMLMinifier](https://github.com/kangax/html-minifier) | 373 | **250** | 349 | n/a |
67
+ | [Mastodon](https://mastodon.social/explore) | 37 | **28** | 36 | 36 |
68
+ | [NBC](https://www.nbc.com/) | 601 | **549** | 593 | n/a |
69
+ | [New York Times](https://www.nytimes.com/) | 822 | **701** | 811 | n/a |
70
+ | [United Nations](https://www.un.org/) | 9 | **7** | 8 | 8 |
71
+ | [W3C](https://www.w3.org/) | 50 | **36** | 41 | 39 |
72
+ | [Wikipedia](https://en.wikipedia.org/wiki/Main_Page) | 225 | **204** | 215 | 215 |
72
73
 
73
74
  ## Options quick reference
74
75
 
@@ -92,6 +93,7 @@ Most of the options are disabled by default.
92
93
  | `ignoreCustomComments` | Array of regexes that allow to ignore certain comments, when matched | `[ /^!/, /^\s*#/ ]` |
93
94
  | `ignoreCustomFragments` | Array of regexes that allow to ignore certain fragments, when matched (e.g. `<?php ... ?>`, `{{ ... }}`, etc.) | `[ /<%[\s\S]*?%>/, /<\?[\s\S]*?\?>/ ]` |
94
95
  | `includeAutoGeneratedTags` | Insert tags generated by HTML parser | `true` |
96
+ | `inlineCustomElements` | Array of names of custom elements which are inline | `[]` |
95
97
  | `keepClosingSlash` | Keep the trailing slash on singleton elements | `false` |
96
98
  | `maxInputLength` | Maximum input length to prevent ReDoS attacks (disabled by default) | `undefined` |
97
99
  | `maxLineLength` | Specify a maximum line length. Compressed output will be split by newlines at valid HTML split-points |
@@ -231,4 +233,4 @@ npm run serve
231
233
 
232
234
  ## Acknowledgements
233
235
 
234
- With many thanks to all the previous authors of HTML Minifier, especially [Juriy Zaytsev](https://github.com/kangax), and to everyone who helped make this new edition better, like [Daniel Ruf](https://github.com/DanielRuf).
236
+ With many thanks to all the previous authors of HTML Minifier, especially [Juriy Zaytsev](https://github.com/kangax), and to everyone who helped make this new edition better, like [Daniel Ruf](https://github.com/DanielRuf).
package/cli.js CHANGED
@@ -73,7 +73,7 @@ function parseJSON(value) {
73
73
  if (value) {
74
74
  try {
75
75
  return JSON.parse(value);
76
- } catch (e) {
76
+ } catch {
77
77
  if (/^{/.test(value)) {
78
78
  fatal('Could not parse JSON value \'' + value + '\'');
79
79
  }
@@ -113,6 +113,7 @@ const mainOptions = {
113
113
  ignoreCustomComments: ['Array of regex\'es that allow to ignore certain comments, when matched', parseJSONRegExpArray],
114
114
  ignoreCustomFragments: ['Array of regex\'es that allow to ignore certain fragments, when matched (e.g. <?php ... ?>, {{ ... }})', parseJSONRegExpArray],
115
115
  includeAutoGeneratedTags: 'Insert tags generated by HTML parser',
116
+ inlineCustomElements: ['Array of names of custom elements which are inline', parseJSONArray],
116
117
  keepClosingSlash: 'Keep the trailing slash on singleton elements',
117
118
  maxInputLength: ['Maximum input length to prevent ReDoS attacks', parseInt],
118
119
  maxLineLength: ['Max line length', parseInt],
@@ -496,9 +496,7 @@ class TokenChain {
496
496
  }
497
497
  }
498
498
 
499
- function trimWhitespace(str) {
500
- return str && str.replace(/^[ \n\r\t\f]+/, '').replace(/[ \n\r\t\f]+$/, '');
501
- }
499
+ const trimWhitespace = str => str && str.replace(/^[ \n\r\t\f]+/, '').replace(/[ \n\r\t\f]+$/, '');
502
500
 
503
501
  function collapseWhitespaceAll(str) {
504
502
  // Non-breaking space is specifically handled inside the replacer function here:
@@ -550,14 +548,14 @@ function collapseWhitespace(str, options, trimLeft, trimRight, collapseAll) {
550
548
  return lineBreakBefore + str + lineBreakAfter;
551
549
  }
552
550
 
553
- // non-empty tags that will maintain whitespace around them
554
- const inlineTags = new Set(['a', 'abbr', 'acronym', 'b', 'bdi', 'bdo', 'big', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'ins', 'kbd', 'label', 'mark', 'math', 'nobr', 'object', 'q', 'rp', 'rt', 'rtc', 'ruby', 's', 'samp', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'svg', 'textarea', 'time', 'tt', 'u', 'var']);
555
- // non-empty tags that will maintain whitespace within them
551
+ // non-empty elements that will maintain whitespace around them
552
+ const inlineHtmlElements = ['a', 'abbr', 'acronym', 'b', 'bdi', 'bdo', 'big', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'mark', 'math', 'meter', 'nobr', 'object', 'output', 'progress', 'q', 'rp', 'rt', 'rtc', 'ruby', 's', 'samp', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'svg', 'textarea', 'time', 'tt', 'u', 'var', 'wbr'];
553
+ // non-empty elements that will maintain whitespace within them
556
554
  const inlineTextTags = new Set(['a', 'abbr', 'acronym', 'b', 'big', 'del', 'em', 'font', 'i', 'ins', 'kbd', 'mark', 'nobr', 'rp', 's', 'samp', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'time', 'tt', 'u', 'var']);
557
- // self-closing tags that will maintain whitespace around them
555
+ // self-closing elements that will maintain whitespace around them
558
556
  const selfClosingInlineTags = new Set(['comment', 'img', 'input', 'wbr']);
559
557
 
560
- function collapseWhitespaceSmart(str, prevTag, nextTag, options) {
558
+ function collapseWhitespaceSmart(str, prevTag, nextTag, options, inlineTags) {
561
559
  let trimLeft = prevTag && !selfClosingInlineTags.has(prevTag);
562
560
  if (trimLeft && !options.collapseInlineTagWhitespace) {
563
561
  trimLeft = prevTag.charAt(0) === '/' ? !inlineTags.has(prevTag.slice(1)) : !inlineTextTags.has(prevTag);
@@ -1357,6 +1355,7 @@ async function minifyHTML(value, options, partialMarkup) {
1357
1355
  let uidIgnore;
1358
1356
  let uidAttr;
1359
1357
  let uidPattern;
1358
+ let inlineTags = new Set([...inlineHtmlElements, ...(options.inlineCustomElements ?? [])]);
1360
1359
 
1361
1360
  // temporarily replace ignored chunks with comments,
1362
1361
  // so that we don't have to worry what's there.
@@ -1488,7 +1487,7 @@ async function minifyHTML(value, options, partialMarkup) {
1488
1487
  const match = str.match(/^<\/([\w:-]+)>$/);
1489
1488
  if (match) {
1490
1489
  endTag = match[1];
1491
- } else if (/>$/.test(str) || (buffer[index] = collapseWhitespaceSmart(str, null, nextTag, options))) {
1490
+ } else if (/>$/.test(str) || (buffer[index] = collapseWhitespaceSmart(str, null, nextTag, options, inlineTags))) {
1492
1491
  break;
1493
1492
  }
1494
1493
  }
@@ -1699,7 +1698,7 @@ async function minifyHTML(value, options, partialMarkup) {
1699
1698
  }
1700
1699
  }
1701
1700
  if (prevTag || nextTag) {
1702
- text = collapseWhitespaceSmart(text, prevTag, nextTag, options);
1701
+ text = collapseWhitespaceSmart(text, prevTag, nextTag, options, inlineTags);
1703
1702
  } else {
1704
1703
  text = collapseWhitespace(text, options, true, true);
1705
1704
  }