html-minifier 0.6.8 → 0.7.2

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/CHANGELOG.md CHANGED
@@ -1,10 +1,23 @@
1
- ## [0.6.7](https://github.com/kangax/html-minifier/compare/v0.6.6...0.6.7)
1
+ ## [0.7.0](https://github.com/kangax/html-minifier/compare/v0.6.9...v0.7.0)
2
+
3
+ * TODO
4
+
5
+ ## [0.6.9](https://github.com/kangax/html-minifier/compare/v0.6.8...v0.6.9)
6
+
7
+ * TODO
8
+
9
+ ## [0.6.8](https://github.com/kangax/html-minifier/compare/v0.6.7...v0.6.8)
10
+
11
+ * TODO
12
+
13
+ ## [0.6.7](https://github.com/kangax/html-minifier/compare/v0.6.6...v0.6.7)
2
14
 
3
15
  * Preserve empty script with `src` attribute
4
16
  * Make `draggable` enumerated attribute
5
17
  * Add option to preserve a single line break on collapse
6
18
  * Do not treat draggable as a boolean attribute
7
- * Add support for `customAttrCollapse`
19
+ * Add `minifyURLs` option
20
+ * Add `customAttrCollapse` option
8
21
  * `collapseBoolean` is case-insensitive
9
22
  * Remove removable attrs with unspecified values
10
23
  * `removeComments` affects htmlmin:ignore comments
@@ -13,40 +26,40 @@
13
26
  * `s` tag has been reinstated
14
27
  * Remove `i`, `b`, `u` tags from linter as problematic
15
28
 
16
- ## [0.6.6](https://github.com/kangax/html-minifier/compare/v0.6.5...0.6.6)
29
+ ## [0.6.6](https://github.com/kangax/html-minifier/compare/v0.6.5...v0.6.6)
17
30
 
18
31
  * Fix Firefox attribute bug
19
32
  * Add `customAttrAssign` option
20
33
  * Add `maxLineLength` option
21
34
  * Add `customAttrSurround` option
22
35
 
23
- ## [0.6.5](https://github.com/kangax/html-minifier/compare/v0.6.4...0.6.5)
36
+ ## [0.6.5](https://github.com/kangax/html-minifier/compare/v0.6.4...v0.6.5)
24
37
 
25
38
  * `caseSensitive` option now applies to tags and attributes
26
39
 
27
- ## [0.6.4](https://github.com/kangax/html-minifier/compare/v0.6.3...0.6.4)
40
+ ## [0.6.4](https://github.com/kangax/html-minifier/compare/v0.6.3...v0.6.4)
28
41
 
29
42
  * Support for mixed-case tags
30
43
  * Support IE downlevel-revealed conditional comments
31
44
  * Add support for `wbr` element
32
45
 
33
- ## [0.6.3](https://github.com/kangax/html-minifier/compare/v0.6.2...0.6.3)
46
+ ## [0.6.3](https://github.com/kangax/html-minifier/compare/v0.6.2...v0.6.3)
34
47
 
35
48
  * Do not treat `translate` attribute as boolean
36
49
  * Add `svg` element in inline list
37
50
  * Do not remove special spaces like ` `
38
51
  * Make `collapseWhitespace` more resilient
39
52
 
40
- ## [0.6.2](https://github.com/kangax/html-minifier/compare/v0.6.1...0.6.2)
53
+ ## [0.6.2](https://github.com/kangax/html-minifier/compare/v0.6.1...v0.6.2)
41
54
 
42
55
  * Fix bug introduced by `processScripts` option
43
56
 
44
- ## [0.6.1](https://github.com/kangax/html-minifier/compare/v0.6.0...0.6.1)
57
+ ## [0.6.1](https://github.com/kangax/html-minifier/compare/v0.6.0...v0.6.1)
45
58
 
46
59
  * Add CLI
