From de98e0b232509d5f40c135d540a70e415272ff85 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 3 May 2017 15:35:00 +0200 Subject: node_modules --- node_modules/html-minifier/src/htmlminifier.js | 1308 ++++++++++++++++++++++++ node_modules/html-minifier/src/htmlparser.js | 528 ++++++++++ node_modules/html-minifier/src/tokenchain.js | 71 ++ node_modules/html-minifier/src/utils.js | 18 + 4 files changed, 1925 insertions(+) create mode 100644 node_modules/html-minifier/src/htmlminifier.js create mode 100644 node_modules/html-minifier/src/htmlparser.js create mode 100644 node_modules/html-minifier/src/tokenchain.js create mode 100644 node_modules/html-minifier/src/utils.js (limited to 'node_modules/html-minifier/src') diff --git a/node_modules/html-minifier/src/htmlminifier.js b/node_modules/html-minifier/src/htmlminifier.js new file mode 100644 index 000000000..f7917cd4a --- /dev/null +++ b/node_modules/html-minifier/src/htmlminifier.js @@ -0,0 +1,1308 @@ +'use strict'; + +var CleanCSS = require('clean-css'); +var decode = require('he').decode; +var HTMLParser = require('./htmlparser').HTMLParser; +var RelateUrl = require('relateurl'); +var TokenChain = require('./tokenchain'); +var UglifyJS = require('uglify-js'); +var utils = require('./utils'); + +var trimWhitespace = String.prototype.trim ? function(str) { + if (typeof str !== 'string') { + return str; + } + return str.trim(); +} : function(str) { + if (typeof str !== 'string') { + return str; + } + return str.replace(/^\s+/, '').replace(/\s+$/, ''); +}; + +function collapseWhitespaceAll(str) { + return str && str.replace(/\s+/g, function(spaces) { + return spaces === '\t' ? '\t' : spaces.replace(/(^|\xA0+)[^\xA0]+/g, '$1 '); + }); +} + +function collapseWhitespace(str, options, trimLeft, trimRight, collapseAll) { + var lineBreakBefore = '', lineBreakAfter = ''; + + if (options.preserveLineBreaks) { + str = str.replace(/^\s*?[\n\r]\s*/, function() { + lineBreakBefore = '\n'; + return ''; + }).replace(/\s*?[\n\r]\s*$/, function() { + lineBreakAfter = '\n'; + return ''; + }); + } + + if (trimLeft) { + str = str.replace(/^\s+/, function(spaces) { + var conservative = !lineBreakBefore && options.conservativeCollapse; + if (conservative && spaces === '\t') { + return '\t'; + } + return spaces.replace(/^[^\xA0]+/, '').replace(/(\xA0+)[^\xA0]+/g, '$1 ') || (conservative ? ' ' : ''); + }); + } + + if (trimRight) { + str = str.replace(/\s+$/, function(spaces) { + var conservative = !lineBreakAfter && options.conservativeCollapse; + if (conservative && spaces === '\t') { + return '\t'; + } + return spaces.replace(/[^\xA0]+(\xA0+)/g, ' $1').replace(/[^\xA0]+$/, '') || (conservative ? ' ' : ''); + }); + } + + if (collapseAll) { + // strip non space whitespace then compress spaces to one + str = collapseWhitespaceAll(str); + } + + return lineBreakBefore + str + lineBreakAfter; +} + +var createMapFromString = utils.createMapFromString; +// non-empty tags that will maintain whitespace around them +var inlineTags = createMapFromString('a,abbr,acronym,b,bdi,bdo,big,button,cite,code,del,dfn,em,font,i,ins,kbd,mark,math,nobr,q,rt,rp,s,samp,small,span,strike,strong,sub,sup,svg,time,tt,u,var'); +// non-empty tags that will maintain whitespace within them +var inlineTextTags = createMapFromString('a,abbr,acronym,b,big,del,em,font,i,ins,kbd,mark,nobr,s,samp,small,span,strike,strong,sub,sup,time,tt,u,var'); +// self-closing tags that will maintain whitespace around them +var selfClosingInlineTags = createMapFromString('comment,img,input,wbr'); + +function collapseWhitespaceSmart(str, prevTag, nextTag, options) { + var trimLeft = prevTag && !selfClosingInlineTags(prevTag); + if (trimLeft && !options.collapseInlineTagWhitespace) { + trimLeft = prevTag.charAt(0) === '/' ? !inlineTags(prevTag.slice(1)) : !inlineTextTags(prevTag); + } + var trimRight = nextTag && !selfClosingInlineTags(nextTag); + if (trimRight && !options.collapseInlineTagWhitespace) { + trimRight = nextTag.charAt(0) === '/' ? !inlineTextTags(nextTag.slice(1)) : !inlineTags(nextTag); + } + return collapseWhitespace(str, options, trimLeft, trimRight, prevTag && nextTag); +} + +function isConditionalComment(text) { + return /^\[if\s[^\]]+]|\[endif]$/.test(text); +} + +function isIgnoredComment(text, options) { + for (var i = 0, len = options.ignoreCustomComments.length; i < len; i++) { + if (options.ignoreCustomComments[i].test(text)) { + return true; + } + } + return false; +} + +function isEventAttribute(attrName, options) { + var patterns = options.customEventAttributes; + if (patterns) { + for (var i = patterns.length; i--;) { + if (patterns[i].test(attrName)) { + return true; + } + } + return false; + } + return /^on[a-z]{3,}$/.test(attrName); +} + +function canRemoveAttributeQuotes(value) { + // http://mathiasbynens.be/notes/unquoted-attribute-values + return /^[^ \t\n\f\r"'`=<>]+$/.test(value); +} + +function attributesInclude(attributes, attribute) { + for (var i = attributes.length; i--;) { + if (attributes[i].name.toLowerCase() === attribute) { + return true; + } + } + return false; +} + +function isAttributeRedundant(tag, attrName, attrValue, attrs) { + attrValue = attrValue ? trimWhitespace(attrValue.toLowerCase()) : ''; + + return ( + tag === 'script' && + attrName === 'language' && + attrValue === 'javascript' || + + tag === 'form' && + attrName === 'method' && + attrValue === 'get' || + + tag === 'input' && + attrName === 'type' && + attrValue === 'text' || + + tag === 'script' && + attrName === 'charset' && + !attributesInclude(attrs, 'src') || + + tag === 'a' && + attrName === 'name' && + attributesInclude(attrs, 'id') || + + tag === 'area' && + attrName === 'shape' && + attrValue === 'rect' + ); +} + +// https://mathiasbynens.be/demo/javascript-mime-type +// https://developer.mozilla.org/en/docs/Web/HTML/Element/script#attr-type +var executableScriptsMimetypes = utils.createMap([ + 'text/javascript', + 'text/ecmascript', + 'text/jscript', + 'application/javascript', + 'application/x-javascript', + 'application/ecmascript' +]); + +function isScriptTypeAttribute(attrValue) { + attrValue = trimWhitespace(attrValue.split(/;/, 2)[0]).toLowerCase(); + return attrValue === '' || executableScriptsMimetypes(attrValue); +} + +function isExecutableScript(tag, attrs) { + if (tag !== 'script') { + return false; + } + for (var i = 0, len = attrs.length; i < len; i++) { + var attrName = attrs[i].name.toLowerCase(); + if (attrName === 'type') { + return isScriptTypeAttribute(attrs[i].value); + } + } + return true; +} + +function isStyleLinkTypeAttribute(attrValue) { + attrValue = trimWhitespace(attrValue).toLowerCase(); + return attrValue === '' || attrValue === 'text/css'; +} + +function isStyleSheet(tag, attrs) { + if (tag !== 'style') { + return false; + } + for (var i = 0, len = attrs.length; i < len; i++) { + var attrName = attrs[i].name.toLowerCase(); + if (attrName === 'type') { + return isStyleLinkTypeAttribute(attrs[i].value); + } + } + return true; +} + +var isSimpleBoolean = createMapFromString('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,truespeed,typemustmatch,visible'); +var isBooleanValue = createMapFromString('true,false'); + +function isBooleanAttribute(attrName, attrValue) { + return isSimpleBoolean(attrName) || attrName === 'draggable' && !isBooleanValue(attrValue); +} + +function isUriTypeAttribute(attrName, tag) { + return ( + /^(?:a|area|link|base)$/.test(tag) && attrName === 'href' || + tag === 'img' && /^(?:src|longdesc|usemap)$/.test(attrName) || + tag === 'object' && /^(?:classid|codebase|data|usemap)$/.test(attrName) || + tag === 'q' && attrName === 'cite' || + tag === 'blockquote' && attrName === 'cite' || + (tag === 'ins' || tag === 'del') && attrName === 'cite' || + tag === 'form' && attrName === 'action' || + tag === 'input' && (attrName === 'src' || attrName === 'usemap') || + tag === 'head' && attrName === 'profile' || + tag === 'script' && (attrName === 'src' || attrName === 'for') + ); +} + +function isNumberTypeAttribute(attrName, tag) { + return ( + /^(?:a|area|object|button)$/.test(tag) && attrName === 'tabindex' || + tag === 'input' && (attrName === 'maxlength' || attrName === 'tabindex') || + tag === 'select' && (attrName === 'size' || attrName === 'tabindex') || + tag === 'textarea' && /^(?:rows|cols|tabindex)$/.test(attrName) || + tag === 'colgroup' && attrName === 'span' || + tag === 'col' && attrName === 'span' || + (tag === 'th' || tag === 'td') && (attrName === 'rowspan' || attrName === 'colspan') + ); +} + +function isLinkType(tag, attrs, value) { + if (tag !== 'link') { + return false; + } + for (var i = 0, len = attrs.length; i < len; i++) { + if (attrs[i].name === 'rel' && attrs[i].value === value) { + return true; + } + } +} + +function isMediaQuery(tag, attrs, attrName) { + return attrName === 'media' && (isLinkType(tag, attrs, 'stylesheet') || isStyleSheet(tag, attrs)); +} + +var srcsetTags = createMapFromString('img,source'); + +function isSrcset(attrName, tag) { + return attrName === 'srcset' && srcsetTags(tag); +} + +function cleanAttributeValue(tag, attrName, attrValue, options, attrs) { + if (attrValue && isEventAttribute(attrName, options)) { + attrValue = trimWhitespace(attrValue).replace(/^javascript:\s*/i, ''); + return options.minifyJS(attrValue, true); + } + else if (attrName === 'class') { + attrValue = trimWhitespace(attrValue); + if (options.sortClassName) { + attrValue = options.sortClassName(attrValue); + } + else { + attrValue = collapseWhitespaceAll(attrValue); + } + return attrValue; + } + else if (isUriTypeAttribute(attrName, tag)) { + attrValue = trimWhitespace(attrValue); + return isLinkType(tag, attrs, 'canonical') ? attrValue : options.minifyURLs(attrValue); + } + else if (isNumberTypeAttribute(attrName, tag)) { + return trimWhitespace(attrValue); + } + else if (attrName === 'style') { + attrValue = trimWhitespace(attrValue); + if (attrValue) { + if (/;$/.test(attrValue) && !/&#?[0-9a-zA-Z]+;$/.test(attrValue)) { + attrValue = attrValue.replace(/\s*;$/, ''); + } + attrValue = unwrapInlineCSS(options.minifyCSS(wrapInlineCSS(attrValue))); + } + return attrValue; + } + else if (isSrcset(attrName, tag)) { + // https://html.spec.whatwg.org/multipage/embedded-content.html#attr-img-srcset + attrValue = trimWhitespace(attrValue).split(/\s+,\s*|\s*,\s+/).map(function(candidate) { + var url = candidate; + var descriptor = ''; + var match = candidate.match(/\s+([1-9][0-9]*w|[0-9]+(?:\.[0-9]+)?x)$/); + if (match) { + url = url.slice(0, -match[0].length); + var num = +match[1].slice(0, -1); + var suffix = match[1].slice(-1); + if (num !== 1 || suffix !== 'x') { + descriptor = ' ' + num + suffix; + } + } + return options.minifyURLs(url) + descriptor; + }).join(', '); + } + else if (isMetaViewport(tag, attrs) && attrName === 'content') { + attrValue = attrValue.replace(/\s+/g, '').replace(/[0-9]+\.[0-9]+/g, function(numString) { + // "0.90000" -> "0.9" + // "1.0" -> "1" + // "1.0001" -> "1.0001" (unchanged) + return (+numString).toString(); + }); + } + else if (attrValue && options.customAttrCollapse && options.customAttrCollapse.test(attrName)) { + attrValue = attrValue.replace(/\n+|\r+|\s{2,}/g, ''); + } + else if (tag === 'script' && attrName === 'type') { + attrValue = trimWhitespace(attrValue.replace(/\s*;\s*/g, ';')); + } + else if (isMediaQuery(tag, attrs, attrName)) { + attrValue = trimWhitespace(attrValue); + return unwrapMediaQuery(options.minifyCSS(wrapMediaQuery(attrValue))); + } + return attrValue; +} + +function isMetaViewport(tag, attrs) { + if (tag !== 'meta') { + return false; + } + for (var i = 0, len = attrs.length; i < len; i++) { + if (attrs[i].name === 'name' && attrs[i].value === 'viewport') { + return true; + } + } +} + +// Wrap CSS declarations for CleanCSS > 3.x +// See https://github.com/jakubpawlowicz/clean-css/issues/418 +function wrapInlineCSS(text) { + return '*{' + text + '}'; +} + +function unwrapInlineCSS(text) { + var matches = text.match(/^\*\{([\s\S]*)\}$/); + return matches ? matches[1] : text; +} + +function wrapMediaQuery(text) { + return '@media ' + text + '{a{top:0}}'; +} + +function unwrapMediaQuery(text) { + var matches = text.match(/^@media ([\s\S]*?)\s*{[\s\S]*}$/); + return matches ? matches[1] : text; +} + +function cleanConditionalComment(comment, options) { + return options.processConditionalComments ? comment.replace(/^(\[if\s[^\]]+]>)([\s\S]*?)( -1) { + return minify(text, options); + } + } + return text; +} + +// Tag omission rules from https://html.spec.whatwg.org/multipage/syntax.html#optional-tags +// with the following deviations: +// - retain if followed by