diff --git a/demo/markdownlint-browser.js b/demo/markdownlint-browser.js index 24e8b625a..a98df79cb 100644 --- a/demo/markdownlint-browser.js +++ b/demo/markdownlint-browser.js @@ -168,6 +168,16 @@ function cloneIfUrl(url) { } module.exports.cloneIfUrl = cloneIfUrl; +/** + * Gets a Regular Expression for matching the specified HTML attribute. + * + * @param {string} name HTML attribute name. + * @returns {RegExp} Regular Expression for matching. + */ +module.exports.getHtmlAttributeRe = function getHtmlAttributeRe(name) { + return new RegExp("\\s".concat(name, "\\s*=\\s*['\"]?([^'\"\\s>]*)"), "iu"); +}; + /** * Returns true iff the input line is blank (contains nothing, whitespace, or * comments (unclosed start/end comments allowed)). @@ -5992,13 +6002,12 @@ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o = function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } var _require = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"), addError = _require.addError, + getHtmlAttributeRe = _require.getHtmlAttributeRe, nextLinesRe = _require.nextLinesRe; var _require2 = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs"), filterByTypes = _require2.filterByTypes, getHtmlTagInfo = _require2.getHtmlTagInfo; - -// Regular expression for identifying alt attribute -var altRe = /\salt=/i; +var altRe = getHtmlAttributeRe("alt"); module.exports = { "names": ["MD045", "no-alt-text"], "description": "Images should have alternate text (alt text)", @@ -6038,7 +6047,7 @@ module.exports = { startLine = htmlText.startLine, text = htmlText.text; var htmlTagInfo = getHtmlTagInfo(htmlText); - if (htmlTagInfo && htmlTagInfo.name.toLowerCase() === "img" && !altRe.test(text)) { + if (htmlTagInfo && !htmlTagInfo.close && htmlTagInfo.name.toLowerCase() === "img" && !altRe.test(text)) { var _range = [startColumn, text.replace(nextLinesRe, "").length]; addError(onError, startLine, undefined, undefined, _range); } @@ -6292,15 +6301,16 @@ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o = function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } var _require = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"), addError = _require.addError, - addErrorDetailIf = _require.addErrorDetailIf; + addErrorDetailIf = _require.addErrorDetailIf, + getHtmlAttributeRe = _require.getHtmlAttributeRe; var _require2 = __webpack_require__(/*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs"), filterByPredicate = _require2.filterByPredicate, filterByTypes = _require2.filterByTypes, getHtmlTagInfo = _require2.getHtmlTagInfo; // Regular expression for identifying HTML anchor names -var idRe = /[\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]id[\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]*=[\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]*["']?((?:(?![\t-\r "'>\xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uD800-\uDFFF\uFEFF])[\s\S]|[\uD800-\uDBFF][\uDC00-\uDFFF])+)/i; -var nameRe = /[\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]name[\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]*=[\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]*["']?((?:(?![\t-\r "'>\xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uD800-\uDFFF\uFEFF])[\s\S]|[\uD800-\uDBFF][\uDC00-\uDFFF])+)/i; +var idRe = getHtmlAttributeRe("id"); +var nameRe = getHtmlAttributeRe("name"); var anchorRe = /\{(#[0-9a-z]+(?:[\x2D_][0-9a-z]+)*)\}/g; // Sets for filtering heading tokens during conversion @@ -6393,7 +6403,7 @@ module.exports = { var htmlTagInfo = getHtmlTagInfo(token); if (htmlTagInfo && !htmlTagInfo.close) { var anchorMatch = idRe.exec(token.text) || htmlTagInfo.name.toLowerCase() === "a" && nameRe.exec(token.text); - if (anchorMatch) { + if (anchorMatch && anchorMatch.length > 0) { fragments.set("#".concat(anchorMatch[1]), 0); } } diff --git a/helpers/helpers.js b/helpers/helpers.js index 2ef5a2974..59230fe3c 100644 --- a/helpers/helpers.js +++ b/helpers/helpers.js @@ -126,6 +126,16 @@ function cloneIfUrl(url) { } module.exports.cloneIfUrl = cloneIfUrl; +/** + * Gets a Regular Expression for matching the specified HTML attribute. + * + * @param {string} name HTML attribute name. + * @returns {RegExp} Regular Expression for matching. + */ +module.exports.getHtmlAttributeRe = function getHtmlAttributeRe(name) { + return new RegExp(`\\s${name}\\s*=\\s*['"]?([^'"\\s>]*)`, "iu"); +}; + /** * Returns true iff the input line is blank (contains nothing, whitespace, or * comments (unclosed start/end comments allowed)). diff --git a/lib/md045.js b/lib/md045.js index e5ab4a7ed..d2b0a3846 100644 --- a/lib/md045.js +++ b/lib/md045.js @@ -2,11 +2,10 @@ "use strict"; -const { addError, nextLinesRe } = require("../helpers"); +const { addError, getHtmlAttributeRe, nextLinesRe } = require("../helpers"); const { filterByTypes, getHtmlTagInfo } = require("../helpers/micromark.cjs"); -// Regular expression for identifying alt attribute -const altRe = /\salt=/i; +const altRe = getHtmlAttributeRe("alt"); module.exports = { "names": [ "MD045", "no-alt-text" ], @@ -40,6 +39,7 @@ module.exports = { const htmlTagInfo = getHtmlTagInfo(htmlText); if ( htmlTagInfo && + !htmlTagInfo.close && (htmlTagInfo.name.toLowerCase() === "img") && !altRe.test(text) ) { diff --git a/lib/md051.js b/lib/md051.js index 98606bdad..bc0ff99a9 100644 --- a/lib/md051.js +++ b/lib/md051.js @@ -2,13 +2,14 @@ "use strict"; -const { addError, addErrorDetailIf } = require("../helpers"); +const { addError, addErrorDetailIf, getHtmlAttributeRe } = + require("../helpers"); const { filterByPredicate, filterByTypes, getHtmlTagInfo } = require("../helpers/micromark.cjs"); // Regular expression for identifying HTML anchor names -const idRe = /\sid\s*=\s*['"]?([^'"\s>]+)/iu; -const nameRe = /\sname\s*=\s*['"]?([^'"\s>]+)/iu; +const idRe = getHtmlAttributeRe("id"); +const nameRe = getHtmlAttributeRe("name"); const anchorRe = /\{(#[a-z\d]+(?:[-_][a-z\d]+)*)\}/gu; // Sets for filtering heading tokens during conversion @@ -101,7 +102,7 @@ module.exports = { if (htmlTagInfo && !htmlTagInfo.close) { const anchorMatch = idRe.exec(token.text) || (htmlTagInfo.name.toLowerCase() === "a" && nameRe.exec(token.text)); - if (anchorMatch) { + if (anchorMatch && anchorMatch.length > 0) { fragments.set(`#${anchorMatch[1]}`, 0); } }