htmlnano 0.2.9 → 1.1.1

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.
Files changed (39) hide show
  1. package/CHANGELOG.md +57 -2
  2. package/README.md +15 -886
  3. package/docs/README.md +33 -0
  4. package/docs/babel.config.js +3 -0
  5. package/docs/docs/010-introduction.md +22 -0
  6. package/docs/docs/020-usage.md +77 -0
  7. package/docs/docs/030-config.md +21 -0
  8. package/docs/docs/040-presets.md +75 -0
  9. package/docs/docs/050-modules.md +786 -0
  10. package/docs/docs/060-contribute.md +16 -0
  11. package/docs/docusaurus.config.js +60 -0
  12. package/docs/netlify.toml +4 -0
  13. package/docs/package-lock.json +11621 -0
  14. package/docs/package.json +39 -0
  15. package/docs/sidebars.js +26 -0
  16. package/docs/versioned_docs/version-1.1.1/010-introduction.md +22 -0
  17. package/docs/versioned_docs/version-1.1.1/020-usage.md +77 -0
  18. package/docs/versioned_docs/version-1.1.1/030-config.md +21 -0
  19. package/docs/versioned_docs/version-1.1.1/040-presets.md +75 -0
  20. package/docs/versioned_docs/version-1.1.1/050-modules.md +786 -0
  21. package/docs/versioned_docs/version-1.1.1/060-contribute.md +16 -0
  22. package/docs/versioned_sidebars/version-1.1.1-sidebars.json +8 -0
  23. package/docs/versions.json +3 -0
  24. package/lib/helpers.js +5 -0
  25. package/lib/htmlnano.js +43 -6
  26. package/lib/modules/collapseAttributeWhitespace.js +62 -6
  27. package/lib/modules/collapseWhitespace.js +42 -17
  28. package/lib/modules/minifyCss.js +4 -2
  29. package/lib/modules/minifyJs.js +5 -3
  30. package/lib/modules/minifySvg.js +6 -12
  31. package/lib/modules/minifyUrls.js +50 -15
  32. package/lib/modules/normalizeAttributeValues.js +48 -0
  33. package/lib/modules/removeComments.js +25 -1
  34. package/lib/modules/removeEmptyAttributes.js +52 -8
  35. package/lib/modules/removeRedundantAttributes.js +69 -14
  36. package/lib/presets/safe.js +9 -4
  37. package/package.json +18 -16
  38. package/test.js +25 -16
  39. package/uncss-fork.patch +13 -0
package/README.md CHANGED
@@ -1,898 +1,27 @@
1
1
  # htmlnano
