htmlnano 0.2.1 → 0.2.5

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/.eslintignore CHANGED
@@ -1 +1,2 @@
1
1
  lib/modules/example.es6
2
+ test.js
package/CHANGELOG.md CHANGED
@@ -2,29 +2,56 @@
2
2
  All notable changes to this project will be documented in this file.
3
3
  This project adheres to [Semantic Versioning](http://semver.org/).
4
4
 
5
+ ## [0.2.5] - 2019-11-09
6
+ ### Added
7
+ - Option to remove unused CSS using PurgeCSS [#84].
8
+
9
+ ### Fixed
10
+ - Keep the order of inline and external JS [#80].
11
+
12
+
13
+ ## [0.2.4] - 2019-07-11
14
+ ### Fixed
15
+ - Remove crossorigin from boolean attribute [#78], [#79].
16
+ - Disable SVGO plugin convertShapeToPath in safe preset [#76].
17
+
18
+
19
+ ## [0.2.3] - 2019-02-14
20
+ ### Fixed
21
+ - Keep `<g>` in SVG by default [#71].
22
+
23
+
24
+ ## [0.2.2] - 2019-01-03
25
+ ### Added
26
+ - `removeUnusedCss` module [#36].
27
+
28
+ ### Fixed
29
+ - Bug when `tag === false` [#66].
30
+ - Add `crossorigin` to boolean attributes [#67].
31
+
5
32
 
6
33
  ## [0.2.1] - 2018-12-01
7
- ## Fixed
34
+ ### Fixed
8
35
  - Disable JS minifying on AMP pages [#65].
9
36
 
10
37
  ## [0.2.0] - 2018-09-14
11
- ## Breaking changes
38
+ ### Breaking changes
12
39
  - The API of `minifyCss` module has been changed since `cssnano` has been updated to version 4, which has a different API. Check the following resources for more info:
13
40
  * [htmlnano docs](https://github.com/posthtml/htmlnano#minifycss)
14
41
  * [cssnano docs](https://cssnano.co/guides/presets)
15
42
  * Diff of commit [979f2c](https://github.com/posthtml/htmlnano/commit/979f2c821892c9e979e8b85f74ed0394330fceaf) with the changes of related docs.
16
43
 
17
- ## Added
44
+ ### Added
18
45
  - Add presets [#64].
19
46
  - Add `collapseAttributeWhitespace` module for collapsing spaces in list-like attributes [#25].
20
47
  - Add `deduplicateAttributeValues` module for de-duplicating values in list-like attributes [#39].
21
48
  - Better support for AMP pages [#59].
22
49
  - Collapse whitespaces between top-level tags [#24].
23
50
 
24
- ## Changed
51
+ ### Changed
25
52
  - Improve whitespace normalization using `normalize-html-whitespace` [#21].
26
53
 
27
- ## Fixed
54
+ ### Fixed
28
55
  - Don't collapse `visible="false"` attributes in A-Frame pages [#62].
29
56
 
30
57
 
@@ -102,6 +129,10 @@ This project adheres to [Semantic Versioning](http://semver.org/).
102
129
 
103
130
 
104
131
 
132
+ [0.2.5]: https://github.com/posthtml/htmlnano/compare/0.2.4...0.2.5
133
+ [0.2.4]: https://github.com/posthtml/htmlnano/compare/0.2.3...0.2.4
134
+ [0.2.3]: https://github.com/posthtml/htmlnano/compare/0.2.2...0.2.3
135
+ [0.2.2]: https://github.com/posthtml/htmlnano/compare/0.2.1...0.2.2
105
136
  [0.2.1]: https://github.com/posthtml/htmlnano/compare/0.2.0...0.2.1
106
137
  [0.2.0]: https://github.com/posthtml/htmlnano/compare/0.1.10...0.2.0
107
138
  [0.1.10]: https://github.com/posthtml/htmlnano/compare/0.1.9...0.1.10
@@ -116,6 +147,14 @@ This project adheres to [Semantic Versioning](http://semver.org/).
116
147
  [0.1.1]: https://github.com/posthtml/htmlnano/compare/0.1.0...0.1.1
117
148
 
118
149
 
150
+ [#84]: https://github.com/posthtml/htmlnano/issues/84
151
+ [#80]: https://github.com/posthtml/htmlnano/issues/80
152
+ [#79]: https://github.com/posthtml/htmlnano/issues/79
153
+ [#78]: https://github.com/posthtml/htmlnano/issues/78
154
+ [#76]: https://github.com/posthtml/htmlnano/issues/76
155
+ [#71]: https://github.com/posthtml/htmlnano/issues/71
156
+ [#67]: https://github.com/posthtml/htmlnano/issues/67
157
+ [#66]: https://github.com/posthtml/htmlnano/issues/66
119
158
  [#65]: https://github.com/posthtml/htmlnano/issues/65
120
159
  [#64]: https://github.com/posthtml/htmlnano/issues/64
121
160
  [#62]: https://github.com/posthtml/htmlnano/issues/62
@@ -126,6 +165,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
126
165
  [#47]: https://github.com/posthtml/htmlnano/issues/47
127
166
  [#42]: https://github.com/posthtml/htmlnano/issues/42
128
167
  [#39]: https://github.com/posthtml/htmlnano/issues/39
168
+ [#36]: https://github.com/posthtml/htmlnano/issues/36
129
169
  [#31]: https://github.com/posthtml/htmlnano/issues/31
130
170
  [#30]: https://github.com/posthtml/htmlnano/issues/30
131
171
  [#28]: https://github.com/posthtml/htmlnano/issues/28
package/README.md CHANGED
@@ -4,6 +4,7 @@
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
8
 
8
9
 
9
10
  ## [Benchmark](https://github.com/maltsev/html-minifiers-benchmark/blob/master/README.md)
@@ -75,8 +76,7 @@ const posthtmlPlugins = [
75
76
  require('htmlnano')(options)
76
77
  ];
77
78
 
78
- // "preset" arg might be skipped (see "Presets" section below for more info)
79
- posthtml(posthtmlPlugins, preset)
79
+ posthtml(posthtmlPlugins)
80
80
  .process(html)
81
81
  .then(function (result) {
82
82
  // result.html is minified
@@ -271,6 +271,81 @@ Minified:
271
271
  <img src="foo.jpg" alt="">
272
272
  ```
273
273
 
274
+ ### removeUnusedCss
275
+
276
+ Removes unused CSS inside `<style>` tags with either [uncss](https://github.com/uncss/uncss)
277
+ or [PurgeCSS](https://github.com/FullHuman/purgecss).
278
+
279
+ #### With uncss
280
+
281
+ ##### Options
282
+ See [the documentation of uncss](https://github.com/uncss/uncss) for all supported options.
283
+
284
+ uncss options can be passed directly to the `removeUnusedCss` module:
285
+ ```js
286
+ htmlnano.process(html, {
287
+ removeUnusedCss: {
288
+ ignore: ['.do-not-remove']
289
+ }
290
+ });
291
+ ```
292
+
293
+ The following uncss options are ignored if passed to the module:
294
+
295
+ - `stylesheets`
296
+ - `ignoreSheets`
297
+ - `raw`
298
+
299
+ #### With PurgeCSS
300
+
301
+ Use PurgeCSS instead of uncss by adding `tool: 'purgeCSS'` to the options.
302
+
303
+ ##### Options
304
+
305
+ See [the documentation of PurgeCSS](https://www.purgecss.com) for all supported options.
306
+
307
+ PurgeCSS options can be passed directly to the `removeUnusedCss` module:
308
+ ```js
309
+ htmlnano.process(html, {
310
+ removeUnusedCss: {
311
+ tool: 'purgeCSS',
312
+ whitelist: ['.do-not-remove']
313
+ }
314
+ });
315
+ ```
316
+
317
+ The following PurgeCSS options are ignored if passed to the module:
318
+
319
+ - `content`
320
+ - `css`
321
+ - `extractors`
322
+
323
+ ##### Example
324
+ Source:
325
+ ```html
326
+ <div class="b">
327
+ <style>
328
+ .a {
329
+ margin: 10px 10px 10px 10px;
330
+ }
331
+ .b {
332
+ color: #ff0000;
333
+ }
334
+ </style>
335
+ </div>
336
+ ```
337
+
338
+ Optimized:
339
+ ```html
340
+ <div class="b">
341
+ <style>
342
+ .b {
343
+ color: #ff0000;
344
+ }
345
+ </style>
346
+ </div>
347
+ ```
348
+
274
349
 
275
350
  ### minifyCss
276
351
  Minifies CSS with [cssnano](http://cssnano.co/) inside `<style>` tags and `style` attributes.
@@ -314,10 +389,20 @@ Minified:
314
389
 
315
390
 
316
391
  ### minifyJs
317
- Minifies JS with [Terser](https://github.com/fabiosantoscode/terser) inside `<script>` tags.
392
+ Minifies JS using [Terser](https://github.com/fabiosantoscode/terser) inside `<script>` tags.
318
393
 
319
394
  ##### Options
320
- See [the API documentation of Terser](https://github.com/fabiosantoscode/terser#api-reference)
395
+ See [the documentation of Terser](https://github.com/fabiosantoscode/terser#api-reference) for all supported options.
396
+ Terser options can be passed directly to the `minifyJs` module:
397
+ ```js
398
+ htmlnano.process(html, {
399
+ minifyJs: {
400
+ output: { quote_style: 1 },
401
+ },
402
+ });
403
+ ```
404
+
405
+
321
406
 
322
407
  ##### Example
323
408
  Source:
@@ -360,10 +445,20 @@ Minified:
360
445
 
361
446
 
362
447
  ### minifySvg
363
- Minifies SVG inside `<svg>` tags with [SVGO](https://github.com/svg/svgo/).
448
+ Minifies SVG inside `<svg>` tags using [SVGO](https://github.com/svg/svgo/).
364
449
 
365
450
  ##### Options
366
- See [the documentation of SVGO](https://github.com/svg/svgo/blob/master/README.md)
451
+ See [the documentation of SVGO](https://github.com/svg/svgo/blob/master/README.md) for all supported options.
452
+ SVGO options can be passed directly to the `minifySvg` module:
453
+ ```js
454
+ htmlnano.process(html, {
455
+ minifySvg: {
456
+ plugins: [
457
+ { collapseGroups: false },
458
+ ],
459
+ },
460
+ });
461
+ ```
367
462
 
368
463
  ##### Example
369
464
  Source:
package/lib/helpers.js CHANGED
@@ -6,6 +6,8 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.isAmpBoilerplate = isAmpBoilerplate;
7
7
  exports.isComment = isComment;
8
8
  exports.isConditionalComment = isConditionalComment;
9
+ exports.isStyleNode = isStyleNode;
10
+ exports.extractCssFromStyleNode = extractCssFromStyleNode;
9
11
  var ampBoilerplateAttributes = ['amp-boilerplate', 'amp4ads-boilerplate', 'amp4email-boilerplate'];
10
12
 
11
13
  function isAmpBoilerplate(node) {
@@ -48,4 +50,12 @@ function isComment(content) {
48
50
 
49
51
  function isConditionalComment(content) {
50
52
  return (content || '').trim().search(/<!--\[if/) === 0;
53
+ }
54
+
55
+ function isStyleNode(node) {
56
+ return node.tag === 'style' && !isAmpBoilerplate(node) && 'content' in node && node.content.length > 0;
57
+ }
58
+
59
+ function extractCssFromStyleNode(node) {
60
+ return Array.isArray(node.content) ? node.content.join(' ') : node.content;
51
61
  }
package/lib/htmlnano.js CHANGED
@@ -4,10 +4,6 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
 
7
- var _objectAssign = require('object-assign');
8
-
9
- var _objectAssign2 = _interopRequireDefault(_objectAssign);
10
-
11
7
  var _posthtml = require('posthtml');
12
8
 
13
9
  var _posthtml2 = _interopRequireDefault(_posthtml);
@@ -31,7 +27,7 @@ function htmlnano() {
31
27
  var preset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _safe2.default;
32
28
 
33
29
  return function minifier(tree) {
34
- options = (0, _objectAssign2.default)({}, preset, options);
30
+ options = Object.assign({}, preset, options);
35
31
  var promise = Promise.resolve(tree);
36
32
 
37
33
  var _loop = function _loop(moduleName) {
@@ -19,6 +19,10 @@ function collapseBooleanAttributes(tree, options, moduleOptions) {
19
19
  for (var _iterator = Object.keys(node.attrs)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
20
20
  var attrName = _step.value;
21
21
 
22
+ if (!node.tag) {
23
+ continue;
24
+ }
25
+
22
26
  if (node.tag.search('a-') === 0 && attrName === 'visible') {
23
27
  continue;
24
28
  }
@@ -7,10 +7,12 @@ exports.default = mergeScripts;
7
7
  /* Merge multiple <script> into one */
8
8
  function mergeScripts(tree) {
9
9
  var scriptNodesIndex = {};
10
+ var scriptSrcIndex = 1;
10
11
 
11
12
  tree.match({ tag: 'script' }, function (node) {
12
13
  var nodeAttrs = node.attrs || {};
13
14
  if (nodeAttrs.src) {
15
+ scriptSrcIndex++;
14
16
  return node;
15
17
  }
16
18
 
@@ -24,7 +26,8 @@ function mergeScripts(tree) {
24
26
  class: nodeAttrs.class,
25
27
  type: scriptType,
26
28
  defer: nodeAttrs.defer !== undefined,
27
- async: nodeAttrs.async !== undefined
29
+ async: nodeAttrs.async !== undefined,
30
+ index: scriptSrcIndex
28
31
  });
29
32
  if (!scriptNodesIndex[scriptKey]) {
30
33
  scriptNodesIndex[scriptKey] = [];
@@ -24,7 +24,7 @@ var postcssOptions = {
24
24
  function minifyCss(tree, options, cssnanoOptions) {
25
25
  var promises = [];
26
26
  tree.walk(function (node) {
27
- if (isStyleNode(node)) {
27
+ if ((0, _helpers.isStyleNode)(node)) {
28
28
  promises.push(processStyleNode(node, cssnanoOptions));
29
29
  } else if (node.attrs && node.attrs.style) {
30
30
  promises.push(processStyleAttr(node, cssnanoOptions));
@@ -38,12 +38,8 @@ function minifyCss(tree, options, cssnanoOptions) {
38
38
  });
39
39
  }
40
40
 
41
- function isStyleNode(node) {
42
- return node.tag === 'style' && !(0, _helpers.isAmpBoilerplate)(node) && node.content && node.content.length;
43
- }
44
-
45
41
  function processStyleNode(styleNode, cssnanoOptions) {
46
- var css = Array.isArray(styleNode.content) ? styleNode.content.join(' ') : styleNode.content;
42
+ var css = (0, _helpers.extractCssFromStyleNode)(styleNode);
47
43
  return _cssnano2.default.process(css, postcssOptions, cssnanoOptions).then(function (result) {
48
44
  return styleNode.content = [result.css];
49
45
  });
@@ -0,0 +1,147 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+
7
+ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
8
+
9
+ exports.default = removeUnusedCss;
10
+
11
+ var _helpers = require('../helpers');
12
+
13
+ var _uncss = require('uncss');
14
+
15
+ var _uncss2 = _interopRequireDefault(_uncss);
16
+
17
+ var _purgecss = require('purgecss');
18
+
19
+ var _purgecss2 = _interopRequireDefault(_purgecss);
20
+
21
+ var _posthtmlRender = require('posthtml-render');
22
+
23
+ var _posthtmlRender2 = _interopRequireDefault(_posthtmlRender);
24
+
25
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
26
+
27
+ function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
28
+
29
+ // These options must be set and shouldn't be overriden to ensure uncss doesn't look at linked stylesheets.
30
+ var uncssOptions = {
31
+ ignoreSheets: [/\s*/],
32
+ stylesheets: []
33
+ };
34
+
35
+ function processStyleNodeUnCSS(html, styleNode, uncssOptions) {
36
+ var css = (0, _helpers.extractCssFromStyleNode)(styleNode);
37
+
38
+ return runUncss(html, css, uncssOptions).then(function (css) {
39
+ // uncss may have left some style tags empty
40
+ if (css.trim().length === 0) {
41
+ styleNode.tag = false;
42
+ styleNode.content = [];
43
+ return;
44
+ }
45
+ styleNode.content = [css];
46
+ });
47
+ }
48
+
49
+ function runUncss(html, css, userOptions) {
50
+ if ((typeof userOptions === 'undefined' ? 'undefined' : _typeof(userOptions)) !== 'object') {
51
+ userOptions = {};
52
+ }
53
+
54
+ var options = Object.assign({}, userOptions, uncssOptions);
55
+ return new Promise(function (resolve, reject) {
56
+ options.raw = css;
57
+ (0, _uncss2.default)(html, options, function (error, output) {
58
+ if (error) {
59
+ reject(error);
60
+ return;
61
+ }
62
+ resolve(output);
63
+ });
64
+ });
65
+ }
66
+
67
+ var purgeFromHtml = function purgeFromHtml(tree) {
68
+ // content is not used as we can directly used the parsed HTML,
69
+ // making the process faster
70
+ var selectors = [];
71
+
72
+ tree.walk(function (node) {
73
+ var classes = node.attrs && node.attrs.class && node.attrs.class.split(' ') || [];
74
+ var ids = node.attrs && node.attrs.id && node.attrs.id.split(' ') || [];
75
+ selectors.push.apply(selectors, _toConsumableArray(classes).concat(_toConsumableArray(ids)));
76
+ node.tag && selectors.push(node.tag);
77
+ return node;
78
+ });
79
+
80
+ return function () {
81
+ return selectors;
82
+ };
83
+ };
84
+
85
+ function processStyleNodePurgeCSS(tree, styleNode, purgecssOptions) {
86
+ var css = (0, _helpers.extractCssFromStyleNode)(styleNode);
87
+ return runPurgecss(tree, css, purgecssOptions).then(function (css) {
88
+ if (css.trim().length === 0) {
89
+ styleNode.tag = false;
90
+ styleNode.content = [];
91
+ return;
92
+ }
93
+ styleNode.content = [css];
94
+ });
95
+ }
96
+
97
+ function runPurgecss(tree, css, userOptions) {
98
+ if ((typeof userOptions === 'undefined' ? 'undefined' : _typeof(userOptions)) !== 'object') {
99
+ userOptions = {};
100
+ }
101
+
102
+ var options = Object.assign({}, userOptions, {
103
+ content: [{
104
+ raw: tree,
105
+ extension: 'html'
106
+ }],
107
+ css: [{
108
+ raw: css,
109
+ extension: 'css'
110
+ }],
111
+ extractors: [{
112
+ extractor: purgeFromHtml(tree),
113
+ extensions: ['html']
114
+ }]
115
+ });
116
+
117
+ return new Promise(function (resolve, reject) {
118
+ try {
119
+ var purgeCss = new _purgecss2.default(options);
120
+ var purgecssResult = purgeCss.purge()[0];
121
+ resolve(purgecssResult.css);
122
+ } catch (err) {
123
+ reject(err);
124
+ }
125
+ });
126
+ }
127
+
128
+ /** Remove unused CSS */
129
+ function removeUnusedCss(tree, options, userOptions) {
130
+ var promises = [];
131
+ var html = userOptions.tool !== 'purgeCSS' && (0, _posthtmlRender2.default)(tree);
132
+
133
+ tree.walk(function (node) {
134
+ if ((0, _helpers.isStyleNode)(node)) {
135
+ if (userOptions.tool === 'purgeCSS') {
136
+ promises.push(processStyleNodePurgeCSS(tree, node, userOptions));
137
+ } else {
138
+ promises.push(processStyleNodeUnCSS(html, node, userOptions));
139
+ }
140
+ }
141
+ return node;
142
+ });
143
+
144
+ return Promise.all(promises).then(function () {
145
+ return tree;
146
+ });
147
+ }
@@ -4,10 +4,6 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
 
7
- var _objectAssign = require('object-assign');
8
-
9
- var _objectAssign2 = _interopRequireDefault(_objectAssign);
10
-
11
7
  var _safe = require('./safe');
12
8
 
13
9
  var _safe2 = _interopRequireDefault(_safe);
@@ -19,7 +15,7 @@ function _interopRequireDefault(obj) {
19
15
  /**
20
16
  * A safe preset for AMP pages (https://www.ampproject.org)
21
17
  */
22
- exports.default = (0, _objectAssign2.default)({}, _safe2.default, {
18
+ exports.default = Object.assign({}, _safe2.default, {
23
19
  collapseBooleanAttributes: {
24
20
  amphtml: true
25
21
  },
@@ -4,10 +4,6 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
 
7
- var _objectAssign = require('object-assign');
8
-
9
- var _objectAssign2 = _interopRequireDefault(_objectAssign);
10
-
11
7
  var _safe = require('./safe');
12
8
 
13
9
  var _safe2 = _interopRequireDefault(_safe);
@@ -19,8 +15,13 @@ function _interopRequireDefault(obj) {
19
15
  /**
20
16
  * Maximal minification (might break some pages)
21
17
  */
22
- exports.default = (0, _objectAssign2.default)({}, _safe2.default, {
18
+ exports.default = Object.assign({}, _safe2.default, {
23
19
  collapseWhitespace: 'all',
24
20
  removeComments: 'all',
25
- removeRedundantAttributes: true
21
+ removeRedundantAttributes: true,
22
+ removeUnusedCss: {},
23
+ minifyCss: {
24
+ preset: 'default'
25
+ },
26
+ minifySvg: {}
26
27
  });
@@ -16,12 +16,15 @@ exports.default = {
16
16
  deduplicateAttributeValues: true,
17
17
  mergeScripts: true,
18
18
  mergeStyles: true,
19
+ removeUnusedCss: false,
19
20
  minifyCss: {
20
21
  preset: 'default'
21
22
  },
22
23
  minifyJs: {},
23
24
  minifyJson: {},
24
- minifySvg: {},
25
+ minifySvg: {
26
+ plugins: [{ collapseGroups: false }, { convertShapeToPath: false }]
27
+ },
25
28
  removeEmptyAttributes: true,
26
29
  removeRedundantAttributes: false,
27
30
  removeComments: 'safe'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "htmlnano",
3
- "version": "0.2.1",
3
+ "version": "0.2.5",
4
4
  "description": "Modular HTML minifier, built on top of the PostHTML",
5
5
  "main": "index.js",
6
6
  "author": "Kirill Maltsev <maltsevkirill@gmail.com>",
@@ -11,7 +11,13 @@
11
11
  "pretest": "npm run lint && npm run compile",
12
12
  "test": ":",
13
13
  "posttest": "mocha --require babel-core/register --recursive --check-leaks --globals addresses",
14
- "prepare": "npm run compile"
14
+ "prepare": "npm run compile",
15
+ "release:patch": "release-it patch -n"
16
+ },
17
+ "release-it": {
18
+ "hooks": {
19
+ "before:init": "npm test"
20
+ }
15
21
  },
16
22
  "keywords": [
17
23
  "posthtml",
@@ -26,23 +32,25 @@
26
32
  ]
27
33
  },
28
34
  "dependencies": {
29
- "cssnano": "^4.1.0",
30
- "normalize-html-whitespace": "^0.2.0",
31
- "object-assign": "^4.0.1",
32
- "posthtml": "^0.11.3",
33
- "posthtml-render": "^1.1.4",
34
- "svgo": "^1.0.5",
35
- "terser": "^3.8.2"
35
+ "cssnano": "^4.1.10",
36
+ "normalize-html-whitespace": "^1.0.0",
37
+ "posthtml": "^0.12.0",
38
+ "posthtml-render": "^1.1.5",
39
+ "purgecss": "^1.4.0",
40
+ "svgo": "^1.3.2",
41
+ "terser": "^4.3.9",
42
+ "uncss": "^0.17.2"
36
43
  },
37
44
  "devDependencies": {
38
45
  "babel-cli": "^6.26.0",
39
46
  "babel-core": "^6.26.3",
40
- "babel-eslint": "^10.0.0",
47
+ "babel-eslint": "^10.0.3",
41
48
  "babel-preset-env": "^1.7.0",
42
- "eslint": "^5.5.0",
43
- "expect": "^23.6.0",
44
- "mocha": "^5.2.0",
45
- "rimraf": "^2.6.2"
49
+ "eslint": "^6.6.0",
50
+ "expect": "^24.9.0",
51
+ "mocha": "^6.2.2",
52
+ "release-it": "^12.4.3",
53
+ "rimraf": "^3.0.0"
46
54
  },
47
55
  "repository": {
48
56
  "type": "git",
package/test.js ADDED
@@ -0,0 +1,16 @@
1
+ const htmlnano = require('./index');
2
+ const fs = require('fs');
3
+ const preset = require('./lib/presets/max').default;
4
+
5
+ const options = {};
6
+
7
+ const html = fs.readFileSync('./test.html', 'utf8');
8
+
9
+ htmlnano
10
+ .process(html, options, preset)
11
+ .then(function (result) {
12
+ console.log(result.html);
13
+ })
14
+ .catch(function (err) {
15
+ console.error(err);
16
+ });