markdownlint 0.27.0 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +378 -0
- package/CONTRIBUTING.md +4 -3
- package/LICENSE +1 -1
- package/README.md +1 -123
- package/demo/markdownlint-browser.js +4944 -3580
- package/doc/CustomRules.md +1 -4
- package/doc/Rules.md +22 -16
- package/doc/md034.md +21 -15
- package/doc/md051.md +1 -1
- package/helpers/LICENSE +1 -1
- package/helpers/helpers.js +106 -248
- package/helpers/micromark.cjs +209 -0
- package/helpers/package.json +4 -1
- package/lib/constants.js +1 -1
- package/lib/markdownlint.d.ts +5 -5
- package/lib/markdownlint.js +39 -17
- package/lib/md002.js +1 -1
- package/lib/md027.js +1 -1
- package/lib/md028.js +1 -1
- package/lib/md033.js +47 -40
- package/lib/md034.js +54 -72
- package/lib/md035.js +9 -11
- package/lib/md036.js +1 -1
- package/lib/md038.js +80 -55
- package/lib/md041.js +1 -1
- package/lib/md044.js +58 -44
- package/lib/md046.js +1 -1
- package/lib/md048.js +3 -1
- package/package.json +29 -24
- package/schema/.markdownlint.jsonc +1 -1
- package/schema/.markdownlint.yaml +3 -4
package/doc/CustomRules.md
CHANGED
|
@@ -34,7 +34,7 @@ module.exports = {
|
|
|
34
34
|
"information": new URL("https://example.com/rules/any-blockquote"),
|
|
35
35
|
"tags": [ "test" ],
|
|
36
36
|
"function": function rule(params, onError) {
|
|
37
|
-
params.tokens.filter(function filterToken(token) {
|
|
37
|
+
params.parsers.markdownit.tokens.filter(function filterToken(token) {
|
|
38
38
|
return token.type === "blockquote_open";
|
|
39
39
|
}).forEach(function forToken(blockquote) {
|
|
40
40
|
var lines = blockquote.map[1] - blockquote.map[0];
|
|
@@ -120,8 +120,6 @@ exception.
|
|
|
120
120
|
- [Code for all `markdownlint` built-in rules][lib]
|
|
121
121
|
- [Package configuration for publishing to npm][test-rules-npm]
|
|
122
122
|
- Packages should export a single rule object or an `Array` of rule objects
|
|
123
|
-
- [Custom rules from the Microsoft/vscode-docs-authoring
|
|
124
|
-
repository][vscode-docs-authoring]
|
|
125
123
|
- [Custom rules from the axibase/docs-util repository][docs-util]
|
|
126
124
|
- [Custom rules from the webhintio/hint repository][hint]
|
|
127
125
|
|
|
@@ -374,4 +372,3 @@ Yields the `params` object:
|
|
|
374
372
|
[options-custom-rules]: ../README.md#optionscustomrules
|
|
375
373
|
[test-rules]: ../test/rules
|
|
376
374
|
[test-rules-npm]: ../test/rules/npm
|
|
377
|
-
[vscode-docs-authoring]: https://github.com/microsoft/vscode-docs-authoring/tree/main/packages/docs-linting/markdownlint-custom-rules
|
package/doc/Rules.md
CHANGED
|
@@ -1410,42 +1410,48 @@ Aliases: `no-bare-urls`
|
|
|
1410
1410
|
|
|
1411
1411
|
Fixable: Some violations can be fixed by tooling
|
|
1412
1412
|
|
|
1413
|
-
This rule is triggered whenever a URL
|
|
1414
|
-
brackets:
|
|
1413
|
+
This rule is triggered whenever a URL or email address appears without
|
|
1414
|
+
surrounding angle brackets:
|
|
1415
1415
|
|
|
1416
1416
|
```markdown
|
|
1417
|
-
For more
|
|
1417
|
+
For more info, visit https://www.example.com/ or email user@example.com.
|
|
1418
1418
|
```
|
|
1419
1419
|
|
|
1420
|
-
To fix this, add angle brackets around the URL:
|
|
1420
|
+
To fix this, add angle brackets around the URL or email address:
|
|
1421
1421
|
|
|
1422
1422
|
```markdown
|
|
1423
|
-
For more
|
|
1423
|
+
For more info, visit <https://www.example.com/> or email <user@example.com>.
|
|
1424
1424
|
```
|
|
1425
1425
|
|
|
1426
|
-
Note: To
|
|
1427
|
-
|
|
1426
|
+
Note: To include a bare URL or email without it being converted into a link,
|
|
1427
|
+
wrap it in a code span:
|
|
1428
1428
|
|
|
1429
1429
|
```markdown
|
|
1430
|
-
`https://www.example.com`
|
|
1430
|
+
Not a clickable link: `https://www.example.com`
|
|
1431
1431
|
```
|
|
1432
1432
|
|
|
1433
|
-
Note: The following scenario does
|
|
1434
|
-
|
|
1433
|
+
Note: The following scenario does not trigger this rule because it could be a
|
|
1434
|
+
shortcut link:
|
|
1435
1435
|
|
|
1436
1436
|
```markdown
|
|
1437
1437
|
[https://www.example.com]
|
|
1438
1438
|
```
|
|
1439
1439
|
|
|
1440
|
-
The
|
|
1440
|
+
Note: The following syntax triggers this rule because the nested link could be
|
|
1441
|
+
a shortcut link (which takes precedence):
|
|
1441
1442
|
|
|
1442
1443
|
```markdown
|
|
1443
|
-
|
|
1444
|
-
'https://www.example.com'
|
|
1444
|
+
[text [shortcut] text](https://example.com)
|
|
1445
1445
|
```
|
|
1446
1446
|
|
|
1447
|
-
|
|
1448
|
-
|
|
1447
|
+
To avoid this, escape both inner brackets:
|
|
1448
|
+
|
|
1449
|
+
```markdown
|
|
1450
|
+
[link \[text\] link](https://example.com)
|
|
1451
|
+
```
|
|
1452
|
+
|
|
1453
|
+
Rationale: Without angle brackets, a bare URL or email isn't converted into a
|
|
1454
|
+
link by some Markdown parsers.
|
|
1449
1455
|
|
|
1450
1456
|
<a name="md035"></a>
|
|
1451
1457
|
|
|
@@ -2184,7 +2190,7 @@ convert heading to lowercase, remove punctuation, convert spaces to dashes,
|
|
|
2184
2190
|
append an incrementing integer as needed for uniqueness.
|
|
2185
2191
|
|
|
2186
2192
|
[github-section-links]: https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#section-links
|
|
2187
|
-
[github-heading-algorithm]: https://github.com/gjtorikian/html-pipeline/blob/
|
|
2193
|
+
[github-heading-algorithm]: https://github.com/gjtorikian/html-pipeline/blob/f13a1534cb650ba17af400d1acd3a22c28004c09/lib/html/pipeline/toc_filter.rb
|
|
2188
2194
|
|
|
2189
2195
|
<a name="md052"></a>
|
|
2190
2196
|
|
package/doc/md034.md
CHANGED
|
@@ -6,39 +6,45 @@ Aliases: `no-bare-urls`
|
|
|
6
6
|
|
|
7
7
|
Fixable: Some violations can be fixed by tooling
|
|
8
8
|
|
|
9
|
-
This rule is triggered whenever a URL
|
|
10
|
-
brackets:
|
|
9
|
+
This rule is triggered whenever a URL or email address appears without
|
|
10
|
+
surrounding angle brackets:
|
|
11
11
|
|
|
12
12
|
```markdown
|
|
13
|
-
For more
|
|
13
|
+
For more info, visit https://www.example.com/ or email user@example.com.
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
To fix this, add angle brackets around the URL:
|
|
16
|
+
To fix this, add angle brackets around the URL or email address:
|
|
17
17
|
|
|
18
18
|
```markdown
|
|
19
|
-
For more
|
|
19
|
+
For more info, visit <https://www.example.com/> or email <user@example.com>.
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
-
Note: To
|
|
23
|
-
|
|
22
|
+
Note: To include a bare URL or email without it being converted into a link,
|
|
23
|
+
wrap it in a code span:
|
|
24
24
|
|
|
25
25
|
```markdown
|
|
26
|
-
`https://www.example.com`
|
|
26
|
+
Not a clickable link: `https://www.example.com`
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
Note: The following scenario does
|
|
30
|
-
|
|
29
|
+
Note: The following scenario does not trigger this rule because it could be a
|
|
30
|
+
shortcut link:
|
|
31
31
|
|
|
32
32
|
```markdown
|
|
33
33
|
[https://www.example.com]
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
The
|
|
36
|
+
Note: The following syntax triggers this rule because the nested link could be
|
|
37
|
+
a shortcut link (which takes precedence):
|
|
37
38
|
|
|
38
39
|
```markdown
|
|
39
|
-
|
|
40
|
-
'https://www.example.com'
|
|
40
|
+
[text [shortcut] text](https://example.com)
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
To avoid this, escape both inner brackets:
|
|
44
|
+
|
|
45
|
+
```markdown
|
|
46
|
+
[link \[text\] link](https://example.com)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Rationale: Without angle brackets, a bare URL or email isn't converted into a
|
|
50
|
+
link by some Markdown parsers.
|
package/doc/md051.md
CHANGED
|
@@ -47,4 +47,4 @@ convert heading to lowercase, remove punctuation, convert spaces to dashes,
|
|
|
47
47
|
append an incrementing integer as needed for uniqueness.
|
|
48
48
|
|
|
49
49
|
[github-section-links]: https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#section-links
|
|
50
|
-
[github-heading-algorithm]: https://github.com/gjtorikian/html-pipeline/blob/
|
|
50
|
+
[github-heading-algorithm]: https://github.com/gjtorikian/html-pipeline/blob/f13a1534cb650ba17af400d1acd3a22c28004c09/lib/html/pipeline/toc_filter.rb
|
package/helpers/LICENSE
CHANGED
package/helpers/helpers.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
"use strict";
|
|
4
4
|
|
|
5
|
+
const micromark = require("./micromark.cjs");
|
|
6
|
+
|
|
5
7
|
// Regular expression for matching common newline characters
|
|
6
8
|
// See NEWLINES_RE in markdown-it/lib/rules_core/normalize.js
|
|
7
9
|
const newLineRe = /\r\n?|\n/g;
|
|
@@ -33,10 +35,6 @@ const emphasisMarkersRe = /[_*]/g;
|
|
|
33
35
|
const blockquotePrefixRe = /^[>\s]*/;
|
|
34
36
|
module.exports.blockquotePrefixRe = blockquotePrefixRe;
|
|
35
37
|
|
|
36
|
-
// Regular expression for reference links (full, collapsed, and shortcut)
|
|
37
|
-
const referenceLinkRe =
|
|
38
|
-
/!?\\?\[((?:\[[^\]\0]*\]|[^[\]\0])*)\](?:\[([^\]\0]*)\]|([^(])|$)/g;
|
|
39
|
-
|
|
40
38
|
// Regular expression for link reference definitions
|
|
41
39
|
const linkReferenceDefinitionRe = /^ {0,3}\[([^\]]*[^\\])\]:/;
|
|
42
40
|
module.exports.linkReferenceDefinitionRe = linkReferenceDefinitionRe;
|
|
@@ -193,19 +191,6 @@ module.exports.escapeForRegExp = function escapeForRegExp(str) {
|
|
|
193
191
|
return str.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
|
|
194
192
|
};
|
|
195
193
|
|
|
196
|
-
// Un-escapes Markdown content (simple algorithm; not a parser)
|
|
197
|
-
const escapedMarkdownRe = /\\./g;
|
|
198
|
-
module.exports.unescapeMarkdown =
|
|
199
|
-
function unescapeMarkdown(markdown, replacement) {
|
|
200
|
-
return markdown.replace(escapedMarkdownRe, (match) => {
|
|
201
|
-
const char = match[1];
|
|
202
|
-
if ("!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~".includes(char)) {
|
|
203
|
-
return replacement || char;
|
|
204
|
-
}
|
|
205
|
-
return match;
|
|
206
|
-
});
|
|
207
|
-
};
|
|
208
|
-
|
|
209
194
|
/**
|
|
210
195
|
* Return the string representation of a fence markup character.
|
|
211
196
|
*
|
|
@@ -288,7 +273,7 @@ module.exports.unorderedListStyleFor = function unorderedListStyleFor(token) {
|
|
|
288
273
|
* @returns {void}
|
|
289
274
|
*/
|
|
290
275
|
function filterTokens(params, type, handler) {
|
|
291
|
-
for (const token of params.tokens) {
|
|
276
|
+
for (const token of params.parsers.markdownit.tokens) {
|
|
292
277
|
if (token.type === type) {
|
|
293
278
|
handler(token);
|
|
294
279
|
}
|
|
@@ -343,7 +328,7 @@ module.exports.getLineMetadata = function getLineMetadata(params) {
|
|
|
343
328
|
filterTokens(params, "hr", (token) => {
|
|
344
329
|
lineMetadata[token.map[0]][6] = true;
|
|
345
330
|
});
|
|
346
|
-
for (const token of params.tokens.filter(isMathBlock)) {
|
|
331
|
+
for (const token of params.parsers.markdownit.tokens.filter(isMathBlock)) {
|
|
347
332
|
for (let i = token.map[0]; i < token.map[1]; i++) {
|
|
348
333
|
lineMetadata[i][7] = true;
|
|
349
334
|
}
|
|
@@ -437,7 +422,7 @@ module.exports.forEachInlineChild = forEachInlineChild;
|
|
|
437
422
|
// Calls the provided function for each heading's content
|
|
438
423
|
module.exports.forEachHeading = function forEachHeading(params, handler) {
|
|
439
424
|
let heading = null;
|
|
440
|
-
for (const token of params.tokens) {
|
|
425
|
+
for (const token of params.parsers.markdownit.tokens) {
|
|
441
426
|
if (token.type === "heading_open") {
|
|
442
427
|
heading = token;
|
|
443
428
|
} else if (token.type === "heading_close") {
|
|
@@ -818,137 +803,117 @@ module.exports.emphasisMarkersInContent = emphasisMarkersInContent;
|
|
|
818
803
|
/**
|
|
819
804
|
* Returns an object with information about reference links and images.
|
|
820
805
|
*
|
|
821
|
-
* @param {Object}
|
|
806
|
+
* @param {Object} params RuleParams instance.
|
|
822
807
|
* @returns {Object} Reference link/image data.
|
|
823
808
|
*/
|
|
824
|
-
function getReferenceLinkImageData(
|
|
825
|
-
|
|
826
|
-
const references = new Map();
|
|
827
|
-
const shortcuts = new Map();
|
|
809
|
+
function getReferenceLinkImageData(params) {
|
|
810
|
+
const normalizeReference = (s) => s.toLowerCase().trim().replace(/\s+/g, " ");
|
|
828
811
|
const definitions = new Map();
|
|
829
|
-
const duplicateDefinitions = [];
|
|
830
812
|
const definitionLineIndices = [];
|
|
831
|
-
|
|
832
|
-
const
|
|
833
|
-
const
|
|
834
|
-
const
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
// Determine single-line exclusions for inline code spans
|
|
856
|
-
forEachInlineCodeSpan(contentLine, (code, lineIndex, columnIndex) => {
|
|
857
|
-
exclusions.push([ 0, columnIndex, code.length ]);
|
|
858
|
-
});
|
|
859
|
-
// Identify all link/image reference definitions
|
|
860
|
-
forEachLine(lineMetadata, (line, lineIndex, inCode) => {
|
|
861
|
-
if (!inCode) {
|
|
862
|
-
const linkReferenceDefinitionMatch = linkReferenceDefinitionRe.exec(line);
|
|
863
|
-
if (linkReferenceDefinitionMatch) {
|
|
864
|
-
const label = normalizeLabel(linkReferenceDefinitionMatch[1]);
|
|
865
|
-
if (definitions.has(label)) {
|
|
866
|
-
duplicateDefinitions.push([ label, lineIndex ]);
|
|
867
|
-
} else {
|
|
868
|
-
definitions.set(label, lineIndex);
|
|
869
|
-
}
|
|
870
|
-
const labelLength = linkReferenceDefinitionMatch[0].length;
|
|
871
|
-
exclusions.push([ 0, lineOffsets[lineIndex], labelLength ]);
|
|
872
|
-
const hasDefinition = line.slice(labelLength).trim().length > 0;
|
|
873
|
-
definitionLineIndices.push(lineIndex);
|
|
874
|
-
if (!hasDefinition) {
|
|
875
|
-
definitionLineIndices.push(lineIndex + 1);
|
|
813
|
+
const duplicateDefinitions = [];
|
|
814
|
+
const references = new Map();
|
|
815
|
+
const shortcuts = new Map();
|
|
816
|
+
const filteredTokens =
|
|
817
|
+
micromark.filterByTypes(
|
|
818
|
+
params.parsers.micromark.tokens,
|
|
819
|
+
[
|
|
820
|
+
// definitionLineIndices
|
|
821
|
+
"definition", "gfmFootnoteDefinition",
|
|
822
|
+
// definitions and definitionLineIndices
|
|
823
|
+
"definitionLabelString", "gfmFootnoteDefinitionLabelString",
|
|
824
|
+
// references and shortcuts
|
|
825
|
+
"gfmFootnoteCall", "image", "link"
|
|
826
|
+
]
|
|
827
|
+
);
|
|
828
|
+
for (const token of filteredTokens) {
|
|
829
|
+
let labelPrefix = "";
|
|
830
|
+
// eslint-disable-next-line default-case
|
|
831
|
+
switch (token.type) {
|
|
832
|
+
case "definition":
|
|
833
|
+
case "gfmFootnoteDefinition":
|
|
834
|
+
// definitionLineIndices
|
|
835
|
+
for (let i = token.startLine; i <= token.endLine; i++) {
|
|
836
|
+
definitionLineIndices.push(i - 1);
|
|
876
837
|
}
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
"contentIndex": 0,
|
|
887
|
-
"topLevel": true
|
|
888
|
-
}
|
|
889
|
-
];
|
|
890
|
-
let pendingContent = null;
|
|
891
|
-
while ((pendingContent = pendingContents.shift())) {
|
|
892
|
-
const { content, contentLineIndex, contentIndex, topLevel } =
|
|
893
|
-
pendingContent;
|
|
894
|
-
let referenceLinkMatch = null;
|
|
895
|
-
while ((referenceLinkMatch = referenceLinkRe.exec(content)) !== null) {
|
|
896
|
-
const [ matchString, matchText, matchLabel ] = referenceLinkMatch;
|
|
897
|
-
if (
|
|
898
|
-
!matchString.startsWith("\\") &&
|
|
899
|
-
!matchString.startsWith("!\\") &&
|
|
900
|
-
!matchText.endsWith("\\") &&
|
|
901
|
-
!(matchLabel || "").endsWith("\\") &&
|
|
902
|
-
!(topLevel && excluded(referenceLinkMatch))
|
|
903
|
-
) {
|
|
904
|
-
const shortcutLink = (matchLabel === undefined);
|
|
905
|
-
const collapsedLink =
|
|
906
|
-
(!shortcutLink && (matchLabel.length === 0));
|
|
907
|
-
const label = normalizeLabel(
|
|
908
|
-
(shortcutLink || collapsedLink) ? matchText : matchLabel
|
|
909
|
-
);
|
|
910
|
-
if (label.length > 0) {
|
|
911
|
-
const referenceindex = referenceLinkMatch.index;
|
|
912
|
-
if (topLevel) {
|
|
913
|
-
// Calculate line index
|
|
914
|
-
while (lineOffsets[lineIndex + 1] <= referenceindex) {
|
|
915
|
-
lineIndex++;
|
|
916
|
-
}
|
|
838
|
+
break;
|
|
839
|
+
case "gfmFootnoteDefinitionLabelString":
|
|
840
|
+
labelPrefix = "^";
|
|
841
|
+
case "definitionLabelString": // eslint-disable-line no-fallthrough
|
|
842
|
+
{
|
|
843
|
+
// definitions and definitionLineIndices
|
|
844
|
+
const reference = normalizeReference(`${labelPrefix}${token.text}`);
|
|
845
|
+
if (definitions.has(reference)) {
|
|
846
|
+
duplicateDefinitions.push([ reference, token.startLine - 1 ]);
|
|
917
847
|
} else {
|
|
918
|
-
|
|
919
|
-
lineIndex = contentLineIndex;
|
|
848
|
+
definitions.set(reference, token.startLine - 1);
|
|
920
849
|
}
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
references.set(label, referenceData);
|
|
850
|
+
}
|
|
851
|
+
break;
|
|
852
|
+
case "gfmFootnoteCall":
|
|
853
|
+
case "image":
|
|
854
|
+
case "link":
|
|
855
|
+
{
|
|
856
|
+
let isShortcut = false;
|
|
857
|
+
let isFullOrCollapsed = false;
|
|
858
|
+
let labelText = null;
|
|
859
|
+
let referenceStringText = null;
|
|
860
|
+
const shortcutCandidate =
|
|
861
|
+
micromark.matchAndGetTokensByType(token.children, [ "label" ]);
|
|
862
|
+
if (shortcutCandidate) {
|
|
863
|
+
labelText =
|
|
864
|
+
micromark.getTokenTextByType(
|
|
865
|
+
shortcutCandidate[0].children, "labelText"
|
|
866
|
+
);
|
|
867
|
+
isShortcut = (labelText !== null);
|
|
940
868
|
}
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
869
|
+
const fullAndCollapsedCandidate =
|
|
870
|
+
micromark.matchAndGetTokensByType(
|
|
871
|
+
token.children, [ "label", "reference" ]
|
|
872
|
+
);
|
|
873
|
+
if (fullAndCollapsedCandidate) {
|
|
874
|
+
labelText =
|
|
875
|
+
micromark.getTokenTextByType(
|
|
876
|
+
fullAndCollapsedCandidate[0].children, "labelText"
|
|
877
|
+
);
|
|
878
|
+
referenceStringText =
|
|
879
|
+
micromark.getTokenTextByType(
|
|
880
|
+
fullAndCollapsedCandidate[1].children, "referenceString"
|
|
881
|
+
);
|
|
882
|
+
isFullOrCollapsed = (labelText !== null);
|
|
883
|
+
}
|
|
884
|
+
const footnote = micromark.matchAndGetTokensByType(
|
|
885
|
+
token.children,
|
|
886
|
+
[
|
|
887
|
+
"gfmFootnoteCallLabelMarker", "gfmFootnoteCallMarker",
|
|
888
|
+
"gfmFootnoteCallString", "gfmFootnoteCallLabelMarker"
|
|
889
|
+
],
|
|
890
|
+
[ "gfmFootnoteCallMarker", "gfmFootnoteCallString" ]
|
|
891
|
+
);
|
|
892
|
+
if (footnote) {
|
|
893
|
+
const callMarkerText = footnote[0].text;
|
|
894
|
+
const callString = footnote[1].text;
|
|
895
|
+
labelText = `${callMarkerText}${callString}`;
|
|
896
|
+
isShortcut = true;
|
|
897
|
+
}
|
|
898
|
+
// Track shortcuts separately due to ambiguity in "text [text] text"
|
|
899
|
+
if (isShortcut || isFullOrCollapsed) {
|
|
900
|
+
const referenceDatum = [
|
|
901
|
+
token.startLine - 1,
|
|
902
|
+
token.startColumn - 1,
|
|
903
|
+
token.text.length,
|
|
904
|
+
// @ts-ignore
|
|
905
|
+
labelText.length,
|
|
906
|
+
(referenceStringText || "").length
|
|
907
|
+
];
|
|
908
|
+
const reference =
|
|
909
|
+
normalizeReference(referenceStringText || labelText);
|
|
910
|
+
const dictionary = isShortcut ? shortcuts : references;
|
|
911
|
+
const referenceData = dictionary.get(reference) || [];
|
|
912
|
+
referenceData.push(referenceDatum);
|
|
913
|
+
dictionary.set(reference, referenceData);
|
|
949
914
|
}
|
|
950
915
|
}
|
|
951
|
-
|
|
916
|
+
break;
|
|
952
917
|
}
|
|
953
918
|
}
|
|
954
919
|
return {
|
|
@@ -1187,110 +1152,3 @@ function expandTildePath(file, os) {
|
|
|
1187
1152
|
return homedir ? file.replace(/^~($|\/|\\)/, `${homedir}$1`) : file;
|
|
1188
1153
|
}
|
|
1189
1154
|
module.exports.expandTildePath = expandTildePath;
|
|
1190
|
-
|
|
1191
|
-
/**
|
|
1192
|
-
* RegExp.exec-style implementation of function expressions.
|
|
1193
|
-
*
|
|
1194
|
-
* @param {Function} funcExp Function that takes string and returns
|
|
1195
|
-
* [index, length] or null.
|
|
1196
|
-
* @param {string} input String to search.
|
|
1197
|
-
* @returns {string[] | null} RegExp.exec-style [match] with an index property.
|
|
1198
|
-
*/
|
|
1199
|
-
function funcExpExec(funcExp, input) {
|
|
1200
|
-
// Start or resume match
|
|
1201
|
-
// @ts-ignore
|
|
1202
|
-
const lastIndex = funcExp.lastIndex || 0;
|
|
1203
|
-
const result = funcExp(input.slice(lastIndex));
|
|
1204
|
-
if (result) {
|
|
1205
|
-
// Update lastIndex and return match
|
|
1206
|
-
const [ subIndex, length ] = result;
|
|
1207
|
-
const index = lastIndex + subIndex;
|
|
1208
|
-
// @ts-ignore
|
|
1209
|
-
funcExp.lastIndex = index + length;
|
|
1210
|
-
const match = [ input.slice(index, index + length) ];
|
|
1211
|
-
// @ts-ignore
|
|
1212
|
-
match.index = index;
|
|
1213
|
-
return match;
|
|
1214
|
-
}
|
|
1215
|
-
// Reset lastIndex and return no match
|
|
1216
|
-
// @ts-ignore
|
|
1217
|
-
funcExp.lastIndex = 0;
|
|
1218
|
-
return null;
|
|
1219
|
-
}
|
|
1220
|
-
module.exports.funcExpExec = funcExpExec;
|
|
1221
|
-
|
|
1222
|
-
const urlFeProtocolRe = /(?:http|ftp)s?:\/\//i;
|
|
1223
|
-
const urlFeAutolinkTerminalsRe = / |$/;
|
|
1224
|
-
const urlFeBareTerminalsRe = /[ ,!`'"\]]|$/;
|
|
1225
|
-
const urlFeNonTerminalsRe = "-#/";
|
|
1226
|
-
const urlFePunctuationRe = /\p{Punctuation}/u;
|
|
1227
|
-
const urlFePrefixToPostfix = new Map([
|
|
1228
|
-
[ " ", " " ],
|
|
1229
|
-
[ "`", "`" ],
|
|
1230
|
-
[ "'", "'" ],
|
|
1231
|
-
[ "\"", "\"" ],
|
|
1232
|
-
[ "‘", "’" ],
|
|
1233
|
-
[ "“", "”" ],
|
|
1234
|
-
[ "«", "»" ],
|
|
1235
|
-
[ "*", "*" ],
|
|
1236
|
-
[ "_", "_" ],
|
|
1237
|
-
[ "(", ")" ],
|
|
1238
|
-
[ "[", "]" ],
|
|
1239
|
-
[ "{", "}" ],
|
|
1240
|
-
[ "<", ">" ],
|
|
1241
|
-
[ ">", "<" ]
|
|
1242
|
-
]);
|
|
1243
|
-
|
|
1244
|
-
/**
|
|
1245
|
-
* Function expression that matches URLs.
|
|
1246
|
-
*
|
|
1247
|
-
* @param {string} input Substring to search for a URL.
|
|
1248
|
-
* @returns {Array | null} [index, length] of URL or null.
|
|
1249
|
-
*/
|
|
1250
|
-
function urlFe(input) {
|
|
1251
|
-
// Find start of URL by searching for protocol
|
|
1252
|
-
const match = input.match(urlFeProtocolRe);
|
|
1253
|
-
if (match) {
|
|
1254
|
-
// Look for matching pre/postfix characters (ex: <...>)
|
|
1255
|
-
const start = match.index || 0;
|
|
1256
|
-
const length = match[0].length;
|
|
1257
|
-
const prefix = input[start - 1] || " ";
|
|
1258
|
-
const postfix = urlFePrefixToPostfix.get(prefix);
|
|
1259
|
-
// @ts-ignore
|
|
1260
|
-
let endPostfix = input.indexOf(postfix, start + length);
|
|
1261
|
-
if (endPostfix === -1) {
|
|
1262
|
-
endPostfix = input.length;
|
|
1263
|
-
}
|
|
1264
|
-
// Look for characters that terminate a URL
|
|
1265
|
-
const terminalsRe =
|
|
1266
|
-
(prefix === "<") ? urlFeAutolinkTerminalsRe : urlFeBareTerminalsRe;
|
|
1267
|
-
const endTerminal = start + input.slice(start).search(terminalsRe);
|
|
1268
|
-
// Determine tentative end of URL
|
|
1269
|
-
let end = Math.min(endPostfix, endTerminal);
|
|
1270
|
-
if (prefix === " ") {
|
|
1271
|
-
// If the URL used " " as pre/postfix characters, trim the end
|
|
1272
|
-
if (input[end - 1] === ")") {
|
|
1273
|
-
// Trim any ")" beyond the last "(...)" pair
|
|
1274
|
-
const lastOpenParen = input.lastIndexOf("(", end - 2);
|
|
1275
|
-
if (lastOpenParen <= start) {
|
|
1276
|
-
end--;
|
|
1277
|
-
} else {
|
|
1278
|
-
const nextCloseParen = input.indexOf(")", lastOpenParen + 1);
|
|
1279
|
-
end = nextCloseParen + 1;
|
|
1280
|
-
}
|
|
1281
|
-
} else {
|
|
1282
|
-
// Trim unwanted punctuation
|
|
1283
|
-
while (
|
|
1284
|
-
!urlFeNonTerminalsRe.includes(input[end - 1]) &&
|
|
1285
|
-
urlFePunctuationRe.test(input[end - 1])
|
|
1286
|
-
) {
|
|
1287
|
-
end--;
|
|
1288
|
-
}
|
|
1289
|
-
}
|
|
1290
|
-
}
|
|
1291
|
-
return [ start, end - start ];
|
|
1292
|
-
}
|
|
1293
|
-
// No match
|
|
1294
|
-
return null;
|
|
1295
|
-
}
|
|
1296
|
-
module.exports.urlFe = urlFe;
|