html-minifier-next 4.17.1 → 4.17.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 CHANGED
@@ -61,7 +61,7 @@ You can use a configuration file to specify options. The file can be either JSON
61
61
 
62
62
  **JavaScript module configuration example:**
63
63
 
64
- ```js
64
+ ```javascript
65
65
  module.exports = {
66
66
  collapseWhitespace: true,
67
67
  removeComments: true,
@@ -74,7 +74,7 @@ module.exports = {
74
74
 
75
75
  ESM with Node.js ≥16.14:
76
76
 
77
- ```js
77
+ ```javascript
78
78
  import { minify } from 'html-minifier-next';
79
79
 
80
80
  const result = await minify('<p title="example" id="moo">foo</p>', {
@@ -86,7 +86,7 @@ console.log(result); // “<p title=example id=moo>foo”
86
86
 
87
87
  CommonJS:
88
88
 
89
- ```js
89
+ ```javascript
90
90
  const { minify, getPreset } = require('html-minifier-next');
91
91
 
92
92
  (async () => {
@@ -188,7 +188,7 @@ When `minifyCSS` is set to `true`, HTML Minifier Next uses [Lightning CSS](https
188
188
 
189
189
  You can pass Lightning CSS configuration options by providing an object:
190
190
 
191
- ```js
191
+ ```javascript
192
192
  const result = await minify(html, {
193
193
  minifyCSS: {
194
194
  targets: {
@@ -211,7 +211,7 @@ Available Lightning CSS options when passed as an object:
211
211
 
212
212
  For advanced usage, you can also pass a function:
213
213
 
214
- ```js
214
+ ```javascript
215
215
  const result = await minify(html, {
216
216
  minifyCSS: function(text, type) {
217
217
  // `text`: CSS string to minify
@@ -227,7 +227,7 @@ When `minifyJS` is set to `true`, HTML Minifier Next uses [Terser](https://githu
227
227
 
228
228
  You can choose between different JS minifiers using the `engine` field:
229
229
 
230
- ```js
230
+ ```javascript
231
231
  const result = await minify(html, {
232
232
  minifyJS: {
233
233
  engine: 'swc', // Use SWC for faster minification
@@ -253,7 +253,7 @@ npm i @swc/core
253
253
 
254
254
  You can pass engine-specific configuration options:
255
255
 
256
- ```js
256
+ ```javascript
257
257
  // Using Terser with custom options
258
258
  const result = await minify(html, {
259
259
  minifyJS: {
@@ -273,7 +273,7 @@ const result = await minify(html, {
273
273
 
274
274
  For advanced usage, you can also pass a function:
275
275
 
276
- ```js
276
+ ```javascript
277
277
  const result = await minify(html, {
278
278
  minifyJS: function(text, inline) {
279
279
  // `text`: JavaScript string to minify
@@ -287,7 +287,7 @@ const result = await minify(html, {
287
287
 
288
288
  When `minifySVG` is set to `true`, HTML Minifier Next applies SVG-specific optimizations to SVG elements and their attributes. These optimizations are lightweight, fast, and safe:
289
289
 
290
- ```js
290
+ ```javascript
291
291
  const result = await minify(html, {
292
292
  minifySVG: true // Enable with default settings
293
293
  });
@@ -313,7 +313,7 @@ What gets optimized:
313
313
 
314
314
  You can customize the optimization behavior by providing an options object:
315
315
 
316
- ```js
316
+ ```javascript
317
317
  const result = await minify(html, {
318
318
  minifySVG: {
319
319
  precision: 2, // Use 2 decimal places instead of 3
@@ -3929,6 +3929,20 @@ async function minifyHTML(value, options, partialMarkup) {
3929
3929
  text = entities.decodeHTML(text);
3930
3930
  }
3931
3931
  }
3932
+ // Trim outermost newline-based whitespace inside `pre`/`textarea` elements
3933
+ // This removes trailing newlines often added by template engines before closing tags
3934
+ // Only trims single trailing newlines (multiple newlines are likely intentional formatting)
3935
+ if (options.collapseWhitespace && stackNoTrimWhitespace.length) {
3936
+ const topTag = stackNoTrimWhitespace[stackNoTrimWhitespace.length - 1];
3937
+ if (stackNoTrimWhitespace.includes('pre') || stackNoTrimWhitespace.includes('textarea')) {
3938
+ // Trim trailing whitespace only if it ends with a single newline (not multiple)
3939
+ // Multiple newlines are likely intentional formatting, single newline is often a template artifact
3940
+ // Treat CRLF (`\r\n`), CR (`\r`), and LF (`\n`) as single line-ending units
3941
+ if (nextTag && nextTag === '/' + topTag && /[^\r\n](?:\r\n|\r|\n)[ \t]*$/.test(text)) {
3942
+ text = text.replace(/(?:\r\n|\r|\n)[ \t]*$/, '');
3943
+ }
3944
+ }
3945
+ }
3932
3946
  if (options.collapseWhitespace) {
3933
3947
  if (!stackNoTrimWhitespace.length) {
3934
3948
  if (prevTag === 'comment') {
@@ -9071,6 +9071,20 @@ async function minifyHTML(value, options, partialMarkup) {
9071
9071
  text = decodeHTML(text);
9072
9072
  }
9073
9073
  }
9074
+ // Trim outermost newline-based whitespace inside `pre`/`textarea` elements
9075
+ // This removes trailing newlines often added by template engines before closing tags
9076
+ // Only trims single trailing newlines (multiple newlines are likely intentional formatting)
9077
+ if (options.collapseWhitespace && stackNoTrimWhitespace.length) {
9078
+ const topTag = stackNoTrimWhitespace[stackNoTrimWhitespace.length - 1];
9079
+ if (stackNoTrimWhitespace.includes('pre') || stackNoTrimWhitespace.includes('textarea')) {
9080
+ // Trim trailing whitespace only if it ends with a single newline (not multiple)
9081
+ // Multiple newlines are likely intentional formatting, single newline is often a template artifact
9082
+ // Treat CRLF (`\r\n`), CR (`\r`), and LF (`\n`) as single line-ending units
9083
+ if (nextTag && nextTag === '/' + topTag && /[^\r\n](?:\r\n|\r|\n)[ \t]*$/.test(text)) {
9084
+ text = text.replace(/(?:\r\n|\r|\n)[ \t]*$/, '');
9085
+ }
9086
+ }
9087
+ }
9074
9088
  if (options.collapseWhitespace) {
9075
9089
  if (!stackNoTrimWhitespace.length) {
9076
9090
  if (prevTag === 'comment') {
@@ -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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"}
package/package.json CHANGED
@@ -21,12 +21,12 @@
21
21
  "@rollup/plugin-json": "^6.1.0",
22
22
  "@rollup/plugin-node-resolve": "^16.0.3",
23
23
  "@rollup/plugin-terser": "^0.4.4",
24
- "@swc/core": "^1.15.7",
24
+ "@swc/core": "^1.15.8",
25
25
  "eslint": "^9.39.2",
26
- "rollup": "^4.54.0",
26
+ "rollup": "^4.55.1",
27
27
  "rollup-plugin-polyfill-node": "^0.13.0",
28
28
  "typescript": "^5.9.3",
29
- "vite": "^7.3.0"
29
+ "vite": "^7.3.1"
30
30
  },
31
31
  "exports": {
32
32
  ".": {
@@ -98,5 +98,5 @@
98
98
  },
99
99
  "type": "module",
100
100
  "types": "./dist/types/htmlminifier.d.ts",
101
- "version": "4.17.1"
101
+ "version": "4.17.2"
102
102
  }
@@ -1088,6 +1088,20 @@ async function minifyHTML(value, options, partialMarkup) {
1088
1088
  text = decodeHTML(text);
1089
1089
  }
1090
1090
  }
1091
+ // Trim outermost newline-based whitespace inside `pre`/`textarea` elements
1092
+ // This removes trailing newlines often added by template engines before closing tags
1093
+ // Only trims single trailing newlines (multiple newlines are likely intentional formatting)
1094
+ if (options.collapseWhitespace && stackNoTrimWhitespace.length) {
1095
+ const topTag = stackNoTrimWhitespace[stackNoTrimWhitespace.length - 1];
1096
+ if (stackNoTrimWhitespace.includes('pre') || stackNoTrimWhitespace.includes('textarea')) {
1097
+ // Trim trailing whitespace only if it ends with a single newline (not multiple)
1098
+ // Multiple newlines are likely intentional formatting, single newline is often a template artifact
1099
+ // Treat CRLF (`\r\n`), CR (`\r`), and LF (`\n`) as single line-ending units
1100
+ if (nextTag && nextTag === '/' + topTag && /[^\r\n](?:\r\n|\r|\n)[ \t]*$/.test(text)) {
1101
+ text = text.replace(/(?:\r\n|\r|\n)[ \t]*$/, '');
1102
+ }
1103
+ }
1104
+ }
1091
1105
  if (options.collapseWhitespace) {
1092
1106
  if (!stackNoTrimWhitespace.length) {
1093
1107
  if (prevTag === 'comment') {