2
2
  [![npm version](https://badge.fury.io/js/htmlnano.svg)](http://badge.fury.io/js/htmlnano)
3
- [![Build Status](https://travis-ci.org/posthtml/htmlnano.svg?branch=master)](https://travis-ci.org/posthtml/htmlnano)
3
+ ![CI](https://github.com/posthtml/htmlnano/actions/workflows/ci.yml/badge.svg)
4
4
 
5
5
  Modular HTML minifier, built on top of the [PostHTML](https://github.com/posthtml/posthtml). Inspired by [cssnano](http://cssnano.co/).
6
6
 
7
- > The author of htmlnano is available for hire as a full stack web developer: https://kirillmaltsev.net/services
7
+ To switch to the optional fork of uncss, apply `uncss-fork.patch`.
8
8
 
9
+ Reasons you may want to do this are: uncss uses outdated dependencies with security issues
10
+
11
+ Reasons you may want to avoid this are: long term support, stability
9
12
 
10
13
  ## [Benchmark](https://github.com/maltsev/html-minifiers-benchmark/blob/master/README.md)
11
- [html-minifier@4.0.0]: https://www.npmjs.com/package/html-minifier
12
- [htmlnano@0.2.8]: https://www.npmjs.com/package/htmlnano
14
+ [html-minifier-terser@5.1.1]: https://www.npmjs.com/package/html-minifier-terser
15
+ [htmlnano@1.0.0]: https://www.npmjs.com/package/htmlnano
13
16
 
14
- | Website | Source (KB) | [html-minifier@4.0.0] | [htmlnano@0.2.8] |
17
+ | Website | Source (KB) | [html-minifier-terser@5.1.1] | [htmlnano@1.0.0] |
15
18
  |---------|------------:|----------------:|-----------:|
16
- | [stackoverflow.blog](https://stackoverflow.blog/) | 78 | 72 | 66 |
17
- | [github.com](https://github.com/) | 215 | 187 | 177 |
18
- | [en.wikipedia.org](https://en.wikipedia.org/wiki/Main_Page) | 78 | 73 | 72 |
19
- | [npmjs.com](https://www.npmjs.com/features) | 29 | 25 | 25 |
20
- | **Avg. minify rate** | 0% | **10%** | **13%** |
21
-
22
-
23
- ## Usage
24
- ### Gulp
25
- ```bash
26
- npm install --save-dev gulp-htmlnano
27
- ```
28
-
29
- ```js
30
- const gulp = require('gulp');
31
- const htmlnano = require('gulp-htmlnano');
32
- const options = {
33
- removeComments: false
34
- };
35
-
36
- gulp.task('default', function() {
37
- return gulp
38
- .src('./index.html')
39
- .pipe(htmlnano(options))
40
- .pipe(gulp.dest('./build'));
41
- });
42
- ```
43
-
44
-
45
- ### Javascript
46
- ```js
47
- const htmlnano = require('htmlnano');
48
- const options = {
49
- removeEmptyAttributes: false, // Disable the module "removeEmptyAttributes"
50
- collapseWhitespace: 'conservative' // Pass options to the module "collapseWhitespace"
51
- };
52
- // posthtml, posthtml-render, and posthtml-parse options
53
- const postHtmlOptions = {
54
- sync: true, // https://github.com/posthtml/posthtml#usage
55
- lowerCaseTags: true, // https://github.com/posthtml/posthtml-parser#options
56
- quoteAllAttributes: false, // https://github.com/posthtml/posthtml-render#options
57
- };
58
-
59
- htmlnano
60
- // "preset" arg might be skipped (see "Presets" section below for more info)
61
- // "postHtmlOptions" arg might be skipped
62
- .process(html, options, preset, postHtmlOptions)
63
- .then(function (result) {
64
- // result.html is minified
65
- })
66
- .catch(function (err) {
67
- console.error(err);
68
- });
69
- ```
70
-
71
-
72
- ### PostHTML
73
- Just add `htmlnano` as a final plugin:
74
- ```js
75
- const posthtml = require('posthtml');
76
- const options = {
77
- removeComments: false, // Disable the module "removeComments"
78
- collapseWhitespace: 'conservative' // Pass options to the module "collapseWhitespace"
79
- };
80
- const posthtmlPlugins = [
81
- /* other PostHTML plugins */
82
-
83
- require('htmlnano')(options)
84
- ];
85
-
86
- const postHtmlOptions = {
87
- // See PostHTML docs
88
- };
89
-
90
- posthtml(posthtmlPlugins)
91
- .process(html, posthtmlOptions)
92
- .then(function (result) {
93
- // result.html is minified
94
- })
95
- .catch(function (err) {
96
- console.error(err);
97
- });
98
- ```
99
-
100
-
101
-
102
- ## Presets
103
- A preset is just an object with modules config.
104
-
105
- Currently the following presets are available:
106
- - [safe](https://github.com/posthtml/htmlnano/blob/master/lib/presets/safe.es6) — a default preset for minifying a regular HTML in a safe way (without breaking anything)
107
- - [ampSafe](https://github.com/posthtml/htmlnano/blob/master/lib/presets/ampSafe.es6) - same as `safe` preset but for [AMP pages](https://www.ampproject.org/)
108
- - [max](https://github.com/posthtml/htmlnano/blob/master/lib/presets/max.es6) - maximal minification (might break some pages)
109
-
110
-
111
- You can use them the following way:
112
- ```js
113
- const htmlnano = require('htmlnano');
114
- const ampSafePreset = require('htmlnano').presets.ampSafe;
115
- const options = {
116
- // Your options
117
- };
118
-
119
- htmlnano
120
- .process(html, options, ampSafePreset)
121
- .then(function (result) {
122
- // result.html is minified
123
- })
124
- .catch(function (err) {
125
- console.error(err);
126
- });
127
- ```
128
-
129
- If you skip `preset` argument [`safe`](https://github.com/posthtml/htmlnano/blob/master/lib/presets/safe.es6) preset would be used by default.
130
-
131
-
132
- If you'd like to define your very own config without any presets pass an empty object as a preset:
133
- ```js
134
- const htmlnano = require('htmlnano');
135
- const options = {
136
- // Your options
137
- };
138
-
139
- htmlnano
140
- .process(html, options, {})
141
- .then(function (result) {
142
- // result.html is minified
143
- })
144
- .catch(function (err) {
145
- console.error(err);
146
- });
147
- ```
148
-
149
-
150
- You might create also your own presets:
151
- ```js
152
- const htmlnano = require('htmlnano');
153
- // Preset for minifying email templates
154
- const emailPreset = {
155
- mergeStyles: true,
156
- minifyCss: {
157
- safe: true
158
- },
159
- };
160
-
161
- const options = {
162
- // Some specific options
163
- };
164
-
165
- htmlnano
166
- .process(html, options, emailPreset)
167
- .then(function (result) {
168
- // result.html is minified
169
- })
170
- .catch(function (err) {
171
- console.error(err);
172
- });
173
- ```
174
-
175
- Feel free [to submit a PR](https://github.com/posthtml/htmlnano/issues/new) with your preset if it might be useful for other developers as well.
176
-
177
-
178
-
179
- ## Modules
180
- By default the modules should only perform safe transforms, see the module documentation below for details.
181
- You can disable modules by passing `false` as option, and enable them by passing `true`.
182
-
183
-
184
- ### collapseAttributeWhitespace
185
- Collapse redundant white spaces in list-like attributes (`class`, `rel`, `ping`).
186
-
187
- ##### Example
188
- Source:
189
- ```html
190
- <div class=" content page "></div>
191
- ```
192
-
193
- Minified:
194
- ```html
195
- <div class="content page"></div>
196
- ```
197
-
198
-
199
-
200
- ### collapseWhitespace
201
- Collapses redundant white spaces (including new lines). It doesn’t affect white spaces in the elements `<style>`, `<textarea>`, `<script>` and `<pre>`.
202
-
203
- ##### Options
204
- - `conservative` — collapses all redundant white spaces to 1 space (default)
205
- - `aggressive` — collapses all whitespaces that are redundant and safe to remove
206
- - `all` — collapses all redundant white spaces
207
-
208
- ##### Side effects
209
-
210
- *all*
211
- `<i>hello</i> <i>world</i>` or `<i>hello</i><br><i>world</i>` after minification will be rendered as `helloworld`.
212
- To prevent that use either the default `conservative` option, or the `aggressive` option.
213
-
214
- ##### Example
215
- Source:
216
- ```html
217
- <div>
218
- hello world!
219
- <a href="#">answer</a>
220
- <style>div { color: red; } </style>
221
- <main></main>
222
- </div>
223
- ```
224
-
225
- Minified (with `all`):
226
- ```html
227
- <div>hello world!<a href="#">answer</a><style>div { color: red; } </style><main></main></div>
228
- ```
229
-
230
- Minified (with `aggressive`):
231
- ```html
232
- <div> hello world! <a href="#">answer</a> <style>div { color: red; } </style><main></main></div>
233
- ```
234
-
235
- Minified (with `conservative`):
236
- ```html
237
- <div> hello world! <a href="#">answer</a> <style>div { color: red; } </style> <main></main> </div>
238
- ```
239
-
240
-
241
- ### deduplicateAttributeValues
242
- Remove duplicate values from list-like attributes (`class`, `rel`, `ping`).
243
-
244
- ##### Example
245
- Source:
246
- ```html
247
- <div class="sidebar left sidebar"></div>
248
- ```
249
-
250
- Minified:
251
- ```html
252
- <div class="sidebar left"></div>
253
- ```
254
-
255
-
256
- ### removeComments
257
- ##### Options
258
- - `safe` – removes all HTML comments except the conditional comments and [`<!--noindex--><!--/noindex-->`](https://yandex.com/support/webmaster/controlling-robot/html.xml) (default)
259
- - `all` — removes all HTML comments
260
-
261
- ##### Example
262
- Source:
263
- ```html
264
- <div><!-- test --></div>
265
- ```
266
-
267
- Minified:
268
- ```html
269
- <div></div>
270
- ```
271
-
272
-
273
- ### removeEmptyAttributes
274
- Removes empty [safe-to-remove](https://github.com/posthtml/htmlnano/blob/master/lib/modules/removeEmptyAttributes.es6) attributes.
275
-
276
- ##### Side effects
277
- This module could break your styles or JS if you use selectors with attributes:
278
- ```CSS
279
- img[style=""] {
280
- margin: 10px;
281
- }
282
- ```
283
-
284
- ##### Example
285
- Source:
286
- ```html
287
- <img src="foo.jpg" alt="" style="">
288
- ```
289
-
290
- Minified:
291
- ```html
292
- <img src="foo.jpg" alt="">
293
- ```
294
-
295
- ### removeAttributeQuotes
296
- Remove quotes around attributes when possible, see [HTML Standard - 12.1.2.3 Attributes - Unquoted attribute value syntax](https://html.spec.whatwg.org/multipage/syntax.html#attributes-2).
297
-
298
- ##### Example
299
- Source:
300
- ```html
301
- <div class="foo" title="hello world"></div>
302
- ```
303
-
304
- Minified:
305
- ```html
306
- <div class=foo title="hello world"></div>
307
- ```
308
-
309
- ##### Notice
310
- The feature is implemented by [posthtml-render's `quoteAllAttributes`](https://github.com/posthtml/posthtml-render#options), which is one of the PostHTML's option. So `removeAttributeQuotes` could be overriden by other PostHTML's plugins and PostHTML's configuration.
311
-
312
- For example:
313
-
314
- ```js
315
- posthtml([
316
- htmlnano({
317
- removeAttributeQuotes: true
318
- })
319
- ]).process(html, {
320
- quoteAllAttributes: true
321
- })
322
- ```
323
-
324
- `removeAttributeQuotes` will not work because PostHTML's `quoteAllAttributes` takes the priority.
325
-
326
- ### removeUnusedCss
327
-
328
- Removes unused CSS inside `<style>` tags with either [uncss](https://github.com/uncss/uncss)
329
- or [PurgeCSS](https://github.com/FullHuman/purgecss).
330
-
331
- #### With uncss
332
-
333
- ##### Options
334
- See [the documentation of uncss](https://github.com/uncss/uncss) for all supported options.
335
-
336
- uncss options can be passed directly to the `removeUnusedCss` module:
337
- ```js
338
- htmlnano.process(html, {
339
- removeUnusedCss: {
340
- ignore: ['.do-not-remove']
341
- }
342
- });
343
- ```
344
-
345
- The following uncss options are ignored if passed to the module:
346
-
347
- - `stylesheets`
348
- - `ignoreSheets`
349
- - `raw`
350
-
351
- #### With PurgeCSS
352
-
353
- Use PurgeCSS instead of uncss by adding `tool: 'purgeCSS'` to the options.
354
-
355
- ##### Options
356
-
357
- See [the documentation of PurgeCSS](https://www.purgecss.com) for all supported options.
358
-
359
- PurgeCSS options can be passed directly to the `removeUnusedCss` module:
360
- ```js
361
- htmlnano.process(html, {
362
- removeUnusedCss: {
363
- tool: 'purgeCSS',
364
- whitelist: ['.do-not-remove']
365
- }
366
- });
367
- ```
368
-
369
- The following PurgeCSS options are ignored if passed to the module:
370
-
371
- - `content`
372
- - `css`
373
- - `extractors`
374
-
375
- ##### Example
376
- Source:
377
- ```html
378
- <div class="b">
379
- <style>
380
- .a {
381
- margin: 10px 10px 10px 10px;
382
- }
383
- .b {
384
- color: #ff0000;
385
- }
386
- </style>
387
- </div>
388
- ```
389
-
390
- Optimized:
391
- ```html
392
- <div class="b">
393
- <style>
394
- .b {
395
- color: #ff0000;
396
- }
397
- </style>
398
- </div>
399
- ```
400
-
401
-
402
- ### minifyCss
403
- Minifies CSS with [cssnano](http://cssnano.co/) inside `<style>` tags and `style` attributes.
404
-
405
- ##### Options
406
- See [the documentation of cssnano](http://cssnano.co/optimisations/) for all supported optimizations.
407
- By default CSS is minified with preset `default`, which shouldn't have any side-effects.
408
-
409
- To use another preset or disabled some optimizations pass options to `minifyCss` module:
410
- ```js
411
- htmlnano.process(html, {
412
- minifyCss: {
413
- preset: ['default', {
414
- discardComments: {
415
- removeAll: true,
416
- },
417
- }]
418
- }
419
- });
420
- ```
421
-
422
- ##### Example
423
- Source:
424
- ```html
425
- <div>
426
- <style>
427
- h1 {
428
- margin: 10px 10px 10px 10px;
429
- color: #ff0000;
430
- }
431
- </style>
432
- </div>
433
- ```
434
-
435
- Minified:
436
- ```html
437
- <div>
438
- <style>h1{margin:10px;color:red}</style>
439
- </div>
440
- ```
441
-
442
-
443
- ### minifyJs
444
- Minifies JS using [Terser](https://github.com/fabiosantoscode/terser) inside `<script>` tags.
445
-
446
- ##### Options
447
- See [the documentation of Terser](https://github.com/fabiosantoscode/terser#api-reference) for all supported options.
448
- Terser options can be passed directly to the `minifyJs` module:
449
- ```js
450
- htmlnano.process(html, {
451
- minifyJs: {
452
- output: { quote_style: 1 },
453
- },
454
- });
455
- ```
456
-
457
-
458
-
459
- ##### Example
460
- Source:
461
- ```html
462
- <div>
463
- <script>
464
- /* comment */
465
- const foo = function () {
466
-
467
- };
468
- </script>
469
- </div>
470
- ```
471
-
472
- Minified:
473
- ```html
474
- <div>
475
- <script>const foo=function(){};</script>
476
- </div>
477
- ```
478
-
479
-
480
- ### minifyJson
481
- Minifies JSON inside `<script type="application/json"></script>`.
482
-
483
- ##### Example
484
- Source:
485
- ```html
486
- <script type="application/json">
487
- {
488
- "user": "me"
489
- }
490
- </script>
491
- ```
492
-
493
- Minified:
494
- ```html
495
- <script type="application/json">{"user":"me"}</script>
496
- ```
497
-
498
-
499
- ### minifySvg
500
- Minifies SVG inside `<svg>` tags using [SVGO](https://github.com/svg/svgo/).
501
-
502
- ##### Options
503
- See [the documentation of SVGO](https://github.com/svg/svgo/blob/master/README.md) for all supported options.
504
- SVGO options can be passed directly to the `minifySvg` module:
505
- ```js
506
- htmlnano.process(html, {
507
- minifySvg: {
508
- plugins: [
509
- { collapseGroups: false },
510
- ],
511
- },
512
- });
513
- ```
514
-
515
- ##### Example
516
- Source:
517
- ```html
518
- <svg version="1.1" baseProfile="full" width="300" height="200" xmlns="http://www.w3.org/2000/svg">
519
- <rect width="100%" height="100%" fill="red" />
520
-
521
- <circle cx="150" cy="100" r="80" fill="green" />
522
-
523
- <text x="150" y="125" font-size="60" text-anchor="middle" fill="white">SVG</text>
524
- </svg>`
525
- ```
526
-
527
- Minified:
528
- ```html
529
- <svg baseProfile="full" width="300" height="200" xmlns="http://www.w3.org/2000/svg"><rect width="100%" height="100%" fill="red"/><circle cx="150" cy="100" r="80" fill="green"/><text x="150" y="125" font-size="60" text-anchor="middle" fill="#fff">SVG</text></svg>
530
- ```
531
-
532
- ### minifyConditionalComments
533
-
534
- Minify content inside conditional comments.
535
-
536
- ##### Example
537
-
538
- Source:
539
-
540
- ```html
541
- <!--[if lte IE 7]>
542
- <style type="text/css">
543
- .title {
544
- color: red;
545
- }
546
- </style>
547
- <![endif]-->
548
- ```
549
-
550
- Minified:
551
-
552
- ```html
553
- <!--[if lte IE 7]><style>.title{color:red}</style><![endif]-->
554
- ```
555
-
556
- ### removeRedundantAttributes
557
- Removes redundant attributes from tags if they contain default values:
558
- - `method="get"` from `<form>`
559
- - `type="text"` from `<input>`
560
- - `type="submit"` from `<button>`
561
- - `language="javascript"` and `type="text/javascript"` from `<script>`
562
- - `charset` from `<script>` if it's an external script
563
- - `media="all"` from `<style>` and `<link>`
564
- - `type="text/css"` from `<link rel="stylesheet">`
565
-
566
- ##### Options
567
- This module is disabled by default, change option to true to enable this module.
568
-
569
- ##### Side effects
570
- This module could break your styles or JS if you use selectors with attributes:
571
- ```CSS
572
- form[method="get"] {
573
- color: red;
574
- }
575
- ```
576
-
577
- ##### Example
578
- Source:
579
- ```html
580
- <form method="get">
581
- <input type="text">
582
- </form>
583
- ```
584
-
585
- Minified:
586
- ```html
587
- <form>
588
- <input>
589
- </form>
590
- ```
591
-
592
-
593
- ### collapseBooleanAttributes
594
- Collapses boolean attributes (like `disabled`) to the minimized form.
595
-
596
- ##### Options
597
- If your document uses [AMP](https://www.ampproject.org/), set the `amphtml` flag
598
- to collapse additonal, AMP-specific boolean attributes:
599
- ```Json
600
- "collapseBooleanAttributes": {
601
- "amphtml": true
602
- }
603
- ```
604
-
605
- ##### Side effects
606
- This module could break your styles or JS if you use selectors with attributes:
607
- ```CSS
608
- button[disabled="disabled"] {
609
- color: red;
610
- }
611
- ```
612
-
613
- ##### Example
614
- Source:
615
- ```html
616
- <button disabled="disabled">click</button>
617
- <script defer=""></script>
618
- ```
619
-
620
- Minified:
621
- ```html
622
- <button disabled>click</button>
623
- <script defer></script>
624
- ```
625
-
626
-
627
- ### mergeStyles
628
- Merges multiple `<style>` with the same `media` and `type` into one tag.
629
- `<style scoped>...</style>` are skipped.
630
-
631
- ##### Example
632
- Source:
633
- ```html
634
- <style>h1 { color: red }</style>
635
- <style media="print">div { color: blue }</style>
636
-
637
- <style type="text/css" media="print">a {}</style>
638
- <style>div { font-size: 20px }</style>
639
- ```
640
-
641
- Minified:
642
- ```html
643
- <style>h1 { color: red } div { font-size: 20px }</style>
644
- <style media="print">div { color: blue } a {}</style>
645
- ```
646
-
647
-
648
- ### mergeScripts
649
- Merge multiple `<script>` with the same attributes (`id, class, type, async, defer`) into one (last) tag.
650
-
651
- ##### Side effects
652
- It could break your code if the tags with different attributes share the same variable scope.
653
- See the example below.
654
-
655
- ##### Example
656
- Source:
657
- ```html
658
- <script>const foo = 'A:1';</script>
659
- <script class="test">foo = 'B:1';</script>
660
- <script type="text/javascript">foo = 'A:2';</script>
661
- <script defer>foo = 'C:1';</script>
662
- <script>foo = 'A:3';</script>
663
- <script defer="defer">foo = 'C:2';</script>
664
- <script class="test" type="text/javascript">foo = 'B:2';</script>
665
- ```
666
-
667
- Minified:
668
- ```html
669
- <script>const foo = 'A:1'; foo = 'A:2'; foo = 'A:3';</script>
670
- <script defer="defer">foo = 'C:1'; foo = 'C:2';</script>
671
- <script class="test" type="text/javascript">foo = 'B:1'; foo = 'B:2';</script>
672
- ```
673
-
674
-
675
- ### custom
676
- It's also possible to pass custom modules in the minifier.
677
- As a function:
678
- ```js
679
- const options = {
680
- custom: function (tree, options) {
681
- // Some minification
682
- return tree;
683
- }
684
- };
685
- ```
686
-
687
- Or as a list of functions:
688
- ```js
689
- const options = {
690
- custom: [
691
- function (tree, options) {
692
- // Some minification
693
- return tree;
694
- },
695
-
696
- function (tree, options) {
697
- // Some other minification
698
- return tree;
699
- }
700
- ]
701
- };
702
- ```
703
-
704
- `options` is an object with all options that were passed to the plugin.
705
-
706
- ### sortAttributesWithLists
707
- Sort values in list-like attributes (`class`, `rel`, `ping`).
708
-
709
- The module won't impact the plain-text size of the output. However it will improve the compression ratio of gzip/brotli used in HTTP compression.
710
-
711
- ##### Options
712
-
713
- - `alphabetical`: Default option. Sort attribute values in alphabetical order.
714
- - `frequency`: Sort attribute values by frequency.
715
-
716
- ##### Example
717
-
718
- **alphabetical**
719
-
720
- Source:
721
- ```html
722
- <div class="foo baz bar">click</div>
723
- ```
724
-
725
- Processed:
726
- ```html
727
- <div class="bar baz foo">click</div>
728
- ```
729
-
730
- **frequency**
731
-
732
- Source:
733
- ```html
734
- <div class="foo baz bar"></div><div class="bar foo"></div>
735
- ```
736
-
737
- Processed:
738
- ```html
739
- <div class="foo bar baz"></div><div class="foo bar"></div>
740
- ```
741
-
742
- ### sortAttributes
743
- Sort attributes inside elements.
744
-
745
- The module won't impact the plain-text size of the output. However it will improve the compression ratio of gzip/brotli used in HTTP compression.
746
-
747
- ##### Options
748
-
749
- - `alphabetical`: Default option. Sort attributes in alphabetical order.
750
- - `frequency`: Sort attributes by frequency.
751
-
752
- ##### Example
753
-
754
- **alphabetical**
755
-
756
- Source:
757
- ```html
758
- <input type="text" class="form-control" name="testInput" autofocus="" autocomplete="off" id="testId">
759
- ```
760
-
761
- Processed:
762
- ```html
763
- <input autocomplete="off" autofocus="" class="form-control" id="testId" name="testInput" type="text">
764
- ```
765
-
766
- **frequency**
767
-
768
- Source:
769
- ```html
770
- <input type="text" class="form-control" name="testInput" id="testId">
771
- <a id="testId" href="#" class="testClass"></a>
772
- <img width="20" src="../images/image.png" height="40" alt="image" class="cls" id="id2">
773
- ```
774
-
775
- Processed:
776
- ```html
777
- <input class="form-control" id="testId" type="text" name="testInput">
778
- <a class="testClass" id="testId" href="#"></a>
779
- <img class="cls" id="id2" width="20" src="../images/image.png" height="40" alt="image">
780
- ```
781
-
782
- ### minifyUrls
783
- Convert absolute URL to relative URL using [relateurl](https://www.npmjs.com/package/relateurl).
784
-
785
- ##### Options
786
-
787
- The base URL to resolve against. Support `String` & `URL`.
788
-
789
- ```js
790
- htmlnano.process(html, {
791
- minifyUrls: 'https://example.com' // Valid configuration
792
- });
793
- ```
794
-
795
- ```js
796
- htmlnano.process(html, {
797
- minifyUrls: new URL('https://example.com') // Valid configuration
798
- });
799
- ```
800
-
801
- ```js
802
- htmlnano.process(html, {
803
- minifyUrls: false // The module will be disabled
804
- });
805
- ```
806
-
807
- ```js
808
- htmlnano.process(html, {
809
- minifyUrls: true // Invalid configuration, the module will be disabled
810
- });
811
- ```
812
-
813
- ##### Example
814
-
815
- **Basic Usage**
816
-
817
- Configuration:
818
-
819
- ```js
820
- htmlnano.process(html, {
821
- minifyUrls: 'https://example.com'
822
- });
823
- ```
824
-
825
- Source:
826
-
827
- ```html
828
- <a href="https://example.com/foo/bar/baz">bar</a>
829
- ```
830
-
831
- Minified:
832
-
833
- ```html
834
- <a href="foo/bar/baz">bar</a>
835
- ```
836
-
837
- **With sub-directory**
838
-
839
- Configuration:
840
-
841
- ```js
842
- htmlnano.process(html, {
843
- minifyUrls: 'https://example.com/foo/baz/'
844
- });
845
- ```
846
-
847
- Source:
848
-
849
- ```html
850
- <a href="https://example.com/foo/bar">bar</a>
851
- ```
852
-
853
- Minified:
854
-
855
- ```html
856
- <a href="../bar">bar</a>
857
- ```
858
-
859
- ## removeOptionalTags
860
- Remove certain tags that can be omitted, see [HTML Standard - 13.1.2.4 Optional tags](https://html.spec.whatwg.org/multipage/syntax.html#optional-tags).
861
-
862
- ##### Example
863
-
864
- Source:
865
-
866
- ```html
867
- <html><head><title>Title</title></head><body><p>Hi</p></body></html>
868
- ```
869
-
870
- Minified:
871
-
872
- ```html
873
- <title>Title</title><p>Hi</p>
874
- ```
875
- ##### Notice
876
- Due to [the limitation of PostHTML](https://github.com/posthtml/htmlnano/issues/99), htmlnano can't remove only the start tag or the end tag of an element. Currently, htmlnano only supports removing the following optional tags, as htmlnano can remove their start tag and end tag at the same time:
877
-
878
- - `html`
879
- - `head`
880
- - `body`
881
- - `colgroup`
882
- - `tbody`
883
-
884
- ## Contribute
885
- Since the minifier is modular, it's very easy to add new modules:
886
-
887
- 1. Create a ES6-file inside `lib/modules/` with a function that does some minification. For example you can check [`lib/modules/example.es6`](https://github.com/posthtml/htmlnano/blob/master/lib/modules/example.es6).
888
-
889
- 2. Add the module's name into one of those [presets](https://github.com/posthtml/htmlnano/tree/master/lib/presets). You can choose either `ampSafe`, `max`, or `safe`.
890
-
891
- 3. Create a JS-file inside `test/modules/` with some unit-tests.
892
-
893
- 4. Describe your module in the section "[Modules](https://github.com/posthtml/htmlnano/blob/master/README.md#modules)".
19
+ | [stackoverflow.blog](https://stackoverflow.blog/) | 95 | 87 | 82 |
20
+ | [github.com](https://github.com/) | 210 | 183 | 171 |
21
+ | [en.wikipedia.org](https://en.wikipedia.org/wiki/Main_Page) | 78 | 72 | 72 |
22
+ | [npmjs.com](https://www.npmjs.com/features) | 41 | 38 | 36 |
23
+ | **Avg. minify rate** | 0% | **9%** | **13%** |
894
24
 
895
- 5. Send me a pull request.
896
25
 
897
- Other types of contribution (bug fixes, documentation improves, etc) are also welcome!
898
- Would like to contribute, but don't have any ideas what to do? Check out [our issues](https://github.com/posthtml/htmlnano/labels/help%20wanted).
26
+ ## Documentation
27
+ https://htmlnano.netlify.app