html-minifier-next 6.2.11 → 7.0.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 +19 -21
- package/cli.js +21 -27
- package/dist/types/htmlminifier.d.ts +20 -43
- package/dist/types/htmlminifier.d.ts.map +1 -1
- package/dist/types/lib/attributes.d.ts +19 -12
- package/dist/types/lib/attributes.d.ts.map +1 -1
- package/dist/types/lib/content.d.ts +8 -10
- package/dist/types/lib/content.d.ts.map +1 -1
- package/dist/types/lib/elements.d.ts +6 -11
- package/dist/types/lib/elements.d.ts.map +1 -1
- package/dist/types/lib/option-definitions.d.ts +11 -17
- package/dist/types/lib/options.d.ts +50 -6
- package/dist/types/lib/options.d.ts.map +1 -1
- package/dist/types/lib/utils.d.ts +5 -2
- package/dist/types/lib/utils.d.ts.map +1 -1
- package/dist/types/presets.d.ts +3 -6
- package/dist/types/presets.d.ts.map +1 -1
- package/package.json +11 -18
- package/src/htmlminifier.js +65 -66
- package/src/htmlparser.js +1 -1
- package/src/lib/attributes.js +15 -14
- package/src/lib/content.js +5 -3
- package/src/lib/elements.js +3 -8
- package/src/lib/option-definitions.js +4 -8
- package/src/lib/options.js +67 -22
- package/src/lib/utils.js +4 -1
- package/src/lib/whitespace.js +1 -1
- package/src/presets.js +2 -4
- package/dist/htmlminifier.cjs +0 -5142
package/src/lib/attributes.js
CHANGED
|
@@ -19,6 +19,8 @@ import { trimWhitespace, collapseWhitespaceAll } from './whitespace.js';
|
|
|
19
19
|
import { shouldMinifyInnerHTML } from './options.js';
|
|
20
20
|
import { identity, isThenable } from './utils.js';
|
|
21
21
|
|
|
22
|
+
/** @import { ProcessedOptions } from './options.js' */
|
|
23
|
+
|
|
22
24
|
// Type definitions
|
|
23
25
|
|
|
24
26
|
/**
|
|
@@ -41,11 +43,9 @@ async function getDecodeHTMLStrict() {
|
|
|
41
43
|
|
|
42
44
|
/**
|
|
43
45
|
* @param {string} text
|
|
44
|
-
* @param {
|
|
46
|
+
* @param {ProcessedOptions} options
|
|
45
47
|
*/
|
|
46
48
|
function isIgnoredComment(text, options) {
|
|
47
|
-
// @@ Optimize: `Array.isArray(options.ignoreCustomComments)` runs on every comment node; it could be eliminated once `parseRegExpArray` is tightened to coerce non-arrays to `[]` at setup time
|
|
48
|
-
if (!Array.isArray(options.ignoreCustomComments)) return false;
|
|
49
49
|
for (const pattern of options.ignoreCustomComments) {
|
|
50
50
|
if (pattern.test(text)) {
|
|
51
51
|
return true;
|
|
@@ -380,7 +380,7 @@ const valueWhitespaceExemptElements = new Set(['button', 'data', 'input', 'optio
|
|
|
380
380
|
* @param {string} tag
|
|
381
381
|
* @param {string} attrName
|
|
382
382
|
* @param {string} attrValue
|
|
383
|
-
* @param {
|
|
383
|
+
* @param {ProcessedOptions} options
|
|
384
384
|
* @param {HTMLAttribute[]} attrs
|
|
385
385
|
* @param {Function} minifyHTMLSelf
|
|
386
386
|
*/
|
|
@@ -432,7 +432,8 @@ function cleanAttributeValue(tag, attrName, attrValue, options, attrs, minifyHTM
|
|
|
432
432
|
if (attrName === 'class') {
|
|
433
433
|
attrValue = trimWhitespace(attrValue);
|
|
434
434
|
if (options.sortClassNames) {
|
|
435
|
-
|
|
435
|
+
// By the time attributes are processed, `createSortFns` has replaced any truthy non-function value
|
|
436
|
+
attrValue = /** @type {(value: string) => string} */ (options.sortClassNames)(attrValue);
|
|
436
437
|
} else {
|
|
437
438
|
attrValue = collapseWhitespaceAll(attrValue);
|
|
438
439
|
}
|
|
@@ -602,7 +603,7 @@ function chooseAttributeQuote(attrValue, options) {
|
|
|
602
603
|
* @param {HTMLAttribute} attr
|
|
603
604
|
* @param {HTMLAttribute[]} attrs
|
|
604
605
|
* @param {string} tag
|
|
605
|
-
* @param {
|
|
606
|
+
* @param {ProcessedOptions} options
|
|
606
607
|
* @param {Function} minifyHTML
|
|
607
608
|
*/
|
|
608
609
|
function normalizeAttr(attr, attrs, tag, options, minifyHTML) {
|
|
@@ -626,16 +627,16 @@ function normalizeAttr(attr, attrs, tag, options, minifyHTML) {
|
|
|
626
627
|
* @param {HTMLAttribute} attr
|
|
627
628
|
* @param {HTMLAttribute[]} attrs
|
|
628
629
|
* @param {string} tag
|
|
629
|
-
* @param {
|
|
630
|
+
* @param {ProcessedOptions} options
|
|
630
631
|
* @param {Function} minifyHTML
|
|
631
632
|
*/
|
|
632
633
|
function normalizeAttrContinue(attrName, attrValue, attr, attrs, tag, options, minifyHTML) {
|
|
633
634
|
if ((options.removeRedundantAttributes &&
|
|
634
635
|
isAttributeRedundant(tag, attrName, attrValue ?? '', attrs)) ||
|
|
635
|
-
(options.
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
636
|
+
(options.removeDefaultTypeAttributes && attrName === 'type' && (
|
|
637
|
+
((tag === 'style' || tag === 'link') && isStyleLinkTypeAttribute(attrValue)) ||
|
|
638
|
+
(tag === 'script' && isScriptTypeAttribute(attrValue) && !keepScriptTypeAttribute(attrValue))
|
|
639
|
+
))) {
|
|
639
640
|
return;
|
|
640
641
|
}
|
|
641
642
|
|
|
@@ -656,7 +657,7 @@ function normalizeAttrContinue(attrName, attrValue, attr, attrs, tag, options, m
|
|
|
656
657
|
* @param {string | undefined} attrValue
|
|
657
658
|
* @param {HTMLAttribute} attr
|
|
658
659
|
* @param {string} tag
|
|
659
|
-
* @param {
|
|
660
|
+
* @param {ProcessedOptions} options
|
|
660
661
|
*/
|
|
661
662
|
function normalizeAttrFinish(attrName, attrValue, attr, tag, options) {
|
|
662
663
|
if (options.removeEmptyAttributes &&
|
|
@@ -676,9 +677,9 @@ function normalizeAttrFinish(attrName, attrValue, attr, tag, options) {
|
|
|
676
677
|
}
|
|
677
678
|
|
|
678
679
|
/**
|
|
679
|
-
* @param {{name: string, value
|
|
680
|
+
* @param {{name: string, value: string | undefined, attr: HTMLAttribute}} normalized
|
|
680
681
|
* @param {string | boolean | undefined} hasUnarySlash
|
|
681
|
-
* @param {
|
|
682
|
+
* @param {ProcessedOptions} options
|
|
682
683
|
* @param {boolean} isLast
|
|
683
684
|
* @param {string | undefined} uidAttr
|
|
684
685
|
*/
|
package/src/lib/content.js
CHANGED
|
@@ -3,13 +3,15 @@ import {
|
|
|
3
3
|
} from './constants.js';
|
|
4
4
|
import { trimWhitespace } from './whitespace.js';
|
|
5
5
|
|
|
6
|
+
/** @import { ProcessedOptions } from './options.js' */
|
|
7
|
+
|
|
6
8
|
// CSS processing
|
|
7
9
|
|
|
8
10
|
// Wrap CSS declarations for inline styles and media queries
|
|
9
11
|
// This ensures proper context for CSS minification
|
|
10
12
|
/**
|
|
11
13
|
* @param {string} text
|
|
12
|
-
* @param {string} type
|
|
14
|
+
* @param {string} [type]
|
|
13
15
|
*/
|
|
14
16
|
function wrapCSS(text, type) {
|
|
15
17
|
switch (type) {
|
|
@@ -24,7 +26,7 @@ function wrapCSS(text, type) {
|
|
|
24
26
|
|
|
25
27
|
/**
|
|
26
28
|
* @param {string} text
|
|
27
|
-
* @param {string} type
|
|
29
|
+
* @param {string} [type]
|
|
28
30
|
*/
|
|
29
31
|
function unwrapCSS(text, type) {
|
|
30
32
|
let matches;
|
|
@@ -73,7 +75,7 @@ function hasJsonScriptType(attrs) {
|
|
|
73
75
|
|
|
74
76
|
/**
|
|
75
77
|
* @param {string} text
|
|
76
|
-
* @param {
|
|
78
|
+
* @param {ProcessedOptions} options
|
|
77
79
|
* @param {Array<{name: string, value?: string | undefined}>} currentAttrs
|
|
78
80
|
* @param {Function} minifyHTML
|
|
79
81
|
*/
|
package/src/lib/elements.js
CHANGED
|
@@ -12,12 +12,7 @@ import {
|
|
|
12
12
|
import { hasAttrName } from './attributes.js';
|
|
13
13
|
|
|
14
14
|
/** @import { HTMLAttribute } from './attributes.js' */
|
|
15
|
-
|
|
16
|
-
// Type definitions
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* @typedef {{ name: (str: string) => string, log?: Function }} MinifierOptions
|
|
20
|
-
*/
|
|
15
|
+
/** @import { ProcessedOptions } from './options.js' */
|
|
21
16
|
|
|
22
17
|
// Tag omission rules
|
|
23
18
|
|
|
@@ -143,7 +138,7 @@ function canRemoveElement(tag, attrs) {
|
|
|
143
138
|
|
|
144
139
|
/**
|
|
145
140
|
* @param {string} str - Tag name or HTML-like element spec (e.g., “td” or “<span aria-hidden='true'>”)
|
|
146
|
-
* @param {
|
|
141
|
+
* @param {ProcessedOptions} options - Options object for name normalization
|
|
147
142
|
* @returns {{tag: string, attrs: Object.<string, string|undefined>|null}|null} Parsed spec or null if invalid
|
|
148
143
|
*/
|
|
149
144
|
function parseElementSpec(str, options) {
|
|
@@ -196,7 +191,7 @@ function parseElementSpec(str, options) {
|
|
|
196
191
|
|
|
197
192
|
/**
|
|
198
193
|
* @param {string[]} input - Array of element specifications from `removeEmptyElementsExcept` option
|
|
199
|
-
* @param {
|
|
194
|
+
* @param {ProcessedOptions} options - Options object for parsing
|
|
200
195
|
* @returns {Array<{tag: string, attrs: Object.<string, string|undefined>|null}>} Array of parsed element specs
|
|
201
196
|
*/
|
|
202
197
|
function parseRemoveEmptyElementsExcept(input, options) {
|
|
@@ -138,6 +138,10 @@ const optionDefinitions = {
|
|
|
138
138
|
description: 'Strip HTML comments',
|
|
139
139
|
type: 'boolean'
|
|
140
140
|
},
|
|
141
|
+
removeDefaultTypeAttributes: {
|
|
142
|
+
description: 'Remove default `type` attributes from `style`/`link` (e.g., `type="text/css"`) and `script` (e.g., `type="text/javascript"`) elements; other `type` attribute values are left intact',
|
|
143
|
+
type: 'boolean'
|
|
144
|
+
},
|
|
141
145
|
removeEmptyAttributes: {
|
|
142
146
|
description: 'Remove all attributes with whitespace-only values',
|
|
143
147
|
type: 'boolean'
|
|
@@ -158,14 +162,6 @@ const optionDefinitions = {
|
|
|
158
162
|
description: 'Remove attributes when value matches default',
|
|
159
163
|
type: 'boolean'
|
|
160
164
|
},
|
|
161
|
-
removeScriptTypeAttributes: {
|
|
162
|
-
description: 'Remove `type="text/javascript"` from `script` elements; other `type` attribute values are left intact',
|
|
163
|
-
type: 'boolean'
|
|
164
|
-
},
|
|
165
|
-
removeStyleLinkTypeAttributes: {
|
|
166
|
-
description: 'Remove `type="text/css"` from `style` and `link` elements; other `type` attribute values are left intact',
|
|
167
|
-
type: 'boolean'
|
|
168
|
-
},
|
|
169
165
|
removeTagWhitespace: {
|
|
170
166
|
description: 'Remove space between attributes whenever possible; note that this will result in invalid HTML',
|
|
171
167
|
type: 'boolean'
|
package/src/lib/options.js
CHANGED
|
@@ -4,19 +4,39 @@ import { RE_TRAILING_SEMICOLON } from './constants.js';
|
|
|
4
4
|
import { canCollapseWhitespace, canTrimWhitespace } from './whitespace.js';
|
|
5
5
|
import { wrapCSS, unwrapCSS } from './content.js';
|
|
6
6
|
import { getPreset, getPresetNames } from '../presets.js';
|
|
7
|
-
import { optionDefaults } from './option-definitions.js';
|
|
7
|
+
import { optionDefinitions, optionDefaults } from './option-definitions.js';
|
|
8
|
+
|
|
9
|
+
/** @import { MinifierOptions, HTMLAttribute } from '../htmlminifier.js' */
|
|
8
10
|
|
|
9
11
|
// Type definitions
|
|
10
12
|
|
|
11
13
|
/**
|
|
12
|
-
*
|
|
14
|
+
* Options object produced by `processOptions` and consumed by `minifyHTML` and
|
|
15
|
+
* the `lib/` helpers; normalization guarantees that the function-valued options
|
|
16
|
+
* below are always present (defaulting to identity/built-in functions), and
|
|
17
|
+
* minification adds writable internal state on top of the public options
|
|
18
|
+
* (set on prototype-chain forks during SVG/MathML namespace transitions)
|
|
19
|
+
*
|
|
20
|
+
* @typedef {Omit<MinifierOptions, 'preset' | 'canCollapseWhitespace' | 'canTrimWhitespace' | 'ignoreCustomComments' | 'log' | 'minifyCSS' | 'minifyJS' | 'minifyURLs' | 'minifySVG'> & {
|
|
21
|
+
* name: (name: string) => string,
|
|
22
|
+
* log: (message: any) => unknown,
|
|
23
|
+
* ignoreCustomComments: RegExp[],
|
|
24
|
+
* canCollapseWhitespace: (tag: string, attrs: HTMLAttribute[], defaultFn: (tag: string) => boolean) => boolean,
|
|
25
|
+
* canTrimWhitespace: (tag: string, attrs: HTMLAttribute[], defaultFn: (tag: string) => boolean) => boolean,
|
|
26
|
+
* minifyCSS: (text: string, type?: string) => string | Promise<string>,
|
|
27
|
+
* minifyJS: (text: string, inline?: boolean, isModule?: boolean) => string | Promise<string>,
|
|
28
|
+
* minifyURLs: (text: string) => string | Promise<string>,
|
|
29
|
+
* minifySVG: ((svgContent: string) => string | Promise<string>) | null,
|
|
30
|
+
* nameParent?: (name: string) => string,
|
|
31
|
+
* nameHTML?: (name: string) => string,
|
|
32
|
+
* insideSVG?: boolean,
|
|
33
|
+
* insideForeignContent?: boolean
|
|
34
|
+
* }} ProcessedOptions
|
|
13
35
|
*/
|
|
14
36
|
|
|
15
|
-
// @@ Extract a `ProcessedOptions` typedef (with `name`, `log`, `canCollapseWhitespace`, `canTrimWhitespace`,`minifyCSS`, `minifyJS`, `minifyURLs` typed as required, non-optional) to replace the current `Record<string, any>` escape hatch and eliminate the `/** @type {Function} */` casts in htmlminifier.js
|
|
16
|
-
|
|
17
37
|
// Helper functions
|
|
18
38
|
|
|
19
|
-
/** @param {
|
|
39
|
+
/** @param {ProcessedOptions} options */
|
|
20
40
|
function shouldMinifyInnerHTML(options) {
|
|
21
41
|
return Boolean(
|
|
22
42
|
options.collapseWhitespace ||
|
|
@@ -29,15 +49,23 @@ function shouldMinifyInnerHTML(options) {
|
|
|
29
49
|
);
|
|
30
50
|
}
|
|
31
51
|
|
|
52
|
+
// User-facing option keys that are valid but not listed in `optionDefinitions`
|
|
53
|
+
const optionKeysExtra = new Set(['preset', 'log', 'canCollapseWhitespace', 'canTrimWhitespace', 'cacheCSS', 'cacheJS', 'cacheSVG']);
|
|
54
|
+
|
|
55
|
+
// Unknown option keys and preset names already warned about—warn once per
|
|
56
|
+
// key per process, so repeated `minify` calls (e.g., batch runs) don’t flood STDERR
|
|
57
|
+
const optionKeysWarned = new Set();
|
|
58
|
+
const presetNamesWarned = new Set();
|
|
59
|
+
|
|
32
60
|
// Main options processor
|
|
33
61
|
|
|
34
62
|
/**
|
|
35
63
|
* @param {MinifierOptions} inputOptions - User-provided options
|
|
36
64
|
* @param {{getLightningCSS?: Function | undefined, getTerser?: Function | undefined, getSwc?: Function | undefined, getSvgo?: Function | undefined, cssMinifyCache?: LRU | undefined, jsMinifyCache?: LRU | undefined, svgMinifyCache?: LRU | undefined}} [deps] - Dependencies from htmlminifier.js
|
|
37
|
-
* @returns {
|
|
65
|
+
* @returns {ProcessedOptions} Normalized options with defaults applied
|
|
38
66
|
*/
|
|
39
67
|
const processOptions = (inputOptions, { getLightningCSS, getTerser, getSwc, getSvgo, cssMinifyCache, jsMinifyCache, svgMinifyCache } = {}) => {
|
|
40
|
-
/** @type {
|
|
68
|
+
/** @type {ProcessedOptions} */
|
|
41
69
|
const options = {
|
|
42
70
|
name: lowercase,
|
|
43
71
|
canCollapseWhitespace,
|
|
@@ -67,6 +95,18 @@ const processOptions = (inputOptions, { getLightningCSS, getTerser, getSwc, getS
|
|
|
67
95
|
});
|
|
68
96
|
};
|
|
69
97
|
|
|
98
|
+
// Route warnings through the user-provided `log` hook so API consumers can
|
|
99
|
+
// capture or suppress them consistently; fall back to `console.warn`
|
|
100
|
+
const warn = typeof inputOptions.log === 'function' ? inputOptions.log : console.warn;
|
|
101
|
+
|
|
102
|
+
// Warn about unrecognized options—catches typos as well as options removed in earlier versions
|
|
103
|
+
Object.keys(inputOptions).forEach(function (key) {
|
|
104
|
+
if (!Object.hasOwn(optionDefinitions, key) && !optionKeysExtra.has(key) && !optionKeysWarned.has(key)) {
|
|
105
|
+
optionKeysWarned.add(key);
|
|
106
|
+
warn(`HTML Minifier Next: Ignoring unknown or deprecated option “${key}” (see README for available options)`);
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
|
|
70
110
|
// Merge preset with user options so all values go through normalization
|
|
71
111
|
// User options take precedence over preset values
|
|
72
112
|
let effectiveInput = inputOptions;
|
|
@@ -74,17 +114,22 @@ const processOptions = (inputOptions, { getLightningCSS, getTerser, getSwc, getS
|
|
|
74
114
|
const preset = getPreset(inputOptions.preset);
|
|
75
115
|
if (preset) {
|
|
76
116
|
effectiveInput = { ...preset, ...inputOptions };
|
|
77
|
-
} else {
|
|
117
|
+
} else if (!presetNamesWarned.has(inputOptions.preset)) {
|
|
118
|
+
presetNamesWarned.add(inputOptions.preset);
|
|
78
119
|
const available = getPresetNames().join(', ');
|
|
79
|
-
|
|
120
|
+
warn(`HTML Minifier Next: Unknown preset “${inputOptions.preset}”; available presets: ${available}`);
|
|
80
121
|
}
|
|
81
122
|
}
|
|
82
123
|
|
|
124
|
+
// Escape hatch for the loop below, which reads and assigns user-provided values by dynamic key
|
|
125
|
+
const optionsDynamic = /** @type {Record<string, any>} */ (options);
|
|
126
|
+
|
|
83
127
|
Object.keys(effectiveInput).forEach(function (key) {
|
|
84
|
-
const option = effectiveInput[key];
|
|
128
|
+
const option = /** @type {Record<string, any>} */ (effectiveInput)[key];
|
|
85
129
|
|
|
86
|
-
// Skip preset
|
|
87
|
-
|
|
130
|
+
// Skip `preset` (already processed) and unrecognized keys (warned about above)—
|
|
131
|
+
// the latter also keeps internal keys from being overridden
|
|
132
|
+
if (key === 'preset' || (!Object.hasOwn(optionDefinitions, key) && !optionKeysExtra.has(key))) {
|
|
88
133
|
return;
|
|
89
134
|
}
|
|
90
135
|
|
|
@@ -106,7 +151,7 @@ const processOptions = (inputOptions, { getLightningCSS, getTerser, getSwc, getS
|
|
|
106
151
|
const cssLoader = getLightningCSS;
|
|
107
152
|
const cssCache = cssMinifyCache;
|
|
108
153
|
|
|
109
|
-
options.minifyCSS = async function (/** @type {string} */ text, /** @type {string} */ type) {
|
|
154
|
+
options.minifyCSS = async function (/** @type {string} */ text, /** @type {string | undefined} */ type) {
|
|
110
155
|
// Fast path: Nothing to minify
|
|
111
156
|
if (!text || !text.trim()) {
|
|
112
157
|
return text;
|
|
@@ -143,7 +188,7 @@ const processOptions = (inputOptions, { getLightningCSS, getTerser, getSwc, getS
|
|
|
143
188
|
: (inputCSS + '|' + type + '|' + cssSig);
|
|
144
189
|
|
|
145
190
|
try {
|
|
146
|
-
const cached = cssCache.get(cssKey);
|
|
191
|
+
const cached = /** @type {string | Promise<string> | undefined} */ (cssCache.get(cssKey));
|
|
147
192
|
if (cached !== undefined) {
|
|
148
193
|
// Support both resolved values and in-flight promises
|
|
149
194
|
return await cached;
|
|
@@ -236,7 +281,7 @@ const processOptions = (inputOptions, { getLightningCSS, getTerser, getSwc, getS
|
|
|
236
281
|
cont: !!options.continueOnMinifyError
|
|
237
282
|
});
|
|
238
283
|
|
|
239
|
-
options.minifyJS = async function (/** @type {string} */ text, /** @type {boolean} */ inline, /** @type {boolean} */ isModule) {
|
|
284
|
+
options.minifyJS = async function (/** @type {string} */ text, /** @type {boolean | undefined} */ inline, /** @type {boolean | undefined} */ isModule) {
|
|
240
285
|
const start = text.match(/^\s*<!--.*/);
|
|
241
286
|
const code = start ? text.slice(start[0].length).replace(/\n\s*-->\s*$/, '') : text;
|
|
242
287
|
|
|
@@ -258,7 +303,7 @@ const processOptions = (inputOptions, { getLightningCSS, getTerser, getSwc, getS
|
|
|
258
303
|
jsKey = (code.length > 2048 ? (hashContent(code) + '|') : (code + '|'))
|
|
259
304
|
+ (inline ? '1' : '0') + '|' + (isModule ? 'm' : '') + '|' + useEngine + '|' + optsSig;
|
|
260
305
|
|
|
261
|
-
const cached = jsCache.get(jsKey);
|
|
306
|
+
const cached = /** @type {string | Promise<string> | undefined} */ (jsCache.get(jsKey));
|
|
262
307
|
if (cached !== undefined) {
|
|
263
308
|
return await cached;
|
|
264
309
|
}
|
|
@@ -331,7 +376,7 @@ const processOptions = (inputOptions, { getLightningCSS, getTerser, getSwc, getS
|
|
|
331
376
|
}
|
|
332
377
|
|
|
333
378
|
// Check cache
|
|
334
|
-
const cached = instanceCache.get(text);
|
|
379
|
+
const cached = /** @type {string | undefined} */ (instanceCache.get(text));
|
|
335
380
|
if (cached !== undefined) {
|
|
336
381
|
return cached;
|
|
337
382
|
}
|
|
@@ -377,7 +422,7 @@ const processOptions = (inputOptions, { getLightningCSS, getTerser, getSwc, getS
|
|
|
377
422
|
: (svgContent + '|' + svgSig);
|
|
378
423
|
|
|
379
424
|
try {
|
|
380
|
-
const cached = svgCache.get(svgKey);
|
|
425
|
+
const cached = /** @type {string | Promise<string> | undefined} */ (svgCache.get(svgKey));
|
|
381
426
|
if (cached !== undefined) {
|
|
382
427
|
return await cached;
|
|
383
428
|
}
|
|
@@ -403,15 +448,15 @@ const processOptions = (inputOptions, { getLightningCSS, getTerser, getSwc, getS
|
|
|
403
448
|
};
|
|
404
449
|
} else if (key === 'customAttrCollapse') {
|
|
405
450
|
// Single regex pattern
|
|
406
|
-
|
|
451
|
+
optionsDynamic[key] = parseRegExp(option);
|
|
407
452
|
} else if (key === 'customAttrSurround') {
|
|
408
453
|
// Nested array of RegExp pairs: `[[openRegExp, closeRegExp], …]`
|
|
409
|
-
|
|
454
|
+
optionsDynamic[key] = parseNestedRegExpArray(option);
|
|
410
455
|
} else if (['customAttrAssign', 'customEventAttributes', 'ignoreCustomComments', 'ignoreCustomFragments'].includes(key)) {
|
|
411
456
|
// Array of regex patterns
|
|
412
|
-
|
|
457
|
+
optionsDynamic[key] = parseRegExpArray(option);
|
|
413
458
|
} else {
|
|
414
|
-
|
|
459
|
+
optionsDynamic[key] = option;
|
|
415
460
|
}
|
|
416
461
|
});
|
|
417
462
|
return options;
|
package/src/lib/utils.js
CHANGED
|
@@ -80,7 +80,10 @@ function identity(value) {
|
|
|
80
80
|
return value;
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
/**
|
|
83
|
+
/**
|
|
84
|
+
* @param {unknown} value
|
|
85
|
+
* @returns {value is PromiseLike<any>}
|
|
86
|
+
*/
|
|
84
87
|
function isThenable(value) {
|
|
85
88
|
return value != null && typeof value === 'object' && typeof /** @type {any} */ (value).then === 'function';
|
|
86
89
|
}
|
package/src/lib/whitespace.js
CHANGED
|
@@ -39,7 +39,7 @@ function collapseWhitespaceAll(str) {
|
|
|
39
39
|
// Fast path: No no-break space, common case—just collapse to single space
|
|
40
40
|
// This avoids the nested regex for the majority of cases
|
|
41
41
|
if (spaces.indexOf('\xA0') === -1) return ' ';
|
|
42
|
-
// For no-break space handling, use the
|
|
42
|
+
// For no-break space handling, use the nested regex
|
|
43
43
|
return spaces.replace(RE_NBSP_LEADING_GROUP, '$1 ');
|
|
44
44
|
});
|
|
45
45
|
}
|
package/src/presets.js
CHANGED
|
@@ -14,8 +14,7 @@ export const presets = {
|
|
|
14
14
|
conservativeCollapse: true,
|
|
15
15
|
preserveLineBreaks: true,
|
|
16
16
|
removeComments: true,
|
|
17
|
-
|
|
18
|
-
removeStyleLinkTypeAttributes: true,
|
|
17
|
+
removeDefaultTypeAttributes: true,
|
|
19
18
|
useShortDoctype: true
|
|
20
19
|
},
|
|
21
20
|
comprehensive: {
|
|
@@ -30,11 +29,10 @@ export const presets = {
|
|
|
30
29
|
minifyURLs: true,
|
|
31
30
|
removeAttributeQuotes: true,
|
|
32
31
|
removeComments: true,
|
|
32
|
+
removeDefaultTypeAttributes: true,
|
|
33
33
|
removeEmptyAttributes: true,
|
|
34
34
|
removeOptionalTags: true,
|
|
35
35
|
removeRedundantAttributes: true,
|
|
36
|
-
removeScriptTypeAttributes: true,
|
|
37
|
-
removeStyleLinkTypeAttributes: true,
|
|
38
36
|
useShortDoctype: true
|
|
39
37
|
}
|
|
40
38
|
};
|