12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484 |
- /*!
- * HTMLMinifier v0.6.9 (http://kangax.github.io/html-minifier/)
- * Copyright 2010-2014 Juriy "kangax" Zaytsev
- * Licensed under MIT (https://github.com/kangax/html-minifier/blob/gh-pages/LICENSE)
- */
- /*!
- * HTML Parser By John Resig (ejohn.org)
- * Modified by Juriy "kangax" Zaytsev
- * Original code by Erik Arvidsson, Mozilla Public License
- * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js
- */
- /*
- * // Use like so:
- * HTMLParser(htmlString, {
- * start: function(tag, attrs, unary) {},
- * end: function(tag) {},
- * chars: function(text) {},
- * comment: function(text) {}
- * });
- *
- * // or to get an XML string:
- * HTMLtoXML(htmlString);
- *
- * // or to get an XML DOM Document
- * HTMLtoDOM(htmlString);
- *
- * // or to inject into an existing document/DOM node
- * HTMLtoDOM(htmlString, document);
- * HTMLtoDOM(htmlString, document.body);
- *
- */
- /* global ActiveXObject, DOMDocument */
- (function(global) {
- 'use strict';
- // Regular Expressions for parsing tags and attributes
- var singleAttrIdentifier = /([\w:.-]+)/,
- singleAttrAssign = /=/,
- singleAttrAssigns = [ singleAttrAssign ],
- singleAttrValues = [
- /"((?:\\.|[^"])*)"/.source, // attr value double quotes
- /'((?:\\.|[^'])*)'/.source, // attr value, single quotes
- /([^>\s]+)/.source // attr value, no quotes
- ],
- startTagOpen = /^<([\w:-]+)/,
- startTagClose = /\s*(\/?)>/,
- endTag = /^<\/([\w:-]+)[^>]*>/,
- endingSlash = /\/>$/,
- doctype = /^<!DOCTYPE [^>]+>/i;
- var IS_REGEX_CAPTURING_BROKEN = false;
- 'x'.replace(/x(.)?/g, function(m, g) {
- IS_REGEX_CAPTURING_BROKEN = g === '';
- });
- // Empty Elements - HTML 4.01
- var empty = makeMap('area,base,basefont,br,col,frame,hr,img,input,isindex,link,meta,param,embed,wbr');
- // Block Elements - HTML 4.01
- // var block = makeMap('address,applet,blockquote,button,center,dd,del,dir,div,dl,dt,fieldset,form,frameset,hr,iframe,ins,isindex,li,map,menu,noframes,noscript,object,ol,p,pre,script,table,tbody,td,tfoot,th,thead,tr,ul');
- // Inline Elements - HTML 4.01
- var inline = makeMap('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');
- // Elements that you can, intentionally, leave open
- // (and which close themselves)
- var closeSelf = makeMap('colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr,source');
- // Attributes that have their values filled in disabled='disabled'
- var fillAttrs = makeMap('checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected');
- // Special Elements (can contain anything)
- var special = makeMap('script,style,noscript');
- var reCache = {}, stackedTag, reStackedTag, tagMatch;
- function startTagForHandler( handler ) {
- var customStartTagAttrs;
- var startTagAttrs = new RegExp(
- '(?:\\s*[\\w:.-]+'
- + '(?:\\s*'
- + '(?:' + joinSingleAttrAssigns(handler) + ')'
- + '\\s*(?:(?:"[^"]*")|(?:\'[^\']*\')|[^>\\s]+)'
- + ')?'
- + ')*'
- );
- if ( handler.customAttrSurround ) {
- var attrClauses = [];
- for ( var i = handler.customAttrSurround.length - 1; i >= 0; i-- ) {
- // Capture the custom attribute opening and closing markup surrounding the standard attribute rules
- attrClauses[i] = '(?:\\s*'
- + handler.customAttrSurround[i][0].source
- + startTagAttrs.source
- + handler.customAttrSurround[i][1].source
- + ')';
- }
- attrClauses.unshift(startTagAttrs.source);
- customStartTagAttrs = new RegExp(
- '((?:' + attrClauses.join('|') + ')*)'
- );
- }
- else {
- // No custom attribute wrappers specified, so just capture the standard attribute rules
- customStartTagAttrs = new RegExp('(' + startTagAttrs.source + ')');
- }
- return new RegExp(startTagOpen.source + customStartTagAttrs.source + startTagClose.source);
- }
- function attrForHandler( handler ) {
- var singleAttr = new RegExp(
- singleAttrIdentifier.source
- + '(?:\\s*'
- + '(' + joinSingleAttrAssigns( handler ) + ')'
- + '\\s*'
- + '(?:'
- + singleAttrValues.join('|')
- + ')'
- + ')?'
- );
- if ( handler.customAttrSurround ) {
- var attrClauses = [];
- for ( var i = handler.customAttrSurround.length - 1; i >= 0; i-- ) {
- attrClauses[i] = '(?:'
- + '(' + handler.customAttrSurround[i][0].source + ')'
- + singleAttr.source
- + '(' + handler.customAttrSurround[i][1].source + ')'
- + ')';
- }
- attrClauses.unshift('(?:' + singleAttr.source + ')');
- return new RegExp(attrClauses.join('|'), 'g');
- }
- else {
- return new RegExp(singleAttr.source, 'g');
- }
- }
- function joinSingleAttrAssigns( handler ) {
- return singleAttrAssigns.concat(
- handler.customAttrAssign || []
- ).map(function (assign) {
- return '(?:' + assign.source + ')';
- }).join('|');
- }
- var HTMLParser = global.HTMLParser = function( html, handler ) {
- var index, chars, match, stack = [], last = html, prevTag, nextTag;
- stack.last = function() {
- var last = this[ this.length - 1 ];
- return last && last.tag;
- };
- var startTag = startTagForHandler(handler);
- var attr = attrForHandler(handler);
- while ( html ) {
- chars = true;
- // Make sure we're not in a script or style element
- if ( !stack.last() || !special[ stack.last() ] ) {
- // Comment:
- if ( /^<!--/.test( html ) ) {
- index = html.indexOf('-->');
- if ( index >= 0 ) {
- if ( handler.comment ) {
- handler.comment( html.substring( 4, index ) );
- }
- html = html.substring( index + 3 );
- chars = false;
- }
- }
- // http://en.wikipedia.org/wiki/Conditional_comment#Downlevel-revealed_conditional_comment
- if ( /^<!\[/.test( html ) ) {
- index = html.indexOf(']>');
- if (index >= 0) {
- if ( handler.comment ) {
- handler.comment( html.substring(2, index + 1 ), true /* non-standard */ );
- }
- html = html.substring( index + 2 );
- chars = false;
- }
- }
- // Ignored elements?
- else if ( /^<\?/.test( html ) ) {
- index = html.indexOf( '?>', 2 );
- if ( index >= 0 ) {
- if ( handler.chars ) {
- handler.chars( html.substring( 0, index + 2 ) );
- }
- html = html.substring( index + 2 );
- }
- }
- else if ( /^<%/.test( html ) ) {
- index = html.indexOf( '%>', 2 );
- if ( index >= 0 ) {
- if ( handler.chars ) {
- handler.chars(html.substring( 0, index + 2) );
- }
- html = html.substring( index + 2 );
- }
- }
- // Doctype:
- else if ( (match = doctype.exec( html )) ) {
- if ( handler.doctype ) {
- handler.doctype( match[0] );
- }
- html = html.substring( match[0].length );
- chars = false;
- }
- // End tag:
- else if ( /^<\//.test( html ) ) {
- match = html.match( endTag );
- if ( match ) {
- html = html.substring( match[0].length );
- match[0].replace( endTag, parseEndTag );
- prevTag = '/' + match[1].toLowerCase();
- chars = false;
- }
- // Start tag:
- }
- else if ( /^</.test( html ) ) {
- match = html.match( startTag );
- if ( match ) {
- html = html.substring( match[0].length );
- match[0].replace( startTag, parseStartTag );
- prevTag = match[1].toLowerCase();
- chars = false;
- }
- }
- if ( chars ) {
- index = html.indexOf('<');
- var text = index < 0 ? html : html.substring( 0, index );
- html = index < 0 ? '' : html.substring( index );
- // next tag
- tagMatch = html.match( startTag );
- if (tagMatch) {
- nextTag = tagMatch[1];
- }
- else {
- tagMatch = html.match( endTag );
- if (tagMatch) {
- nextTag = '/' + tagMatch[1];
- }
- else {
- nextTag = '';
- }
- }
- if ( handler.chars ) {
- handler.chars(text, prevTag, nextTag);
- }
- }
- }
- else {
- stackedTag = stack.last().toLowerCase();
- reStackedTag = reCache[stackedTag] || (reCache[stackedTag] = new RegExp('([\\s\\S]*?)<\/' + stackedTag + '[^>]*>', 'i'));
- html = html.replace(reStackedTag, function(all, text) {
- if (stackedTag !== 'script' && stackedTag !== 'style' && stackedTag !== 'noscript') {
- text = text
- .replace(/<!--([\s\S]*?)-->/g, '$1')
- .replace(/<!\[CDATA\[([\s\S]*?)\]\]>/g, '$1');
- }
- if ( handler.chars ) {
- handler.chars( text );
- }
- return '';
- });
- parseEndTag( '', stackedTag );
- }
- if ( html === last ) {
- throw 'Parse Error: ' + html;
- }
- last = html;
- }
- // Clean up any remaining tags
- parseEndTag();
- function parseStartTag( tag, tagName, rest, unary ) {
- var unarySlash = false;
- while ( !handler.html5 && stack.last() && inline[ stack.last() ]) {
- parseEndTag( '', stack.last() );
- }
- if ( closeSelf[ tagName ] && stack.last() === tagName ) {
- parseEndTag( '', tagName );
- }
- unary = empty[ tagName ] || !!unary;
- var attrs = [];
- rest.replace(attr, function () {
- var name, value, fallbackValue, customOpen, customClose, customAssign;
- var ncp = 7; // number of captured parts, scalar
- // hackish work around FF bug https://bugzilla.mozilla.org/show_bug.cgi?id=369778
- if (IS_REGEX_CAPTURING_BROKEN && arguments[0].indexOf('""') === -1) {
- if (arguments[3] === '') { arguments[3] = undefined; }
- if (arguments[4] === '') { arguments[4] = undefined; }
- if (arguments[5] === '') { arguments[5] = undefined; }
- }
- name = arguments[1];
- if ( name ) {
- customAssign = arguments[2];
- fallbackValue = arguments[3];
- value = fallbackValue || arguments[4] || arguments[5];
- }
- else if ( handler.customAttrSurround ) {
- for ( var i = handler.customAttrSurround.length - 1; i >= 0; i-- ) {
- name = arguments[i * ncp + 7];
- customAssign = arguments[i * ncp + 8];
- if ( name ) {
- fallbackValue = arguments[i * ncp + 9];
- value = fallbackValue
- || arguments[i * ncp + 10]
- || arguments[i * ncp + 11];
- customOpen = arguments[i * ncp + 6];
- customClose = arguments[i * ncp + 12];
- break;
- }
- }
- }
- if ( value === undefined ) {
- value = fillAttrs[name] ? name : fallbackValue;
- }
- attrs.push({
- name: name,
- value: value,
- escaped: value && value.replace(/(^|.)("+)/g, function(match) {
- return match.replace(/"/g, '"');
- }),
- customAssign: customAssign || '=',
- customOpen: customOpen || '',
- customClose: customClose || ''
- });
- });
- if ( !unary ) {
- stack.push( { tag: tagName, attrs: attrs } );
- }
- else {
- unarySlash = tag.match( endingSlash );
- }
- if ( handler.start ) {
- handler.start( tagName, attrs, unary, unarySlash );
- }
- }
- function parseEndTag( tag, tagName ) {
- var pos;
- // If no tag name is provided, clean shop
- if ( !tagName ) {
- pos = 0;
- }
- else {
- // Find the closest opened tag of the same type
- var needle = tagName.toLowerCase();
- for ( pos = stack.length - 1; pos >= 0; pos-- ) {
- if ( stack[ pos ].tag.toLowerCase() === needle ) {
- break;
- }
- }
- }
- if ( pos >= 0 ) {
- // Close all the open elements, up the stack
- for ( var i = stack.length - 1; i >= pos; i-- ) {
- if ( handler.end ) {
- handler.end( stack[ i ].tag, stack[ i ].attrs );
- }
- }
- // Remove the open elements from the stack
- stack.length = pos;
- }
- }
- };
- global.HTMLtoXML = function( html ) {
- var results = '';
- new HTMLParser(html, {
- start: function( tag, attrs, unary ) {
- results += '<' + tag;
- for ( var i = 0; i < attrs.length; i++ ) {
- results += ' ' + attrs[i].name + '="' + attrs[i].escaped + '"';
- }
- results += (unary ? '/' : '') + '>';
- },
- end: function( tag ) {
- results += '</' + tag + '>';
- },
- chars: function( text ) {
- results += text;
- },
- comment: function( text ) {
- results += '<!--' + text + '-->';
- },
- ignore: function(text) {
- results += text;
- }
- });
- return results;
- };
- global.HTMLtoDOM = function( html, doc ) {
- // There can be only one of these elements
- var one = makeMap('html,head,body,title');
- // Enforce a structure for the document
- var structure = {
- link: 'head',
- base: 'head'
- };
- if ( !doc ) {
- if ( typeof DOMDocument !== 'undefined' ) {
- doc = new DOMDocument();
- }
- else if ( typeof document !== 'undefined' && document.implementation && document.implementation.createDocument ) {
- doc = document.implementation.createDocument('', '', null);
- }
- else if ( typeof ActiveX !== 'undefined' ) {
- doc = new ActiveXObject('Msxml.DOMDocument');
- }
- }
- else {
- doc = doc.ownerDocument ||
- doc.getOwnerDocument && doc.getOwnerDocument() ||
- doc;
- }
- var elems = [],
- documentElement = doc.documentElement ||
- doc.getDocumentElement && doc.getDocumentElement();
- // If we're dealing with an empty document then we
- // need to pre-populate it with the HTML document structure
- if ( !documentElement && doc.createElement ) {
- (function() {
- var html = doc.createElement('html');
- var head = doc.createElement('head');
- head.appendChild( doc.createElement('title') );
- html.appendChild( head );
- html.appendChild( doc.createElement('body') );
- doc.appendChild( html );
- })();
- }
- // Find all the unique elements
- if ( doc.getElementsByTagName ) {
- for ( var i in one ) {
- one[ i ] = doc.getElementsByTagName( i )[0];
- }
- }
- // If we're working with a document, inject contents into
- // the body element
- var curParentNode = one.body;
- new HTMLParser( html, {
- start: function( tagName, attrs, unary ) {
- // If it's a pre-built element, then we can ignore
- // its construction
- if ( one[ tagName ] ) {
- curParentNode = one[ tagName ];
- return;
- }
- var elem = doc.createElement( tagName );
- for ( var attr in attrs ) {
- elem.setAttribute( attrs[ attr ].name, attrs[ attr ].value );
- }
- if ( structure[ tagName ] && typeof one[ structure[ tagName ] ] !== 'boolean' ) {
- one[ structure[ tagName ] ].appendChild( elem );
- }
- else if ( curParentNode && curParentNode.appendChild ) {
- curParentNode.appendChild( elem );
- }
- if ( !unary ) {
- elems.push( elem );
- curParentNode = elem;
- }
- },
- end: function( /* tag */ ) {
- elems.length -= 1;
- // Init the new parentNode
- curParentNode = elems[ elems.length - 1 ];
- },
- chars: function( text ) {
- curParentNode.appendChild( doc.createTextNode( text ) );
- },
- comment: function( /*text*/ ) {
- // create comment node
- },
- ignore: function( /* text */ ) {
- // What to do here?
- }
- });
- return doc;
- };
- function makeMap(str) {
- var obj = {}, items = str.split(',');
- for ( var i = 0; i < items.length; i++ ) {
- obj[ items[i] ] = true;
- obj[ items[i].toUpperCase() ] = true;
- }
- return obj;
- }
- })(typeof exports === 'undefined' ? this : exports);
- /* global CleanCSS */
- (function(global) {
- 'use strict';
- var log, HTMLParser;
- if (global.console && global.console.log) {
- log = function(message) {
- // "preserving" `this`
- global.console.log(message);
- };
- }
- else {
- log = function() {};
- }
- if (global.HTMLParser) {
- HTMLParser = global.HTMLParser;
- }
- else if (typeof require === 'function') {
- HTMLParser = require('./htmlparser').HTMLParser;
- }
- var trimWhitespace = function(str) {
- if (typeof str !== 'string') {
- return str;
- }
- return str.replace(/^\s+/, '').replace(/\s+$/, '');
- };
- if (String.prototype.trim) {
- trimWhitespace = function(str) {
- if (typeof str !== 'string') {
- return str;
- }
- return str.trim();
- };
- }
- function collapseWhitespace(str) {
- return str ? str.replace(/[\t\n\r ]+/g, ' ') : str;
- }
- function collapseWhitespaceSmart(str, prevTag, nextTag, options) {
- // array of non-empty element tags that will maintain a single space outside of them
- var tags = [
- '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'
- ],
- lineBreakBefore = /^[\t ]*[\n\r]+[\t\n\r ]*/,
- lineBreakAfter = /[\t\n\r ]*[\n\r]+[\t ]*$/,
- preserveBefore = lineBreakBefore.test(str) ? '\n' : ' ',
- preserveAfter = lineBreakAfter.test(str) ? '\n' : ' ',
- lineBreakStamp = '[{htmlmin-lb}]';
- if (prevTag && prevTag !== 'img' && prevTag !== 'input' && (prevTag.substr(0,1) !== '/'
- || ( prevTag.substr(0,1) === '/' && tags.indexOf(prevTag.substr(1)) === -1))) {
- str = str.replace(/^\s+/, options.conservativeCollapse ? ' ' : options.preserveLineBreaks ? preserveBefore : '');
- }
- if (nextTag && nextTag !== 'img' && nextTag !== 'input' && (nextTag.substr(0,1) === '/'
- || ( nextTag.substr(0,1) !== '/' && tags.indexOf(nextTag) === -1))) {
- str = str.replace(/\s+$/, options.conservativeCollapse ? ' ' : options.preserveLineBreaks ? preserveAfter : '');
- }
- if (prevTag && nextTag) {
- if (options.preserveLineBreaks) {
- str = str
- .replace(lineBreakBefore, lineBreakStamp)
- .replace(lineBreakAfter, lineBreakStamp);
- }
- // strip non space whitespace then compress spaces to one
- return str
- .replace(/[\t\n\r]+/g, ' ').replace(/[ ]+/g, ' ')
- .replace(lineBreakStamp, '\n');
- }
- return str;
- }
- function isConditionalComment(text) {
- return ((/\[if[^\]]+\]/).test(text) || (/\s*((?:<!)?\[endif\])$/).test(text));
- }
- function isIgnoredComment(text, options) {
- if ((/^!/).test(text)) {
- return true;
- }
- if (options.ignoreCustomComments) {
- for (var i = 0, len = options.ignoreCustomComments.length; i < len; i++) {
- if (options.ignoreCustomComments[i].test(text)) {
- return true;
- }
- }
- }
- return false;
- }
- function isEventAttribute(attrName) {
- return (/^on[a-z]+/).test(attrName);
- }
- function canRemoveAttributeQuotes(value) {
- // http://mathiasbynens.be/notes/unquoted-attribute-values
- return (/^[^\x20\t\n\f\r"'`=<>]+$/).test(value) && !(/\/$/ ).test(value) &&
- // make sure trailing slash is not interpreted as HTML self-closing tag
- !(/\/$/).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')
- );
- }
- function isScriptTypeAttribute(tag, attrName, attrValue) {
- return (
- tag === 'script' &&
- attrName === 'type' &&
- trimWhitespace(attrValue.toLowerCase()) === 'text/javascript'
- );
- }
- function isStyleLinkTypeAttribute(tag, attrName, attrValue) {
- return (
- (tag === 'style' || tag === 'link') &&
- attrName === 'type' &&
- trimWhitespace(attrValue.toLowerCase()) === 'text/css'
- );
- }
- var enumeratedAttributeValues = {
- draggable: ['true', 'false'] // defaults to 'auto'
- };
- function isBooleanAttribute(attrName, attrValue) {
- var isSimpleBoolean = (/^(?: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(attrName);
- if (isSimpleBoolean) {
- return true;
- }
- var attrValueEnumeration = enumeratedAttributeValues[attrName.toLowerCase()];
- if (!attrValueEnumeration) {
- return false;
- }
- else {
- return (-1 === attrValueEnumeration.indexOf(attrValue.toLowerCase()));
- }
- }
- 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 cleanAttributeValue(tag, attrName, attrValue, options, attrs) {
- if (attrValue && isEventAttribute(attrName)) {
- attrValue = trimWhitespace(attrValue).replace(/^javascript:\s*/i, '').replace(/\s*;$/, '');
- if (options.minifyJS) {
- var wrappedCode = '(function(){' + attrValue + '})()';
- var minified = minifyJS(wrappedCode, options.minifyJS);
- return minified.slice(12, minified.length - 4).replace(/"/g, '"');
- }
- return attrValue;
- }
- else if (attrName === 'class') {
- return collapseWhitespace(trimWhitespace(attrValue));
- }
- else if (isUriTypeAttribute(attrName, tag)) {
- attrValue = trimWhitespace(attrValue);
- if (options.minifyURLs) {
- return minifyURLs(attrValue, options.minifyURLs);
- }
- return attrValue;
- }
- else if (isNumberTypeAttribute(attrName, tag)) {
- return trimWhitespace(attrValue);
- }
- else if (attrName === 'style') {
- attrValue = trimWhitespace(attrValue);
- if (attrValue) {
- attrValue = attrValue.replace(/\s*;\s*$/, '');
- }
- if (options.minifyCSS) {
- return minifyCSS(attrValue, options.minifyCSS);
- }
- return attrValue;
- }
- else if (isMetaViewport(tag, attrs) && attrName === 'content') {
- attrValue = attrValue.replace(/1\.0/g, '1').replace(/\s+/g, '');
- }
- else if (attrValue && options.customAttrCollapse && options.customAttrCollapse.test(attrName)) {
- attrValue = attrValue.replace(/\n+/g, '');
- }
- 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;
- }
- }
- }
- function cleanConditionalComment(comment) {
- return comment
- .replace(/^(\[[^\]]+\]>)\s*/, '$1')
- .replace(/\s*(<!\[endif\])$/, '$1');
- }
- function removeCDATASections(text) {
- return text
- // "/* <![CDATA[ */" or "// <![CDATA["
- .replace(/^(?:\s*\/\*\s*<!\[CDATA\[\s*\*\/|\s*\/\/\s*<!\[CDATA\[.*)/, '')
- // "/* ]]> */" or "// ]]>"
- .replace(/(?:\/\*\s*\]\]>\s*\*\/|\/\/\s*\]\]>)\s*$/, '');
- }
- function processScript(text, options, currentAttrs) {
- for (var i = 0, len = currentAttrs.length; i < len; i++) {
- if (currentAttrs[i].name.toLowerCase() === 'type' &&
- options.processScripts.indexOf(currentAttrs[i].value) > -1) {
- return minify(text, options);
- }
- }
- return text;
- }
- var reStartDelimiter = {
- // account for js + html comments (e.g.: //<!--)
- script: /^\s*(?:\/\/)?\s*<!--.*\n?/,
- style: /^\s*<!--\s*/
- };
- var reEndDelimiter = {
- script: /\s*(?:\/\/)?\s*-->\s*$/,
- style: /\s*-->\s*$/
- };
- function removeComments(text, tag) {
- return text.replace(reStartDelimiter[tag], '').replace(reEndDelimiter[tag], '');
- }
- function isOptionalTag(tag) {
- return (/^(?:html|t?body|t?head|tfoot|tr|td|th|dt|dd|option|colgroup|source)$/).test(tag);
- }
- var reEmptyAttribute = new RegExp(
- '^(?:class|id|style|title|lang|dir|on(?:focus|blur|change|click|dblclick|mouse(' +
- '?:down|up|over|move|out)|key(?:press|down|up)))$');
- function canDeleteEmptyAttribute(tag, attrName, attrValue) {
- var isValueEmpty = !attrValue || (/^\s*$/).test(attrValue);
- if (isValueEmpty) {
- return (
- (tag === 'input' && attrName === 'value') ||
- reEmptyAttribute.test(attrName));
- }
- return false;
- }
- function canRemoveElement(tag, attrs) {
- if (tag === 'textarea') {
- return false;
- }
- if (tag === 'script') {
- for (var i = attrs.length - 1; i >= 0; i--) {
- if (attrs[i].name === 'src') {
- return false;
- }
- }
- }
- return true;
- }
- function canCollapseWhitespace(tag) {
- return !(/^(?:script|style|pre|textarea)$/.test(tag));
- }
- function canTrimWhitespace(tag) {
- return !(/^(?:pre|textarea)$/.test(tag));
- }
- function attrsToMarkup(attrs) {
- var markup = '';
- for (var i = 0, len = attrs.length; i < len; i++) {
- markup += (' ' + attrs[i].name + (isBooleanAttribute(attrs[i].value) ? '' : ('="' + attrs[i].value + '"')));
- }
- return markup;
- }
- function normalizeAttribute(attr, attrs, tag, unarySlash, index, options) {
- var attrName = options.caseSensitive ? attr.name : attr.name.toLowerCase(),
- attrValue = attr.escaped,
- attrFragment,
- emittedAttrValue,
- isTerminalOfUnarySlash = unarySlash && index === attrs.length - 1;
- if ((options.removeRedundantAttributes &&
- isAttributeRedundant(tag, attrName, attrValue, attrs))
- ||
- (options.removeScriptTypeAttributes &&
- isScriptTypeAttribute(tag, attrName, attrValue))
- ||
- (options.removeStyleLinkTypeAttributes &&
- isStyleLinkTypeAttribute(tag, attrName, attrValue))) {
- return '';
- }
- attrValue = cleanAttributeValue(tag, attrName, attrValue, options, attrs);
- if (attrValue !== undefined && !options.removeAttributeQuotes ||
- !canRemoveAttributeQuotes(attrValue) || isTerminalOfUnarySlash) {
- emittedAttrValue = '"' + attrValue + '"';
- }
- else {
- emittedAttrValue = attrValue;
- }
- if (options.removeEmptyAttributes &&
- canDeleteEmptyAttribute(tag, attrName, attrValue)) {
- return '';
- }
- if (attrValue === undefined || (options.collapseBooleanAttributes &&
- isBooleanAttribute(attrName, attrValue))) {
- attrFragment = attrName;
- }
- else {
- attrFragment = attrName + attr.customAssign + emittedAttrValue;
- }
- return (' ' + attr.customOpen + attrFragment + attr.customClose);
- }
- function setDefaultTesters(options) {
- var defaultTesters = ['canCollapseWhitespace','canTrimWhitespace'];
- for (var i = 0, len = defaultTesters.length; i < len; i++) {
- if (!options[defaultTesters[i]]) {
- options[defaultTesters[i]] = function() {
- return false;
- };
- }
- }
- }
- function minifyURLs(text, options) {
- if (typeof options !== 'object') {
- options = { };
- }
- try {
- // try to get global reference first
- var __RelateUrl = global.RelateUrl;
- if (typeof __RelateUrl === 'undefined' && typeof require === 'function') {
- __RelateUrl = require('relateurl');
- }
- // noop
- if (!__RelateUrl) {
- return text;
- }
- if (__RelateUrl.relate) {
- return __RelateUrl.relate(text, options);
- }
- else {
- return text;
- }
- }
- catch (err) {
- log(err);
- }
- return text;
- }
- function minifyJS(text, options) {
- if (typeof options !== 'object') {
- options = { };
- }
- options.fromString = true;
- options.output = { inline_script: true };
- try {
- // try to get global reference first
- var __UglifyJS = global.UglifyJS;
- if (typeof __UglifyJS === 'undefined' && typeof require === 'function') {
- __UglifyJS = require('uglify-js');
- }
- // noop
- if (!__UglifyJS) {
- return text;
- }
- if (__UglifyJS.minify) {
- return __UglifyJS.minify(text, options).code;
- }
- else if (__UglifyJS.parse) {
- var ast = __UglifyJS.parse(text);
- ast.figure_out_scope();
- var compressor = __UglifyJS.Compressor();
- var compressedAst = ast.transform(compressor);
- compressedAst.figure_out_scope();
- compressedAst.compute_char_frequency();
- if (options.mangle !== false) {
- compressedAst.mangle_names();
- }
- var stream = __UglifyJS.OutputStream(options.output);
- compressedAst.print(stream);
- return stream.toString();
- }
- else {
- return text;
- }
- }
- catch (err) {
- log(err);
- }
- return text;
- }
- function minifyCSS(text, options) {
- if (typeof options !== 'object') {
- options = { };
- }
- if (typeof options.noAdvanced === 'undefined') {
- options.noAdvanced = true;
- }
- try {
- if (typeof CleanCSS !== 'undefined') {
- return new CleanCSS(options).minify(text);
- }
- else if (typeof require === 'function') {
- var CleanCSSModule = require('clean-css');
- return new CleanCSSModule(options).minify(text);
- }
- }
- catch (err) {
- log(err);
- }
- return text;
- }
- function minify(value, options) {
- options = options || {};
- value = trimWhitespace(value);
- setDefaultTesters(options);
- var results = [ ],
- buffer = [ ],
- currentChars = '',
- currentTag = '',
- currentAttrs = [],
- stackNoTrimWhitespace = [],
- stackNoCollapseWhitespace = [],
- lint = options.lint,
- isIgnoring = false,
- t = new Date();
- if (options.removeIgnored) {
- value = value
- .replace(/<\?[^\?]+\?>/g, '')
- .replace(/<%[^%]+%>/g, '');
- }
- function _canCollapseWhitespace(tag, attrs) {
- return canCollapseWhitespace(tag) || options.canCollapseWhitespace(tag, attrs);
- }
- function _canTrimWhitespace(tag, attrs) {
- return canTrimWhitespace(tag) || options.canTrimWhitespace(tag, attrs);
- }
- new HTMLParser(value, {
- html5: typeof options.html5 !== 'undefined' ? options.html5 : true,
- start: function( tag, attrs, unary, unarySlash ) {
- if (isIgnoring) {
- buffer.push('<' + tag, attrsToMarkup(attrs), unarySlash ? '/' : '', '>');
- return;
- }
- tag = options.caseSensitive ? tag : tag.toLowerCase();
- currentTag = tag;
- currentChars = '';
- currentAttrs = attrs;
- // set whitespace flags for nested tags (eg. <code> within a <pre>)
- if (options.collapseWhitespace) {
- if (!_canTrimWhitespace(tag, attrs)) {
- stackNoTrimWhitespace.push(tag);
- }
- if (!_canCollapseWhitespace(tag, attrs)) {
- stackNoCollapseWhitespace.push(tag);
- }
- }
- var openTag = '<' + tag;
- var closeTag = ((unarySlash && options.keepClosingSlash) ? '/' : '') + '>';
- if ( attrs.length === 0) {
- openTag += closeTag;
- }
- buffer.push(openTag);
- lint && lint.testElement(tag);
- var token;
- for ( var i = 0, len = attrs.length; i < len; i++ ) {
- lint && lint.testAttribute(tag, attrs[i].name.toLowerCase(), attrs[i].escaped);
- token = normalizeAttribute(attrs[i], attrs, tag, unarySlash, i, options);
- if ( i === len - 1 ) {
- token += closeTag;
- }
- buffer.push(token);
- }
- },
- end: function( tag, attrs ) {
- if (isIgnoring) {
- buffer.push('</' + tag + '>');
- return;
- }
- // check if current tag is in a whitespace stack
- if (options.collapseWhitespace) {
- if (stackNoTrimWhitespace.length &&
- tag === stackNoTrimWhitespace[stackNoTrimWhitespace.length - 1]) {
- stackNoTrimWhitespace.pop();
- }
- if (stackNoCollapseWhitespace.length &&
- tag === stackNoCollapseWhitespace[stackNoCollapseWhitespace.length - 1]) {
- stackNoCollapseWhitespace.pop();
- }
- }
- var isElementEmpty = currentChars === '' && tag === currentTag;
- if ((options.removeEmptyElements && isElementEmpty && canRemoveElement(tag, attrs))) {
- // remove last "element" from buffer, return
- for ( var i = buffer.length - 1; i >= 0; i-- ) {
- if ( /^<[^\/!]/.test(buffer[i]) ) {
- buffer.splice(i);
- break;
- }
- }
- return;
- }
- else if (options.removeOptionalTags && isOptionalTag(tag)) {
- // noop, leave start tag in buffer
- return;
- }
- else {
- // push end tag to buffer
- buffer.push('</' + (options.caseSensitive ? tag : tag.toLowerCase()) + '>');
- results.push.apply(results, buffer);
- }
- // flush buffer
- buffer.length = 0;
- currentChars = '';
- },
- chars: function( text, prevTag, nextTag ) {
- prevTag = prevTag === '' ? 'comment' : prevTag;
- nextTag = nextTag === '' ? 'comment' : nextTag;
- if (isIgnoring) {
- buffer.push(text);
- return;
- }
- if (currentTag === 'script' || currentTag === 'style') {
- if (options.removeCommentsFromCDATA) {
- text = removeComments(text, currentTag);
- }
- if (options.removeCDATASectionsFromCDATA) {
- text = removeCDATASections(text);
- }
- if (options.processScripts) {
- text = processScript(text, options, currentAttrs);
- }
- }
- if (currentTag === 'script' && options.minifyJS) {
- text = minifyJS(text, options.minifyJS);
- }
- if (currentTag === 'style' && options.minifyCSS) {
- text = minifyCSS(text, options.minifyCSS);
- }
- if (options.collapseWhitespace) {
- if (!stackNoTrimWhitespace.length) {
- text = ((prevTag && prevTag !== 'comment') || (nextTag && nextTag !== 'comment')) ?
- collapseWhitespaceSmart(text, prevTag, nextTag, options)
- : trimWhitespace(text);
- }
- if (!stackNoCollapseWhitespace.length) {
- text = !(prevTag && nextTag || nextTag === 'html') ? collapseWhitespace(text) : text;
- }
- }
- currentChars = text;
- lint && lint.testChars(text);
- buffer.push(text);
- },
- comment: function( text, nonStandard ) {
- var prefix = nonStandard ? '<!' : '<!--';
- var suffix = nonStandard ? '>' : '-->';
- if (/^\s*htmlmin:ignore/.test(text)) {
- isIgnoring = !isIgnoring;
- if (!options.removeComments) {
- buffer.push('<!--' + text + '-->');
- }
- return;
- }
- if (options.removeComments) {
- if (isConditionalComment(text)) {
- text = prefix + cleanConditionalComment(text) + suffix;
- }
- else if (isIgnoredComment(text, options)) {
- text = '<!--' + text + '-->';
- }
- else {
- text = '';
- }
- }
- else {
- text = prefix + text + suffix;
- }
- buffer.push(text);
- },
- doctype: function(doctype) {
- buffer.push(options.useShortDoctype ? '<!DOCTYPE html>' : collapseWhitespace(doctype));
- },
- customAttrAssign: options.customAttrAssign,
- customAttrSurround: options.customAttrSurround
- });
- results.push.apply(results, buffer);
- var str = joinResultSegments(results, options);
- log('minified in: ' + (new Date() - t) + 'ms');
- return str;
- }
- function joinResultSegments( results, options ) {
- var str;
- var maxLineLength = options.maxLineLength;
- if ( maxLineLength ) {
- var token;
- var lines = [];
- var line = '';
- for ( var i = 0, len = results.length; i < len; i++ ) {
- token = results[i];
- if ( line.length + token.length < maxLineLength ) {
- line += token;
- }
- else {
- lines.push(line.replace(/^\n/, ''));
- line = token;
- }
- }
- lines.push(line);
- str = lines.join('\n');
- }
- else {
- str = results.join('');
- }
- return str;
- }
- // for CommonJS enviroments, export everything
- if ( typeof exports !== 'undefined' ) {
- exports.minify = minify;
- }
- else {
- global.minify = minify;
- }
- }(this));
- /*!
- * HTMLLint (to be used in conjunction with HTMLMinifier)
- *
- * Copyright (c) 2010-2013 Juriy "kangax" Zaytsev
- * Licensed under the MIT license.
- *
- */
- (function(global) {
- 'use strict';
- function isPresentationalElement(tag) {
- return (/^(?:big|small|hr|blink|marquee)$/).test(tag);
- }
- function isDeprecatedElement(tag) {
- return (/^(?:applet|basefont|center|dir|font|isindex|strike)$/).test(tag);
- }
- function isEventAttribute(attrName) {
- return (/^on[a-z]+/).test(attrName);
- }
- function isStyleAttribute(attrName) {
- return ('style' === attrName.toLowerCase());
- }
- function isDeprecatedAttribute(tag, attrName) {
- return (
- (attrName === 'align' &&
- (/^(?:caption|applet|iframe|img|imput|object|legend|table|hr|div|h[1-6]|p)$/).test(tag)) ||
- (attrName === 'alink' && tag === 'body') ||
- (attrName === 'alt' && tag === 'applet') ||
- (attrName === 'archive' && tag === 'applet') ||
- (attrName === 'background' && tag === 'body') ||
- (attrName === 'bgcolor' && (/^(?:table|t[rdh]|body)$/).test(tag)) ||
- (attrName === 'border' && (/^(?:img|object)$/).test(tag)) ||
- (attrName === 'clear' && tag === 'br') ||
- (attrName === 'code' && tag === 'applet') ||
- (attrName === 'codebase' && tag === 'applet') ||
- (attrName === 'color' && (/^(?:base(?:font)?)$/).test(tag)) ||
- (attrName === 'compact' && (/^(?:dir|[dou]l|menu)$/).test(tag)) ||
- (attrName === 'face' && (/^base(?:font)?$/).test(tag)) ||
- (attrName === 'height' && (/^(?:t[dh]|applet)$/).test(tag)) ||
- (attrName === 'hspace' && (/^(?:applet|img|object)$/).test(tag)) ||
- (attrName === 'language' && tag === 'script') ||
- (attrName === 'link' && tag === 'body') ||
- (attrName === 'name' && tag === 'applet') ||
- (attrName === 'noshade' && tag === 'hr') ||
- (attrName === 'nowrap' && (/^t[dh]$/).test(tag)) ||
- (attrName === 'object' && tag === 'applet') ||
- (attrName === 'prompt' && tag === 'isindex') ||
- (attrName === 'size' && (/^(?:hr|font|basefont)$/).test(tag)) ||
- (attrName === 'start' && tag === 'ol') ||
- (attrName === 'text' && tag === 'body') ||
- (attrName === 'type' && (/^(?:li|ol|ul)$/).test(tag)) ||
- (attrName === 'value' && tag === 'li') ||
- (attrName === 'version' && tag === 'html') ||
- (attrName === 'vlink' && tag === 'body') ||
- (attrName === 'vspace' && (/^(?:applet|img|object)$/).test(tag)) ||
- (attrName === 'width' && (/^(?:hr|td|th|applet|pre)$/).test(tag))
- );
- }
- function isInaccessibleAttribute(attrName, attrValue) {
- return (
- attrName === 'href' &&
- (/^\s*javascript\s*:\s*void\s*(\s+0|\(\s*0\s*\))\s*$/i).test(attrValue)
- );
- }
- function Lint() {
- this.log = [ ];
- this._lastElement = null;
- this._isElementRepeated = false;
- }
- Lint.prototype.testElement = function(tag) {
- if (isDeprecatedElement(tag)) {
- this.log.push(
- 'Found <span class="deprecated-element">deprecated</span> <strong><code><' +
- tag + '></code></strong> element'
- );
- }
- else if (isPresentationalElement(tag)) {
- this.log.push(
- 'Found <span class="presentational-element">presentational</span> <strong><code><' +
- tag + '></code></strong> element'
- );
- }
- else {
- this.checkRepeatingElement(tag);
- }
- };
- Lint.prototype.checkRepeatingElement = function(tag) {
- if (tag === 'br' && this._lastElement === 'br') {
- this._isElementRepeated = true;
- }
- else if (this._isElementRepeated) {
- this._reportRepeatingElement();
- this._isElementRepeated = false;
- }
- this._lastElement = tag;
- };
- Lint.prototype._reportRepeatingElement = function() {
- this.log.push('Found <code><br></code> sequence. Try replacing it with styling.');
- };
- Lint.prototype.testAttribute = function(tag, attrName, attrValue) {
- if (isEventAttribute(attrName)) {
- this.log.push(
- 'Found <span class="event-attribute">event attribute</span> (<strong>' +
- attrName + '</strong>) on <strong><code><' + tag + '></code></strong> element.'
- );
- }
- else if (isDeprecatedAttribute(tag, attrName)) {
- this.log.push(
- 'Found <span class="deprecated-attribute">deprecated</span> <strong>' +
- attrName + '</strong> attribute on <strong><code><' + tag + '></code></strong> element.'
- );
- }
- else if (isStyleAttribute(attrName)) {
- this.log.push(
- 'Found <span class="style-attribute">style attribute</span> on <strong><code><' +
- tag + '></code></strong> element.'
- );
- }
- else if (isInaccessibleAttribute(attrName, attrValue)) {
- this.log.push(
- 'Found <span class="inaccessible-attribute">inaccessible attribute</span> ' +
- '(on <strong><code><' + tag + '></code></strong> element).'
- );
- }
- };
- Lint.prototype.testChars = function(chars) {
- this._lastElement = '';
- if (/( \s*){2,}/.test(chars)) {
- this.log.push('Found repeating <strong><code>&nbsp;</code></strong> sequence. Try replacing it with styling.');
- }
- };
- Lint.prototype.test = function(tag, attrName, attrValue) {
- this.testElement(tag);
- this.testAttribute(tag, attrName, attrValue);
- };
- Lint.prototype.populate = function(writeToElement) {
- if (this._isElementRepeated) {
- this._reportRepeatingElement();
- }
- if (this.log.length) {
- if (writeToElement) {
- writeToElement.innerHTML = '<ol><li>' + this.log.join('<li>') + '</ol>';
- }
- else {
- var output = ' - ' +
- this.log.join('\n - ')
- .replace(/(<([^>]+)>)/ig, '')
- .replace(/</g, '<')
- .replace(/>/g, '>');
- console.log(output);
- }
- }
- };
- global.HTMLLint = Lint;
- })(typeof exports === 'undefined' ? this : exports);
|