diff --git a/dist/core/rules/doctype-first.js b/dist/core/rules/doctype-first.js index f7767d371..235ea1cea 100644 --- a/dist/core/rules/doctype-first.js +++ b/dist/core/rules/doctype-first.js @@ -2,20 +2,35 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.default = { id: 'doctype-first', - description: 'Doctype must be declared first.', + description: 'Doctype must be declared first (comments and whitespace allowed before DOCTYPE).', init(parser, reporter) { + let doctypeFound = false; + let nonCommentContentBeforeDoctype = false; const allEvent = (event) => { if (event.type === 'start' || (event.type === 'text' && /^\s*$/.test(event.raw))) { return; } - if ((event.type !== 'comment' && event.long === false) || - /^DOCTYPE\s+/i.test(event.content) === false) { - reporter.error('Doctype must be declared first.', event.line, event.col, this, event.raw); + if (doctypeFound) { + return; + } + if (event.type === 'comment' && + event.long === false && + /^DOCTYPE\s+/i.test(event.content)) { + doctypeFound = true; + if (nonCommentContentBeforeDoctype) { + reporter.error('Doctype must be declared before any non-comment content.', event.line, event.col, this, event.raw); + } + return; + } + if (event.type === 'comment') { + return; } + nonCommentContentBeforeDoctype = true; + reporter.error('Doctype must be declared before any non-comment content.', event.line, event.col, this, event.raw); parser.removeListener('all', allEvent); }; parser.addListener('all', allEvent); }, }; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZG9jdHlwZS1maXJzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jb3JlL3J1bGVzL2RvY3R5cGUtZmlyc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFHQSxrQkFBZTtJQUNiLEVBQUUsRUFBRSxlQUFlO0lBQ25CLFdBQVcsRUFBRSxpQ0FBaUM7SUFDOUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxRQUFRO1FBQ25CLE1BQU0sUUFBUSxHQUFhLENBQUMsS0FBSyxFQUFFLEVBQUU7WUFDbkMsSUFDRSxLQUFLLENBQUMsSUFBSSxLQUFLLE9BQU87Z0JBQ3RCLENBQUMsS0FBSyxDQUFDLElBQUksS0FBSyxNQUFNLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsRUFDbEQ7Z0JBQ0EsT0FBTTthQUNQO1lBRUQsSUFDRSxDQUFDLEtBQUssQ0FBQyxJQUFJLEtBQUssU0FBUyxJQUFJLEtBQUssQ0FBQyxJQUFJLEtBQUssS0FBSyxDQUFDO2dCQUNsRCxjQUFjLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxLQUFLLEVBQzVDO2dCQUNBLFFBQVEsQ0FBQyxLQUFLLENBQ1osaUNBQWlDLEVBQ2pDLEtBQUssQ0FBQyxJQUFJLEVBQ1YsS0FBSyxDQUFDLEdBQUcsRUFDVCxJQUFJLEVBQ0osS0FBSyxDQUFDLEdBQUcsQ0FDVixDQUFBO2FBQ0Y7WUFFRCxNQUFNLENBQUMsY0FBYyxDQUFDLEtBQUssRUFBRSxRQUFRLENBQUMsQ0FBQTtRQUN4QyxDQUFDLENBQUE7UUFFRCxNQUFNLENBQUMsV0FBVyxDQUFDLEtBQUssRUFBRSxRQUFRLENBQUMsQ0FBQTtJQUNyQyxDQUFDO0NBQ00sQ0FBQSJ9 \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZG9jdHlwZS1maXJzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jb3JlL3J1bGVzL2RvY3R5cGUtZmlyc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFHQSxrQkFBZTtJQUNiLEVBQUUsRUFBRSxlQUFlO0lBQ25CLFdBQVcsRUFDVCxrRkFBa0Y7SUFDcEYsSUFBSSxDQUFDLE1BQU0sRUFBRSxRQUFRO1FBQ25CLElBQUksWUFBWSxHQUFHLEtBQUssQ0FBQTtRQUN4QixJQUFJLDhCQUE4QixHQUFHLEtBQUssQ0FBQTtRQUUxQyxNQUFNLFFBQVEsR0FBYSxDQUFDLEtBQUssRUFBRSxFQUFFO1lBRW5DLElBQ0UsS0FBSyxDQUFDLElBQUksS0FBSyxPQUFPO2dCQUN0QixDQUFDLEtBQUssQ0FBQyxJQUFJLEtBQUssTUFBTSxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQ2xEO2dCQUNBLE9BQU07YUFDUDtZQUdELElBQUksWUFBWSxFQUFFO2dCQUNoQixPQUFNO2FBQ1A7WUFHRCxJQUNFLEtBQUssQ0FBQyxJQUFJLEtBQUssU0FBUztnQkFDeEIsS0FBSyxDQUFDLElBQUksS0FBSyxLQUFLO2dCQUNwQixjQUFjLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsRUFDbEM7Z0JBQ0EsWUFBWSxHQUFHLElBQUksQ0FBQTtnQkFDbkIsSUFBSSw4QkFBOEIsRUFBRTtvQkFFbEMsUUFBUSxDQUFDLEtBQUssQ0FDWiwwREFBMEQsRUFDMUQsS0FBSyxDQUFDLElBQUksRUFDVixLQUFLLENBQUMsR0FBRyxFQUNULElBQUksRUFDSixLQUFLLENBQUMsR0FBRyxDQUNWLENBQUE7aUJBQ0Y7Z0JBQ0QsT0FBTTthQUNQO1lBR0QsSUFBSSxLQUFLLENBQUMsSUFBSSxLQUFLLFNBQVMsRUFBRTtnQkFDNUIsT0FBTTthQUNQO1lBR0QsOEJBQThCLEdBQUcsSUFBSSxDQUFBO1lBR3JDLFFBQVEsQ0FBQyxLQUFLLENBQ1osMERBQTBELEVBQzFELEtBQUssQ0FBQyxJQUFJLEVBQ1YsS0FBSyxDQUFDLEdBQUcsRUFDVCxJQUFJLEVBQ0osS0FBSyxDQUFDLEdBQUcsQ0FDVixDQUFBO1lBR0QsTUFBTSxDQUFDLGNBQWMsQ0FBQyxLQUFLLEVBQUUsUUFBUSxDQUFDLENBQUE7UUFDeEMsQ0FBQyxDQUFBO1FBRUQsTUFBTSxDQUFDLFdBQVcsQ0FBQyxLQUFLLEVBQUUsUUFBUSxDQUFDLENBQUE7SUFDckMsQ0FBQztDQUNNLENBQUEifQ== \ No newline at end of file diff --git a/dist/htmlhint.js b/dist/htmlhint.js deleted file mode 100644 index 46cdeb58b..000000000 --- a/dist/htmlhint.js +++ /dev/null @@ -1,2065 +0,0 @@ -/*! - * HTMLHint v1.2.0 - * https://htmlhint.com - * Built on: 2025-05-31 - * Copyright (c) 2025 HTMLHint - * Licensed under MIT License - */ -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : - typeof define === 'function' && define.amd ? define(factory) : - (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.HTMLHint = factory()); -})(this, (function () { 'use strict'; - - function getDefaultExportFromCjs (x) { - return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; - } - - var core$1 = {}; - - var htmlparser = {}; - - var hasRequiredHtmlparser; - - function requireHtmlparser () { - if (hasRequiredHtmlparser) return htmlparser; - hasRequiredHtmlparser = 1; - Object.defineProperty(htmlparser, "__esModule", { value: true }); - class HTMLParser { - constructor() { - this._listeners = {}; - this._mapCdataTags = this.makeMap('script,style'); - this._arrBlocks = []; - this.lastEvent = null; - } - makeMap(str) { - const obj = {}; - const items = str.split(','); - for (let i = 0; i < items.length; i++) { - obj[items[i]] = true; - } - return obj; - } - parse(html) { - const mapCdataTags = this._mapCdataTags; - const regTag = /<(?:\/([^\s>]+)\s*|!--([\s\S]*?)--|!([^>]*?)|([\w\-:]+)((?:\s+[^\s"'>\/=\x00-\x0F\x7F\x80-\x9F]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s"'>]*))?)*?)\s*(\/?))>/g; - const regAttr = /\s*([^\s"'>\/=\x00-\x0F\x7F\x80-\x9F]+)(?:\s*=\s*(?:(")([^"]*)"|(')([^']*)'|([^\s"'>]*)))?/g; - const regLine = /\r?\n/g; - let match; - let matchIndex; - let lastIndex = 0; - let tagName; - let arrAttrs; - let tagCDATA = null; - let attrsCDATA; - let arrCDATA = []; - let lastCDATAIndex = 0; - let text; - let lastLineIndex = 0; - let line = 1; - const arrBlocks = this._arrBlocks; - this.fire('start', { - pos: 0, - line: 1, - col: 1, - }); - const isMapCdataTagsRequired = () => { - const attrType = arrAttrs.find((attr) => attr.name === 'type') || { - value: '', - }; - return (mapCdataTags[tagName] && - attrType.value.indexOf('text/ng-template') === -1); - }; - const saveBlock = (type, raw, pos, data) => { - const col = pos - lastLineIndex + 1; - if (data === undefined) { - data = {}; - } - data.raw = raw; - data.pos = pos; - data.line = line; - data.col = col; - arrBlocks.push(data); - this.fire(type, data); - while (regLine.exec(raw)) { - line++; - lastLineIndex = pos + regLine.lastIndex; - } - }; - while ((match = regTag.exec(html))) { - matchIndex = match.index; - if (matchIndex > lastIndex) { - text = html.substring(lastIndex, matchIndex); - if (tagCDATA) { - arrCDATA.push(text); - } - else { - saveBlock('text', text, lastIndex); - } - } - lastIndex = regTag.lastIndex; - if ((tagName = match[1])) { - if (tagCDATA && tagName === tagCDATA) { - text = arrCDATA.join(''); - saveBlock('cdata', text, lastCDATAIndex, { - tagName: tagCDATA, - attrs: attrsCDATA, - }); - tagCDATA = null; - attrsCDATA = undefined; - arrCDATA = []; - } - if (!tagCDATA) { - saveBlock('tagend', match[0], matchIndex, { - tagName: tagName, - }); - continue; - } - } - if (tagCDATA) { - arrCDATA.push(match[0]); - } - else { - if ((tagName = match[4])) { - arrAttrs = []; - const attrs = match[5]; - let attrMatch; - let attrMatchCount = 0; - while ((attrMatch = regAttr.exec(attrs))) { - const name = attrMatch[1]; - const quote = attrMatch[2] - ? attrMatch[2] - : attrMatch[4] - ? attrMatch[4] - : ''; - const value = attrMatch[3] - ? attrMatch[3] - : attrMatch[5] - ? attrMatch[5] - : attrMatch[6] - ? attrMatch[6] - : ''; - arrAttrs.push({ - name: name, - value: value, - quote: quote, - index: attrMatch.index, - raw: attrMatch[0], - }); - attrMatchCount += attrMatch[0].length; - } - if (attrMatchCount === attrs.length) { - saveBlock('tagstart', match[0], matchIndex, { - tagName: tagName, - attrs: arrAttrs, - close: match[6], - }); - if (isMapCdataTagsRequired()) { - tagCDATA = tagName; - attrsCDATA = arrAttrs.concat(); - arrCDATA = []; - lastCDATAIndex = lastIndex; - } - } - else { - saveBlock('text', match[0], matchIndex); - } - } - else if (match[2] || match[3]) { - saveBlock('comment', match[0], matchIndex, { - content: match[2] || match[3], - long: match[2] ? true : false, - }); - } - } - } - if (html.length > lastIndex) { - text = html.substring(lastIndex, html.length); - saveBlock('text', text, lastIndex); - } - this.fire('end', { - pos: lastIndex, - line: line, - col: html.length - lastLineIndex + 1, - }); - } - addListener(types, listener) { - const _listeners = this._listeners; - const arrTypes = types.split(/[,\s]/); - let type; - for (let i = 0, l = arrTypes.length; i < l; i++) { - type = arrTypes[i]; - if (_listeners[type] === undefined) { - _listeners[type] = []; - } - _listeners[type].push(listener); - } - } - fire(type, data) { - if (data === undefined) { - data = {}; - } - data.type = type; - let listeners = []; - const listenersType = this._listeners[type]; - const listenersAll = this._listeners['all']; - if (listenersType !== undefined) { - listeners = listeners.concat(listenersType); - } - if (listenersAll !== undefined) { - listeners = listeners.concat(listenersAll); - } - const lastEvent = this.lastEvent; - if (lastEvent !== null) { - delete lastEvent['lastEvent']; - data.lastEvent = lastEvent; - } - this.lastEvent = data; - for (let i = 0, l = listeners.length; i < l; i++) { - listeners[i].call(this, data); - } - } - removeListener(type, listener) { - const listenersType = this._listeners[type]; - if (listenersType !== undefined) { - for (let i = 0, l = listenersType.length; i < l; i++) { - if (listenersType[i] === listener) { - listenersType.splice(i, 1); - break; - } - } - } - } - fixPos(event, index) { - const text = event.raw.substr(0, index); - const arrLines = text.split(/\r?\n/); - const lineCount = arrLines.length - 1; - let line = event.line; - let col; - if (lineCount > 0) { - line += lineCount; - col = arrLines[lineCount].length + 1; - } - else { - col = event.col + index; - } - return { - line: line, - col: col, - }; - } - getMapAttrs(arrAttrs) { - const mapAttrs = {}; - let attr; - for (let i = 0, l = arrAttrs.length; i < l; i++) { - attr = arrAttrs[i]; - mapAttrs[attr.name] = attr.value; - } - return mapAttrs; - } - } - htmlparser.default = HTMLParser; - - return htmlparser; - } - - var reporter = {}; - - var hasRequiredReporter; - - function requireReporter () { - if (hasRequiredReporter) return reporter; - hasRequiredReporter = 1; - Object.defineProperty(reporter, "__esModule", { value: true }); - class Reporter { - constructor(html, ruleset) { - this.html = html; - this.lines = html.split(/\r?\n/); - const match = /\r?\n/.exec(html); - this.brLen = match !== null ? match[0].length : 0; - this.ruleset = ruleset; - this.messages = []; - } - info(message, line, col, rule, raw) { - this.report("info", message, line, col, rule, raw); - } - warn(message, line, col, rule, raw) { - this.report("warning", message, line, col, rule, raw); - } - error(message, line, col, rule, raw) { - this.report("error", message, line, col, rule, raw); - } - report(type, message, line, col, rule, raw) { - const lines = this.lines; - const brLen = this.brLen; - let evidence = ''; - let evidenceLen = 0; - for (let i = line - 1, lineCount = lines.length; i < lineCount; i++) { - evidence = lines[i]; - evidenceLen = evidence.length; - if (col > evidenceLen && line < lineCount) { - line++; - col -= evidenceLen; - if (col !== 1) { - col -= brLen; - } - } - else { - break; - } - } - this.messages.push({ - type: type, - message: message, - raw: raw, - evidence: evidence, - line: line, - col: col, - rule: { - id: rule.id, - description: rule.description, - link: `https://htmlhint.com/docs/user-guide/rules/${rule.id}`, - }, - }); - } - } - reporter.default = Reporter; - - return reporter; - } - - var rules = {}; - - var altRequire = {}; - - var hasRequiredAltRequire; - - function requireAltRequire () { - if (hasRequiredAltRequire) return altRequire; - hasRequiredAltRequire = 1; - Object.defineProperty(altRequire, "__esModule", { value: true }); - altRequire.default = { - id: 'alt-require', - description: 'The alt attribute of an element must be present and alt attribute of area[href] and input[type=image] must have a value.', - init(parser, reporter) { - parser.addListener('tagstart', (event) => { - const tagName = event.tagName.toLowerCase(); - const mapAttrs = parser.getMapAttrs(event.attrs); - const col = event.col + tagName.length + 1; - let selector; - if (tagName === 'img' && !('alt' in mapAttrs)) { - reporter.warn('An alt attribute must be present on elements.', event.line, col, this, event.raw); - } - else if ((tagName === 'area' && 'href' in mapAttrs) || - (tagName === 'input' && mapAttrs['type'] === 'image')) { - if (!('alt' in mapAttrs) || mapAttrs['alt'] === '') { - selector = tagName === 'area' ? 'area[href]' : 'input[type=image]'; - reporter.warn(`The alt attribute of ${selector} must have a value.`, event.line, col, this, event.raw); - } - } - }); - }, - }; - - return altRequire; - } - - var attrLowercase = {}; - - var hasRequiredAttrLowercase; - - function requireAttrLowercase () { - if (hasRequiredAttrLowercase) return attrLowercase; - hasRequiredAttrLowercase = 1; - Object.defineProperty(attrLowercase, "__esModule", { value: true }); - const svgIgnores = [ - 'allowReorder', - 'attributeName', - 'attributeType', - 'autoReverse', - 'baseFrequency', - 'baseProfile', - 'calcMode', - 'clipPath', - 'clipPathUnits', - 'contentScriptType', - 'contentStyleType', - 'diffuseConstant', - 'edgeMode', - 'externalResourcesRequired', - 'filterRes', - 'filterUnits', - 'glyphRef', - 'gradientTransform', - 'gradientUnits', - 'kernelMatrix', - 'kernelUnitLength', - 'keyPoints', - 'keySplines', - 'keyTimes', - 'lengthAdjust', - 'limitingConeAngle', - 'markerHeight', - 'markerUnits', - 'markerWidth', - 'maskContentUnits', - 'maskUnits', - 'numOctaves', - 'onBlur', - 'onChange', - 'onClick', - 'onFocus', - 'onKeyUp', - 'onLoad', - 'pathLength', - 'patternContentUnits', - 'patternTransform', - 'patternUnits', - 'pointsAtX', - 'pointsAtY', - 'pointsAtZ', - 'preserveAlpha', - 'preserveAspectRatio', - 'primitiveUnits', - 'refX', - 'refY', - 'repeatCount', - 'repeatDur', - 'requiredExtensions', - 'requiredFeatures', - 'specularConstant', - 'specularExponent', - 'spreadMethod', - 'startOffset', - 'stdDeviation', - 'stitchTiles', - 'surfaceScale', - 'systemLanguage', - 'tableValues', - 'targetX', - 'targetY', - 'textLength', - 'viewBox', - 'viewTarget', - 'xChannelSelector', - 'yChannelSelector', - 'zoomAndPan', - ]; - function testAgainstStringOrRegExp(value, comparison) { - if (comparison instanceof RegExp) { - return comparison.test(value) - ? { match: value, pattern: comparison } - : false; - } - const firstComparisonChar = comparison[0]; - const lastComparisonChar = comparison[comparison.length - 1]; - const secondToLastComparisonChar = comparison[comparison.length - 2]; - const comparisonIsRegex = firstComparisonChar === '/' && - (lastComparisonChar === '/' || - (secondToLastComparisonChar === '/' && lastComparisonChar === 'i')); - const hasCaseInsensitiveFlag = comparisonIsRegex && lastComparisonChar === 'i'; - if (comparisonIsRegex) { - const valueMatches = hasCaseInsensitiveFlag - ? new RegExp(comparison.slice(1, -2), 'i').test(value) - : new RegExp(comparison.slice(1, -1)).test(value); - return valueMatches; - } - return value === comparison; - } - attrLowercase.default = { - id: 'attr-lowercase', - description: 'All attribute names must be in lowercase.', - init(parser, reporter, options) { - const exceptions = (Array.isArray(options) ? options : []).concat(svgIgnores); - parser.addListener('tagstart', (event) => { - const attrs = event.attrs; - let attr; - const col = event.col + event.tagName.length + 1; - for (let i = 0, l = attrs.length; i < l; i++) { - attr = attrs[i]; - const attrName = attr.name; - if (!exceptions.find((exp) => testAgainstStringOrRegExp(attrName, exp)) && - attrName !== attrName.toLowerCase()) { - reporter.error(`The attribute name of [ ${attrName} ] must be in lowercase.`, event.line, col + attr.index, this, attr.raw); - } - } - }); - }, - }; - - return attrLowercase; - } - - var attrNoDuplication = {}; - - var hasRequiredAttrNoDuplication; - - function requireAttrNoDuplication () { - if (hasRequiredAttrNoDuplication) return attrNoDuplication; - hasRequiredAttrNoDuplication = 1; - Object.defineProperty(attrNoDuplication, "__esModule", { value: true }); - attrNoDuplication.default = { - id: 'attr-no-duplication', - description: 'Elements cannot have duplicate attributes.', - init(parser, reporter) { - parser.addListener('tagstart', (event) => { - const attrs = event.attrs; - let attr; - let attrName; - const col = event.col + event.tagName.length + 1; - const mapAttrName = {}; - for (let i = 0, l = attrs.length; i < l; i++) { - attr = attrs[i]; - attrName = attr.name; - if (mapAttrName[attrName] === true) { - reporter.error(`Duplicate of attribute name [ ${attr.name} ] was found.`, event.line, col + attr.index, this, attr.raw); - } - mapAttrName[attrName] = true; - } - }); - }, - }; - - return attrNoDuplication; - } - - var attrNoUnnecessaryWhitespace = {}; - - var hasRequiredAttrNoUnnecessaryWhitespace; - - function requireAttrNoUnnecessaryWhitespace () { - if (hasRequiredAttrNoUnnecessaryWhitespace) return attrNoUnnecessaryWhitespace; - hasRequiredAttrNoUnnecessaryWhitespace = 1; - Object.defineProperty(attrNoUnnecessaryWhitespace, "__esModule", { value: true }); - attrNoUnnecessaryWhitespace.default = { - id: 'attr-no-unnecessary-whitespace', - description: 'No spaces between attribute names and values.', - init(parser, reporter, options) { - const exceptions = Array.isArray(options) ? options : []; - parser.addListener('tagstart', (event) => { - const attrs = event.attrs; - const col = event.col + event.tagName.length + 1; - for (let i = 0; i < attrs.length; i++) { - if (exceptions.indexOf(attrs[i].name) === -1) { - const match = /(\s*)=(\s*)/.exec(attrs[i].raw.trim()); - if (match && (match[1].length !== 0 || match[2].length !== 0)) { - reporter.error(`The attribute '${attrs[i].name}' must not have spaces between the name and value.`, event.line, col + attrs[i].index, this, attrs[i].raw); - } - } - } - }); - }, - }; - - return attrNoUnnecessaryWhitespace; - } - - var attrSorted = {}; - - var hasRequiredAttrSorted; - - function requireAttrSorted () { - if (hasRequiredAttrSorted) return attrSorted; - hasRequiredAttrSorted = 1; - Object.defineProperty(attrSorted, "__esModule", { value: true }); - attrSorted.default = { - id: 'attr-sorted', - description: 'Attribute tags must be in proper order.', - init(parser, reporter) { - const orderMap = {}; - const sortOrder = [ - 'class', - 'id', - 'name', - 'src', - 'for', - 'type', - 'rel', - 'href', - 'value', - 'title', - 'alt', - 'role', - ]; - for (let i = 0; i < sortOrder.length; i++) { - orderMap[sortOrder[i]] = i; - } - parser.addListener('tagstart', (event) => { - const attrs = event.attrs; - const listOfAttributes = []; - for (let i = 0; i < attrs.length; i++) { - listOfAttributes.push(attrs[i].name); - } - const originalAttrs = JSON.stringify(listOfAttributes); - listOfAttributes.sort((a, b) => { - if (orderMap[a] !== undefined) { - if (orderMap[b] !== undefined) { - return orderMap[a] - orderMap[b]; - } - return -1; - } - if (a.startsWith('data-')) { - if (b.startsWith('data-')) { - return a.localeCompare(b); - } - return 1; - } - if (orderMap[b] !== undefined) { - return 1; - } - if (b.startsWith('data-')) { - return -1; - } - return a.localeCompare(b); - }); - if (originalAttrs !== JSON.stringify(listOfAttributes)) { - reporter.error(`Inaccurate order ${originalAttrs} should be in hierarchy ${JSON.stringify(listOfAttributes)} `, event.line, event.col, this, event.raw); - } - }); - }, - }; - - return attrSorted; - } - - var attrUnsafeChars = {}; - - var hasRequiredAttrUnsafeChars; - - function requireAttrUnsafeChars () { - if (hasRequiredAttrUnsafeChars) return attrUnsafeChars; - hasRequiredAttrUnsafeChars = 1; - Object.defineProperty(attrUnsafeChars, "__esModule", { value: true }); - attrUnsafeChars.default = { - id: 'attr-unsafe-chars', - description: 'Attribute values cannot contain unsafe chars.', - init(parser, reporter) { - parser.addListener('tagstart', (event) => { - const attrs = event.attrs; - let attr; - const col = event.col + event.tagName.length + 1; - const regUnsafe = /[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/; - let match; - for (let i = 0, l = attrs.length; i < l; i++) { - attr = attrs[i]; - match = regUnsafe.exec(attr.value); - if (match !== null) { - const unsafeCode = escape(match[0]) - .replace(/%u/, '\\u') - .replace(/%/, '\\x'); - reporter.warn(`The value of attribute [ ${attr.name} ] cannot contain an unsafe char [ ${unsafeCode} ].`, event.line, col + attr.index, this, attr.raw); - } - } - }); - }, - }; - - return attrUnsafeChars; - } - - var attrValueDoubleQuotes = {}; - - var hasRequiredAttrValueDoubleQuotes; - - function requireAttrValueDoubleQuotes () { - if (hasRequiredAttrValueDoubleQuotes) return attrValueDoubleQuotes; - hasRequiredAttrValueDoubleQuotes = 1; - Object.defineProperty(attrValueDoubleQuotes, "__esModule", { value: true }); - attrValueDoubleQuotes.default = { - id: 'attr-value-double-quotes', - description: 'Attribute values must be in double quotes.', - init(parser, reporter) { - parser.addListener('tagstart', (event) => { - const attrs = event.attrs; - let attr; - const col = event.col + event.tagName.length + 1; - for (let i = 0, l = attrs.length; i < l; i++) { - attr = attrs[i]; - if ((attr.value !== '' && attr.quote !== '"') || - (attr.value === '' && attr.quote === "'")) { - reporter.error(`The value of attribute [ ${attr.name} ] must be in double quotes.`, event.line, col + attr.index, this, attr.raw); - } - } - }); - }, - }; - - return attrValueDoubleQuotes; - } - - var attrValueNotEmpty = {}; - - var hasRequiredAttrValueNotEmpty; - - function requireAttrValueNotEmpty () { - if (hasRequiredAttrValueNotEmpty) return attrValueNotEmpty; - hasRequiredAttrValueNotEmpty = 1; - Object.defineProperty(attrValueNotEmpty, "__esModule", { value: true }); - attrValueNotEmpty.default = { - id: 'attr-value-not-empty', - description: 'All attributes must have values.', - init(parser, reporter) { - parser.addListener('tagstart', (event) => { - const attrs = event.attrs; - let attr; - const col = event.col + event.tagName.length + 1; - for (let i = 0, l = attrs.length; i < l; i++) { - attr = attrs[i]; - if (attr.quote === '' && attr.value === '') { - reporter.warn(`The attribute [ ${attr.name} ] must have a value.`, event.line, col + attr.index, this, attr.raw); - } - } - }); - }, - }; - - return attrValueNotEmpty; - } - - var attrValueSingleQuotes = {}; - - var hasRequiredAttrValueSingleQuotes; - - function requireAttrValueSingleQuotes () { - if (hasRequiredAttrValueSingleQuotes) return attrValueSingleQuotes; - hasRequiredAttrValueSingleQuotes = 1; - Object.defineProperty(attrValueSingleQuotes, "__esModule", { value: true }); - attrValueSingleQuotes.default = { - id: 'attr-value-single-quotes', - description: 'Attribute values must be in single quotes.', - init(parser, reporter) { - parser.addListener('tagstart', (event) => { - const attrs = event.attrs; - let attr; - const col = event.col + event.tagName.length + 1; - for (let i = 0, l = attrs.length; i < l; i++) { - attr = attrs[i]; - if ((attr.value !== '' && attr.quote !== "'") || - (attr.value === '' && attr.quote === '"')) { - reporter.error(`The value of attribute [ ${attr.name} ] must be in single quotes.`, event.line, col + attr.index, this, attr.raw); - } - } - }); - }, - }; - - return attrValueSingleQuotes; - } - - var attrWhitespace = {}; - - var hasRequiredAttrWhitespace; - - function requireAttrWhitespace () { - if (hasRequiredAttrWhitespace) return attrWhitespace; - hasRequiredAttrWhitespace = 1; - Object.defineProperty(attrWhitespace, "__esModule", { value: true }); - attrWhitespace.default = { - id: 'attr-whitespace', - description: 'All attributes should be separated by only one space and not have leading/trailing whitespace.', - init(parser, reporter, options) { - const exceptions = Array.isArray(options) - ? options - : []; - parser.addListener('tagstart', (event) => { - const attrs = event.attrs; - let attr; - const col = event.col + event.tagName.length + 1; - attrs.forEach((elem) => { - attr = elem; - const attrName = elem.name; - if (exceptions.indexOf(attrName) !== -1) { - return; - } - if (elem.value.trim() !== elem.value) { - reporter.error(`The attributes of [ ${attrName} ] must not have leading or trailing whitespace.`, event.line, col + attr.index, this, attr.raw); - } - if (elem.value.replace(/ +(?= )/g, '') !== elem.value) { - reporter.error(`The attributes of [ ${attrName} ] must be separated by only one space.`, event.line, col + attr.index, this, attr.raw); - } - }); - }); - }, - }; - - return attrWhitespace; - } - - var doctypeFirst = {}; - - var hasRequiredDoctypeFirst; - - function requireDoctypeFirst () { - if (hasRequiredDoctypeFirst) return doctypeFirst; - hasRequiredDoctypeFirst = 1; - Object.defineProperty(doctypeFirst, "__esModule", { value: true }); - doctypeFirst.default = { - id: 'doctype-first', - description: 'Doctype must be declared first.', - init(parser, reporter) { - const allEvent = (event) => { - if (event.type === 'start' || - (event.type === 'text' && /^\s*$/.test(event.raw))) { - return; - } - if ((event.type !== 'comment' && event.long === false) || - /^DOCTYPE\s+/i.test(event.content) === false) { - reporter.error('Doctype must be declared first.', event.line, event.col, this, event.raw); - } - parser.removeListener('all', allEvent); - }; - parser.addListener('all', allEvent); - }, - }; - - return doctypeFirst; - } - - var doctypeHtml5 = {}; - - var hasRequiredDoctypeHtml5; - - function requireDoctypeHtml5 () { - if (hasRequiredDoctypeHtml5) return doctypeHtml5; - hasRequiredDoctypeHtml5 = 1; - Object.defineProperty(doctypeHtml5, "__esModule", { value: true }); - doctypeHtml5.default = { - id: 'doctype-html5', - description: 'Invalid doctype. Use: ""', - init(parser, reporter) { - const onComment = (event) => { - if (event.long === false && - event.content.toLowerCase() !== 'doctype html') { - reporter.warn('Invalid doctype. Use: ""', event.line, event.col, this, event.raw); - } - }; - const onTagStart = () => { - parser.removeListener('comment', onComment); - parser.removeListener('tagstart', onTagStart); - }; - parser.addListener('all', onComment); - parser.addListener('tagstart', onTagStart); - }, - }; - - return doctypeHtml5; - } - - var emptyTagNotSelfClosed = {}; - - var hasRequiredEmptyTagNotSelfClosed; - - function requireEmptyTagNotSelfClosed () { - if (hasRequiredEmptyTagNotSelfClosed) return emptyTagNotSelfClosed; - hasRequiredEmptyTagNotSelfClosed = 1; - Object.defineProperty(emptyTagNotSelfClosed, "__esModule", { value: true }); - emptyTagNotSelfClosed.default = { - id: 'empty-tag-not-self-closed', - description: 'Empty tags must not use self closed syntax.', - init(parser, reporter) { - const mapEmptyTags = parser.makeMap('area,base,basefont,bgsound,br,col,frame,hr,img,input,isindex,link,meta,param,embed,track,command,source,keygen,wbr'); - parser.addListener('tagstart', (event) => { - const tagName = event.tagName.toLowerCase(); - if (mapEmptyTags[tagName] !== undefined) { - if (event.close) { - reporter.error(`The empty tag : [ ${tagName} ] must not use self closed syntax.`, event.line, event.col, this, event.raw); - } - } - }); - }, - }; - - return emptyTagNotSelfClosed; - } - - var h1Require = {}; - - var hasRequiredH1Require; - - function requireH1Require () { - if (hasRequiredH1Require) return h1Require; - hasRequiredH1Require = 1; - Object.defineProperty(h1Require, "__esModule", { value: true }); - h1Require.default = { - id: 'h1-require', - description: '

must be present in tag and not be empty.', - init(parser, reporter) { - let bodyDepth = 0; - let hasH1InBody = false; - let bodyTagEvent = null; - let currentH1Event = null; - let h1IsEmpty = false; - const onTagStart = (event) => { - const tagName = event.tagName.toLowerCase(); - if (tagName === 'body') { - bodyDepth++; - if (bodyDepth === 1) { - hasH1InBody = false; - bodyTagEvent = event; - } - } - else if (tagName === 'h1' && bodyDepth > 0) { - hasH1InBody = true; - currentH1Event = event; - h1IsEmpty = true; - } - }; - const onText = (event) => { - if (currentH1Event && h1IsEmpty) { - if (event.raw && !/^\s*$/.test(event.raw)) { - h1IsEmpty = false; - } - } - }; - const onTagEnd = (event) => { - const tagName = event.tagName.toLowerCase(); - if (tagName === 'h1' && currentH1Event) { - if (h1IsEmpty) { - reporter.warn('

tag must not be empty.', currentH1Event.line, currentH1Event.col, this, currentH1Event.raw); - } - currentH1Event = null; - } - else if (tagName === 'body') { - if (bodyDepth === 1 && !hasH1InBody && bodyTagEvent) { - reporter.warn('

must be present in tag.', bodyTagEvent.line, bodyTagEvent.col, this, bodyTagEvent.raw); - } - bodyDepth--; - if (bodyDepth < 0) - bodyDepth = 0; - } - }; - parser.addListener('tagstart', onTagStart); - parser.addListener('tagend', onTagEnd); - parser.addListener('text', onText); - parser.addListener('end', () => { - if (bodyDepth > 0 && !hasH1InBody && bodyTagEvent) { - reporter.warn('

must be present in tag.', bodyTagEvent.line, bodyTagEvent.col, this, bodyTagEvent.raw); - } - }); - }, - }; - - return h1Require; - } - - var headScriptDisabled = {}; - - var hasRequiredHeadScriptDisabled; - - function requireHeadScriptDisabled () { - if (hasRequiredHeadScriptDisabled) return headScriptDisabled; - hasRequiredHeadScriptDisabled = 1; - Object.defineProperty(headScriptDisabled, "__esModule", { value: true }); - headScriptDisabled.default = { - id: 'head-script-disabled', - description: 'The