Update MD052/reference-links-images to add a shortcut_syntax parameter for opting into shortcut scanning (fixes #915).

This commit is contained in:
David Anson 2023-09-04 16:40:48 -07:00
parent a736588958
commit c118c1160a
13 changed files with 433 additions and 29 deletions

View file

@ -6315,7 +6315,11 @@ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructur
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
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;
@ -6326,12 +6330,16 @@ module.exports = {
"description": "Reference links and images should use a label that is defined",
"tags": ["images", "links"],
"function": function MD052(params, onError) {
var lines = params.lines;
var config = params.config,
lines = params.lines;
var shortcutSyntax = config.shortcut_syntax || false;
var _referenceLinkImageDa = referenceLinkImageData(),
definitions = _referenceLinkImageDa.definitions,
references = _referenceLinkImageDa.references,
definitions = _referenceLinkImageDa.definitions;
shortcuts = _referenceLinkImageDa.shortcuts;
var entries = shortcutSyntax ? [].concat(_toConsumableArray(references.entries()), _toConsumableArray(shortcuts.entries())) : references.entries();
// Look for links/images that use an undefined link reference
var _iterator = _createForOfIteratorHelper(references.entries()),
var _iterator = _createForOfIteratorHelper(entries),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {

View file

@ -18,10 +18,13 @@ Shortcut: ![image]
[image]: https://example.com/image
```
A link or image renders correctly when a corresponding label is defined, but
the text displays with brackets if the label is not present. This rule warns
of undefined labels for "full" and "collapsed" reference syntax.
A link or image renders correctly when the corresponding label is defined, but
displays as text with brackets when the label is not present. By default, this
rule warns of undefined labels for "full" and "collapsed" reference syntax but
not for "shortcut" syntax because it is ambiguous.
> "Shortcut" syntax is ambiguous and a missing label will not generate an
error. For example, `[shortcut]` could be a shortcut link or the text
"shortcut" in brackets.
The text `[example]` could be a shortcut link or the text "example" in brackets,
so "shortcut" syntax is ignored by default. To include "shortcut" syntax, set
the `include_shortcut` parameter to `true`. Note that doing so produces warnings
for *all* text in the document that *could* be a shortcut. If bracketed text is
intentional, brackets can be escaped with the `\` character: `\[example\]`.

View file

@ -2216,6 +2216,10 @@ Tags: `images`, `links`
Aliases: `reference-links-images`
Parameters:
- `shortcut_syntax`: Include shortcut syntax (`boolean`, default `false`)
Links and images in Markdown can provide the link destination or image source
at the time of use or can define it elsewhere and use a label for reference.
The reference format is convenient for keeping paragraph text clutter-free
@ -2236,13 +2240,16 @@ Shortcut: ![image]
[image]: https://example.com/image
```
A link or image renders correctly when a corresponding label is defined, but
the text displays with brackets if the label is not present. This rule warns
of undefined labels for "full" and "collapsed" reference syntax.
A link or image renders correctly when the corresponding label is defined, but
displays as text with brackets when the label is not present. By default, this
rule warns of undefined labels for "full" and "collapsed" reference syntax but
not for "shortcut" syntax because it is ambiguous.
> "Shortcut" syntax is ambiguous and a missing label will not generate an
error. For example, `[shortcut]` could be a shortcut link or the text
"shortcut" in brackets.
The text `[example]` could be a shortcut link or the text "example" in brackets,
so "shortcut" syntax is ignored by default. To include "shortcut" syntax, set
the `include_shortcut` parameter to `true`. Note that doing so produces warnings
for *all* text in the document that *could* be a shortcut. If bracketed text is
intentional, brackets can be escaped with the `\` character: `\[example\]`.
<a name="md053"></a>

View file

@ -4,6 +4,10 @@ Tags: `images`, `links`
Aliases: `reference-links-images`
Parameters:
- `shortcut_syntax`: Include shortcut syntax (`boolean`, default `false`)
Links and images in Markdown can provide the link destination or image source
at the time of use or can define it elsewhere and use a label for reference.
The reference format is convenient for keeping paragraph text clutter-free
@ -24,10 +28,13 @@ Shortcut: ![image]
[image]: https://example.com/image
```
A link or image renders correctly when a corresponding label is defined, but
the text displays with brackets if the label is not present. This rule warns
of undefined labels for "full" and "collapsed" reference syntax.
A link or image renders correctly when the corresponding label is defined, but
displays as text with brackets when the label is not present. By default, this
rule warns of undefined labels for "full" and "collapsed" reference syntax but
not for "shortcut" syntax because it is ambiguous.
> "Shortcut" syntax is ambiguous and a missing label will not generate an
error. For example, `[shortcut]` could be a shortcut link or the text
"shortcut" in brackets.
The text `[example]` could be a shortcut link or the text "example" in brackets,
so "shortcut" syntax is ignored by default. To include "shortcut" syntax, set
the `include_shortcut` parameter to `true`. Note that doing so produces warnings
for *all* text in the document that *could* be a shortcut. If bracketed text is
intentional, brackets can be escaped with the `\` character: `\[example\]`.

View file

@ -11,10 +11,14 @@ module.exports = {
"Reference links and images should use a label that is defined",
"tags": [ "images", "links" ],
"function": function MD052(params, onError) {
const { lines } = params;
const { references, definitions } = referenceLinkImageData();
const { config, lines } = params;
const shortcutSyntax = config.shortcut_syntax || false;
const { definitions, references, shortcuts } = referenceLinkImageData();
const entries = shortcutSyntax ?
[ ...references.entries(), ...shortcuts.entries() ] :
references.entries();
// Look for links/images that use an undefined link reference
for (const reference of references.entries()) {
for (const reference of entries) {
const [ label, datas ] = reference;
if (!definitions.has(label)) {
for (const data of datas) {

View file

@ -279,7 +279,10 @@
"MD051": true,
// MD052/reference-links-images - Reference links and images should use a label that is defined
"MD052": true,
"MD052": {
// Include shortcut syntax
"shortcut_syntax": false
},
// MD053/link-image-reference-definitions - Link and image reference definitions should be needed
"MD053": {

View file

@ -252,7 +252,9 @@ MD050:
MD051: true
# MD052/reference-links-images - Reference links and images should use a label that is defined
MD052: true
MD052:
# Include shortcut syntax
shortcut_syntax: false
# MD053/link-image-reference-definitions - Link and image reference definitions should be needed
MD053:

View file

@ -497,6 +497,15 @@ for (const rule of rules) {
}
};
break;
case "MD052":
scheme.properties = {
"shortcut_syntax": {
"description": "Include shortcut syntax",
"type": "boolean",
"default": false
}
};
break;
case "MD053":
scheme.properties = {
"ignored_definitions": {

View file

@ -937,8 +937,19 @@
},
"MD052": {
"description": "MD052/reference-links-images - Reference links and images should use a label that is defined",
"type": [
"boolean",
"object"
],
"default": true,
"properties": {
"shortcut_syntax": {
"description": "Include shortcut syntax",
"type": "boolean",
"default": true
"default": false
}
},
"additionalProperties": false
},
"reference-links-images": {
"$ref": "#/properties/MD052"

View file

@ -912,7 +912,7 @@ test("readme", async(t) => {
});
test("validateJsonUsingConfigSchemaStrict", (t) => {
t.plan(160);
t.plan(161);
const configRe =
/^[\s\S]*<!-- markdownlint-configure-file ([\s\S]*) -->[\s\S]*$/;
const ignoreFiles = new Set([

View file

@ -0,0 +1,112 @@
# Reference Links and Images (Shortcuts)
## Shortcut Handling
Validates the shortcut: [shortcut]
[shortcut]: https://example.com/shortcut
Missing reference: [missing] {MD052}
## Valid Links
Full reference link: [text][label]
Collapsed reference link: [label][]
Shortcut reference link: [label]
Same line: [text][label] [label][] [label]
Mixed case: [TEXT][LABEL] [LABEL][] [LABEL]
With nested brackets: [t\[ex\]t][label]
Shortcut inline code span: [`code`]
Shortcut ending in colon: [colon]:
## Invalid Links
Missing: [missing] {MD052}
> Missing in blockquote: [missing] {MD052}
## Non-Links
Code span: `[code]`
Escaped left: \[escaped]
Escaped right: [escaped\]
Escaped both: \[escaped\]
Unmatched [ in text
Unmatched ] in text
## Valid Images
Full style: ![text][image0]
Collapsed style: ![image1][]
Shortcut style: ![image2]
Image in link: [![text][image3]](link) [![image4][]](link) [![image5]](link)
Image in shortcut link: [![text][image6]][unique6] [![image7][]][unique7] [![image8]][unique8]
Wrapped in brackets: \[![text][unique9]\]
Embedded \[in ![text][unique10] brackets\]
## Invalid Images
Missing: ![missing] {MD052}
> Missing in blockquote: ![missing] {MD052}
## Non-Images
Escaped left: !\[escaped]
Escaped right: ![escaped\]
Escaped both: !\[escaped\]
## Valid Footnotes
Footnote[^1]
## Invalid Footnotes
Missing[^2] {MD052}
## Valid Labels
[label]: https://example.com/label
[image0]: https://example.com/image0
[image1]: https://example.com/image1
[image2]: https://example.com/image2
[image3]: https://example.com/image3
[image4]: https://example.com/image4
[image5]: https://example.com/image5
[image6]: https://example.com/image6
[image7]: https://example.com/image7
[image8]: https://example.com/image8
[`code`]: https://example.com/code
[colon]: https://example.com/colon
[unique6]: https://example.com/unique6
[unique7]: https://example.com/unique7
[unique8]: https://example.com/unique8
[unique9]: https://example.com/unique9
[unique10]: https://example.com/unique10
[^1]: https://example.com/footnote {MD034}
<!-- markdownlint-configure-file {
"reference-links-images": {
"shortcut_syntax": true
}
} -->

View file

@ -38664,6 +38664,244 @@ Generated by [AVA](https://avajs.dev).
`,
}
## reference-links-and-images-shortcuts.md
> Snapshot 1
{
errors: [
{
errorContext: 'https://example.com/footnote',
errorDetail: null,
errorRange: [
7,
28,
],
fixInfo: {
deleteCount: 28,
editColumn: 7,
insertText: '<https://example.com/footnote>',
},
lineNumber: 106,
ruleDescription: 'Bare URL used',
ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/md034.md',
ruleNames: [
'MD034',
'no-bare-urls',
],
},
{
errorContext: '[missing]',
errorDetail: 'Missing link or image reference definition: "missing"',
errorRange: [
20,
9,
],
fixInfo: null,
lineNumber: 9,
ruleDescription: 'Reference links and images should use a label that is defined',
ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/md052.md',
ruleNames: [
'MD052',
'reference-links-images',
],
},
{
errorContext: '[missing]',
errorDetail: 'Missing link or image reference definition: "missing"',
errorRange: [
10,
9,
],
fixInfo: null,
lineNumber: 31,
ruleDescription: 'Reference links and images should use a label that is defined',
ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/md052.md',
ruleNames: [
'MD052',
'reference-links-images',
],
},
{
errorContext: '[missing]',
errorDetail: 'Missing link or image reference definition: "missing"',
errorRange: [
26,
9,
],
fixInfo: null,
lineNumber: 33,
ruleDescription: 'Reference links and images should use a label that is defined',
ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/md052.md',
ruleNames: [
'MD052',
'reference-links-images',
],
},
{
errorContext: '![missing]',
errorDetail: 'Missing link or image reference definition: "missing"',
errorRange: [
10,
10,
],
fixInfo: null,
lineNumber: 67,
ruleDescription: 'Reference links and images should use a label that is defined',
ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/md052.md',
ruleNames: [
'MD052',
'reference-links-images',
],
},
{
errorContext: '![missing]',
errorDetail: 'Missing link or image reference definition: "missing"',
errorRange: [
26,
10,
],
fixInfo: null,
lineNumber: 69,
ruleDescription: 'Reference links and images should use a label that is defined',
ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/md052.md',
ruleNames: [
'MD052',
'reference-links-images',
],
},
{
errorContext: '[^2]',
errorDetail: 'Missing link or image reference definition: "^2"',
errorRange: [
8,
4,
],
fixInfo: null,
lineNumber: 85,
ruleDescription: 'Reference links and images should use a label that is defined',
ruleInformation: 'https://github.com/DavidAnson/markdownlint/blob/v0.0.0/doc/md052.md',
ruleNames: [
'MD052',
'reference-links-images',
],
},
],
fixed: `# Reference Links and Images (Shortcuts)␊
## Shortcut Handling␊
Validates the shortcut: [shortcut]␊
[shortcut]: https://example.com/shortcut␊
Missing reference: [missing] {MD052}␊
## Valid Links␊
Full reference link: [text][label]␊
Collapsed reference link: [label][]␊
Shortcut reference link: [label]␊
Same line: [text][label] [label][] [label]␊
Mixed case: [TEXT][LABEL] [LABEL][] [LABEL]␊
With nested brackets: [t\\[ex\\]t][label]␊
Shortcut inline code span: [\`code\`]␊
Shortcut ending in colon: [colon]:␊
## Invalid Links␊
Missing: [missing] {MD052}␊
> Missing in blockquote: [missing] {MD052}␊
## Non-Links␊
Code span: \`[code]\`␊
Escaped left: \\[escaped]␊
Escaped right: [escaped\\]␊
Escaped both: \\[escaped\\]␊
Unmatched [ in text␊
Unmatched ] in text␊
## Valid Images␊
Full style: ![text][image0]␊
Collapsed style: ![image1][]␊
Shortcut style: ![image2]␊
Image in link: [![text][image3]](link) [![image4][]](link) [![image5]](link)␊
Image in shortcut link: [![text][image6]][unique6] [![image7][]][unique7] [![image8]][unique8]␊
Wrapped in brackets: \\[![text][unique9]\\]␊
Embedded \\[in ![text][unique10] brackets\\]␊
## Invalid Images␊
Missing: ![missing] {MD052}␊
> Missing in blockquote: ![missing] {MD052}␊
## Non-Images␊
Escaped left: !\\[escaped]␊
Escaped right: ![escaped\\]␊
Escaped both: !\\[escaped\\]␊
## Valid Footnotes␊
Footnote[^1]␊
## Invalid Footnotes␊
Missing[^2] {MD052}␊
## Valid Labels␊
[label]: https://example.com/label␊
[image0]: https://example.com/image0␊
[image1]: https://example.com/image1␊
[image2]: https://example.com/image2␊
[image3]: https://example.com/image3␊
[image4]: https://example.com/image4␊
[image5]: https://example.com/image5␊
[image6]: https://example.com/image6␊
[image7]: https://example.com/image7␊
[image8]: https://example.com/image8␊
[\`code\`]: https://example.com/code␊
[colon]: https://example.com/colon␊
[unique6]: https://example.com/unique6␊
[unique7]: https://example.com/unique7␊
[unique8]: https://example.com/unique8␊
[unique9]: https://example.com/unique9␊
[unique10]: https://example.com/unique10␊
[^1]: <https://example.com/footnote> {MD034}␊
<!-- markdownlint-configure-file {␊
"reference-links-images": {␊
"shortcut_syntax": true␊
}␊
} -->␊
`,
}
## reference-links-and-images.md
> Snapshot 1