@dougis/markdown-lint-mcp 1.0.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 +80 -0
- package/CONTRIBUTING.md +474 -0
- package/LICENSE +21 -0
- package/README.md +240 -0
- package/USAGE.md +40 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -0
- package/dist/rules/index.d.ts +22 -0
- package/dist/rules/index.d.ts.map +1 -0
- package/dist/rules/index.js +144 -0
- package/dist/rules/index.js.map +1 -0
- package/dist/rules/md001.d.ts +25 -0
- package/dist/rules/md001.d.ts.map +1 -0
- package/dist/rules/md001.js +79 -0
- package/dist/rules/md001.js.map +1 -0
- package/dist/rules/md003.d.ts +41 -0
- package/dist/rules/md003.d.ts.map +1 -0
- package/dist/rules/md003.js +130 -0
- package/dist/rules/md003.js.map +1 -0
- package/dist/rules/md004.d.ts +28 -0
- package/dist/rules/md004.d.ts.map +1 -0
- package/dist/rules/md004.js +79 -0
- package/dist/rules/md004.js.map +1 -0
- package/dist/rules/md005.d.ts +21 -0
- package/dist/rules/md005.d.ts.map +1 -0
- package/dist/rules/md005.js +88 -0
- package/dist/rules/md005.js.map +1 -0
- package/dist/rules/md007.d.ts +21 -0
- package/dist/rules/md007.d.ts.map +1 -0
- package/dist/rules/md007.js +66 -0
- package/dist/rules/md007.js.map +1 -0
- package/dist/rules/md009.d.ts +35 -0
- package/dist/rules/md009.d.ts.map +1 -0
- package/dist/rules/md009.js +122 -0
- package/dist/rules/md009.js.map +1 -0
- package/dist/rules/md010.d.ts +34 -0
- package/dist/rules/md010.d.ts.map +1 -0
- package/dist/rules/md010.js +75 -0
- package/dist/rules/md010.js.map +1 -0
- package/dist/rules/md011.d.ts +30 -0
- package/dist/rules/md011.d.ts.map +1 -0
- package/dist/rules/md011.js +123 -0
- package/dist/rules/md011.js.map +1 -0
- package/dist/rules/md012.d.ts +33 -0
- package/dist/rules/md012.d.ts.map +1 -0
- package/dist/rules/md012.js +125 -0
- package/dist/rules/md012.js.map +1 -0
- package/dist/rules/md013.d.ts +26 -0
- package/dist/rules/md013.d.ts.map +1 -0
- package/dist/rules/md013.js +32 -0
- package/dist/rules/md013.js.map +1 -0
- package/dist/rules/md014.d.ts +29 -0
- package/dist/rules/md014.d.ts.map +1 -0
- package/dist/rules/md014.js +176 -0
- package/dist/rules/md014.js.map +1 -0
- package/dist/rules/md018.d.ts +22 -0
- package/dist/rules/md018.d.ts.map +1 -0
- package/dist/rules/md018.js +27 -0
- package/dist/rules/md018.js.map +1 -0
- package/dist/rules/md019.d.ts +22 -0
- package/dist/rules/md019.d.ts.map +1 -0
- package/dist/rules/md019.js +27 -0
- package/dist/rules/md019.js.map +1 -0
- package/dist/rules/md020.d.ts +22 -0
- package/dist/rules/md020.d.ts.map +1 -0
- package/dist/rules/md020.js +27 -0
- package/dist/rules/md020.js.map +1 -0
- package/dist/rules/md021.d.ts +22 -0
- package/dist/rules/md021.d.ts.map +1 -0
- package/dist/rules/md021.js +27 -0
- package/dist/rules/md021.js.map +1 -0
- package/dist/rules/md022.d.ts +21 -0
- package/dist/rules/md022.d.ts.map +1 -0
- package/dist/rules/md022.js +43 -0
- package/dist/rules/md022.js.map +1 -0
- package/dist/rules/md023.d.ts +21 -0
- package/dist/rules/md023.d.ts.map +1 -0
- package/dist/rules/md023.js +34 -0
- package/dist/rules/md023.js.map +1 -0
- package/dist/rules/md024.d.ts +30 -0
- package/dist/rules/md024.d.ts.map +1 -0
- package/dist/rules/md024.js +123 -0
- package/dist/rules/md024.js.map +1 -0
- package/dist/rules/md025.d.ts +34 -0
- package/dist/rules/md025.d.ts.map +1 -0
- package/dist/rules/md025.js +134 -0
- package/dist/rules/md025.js.map +1 -0
- package/dist/rules/md026.d.ts +21 -0
- package/dist/rules/md026.d.ts.map +1 -0
- package/dist/rules/md026.js +31 -0
- package/dist/rules/md026.js.map +1 -0
- package/dist/rules/md027.d.ts +22 -0
- package/dist/rules/md027.d.ts.map +1 -0
- package/dist/rules/md027.js +27 -0
- package/dist/rules/md027.js.map +1 -0
- package/dist/rules/md028.d.ts +37 -0
- package/dist/rules/md028.d.ts.map +1 -0
- package/dist/rules/md028.js +84 -0
- package/dist/rules/md028.js.map +1 -0
- package/dist/rules/md029.d.ts +30 -0
- package/dist/rules/md029.d.ts.map +1 -0
- package/dist/rules/md029.js +36 -0
- package/dist/rules/md029.js.map +1 -0
- package/dist/rules/md030.d.ts +28 -0
- package/dist/rules/md030.d.ts.map +1 -0
- package/dist/rules/md030.js +76 -0
- package/dist/rules/md030.js.map +1 -0
- package/dist/rules/md031.d.ts +22 -0
- package/dist/rules/md031.d.ts.map +1 -0
- package/dist/rules/md031.js +55 -0
- package/dist/rules/md031.js.map +1 -0
- package/dist/rules/md032.d.ts +21 -0
- package/dist/rules/md032.d.ts.map +1 -0
- package/dist/rules/md032.js +69 -0
- package/dist/rules/md032.js.map +1 -0
- package/dist/rules/md033.d.ts +28 -0
- package/dist/rules/md033.d.ts.map +1 -0
- package/dist/rules/md033.js +34 -0
- package/dist/rules/md033.js.map +1 -0
- package/dist/rules/md034.d.ts +28 -0
- package/dist/rules/md034.d.ts.map +1 -0
- package/dist/rules/md034.js +100 -0
- package/dist/rules/md034.js.map +1 -0
- package/dist/rules/md035.d.ts +23 -0
- package/dist/rules/md035.d.ts.map +1 -0
- package/dist/rules/md035.js +52 -0
- package/dist/rules/md035.js.map +1 -0
- package/dist/rules/md036.d.ts +34 -0
- package/dist/rules/md036.d.ts.map +1 -0
- package/dist/rules/md036.js +112 -0
- package/dist/rules/md036.js.map +1 -0
- package/dist/rules/md037.d.ts +28 -0
- package/dist/rules/md037.d.ts.map +1 -0
- package/dist/rules/md037.js +122 -0
- package/dist/rules/md037.js.map +1 -0
- package/dist/rules/md038.d.ts +28 -0
- package/dist/rules/md038.d.ts.map +1 -0
- package/dist/rules/md038.js +62 -0
- package/dist/rules/md038.js.map +1 -0
- package/dist/rules/md039.d.ts +21 -0
- package/dist/rules/md039.d.ts.map +1 -0
- package/dist/rules/md039.js +34 -0
- package/dist/rules/md039.js.map +1 -0
- package/dist/rules/md040.d.ts +21 -0
- package/dist/rules/md040.d.ts.map +1 -0
- package/dist/rules/md040.js +46 -0
- package/dist/rules/md040.js.map +1 -0
- package/dist/rules/md041.d.ts +33 -0
- package/dist/rules/md041.d.ts.map +1 -0
- package/dist/rules/md041.js +92 -0
- package/dist/rules/md041.js.map +1 -0
- package/dist/rules/md042.d.ts +22 -0
- package/dist/rules/md042.d.ts.map +1 -0
- package/dist/rules/md042.js +50 -0
- package/dist/rules/md042.js.map +1 -0
- package/dist/rules/md043.d.ts +39 -0
- package/dist/rules/md043.d.ts.map +1 -0
- package/dist/rules/md043.js +116 -0
- package/dist/rules/md043.js.map +1 -0
- package/dist/rules/md044.d.ts +40 -0
- package/dist/rules/md044.d.ts.map +1 -0
- package/dist/rules/md044.js +167 -0
- package/dist/rules/md044.js.map +1 -0
- package/dist/rules/md045.d.ts +22 -0
- package/dist/rules/md045.d.ts.map +1 -0
- package/dist/rules/md045.js +57 -0
- package/dist/rules/md045.js.map +1 -0
- package/dist/rules/md046.d.ts +23 -0
- package/dist/rules/md046.d.ts.map +1 -0
- package/dist/rules/md046.js +174 -0
- package/dist/rules/md046.js.map +1 -0
- package/dist/rules/md047.d.ts +22 -0
- package/dist/rules/md047.d.ts.map +1 -0
- package/dist/rules/md047.js +35 -0
- package/dist/rules/md047.js.map +1 -0
- package/dist/rules/md048.d.ts +22 -0
- package/dist/rules/md048.d.ts.map +1 -0
- package/dist/rules/md048.js +80 -0
- package/dist/rules/md048.js.map +1 -0
- package/dist/rules/md049.d.ts +33 -0
- package/dist/rules/md049.d.ts.map +1 -0
- package/dist/rules/md049.js +189 -0
- package/dist/rules/md049.js.map +1 -0
- package/dist/rules/md050.d.ts +22 -0
- package/dist/rules/md050.d.ts.map +1 -0
- package/dist/rules/md050.js +32 -0
- package/dist/rules/md050.js.map +1 -0
- package/dist/rules/md051.d.ts +23 -0
- package/dist/rules/md051.d.ts.map +1 -0
- package/dist/rules/md051.js +63 -0
- package/dist/rules/md051.js.map +1 -0
- package/dist/rules/md052.d.ts +21 -0
- package/dist/rules/md052.d.ts.map +1 -0
- package/dist/rules/md052.js +71 -0
- package/dist/rules/md052.js.map +1 -0
- package/dist/rules/md053.d.ts +21 -0
- package/dist/rules/md053.d.ts.map +1 -0
- package/dist/rules/md053.js +95 -0
- package/dist/rules/md053.js.map +1 -0
- package/dist/rules/md054.d.ts +21 -0
- package/dist/rules/md054.d.ts.map +1 -0
- package/dist/rules/md054.js +87 -0
- package/dist/rules/md054.js.map +1 -0
- package/dist/rules/md055.d.ts +22 -0
- package/dist/rules/md055.d.ts.map +1 -0
- package/dist/rules/md055.js +157 -0
- package/dist/rules/md055.js.map +1 -0
- package/dist/rules/md056.d.ts +21 -0
- package/dist/rules/md056.d.ts.map +1 -0
- package/dist/rules/md056.js +154 -0
- package/dist/rules/md056.js.map +1 -0
- package/dist/rules/md058.d.ts +27 -0
- package/dist/rules/md058.d.ts.map +1 -0
- package/dist/rules/md058.js +71 -0
- package/dist/rules/md058.js.map +1 -0
- package/dist/rules/md059.d.ts +22 -0
- package/dist/rules/md059.d.ts.map +1 -0
- package/dist/rules/md059.js +161 -0
- package/dist/rules/md059.js.map +1 -0
- package/dist/rules/rule-interface.d.ts +51 -0
- package/dist/rules/rule-interface.d.ts.map +1 -0
- package/dist/rules/rule-interface.js +2 -0
- package/dist/rules/rule-interface.js.map +1 -0
- package/dist/server.d.ts +59 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +419 -0
- package/dist/server.js.map +1 -0
- package/dist/types.d.ts +74 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +14 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/file.d.ts +39 -0
- package/dist/utils/file.d.ts.map +1 -0
- package/dist/utils/file.js +124 -0
- package/dist/utils/file.js.map +1 -0
- package/dist/utils/logger.d.ts +61 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +85 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/safe-match.d.ts +4 -0
- package/dist/utils/safe-match.d.ts.map +1 -0
- package/dist/utils/safe-match.js +51 -0
- package/dist/utils/safe-match.js.map +1 -0
- package/package.json +85 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MD024: Multiple headings with the same content
|
|
3
|
+
*
|
|
4
|
+
* This rule is triggered when multiple headings in the document have the same text content.
|
|
5
|
+
* The rule can be configured to allow this behavior for siblings (headings at the same level)
|
|
6
|
+
* while still preventing duplicate headings across different levels.
|
|
7
|
+
*/
|
|
8
|
+
export const name = 'MD024';
|
|
9
|
+
export const description = 'Multiple headings with the same content';
|
|
10
|
+
/**
|
|
11
|
+
* Fix markdown content to make heading content unique
|
|
12
|
+
* @param lines Array of string lines to fix
|
|
13
|
+
* @param config Optional configuration object
|
|
14
|
+
* @returns Fixed lines array with unique heading content
|
|
15
|
+
*/
|
|
16
|
+
export function fix(lines, config) {
|
|
17
|
+
if (lines.length === 0)
|
|
18
|
+
return lines;
|
|
19
|
+
// Default configuration
|
|
20
|
+
const allowDifferentNesting = config?.allow_different_nesting || false;
|
|
21
|
+
const siblingsOnly = config?.siblings_only || false;
|
|
22
|
+
// Track all headings
|
|
23
|
+
const headings = [];
|
|
24
|
+
// Helper to extract heading level and content from a line
|
|
25
|
+
function parseHeading(line) {
|
|
26
|
+
// ATX style heading (# Heading)
|
|
27
|
+
const atxMatch = line.match(/^(#{1,6})\s+(.+?)(?:\s+#*)?$/);
|
|
28
|
+
if (atxMatch) {
|
|
29
|
+
return {
|
|
30
|
+
level: atxMatch[1].length,
|
|
31
|
+
content: atxMatch[2].trim(),
|
|
32
|
+
index: -1, // Will be set when processing
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
// First pass: collect all headings and track their positions
|
|
38
|
+
for (let i = 0; i < lines.length; i++) {
|
|
39
|
+
const heading = parseHeading(lines[i]);
|
|
40
|
+
if (heading) {
|
|
41
|
+
heading.index = i;
|
|
42
|
+
headings.push(heading);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
// Add section numbering to help track hierarchy
|
|
46
|
+
let currentSection = [];
|
|
47
|
+
for (let i = 0; i < headings.length; i++) {
|
|
48
|
+
const heading = headings[i];
|
|
49
|
+
// Update section tracking
|
|
50
|
+
while (currentSection.length >= heading.level) {
|
|
51
|
+
currentSection.pop();
|
|
52
|
+
}
|
|
53
|
+
while (currentSection.length < heading.level - 1) {
|
|
54
|
+
currentSection.push(0);
|
|
55
|
+
}
|
|
56
|
+
if (currentSection.length < heading.level) {
|
|
57
|
+
currentSection.push(1);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
currentSection[currentSection.length - 1]++;
|
|
61
|
+
}
|
|
62
|
+
heading.section = [...currentSection];
|
|
63
|
+
}
|
|
64
|
+
// Second pass: identify duplicate headings and modify them
|
|
65
|
+
const result = [...lines];
|
|
66
|
+
const seenHeadings = new Map();
|
|
67
|
+
for (const heading of headings) {
|
|
68
|
+
const { level, content, index, section } = heading;
|
|
69
|
+
// Key to check against depends on configuration
|
|
70
|
+
let key = content.toLowerCase();
|
|
71
|
+
if (allowDifferentNesting || siblingsOnly) {
|
|
72
|
+
// For allow_different_nesting or siblings_only, also consider the heading's location
|
|
73
|
+
if (allowDifferentNesting) {
|
|
74
|
+
// Consider full path (different nesting allowed)
|
|
75
|
+
key = section?.join('.') + ':' + key;
|
|
76
|
+
}
|
|
77
|
+
else if (siblingsOnly) {
|
|
78
|
+
// Consider only parent section (siblings only)
|
|
79
|
+
key = section?.slice(0, -1).join('.') + ':' + level + ':' + key;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// Track seen headings by key
|
|
83
|
+
if (!seenHeadings.has(key)) {
|
|
84
|
+
seenHeadings.set(key, new Set([content]));
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
const headingSet = seenHeadings.get(key);
|
|
88
|
+
// If we've seen this heading before, modify it to make it unique
|
|
89
|
+
if (headingSet.has(content)) {
|
|
90
|
+
// Use section numbering to make the heading unique
|
|
91
|
+
const sectionLabel = section?.join('.') || '';
|
|
92
|
+
const newContent = `${content} (${sectionLabel})`;
|
|
93
|
+
// Update the line with the new heading content
|
|
94
|
+
const line = result[index];
|
|
95
|
+
if (line.endsWith('#')) {
|
|
96
|
+
// For closed ATX headings (# Heading #)
|
|
97
|
+
result[index] = line.replace(/^(#{1,6}\s+)(.+?)(\s+#*)?$/, `$1${newContent}$3`);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
// For regular ATX headings (# Heading)
|
|
101
|
+
result[index] = line.replace(/^(#{1,6}\s+)(.+?)$/, `$1${newContent}`);
|
|
102
|
+
}
|
|
103
|
+
// Add the new content to the set to avoid duplicates
|
|
104
|
+
headingSet.add(newContent);
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
// First time seeing this exact content in this context
|
|
108
|
+
headingSet.add(content);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return result;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Rule implementation for MD024
|
|
116
|
+
*/
|
|
117
|
+
export const rule = {
|
|
118
|
+
name,
|
|
119
|
+
description,
|
|
120
|
+
fix,
|
|
121
|
+
};
|
|
122
|
+
export default rule;
|
|
123
|
+
//# sourceMappingURL=md024.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"md024.js","sourceRoot":"","sources":["../../src/rules/md024.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,OAAO,CAAC;AAC5B,MAAM,CAAC,MAAM,WAAW,GAAG,yCAAyC,CAAC;AAoBrE;;;;;GAKG;AACH,MAAM,UAAU,GAAG,CAAC,KAAe,EAAE,MAAoB;IACvD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAErC,wBAAwB;IACxB,MAAM,qBAAqB,GAAG,MAAM,EAAE,uBAAuB,IAAI,KAAK,CAAC;IACvE,MAAM,YAAY,GAAG,MAAM,EAAE,aAAa,IAAI,KAAK,CAAC;IAEpD,qBAAqB;IACrB,MAAM,QAAQ,GAAkB,EAAE,CAAC;IAEnC,0DAA0D;IAC1D,SAAS,YAAY,CAAC,IAAY;QAChC,gCAAgC;QAChC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;QAC5D,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO;gBACL,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM;gBACzB,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE;gBAC3B,KAAK,EAAE,CAAC,CAAC,EAAE,8BAA8B;aAC1C,CAAC;QACJ,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED,6DAA6D;IAC7D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACvC,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC;YAClB,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IAED,gDAAgD;IAChD,IAAI,cAAc,GAAa,EAAE,CAAC;IAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QAE5B,0BAA0B;QAC1B,OAAO,cAAc,CAAC,MAAM,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YAC9C,cAAc,CAAC,GAAG,EAAE,CAAC;QACvB,CAAC;QAED,OAAO,cAAc,CAAC,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC;YACjD,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACzB,CAAC;QAED,IAAI,cAAc,CAAC,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;YAC1C,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACzB,CAAC;aAAM,CAAC;YACN,cAAc,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC;QAC9C,CAAC;QAED,OAAO,CAAC,OAAO,GAAG,CAAC,GAAG,cAAc,CAAC,CAAC;IACxC,CAAC;IAED,2DAA2D;IAC3D,MAAM,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;IAC1B,MAAM,YAAY,GAA6B,IAAI,GAAG,EAAE,CAAC;IAEzD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;QAEnD,gDAAgD;QAChD,IAAI,GAAG,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;QAChC,IAAI,qBAAqB,IAAI,YAAY,EAAE,CAAC;YAC1C,qFAAqF;YACrF,IAAI,qBAAqB,EAAE,CAAC;gBAC1B,iDAAiD;gBACjD,GAAG,GAAG,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC;YACvC,CAAC;iBAAM,IAAI,YAAY,EAAE,CAAC;gBACxB,+CAA+C;gBAC/C,GAAG,GAAG,OAAO,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,KAAK,GAAG,GAAG,GAAG,GAAG,CAAC;YAClE,CAAC;QACH,CAAC;QAED,6BAA6B;QAC7B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAC3B,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAC5C,CAAC;aAAM,CAAC;YACN,MAAM,UAAU,GAAG,YAAY,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC;YAE1C,iEAAiE;YACjE,IAAI,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC5B,mDAAmD;gBACnD,MAAM,YAAY,GAAG,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;gBAC9C,MAAM,UAAU,GAAG,GAAG,OAAO,KAAK,YAAY,GAAG,CAAC;gBAElD,+CAA+C;gBAC/C,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;gBAC3B,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;oBACvB,wCAAwC;oBACxC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,4BAA4B,EAAE,KAAK,UAAU,IAAI,CAAC,CAAC;gBAClF,CAAC;qBAAM,CAAC;oBACN,uCAAuC;oBACvC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,oBAAoB,EAAE,KAAK,UAAU,EAAE,CAAC,CAAC;gBACxE,CAAC;gBAED,qDAAqD;gBACrD,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YAC7B,CAAC;iBAAM,CAAC;gBACN,uDAAuD;gBACvD,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,IAAI,GAAS;IACxB,IAAI;IACJ,WAAW;IACX,GAAG;CACJ,CAAC;AAEF,eAAe,IAAI,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Rule } from './rule-interface';
|
|
2
|
+
/**
|
|
3
|
+
* MD025: Multiple top-level headings in the same document
|
|
4
|
+
*
|
|
5
|
+
* This rule is triggered when a document has multiple top-level headings (h1).
|
|
6
|
+
* A top-level heading is a heading with level 1, created using:
|
|
7
|
+
* - # Heading (atx style)
|
|
8
|
+
* - Heading
|
|
9
|
+
* ======= (setext style)
|
|
10
|
+
*
|
|
11
|
+
* Having a single h1 heading is recommended for accessibility and SEO reasons.
|
|
12
|
+
*/
|
|
13
|
+
export declare const name = "MD025";
|
|
14
|
+
export declare const description = "Multiple top-level headings in the same document";
|
|
15
|
+
/**
|
|
16
|
+
* Configuration options for MD025
|
|
17
|
+
*/
|
|
18
|
+
interface MD025Config {
|
|
19
|
+
level?: number;
|
|
20
|
+
front_matter_title?: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Fixes markdown content to ensure there's only one top-level heading
|
|
24
|
+
* @param lines Array of string lines to fix
|
|
25
|
+
* @param config Optional configuration object
|
|
26
|
+
* @returns Fixed lines array with only one top-level heading
|
|
27
|
+
*/
|
|
28
|
+
export declare function fix(lines: string[], _config?: MD025Config): string[];
|
|
29
|
+
/**
|
|
30
|
+
* Rule implementation for MD025
|
|
31
|
+
*/
|
|
32
|
+
export declare const rule: Rule;
|
|
33
|
+
export default rule;
|
|
34
|
+
//# sourceMappingURL=md025.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"md025.d.ts","sourceRoot":"","sources":["../../src/rules/md025.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAGxC;;;;;;;;;;GAUG;AACH,eAAO,MAAM,IAAI,UAAU,CAAC;AAC5B,eAAO,MAAM,WAAW,qDAAqD,CAAC;AAE9E;;GAEG;AACH,UAAU,WAAW;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;GAKG;AACH,wBAAgB,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,MAAM,EAAE,CA4HpE;AAED;;GAEG;AAEH,eAAO,MAAM,IAAI,EAAE,IAIlB,CAAC;AAEF,eAAe,IAAI,CAAC"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { hasFrontMatterTitle } from '../utils/safe-match';
|
|
2
|
+
/**
|
|
3
|
+
* MD025: Multiple top-level headings in the same document
|
|
4
|
+
*
|
|
5
|
+
* This rule is triggered when a document has multiple top-level headings (h1).
|
|
6
|
+
* A top-level heading is a heading with level 1, created using:
|
|
7
|
+
* - # Heading (atx style)
|
|
8
|
+
* - Heading
|
|
9
|
+
* ======= (setext style)
|
|
10
|
+
*
|
|
11
|
+
* Having a single h1 heading is recommended for accessibility and SEO reasons.
|
|
12
|
+
*/
|
|
13
|
+
export const name = 'MD025';
|
|
14
|
+
export const description = 'Multiple top-level headings in the same document';
|
|
15
|
+
/**
|
|
16
|
+
* Fixes markdown content to ensure there's only one top-level heading
|
|
17
|
+
* @param lines Array of string lines to fix
|
|
18
|
+
* @param config Optional configuration object
|
|
19
|
+
* @returns Fixed lines array with only one top-level heading
|
|
20
|
+
*/
|
|
21
|
+
export function fix(lines, _config) {
|
|
22
|
+
if (lines.length === 0)
|
|
23
|
+
return lines;
|
|
24
|
+
// Default configuration
|
|
25
|
+
const levelToRestrict = _config?.level || 1;
|
|
26
|
+
const frontMatterTitlePattern = _config?.front_matter_title;
|
|
27
|
+
const result = [...lines];
|
|
28
|
+
let firstTopLevelHeadingIndex = -1;
|
|
29
|
+
let frontMatterHasTitle = false;
|
|
30
|
+
// Check if front matter has a title
|
|
31
|
+
if (lines.length > 0 && lines[0] === '---') {
|
|
32
|
+
for (let i = 1; i < lines.length; i++) {
|
|
33
|
+
if (lines[i] === '---' || lines[i] === '...') {
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
if (hasFrontMatterTitle(lines[i], frontMatterTitlePattern)) {
|
|
37
|
+
frontMatterHasTitle = true;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// Helper to extract heading level from a line
|
|
42
|
+
function getHeadingLevel(line, nextLine) {
|
|
43
|
+
// Check for ATX style heading (# Heading)
|
|
44
|
+
const atxMatch = line.match(/^(#{1,6})\s+/);
|
|
45
|
+
if (atxMatch) {
|
|
46
|
+
return atxMatch[1].length;
|
|
47
|
+
}
|
|
48
|
+
// Check for Setext style heading (Heading ======)
|
|
49
|
+
if (nextLine && /^=+\s*$/.test(nextLine)) {
|
|
50
|
+
return 1; // Level 1 heading (===)
|
|
51
|
+
}
|
|
52
|
+
if (nextLine && /^-+\s*$/.test(nextLine)) {
|
|
53
|
+
return 2; // Level 2 heading (---)
|
|
54
|
+
}
|
|
55
|
+
return 0; // Not a heading
|
|
56
|
+
}
|
|
57
|
+
// Helper to change a heading's level
|
|
58
|
+
function changeHeadingLevel(line, currentLevel, newLevel, nextLine) {
|
|
59
|
+
const updatedLines = [];
|
|
60
|
+
// ATX style heading (# Heading)
|
|
61
|
+
if (/^#{1,6}\s+/.test(line)) {
|
|
62
|
+
// Extract content without the heading marks
|
|
63
|
+
const content = line.replace(/^#{1,6}\s+/, '').replace(/\s+#{1,6}$/, '');
|
|
64
|
+
// Create new heading with desired level
|
|
65
|
+
updatedLines.push('#'.repeat(newLevel) + ' ' + content);
|
|
66
|
+
}
|
|
67
|
+
// Setext style heading (Heading ======)
|
|
68
|
+
else if (nextLine && (/^=+\s*$/.test(nextLine) || /^-+\s*$/.test(nextLine))) {
|
|
69
|
+
if (newLevel <= 2) {
|
|
70
|
+
// Convert to another setext style
|
|
71
|
+
updatedLines.push(line);
|
|
72
|
+
updatedLines.push(newLevel === 1 ? '='.repeat(line.length) : '-'.repeat(line.length));
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
// Convert to ATX style for levels > 2
|
|
76
|
+
updatedLines.push('#'.repeat(newLevel) + ' ' + line);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return updatedLines;
|
|
80
|
+
}
|
|
81
|
+
// First pass: find the first top-level heading
|
|
82
|
+
for (let i = 0; i < lines.length; i++) {
|
|
83
|
+
const line = lines[i];
|
|
84
|
+
const nextLine = i < lines.length - 1 ? lines[i + 1] : undefined;
|
|
85
|
+
const level = getHeadingLevel(line, nextLine);
|
|
86
|
+
if (level === levelToRestrict) {
|
|
87
|
+
// If we should respect front matter title and one exists, demote all headings
|
|
88
|
+
if (frontMatterHasTitle) {
|
|
89
|
+
const updatedLines = changeHeadingLevel(line, level, level + 1, nextLine);
|
|
90
|
+
// Replace the current line(s)
|
|
91
|
+
result[i] = updatedLines[0];
|
|
92
|
+
if (updatedLines.length > 1 && nextLine) {
|
|
93
|
+
result[i + 1] = updatedLines[1];
|
|
94
|
+
}
|
|
95
|
+
// Skip the next line if it was a setext underline
|
|
96
|
+
if (/^[=\-]+\s*$/.test(nextLine || '')) {
|
|
97
|
+
i++;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// Otherwise, find the first top-level heading and demote subsequent ones
|
|
101
|
+
else if (firstTopLevelHeadingIndex === -1) {
|
|
102
|
+
firstTopLevelHeadingIndex = i;
|
|
103
|
+
// Skip the next line if it was a setext underline
|
|
104
|
+
if (/^[=\-]+\s*$/.test(nextLine || '')) {
|
|
105
|
+
i++;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
// Demote this heading since it's not the first one
|
|
110
|
+
const updatedLines = changeHeadingLevel(line, level, level + 1, nextLine);
|
|
111
|
+
// Replace the current line(s)
|
|
112
|
+
result[i] = updatedLines[0];
|
|
113
|
+
if (updatedLines.length > 1 && nextLine) {
|
|
114
|
+
result[i + 1] = updatedLines[1];
|
|
115
|
+
}
|
|
116
|
+
// Skip the next line if it was a setext underline
|
|
117
|
+
if (/^[=\-]+\s*$/.test(nextLine || '')) {
|
|
118
|
+
i++;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return result;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Rule implementation for MD025
|
|
127
|
+
*/
|
|
128
|
+
export const rule = {
|
|
129
|
+
name,
|
|
130
|
+
description,
|
|
131
|
+
fix,
|
|
132
|
+
};
|
|
133
|
+
export default rule;
|
|
134
|
+
//# sourceMappingURL=md025.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"md025.js","sourceRoot":"","sources":["../../src/rules/md025.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Rule } from './rule-interface';
|
|
2
|
+
/**
|
|
3
|
+
* MD026: Trailing punctuation in heading
|
|
4
|
+
*
|
|
5
|
+
* This rule is triggered when headings end with punctuation characters (.,;:!?).
|
|
6
|
+
* The punctuation characters are typically unnecessary and don't add value to the heading.
|
|
7
|
+
*/
|
|
8
|
+
export declare const name = "MD026";
|
|
9
|
+
export declare const description = "Trailing punctuation in heading";
|
|
10
|
+
/**
|
|
11
|
+
* Fix headings with trailing punctuation by removing it
|
|
12
|
+
* @param lines Array of string lines to fix
|
|
13
|
+
* @returns Fixed lines array with heading punctuation removed
|
|
14
|
+
*/
|
|
15
|
+
export declare function fix(lines: string[]): string[];
|
|
16
|
+
/**
|
|
17
|
+
* Rule implementation for MD026
|
|
18
|
+
*/
|
|
19
|
+
export declare const rule: Rule;
|
|
20
|
+
export default rule;
|
|
21
|
+
//# sourceMappingURL=md026.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"md026.d.ts","sourceRoot":"","sources":["../../src/rules/md026.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAExC;;;;;GAKG;AACH,eAAO,MAAM,IAAI,UAAU,CAAC;AAC5B,eAAO,MAAM,WAAW,oCAAoC,CAAC;AAE7D;;;;GAIG;AACH,wBAAgB,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAO7C;AAED;;GAEG;AACH,eAAO,MAAM,IAAI,EAAE,IAIlB,CAAC;AAEF,eAAe,IAAI,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MD026: Trailing punctuation in heading
|
|
3
|
+
*
|
|
4
|
+
* This rule is triggered when headings end with punctuation characters (.,;:!?).
|
|
5
|
+
* The punctuation characters are typically unnecessary and don't add value to the heading.
|
|
6
|
+
*/
|
|
7
|
+
export const name = 'MD026';
|
|
8
|
+
export const description = 'Trailing punctuation in heading';
|
|
9
|
+
/**
|
|
10
|
+
* Fix headings with trailing punctuation by removing it
|
|
11
|
+
* @param lines Array of string lines to fix
|
|
12
|
+
* @returns Fixed lines array with heading punctuation removed
|
|
13
|
+
*/
|
|
14
|
+
export function fix(lines) {
|
|
15
|
+
return lines.map(line => {
|
|
16
|
+
if (/^#{1,6}\s+.+$/.test(line)) {
|
|
17
|
+
return line.replace(/^(#{1,6}\s+.+?)[.,;:!?]+(\s*#*\s*)$/, '$1$2');
|
|
18
|
+
}
|
|
19
|
+
return line;
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Rule implementation for MD026
|
|
24
|
+
*/
|
|
25
|
+
export const rule = {
|
|
26
|
+
name,
|
|
27
|
+
description,
|
|
28
|
+
fix,
|
|
29
|
+
};
|
|
30
|
+
export default rule;
|
|
31
|
+
//# sourceMappingURL=md026.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"md026.js","sourceRoot":"","sources":["../../src/rules/md026.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,OAAO,CAAC;AAC5B,MAAM,CAAC,MAAM,WAAW,GAAG,iCAAiC,CAAC;AAE7D;;;;GAIG;AACH,MAAM,UAAU,GAAG,CAAC,KAAe;IACjC,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;QACtB,IAAI,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/B,OAAO,IAAI,CAAC,OAAO,CAAC,qCAAqC,EAAE,MAAM,CAAC,CAAC;QACrE,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,IAAI,GAAS;IACxB,IAAI;IACJ,WAAW;IACX,GAAG;CACJ,CAAC;AAEF,eAAe,IAAI,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Rule } from './rule-interface';
|
|
2
|
+
/**
|
|
3
|
+
* MD027: Multiple spaces after blockquote symbol
|
|
4
|
+
*
|
|
5
|
+
* This rule is triggered when blockquotes have more than one space after the
|
|
6
|
+
* blockquote marker (>). According to the CommonMark spec, only one space is
|
|
7
|
+
* required after the blockquote marker.
|
|
8
|
+
*/
|
|
9
|
+
export declare const name = "MD027";
|
|
10
|
+
export declare const description = "Multiple spaces after blockquote symbol";
|
|
11
|
+
/**
|
|
12
|
+
* Fix blockquotes with too many spaces after the blockquote symbol
|
|
13
|
+
* @param lines Array of string lines to fix
|
|
14
|
+
* @returns Fixed lines array with proper spacing after blockquote symbols
|
|
15
|
+
*/
|
|
16
|
+
export declare function fix(lines: string[]): string[];
|
|
17
|
+
/**
|
|
18
|
+
* Rule implementation for MD027
|
|
19
|
+
*/
|
|
20
|
+
export declare const rule: Rule;
|
|
21
|
+
export default rule;
|
|
22
|
+
//# sourceMappingURL=md027.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"md027.d.ts","sourceRoot":"","sources":["../../src/rules/md027.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAExC;;;;;;GAMG;AACH,eAAO,MAAM,IAAI,UAAU,CAAC;AAC5B,eAAO,MAAM,WAAW,4CAA4C,CAAC;AAErE;;;;GAIG;AACH,wBAAgB,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAE7C;AAED;;GAEG;AACH,eAAO,MAAM,IAAI,EAAE,IAIlB,CAAC;AAEF,eAAe,IAAI,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MD027: Multiple spaces after blockquote symbol
|
|
3
|
+
*
|
|
4
|
+
* This rule is triggered when blockquotes have more than one space after the
|
|
5
|
+
* blockquote marker (>). According to the CommonMark spec, only one space is
|
|
6
|
+
* required after the blockquote marker.
|
|
7
|
+
*/
|
|
8
|
+
export const name = 'MD027';
|
|
9
|
+
export const description = 'Multiple spaces after blockquote symbol';
|
|
10
|
+
/**
|
|
11
|
+
* Fix blockquotes with too many spaces after the blockquote symbol
|
|
12
|
+
* @param lines Array of string lines to fix
|
|
13
|
+
* @returns Fixed lines array with proper spacing after blockquote symbols
|
|
14
|
+
*/
|
|
15
|
+
export function fix(lines) {
|
|
16
|
+
return lines.map(line => line.replace(/^(\s*>)\s{2,}(.*)$/, '$1 $2'));
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Rule implementation for MD027
|
|
20
|
+
*/
|
|
21
|
+
export const rule = {
|
|
22
|
+
name,
|
|
23
|
+
description,
|
|
24
|
+
fix,
|
|
25
|
+
};
|
|
26
|
+
export default rule;
|
|
27
|
+
//# sourceMappingURL=md027.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"md027.js","sourceRoot":"","sources":["../../src/rules/md027.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,OAAO,CAAC;AAC5B,MAAM,CAAC,MAAM,WAAW,GAAG,yCAAyC,CAAC;AAErE;;;;GAIG;AACH,MAAM,UAAU,GAAG,CAAC,KAAe;IACjC,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,oBAAoB,EAAE,OAAO,CAAC,CAAC,CAAC;AACxE,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,IAAI,GAAS;IACxB,IAAI;IACJ,WAAW;IACX,GAAG;CACJ,CAAC;AAEF,eAAe,IAAI,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Rule, RuleViolation } from './rule-interface';
|
|
2
|
+
/**
|
|
3
|
+
* MD028: Blank line inside blockquote
|
|
4
|
+
*
|
|
5
|
+
* This rule is triggered when two blockquote blocks are separated by a blank line.
|
|
6
|
+
* Some Markdown parsers will treat these as the same blockquote, while others
|
|
7
|
+
* will treat them as separate blockquotes. To ensure consistent rendering,
|
|
8
|
+
* either add content between the blockquotes or add the blockquote symbol to
|
|
9
|
+
* the blank line.
|
|
10
|
+
*
|
|
11
|
+
* Note: This rule is detection-only and doesn't provide automatic fixes
|
|
12
|
+
* since fixing requires knowing the author's intention.
|
|
13
|
+
*/
|
|
14
|
+
export declare const name = "MD028";
|
|
15
|
+
export declare const description = "Blank line inside blockquote";
|
|
16
|
+
/**
|
|
17
|
+
* Validate function to detect blank lines inside blockquotes
|
|
18
|
+
* @param lines Array of string lines to validate
|
|
19
|
+
* @param config Optional rule configuration
|
|
20
|
+
* @returns Array of rule violations
|
|
21
|
+
*/
|
|
22
|
+
export declare function validate(lines: string[], _config?: unknown): RuleViolation[];
|
|
23
|
+
/**
|
|
24
|
+
* Fix function for MD028
|
|
25
|
+
* Since resolving blank lines in blockquotes requires understanding
|
|
26
|
+
* the author's intention (whether it should be one blockquote or two),
|
|
27
|
+
* this rule only detects the issue and doesn't automatically fix it.
|
|
28
|
+
* @param lines Array of string lines to check
|
|
29
|
+
* @returns Original lines array unchanged
|
|
30
|
+
*/
|
|
31
|
+
export declare function fix(lines: string[]): string[];
|
|
32
|
+
/**
|
|
33
|
+
* Rule implementation for MD028
|
|
34
|
+
*/
|
|
35
|
+
export declare const rule: Rule;
|
|
36
|
+
export default rule;
|
|
37
|
+
//# sourceMappingURL=md028.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"md028.d.ts","sourceRoot":"","sources":["../../src/rules/md028.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEvD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,IAAI,UAAU,CAAC;AAC5B,eAAO,MAAM,WAAW,iCAAiC,CAAC;AAE1D;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,aAAa,EAAE,CA4C5E;AAED;;;;;;;GAOG;AACH,wBAAgB,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAG7C;AAED;;GAEG;AACH,eAAO,MAAM,IAAI,EAAE,IAKlB,CAAC;AAEF,eAAe,IAAI,CAAC"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MD028: Blank line inside blockquote
|
|
3
|
+
*
|
|
4
|
+
* This rule is triggered when two blockquote blocks are separated by a blank line.
|
|
5
|
+
* Some Markdown parsers will treat these as the same blockquote, while others
|
|
6
|
+
* will treat them as separate blockquotes. To ensure consistent rendering,
|
|
7
|
+
* either add content between the blockquotes or add the blockquote symbol to
|
|
8
|
+
* the blank line.
|
|
9
|
+
*
|
|
10
|
+
* Note: This rule is detection-only and doesn't provide automatic fixes
|
|
11
|
+
* since fixing requires knowing the author's intention.
|
|
12
|
+
*/
|
|
13
|
+
export const name = 'MD028';
|
|
14
|
+
export const description = 'Blank line inside blockquote';
|
|
15
|
+
/**
|
|
16
|
+
* Validate function to detect blank lines inside blockquotes
|
|
17
|
+
* @param lines Array of string lines to validate
|
|
18
|
+
* @param config Optional rule configuration
|
|
19
|
+
* @returns Array of rule violations
|
|
20
|
+
*/
|
|
21
|
+
export function validate(lines, _config) {
|
|
22
|
+
const violations = [];
|
|
23
|
+
// Track blockquote state
|
|
24
|
+
let inBlockquote = false;
|
|
25
|
+
let lastBlockquoteLine = -1;
|
|
26
|
+
for (let i = 0; i < lines.length; i++) {
|
|
27
|
+
const line = lines[i];
|
|
28
|
+
const trimmedLine = line.trim();
|
|
29
|
+
// Check if current line is a blockquote
|
|
30
|
+
const isBlockquoteLine = trimmedLine.startsWith('>');
|
|
31
|
+
if (isBlockquoteLine) {
|
|
32
|
+
// If we're starting a new blockquote after a blank line
|
|
33
|
+
if (inBlockquote && i > lastBlockquoteLine + 1) {
|
|
34
|
+
// Check if there's a blank line between blockquotes
|
|
35
|
+
for (let j = lastBlockquoteLine + 1; j < i; j++) {
|
|
36
|
+
const intermediateLine = lines[j];
|
|
37
|
+
// Only treat truly empty lines as blank lines, not whitespace-only lines
|
|
38
|
+
if (intermediateLine === '') {
|
|
39
|
+
// Found a blank line between blockquotes
|
|
40
|
+
violations.push({
|
|
41
|
+
lineNumber: j + 1,
|
|
42
|
+
details: 'Blank line inside blockquote',
|
|
43
|
+
range: [0, intermediateLine.length],
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
inBlockquote = true;
|
|
49
|
+
lastBlockquoteLine = i;
|
|
50
|
+
}
|
|
51
|
+
else if (trimmedLine === '') {
|
|
52
|
+
// Empty line - continue tracking
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
// Non-blockquote, non-empty line - end blockquote tracking
|
|
57
|
+
inBlockquote = false;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return violations;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Fix function for MD028
|
|
64
|
+
* Since resolving blank lines in blockquotes requires understanding
|
|
65
|
+
* the author's intention (whether it should be one blockquote or two),
|
|
66
|
+
* this rule only detects the issue and doesn't automatically fix it.
|
|
67
|
+
* @param lines Array of string lines to check
|
|
68
|
+
* @returns Original lines array unchanged
|
|
69
|
+
*/
|
|
70
|
+
export function fix(lines) {
|
|
71
|
+
// This rule is detection-only, so we return the lines unchanged
|
|
72
|
+
return [...lines];
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Rule implementation for MD028
|
|
76
|
+
*/
|
|
77
|
+
export const rule = {
|
|
78
|
+
name,
|
|
79
|
+
description,
|
|
80
|
+
validate,
|
|
81
|
+
fix,
|
|
82
|
+
};
|
|
83
|
+
export default rule;
|
|
84
|
+
//# sourceMappingURL=md028.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"md028.js","sourceRoot":"","sources":["../../src/rules/md028.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,OAAO,CAAC;AAC5B,MAAM,CAAC,MAAM,WAAW,GAAG,8BAA8B,CAAC;AAE1D;;;;;GAKG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAe,EAAE,OAAiB;IACzD,MAAM,UAAU,GAAoB,EAAE,CAAC;IAEvC,yBAAyB;IACzB,IAAI,YAAY,GAAG,KAAK,CAAC;IACzB,IAAI,kBAAkB,GAAG,CAAC,CAAC,CAAC;IAE5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAEhC,wCAAwC;QACxC,MAAM,gBAAgB,GAAG,WAAW,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QAErD,IAAI,gBAAgB,EAAE,CAAC;YACrB,wDAAwD;YACxD,IAAI,YAAY,IAAI,CAAC,GAAG,kBAAkB,GAAG,CAAC,EAAE,CAAC;gBAC/C,oDAAoD;gBACpD,KAAK,IAAI,CAAC,GAAG,kBAAkB,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;oBAChD,MAAM,gBAAgB,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;oBAClC,yEAAyE;oBACzE,IAAI,gBAAgB,KAAK,EAAE,EAAE,CAAC;wBAC5B,yCAAyC;wBACzC,UAAU,CAAC,IAAI,CAAC;4BACd,UAAU,EAAE,CAAC,GAAG,CAAC;4BACjB,OAAO,EAAE,8BAA8B;4BACvC,KAAK,EAAE,CAAC,CAAC,EAAE,gBAAgB,CAAC,MAAM,CAAC;yBACpC,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;YACH,CAAC;YAED,YAAY,GAAG,IAAI,CAAC;YACpB,kBAAkB,GAAG,CAAC,CAAC;QACzB,CAAC;aAAM,IAAI,WAAW,KAAK,EAAE,EAAE,CAAC;YAC9B,iCAAiC;YACjC,SAAS;QACX,CAAC;aAAM,CAAC;YACN,2DAA2D;YAC3D,YAAY,GAAG,KAAK,CAAC;QACvB,CAAC;IACH,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,GAAG,CAAC,KAAe;IACjC,gEAAgE;IAChE,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC;AACpB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,IAAI,GAAS;IACxB,IAAI;IACJ,WAAW;IACX,QAAQ;IACR,GAAG;CACJ,CAAC;AAEF,eAAe,IAAI,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Rule } from './rule-interface';
|
|
2
|
+
/**
|
|
3
|
+
* MD029: Ordered list item prefix
|
|
4
|
+
*
|
|
5
|
+
* This rule is triggered when ordered lists don't use the specified prefix style.
|
|
6
|
+
* The rule supports several different styles:
|
|
7
|
+
* - 'one': All items use '1.' as the prefix
|
|
8
|
+
* - 'ordered': Items use increasing numbers ('1.', '2.', etc.)
|
|
9
|
+
* - 'one_or_ordered': Items use either all '1.' or increasing numbers
|
|
10
|
+
* - 'zero': All items use '0.' as the prefix
|
|
11
|
+
*
|
|
12
|
+
* Note: This rule is detection-only and doesn't provide automatic fixes
|
|
13
|
+
* because it's hard to automatically determine the correct style.
|
|
14
|
+
*/
|
|
15
|
+
export declare const name = "MD029";
|
|
16
|
+
export declare const description = "Ordered list item prefix";
|
|
17
|
+
/**
|
|
18
|
+
* Fix function for MD029
|
|
19
|
+
* Since fixing ordered list numbering requires knowing the preferred style,
|
|
20
|
+
* this rule only detects the issue and doesn't automatically fix it.
|
|
21
|
+
* @param lines Array of string lines to check
|
|
22
|
+
* @returns Original lines array unchanged
|
|
23
|
+
*/
|
|
24
|
+
export declare function fix(lines: string[]): string[];
|
|
25
|
+
/**
|
|
26
|
+
* Rule implementation for MD029
|
|
27
|
+
*/
|
|
28
|
+
export declare const rule: Rule;
|
|
29
|
+
export default rule;
|
|
30
|
+
//# sourceMappingURL=md029.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"md029.d.ts","sourceRoot":"","sources":["../../src/rules/md029.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAExC;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,IAAI,UAAU,CAAC;AAC5B,eAAO,MAAM,WAAW,6BAA6B,CAAC;AAEtD;;;;;;GAMG;AACH,wBAAgB,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAG7C;AAED;;GAEG;AACH,eAAO,MAAM,IAAI,EAAE,IAIlB,CAAC;AAEF,eAAe,IAAI,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MD029: Ordered list item prefix
|
|
3
|
+
*
|
|
4
|
+
* This rule is triggered when ordered lists don't use the specified prefix style.
|
|
5
|
+
* The rule supports several different styles:
|
|
6
|
+
* - 'one': All items use '1.' as the prefix
|
|
7
|
+
* - 'ordered': Items use increasing numbers ('1.', '2.', etc.)
|
|
8
|
+
* - 'one_or_ordered': Items use either all '1.' or increasing numbers
|
|
9
|
+
* - 'zero': All items use '0.' as the prefix
|
|
10
|
+
*
|
|
11
|
+
* Note: This rule is detection-only and doesn't provide automatic fixes
|
|
12
|
+
* because it's hard to automatically determine the correct style.
|
|
13
|
+
*/
|
|
14
|
+
export const name = 'MD029';
|
|
15
|
+
export const description = 'Ordered list item prefix';
|
|
16
|
+
/**
|
|
17
|
+
* Fix function for MD029
|
|
18
|
+
* Since fixing ordered list numbering requires knowing the preferred style,
|
|
19
|
+
* this rule only detects the issue and doesn't automatically fix it.
|
|
20
|
+
* @param lines Array of string lines to check
|
|
21
|
+
* @returns Original lines array unchanged
|
|
22
|
+
*/
|
|
23
|
+
export function fix(lines) {
|
|
24
|
+
// This rule is detection-only, so we return the lines unchanged
|
|
25
|
+
return [...lines];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Rule implementation for MD029
|
|
29
|
+
*/
|
|
30
|
+
export const rule = {
|
|
31
|
+
name,
|
|
32
|
+
description,
|
|
33
|
+
fix,
|
|
34
|
+
};
|
|
35
|
+
export default rule;
|
|
36
|
+
//# sourceMappingURL=md029.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"md029.js","sourceRoot":"","sources":["../../src/rules/md029.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,OAAO,CAAC;AAC5B,MAAM,CAAC,MAAM,WAAW,GAAG,0BAA0B,CAAC;AAEtD;;;;;;GAMG;AACH,MAAM,UAAU,GAAG,CAAC,KAAe;IACjC,gEAAgE;IAChE,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC;AACpB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,IAAI,GAAS;IACxB,IAAI;IACJ,WAAW;IACX,GAAG;CACJ,CAAC;AAEF,eAAe,IAAI,CAAC"}
|