47
60
  * Fix error with valueless attributes (e.g. `<a href>`). [#169](https://github.com/kangax/html-minifier/issues/169)
48
61
 
49
- ## [0.6.0](https://github.com/kangax/html-minifier/compare/v0.5.6...0.6.0)
62
+ ## [0.6.0](https://github.com/kangax/html-minifier/compare/v0.5.6...v0.6.0)
50
63
 
51
64
  * Minify meta viewport value [#159](https://github.com/kangax/html-minifier/issues/159)
52
65
  * Add support for ignoring markup via `<!-- htmlmin:ignore -->` [#89](https://github.com/kangax/html-minifier/issues/89)
package/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2010-2014 Juriy "kangax" Zaytsev
1
+ Copyright (c) 2010-2015 Juriy "kangax" Zaytsev
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person
4
4
  obtaining a copy of this software and associated documentation
package/README.md CHANGED
@@ -1,25 +1,25 @@
1
- [![NPM version](https://badge.fury.io/js/html-minifier.svg)](http://badge.fury.io/js/html-minifier)
2
- [![Build Status](https://travis-ci.org/kangax/html-minifier.svg)](https://travis-ci.org/kangax/html-minifier)
3
- [![Dependency Status](https://david-dm.org/kangax/html-minifier.svg?theme=shields.io)](https://david-dm.org/kangax/html-minifier)
4
- [![devDependency Status](https://david-dm.org/kangax/html-minifier/dev-status.svg?theme=shields.io)](https://david-dm.org/kangax/html-minifier#info=devDependencies)
1
+ [![NPM version](https://img.shields.io/npm/v/html-minifier.svg?style=flat)](https://www.npmjs.com/package/html-minifier)
2
+ [![Build Status](https://img.shields.io/travis/kangax/html-minifier.svg?style=flat)](https://travis-ci.org/kangax/html-minifier)
3
+ [![Dependency Status](https://img.shields.io/david/kangax/html-minifier.svg?style=flat)](https://david-dm.org/kangax/html-minifier)
4
+ [![devDependency Status](https://img.shields.io/david/dev/kangax/html-minifier.svg?style=flat)](https://david-dm.org/kangax/html-minifier#info=devDependencies)
5
5
 
6
- [HTMLMinifier](http://kangax.github.io/html-minifier/) is a highly __configurable__, __well-tested__, Javascript-based HTML minifier, with lint-like capabilities.
6
+ [HTMLMinifier](http://kangax.github.io/html-minifier/) is a highly **configurable**, **well-tested**, Javascript-based HTML minifier, with lint-like capabilities.
7
7
 
8
8
  See [corresponding blog post](http://perfectionkills.com/experimenting-with-html-minifier/) for all the gory details of [how it works](http://perfectionkills.com/experimenting-with-html-minifier/#how_it_works), [description of each option](http://perfectionkills.com/experimenting-with-html-minifier/#options), [testing results](http://perfectionkills.com/experimenting-with-html-minifier/#field_testing) and [conclusions](http://perfectionkills.com/experimenting-with-html-minifier/#cost_and_benefits).
9
9
 
10
10
  [Test suite is available online](http://kangax.github.io/html-minifier/tests/).
11
11
 
12
- Also see corresponding [Ruby wrapper](https://github.com/stereobooster/html_minifier), and for Node.js, [Grunt plugin](https://github.com/gruntjs/grunt-contrib-htmlmin) & [Gulp module](https://github.com/jonschlinkert/gulp-htmlmin).
12
+ Also see corresponding [Ruby wrapper](https://github.com/stereobooster/html_minifier), and for Node.js, [Grunt plugin](https://github.com/gruntjs/grunt-contrib-htmlmin), [Gulp module](https://github.com/jonschlinkert/gulp-htmlmin), and [Koa middleware wrapper](https://github.com/koajs/html-minifier).
13
13
 
14
14
  How does HTMLMinifier compare to [another solution](http://www.willpeavy.com/minifier/) — HTML Minifier from Will Peavy (1st result in [google search for "html minifier"](https://www.google.com/#q=html+minifier)) as well as htmlcompressor.com?
15
15
 
16
- | Site | Original size _(KB)_ | HTMLMinifier _(KB)_ | Will Peavy _(KB)_ | htmlcompressor.com _(KB)_ |
16
+ | Site | Original size _(KB)_ | HTMLMinifier _(KB)_ | Will Peavy _(KB)_ | htmlcompressor.com _(KB)_ |
17
17
  | --------------------------------------------------------------------------- |:-----------:| ----------------:| ------------:| ----------------:|
18
18
  | [HTMLMinifier page](https://github.com/kangax/html-minifier) | 48.8 | <b>37.3</b> | 43.3 | 41.9 |
19
19
  | [ES6 table](http://kangax.github.io/es5-compat-table/es6/) | 117.9 | <b>79.9</b> | 92 | 91.9 |
20
20
  | [MSN](http://msn.com) | 156.6 | <b>133</b> | 145 | 138.3 |
21
21
  | [Stackoverflow](http://stackoverflow.com) | 200.4 | <b>159.5</b> | 168.3 | 163.3 |
22
- | [Amazon](http://amazon.com) | 245.9 | <b>206.3</b> | 225 | 218.5 |
22
+ | [Amazon](http://amazon.com) | 245.9 | <b>206.3</b> | 225 | 218.5 |
23
23
  | [Wikipedia](http://en.wikipedia.org/wiki/President_of_the_United_States) | 401.4 | <b>380.6</b> | 396.3 | n/a |
24
24
  | [Eloquent Javascript](http://eloquentjavascript.net/print.html) | 869.5 | <b>830</b> | 872 | n/a |
25
25
 
@@ -34,10 +34,11 @@ How does HTMLMinifier compare to [another solution](http://www.willpeavy.com/min
34
34
  | `removeCDATASectionsFromCDATA` | [Remove CDATA sections from script and style elements](http://perfectionkills.com/experimenting-with-html-minifier/#remove_cdata_sections) | `false` |
35
35
  | `collapseWhitespace` | [Collapse white space that contributes to text nodes in a document tree.](http://perfectionkills.com/experimenting-with-html-minifier/#collapse_whitespace) | `false` |
36
36
  | `conservativeCollapse` | Always collapse to 1 space (never remove it entirely). Must be used in conjunction with `collapseWhitespace=true` | `false` |
37
- | `preserveLineBreaks` | Always collapse to 1 line break (never remove it entirely) when whitespace between tags include a line break. Must be used in conjunction with `collapseWhitespace=true` | `false` |
37
+ | `preserveLineBreaks` | Always collapse to 1 line break (never remove it entirely) when whitespace between tags include a line break. Must be used in conjunction with `collapseWhitespace=true` | `false` |
38
38
  | `collapseBooleanAttributes` | [Omit attribute values from boolean attributes](http://perfectionkills.com/experimenting-with-html-minifier/#collapse_boolean_attributes) | `false` |
39
39
  | `removeAttributeQuotes` | [Remove quotes around attributes when possible.](http://perfectionkills.com/experimenting-with-html-minifier/#remove_attribute_quotes) | `false` |
40
40
  | `removeRedundantAttributes` | [Remove attributes when value matches default.](http://perfectionkills.com/experimenting-with-html-minifier/#remove_redundant_attributes) | `false` |
41
+ | `preventAttributesEscaping` | Prevents the escaping of the values of attributes. | `false` |
41
42
  | `useShortDoctype` | [Replaces the doctype with the short (HTML5) doctype](http://perfectionkills.com/experimenting-with-html-minifier/#use_short_doctype) | `false` |
42
43
  | `removeEmptyAttributes` | [Remove all attributes with whitespace-only values](http://perfectionkills.com/experimenting-with-html-minifier/#remove_empty_or_blank_attributes) | `false` |
43
44
  | `removeScriptTypeAttributes` | Remove `type="text/javascript"` from `script` tags. Other `type` attribute values are left intact. | `false` |
@@ -47,7 +48,7 @@ How does HTMLMinifier compare to [another solution](http://www.willpeavy.com/min
47
48
  | `removeEmptyElements` | [Remove all elements with empty contents](http://perfectionkills.com/experimenting-with-html-minifier/#remove_empty_elements) | `false` |
48
49
  | `lint` | [Toggle linting](http://perfectionkills.com/experimenting-with-html-minifier/#validate_input_through_html_lint) | `false` |
49
50
  | `keepClosingSlash` | Keep the trailing slash on singleton elements | `false` |
50
- | `caseSensitive` | Treat attributes in case sensitive manner (useful for SVG; e.g. viewBox) | `false` |
51
+ | `caseSensitive` | Treat attributes in case sensitive manner (useful for custom HTML tags.) | `false` |
51
52
  | `minifyJS` | Minify Javascript in script elements and on* attributes (uses [UglifyJS](https://github.com/mishoo/UglifyJS2)) | `false` (could be `true`, `false`, `Object` (options)) |
52
53
  | `minifyCSS` | Minify CSS in style elements and style attributes (uses [clean-css](https://github.com/GoalSmashers/clean-css)) | `false` (could be `true`, `false`, `Object` (options)) |
53
54
  | `minifyURLs` | Minify URLs in various attributes (uses [relateurl](https://github.com/stevenvachon/relateurl)) | `false` (could be `Object` (options)) |
@@ -58,8 +59,15 @@ How does HTMLMinifier compare to [another solution](http://www.willpeavy.com/min
58
59
  | `customAttrSurround` | Arrays of regex'es that allow to support custom attribute surround expressions (e.g. `<input {{#if value}}checked="checked"{{/if}}>`) | `[ ]` |
59
60
  | `customAttrCollapse` | Regex that specifies custom attribute to strip newlines from (e.g. `/ng\-class/`) | |
60
61
 
62
+ ## Special cases
61
63
 
62
- Chunks of markup can be ignored by wrapping them with `<!-- htmlmin:ignore -->`.
64
+ ### Ignoring chunks of markup.
65
+
66
+ If you have chunks of markup you would like preserved, you can wrap them `<!-- htmlmin:ignore -->`.
67
+
68
+ ### Preserving SVG tags
69
+
70
+ SVG tags are automatically recognized, and when they are minified, both case-sensitivity and closing-slashes are preserved, regardless of the minification settings used for the rest of the file.
63
71
 
64
72
  ## Installation Instructions
65
73
 
@@ -84,7 +92,7 @@ npm link .
84
92
 
85
93
  For command line usage please see `html-minifier --help`
86
94
 
87
- ## Node.js
95
+ ### Node.js
88
96
 
89
97
  ```js
90
98
  var minify = require('html-minifier').minify;
@@ -94,8 +102,8 @@ var result = minify('<p title="blah" id="moo">foo</p>', {
94
102
  result; // '<p title=blah id=moo>foo</p>'
95
103
  ```
96
104
 
97
- Running benchmarks
98
- ------------------
105
+ ## Running benchmarks
106
+
99
107
  Benchmarks for minified HTML:
100
108
  ```
101
109
  node benchmark.js
package/cli.js CHANGED
@@ -4,7 +4,7 @@
4
4
  *
5
5
  * The MIT License (MIT)
6
6
  *
7
- * Copyright (c) 2014 Zoltan Frombach
7
+ * Copyright (c) 2014-2015 Zoltan Frombach
8
8
  *
9
9
  * Permission is hereby granted, free of charge, to any person obtaining a copy of
10
10
  * this software and associated documentation files (the "Software"), to deal in
@@ -25,15 +25,19 @@
25
25
  *
26
26
  */
27
27
 
28
+ /* globals JSON:true */
29
+
28
30
  'use strict';
29
31
 
30
32
  var cli = require('cli');
33
+ var concat = require('concat-stream');
31
34
  var changeCase = require('change-case');
32
35
  var path = require('path');
33
36
  var fs = require('fs');
34
37
  var appName = require('./package.json').name;
35
38
  var appVersion = require('./package.json').version;
36
39
  var minify = require('./dist/htmlminifier.min.js').minify;
40
+ var HTMLLint = require('./dist/htmlminifier.min.js').HTMLLint;
37
41
  var minifyOptions = {};
38
42
  var input = null;
39
43
  var output = null;
@@ -58,12 +62,17 @@ var mainOptions = {
58
62
  removeCDATASectionsFromCDATA: [[false, 'Remove CDATA sections from script and style elements']],
59
63
  collapseWhitespace: [[false, 'Collapse white space that contributes to text nodes in a document tree.']],
60
64
  conservativeCollapse: [[false, 'Always collapse to 1 space (never remove it entirely)']],
65
+ preserveLineBreaks: [[false, 'Always collapse to 1 line break (never remove it entirely) when whitespace between tags include a line break.']],
61
66
  collapseBooleanAttributes: [[false, 'Omit attribute values from boolean attributes']],
62
67
  removeAttributeQuotes: [[false, 'Remove quotes around attributes when possible.']],
63
68
  removeRedundantAttributes: [[false, 'Remove attributes when value matches default.']],
69
+ preventAttributesEscaping: [[false, 'Prevents the escaping of the values of attributes.']],
64
70
  useShortDoctype: [[false, 'Replaces the doctype with the short (HTML5) doctype']],
65
71
  removeEmptyAttributes: [[false, 'Remove all attributes with whitespace-only values']],
72
+ removeScriptTypeAttributes: [[false, 'Remove type="text/javascript" from script tags. Other type attribute values are left intact.']],
73
+ removeStyleLinkTypeAttributes: [[false, 'Remove type="text/css" from style and link tags. Other type attribute values are left intact.']],
66
74
  removeOptionalTags: [[false, 'Remove unrequired tags']],
75
+ removeIgnored: [[false, 'Remove all tags starting and ending with <%, %>, <?, ?>']],
67
76
  removeEmptyElements: [[false, 'Remove all elements with empty contents']],
68
77
  lint: [[false, 'Toggle linting']],
69
78
  keepClosingSlash: [[false, 'Keep the trailing slash on singleton elements']],
@@ -73,7 +82,10 @@ var mainOptions = {
73
82
  minifyURLs: [[false, 'Minify URLs in various attributes (uses relateurl)']],
74
83
  ignoreCustomComments: [[false, 'Array of regex\'es that allow to ignore certain comments, when matched', 'string'], 'json'],
75
84
  processScripts: [[false, 'Array of strings corresponding to types of script elements to process through minifier (e.g. "text/ng-template", "text/x-handlebars-template", etc.)', 'string'], 'json'],
76
- maxLineLength: [[false, 'Max line length', 'number'], true]
85
+ maxLineLength: [[false, 'Max line length', 'number'], true],
86
+ customAttrAssign: [[false, 'Arrays of regex\'es that allow to support custom attribute assign expressions (e.g. \'<div flex?="{{mode != cover}}"></div>\')', 'string'], 'json'],
87
+ customAttrSurround: [[false, 'Arrays of regex\'es that allow to support custom attribute surround expressions (e.g. <input {{#if value}}checked="checked"{{/if}}>)', 'string'], 'json'],
88
+ customAttrCollapse: [[false, 'Regex that specifies custom attribute to strip newlines from (e.g. /ng\-class/)', 'string'], true]
77
89
  };
78
90
 
79
91
  var cliOptions = {
@@ -91,6 +103,56 @@ cli.parse(cliOptions);
91
103
 
92
104
  cli.main(function(args, options) {
93
105
 
106
+ function parseJSONOption(value) {
107
+ if (value !== null) {
108
+ var jsonArray;
109
+ try {
110
+ jsonArray = JSON.parse(value);
111
+ }
112
+ catch (e) {}
113
+ if (jsonArray instanceof Array) {
114
+ return jsonArray;
115
+ }
116
+ else {
117
+ return [value];
118
+ }
119
+ }
120
+ }
121
+
122
+ function runMinify(original) {
123
+ var status = 0;
124
+ var minified = null;
125
+ try {
126
+ minified = minify(original, minifyOptions);
127
+ }
128
+ catch (e) {
129
+ status = 3;
130
+ process.stderr.write('Error: Minification error');
131
+ }
132
+
133
+ if (minifyOptions.lint) {
134
+ minifyOptions.lint.populate();
135
+ }
136
+
137
+ if (minified !== null) {
138
+ // Write the output
139
+ try {
140
+ if (output !== null) {
141
+ fs.writeFileSync(path.resolve(output), minified);
142
+ }
143
+ else {
144
+ process.stdout.write(minified);
145
+ }
146
+ }
147
+ catch (e) {
148
+ status = 4;
149
+ process.stderr.write('Error: Cannot write to output');
150
+ }
151
+ }
152
+
153
+ cli.exit(status);
154
+ }
155
+
94
156
  if (options.version) {
95
157
  process.stderr.write(appName + ' v' + appVersion);
96
158
  cli.exit(0);
@@ -126,6 +188,10 @@ cli.main(function(args, options) {
126
188
  }
127
189
  });
128
190
 
191
+ if (minifyOptions.lint === true) {
192
+ minifyOptions.lint = new HTMLLint();
193
+ }
194
+
129
195
  if (args.length) {
130
196
  input = args;
131
197
  }
@@ -134,104 +200,25 @@ cli.main(function(args, options) {
134
200
  output = options.output;
135
201
  }
136
202
 
137
- var original = '';
138
- var status = 0;
139
-
140
203
  if (input !== null) { // Minifying one or more files specified on the CMD line
141
204
 
205
+ var original = '';
206
+
142
207
  input.forEach(function(afile) {
143
208
  try {
144
209
  original += fs.readFileSync(afile, 'utf8');
145
210
  }
146
211
  catch (e) {
147
- status = 2;
148
212
  process.stderr.write('Error: Cannot read file ' + afile);
213
+ cli.exit(2);
149
214
  }
150
215
  });
151
216
 
152
- }
153
- else { // Minifying input coming from STDIN
154
-
155
- var BUFSIZE = 4096;
156
- var buf = new Buffer(BUFSIZE);
157
- var bytesRead;
158
-
159
- while (true) { // Loop as long as stdin input is available.
160
- bytesRead = 0;
161
- try {
162
- bytesRead = fs.readSync(process.stdin.fd, buf, 0, BUFSIZE);
163
- }
164
- catch (e) {
165
- if (e.code === 'EAGAIN') { // 'resource temporarily unavailable'
166
- // Happens on OS X 10.8.3 (not Windows 7!), if there's no
167
- // stdin input - typically when invoking a script without any
168
- // input (for interactive stdin input).
169
- // If you were to just continue, you'd create a tight loop.
170
- process.stderr.write('ERROR: interactive stdin input not supported');
171
- cli.exit(2);
172
- }
173
- else if (e.code === 'EOF') {
174
- // Happens on Windows 7, but not OS X 10.8.3:
175
- // simply signals the end of *piped* stdin input.
176
- break;
177
- }
178
- throw e; // unexpected exception
179
- }
180
- if (bytesRead === 0) {
181
- // No more stdin input available.
182
- // OS X 10.8.3: regardless of input method, this is how the end
183
- // of input is signaled.
184
- // Windows 7: this is how the end of input is signaled for
185
- // *interactive* stdin input.
186
- break;
187
- }
188
- original += buf.toString('utf8', 0, bytesRead);
189
- }
190
-
191
- }
192
-
193
- function parseJSONOption(value) {
194
- if (value !== null) {
195
- var jsonArray;
196
- try {
197
- jsonArray = JSON.parse(value);
198
- }
199
- catch (e) {}
200
- if (jsonArray instanceof Array) {
201
- return jsonArray;
202
- }
203
- else {
204
- return [value];
205
- }
206
- }
207
- }
217
+ runMinify(original);
208
218
 
209
- // Run minify
210
- var minified = null;
211
- try {
212
- minified = minify(original, minifyOptions);
213
- }
214
- catch (e) {
215
- status = 3;
216
- process.stderr.write('Error: Minification error');
217
219
  }
218
-
219
- if (minified !== null) {
220
- // Write the output
221
- try {
222
- if (output !== null) {
223
- fs.writeFileSync(path.resolve(output), minified);
224
- }
225
- else {
226
- process.stdout.write(minified);
227
- }
228
- }
229
- catch (e) {
230
- status = 4;
231
- process.stderr.write('Error: Cannot write to output');
232
- }
220
+ else { // Minifying input coming from STDIN
221
+ process.stdin.pipe(concat({ encoding: 'string' }, runMinify));
233
222
  }
234
223
 
235
- cli.exit(status);
236
-
237
224
  });
@@ -1,6 +1,6 @@
1
1
  /*!
2
- * HTMLMinifier v0.6.8 (http://kangax.github.io/html-minifier/)
3
- * Copyright 2010-2014 Juriy "kangax" Zaytsev
2
+ * HTMLMinifier v0.7.2 (http://kangax.github.io/html-minifier/)
3
+ * Copyright 2010-2015 Juriy "kangax" Zaytsev
4
4
  * Licensed under MIT (https://github.com/kangax/html-minifier/blob/gh-pages/LICENSE)
5
5
  */
6
6
  /*!
@@ -37,7 +37,7 @@
37
37
  'use strict';
38
38
 
39
39
  // Regular Expressions for parsing tags and attributes
40
- var singleAttrIdentifier = /([\w:-]+)/,
40
+ var singleAttrIdentifier = /([\w:\.-]+)/,
41
41
  singleAttrAssign = /=/,
42
42
  singleAttrAssigns = [ singleAttrAssign ],
43
43
  singleAttrValues = [
@@ -49,9 +49,7 @@
49
49
  startTagClose = /\s*(\/?)>/,
50
50
  endTag = /^<\/([\w:-]+)[^>]*>/,
51
51
  endingSlash = /\/>$/,
52
- doctype = /^<!DOCTYPE [^>]+>/i,
53
- startIgnore = /<(%|\?)/,
54
- endIgnore = /(%|\?)>/;
52
+ doctype = /^<!DOCTYPE [^>]+>/i;
55
53
 
56
54
  var IS_REGEX_CAPTURING_BROKEN = false;
57
55
  'x'.replace(/x(.)?/g, function(m, g) {
@@ -83,7 +81,7 @@
83
81
  var customStartTagAttrs;
84
82
 
85
83
  var startTagAttrs = new RegExp(
86
- '(?:\\s*[\\w:-]+'
84
+ '(?:\\s*[\\w:\\.-]+'
87
85
  + '(?:\\s*'
88
86
  + '(?:' + joinSingleAttrAssigns(handler) + ')'
89
87
  + '\\s*(?:(?:"[^"]*")|(?:\'[^\']*\')|[^>\\s]+)'
@@ -197,13 +195,23 @@
197
195
  }
198
196
 
199
197
  // Ignored elements?
200
- else if (html.search(startIgnore) === 0) {
201
- index = html.search(endIgnore); // Find closing tag.
202
- if (index >= 0) { // Found?
203
- // @TODO: Pass matched open/close tags back to handler.
204
- handler.ignore && handler.ignore(html.substring(0, index + 2)); // Return ignored string if callback exists.
205
- html = html.substring(index + 2); // Next starting point for parser.
206
- chars = false; // Chars flag.
198
+ else if ( /^<\?/.test( html ) ) {
199
+ index = html.indexOf( '?>', 2 );
200
+ if ( index >= 0 ) {
201
+ if ( handler.chars ) {
202
+ handler.chars( html.substring( 0, index + 2 ) );
203
+ }
204
+ html = html.substring( index + 2 );
205
+ }
206
+ }
207
+
208
+ else if ( /^<%/.test( html ) ) {
209
+ index = html.indexOf( '%>', 2 );
210
+ if ( index >= 0 ) {
211
+ if ( handler.chars ) {
212
+ handler.chars(html.substring( 0, index + 2) );
213
+ }
214
+ html = html.substring( index + 2 );
207
215
  }
208
216
  }
209
217
 
@@ -227,8 +235,8 @@
227
235
  chars = false;
228
236
  }
229
237
 
230
- // Start tag:
231
238
  }
239
+ // Start tag:
232
240
  else if ( /^</.test( html ) ) {
233
241
  match = html.match( startTag );
234
242
  if ( match ) {
@@ -314,7 +322,7 @@
314
322
  var attrs = [];
315
323
 
316
324
  rest.replace(attr, function () {
317
- var name, value, fallbackValue, customOpen, customClose, customAssign;
325
+ var name, value, fallbackValue, customOpen, customClose, customAssign, quote;
318
326
  var ncp = 7; // number of captured parts, scalar
319
327
 
320
328
  // hackish work around FF bug https://bugzilla.mozilla.org/show_bug.cgi?id=369778
@@ -329,6 +337,12 @@
329
337
  customAssign = arguments[2];
330
338
  fallbackValue = arguments[3];
331
339
  value = fallbackValue || arguments[4] || arguments[5];
340
+
341
+ if (customAssign) {
342
+ quote = arguments[0].charAt(name.length + customAssign.length);
343
+ quote = (quote === '\'' || quote === '"') ? quote : '';
344
+ }
345
+
332
346
  }
333
347
  else if ( handler.customAttrSurround ) {
334
348
  for ( var i = handler.customAttrSurround.length - 1; i >= 0; i-- ) {
@@ -353,10 +367,13 @@
353
367
  attrs.push({
354
368
  name: name,
355
369
  value: value,
356
- escaped: value && value.replace(/(^|[^\\])"/g, '$1&quot;'),
370
+ escaped: value && value.replace(/(^|.)("+)/g, function(match) {
371
+ return match.replace(/"/g, '&quot;');
372
+ }),
357
373
  customAssign: customAssign || '=',
358
374
  customOpen: customOpen || '',
359
- customClose: customClose || ''
375
+ customClose: customClose || '',
376
+ quote: quote || ''
360
377
  });
361
378
  });
362
379
 
@@ -602,15 +619,15 @@
602
619
  lineBreakAfter = /[\t\n\r ]*[\n\r]+[\t ]*$/,
603
620
  preserveBefore = lineBreakBefore.test(str) ? '\n' : ' ',
604
621
  preserveAfter = lineBreakAfter.test(str) ? '\n' : ' ',
605
- lineBreakStamp = '[{htmlmin-lb}]';
622
+ lineBreakStamp = 'htmlmincollapsedlinebreak';
606
623
 
607
- if (prevTag && prevTag !== 'img' && prevTag !== 'input' && (prevTag.substr(0,1) !== '/'
608
- || ( prevTag.substr(0,1) === '/' && tags.indexOf(prevTag.substr(1)) === -1))) {
624
+ if (prevTag && prevTag !== 'img' && prevTag !== 'input' && (prevTag.substr(0, 1) !== '/'
625
+ || (prevTag.substr(0, 1) === '/' && tags.indexOf(prevTag.substr(1)) === -1))) {
609
626
  str = str.replace(/^\s+/, options.conservativeCollapse ? ' ' : options.preserveLineBreaks ? preserveBefore : '');
610
627
  }
611
628
 
612
- if (nextTag && nextTag !== 'img' && nextTag !== 'input' && (nextTag.substr(0,1) === '/'
613
- || ( nextTag.substr(0,1) !== '/' && tags.indexOf(nextTag) === -1))) {
629
+ if (nextTag && nextTag !== 'img' && nextTag !== 'input' && (nextTag.substr(0, 1) === '/'
630
+ || (nextTag.substr(0, 1) !== '/' && tags.indexOf(nextTag) === -1))) {
614
631
  str = str.replace(/\s+$/, options.conservativeCollapse ? ' ' : options.preserveLineBreaks ? preserveAfter : '');
615
632
  }
616
633
 
@@ -624,7 +641,7 @@
624
641
  // strip non space whitespace then compress spaces to one
625
642
  return str
626
643
  .replace(/[\t\n\r]+/g, ' ').replace(/[ ]+/g, ' ')
627
- .replace(lineBreakStamp, '\n');
644
+ .replace(new RegExp(lineBreakStamp, 'g'), '\n');
628
645
  }
629
646
 
630
647
  return str;
@@ -656,13 +673,13 @@
656
673
 
657
674
  function canRemoveAttributeQuotes(value) {
658
675
  // http://mathiasbynens.be/notes/unquoted-attribute-values
659
- return (/^[^\x20\t\n\f\r"'`=<>]+$/).test(value) && !(/\/$/ ).test(value) &&
676
+ return (/^[^\x20\t\n\f\r"'`=<>]+$/).test(value) && !(/\/$/).test(value) &&
660
677
  // make sure trailing slash is not interpreted as HTML self-closing tag
661
678
  !(/\/$/).test(value);
662
679
  }
663
680
 
664
681
  function attributesInclude(attributes, attribute) {
665
- for (var i = attributes.length; i--; ) {
682
+ for (var i = attributes.length; i--;) {
666
683
  if (attributes[i].name.toLowerCase() === attribute) {
667
684
  return true;
668
685
  }
@@ -708,6 +725,31 @@
708
725
  );
709
726
  }
710
727
 
728
+ // https://mathiasbynens.be/demo/javascript-mime-type
729
+ // https://developer.mozilla.org/en/docs/Web/HTML/Element/script#attr-type
730
+ var executableScriptsMimetypes = {
731
+ 'text/javascript': 1,
732
+ 'text/ecmascript': 1,
733
+ 'text/jscript': 1,
734
+ 'application/javascript': 1,
735
+ 'application/x-javascript': 1,
736
+ 'application/ecmascript': 1
737
+ };
738
+
739
+ function isExecutableScript(tag, attrs) {
740
+ if (tag !== 'script') {
741
+ return false;
742
+ }
743
+ for (var i = 0, len = attrs.length; i < len; i++) {
744
+ var attrName = attrs[i].name.toLowerCase();
745
+ if (attrName === 'type') {
746
+ return attrs[i].value === '' ||
747
+ executableScriptsMimetypes[attrs[i].value] === 1;
748
+ }
749
+ }
750
+ return true;
751
+ }
752
+
711
753
  function isStyleLinkTypeAttribute(tag, attrName, attrValue) {
712
754
  return (
713
755
  (tag === 'style' || tag === 'link') &&
@@ -791,14 +833,14 @@
791
833
  attrValue = attrValue.replace(/\s*;\s*$/, '');
792
834
  }
793
835
  if (options.minifyCSS) {
794
- return minifyCSS(attrValue, options.minifyCSS);
836
+ return minifyCSS(attrValue, options.minifyCSS, true);
795
837
  }
796
838
  return attrValue;
797
839
  }
798
840
  else if (isMetaViewport(tag, attrs) && attrName === 'content') {
799
841
  attrValue = attrValue.replace(/1\.0/g, '1').replace(/\s+/g, '');
800
842
  }
801
- else if (options.customAttrCollapse && options.customAttrCollapse.test(attrName)) {
843
+ else if (attrValue && options.customAttrCollapse && options.customAttrCollapse.test(attrName)) {
802
844
  attrValue = attrValue.replace(/\n+/g, '');
803
845
  }
804
846
  return attrValue;
@@ -815,6 +857,22 @@
815
857
  }
816
858
  }
817
859
 
860
+ // Wrap CSS declarations for CleanCSS > 3.x
861
+ // See https://github.com/jakubpawlowicz/clean-css/issues/418
862
+ function wrapCSS(text) {
863
+ return '*{' + text + '}';
864
+ }
865
+
866
+ function unwrapCSS(text) {
867
+ var matches = text.match(/^\*\{([\s\S]*)\}$/m);
868
+ if (matches && matches[1]) {
869
+ return matches[1];
870
+ }
871
+ else {
872
+ return text;
873
+ }
874
+ }
875
+
818
876
  function cleanConditionalComment(comment) {
819
877
  return comment
820
878
  .replace(/^(\[[^\]]+\]>)\s*/, '$1')
@@ -905,7 +963,8 @@
905
963
  function normalizeAttribute(attr, attrs, tag, unarySlash, index, options) {
906
964
 
907
965
  var attrName = options.caseSensitive ? attr.name : attr.name.toLowerCase(),
908
- attrValue = attr.escaped,
966
+ attrValue = options.preventAttributesEscaping ? attr.value : attr.escaped,
967
+ attrQuote = options.preventAttributesEscaping ? attr.quote : '"',
909
968
  attrFragment,
910
969
  emittedAttrValue,
911
970
  isTerminalOfUnarySlash = unarySlash && index === attrs.length - 1;
@@ -925,7 +984,7 @@
925
984
 
926
985
  if (attrValue !== undefined && !options.removeAttributeQuotes ||
927
986
  !canRemoveAttributeQuotes(attrValue) || isTerminalOfUnarySlash) {
928
- emittedAttrValue = '"' + attrValue + '"';
987
+ emittedAttrValue = attrQuote + attrValue + attrQuote;
929
988
  }
930
989
  else {
931
990
  emittedAttrValue = attrValue;
@@ -949,7 +1008,7 @@
949
1008
 
950
1009
  function setDefaultTesters(options) {
951
1010
 
952
- var defaultTesters = ['canCollapseWhitespace','canTrimWhitespace'];
1011
+ var defaultTesters = ['canCollapseWhitespace', 'canTrimWhitespace'];
953
1012
 
954
1013
  for (var i = 0, len = defaultTesters.length; i < len; i++) {
955
1014
  if (!options[defaultTesters[i]]) {
@@ -996,7 +1055,9 @@
996
1055
  options = { };
997
1056
  }
998
1057
  options.fromString = true;
999
- options.output = { inline_script: true };
1058
+ var outputOptions = options.output || {};
1059
+ outputOptions.inline_script = true;
1060
+ options.output = outputOptions;
1000
1061
 
1001
1062
  try {
1002
1063
  // try to get global reference first
@@ -1044,20 +1105,28 @@
1044
1105
  return text;
1045
1106
  }
1046
1107
 
1047
- function minifyCSS(text, options) {
1108
+ function minifyCSS(text, options, inline) {
1048
1109
  if (typeof options !== 'object') {
1049
1110
  options = { };
1050
1111
  }
1051
- if (typeof options.noAdvanced === 'undefined') {
1052
- options.noAdvanced = true;
1112
+ if (typeof options.advanced === 'undefined') {
1113
+ options.advanced = false;
1053
1114
  }
1054
1115
  try {
1116
+ var cleanCSS;
1117
+
1055
1118
  if (typeof CleanCSS !== 'undefined') {
1056
- return new CleanCSS(options).minify(text);
1119
+ cleanCSS = new CleanCSS(options);
1057
1120
  }
1058
1121
  else if (typeof require === 'function') {
1059
1122
  var CleanCSSModule = require('clean-css');
1060
- return new CleanCSSModule(options).minify(text);
1123
+ cleanCSS = new CleanCSSModule(options);
1124
+ }
1125
+ if (inline) {
1126
+ return unwrapCSS(cleanCSS.minify(wrapCSS(text)).styles);
1127
+ }
1128
+ else {
1129
+ return cleanCSS.minify(text).styles;
1061
1130
  }
1062
1131
  }
1063
1132
  catch (err) {
@@ -1069,6 +1138,8 @@
1069
1138
  function minify(value, options) {
1070
1139
 
1071
1140
  options = options || {};
1141
+ var optionsStack = [];
1142
+
1072
1143
  value = trimWhitespace(value);
1073
1144
  setDefaultTesters(options);
1074
1145
 
@@ -1083,6 +1154,12 @@
1083
1154
  isIgnoring = false,
1084
1155
  t = new Date();
1085
1156
 
1157
+ if (options.removeIgnored) {
1158
+ value = value
1159
+ .replace(/<\?[^\?]+\?>/g, '')
1160
+ .replace(/<%[^%]+%>/g, '');
1161
+ }
1162
+
1086
1163
  function _canCollapseWhitespace(tag, attrs) {
1087
1164
  return canCollapseWhitespace(tag) || options.canCollapseWhitespace(tag, attrs);
1088
1165
  }
@@ -1094,14 +1171,27 @@
1094
1171
  new HTMLParser(value, {
1095
1172
  html5: typeof options.html5 !== 'undefined' ? options.html5 : true,
1096
1173
 
1097
- start: function( tag, attrs, unary, unarySlash ) {
1098
-
1174
+ start: function(tag, attrs, unary, unarySlash) {
1099
1175
  if (isIgnoring) {
1100
1176
  buffer.push('<' + tag, attrsToMarkup(attrs), unarySlash ? '/' : '', '>');
1101
1177
  return;
1102
1178
  }
1103
1179
 
1104
- tag = options.caseSensitive ? tag : tag.toLowerCase();
1180
+ var lowerTag = tag.toLowerCase();
1181
+
1182
+ if (lowerTag === 'svg') {
1183
+ optionsStack.push(options);
1184
+ var nextOptions = {};
1185
+ for (var key in options) {
1186
+ nextOptions[key] = options[key];
1187
+ }
1188
+ nextOptions.keepClosingSlash = true;
1189
+ nextOptions.caseSensitive = true;
1190
+ options = nextOptions;
1191
+ }
1192
+
1193
+ tag = options.caseSensitive ? tag : lowerTag;
1194
+
1105
1195
  currentTag = tag;
1106
1196
  currentChars = '';
1107
1197
  currentAttrs = attrs;
@@ -1118,31 +1208,40 @@
1118
1208
 
1119
1209
  var openTag = '<' + tag;
1120
1210
  var closeTag = ((unarySlash && options.keepClosingSlash) ? '/' : '') + '>';
1121
- if ( attrs.length === 0) {
1211
+ if (attrs.length === 0) {
1122
1212
  openTag += closeTag;
1123
1213
  }
1124
1214
 
1125
1215
  buffer.push(openTag);
1126
1216
 
1127
- lint && lint.testElement(tag);
1217
+ if (lint) {
1218
+ lint.testElement(tag);
1219
+ }
1128
1220
 
1129
1221
  var token;
1130
- for ( var i = 0, len = attrs.length; i < len; i++ ) {
1131
- lint && lint.testAttribute(tag, attrs[i].name.toLowerCase(), attrs[i].escaped);
1222
+ for (var i = 0, len = attrs.length; i < len; i++) {
1223
+ if (lint) {
1224
+ lint.testAttribute(tag, attrs[i].name.toLowerCase(), attrs[i].escaped);
1225
+ }
1132
1226
  token = normalizeAttribute(attrs[i], attrs, tag, unarySlash, i, options);
1133
- if ( i === len - 1 ) {
1227
+ if (i === len - 1) {
1134
1228
  token += closeTag;
1135
1229
  }
1136
1230
  buffer.push(token);
1137
1231
  }
1138
1232
  },
1139
- end: function( tag, attrs ) {
1233
+ end: function(tag, attrs) {
1140
1234
 
1141
1235
  if (isIgnoring) {
1142
1236
  buffer.push('</' + tag + '>');
1143
1237
  return;
1144
1238
  }
1145
1239
 
1240
+ var lowerTag = tag.toLowerCase();
1241
+ if (lowerTag === 'svg') {
1242
+ options = optionsStack.pop();
1243
+ }
1244
+
1146
1245
  // check if current tag is in a whitespace stack
1147
1246
  if (options.collapseWhitespace) {
1148
1247
  if (stackNoTrimWhitespace.length &&
@@ -1158,8 +1257,8 @@
1158
1257
  var isElementEmpty = currentChars === '' && tag === currentTag;
1159
1258
  if ((options.removeEmptyElements && isElementEmpty && canRemoveElement(tag, attrs))) {
1160
1259
  // remove last "element" from buffer, return
1161
- for ( var i = buffer.length - 1; i >= 0; i-- ) {
1162
- if ( /^<[^\/!]/.test(buffer[i]) ) {
1260
+ for (var i = buffer.length - 1; i >= 0; i--) {
1261
+ if (/^<[^\/!]/.test(buffer[i])) {
1163
1262
  buffer.splice(i);
1164
1263
  break;
1165
1264
  }
@@ -1172,14 +1271,17 @@
1172
1271
  }
1173
1272
  else {
1174
1273
  // push end tag to buffer
1175
- buffer.push('</' + (options.caseSensitive ? tag : tag.toLowerCase()) + '>');
1274
+ buffer.push('</' + (options.caseSensitive ? tag : lowerTag) + '>');
1176
1275
  results.push.apply(results, buffer);
1177
1276
  }
1178
1277
  // flush buffer
1179
1278
  buffer.length = 0;
1180
1279
  currentChars = '';
1181
1280
  },
1182
- chars: function( text, prevTag, nextTag ) {
1281
+ chars: function(text, prevTag, nextTag) {
1282
+ prevTag = prevTag === '' ? 'comment' : prevTag;
1283
+ nextTag = nextTag === '' ? 'comment' : nextTag;
1284
+
1183
1285
  if (isIgnoring) {
1184
1286
  buffer.push(text);
1185
1287
  return;
@@ -1196,7 +1298,7 @@
1196
1298
  text = processScript(text, options, currentAttrs);
1197
1299
  }
1198
1300
  }
1199
- if (currentTag === 'script' && options.minifyJS) {
1301
+ if (options.minifyJS && isExecutableScript(currentTag, currentAttrs)) {
1200
1302
  text = minifyJS(text, options.minifyJS);
1201
1303
  }
1202
1304
  if (currentTag === 'style' && options.minifyCSS) {
@@ -1204,7 +1306,7 @@
1204
1306
  }
1205
1307
  if (options.collapseWhitespace) {
1206
1308
  if (!stackNoTrimWhitespace.length) {
1207
- text = (prevTag || nextTag) ?
1309
+ text = ((prevTag && prevTag !== 'comment') || (nextTag && nextTag !== 'comment')) ?
1208
1310
  collapseWhitespaceSmart(text, prevTag, nextTag, options)
1209
1311
  : trimWhitespace(text);
1210
1312
  }
@@ -1213,10 +1315,12 @@
1213
1315
  }
1214
1316
  }
1215
1317
  currentChars = text;
1216
- lint && lint.testChars(text);
1318
+ if (lint) {
1319
+ lint.testChars(text);
1320
+ }
1217
1321
  buffer.push(text);
1218
1322
  },
1219
- comment: function( text, nonStandard ) {
1323
+ comment: function(text, nonStandard) {
1220
1324
 
1221
1325
  var prefix = nonStandard ? '<!' : '<!--';
1222
1326
  var suffix = nonStandard ? '>' : '-->';
@@ -1244,10 +1348,6 @@
1244
1348
  }
1245
1349
  buffer.push(text);
1246
1350
  },
1247
- ignore: function(text) {
1248
- // `text` === strings that start with `<?` or `<%` and end with `?>` or `%>`.
1249
- buffer.push(options.removeIgnored ? '' : text); // `text` allowed by default.
1250
- },
1251
1351
  doctype: function(doctype) {
1252
1352
  buffer.push(options.useShortDoctype ? '<!DOCTYPE html>' : collapseWhitespace(doctype));
1253
1353
  },
@@ -1261,16 +1361,16 @@
1261
1361
  return str;
1262
1362
  }
1263
1363
 
1264
- function joinResultSegments( results, options ) {
1364
+ function joinResultSegments(results, options) {
1265
1365
  var str;
1266
1366
  var maxLineLength = options.maxLineLength;
1267
- if ( maxLineLength ) {
1367
+ if (maxLineLength) {
1268
1368
  var token;
1269
1369
  var lines = [];
1270
1370
  var line = '';
1271
- for ( var i = 0, len = results.length; i < len; i++ ) {
1371
+ for (var i = 0, len = results.length; i < len; i++) {
1272
1372
  token = results[i];
1273
- if ( line.length + token.length < maxLineLength ) {
1373
+ if (line.length + token.length < maxLineLength) {
1274
1374
  line += token;
1275
1375
  }
1276
1376
  else {
@@ -1290,7 +1390,7 @@
1290
1390
  }
1291
1391
 
1292
1392
  // for CommonJS enviroments, export everything
1293
- if ( typeof exports !== 'undefined' ) {
1393
+ if (typeof exports !== 'undefined') {
1294
1394
  exports.minify = minify;
1295
1395
  }
1296
1396
  else {
@@ -1320,7 +1420,7 @@
1320
1420
  return (/^on[a-z]+/).test(attrName);
1321
1421
  }
1322
1422
  function isStyleAttribute(attrName) {
1323
- return ('style' === attrName.toLowerCase());
1423
+ return (attrName.toLowerCase() === 'style');
1324
1424
  }
1325
1425
  function isDeprecatedAttribute(tag, attrName) {
1326
1426
  return (
@@ -1,6 +1,6 @@
1
1
  /*!
2
- * HTMLMinifier v0.6.8 (http://kangax.github.io/html-minifier/)
3
- * Copyright 2010-2014 Juriy "kangax" Zaytsev
2
+ * HTMLMinifier v0.7.2 (http://kangax.github.io/html-minifier/)
3
+ * Copyright 2010-2015 Juriy "kangax" Zaytsev
4
4
  * Licensed under MIT (https://github.com/kangax/html-minifier/blob/gh-pages/LICENSE)
5
5
  */
6
- !function(a){"use strict";function b(a){var b,c=new RegExp("(?:\\s*[\\w:-]+(?:\\s*(?:"+d(a)+")\\s*(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>\\s]+))?)*");if(a.customAttrSurround){for(var e=[],f=a.customAttrSurround.length-1;f>=0;f--)e[f]="(?:\\s*"+a.customAttrSurround[f][0].source+c.source+a.customAttrSurround[f][1].source+")";e.unshift(c.source),b=new RegExp("((?:"+e.join("|")+")*)")}else b=new RegExp("("+c.source+")");return new RegExp(j.source+b.source+k.source)}function c(a){var b=new RegExp(f.source+"(?:\\s*("+d(a)+")\\s*(?:"+i.join("|")+"))?");if(a.customAttrSurround){for(var c=[],e=a.customAttrSurround.length-1;e>=0;e--)c[e]="(?:("+a.customAttrSurround[e][0].source+")"+b.source+"("+a.customAttrSurround[e][1].source+"))";return c.unshift("(?:"+b.source+")"),new RegExp(c.join("|"),"g")}return new RegExp(b.source,"g")}function d(a){return h.concat(a.customAttrAssign||[]).map(function(a){return"(?:"+a.source+")"}).join("|")}function e(a){for(var b={},c=a.split(","),d=0;d<c.length;d++)b[c[d]]=!0,b[c[d].toUpperCase()]=!0;return b}var f=/([\w:-]+)/,g=/=/,h=[g],i=[/"((?:\\.|[^"])*)"/.source,/'((?:\\.|[^'])*)'/.source,/([^>\s]+)/.source],j=/^<([\w:-]+)/,k=/\s*(\/?)>/,l=/^<\/([\w:-]+)[^>]*>/,m=/\/>$/,n=/^<!DOCTYPE [^>]+>/i,o=/<(%|\?)/,p=/(%|\?)>/,q=!1;"x".replace(/x(.)?/g,function(a,b){q=""===b});var r,s,t,u=e("area,base,basefont,br,col,frame,hr,img,input,isindex,link,meta,param,embed,wbr"),v=e("a,abbr,acronym,applet,b,basefont,bdo,big,br,button,cite,code,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,noscript,object,q,s,samp,script,select,small,span,strike,strong,sub,sup,svg,textarea,tt,u,var"),w=e("colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr,source"),x=e("checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected"),y=e("script,style,noscript"),z={},A=a.HTMLParser=function(a,d){function e(a,b,c,e){for(var g=!1;!d.html5&&A.last()&&v[A.last()];)f("",A.last());w[b]&&A.last()===b&&f("",b),e=u[b]||!!e;var h=[];c.replace(D,function(){var a,b,c,e,f,g,i=7;if(q&&-1===arguments[0].indexOf('""')&&(""===arguments[3]&&(arguments[3]=void 0),""===arguments[4]&&(arguments[4]=void 0),""===arguments[5]&&(arguments[5]=void 0)),a=arguments[1])g=arguments[2],c=arguments[3],b=c||arguments[4]||arguments[5];else if(d.customAttrSurround)for(var j=d.customAttrSurround.length-1;j>=0;j--)if(a=arguments[j*i+7],g=arguments[j*i+8],a){c=arguments[j*i+9],b=c||arguments[j*i+10]||arguments[j*i+11],e=arguments[j*i+6],f=arguments[j*i+12];break}void 0===b&&(b=x[a]?a:c),h.push({name:a,value:b,escaped:b&&b.replace(/(^|[^\\])"/g,"$1&quot;"),customAssign:g||"=",customOpen:e||"",customClose:f||""})}),e?g=a.match(m):A.push({tag:b,attrs:h}),d.start&&d.start(b,h,e,g)}function f(a,b){var c;if(b){var e=b.toLowerCase();for(c=A.length-1;c>=0&&A[c].tag.toLowerCase()!==e;c--);}else c=0;if(c>=0){for(var f=A.length-1;f>=c;f--)d.end&&d.end(A[f].tag,A[f].attrs);A.length=c}}var g,h,i,j,k,A=[],B=a;A.last=function(){var a=this[this.length-1];return a&&a.tag};for(var C=b(d),D=c(d);a;){if(h=!0,A.last()&&y[A.last()])r=A.last().toLowerCase(),s=z[r]||(z[r]=new RegExp("([\\s\\S]*?)</"+r+"[^>]*>","i")),a=a.replace(s,function(a,b){return"script"!==r&&"style"!==r&&"noscript"!==r&&(b=b.replace(/<!--([\s\S]*?)-->/g,"$1").replace(/<!\[CDATA\[([\s\S]*?)\]\]>/g,"$1")),d.chars&&d.chars(b),""}),f("",r);else if(/^<!--/.test(a)&&(g=a.indexOf("-->"),g>=0&&(d.comment&&d.comment(a.substring(4,g)),a=a.substring(g+3),h=!1)),/^<!\[/.test(a)?(g=a.indexOf("]>"),g>=0&&(d.comment&&d.comment(a.substring(2,g+1),!0),a=a.substring(g+2),h=!1)):0===a.search(o)?(g=a.search(p),g>=0&&(d.ignore&&d.ignore(a.substring(0,g+2)),a=a.substring(g+2),h=!1)):(i=n.exec(a))?(d.doctype&&d.doctype(i[0]),a=a.substring(i[0].length),h=!1):/^<\//.test(a)?(i=a.match(l),i&&(a=a.substring(i[0].length),i[0].replace(l,f),j="/"+i[1].toLowerCase(),h=!1)):/^</.test(a)&&(i=a.match(C),i&&(a=a.substring(i[0].length),i[0].replace(C,e),j=i[1].toLowerCase(),h=!1)),h){g=a.indexOf("<");var E=0>g?a:a.substring(0,g);a=0>g?"":a.substring(g),t=a.match(C),t?k=t[1]:(t=a.match(l),k=t?"/"+t[1]:""),d.chars&&d.chars(E,j,k)}if(a===B)throw"Parse Error: "+a;B=a}f()};a.HTMLtoXML=function(a){var b="";return new A(a,{start:function(a,c,d){b+="<"+a;for(var e=0;e<c.length;e++)b+=" "+c[e].name+'="'+c[e].escaped+'"';b+=(d?"/":"")+">"},end:function(a){b+="</"+a+">"},chars:function(a){b+=a},comment:function(a){b+="<!--"+a+"-->"},ignore:function(a){b+=a}}),b},a.HTMLtoDOM=function(a,b){var c=e("html,head,body,title"),d={link:"head",base:"head"};b?b=b.ownerDocument||b.getOwnerDocument&&b.getOwnerDocument()||b:"undefined"!=typeof DOMDocument?b=new DOMDocument:"undefined"!=typeof document&&document.implementation&&document.implementation.createDocument?b=document.implementation.createDocument("","",null):"undefined"!=typeof ActiveX&&(b=new ActiveXObject("Msxml.DOMDocument"));var f=[],g=b.documentElement||b.getDocumentElement&&b.getDocumentElement();if(!g&&b.createElement&&!function(){var a=b.createElement("html"),c=b.createElement("head");c.appendChild(b.createElement("title")),a.appendChild(c),a.appendChild(b.createElement("body")),b.appendChild(a)}(),b.getElementsByTagName)for(var h in c)c[h]=b.getElementsByTagName(h)[0];var i=c.body;return new A(a,{start:function(a,e,g){if(c[a])return void(i=c[a]);var h=b.createElement(a);for(var j in e)h.setAttribute(e[j].name,e[j].value);d[a]&&"boolean"!=typeof c[d[a]]?c[d[a]].appendChild(h):i&&i.appendChild&&i.appendChild(h),g||(f.push(h),i=h)},end:function(){f.length-=1,i=f[f.length-1]},chars:function(a){i.appendChild(b.createTextNode(a))},comment:function(){},ignore:function(){}}),b}}("undefined"==typeof exports?this:exports),function(a){"use strict";function b(a){return a?a.replace(/[\t\n\r ]+/g," "):a}function c(a,b,c,d){var e=["a","abbr","acronym","b","bdi","bdo","big","button","cite","code","del","dfn","em","font","i","ins","kbd","mark","q","rt","rp","s","samp","small","span","strike","strong","sub","sup","svg","time","tt","u","var"],f=/^[\t ]*[\n\r]+[\t\n\r ]*/,g=/[\t\n\r ]*[\n\r]+[\t ]*$/,h=f.test(a)?"\n":" ",i=g.test(a)?"\n":" ",j="[{htmlmin-lb}]";return b&&"img"!==b&&"input"!==b&&("/"!==b.substr(0,1)||"/"===b.substr(0,1)&&-1===e.indexOf(b.substr(1)))&&(a=a.replace(/^\s+/,d.conservativeCollapse?" ":d.preserveLineBreaks?h:"")),c&&"img"!==c&&"input"!==c&&("/"===c.substr(0,1)||"/"!==c.substr(0,1)&&-1===e.indexOf(c))&&(a=a.replace(/\s+$/,d.conservativeCollapse?" ":d.preserveLineBreaks?i:"")),b&&c?(d.preserveLineBreaks&&(a=a.replace(f,j).replace(g,j)),a.replace(/[\t\n\r]+/g," ").replace(/[ ]+/g," ").replace(j,"\n")):a}function d(a){return/\[if[^\]]+\]/.test(a)||/\s*((?:<!)?\[endif\])$/.test(a)}function e(a,b){if(/^!/.test(a))return!0;if(b.ignoreCustomComments)for(var c=0,d=b.ignoreCustomComments.length;d>c;c++)if(b.ignoreCustomComments[c].test(a))return!0;return!1}function f(a){return/^on[a-z]+/.test(a)}function g(a){return/^[^\x20\t\n\f\r"'`=<>]+$/.test(a)&&!/\/$/.test(a)&&!/\/$/.test(a)}function h(a,b){for(var c=a.length;c--;)if(a[c].name.toLowerCase()===b)return!0;return!1}function i(a,b,c,d){return c=c?J(c.toLowerCase()):"","script"===a&&"language"===b&&"javascript"===c||"form"===a&&"method"===b&&"get"===c||"input"===a&&"type"===b&&"text"===c||"script"===a&&"charset"===b&&!h(d,"src")||"a"===a&&"name"===b&&h(d,"id")||"area"===a&&"shape"===b&&"rect"===c}function j(a,b,c){return"script"===a&&"type"===b&&"text/javascript"===J(c.toLowerCase())}function k(a,b,c){return("style"===a||"link"===a)&&"type"===b&&"text/css"===J(c.toLowerCase())}function l(a,b){var c=/^(?:allowfullscreen|async|autofocus|autoplay|checked|compact|controls|declare|default|defaultchecked|defaultmuted|defaultselected|defer|disabled|enabled|formnovalidate|hidden|indeterminate|inert|ismap|itemscope|loop|multiple|muted|nohref|noresize|noshade|novalidate|nowrap|open|pauseonexit|readonly|required|reversed|scoped|seamless|selected|sortable|spellcheck|truespeed|typemustmatch|visible)$/i.test(a);if(c)return!0;var d=K[a.toLowerCase()];return d?-1===d.indexOf(b.toLowerCase()):!1}function m(a,b){return/^(?:a|area|link|base)$/.test(b)&&"href"===a||"img"===b&&/^(?:src|longdesc|usemap)$/.test(a)||"object"===b&&/^(?:classid|codebase|data|usemap)$/.test(a)||"q"===b&&"cite"===a||"blockquote"===b&&"cite"===a||("ins"===b||"del"===b)&&"cite"===a||"form"===b&&"action"===a||"input"===b&&("src"===a||"usemap"===a)||"head"===b&&"profile"===a||"script"===b&&("src"===a||"for"===a)}function n(a,b){return/^(?:a|area|object|button)$/.test(b)&&"tabindex"===a||"input"===b&&("maxlength"===a||"tabindex"===a)||"select"===b&&("size"===a||"tabindex"===a)||"textarea"===b&&/^(?:rows|cols|tabindex)$/.test(a)||"colgroup"===b&&"span"===a||"col"===b&&"span"===a||("th"===b||"td"===b)&&("rowspan"===a||"colspan"===a)}function o(a,c,d,e,g){if(d&&f(c)){if(d=J(d).replace(/^javascript:\s*/i,"").replace(/\s*;$/,""),e.minifyJS){var h="(function(){"+d+"})()",i=D(h,e.minifyJS);return i.slice(12,i.length-4).replace(/"/g,"&quot;")}return d}return"class"===c?b(J(d)):m(c,a)?(d=J(d),e.minifyURLs?C(d,e.minifyURLs):d):n(c,a)?J(d):"style"===c?(d=J(d),d&&(d=d.replace(/\s*;\s*$/,"")),e.minifyCSS?E(d,e.minifyCSS):d):(p(a,g)&&"content"===c?d=d.replace(/1\.0/g,"1").replace(/\s+/g,""):e.customAttrCollapse&&e.customAttrCollapse.test(c)&&(d=d.replace(/\n+/g,"")),d)}function p(a,b){if("meta"!==a)return!1;for(var c=0,d=b.length;d>c;c++)if("name"===b[c].name&&"viewport"===b[c].value)return!0}function q(a){return a.replace(/^(\[[^\]]+\]>)\s*/,"$1").replace(/\s*(<!\[endif\])$/,"$1")}function r(a){return a.replace(/^(?:\s*\/\*\s*<!\[CDATA\[\s*\*\/|\s*\/\/\s*<!\[CDATA\[.*)/,"").replace(/(?:\/\*\s*\]\]>\s*\*\/|\/\/\s*\]\]>)\s*$/,"")}function s(a,b,c){for(var d=0,e=c.length;e>d;d++)if("type"===c[d].name.toLowerCase()&&b.processScripts.indexOf(c[d].value)>-1)return F(a,b);return a}function t(a,b){return a.replace(L[b],"").replace(M[b],"")}function u(a){return/^(?:html|t?body|t?head|tfoot|tr|td|th|dt|dd|option|colgroup|source)$/.test(a)}function v(a,b,c){var d=!c||/^\s*$/.test(c);return d?"input"===a&&"value"===b||N.test(b):!1}function w(a,b){if("textarea"===a)return!1;if("script"===a)for(var c=b.length-1;c>=0;c--)if("src"===b[c].name)return!1;return!0}function x(a){return!/^(?:script|style|pre|textarea)$/.test(a)}function y(a){return!/^(?:pre|textarea)$/.test(a)}function z(a){for(var b="",c=0,d=a.length;d>c;c++)b+=" "+a[c].name+(l(a[c].value)?"":'="'+a[c].value+'"');return b}function A(a,b,c,d,e,f){var h,m,n=f.caseSensitive?a.name:a.name.toLowerCase(),p=a.escaped,q=d&&e===b.length-1;return f.removeRedundantAttributes&&i(c,n,p,b)||f.removeScriptTypeAttributes&&j(c,n,p)||f.removeStyleLinkTypeAttributes&&k(c,n,p)?"":(p=o(c,n,p,f,b),m=void 0!==p&&!f.removeAttributeQuotes||!g(p)||q?'"'+p+'"':p,f.removeEmptyAttributes&&v(c,n,p)?"":(h=void 0===p||f.collapseBooleanAttributes&&l(n,p)?n:n+a.customAssign+m," "+a.customOpen+h+a.customClose))}function B(a){for(var b=["canCollapseWhitespace","canTrimWhitespace"],c=0,d=b.length;d>c;c++)a[b[c]]||(a[b[c]]=function(){return!1})}function C(b,c){"object"!=typeof c&&(c={});try{var d=a.RelateUrl;return"undefined"==typeof d&&"function"==typeof require&&(d=require("relateurl")),d&&d.relate?d.relate(b,c):b}catch(e){H(e)}return b}function D(b,c){"object"!=typeof c&&(c={}),c.fromString=!0,c.output={inline_script:!0};try{var d=a.UglifyJS;if("undefined"==typeof d&&"function"==typeof require&&(d=require("uglify-js")),!d)return b;if(d.minify)return d.minify(b,c).code;if(d.parse){var e=d.parse(b);e.figure_out_scope();var f=d.Compressor(),g=e.transform(f);g.figure_out_scope(),g.compute_char_frequency(),c.mangle!==!1&&g.mangle_names();var h=d.OutputStream(c.output);return g.print(h),h.toString()}return b}catch(i){H(i)}return b}function E(a,b){"object"!=typeof b&&(b={}),"undefined"==typeof b.noAdvanced&&(b.noAdvanced=!0);try{if("undefined"!=typeof CleanCSS)return new CleanCSS(b).minify(a);if("function"==typeof require){var c=require("clean-css");return new c(b).minify(a)}}catch(d){H(d)}return a}function F(a,f){function g(a,b){return x(a)||f.canCollapseWhitespace(a,b)}function h(a,b){return y(a)||f.canTrimWhitespace(a,b)}f=f||{},a=J(a),B(f);var i=[],j=[],k="",l="",m=[],n=[],o=[],p=f.lint,v=!1,C=new Date;new I(a,{html5:"undefined"!=typeof f.html5?f.html5:!0,start:function(a,b,c,d){if(v)return void j.push("<"+a,z(b),d?"/":"",">");a=f.caseSensitive?a:a.toLowerCase(),l=a,k="",m=b,f.collapseWhitespace&&(h(a,b)||n.push(a),g(a,b)||o.push(a));var e="<"+a,i=(d&&f.keepClosingSlash?"/":"")+">";0===b.length&&(e+=i),j.push(e),p&&p.testElement(a);for(var q,r=0,s=b.length;s>r;r++)p&&p.testAttribute(a,b[r].name.toLowerCase(),b[r].escaped),q=A(b[r],b,a,d,r,f),r===s-1&&(q+=i),j.push(q)},end:function(a,b){if(v)return void j.push("</"+a+">");f.collapseWhitespace&&(n.length&&a===n[n.length-1]&&n.pop(),o.length&&a===o[o.length-1]&&o.pop());var c=""===k&&a===l;if(f.removeEmptyElements&&c&&w(a,b)){for(var d=j.length-1;d>=0;d--)if(/^<[^\/!]/.test(j[d])){j.splice(d);break}}else f.removeOptionalTags&&u(a)||(j.push("</"+(f.caseSensitive?a:a.toLowerCase())+">"),i.push.apply(i,j),j.length=0,k="")},chars:function(a,d,e){return v?void j.push(a):(("script"===l||"style"===l)&&(f.removeCommentsFromCDATA&&(a=t(a,l)),f.removeCDATASectionsFromCDATA&&(a=r(a)),f.processScripts&&(a=s(a,f,m))),"script"===l&&f.minifyJS&&(a=D(a,f.minifyJS)),"style"===l&&f.minifyCSS&&(a=E(a,f.minifyCSS)),f.collapseWhitespace&&(n.length||(a=d||e?c(a,d,e,f):J(a)),o.length||(a=d&&e||"html"===e?a:b(a))),k=a,p&&p.testChars(a),void j.push(a))},comment:function(a,b){var c=b?"<!":"<!--",g=b?">":"-->";return/^\s*htmlmin:ignore/.test(a)?(v=!v,void(f.removeComments||j.push("<!--"+a+"-->"))):(a=f.removeComments?d(a)?c+q(a)+g:e(a,f)?"<!--"+a+"-->":"":c+a+g,void j.push(a))},ignore:function(a){j.push(f.removeIgnored?"":a)},doctype:function(a){j.push(f.useShortDoctype?"<!DOCTYPE html>":b(a))},customAttrAssign:f.customAttrAssign,customAttrSurround:f.customAttrSurround}),i.push.apply(i,j);var F=G(i,f);return H("minified in: "+(new Date-C)+"ms"),F}function G(a,b){var c,d=b.maxLineLength;if(d){for(var e,f=[],g="",h=0,i=a.length;i>h;h++)e=a[h],g.length+e.length<d?g+=e:(f.push(g.replace(/^\n/,"")),g=e);f.push(g),c=f.join("\n")}else c=a.join("");return c}var H,I;H=a.console&&a.console.log?function(b){a.console.log(b)}:function(){},a.HTMLParser?I=a.HTMLParser:"function"==typeof require&&(I=require("./htmlparser").HTMLParser);var J=function(a){return"string"!=typeof a?a:a.replace(/^\s+/,"").replace(/\s+$/,"")};String.prototype.trim&&(J=function(a){return"string"!=typeof a?a:a.trim()});var K={draggable:["true","false"]},L={script:/^\s*(?:\/\/)?\s*<!--.*\n?/,style:/^\s*<!--\s*/},M={script:/\s*(?:\/\/)?\s*-->\s*$/,style:/\s*-->\s*$/},N=new RegExp("^(?:class|id|style|title|lang|dir|on(?:focus|blur|change|click|dblclick|mouse(?:down|up|over|move|out)|key(?:press|down|up)))$");"undefined"!=typeof exports?exports.minify=F:a.minify=F}(this),function(a){"use strict";function b(a){return/^(?:big|small|hr|blink|marquee)$/.test(a)}function c(a){return/^(?:applet|basefont|center|dir|font|isindex|strike)$/.test(a)}function d(a){return/^on[a-z]+/.test(a)}function e(a){return"style"===a.toLowerCase()}function f(a,b){return"align"===b&&/^(?:caption|applet|iframe|img|imput|object|legend|table|hr|div|h[1-6]|p)$/.test(a)||"alink"===b&&"body"===a||"alt"===b&&"applet"===a||"archive"===b&&"applet"===a||"background"===b&&"body"===a||"bgcolor"===b&&/^(?:table|t[rdh]|body)$/.test(a)||"border"===b&&/^(?:img|object)$/.test(a)||"clear"===b&&"br"===a||"code"===b&&"applet"===a||"codebase"===b&&"applet"===a||"color"===b&&/^(?:base(?:font)?)$/.test(a)||"compact"===b&&/^(?:dir|[dou]l|menu)$/.test(a)||"face"===b&&/^base(?:font)?$/.test(a)||"height"===b&&/^(?:t[dh]|applet)$/.test(a)||"hspace"===b&&/^(?:applet|img|object)$/.test(a)||"language"===b&&"script"===a||"link"===b&&"body"===a||"name"===b&&"applet"===a||"noshade"===b&&"hr"===a||"nowrap"===b&&/^t[dh]$/.test(a)||"object"===b&&"applet"===a||"prompt"===b&&"isindex"===a||"size"===b&&/^(?:hr|font|basefont)$/.test(a)||"start"===b&&"ol"===a||"text"===b&&"body"===a||"type"===b&&/^(?:li|ol|ul)$/.test(a)||"value"===b&&"li"===a||"version"===b&&"html"===a||"vlink"===b&&"body"===a||"vspace"===b&&/^(?:applet|img|object)$/.test(a)||"width"===b&&/^(?:hr|td|th|applet|pre)$/.test(a)}function g(a,b){return"href"===a&&/^\s*javascript\s*:\s*void\s*(\s+0|\(\s*0\s*\))\s*$/i.test(b)}function h(){this.log=[],this._lastElement=null,this._isElementRepeated=!1}h.prototype.testElement=function(a){c(a)?this.log.push('Found <span class="deprecated-element">deprecated</span> <strong><code>&lt;'+a+"&gt;</code></strong> element"):b(a)?this.log.push('Found <span class="presentational-element">presentational</span> <strong><code>&lt;'+a+"&gt;</code></strong> element"):this.checkRepeatingElement(a)},h.prototype.checkRepeatingElement=function(a){"br"===a&&"br"===this._lastElement?this._isElementRepeated=!0:this._isElementRepeated&&(this._reportRepeatingElement(),this._isElementRepeated=!1),this._lastElement=a},h.prototype._reportRepeatingElement=function(){this.log.push("Found <code>&lt;br></code> sequence. Try replacing it with styling.")},h.prototype.testAttribute=function(a,b,c){d(b)?this.log.push('Found <span class="event-attribute">event attribute</span> (<strong>'+b+"</strong>) on <strong><code>&lt;"+a+"&gt;</code></strong> element."):f(a,b)?this.log.push('Found <span class="deprecated-attribute">deprecated</span> <strong>'+b+"</strong> attribute on <strong><code>&lt;"+a+"&gt;</code></strong> element."):e(b)?this.log.push('Found <span class="style-attribute">style attribute</span> on <strong><code>&lt;'+a+"&gt;</code></strong> element."):g(b,c)&&this.log.push('Found <span class="inaccessible-attribute">inaccessible attribute</span> (on <strong><code>&lt;'+a+"&gt;</code></strong> element).")},h.prototype.testChars=function(a){this._lastElement="",/(&nbsp;\s*){2,}/.test(a)&&this.log.push("Found repeating <strong><code>&amp;nbsp;</code></strong> sequence. Try replacing it with styling.")},h.prototype.test=function(a,b,c){this.testElement(a),this.testAttribute(a,b,c)},h.prototype.populate=function(a){if(this._isElementRepeated&&this._reportRepeatingElement(),this.log.length)if(a)a.innerHTML="<ol><li>"+this.log.join("<li>")+"</ol>";else{var b=" - "+this.log.join("\n - ").replace(/(<([^>]+)>)/gi,"").replace(/&lt;/g,"<").replace(/&gt;/g,">");console.log(b)}},a.HTMLLint=h}("undefined"==typeof exports?this:exports);
6
+ !function(a){"use strict";function b(a){var b,c=new RegExp("(?:\\s*[\\w:\\.-]+(?:\\s*(?:"+d(a)+")\\s*(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>\\s]+))?)*");if(a.customAttrSurround){for(var e=[],f=a.customAttrSurround.length-1;f>=0;f--)e[f]="(?:\\s*"+a.customAttrSurround[f][0].source+c.source+a.customAttrSurround[f][1].source+")";e.unshift(c.source),b=new RegExp("((?:"+e.join("|")+")*)")}else b=new RegExp("("+c.source+")");return new RegExp(j.source+b.source+k.source)}function c(a){var b=new RegExp(f.source+"(?:\\s*("+d(a)+")\\s*(?:"+i.join("|")+"))?");if(a.customAttrSurround){for(var c=[],e=a.customAttrSurround.length-1;e>=0;e--)c[e]="(?:("+a.customAttrSurround[e][0].source+")"+b.source+"("+a.customAttrSurround[e][1].source+"))";return c.unshift("(?:"+b.source+")"),new RegExp(c.join("|"),"g")}return new RegExp(b.source,"g")}function d(a){return h.concat(a.customAttrAssign||[]).map(function(a){return"(?:"+a.source+")"}).join("|")}function e(a){for(var b={},c=a.split(","),d=0;d<c.length;d++)b[c[d]]=!0,b[c[d].toUpperCase()]=!0;return b}var f=/([\w:\.-]+)/,g=/=/,h=[g],i=[/"((?:\\.|[^"])*)"/.source,/'((?:\\.|[^'])*)'/.source,/([^>\s]+)/.source],j=/^<([\w:-]+)/,k=/\s*(\/?)>/,l=/^<\/([\w:-]+)[^>]*>/,m=/\/>$/,n=/^<!DOCTYPE [^>]+>/i,o=!1;"x".replace(/x(.)?/g,function(a,b){o=""===b});var p,q,r,s=e("area,base,basefont,br,col,frame,hr,img,input,isindex,link,meta,param,embed,wbr"),t=e("a,abbr,acronym,applet,b,basefont,bdo,big,br,button,cite,code,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,noscript,object,q,s,samp,script,select,small,span,strike,strong,sub,sup,svg,textarea,tt,u,var"),u=e("colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr,source"),v=e("checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected"),w=e("script,style,noscript"),x={},y=a.HTMLParser=function(a,d){function e(a,b,c,e){for(var g=!1;!d.html5&&y.last()&&t[y.last()];)f("",y.last());u[b]&&y.last()===b&&f("",b),e=s[b]||!!e;var h=[];c.replace(B,function(){var a,b,c,e,f,g,i,j=7;if(o&&-1===arguments[0].indexOf('""')&&(""===arguments[3]&&(arguments[3]=void 0),""===arguments[4]&&(arguments[4]=void 0),""===arguments[5]&&(arguments[5]=void 0)),a=arguments[1])g=arguments[2],c=arguments[3],b=c||arguments[4]||arguments[5],g&&(i=arguments[0].charAt(a.length+g.length),i="'"===i||'"'===i?i:"");else if(d.customAttrSurround)for(var k=d.customAttrSurround.length-1;k>=0;k--)if(a=arguments[k*j+7],g=arguments[k*j+8],a){c=arguments[k*j+9],b=c||arguments[k*j+10]||arguments[k*j+11],e=arguments[k*j+6],f=arguments[k*j+12];break}void 0===b&&(b=v[a]?a:c),h.push({name:a,value:b,escaped:b&&b.replace(/(^|.)("+)/g,function(a){return a.replace(/"/g,"&quot;")}),customAssign:g||"=",customOpen:e||"",customClose:f||"",quote:i||""})}),e?g=a.match(m):y.push({tag:b,attrs:h}),d.start&&d.start(b,h,e,g)}function f(a,b){var c;if(b){var e=b.toLowerCase();for(c=y.length-1;c>=0&&y[c].tag.toLowerCase()!==e;c--);}else c=0;if(c>=0){for(var f=y.length-1;f>=c;f--)d.end&&d.end(y[f].tag,y[f].attrs);y.length=c}}var g,h,i,j,k,y=[],z=a;y.last=function(){var a=this[this.length-1];return a&&a.tag};for(var A=b(d),B=c(d);a;){if(h=!0,y.last()&&w[y.last()])p=y.last().toLowerCase(),q=x[p]||(x[p]=new RegExp("([\\s\\S]*?)</"+p+"[^>]*>","i")),a=a.replace(q,function(a,b){return"script"!==p&&"style"!==p&&"noscript"!==p&&(b=b.replace(/<!--([\s\S]*?)-->/g,"$1").replace(/<!\[CDATA\[([\s\S]*?)\]\]>/g,"$1")),d.chars&&d.chars(b),""}),f("",p);else if(/^<!--/.test(a)&&(g=a.indexOf("-->"),g>=0&&(d.comment&&d.comment(a.substring(4,g)),a=a.substring(g+3),h=!1)),/^<!\[/.test(a)?(g=a.indexOf("]>"),g>=0&&(d.comment&&d.comment(a.substring(2,g+1),!0),a=a.substring(g+2),h=!1)):/^<\?/.test(a)?(g=a.indexOf("?>",2),g>=0&&(d.chars&&d.chars(a.substring(0,g+2)),a=a.substring(g+2))):/^<%/.test(a)?(g=a.indexOf("%>",2),g>=0&&(d.chars&&d.chars(a.substring(0,g+2)),a=a.substring(g+2))):(i=n.exec(a))?(d.doctype&&d.doctype(i[0]),a=a.substring(i[0].length),h=!1):/^<\//.test(a)?(i=a.match(l),i&&(a=a.substring(i[0].length),i[0].replace(l,f),j="/"+i[1].toLowerCase(),h=!1)):/^</.test(a)&&(i=a.match(A),i&&(a=a.substring(i[0].length),i[0].replace(A,e),j=i[1].toLowerCase(),h=!1)),h){g=a.indexOf("<");var C=0>g?a:a.substring(0,g);a=0>g?"":a.substring(g),r=a.match(A),r?k=r[1]:(r=a.match(l),k=r?"/"+r[1]:""),d.chars&&d.chars(C,j,k)}if(a===z)throw"Parse Error: "+a;z=a}f()};a.HTMLtoXML=function(a){var b="";return new y(a,{start:function(a,c,d){b+="<"+a;for(var e=0;e<c.length;e++)b+=" "+c[e].name+'="'+c[e].escaped+'"';b+=(d?"/":"")+">"},end:function(a){b+="</"+a+">"},chars:function(a){b+=a},comment:function(a){b+="<!--"+a+"-->"},ignore:function(a){b+=a}}),b},a.HTMLtoDOM=function(a,b){var c=e("html,head,body,title"),d={link:"head",base:"head"};b?b=b.ownerDocument||b.getOwnerDocument&&b.getOwnerDocument()||b:"undefined"!=typeof DOMDocument?b=new DOMDocument:"undefined"!=typeof document&&document.implementation&&document.implementation.createDocument?b=document.implementation.createDocument("","",null):"undefined"!=typeof ActiveX&&(b=new ActiveXObject("Msxml.DOMDocument"));var f=[],g=b.documentElement||b.getDocumentElement&&b.getDocumentElement();if(!g&&b.createElement&&!function(){var a=b.createElement("html"),c=b.createElement("head");c.appendChild(b.createElement("title")),a.appendChild(c),a.appendChild(b.createElement("body")),b.appendChild(a)}(),b.getElementsByTagName)for(var h in c)c[h]=b.getElementsByTagName(h)[0];var i=c.body;return new y(a,{start:function(a,e,g){if(c[a])return void(i=c[a]);var h=b.createElement(a);for(var j in e)h.setAttribute(e[j].name,e[j].value);d[a]&&"boolean"!=typeof c[d[a]]?c[d[a]].appendChild(h):i&&i.appendChild&&i.appendChild(h),g||(f.push(h),i=h)},end:function(){f.length-=1,i=f[f.length-1]},chars:function(a){i.appendChild(b.createTextNode(a))},comment:function(){},ignore:function(){}}),b}}("undefined"==typeof exports?this:exports),function(a){"use strict";function b(a){return a?a.replace(/[\t\n\r ]+/g," "):a}function c(a,b,c,d){var e=["a","abbr","acronym","b","bdi","bdo","big","button","cite","code","del","dfn","em","font","i","ins","kbd","mark","q","rt","rp","s","samp","small","span","strike","strong","sub","sup","svg","time","tt","u","var"],f=/^[\t ]*[\n\r]+[\t\n\r ]*/,g=/[\t\n\r ]*[\n\r]+[\t ]*$/,h=f.test(a)?"\n":" ",i=g.test(a)?"\n":" ",j="htmlmincollapsedlinebreak";return b&&"img"!==b&&"input"!==b&&("/"!==b.substr(0,1)||"/"===b.substr(0,1)&&-1===e.indexOf(b.substr(1)))&&(a=a.replace(/^\s+/,d.conservativeCollapse?" ":d.preserveLineBreaks?h:"")),c&&"img"!==c&&"input"!==c&&("/"===c.substr(0,1)||"/"!==c.substr(0,1)&&-1===e.indexOf(c))&&(a=a.replace(/\s+$/,d.conservativeCollapse?" ":d.preserveLineBreaks?i:"")),b&&c?(d.preserveLineBreaks&&(a=a.replace(f,j).replace(g,j)),a.replace(/[\t\n\r]+/g," ").replace(/[ ]+/g," ").replace(new RegExp(j,"g"),"\n")):a}function d(a){return/\[if[^\]]+\]/.test(a)||/\s*((?:<!)?\[endif\])$/.test(a)}function e(a,b){if(/^!/.test(a))return!0;if(b.ignoreCustomComments)for(var c=0,d=b.ignoreCustomComments.length;d>c;c++)if(b.ignoreCustomComments[c].test(a))return!0;return!1}function f(a){return/^on[a-z]+/.test(a)}function g(a){return/^[^\x20\t\n\f\r"'`=<>]+$/.test(a)&&!/\/$/.test(a)&&!/\/$/.test(a)}function h(a,b){for(var c=a.length;c--;)if(a[c].name.toLowerCase()===b)return!0;return!1}function i(a,b,c,d){return c=c?M(c.toLowerCase()):"","script"===a&&"language"===b&&"javascript"===c||"form"===a&&"method"===b&&"get"===c||"input"===a&&"type"===b&&"text"===c||"script"===a&&"charset"===b&&!h(d,"src")||"a"===a&&"name"===b&&h(d,"id")||"area"===a&&"shape"===b&&"rect"===c}function j(a,b,c){return"script"===a&&"type"===b&&"text/javascript"===M(c.toLowerCase())}function k(a,b){if("script"!==a)return!1;for(var c=0,d=b.length;d>c;c++){var e=b[c].name.toLowerCase();if("type"===e)return""===b[c].value||1===N[b[c].value]}return!0}function l(a,b,c){return("style"===a||"link"===a)&&"type"===b&&"text/css"===M(c.toLowerCase())}function m(a,b){var c=/^(?:allowfullscreen|async|autofocus|autoplay|checked|compact|controls|declare|default|defaultchecked|defaultmuted|defaultselected|defer|disabled|enabled|formnovalidate|hidden|indeterminate|inert|ismap|itemscope|loop|multiple|muted|nohref|noresize|noshade|novalidate|nowrap|open|pauseonexit|readonly|required|reversed|scoped|seamless|selected|sortable|spellcheck|truespeed|typemustmatch|visible)$/i.test(a);if(c)return!0;var d=O[a.toLowerCase()];return d?-1===d.indexOf(b.toLowerCase()):!1}function n(a,b){return/^(?:a|area|link|base)$/.test(b)&&"href"===a||"img"===b&&/^(?:src|longdesc|usemap)$/.test(a)||"object"===b&&/^(?:classid|codebase|data|usemap)$/.test(a)||"q"===b&&"cite"===a||"blockquote"===b&&"cite"===a||("ins"===b||"del"===b)&&"cite"===a||"form"===b&&"action"===a||"input"===b&&("src"===a||"usemap"===a)||"head"===b&&"profile"===a||"script"===b&&("src"===a||"for"===a)}function o(a,b){return/^(?:a|area|object|button)$/.test(b)&&"tabindex"===a||"input"===b&&("maxlength"===a||"tabindex"===a)||"select"===b&&("size"===a||"tabindex"===a)||"textarea"===b&&/^(?:rows|cols|tabindex)$/.test(a)||"colgroup"===b&&"span"===a||"col"===b&&"span"===a||("th"===b||"td"===b)&&("rowspan"===a||"colspan"===a)}function p(a,c,d,e,g){if(d&&f(c)){if(d=M(d).replace(/^javascript:\s*/i,"").replace(/\s*;$/,""),e.minifyJS){var h="(function(){"+d+"})()",i=G(h,e.minifyJS);return i.slice(12,i.length-4).replace(/"/g,"&quot;")}return d}return"class"===c?b(M(d)):n(c,a)?(d=M(d),e.minifyURLs?F(d,e.minifyURLs):d):o(c,a)?M(d):"style"===c?(d=M(d),d&&(d=d.replace(/\s*;\s*$/,"")),e.minifyCSS?H(d,e.minifyCSS,!0):d):(q(a,g)&&"content"===c?d=d.replace(/1\.0/g,"1").replace(/\s+/g,""):d&&e.customAttrCollapse&&e.customAttrCollapse.test(c)&&(d=d.replace(/\n+/g,"")),d)}function q(a,b){if("meta"!==a)return!1;for(var c=0,d=b.length;d>c;c++)if("name"===b[c].name&&"viewport"===b[c].value)return!0}function r(a){return"*{"+a+"}"}function s(a){var b=a.match(/^\*\{([\s\S]*)\}$/m);return b&&b[1]?b[1]:a}function t(a){return a.replace(/^(\[[^\]]+\]>)\s*/,"$1").replace(/\s*(<!\[endif\])$/,"$1")}function u(a){return a.replace(/^(?:\s*\/\*\s*<!\[CDATA\[\s*\*\/|\s*\/\/\s*<!\[CDATA\[.*)/,"").replace(/(?:\/\*\s*\]\]>\s*\*\/|\/\/\s*\]\]>)\s*$/,"")}function v(a,b,c){for(var d=0,e=c.length;e>d;d++)if("type"===c[d].name.toLowerCase()&&b.processScripts.indexOf(c[d].value)>-1)return I(a,b);return a}function w(a,b){return a.replace(P[b],"").replace(Q[b],"")}function x(a){return/^(?:html|t?body|t?head|tfoot|tr|td|th|dt|dd|option|colgroup|source)$/.test(a)}function y(a,b,c){var d=!c||/^\s*$/.test(c);return d?"input"===a&&"value"===b||R.test(b):!1}function z(a,b){if("textarea"===a)return!1;if("script"===a)for(var c=b.length-1;c>=0;c--)if("src"===b[c].name)return!1;return!0}function A(a){return!/^(?:script|style|pre|textarea)$/.test(a)}function B(a){return!/^(?:pre|textarea)$/.test(a)}function C(a){for(var b="",c=0,d=a.length;d>c;c++)b+=" "+a[c].name+(m(a[c].value)?"":'="'+a[c].value+'"');return b}function D(a,b,c,d,e,f){var h,k,n=f.caseSensitive?a.name:a.name.toLowerCase(),o=f.preventAttributesEscaping?a.value:a.escaped,q=f.preventAttributesEscaping?a.quote:'"',r=d&&e===b.length-1;return f.removeRedundantAttributes&&i(c,n,o,b)||f.removeScriptTypeAttributes&&j(c,n,o)||f.removeStyleLinkTypeAttributes&&l(c,n,o)?"":(o=p(c,n,o,f,b),k=void 0!==o&&!f.removeAttributeQuotes||!g(o)||r?q+o+q:o,f.removeEmptyAttributes&&y(c,n,o)?"":(h=void 0===o||f.collapseBooleanAttributes&&m(n,o)?n:n+a.customAssign+k," "+a.customOpen+h+a.customClose))}function E(a){for(var b=["canCollapseWhitespace","canTrimWhitespace"],c=0,d=b.length;d>c;c++)a[b[c]]||(a[b[c]]=function(){return!1})}function F(b,c){"object"!=typeof c&&(c={});try{var d=a.RelateUrl;return"undefined"==typeof d&&"function"==typeof require&&(d=require("relateurl")),d&&d.relate?d.relate(b,c):b}catch(e){K(e)}return b}function G(b,c){"object"!=typeof c&&(c={}),c.fromString=!0;var d=c.output||{};d.inline_script=!0,c.output=d;try{var e=a.UglifyJS;if("undefined"==typeof e&&"function"==typeof require&&(e=require("uglify-js")),!e)return b;if(e.minify)return e.minify(b,c).code;if(e.parse){var f=e.parse(b);f.figure_out_scope();var g=e.Compressor(),h=f.transform(g);h.figure_out_scope(),h.compute_char_frequency(),c.mangle!==!1&&h.mangle_names();var i=e.OutputStream(c.output);return h.print(i),i.toString()}return b}catch(j){K(j)}return b}function H(a,b,c){"object"!=typeof b&&(b={}),"undefined"==typeof b.advanced&&(b.advanced=!1);try{var d;if("undefined"!=typeof CleanCSS)d=new CleanCSS(b);else if("function"==typeof require){var e=require("clean-css");d=new e(b)}return c?s(d.minify(r(a)).styles):d.minify(a).styles}catch(f){K(f)}return a}function I(a,f){function g(a,b){return A(a)||f.canCollapseWhitespace(a,b)}function h(a,b){return B(a)||f.canTrimWhitespace(a,b)}f=f||{};var i=[];a=M(a),E(f);var j=[],l=[],m="",n="",o=[],p=[],q=[],r=f.lint,s=!1,y=new Date;f.removeIgnored&&(a=a.replace(/<\?[^\?]+\?>/g,"").replace(/<%[^%]+%>/g,"")),new L(a,{html5:"undefined"!=typeof f.html5?f.html5:!0,start:function(a,b,c,d){if(s)return void l.push("<"+a,C(b),d?"/":"",">");var e=a.toLowerCase();if("svg"===e){i.push(f);var j={};for(var k in f)j[k]=f[k];j.keepClosingSlash=!0,j.caseSensitive=!0,f=j}a=f.caseSensitive?a:e,n=a,m="",o=b,f.collapseWhitespace&&(h(a,b)||p.push(a),g(a,b)||q.push(a));var t="<"+a,u=(d&&f.keepClosingSlash?"/":"")+">";0===b.length&&(t+=u),l.push(t),r&&r.testElement(a);for(var v,w=0,x=b.length;x>w;w++)r&&r.testAttribute(a,b[w].name.toLowerCase(),b[w].escaped),v=D(b[w],b,a,d,w,f),w===x-1&&(v+=u),l.push(v)},end:function(a,b){if(s)return void l.push("</"+a+">");var c=a.toLowerCase();"svg"===c&&(f=i.pop()),f.collapseWhitespace&&(p.length&&a===p[p.length-1]&&p.pop(),q.length&&a===q[q.length-1]&&q.pop());var d=""===m&&a===n;if(f.removeEmptyElements&&d&&z(a,b)){for(var e=l.length-1;e>=0;e--)if(/^<[^\/!]/.test(l[e])){l.splice(e);break}}else f.removeOptionalTags&&x(a)||(l.push("</"+(f.caseSensitive?a:c)+">"),j.push.apply(j,l),l.length=0,m="")},chars:function(a,d,e){return d=""===d?"comment":d,e=""===e?"comment":e,s?void l.push(a):(("script"===n||"style"===n)&&(f.removeCommentsFromCDATA&&(a=w(a,n)),f.removeCDATASectionsFromCDATA&&(a=u(a)),f.processScripts&&(a=v(a,f,o))),f.minifyJS&&k(n,o)&&(a=G(a,f.minifyJS)),"style"===n&&f.minifyCSS&&(a=H(a,f.minifyCSS)),f.collapseWhitespace&&(p.length||(a=d&&"comment"!==d||e&&"comment"!==e?c(a,d,e,f):M(a)),q.length||(a=d&&e||"html"===e?a:b(a))),m=a,r&&r.testChars(a),void l.push(a))},comment:function(a,b){var c=b?"<!":"<!--",g=b?">":"-->";return/^\s*htmlmin:ignore/.test(a)?(s=!s,void(f.removeComments||l.push("<!--"+a+"-->"))):(a=f.removeComments?d(a)?c+t(a)+g:e(a,f)?"<!--"+a+"-->":"":c+a+g,void l.push(a))},doctype:function(a){l.push(f.useShortDoctype?"<!DOCTYPE html>":b(a))},customAttrAssign:f.customAttrAssign,customAttrSurround:f.customAttrSurround}),j.push.apply(j,l);var F=J(j,f);return K("minified in: "+(new Date-y)+"ms"),F}function J(a,b){var c,d=b.maxLineLength;if(d){for(var e,f=[],g="",h=0,i=a.length;i>h;h++)e=a[h],g.length+e.length<d?g+=e:(f.push(g.replace(/^\n/,"")),g=e);f.push(g),c=f.join("\n")}else c=a.join("");return c}var K,L;K=a.console&&a.console.log?function(b){a.console.log(b)}:function(){},a.HTMLParser?L=a.HTMLParser:"function"==typeof require&&(L=require("./htmlparser").HTMLParser);var M=function(a){return"string"!=typeof a?a:a.replace(/^\s+/,"").replace(/\s+$/,"")};String.prototype.trim&&(M=function(a){return"string"!=typeof a?a:a.trim()});var N={"text/javascript":1,"text/ecmascript":1,"text/jscript":1,"application/javascript":1,"application/x-javascript":1,"application/ecmascript":1},O={draggable:["true","false"]},P={script:/^\s*(?:\/\/)?\s*<!--.*\n?/,style:/^\s*<!--\s*/},Q={script:/\s*(?:\/\/)?\s*-->\s*$/,style:/\s*-->\s*$/},R=new RegExp("^(?:class|id|style|title|lang|dir|on(?:focus|blur|change|click|dblclick|mouse(?:down|up|over|move|out)|key(?:press|down|up)))$");"undefined"!=typeof exports?exports.minify=I:a.minify=I}(this),function(a){"use strict";function b(a){return/^(?:big|small|hr|blink|marquee)$/.test(a)}function c(a){return/^(?:applet|basefont|center|dir|font|isindex|strike)$/.test(a)}function d(a){return/^on[a-z]+/.test(a)}function e(a){return"style"===a.toLowerCase()}function f(a,b){return"align"===b&&/^(?:caption|applet|iframe|img|imput|object|legend|table|hr|div|h[1-6]|p)$/.test(a)||"alink"===b&&"body"===a||"alt"===b&&"applet"===a||"archive"===b&&"applet"===a||"background"===b&&"body"===a||"bgcolor"===b&&/^(?:table|t[rdh]|body)$/.test(a)||"border"===b&&/^(?:img|object)$/.test(a)||"clear"===b&&"br"===a||"code"===b&&"applet"===a||"codebase"===b&&"applet"===a||"color"===b&&/^(?:base(?:font)?)$/.test(a)||"compact"===b&&/^(?:dir|[dou]l|menu)$/.test(a)||"face"===b&&/^base(?:font)?$/.test(a)||"height"===b&&/^(?:t[dh]|applet)$/.test(a)||"hspace"===b&&/^(?:applet|img|object)$/.test(a)||"language"===b&&"script"===a||"link"===b&&"body"===a||"name"===b&&"applet"===a||"noshade"===b&&"hr"===a||"nowrap"===b&&/^t[dh]$/.test(a)||"object"===b&&"applet"===a||"prompt"===b&&"isindex"===a||"size"===b&&/^(?:hr|font|basefont)$/.test(a)||"start"===b&&"ol"===a||"text"===b&&"body"===a||"type"===b&&/^(?:li|ol|ul)$/.test(a)||"value"===b&&"li"===a||"version"===b&&"html"===a||"vlink"===b&&"body"===a||"vspace"===b&&/^(?:applet|img|object)$/.test(a)||"width"===b&&/^(?:hr|td|th|applet|pre)$/.test(a)}function g(a,b){return"href"===a&&/^\s*javascript\s*:\s*void\s*(\s+0|\(\s*0\s*\))\s*$/i.test(b)}function h(){this.log=[],this._lastElement=null,this._isElementRepeated=!1}h.prototype.testElement=function(a){c(a)?this.log.push('Found <span class="deprecated-element">deprecated</span> <strong><code>&lt;'+a+"&gt;</code></strong> element"):b(a)?this.log.push('Found <span class="presentational-element">presentational</span> <strong><code>&lt;'+a+"&gt;</code></strong> element"):this.checkRepeatingElement(a)},h.prototype.checkRepeatingElement=function(a){"br"===a&&"br"===this._lastElement?this._isElementRepeated=!0:this._isElementRepeated&&(this._reportRepeatingElement(),this._isElementRepeated=!1),this._lastElement=a},h.prototype._reportRepeatingElement=function(){this.log.push("Found <code>&lt;br></code> sequence. Try replacing it with styling.")},h.prototype.testAttribute=function(a,b,c){d(b)?this.log.push('Found <span class="event-attribute">event attribute</span> (<strong>'+b+"</strong>) on <strong><code>&lt;"+a+"&gt;</code></strong> element."):f(a,b)?this.log.push('Found <span class="deprecated-attribute">deprecated</span> <strong>'+b+"</strong> attribute on <strong><code>&lt;"+a+"&gt;</code></strong> element."):e(b)?this.log.push('Found <span class="style-attribute">style attribute</span> on <strong><code>&lt;'+a+"&gt;</code></strong> element."):g(b,c)&&this.log.push('Found <span class="inaccessible-attribute">inaccessible attribute</span> (on <strong><code>&lt;'+a+"&gt;</code></strong> element).")},h.prototype.testChars=function(a){this._lastElement="",/(&nbsp;\s*){2,}/.test(a)&&this.log.push("Found repeating <strong><code>&amp;nbsp;</code></strong> sequence. Try replacing it with styling.")},h.prototype.test=function(a,b,c){this.testElement(a),this.testAttribute(a,b,c)},h.prototype.populate=function(a){if(this._isElementRepeated&&this._reportRepeatingElement(),this.log.length)if(a)a.innerHTML="<ol><li>"+this.log.join("<li>")+"</ol>";else{var b=" - "+this.log.join("\n - ").replace(/(<([^>]+)>)/gi,"").replace(/&lt;/g,"<").replace(/&gt;/g,">");console.log(b)}},a.HTMLLint=h}("undefined"==typeof exports?this:exports);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "html-minifier",
3
3
  "description": "HTML minifier with lint-like capabilities.",
4
- "version": "0.6.8",
4
+ "version": "0.7.2",
5
5
  "keywords": [
6
6
  "html",
7
7
  "minifier",
@@ -39,24 +39,26 @@
39
39
  "test": "grunt test"
40
40
  },
41
41
  "dependencies": {
42
- "change-case": "2.1.x",
43
- "clean-css": "2.2.x",
42
+ "change-case": "2.3.x",
43
+ "clean-css": "3.1.x",
44
44
  "cli": "0.6.x",
45
+ "concat-stream": "1.4.x",
45
46
  "uglify-js": "2.4.x",
46
47
  "relateurl": "0.2.x"
47
48
  },
48
49
  "devDependencies": {
50
+ "chalk": "1.0.x",
49
51
  "cli-table": "0.3.x",
50
52
  "grunt": "0.4.x",
51
53
  "grunt-contrib-concat": "0.5.x",
52
- "grunt-contrib-jshint": "0.10.x",
53
- "grunt-contrib-qunit": "0.5.x",
54
- "grunt-contrib-uglify": "0.5.x",
54
+ "grunt-contrib-jshint": "0.11.x",
55
+ "grunt-contrib-qunit": "0.7.x",
56
+ "grunt-contrib-uglify": "0.8.x",
55
57
  "grunt-exec": "0.4.x",
56
- "grunt-jscs": "0.6.x",
57
- "load-grunt-tasks": "0.6.x",
58
+ "grunt-jscs": "1.6.x",
59
+ "load-grunt-tasks": "3.1.x",
58
60
  "qunit": "0.7.x",
59
- "time-grunt": "1.0.x"
61
+ "time-grunt": "1.1.x"
60
62
  },
61
63
  "files": [
62
64
  "dist",