Update re-implementation of MD044/proper-names to exclude link destinations and references.

This commit is contained in:
David Anson 2021-06-13 13:07:03 -07:00
parent 4db40256d9
commit 72543a82e7
4 changed files with 99 additions and 16 deletions

View file

@ -51,7 +51,10 @@ module.exports.orderedListItemMarkerRe = /^[\s>]*0*(\d+)[.)]/;
// Regular expression for all instances of emphasis markers // Regular expression for all instances of emphasis markers
var emphasisMarkersRe = /[_*]/g; var emphasisMarkersRe = /[_*]/g;
// Regular expression for inline links and shortcut reference links // Regular expression for inline links and shortcut reference links
var linkRe = /\[(?:[^[\]]|\[[^\]]*\])*\](?:\(\S*\))?/g; var linkRe = /(\[(?:[^[\]]|\[[^\]]*\])*\])(\(\S*\)|\[\S*\])?/g;
module.exports.linkRe = linkRe;
// Regular expression for link reference definition lines
module.exports.linkReferenceRe = /^ {0,3}\[[^\]]+]:\s.*$/;
// readFile options for reading with the UTF-8 encoding // readFile options for reading with the UTF-8 encoding
module.exports.utf8Encoding = "utf8"; module.exports.utf8Encoding = "utf8";
// All punctuation characters (normal and full-width) // All punctuation characters (normal and full-width)
@ -3745,7 +3748,7 @@ module.exports = {
"use strict"; "use strict";
// @ts-check // @ts-check
var _a = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"), addErrorDetailIf = _a.addErrorDetailIf, bareUrlRe = _a.bareUrlRe, escapeForRegExp = _a.escapeForRegExp, forEachLine = _a.forEachLine, newLineRe = _a.newLineRe, forEachInlineCodeSpan = _a.forEachInlineCodeSpan; var _a = __webpack_require__(/*! ../helpers */ "../helpers/helpers.js"), addErrorDetailIf = _a.addErrorDetailIf, bareUrlRe = _a.bareUrlRe, escapeForRegExp = _a.escapeForRegExp, forEachLine = _a.forEachLine, linkRe = _a.linkRe, linkReferenceRe = _a.linkReferenceRe, newLineRe = _a.newLineRe, forEachInlineCodeSpan = _a.forEachInlineCodeSpan;
var lineMetadata = __webpack_require__(/*! ./cache */ "../lib/cache.js").lineMetadata; var lineMetadata = __webpack_require__(/*! ./cache */ "../lib/cache.js").lineMetadata;
module.exports = { module.exports = {
"names": ["MD044", "proper-names"], "names": ["MD044", "proper-names"],
@ -3758,6 +3761,23 @@ module.exports = {
var codeBlocks = params.config.code_blocks; var codeBlocks = params.config.code_blocks;
var includeCodeBlocks = (codeBlocks === undefined) ? true : !!codeBlocks; var includeCodeBlocks = (codeBlocks === undefined) ? true : !!codeBlocks;
var exclusions = []; var exclusions = [];
forEachLine(lineMetadata(), function (line, lineIndex) {
if (linkReferenceRe.test(line)) {
exclusions.push([lineIndex, 0, line.length]);
}
else {
var match = null;
while ((match = bareUrlRe.exec(line)) !== null) {
exclusions.push([lineIndex, match.index, match[0].length]);
}
while ((match = linkRe.exec(line)) !== null) {
var text = match[1], destination = match[2];
if (destination) {
exclusions.push([lineIndex, match.index + text.length, destination.length]);
}
}
}
});
if (!includeCodeBlocks) { if (!includeCodeBlocks) {
forEachInlineCodeSpan(params.lines.join("\n"), function (code, lineIndex, columnIndex) { forEachInlineCodeSpan(params.lines.join("\n"), function (code, lineIndex, columnIndex) {
var codeLines = code.split(newLineRe); var codeLines = code.split(newLineRe);
@ -3770,19 +3790,18 @@ module.exports = {
} }
var _loop_1 = function (name_1) { var _loop_1 = function (name_1) {
var escapedName = escapeForRegExp(name_1); var escapedName = escapeForRegExp(name_1);
var startNamePattern = /^\W/.test(name_1) ? "" : "[^\\s([\"]*\\b_*"; var startNamePattern = /^\W/.test(name_1) ? "" : "\\b_*";
var endNamePattern = /\W$/.test(name_1) ? "" : "_*\\b[^\\s)\\]\"]*"; var endNamePattern = /\W$/.test(name_1) ? "" : "_*\\b";
var namePattern = "(" + startNamePattern + ")(" + escapedName + ")" + endNamePattern; var namePattern = "(" + startNamePattern + ")(" + escapedName + ")" + endNamePattern;
var nameRe = new RegExp(namePattern, "gi"); var nameRe = new RegExp(namePattern, "gi");
forEachLine(lineMetadata(), function (line, lineIndex, inCode, onFence) { forEachLine(lineMetadata(), function (line, lineIndex, inCode, onFence) {
if (includeCodeBlocks || (!inCode && !onFence)) { if (includeCodeBlocks || (!inCode && !onFence)) {
var match = null; var match = null;
var _loop_2 = function () { var _loop_2 = function () {
var fullMatch = match[0], leftMatch = match[1], nameMatch = match[2]; var leftMatch = match[1], nameMatch = match[2];
var index = match.index + leftMatch.length; var index = match.index + leftMatch.length;
var length_1 = nameMatch.length; var length_1 = nameMatch.length;
if ((fullMatch.search(bareUrlRe) === -1) && if (exclusions.every(function (span) { return ((lineIndex !== span[0]) ||
exclusions.every(function (span) { return ((lineIndex !== span[0]) ||
(index + length_1 < span[1]) || (index + length_1 < span[1]) ||
(index > span[1] + span[2])); })) { (index > span[1] + span[2])); })) {
addErrorDetailIf(onError, lineIndex + 1, name_1, nameMatch, null, null, [index + 1, length_1], { addErrorDetailIf(onError, lineIndex + 1, name_1, nameMatch, null, null, [index + 1, length_1], {

View file

@ -29,7 +29,11 @@ module.exports.orderedListItemMarkerRe = /^[\s>]*0*(\d+)[.)]/;
const emphasisMarkersRe = /[_*]/g; const emphasisMarkersRe = /[_*]/g;
// Regular expression for inline links and shortcut reference links // Regular expression for inline links and shortcut reference links
const linkRe = /\[(?:[^[\]]|\[[^\]]*\])*\](?:\(\S*\))?/g; const linkRe = /(\[(?:[^[\]]|\[[^\]]*\])*\])(\(\S*\)|\[\S*\])?/g;
module.exports.linkRe = linkRe;
// Regular expression for link reference definition lines
module.exports.linkReferenceRe = /^ {0,3}\[[^\]]+]:\s.*$/;
// readFile options for reading with the UTF-8 encoding // readFile options for reading with the UTF-8 encoding
module.exports.utf8Encoding = "utf8"; module.exports.utf8Encoding = "utf8";

View file

@ -2,8 +2,8 @@
"use strict"; "use strict";
const { addErrorDetailIf, bareUrlRe, escapeForRegExp, forEachLine, newLineRe, const { addErrorDetailIf, bareUrlRe, escapeForRegExp, forEachLine, linkRe,
forEachInlineCodeSpan } = require("../helpers"); linkReferenceRe, newLineRe, forEachInlineCodeSpan } = require("../helpers");
const { lineMetadata } = require("./cache"); const { lineMetadata } = require("./cache");
module.exports = { module.exports = {
@ -17,6 +17,24 @@ module.exports = {
const codeBlocks = params.config.code_blocks; const codeBlocks = params.config.code_blocks;
const includeCodeBlocks = (codeBlocks === undefined) ? true : !!codeBlocks; const includeCodeBlocks = (codeBlocks === undefined) ? true : !!codeBlocks;
const exclusions = []; const exclusions = [];
forEachLine(lineMetadata(), (line, lineIndex) => {
if (linkReferenceRe.test(line)) {
exclusions.push([ lineIndex, 0, line.length ]);
} else {
let match = null;
while ((match = bareUrlRe.exec(line)) !== null) {
exclusions.push([ lineIndex, match.index, match[0].length ]);
}
while ((match = linkRe.exec(line)) !== null) {
const [ , text, destination ] = match;
if (destination) {
exclusions.push(
[ lineIndex, match.index + text.length, destination.length ]
);
}
}
}
});
if (!includeCodeBlocks) { if (!includeCodeBlocks) {
forEachInlineCodeSpan( forEachInlineCodeSpan(
params.lines.join("\n"), params.lines.join("\n"),
@ -34,8 +52,8 @@ module.exports = {
} }
for (const name of names) { for (const name of names) {
const escapedName = escapeForRegExp(name); const escapedName = escapeForRegExp(name);
const startNamePattern = /^\W/.test(name) ? "" : "[^\\s([\"]*\\b_*"; const startNamePattern = /^\W/.test(name) ? "" : "\\b_*";
const endNamePattern = /\W$/.test(name) ? "" : "_*\\b[^\\s)\\]\"]*"; const endNamePattern = /\W$/.test(name) ? "" : "_*\\b";
const namePattern = const namePattern =
`(${startNamePattern})(${escapedName})${endNamePattern}`; `(${startNamePattern})(${escapedName})${endNamePattern}`;
const nameRe = new RegExp(namePattern, "gi"); const nameRe = new RegExp(namePattern, "gi");
@ -43,11 +61,10 @@ module.exports = {
if (includeCodeBlocks || (!inCode && !onFence)) { if (includeCodeBlocks || (!inCode && !onFence)) {
let match = null; let match = null;
while ((match = nameRe.exec(line)) !== null) { while ((match = nameRe.exec(line)) !== null) {
const [ fullMatch, leftMatch, nameMatch ] = match; const [ , leftMatch, nameMatch ] = match;
const index = match.index + leftMatch.length; const index = match.index + leftMatch.length;
const length = nameMatch.length; const length = nameMatch.length;
if ( if (
(fullMatch.search(bareUrlRe) === -1) &&
exclusions.every((span) => ( exclusions.every((span) => (
(lineIndex !== span[0]) || (lineIndex !== span[0]) ||
(index + length < span[1]) || (index + length < span[1]) ||

View file

@ -0,0 +1,43 @@
# Proper names in links
javascript {MD044}
Learn about JavaScript here: https://example.com/javascript/about
Learn about JavaScript here: <https://example.com/javascript/about>
Learn about [JavaScript](https://example.com/javascript/about).
Learn about [JavaScript](wiki/javascript/about).
Learn about [JavaScript](wiki/javascript).
Learn about [JavaScript](javascript/about).
Learn about [JavaScript](javascript).
Learn about [JavaScript][js].
Learn about [JavaScript][example-js].
Learn about [JavaScript][javascript].
Learn about [javascript][js]. {MD044}
Learn about [javascript][example-js]. {MD044}
Learn about [javascript]. {MD044}
[js]: https://example.com/javascript/about
[example-js]: javascript
[javascript]: https://example.com/js
[javascript]: https://example.com/js {MD044}
<!-- markdownlint-configure-file {
"proper-names": {
"names": [
"JavaScript"
]
},
"no-bare-urls": false
} -->