html-minifier-next 4.5.1 → 4.6.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 CHANGED
@@ -107,7 +107,7 @@ For lint-like capabilities, take a look at [HTMLLint](https://github.com/kangax/
107
107
  HTML Minifier Next provides presets for common use cases. Presets are pre-configured option sets that can be used as a starting point:
108
108
 
109
109
  * `conservative`: Safe minification suitable for most projects. Includes whitespace collapsing, comment removal, and doctype normalization.
110
- * `comprehensive`: Aggressive minification for maximum file size reduction. Includes all conservative options plus attribute quote removal, optional tag removal, and more.
110
+ * `comprehensive`: Aggressive minification for maximum file size reduction. Includes relevant conservative options plus attribute quote removal, optional tag removal, and more.
111
111
 
112
112
  **Using presets:**
113
113
 
@@ -1032,11 +1032,55 @@ async function cleanConditionalComment(comment, options) {
1032
1032
  : comment;
1033
1033
  }
1034
1034
 
1035
+ const jsonScriptTypes = new Set([
1036
+ 'application/json',
1037
+ 'application/ld+json',
1038
+ 'application/manifest+json',
1039
+ 'application/vnd.geo+json',
1040
+ 'importmap',
1041
+ 'speculationrules',
1042
+ ]);
1043
+
1044
+ function minifyJson(text, options) {
1045
+ try {
1046
+ return JSON.stringify(JSON.parse(text));
1047
+ }
1048
+ catch (err) {
1049
+ if (!options.continueOnMinifyError) {
1050
+ throw err;
1051
+ }
1052
+ options.log && options.log(err);
1053
+ return text;
1054
+ }
1055
+ }
1056
+
1057
+ function hasJsonScriptType(attrs) {
1058
+ for (let i = 0, len = attrs.length; i < len; i++) {
1059
+ const attrName = attrs[i].name.toLowerCase();
1060
+ if (attrName === 'type') {
1061
+ const attrValue = trimWhitespace((attrs[i].value || '').split(/;/, 2)[0]).toLowerCase();
1062
+ if (jsonScriptTypes.has(attrValue)) {
1063
+ return true;
1064
+ }
1065
+ }
1066
+ }
1067
+ return false;
1068
+ }
1069
+
1035
1070
  async function processScript(text, options, currentAttrs) {
1036
1071
  for (let i = 0, len = currentAttrs.length; i < len; i++) {
1037
- if (currentAttrs[i].name.toLowerCase() === 'type' &&
1038
- options.processScripts.indexOf(currentAttrs[i].value) > -1) {
1039
- return await minifyHTML(text, options);
1072
+ const attrName = currentAttrs[i].name.toLowerCase();
1073
+ if (attrName === 'type') {
1074
+ const rawValue = currentAttrs[i].value;
1075
+ const normalizedValue = trimWhitespace((rawValue || '').split(/;/, 2)[0]).toLowerCase();
1076
+ // Minify JSON script types automatically
1077
+ if (jsonScriptTypes.has(normalizedValue)) {
1078
+ return minifyJson(text, options);
1079
+ }
1080
+ // Process custom script types if specified
1081
+ if (options.processScripts && options.processScripts.indexOf(rawValue) > -1) {
1082
+ return await minifyHTML(text, options);
1083
+ }
1040
1084
  }
1041
1085
  }
1042
1086
  return text;
@@ -1916,7 +1960,7 @@ async function minifyHTML(value, options, partialMarkup) {
1916
1960
  text = collapseWhitespace(text, options, false, false, true);
1917
1961
  }
1918
1962
  }
1919
- if (options.processScripts && specialContentTags.has(currentTag)) {
1963
+ if (specialContentTags.has(currentTag) && (options.processScripts || hasJsonScriptType(currentAttrs))) {
1920
1964
  text = await processScript(text, options, currentAttrs);
1921
1965
  }
1922
1966
  if (isExecutableScript(currentTag, currentAttrs)) {
@@ -40085,11 +40085,55 @@ async function cleanConditionalComment(comment, options) {
40085
40085
  : comment;
40086
40086
  }
40087
40087
 
40088
+ const jsonScriptTypes = new Set([
40089
+ 'application/json',
40090
+ 'application/ld+json',
40091
+ 'application/manifest+json',
40092
+ 'application/vnd.geo+json',
40093
+ 'importmap',
40094
+ 'speculationrules',
40095
+ ]);
40096
+
40097
+ function minifyJson(text, options) {
40098
+ try {
40099
+ return JSON.stringify(JSON.parse(text));
40100
+ }
40101
+ catch (err) {
40102
+ if (!options.continueOnMinifyError) {
40103
+ throw err;
40104
+ }
40105
+ options.log && options.log(err);
40106
+ return text;
40107
+ }
40108
+ }
40109
+
40110
+ function hasJsonScriptType(attrs) {
40111
+ for (let i = 0, len = attrs.length; i < len; i++) {
40112
+ const attrName = attrs[i].name.toLowerCase();
40113
+ if (attrName === 'type') {
40114
+ const attrValue = trimWhitespace((attrs[i].value || '').split(/;/, 2)[0]).toLowerCase();
40115
+ if (jsonScriptTypes.has(attrValue)) {
40116
+ return true;
40117
+ }
40118
+ }
40119
+ }
40120
+ return false;
40121
+ }
40122
+
40088
40123
  async function processScript(text, options, currentAttrs) {
40089
40124
  for (let i = 0, len = currentAttrs.length; i < len; i++) {
40090
- if (currentAttrs[i].name.toLowerCase() === 'type' &&
40091
- options.processScripts.indexOf(currentAttrs[i].value) > -1) {
40092
- return await minifyHTML(text, options);
40125
+ const attrName = currentAttrs[i].name.toLowerCase();
40126
+ if (attrName === 'type') {
40127
+ const rawValue = currentAttrs[i].value;
40128
+ const normalizedValue = trimWhitespace((rawValue || '').split(/;/, 2)[0]).toLowerCase();
40129
+ // Minify JSON script types automatically
40130
+ if (jsonScriptTypes.has(normalizedValue)) {
40131
+ return minifyJson(text, options);
40132
+ }
40133
+ // Process custom script types if specified
40134
+ if (options.processScripts && options.processScripts.indexOf(rawValue) > -1) {
40135
+ return await minifyHTML(text, options);
40136
+ }
40093
40137
  }
40094
40138
  }
40095
40139
  return text;
@@ -40969,7 +41013,7 @@ async function minifyHTML(value, options, partialMarkup) {
40969
41013
  text = collapseWhitespace(text, options, false, false, true);
40970
41014
  }
40971
41015
  }
40972
- if (options.processScripts && specialContentTags.has(currentTag)) {
41016
+ if (specialContentTags.has(currentTag) && (options.processScripts || hasJsonScriptType(currentAttrs))) {
40973
41017
  text = await processScript(text, options, currentAttrs);
40974
41018
  }
40975
41019
  if (isExecutableScript(currentTag, currentAttrs)) {
@@ -1 +1 @@
1
- {"version":3,"file":"htmlminifier.d.ts","sourceRoot":"","sources":["../../src/htmlminifier.js"],"names":[],"mappings":"AAu8CO,8BAJI,MAAM,YACN,eAAe,GACb,OAAO,CAAC,MAAM,CAAC,CAQ3B;;;;;;;;;;;;UAUS,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;;wBAhyDkC,cAAc;0BAAd,cAAc;+BAAd,cAAc"}
1
+ {"version":3,"file":"htmlminifier.d.ts","sourceRoot":"","sources":["../../src/htmlminifier.js"],"names":[],"mappings":"AAm/CO,8BAJI,MAAM,YACN,eAAe,GACb,OAAO,CAAC,MAAM,CAAC,CAQ3B;;;;;;;;;;;;UAUS,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;;wBA50DkC,cAAc;0BAAd,cAAc;+BAAd,cAAc"}
package/package.json CHANGED
@@ -84,5 +84,5 @@
84
84
  "test:watch": "node --test --watch tests/*.spec.js"
85
85
  },
86
86
  "type": "module",
87
- "version": "4.5.1"
87
+ "version": "4.6.0"
88
88
  }
@@ -431,11 +431,55 @@ async function cleanConditionalComment(comment, options) {
431
431
  : comment;
432
432
  }
433
433
 
434
+ const jsonScriptTypes = new Set([
435
+ 'application/json',
436
+ 'application/ld+json',
437
+ 'application/manifest+json',
438
+ 'application/vnd.geo+json',
439
+ 'importmap',
440
+ 'speculationrules',
441
+ ]);
442
+
443
+ function minifyJson(text, options) {
444
+ try {
445
+ return JSON.stringify(JSON.parse(text));
446
+ }
447
+ catch (err) {
448
+ if (!options.continueOnMinifyError) {
449
+ throw err;
450
+ }
451
+ options.log && options.log(err);
452
+ return text;
453
+ }
454
+ }
455
+
456
+ function hasJsonScriptType(attrs) {
457
+ for (let i = 0, len = attrs.length; i < len; i++) {
458
+ const attrName = attrs[i].name.toLowerCase();
459
+ if (attrName === 'type') {
460
+ const attrValue = trimWhitespace((attrs[i].value || '').split(/;/, 2)[0]).toLowerCase();
461
+ if (jsonScriptTypes.has(attrValue)) {
462
+ return true;
463
+ }
464
+ }
465
+ }
466
+ return false;
467
+ }
468
+
434
469
  async function processScript(text, options, currentAttrs) {
435
470
  for (let i = 0, len = currentAttrs.length; i < len; i++) {
436
- if (currentAttrs[i].name.toLowerCase() === 'type' &&
437
- options.processScripts.indexOf(currentAttrs[i].value) > -1) {
438
- return await minifyHTML(text, options);
471
+ const attrName = currentAttrs[i].name.toLowerCase();
472
+ if (attrName === 'type') {
473
+ const rawValue = currentAttrs[i].value;
474
+ const normalizedValue = trimWhitespace((rawValue || '').split(/;/, 2)[0]).toLowerCase();
475
+ // Minify JSON script types automatically
476
+ if (jsonScriptTypes.has(normalizedValue)) {
477
+ return minifyJson(text, options);
478
+ }
479
+ // Process custom script types if specified
480
+ if (options.processScripts && options.processScripts.indexOf(rawValue) > -1) {
481
+ return await minifyHTML(text, options);
482
+ }
439
483
  }
440
484
  }
441
485
  return text;
@@ -1315,7 +1359,7 @@ async function minifyHTML(value, options, partialMarkup) {
1315
1359
  text = collapseWhitespace(text, options, false, false, true);
1316
1360
  }
1317
1361
  }
1318
- if (options.processScripts && specialContentTags.has(currentTag)) {
1362
+ if (specialContentTags.has(currentTag) && (options.processScripts || hasJsonScriptType(currentAttrs))) {
1319
1363
  text = await processScript(text, options, currentAttrs);
1320
1364
  }
1321
1365
  if (isExecutableScript(currentTag, currentAttrs)) {