diff --git a/src/htmlminifier.js b/src/htmlminifier.js index 120e62b8..7e887f29 100644 --- a/src/htmlminifier.js +++ b/src/htmlminifier.js @@ -613,113 +613,107 @@ function identity(value) { return value; } -function processOptions(options) { - ['html5', 'includeAutoGeneratedTags'].forEach(function(key) { - if (!(key in options)) { - options[key] = true; - } - }); - - if (typeof options.log !== 'function') { - options.log = identity; - } - - if (!options.canCollapseWhitespace) { - options.canCollapseWhitespace = canCollapseWhitespace; - } - if (!options.canTrimWhitespace) { - options.canTrimWhitespace = canTrimWhitespace; - } - - if (!('ignoreCustomComments' in options)) { - options.ignoreCustomComments = [/^!/]; - } - - if (!('ignoreCustomFragments' in options)) { - options.ignoreCustomFragments = [ +function processOptions(values) { + var options = { + canCollapseWhitespace: canCollapseWhitespace, + canTrimWhitespace: canTrimWhitespace, + html5: true, + ignoreCustomComments: [/^!/], + ignoreCustomFragments: [ /<%[\s\S]*?%>/, /<\?[\s\S]*?\?>/ - ]; - } - - if (!options.minifyURLs) { - options.minifyURLs = identity; - } - if (typeof options.minifyURLs !== 'function') { - var minifyURLs = options.minifyURLs; - if (typeof minifyURLs === 'string') { - minifyURLs = { site: minifyURLs }; - } - else if (typeof minifyURLs !== 'object') { - minifyURLs = {}; - } - options.minifyURLs = function(text) { - try { - return RelateUrl.relate(text, minifyURLs); - } - catch (err) { - options.log(err); - return text; + ], + includeAutoGeneratedTags: true, + log: identity, + minifyCSS: identity, + minifyJS: identity, + minifyURLs: identity + }; + Object.keys(values).forEach(function(key) { + var value = values[key]; + if (key === 'log') { + if (typeof value === 'function') { + options.log = value; } - }; - } - - if (!options.minifyJS) { - options.minifyJS = identity; - } - if (typeof options.minifyJS !== 'function') { - var minifyJS = options.minifyJS; - if (typeof minifyJS !== 'object') { - minifyJS = {}; } - (minifyJS.parse || (minifyJS.parse = {})).bare_returns = false; - options.minifyJS = function(text, inline) { - var start = text.match(/^\s*\s*$/, '') : text; - minifyJS.parse.bare_returns = inline; - var result = UglifyJS.minify(code, minifyJS); - if (result.error) { - options.log(result.error); - return text; + else if (key === 'minifyCSS' && typeof value !== 'function') { + if (!value) { + return; } - return result.code.replace(/;$/, ''); - }; - } - - if (!options.minifyCSS) { - options.minifyCSS = identity; - } - if (typeof options.minifyCSS !== 'function') { - var minifyCSS = options.minifyCSS; - if (typeof minifyCSS !== 'object') { - minifyCSS = {}; - } - options.minifyCSS = function(text, type) { - text = text.replace(/(url\s*\(\s*)("|'|)(.*?)\2(\s*\))/ig, function(match, prefix, quote, url, suffix) { - return prefix + quote + options.minifyURLs(url) + quote + suffix; - }); - try { - if (type === 'inline') { - text = wrapInlineCSS(text); - } - else if (type === 'media') { - text = wrapMediaQuery(text); + if (typeof value !== 'object') { + value = {}; + } + options.minifyCSS = function(text, type) { + text = text.replace(/(url\s*\(\s*)("|'|)(.*?)\2(\s*\))/ig, function(match, prefix, quote, url, suffix) { + return prefix + quote + options.minifyURLs(url) + quote + suffix; + }); + try { + if (type === 'inline') { + text = wrapInlineCSS(text); + } + else if (type === 'media') { + text = wrapMediaQuery(text); + } + text = new CleanCSS(value).minify(text).styles; + if (type === 'inline') { + text = unwrapInlineCSS(text); + } + else if (type === 'media') { + text = unwrapMediaQuery(text); + } + return text; } - text = new CleanCSS(minifyCSS).minify(text).styles; - if (type === 'inline') { - text = unwrapInlineCSS(text); + catch (err) { + options.log(err); + return text; } - else if (type === 'media') { - text = unwrapMediaQuery(text); + }; + } + else if (key === 'minifyJS' && typeof value !== 'function') { + if (!value) { + return; + } + if (typeof value !== 'object') { + value = {}; + } + (value.parse || (value.parse = {})).bare_returns = false; + options.minifyJS = function(text, inline) { + var start = text.match(/^\s*\s*$/, '') : text; + value.parse.bare_returns = inline; + var result = UglifyJS.minify(code, value); + if (result.error) { + options.log(result.error); + return text; } - return text; + return result.code.replace(/;$/, ''); + }; + } + else if (key === 'minifyURLs' && typeof value !== 'function') { + if (!value) { + return; } - catch (err) { - options.log(err); - return text; + if (typeof value === 'string') { + value = { site: value }; } - }; - } + else if (typeof value !== 'object') { + value = {}; + } + options.minifyURLs = function(text) { + try { + return RelateUrl.relate(text, value); + } + catch (err) { + options.log(err); + return text; + } + }; + } + else { + options[key] = value; + } + }); + return options; } function uniqueId(value) { @@ -817,9 +811,7 @@ function createSortFns(value, options, uidIgnore, uidAttr) { } function minify(value, options, partialMarkup) { - options = options || {}; - var optionsStack = []; - processOptions(options); + options = processOptions(options || {}); if (options.collapseWhitespace) { value = collapseWhitespace(value, options, true, true); } @@ -850,22 +842,25 @@ function minify(value, options, partialMarkup) { uidIgnore = uniqueId(value); var pattern = new RegExp('^' + uidIgnore + '([0-9]+)$'); if (options.ignoreCustomComments) { - options.ignoreCustomComments.push(pattern); + options.ignoreCustomComments = options.ignoreCustomComments.slice(); } else { - options.ignoreCustomComments = [pattern]; + options.ignoreCustomComments = []; } + options.ignoreCustomComments.push(pattern); } var token = ''; ignoredMarkupChunks.push(group1); return token; }); - function escapeFragments(text) { - return text.replace(uidPattern, function(match, prefix, index) { - var chunks = ignoredCustomMarkupChunks[+index]; - return chunks[1] + uidAttr + index + chunks[2]; - }); + function escapeFragments(fn) { + return function(text, type) { + return fn(text.replace(uidPattern, function(match, prefix, index) { + var chunks = ignoredCustomMarkupChunks[+index]; + return chunks[1] + uidAttr + index + chunks[2]; + }), type); + }; } var customFragments = options.ignoreCustomFragments.map(function(re) { @@ -878,17 +873,11 @@ function minify(value, options, partialMarkup) { if (!uidAttr) { uidAttr = uniqueId(value); uidPattern = new RegExp('(\\s*)' + uidAttr + '([0-9]+)(\\s*)', 'g'); - var minifyCSS = options.minifyCSS; - if (minifyCSS) { - options.minifyCSS = function(text, type) { - return minifyCSS(escapeFragments(text), type); - }; + if (options.minifyCSS) { + options.minifyCSS = escapeFragments(options.minifyCSS); } - var minifyJS = options.minifyJS; - if (minifyJS) { - options.minifyJS = function(text, inline) { - return minifyJS(escapeFragments(text), inline); - }; + if (options.minifyJS) { + options.minifyJS = escapeFragments(options.minifyJS); } } var token = uidAttr + ignoredCustomMarkupChunks.length; @@ -962,14 +951,9 @@ function minify(value, options, partialMarkup) { var lowerTag = tag.toLowerCase(); if (lowerTag === 'svg') { - optionsStack.push(options); - var nextOptions = {}; - for (var key in options) { - nextOptions[key] = options[key]; - } - nextOptions.keepClosingSlash = true; - nextOptions.caseSensitive = true; - options = nextOptions; + options = Object.create(options); + options.keepClosingSlash = true; + options.caseSensitive = true; } tag = options.caseSensitive ? tag : lowerTag; @@ -1055,7 +1039,7 @@ function minify(value, options, partialMarkup) { end: function(tag, attrs, autoGenerated) { var lowerTag = tag.toLowerCase(); if (lowerTag === 'svg') { - options = optionsStack.pop(); + options = Object.getPrototypeOf(options); } tag = options.caseSensitive ? tag : lowerTag;