@depup/html-minifier-terser 7.2.0-depup.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 ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2010-2019 Juriy "kangax" Zaytsev
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,36 @@
1
+ # @depup/html-minifier-terser
2
+
3
+ > Dependency-bumped version of [html-minifier-terser](https://www.npmjs.com/package/html-minifier-terser)
4
+
5
+ Generated by [DepUp](https://github.com/depup/npm) -- all production
6
+ dependencies bumped to latest versions.
7
+
8
+ ## Installation
9
+
10
+ ```bash
11
+ npm install @depup/html-minifier-terser
12
+ ```
13
+
14
+ | Field | Value |
15
+ |-------|-------|
16
+ | Original | [html-minifier-terser](https://www.npmjs.com/package/html-minifier-terser) @ 7.2.0 |
17
+ | Processed | 2026-03-19 |
18
+ | Smoke test | passed |
19
+ | Deps updated | 6 |
20
+
21
+ ## Dependency Changes
22
+
23
+ | Dependency | From | To |
24
+ |------------|------|-----|
25
+ | camel-case | ^4.1.2 | ^5.0.0 |
26
+ | clean-css | ~5.3.2 | ^5.3.3 |
27
+ | commander | ^10.0.0 | ^14.0.3 |
28
+ | entities | ^4.4.0 | ^8.0.0 |
29
+ | param-case | ^3.0.4 | ^4.0.0 |
30
+ | terser | ^5.15.1 | ^5.46.1 |
31
+
32
+ ---
33
+
34
+ Source: https://github.com/depup/npm | Original: https://www.npmjs.com/package/html-minifier-terser
35
+
36
+ License inherited from the original package.
package/changes.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "bumped": {
3
+ "camel-case": {
4
+ "from": "^4.1.2",
5
+ "to": "^5.0.0"
6
+ },
7
+ "clean-css": {
8
+ "from": "~5.3.2",
9
+ "to": "^5.3.3"
10
+ },
11
+ "commander": {
12
+ "from": "^10.0.0",
13
+ "to": "^14.0.3"
14
+ },
15
+ "entities": {
16
+ "from": "^4.4.0",
17
+ "to": "^8.0.0"
18
+ },
19
+ "param-case": {
20
+ "from": "^3.0.4",
21
+ "to": "^4.0.0"
22
+ },
23
+ "terser": {
24
+ "from": "^5.15.1",
25
+ "to": "^5.46.1"
26
+ }
27
+ },
28
+ "timestamp": "2026-03-19T03:28:27.770Z",
29
+ "totalUpdated": 6
30
+ }
package/cli.js ADDED
@@ -0,0 +1,308 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * html-minifier-terser CLI tool
4
+ *
5
+ * The MIT License (MIT)
6
+ *
7
+ * Copyright (c) 2014-2016 Zoltan Frombach
8
+ *
9
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
10
+ * this software and associated documentation files (the "Software"), to deal in
11
+ * the Software without restriction, including without limitation the rights to
12
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
13
+ * the Software, and to permit persons to whom the Software is furnished to do so,
14
+ * subject to the following conditions:
15
+ *
16
+ * The above copyright notice and this permission notice shall be included in all
17
+ * copies or substantial portions of the Software.
18
+ *
19
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
21
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
22
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
23
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
+ *
26
+ */
27
+
28
+ import fs from 'fs';
29
+ import path from 'path';
30
+ import { createRequire } from 'module';
31
+ import { camelCase } from 'camel-case';
32
+ import { paramCase } from 'param-case';
33
+ import { Command } from 'commander';
34
+ import { minify } from './src/htmlminifier.js';
35
+
36
+ const require = createRequire(import.meta.url);
37
+
38
+ const pkg = require('./package.json');
39
+
40
+ const program = new Command();
41
+ program.name(pkg.name);
42
+ program.version(pkg.version);
43
+
44
+ function fatal(message) {
45
+ console.error(message);
46
+ process.exit(1);
47
+ }
48
+
49
+ /**
50
+ * JSON does not support regexes, so, e.g., JSON.parse() will not create
51
+ * a RegExp from the JSON value `[ "/matchString/" ]`, which is
52
+ * technically just an array containing a string that begins and end with
53
+ * a forward slash. To get a RegExp from a JSON string, it must be
54
+ * constructed explicitly in JavaScript.
55
+ *
56
+ * The likelihood of actually wanting to match text that is enclosed in
57
+ * forward slashes is probably quite rare, so if forward slashes were
58
+ * included in an argument that requires a regex, the user most likely
59
+ * thought they were part of the syntax for specifying a regex.
60
+ *
61
+ * In the unlikely case that forward slashes are indeed desired in the
62
+ * search string, the user would need to enclose the expression in a
63
+ * second set of slashes:
64
+ *
65
+ * --customAttrSrround "[\"//matchString//\"]"
66
+ */
67
+ function parseRegExp(value) {
68
+ if (value) {
69
+ return new RegExp(value.replace(/^\/(.*)\/$/, '$1'));
70
+ }
71
+ }
72
+
73
+ function parseJSON(value) {
74
+ if (value) {
75
+ try {
76
+ return JSON.parse(value);
77
+ } catch (e) {
78
+ if (/^{/.test(value)) {
79
+ fatal('Could not parse JSON value \'' + value + '\'');
80
+ }
81
+ return value;
82
+ }
83
+ }
84
+ }
85
+
86
+ function parseJSONArray(value) {
87
+ if (value) {
88
+ value = parseJSON(value);
89
+ return Array.isArray(value) ? value : [value];
90
+ }
91
+ }
92
+
93
+ function parseJSONRegExpArray(value) {
94
+ value = parseJSONArray(value);
95
+ return value && value.map(parseRegExp);
96
+ }
97
+
98
+ function parseString(value) {
99
+ return value;
100
+ }
101
+
102
+ const mainOptions = {
103
+ caseSensitive: 'Treat attributes in case sensitive manner (useful for SVG; e.g. viewBox)',
104
+ collapseBooleanAttributes: 'Omit attribute values from boolean attributes',
105
+ collapseInlineTagWhitespace: 'Collapse white space around inline tag',
106
+ collapseWhitespace: 'Collapse white space that contributes to text nodes in a document tree.',
107
+ conservativeCollapse: 'Always collapse to 1 space (never remove it entirely)',
108
+ continueOnParseError: 'Handle parse errors instead of aborting',
109
+ customAttrAssign: ['Arrays of regex\'es that allow to support custom attribute assign expressions (e.g. \'<div flex?="{{mode != cover}}"></div>\')', parseJSONRegExpArray],
110
+ customAttrCollapse: ['Regex that specifies custom attribute to strip newlines from (e.g. /ng-class/)', parseRegExp],
111
+ customAttrSurround: ['Arrays of regex\'es that allow to support custom attribute surround expressions (e.g. <input {{#if value}}checked="checked"{{/if}}>)', parseJSONRegExpArray],
112
+ customEventAttributes: ['Arrays of regex\'es that allow to support custom event attributes for minifyJS (e.g. ng-click)', parseJSONRegExpArray],
113
+ decodeEntities: 'Use direct Unicode characters whenever possible',
114
+ html5: 'Parse input according to HTML5 specifications',
115
+ ignoreCustomComments: ['Array of regex\'es that allow to ignore certain comments, when matched', parseJSONRegExpArray],
116
+ ignoreCustomFragments: ['Array of regex\'es that allow to ignore certain fragments, when matched (e.g. <?php ... ?>, {{ ... }})', parseJSONRegExpArray],
117
+ includeAutoGeneratedTags: 'Insert tags generated by HTML parser',
118
+ keepClosingSlash: 'Keep the trailing slash on singleton elements',
119
+ maxLineLength: ['Max line length', parseInt],
120
+ minifyCSS: ['Minify CSS in style elements and style attributes (uses clean-css)', parseJSON],
121
+ minifyJS: ['Minify Javascript in script elements and on* attributes (uses terser)', parseJSON],
122
+ minifyURLs: ['Minify URLs in various attributes (uses relateurl)', parseJSON],
123
+ noNewlinesBeforeTagClose: 'Never add a newline before a tag that closes an element',
124
+ preserveLineBreaks: 'Always collapse to 1 line break (never remove it entirely) when whitespace between tags include a line break.',
125
+ preventAttributesEscaping: 'Prevents the escaping of the values of attributes.',
126
+ processConditionalComments: 'Process contents of conditional comments through minifier',
127
+ 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],
128
+ quoteCharacter: ['Type of quote to use for attribute values (\' or ")', parseString],
129
+ removeAttributeQuotes: 'Remove quotes around attributes when possible.',
130
+ removeComments: 'Strip HTML comments',
131
+ removeEmptyAttributes: 'Remove all attributes with whitespace-only values',
132
+ removeEmptyElements: 'Remove all elements with empty contents',
133
+ removeOptionalTags: 'Remove unrequired tags',
134
+ removeRedundantAttributes: 'Remove attributes when value matches default.',
135
+ removeScriptTypeAttributes: 'Removes the following attributes from script tags: text/javascript, text/ecmascript, text/jscript, application/javascript, application/x-javascript, application/ecmascript. Other type attribute values are left intact',
136
+ removeStyleLinkTypeAttributes: 'Remove type="text/css" from style and link tags. Other type attribute values are left intact.',
137
+ removeTagWhitespace: 'Remove space between attributes whenever possible',
138
+ sortAttributes: 'Sort attributes by frequency',
139
+ sortClassName: 'Sort style classes by frequency',
140
+ trimCustomFragments: 'Trim white space around ignoreCustomFragments.',
141
+ useShortDoctype: 'Replaces the doctype with the short (HTML5) doctype'
142
+ };
143
+
144
+ // configure commandline flags
145
+ const mainOptionKeys = Object.keys(mainOptions);
146
+ mainOptionKeys.forEach(function (key) {
147
+ const option = mainOptions[key];
148
+ if (Array.isArray(option)) {
149
+ key = key === 'minifyURLs' ? '--minify-urls' : '--' + paramCase(key);
150
+ key += option[1] === parseJSON ? ' [value]' : ' <value>';
151
+ program.option(key, option[0], option[1]);
152
+ } else if (~['html5', 'includeAutoGeneratedTags'].indexOf(key)) {
153
+ program.option('--no-' + paramCase(key), option);
154
+ } else {
155
+ program.option('--' + paramCase(key), option);
156
+ }
157
+ });
158
+ program.option('-o --output <file>', 'Specify output file (if not specified STDOUT will be used for output)');
159
+
160
+ function readFile(file) {
161
+ try {
162
+ return fs.readFileSync(file, { encoding: 'utf8' });
163
+ } catch (e) {
164
+ fatal('Cannot read ' + file + '\n' + e.message);
165
+ }
166
+ }
167
+
168
+ let config = {};
169
+ program.option('-c --config-file <file>', 'Use config file', function (configPath) {
170
+ const data = readFile(configPath);
171
+ try {
172
+ config = JSON.parse(data);
173
+ } catch (je) {
174
+ try {
175
+ config = require(path.resolve(configPath));
176
+ } catch (ne) {
177
+ fatal('Cannot read the specified config file.\nAs JSON: ' + je.message + '\nAs module: ' + ne.message);
178
+ }
179
+ }
180
+ mainOptionKeys.forEach(function (key) {
181
+ if (key in config) {
182
+ const option = mainOptions[key];
183
+ if (Array.isArray(option)) {
184
+ const value = config[key];
185
+ config[key] = option[1](typeof value === 'string' ? value : JSON.stringify(value));
186
+ }
187
+ }
188
+ });
189
+ });
190
+ program.option('--input-dir <dir>', 'Specify an input directory');
191
+ program.option('--output-dir <dir>', 'Specify an output directory');
192
+ program.option('--file-ext <text>', 'Specify an extension to be read, ex: html');
193
+
194
+ let content;
195
+ program.arguments('[files...]').action(function (files) {
196
+ content = files.map(readFile).join('');
197
+ }).parse(process.argv);
198
+
199
+ const programOptions = program.opts();
200
+
201
+ function createOptions() {
202
+ const options = {};
203
+
204
+ mainOptionKeys.forEach(function (key) {
205
+ const param = programOptions[key === 'minifyURLs' ? 'minifyUrls' : camelCase(key)];
206
+
207
+ if (typeof param !== 'undefined') {
208
+ options[key] = param;
209
+ } else if (key in config) {
210
+ options[key] = config[key];
211
+ }
212
+ });
213
+ return options;
214
+ }
215
+
216
+ function mkdir(outputDir, callback) {
217
+ fs.mkdir(outputDir, { recursive: true }, function (err) {
218
+ if (err) {
219
+ fatal('Cannot create directory ' + outputDir + '\n' + err.message);
220
+ }
221
+ callback();
222
+ });
223
+ }
224
+
225
+ function processFile(inputFile, outputFile) {
226
+ fs.readFile(inputFile, { encoding: 'utf8' }, async function (err, data) {
227
+ if (err) {
228
+ fatal('Cannot read ' + inputFile + '\n' + err.message);
229
+ }
230
+ let minified;
231
+ try {
232
+ minified = await minify(data, createOptions());
233
+ } catch (e) {
234
+ fatal('Minification error on ' + inputFile + '\n' + e.message);
235
+ }
236
+ fs.writeFile(outputFile, minified, { encoding: 'utf8' }, function (err) {
237
+ if (err) {
238
+ fatal('Cannot write ' + outputFile + '\n' + err.message);
239
+ }
240
+ });
241
+ });
242
+ }
243
+
244
+ function processDirectory(inputDir, outputDir, fileExt) {
245
+ fs.readdir(inputDir, function (err, files) {
246
+ if (err) {
247
+ fatal('Cannot read directory ' + inputDir + '\n' + err.message);
248
+ }
249
+
250
+ files.forEach(function (file) {
251
+ const inputFile = path.join(inputDir, file);
252
+ const outputFile = path.join(outputDir, file);
253
+
254
+ fs.stat(inputFile, function (err, stat) {
255
+ if (err) {
256
+ fatal('Cannot read ' + inputFile + '\n' + err.message);
257
+ } else if (stat.isDirectory()) {
258
+ processDirectory(inputFile, outputFile, fileExt);
259
+ } else if (!fileExt || path.extname(file) === '.' + fileExt) {
260
+ mkdir(outputDir, function () {
261
+ processFile(inputFile, outputFile);
262
+ });
263
+ }
264
+ });
265
+ });
266
+ });
267
+ }
268
+
269
+ const writeMinify = async () => {
270
+ const minifierOptions = createOptions();
271
+ let minified;
272
+
273
+ try {
274
+ minified = await minify(content, minifierOptions);
275
+ } catch (e) {
276
+ fatal('Minification error:\n' + e.message);
277
+ }
278
+
279
+ let stream = process.stdout;
280
+
281
+ if (programOptions.output) {
282
+ stream = fs.createWriteStream(programOptions.output)
283
+ .on('error', (e) => {
284
+ fatal('Cannot write ' + programOptions.output + '\n' + e.message);
285
+ });
286
+ }
287
+
288
+ stream.write(minified);
289
+ };
290
+
291
+ const { inputDir, outputDir, fileExt } = programOptions;
292
+
293
+ if (inputDir || outputDir) {
294
+ if (!inputDir) {
295
+ fatal('The option output-dir needs to be used with the option input-dir. If you are working with a single file, use -o.');
296
+ } else if (!outputDir) {
297
+ fatal('You need to specify where to write the output files with the option --output-dir');
298
+ }
299
+ processDirectory(inputDir, outputDir, fileExt);
300
+ } else if (content) { // Minifying one or more files specified on the CMD line
301
+ writeMinify();
302
+ } else { // Minifying input coming from STDIN
303
+ content = '';
304
+ process.stdin.setEncoding('utf8');
305
+ process.stdin.on('data', function (data) {
306
+ content += data;
307
+ }).on('end', writeMinify);
308
+ }