@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.
Files changed (246) hide show
  1. package/CHANGELOG.md +80 -0
  2. package/CONTRIBUTING.md +474 -0
  3. package/LICENSE +21 -0
  4. package/README.md +240 -0
  5. package/USAGE.md +40 -0
  6. package/dist/index.d.ts +3 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +39 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/rules/index.d.ts +22 -0
  11. package/dist/rules/index.d.ts.map +1 -0
  12. package/dist/rules/index.js +144 -0
  13. package/dist/rules/index.js.map +1 -0
  14. package/dist/rules/md001.d.ts +25 -0
  15. package/dist/rules/md001.d.ts.map +1 -0
  16. package/dist/rules/md001.js +79 -0
  17. package/dist/rules/md001.js.map +1 -0
  18. package/dist/rules/md003.d.ts +41 -0
  19. package/dist/rules/md003.d.ts.map +1 -0
  20. package/dist/rules/md003.js +130 -0
  21. package/dist/rules/md003.js.map +1 -0
  22. package/dist/rules/md004.d.ts +28 -0
  23. package/dist/rules/md004.d.ts.map +1 -0
  24. package/dist/rules/md004.js +79 -0
  25. package/dist/rules/md004.js.map +1 -0
  26. package/dist/rules/md005.d.ts +21 -0
  27. package/dist/rules/md005.d.ts.map +1 -0
  28. package/dist/rules/md005.js +88 -0
  29. package/dist/rules/md005.js.map +1 -0
  30. package/dist/rules/md007.d.ts +21 -0
  31. package/dist/rules/md007.d.ts.map +1 -0
  32. package/dist/rules/md007.js +66 -0
  33. package/dist/rules/md007.js.map +1 -0
  34. package/dist/rules/md009.d.ts +35 -0
  35. package/dist/rules/md009.d.ts.map +1 -0
  36. package/dist/rules/md009.js +122 -0
  37. package/dist/rules/md009.js.map +1 -0
  38. package/dist/rules/md010.d.ts +34 -0
  39. package/dist/rules/md010.d.ts.map +1 -0
  40. package/dist/rules/md010.js +75 -0
  41. package/dist/rules/md010.js.map +1 -0
  42. package/dist/rules/md011.d.ts +30 -0
  43. package/dist/rules/md011.d.ts.map +1 -0
  44. package/dist/rules/md011.js +123 -0
  45. package/dist/rules/md011.js.map +1 -0
  46. package/dist/rules/md012.d.ts +33 -0
  47. package/dist/rules/md012.d.ts.map +1 -0
  48. package/dist/rules/md012.js +125 -0
  49. package/dist/rules/md012.js.map +1 -0
  50. package/dist/rules/md013.d.ts +26 -0
  51. package/dist/rules/md013.d.ts.map +1 -0
  52. package/dist/rules/md013.js +32 -0
  53. package/dist/rules/md013.js.map +1 -0
  54. package/dist/rules/md014.d.ts +29 -0
  55. package/dist/rules/md014.d.ts.map +1 -0
  56. package/dist/rules/md014.js +176 -0
  57. package/dist/rules/md014.js.map +1 -0
  58. package/dist/rules/md018.d.ts +22 -0
  59. package/dist/rules/md018.d.ts.map +1 -0
  60. package/dist/rules/md018.js +27 -0
  61. package/dist/rules/md018.js.map +1 -0
  62. package/dist/rules/md019.d.ts +22 -0
  63. package/dist/rules/md019.d.ts.map +1 -0
  64. package/dist/rules/md019.js +27 -0
  65. package/dist/rules/md019.js.map +1 -0
  66. package/dist/rules/md020.d.ts +22 -0
  67. package/dist/rules/md020.d.ts.map +1 -0
  68. package/dist/rules/md020.js +27 -0
  69. package/dist/rules/md020.js.map +1 -0
  70. package/dist/rules/md021.d.ts +22 -0
  71. package/dist/rules/md021.d.ts.map +1 -0
  72. package/dist/rules/md021.js +27 -0
  73. package/dist/rules/md021.js.map +1 -0
  74. package/dist/rules/md022.d.ts +21 -0
  75. package/dist/rules/md022.d.ts.map +1 -0
  76. package/dist/rules/md022.js +43 -0
  77. package/dist/rules/md022.js.map +1 -0
  78. package/dist/rules/md023.d.ts +21 -0
  79. package/dist/rules/md023.d.ts.map +1 -0
  80. package/dist/rules/md023.js +34 -0
  81. package/dist/rules/md023.js.map +1 -0
  82. package/dist/rules/md024.d.ts +30 -0
  83. package/dist/rules/md024.d.ts.map +1 -0
  84. package/dist/rules/md024.js +123 -0
  85. package/dist/rules/md024.js.map +1 -0
  86. package/dist/rules/md025.d.ts +34 -0
  87. package/dist/rules/md025.d.ts.map +1 -0
  88. package/dist/rules/md025.js +134 -0
  89. package/dist/rules/md025.js.map +1 -0
  90. package/dist/rules/md026.d.ts +21 -0
  91. package/dist/rules/md026.d.ts.map +1 -0
  92. package/dist/rules/md026.js +31 -0
  93. package/dist/rules/md026.js.map +1 -0
  94. package/dist/rules/md027.d.ts +22 -0
  95. package/dist/rules/md027.d.ts.map +1 -0
  96. package/dist/rules/md027.js +27 -0
  97. package/dist/rules/md027.js.map +1 -0
  98. package/dist/rules/md028.d.ts +37 -0
  99. package/dist/rules/md028.d.ts.map +1 -0
  100. package/dist/rules/md028.js +84 -0
  101. package/dist/rules/md028.js.map +1 -0
  102. package/dist/rules/md029.d.ts +30 -0
  103. package/dist/rules/md029.d.ts.map +1 -0
  104. package/dist/rules/md029.js +36 -0
  105. package/dist/rules/md029.js.map +1 -0
  106. package/dist/rules/md030.d.ts +28 -0
  107. package/dist/rules/md030.d.ts.map +1 -0
  108. package/dist/rules/md030.js +76 -0
  109. package/dist/rules/md030.js.map +1 -0
  110. package/dist/rules/md031.d.ts +22 -0
  111. package/dist/rules/md031.d.ts.map +1 -0
  112. package/dist/rules/md031.js +55 -0
  113. package/dist/rules/md031.js.map +1 -0
  114. package/dist/rules/md032.d.ts +21 -0
  115. package/dist/rules/md032.d.ts.map +1 -0
  116. package/dist/rules/md032.js +69 -0
  117. package/dist/rules/md032.js.map +1 -0
  118. package/dist/rules/md033.d.ts +28 -0
  119. package/dist/rules/md033.d.ts.map +1 -0
  120. package/dist/rules/md033.js +34 -0
  121. package/dist/rules/md033.js.map +1 -0
  122. package/dist/rules/md034.d.ts +28 -0
  123. package/dist/rules/md034.d.ts.map +1 -0
  124. package/dist/rules/md034.js +100 -0
  125. package/dist/rules/md034.js.map +1 -0
  126. package/dist/rules/md035.d.ts +23 -0
  127. package/dist/rules/md035.d.ts.map +1 -0
  128. package/dist/rules/md035.js +52 -0
  129. package/dist/rules/md035.js.map +1 -0
  130. package/dist/rules/md036.d.ts +34 -0
  131. package/dist/rules/md036.d.ts.map +1 -0
  132. package/dist/rules/md036.js +112 -0
  133. package/dist/rules/md036.js.map +1 -0
  134. package/dist/rules/md037.d.ts +28 -0
  135. package/dist/rules/md037.d.ts.map +1 -0
  136. package/dist/rules/md037.js +122 -0
  137. package/dist/rules/md037.js.map +1 -0
  138. package/dist/rules/md038.d.ts +28 -0
  139. package/dist/rules/md038.d.ts.map +1 -0
  140. package/dist/rules/md038.js +62 -0
  141. package/dist/rules/md038.js.map +1 -0
  142. package/dist/rules/md039.d.ts +21 -0
  143. package/dist/rules/md039.d.ts.map +1 -0
  144. package/dist/rules/md039.js +34 -0
  145. package/dist/rules/md039.js.map +1 -0
  146. package/dist/rules/md040.d.ts +21 -0
  147. package/dist/rules/md040.d.ts.map +1 -0
  148. package/dist/rules/md040.js +46 -0
  149. package/dist/rules/md040.js.map +1 -0
  150. package/dist/rules/md041.d.ts +33 -0
  151. package/dist/rules/md041.d.ts.map +1 -0
  152. package/dist/rules/md041.js +92 -0
  153. package/dist/rules/md041.js.map +1 -0
  154. package/dist/rules/md042.d.ts +22 -0
  155. package/dist/rules/md042.d.ts.map +1 -0
  156. package/dist/rules/md042.js +50 -0
  157. package/dist/rules/md042.js.map +1 -0
  158. package/dist/rules/md043.d.ts +39 -0
  159. package/dist/rules/md043.d.ts.map +1 -0
  160. package/dist/rules/md043.js +116 -0
  161. package/dist/rules/md043.js.map +1 -0
  162. package/dist/rules/md044.d.ts +40 -0
  163. package/dist/rules/md044.d.ts.map +1 -0
  164. package/dist/rules/md044.js +167 -0
  165. package/dist/rules/md044.js.map +1 -0
  166. package/dist/rules/md045.d.ts +22 -0
  167. package/dist/rules/md045.d.ts.map +1 -0
  168. package/dist/rules/md045.js +57 -0
  169. package/dist/rules/md045.js.map +1 -0
  170. package/dist/rules/md046.d.ts +23 -0
  171. package/dist/rules/md046.d.ts.map +1 -0
  172. package/dist/rules/md046.js +174 -0
  173. package/dist/rules/md046.js.map +1 -0
  174. package/dist/rules/md047.d.ts +22 -0
  175. package/dist/rules/md047.d.ts.map +1 -0
  176. package/dist/rules/md047.js +35 -0
  177. package/dist/rules/md047.js.map +1 -0
  178. package/dist/rules/md048.d.ts +22 -0
  179. package/dist/rules/md048.d.ts.map +1 -0
  180. package/dist/rules/md048.js +80 -0
  181. package/dist/rules/md048.js.map +1 -0
  182. package/dist/rules/md049.d.ts +33 -0
  183. package/dist/rules/md049.d.ts.map +1 -0
  184. package/dist/rules/md049.js +189 -0
  185. package/dist/rules/md049.js.map +1 -0
  186. package/dist/rules/md050.d.ts +22 -0
  187. package/dist/rules/md050.d.ts.map +1 -0
  188. package/dist/rules/md050.js +32 -0
  189. package/dist/rules/md050.js.map +1 -0
  190. package/dist/rules/md051.d.ts +23 -0
  191. package/dist/rules/md051.d.ts.map +1 -0
  192. package/dist/rules/md051.js +63 -0
  193. package/dist/rules/md051.js.map +1 -0
  194. package/dist/rules/md052.d.ts +21 -0
  195. package/dist/rules/md052.d.ts.map +1 -0
  196. package/dist/rules/md052.js +71 -0
  197. package/dist/rules/md052.js.map +1 -0
  198. package/dist/rules/md053.d.ts +21 -0
  199. package/dist/rules/md053.d.ts.map +1 -0
  200. package/dist/rules/md053.js +95 -0
  201. package/dist/rules/md053.js.map +1 -0
  202. package/dist/rules/md054.d.ts +21 -0
  203. package/dist/rules/md054.d.ts.map +1 -0
  204. package/dist/rules/md054.js +87 -0
  205. package/dist/rules/md054.js.map +1 -0
  206. package/dist/rules/md055.d.ts +22 -0
  207. package/dist/rules/md055.d.ts.map +1 -0
  208. package/dist/rules/md055.js +157 -0
  209. package/dist/rules/md055.js.map +1 -0
  210. package/dist/rules/md056.d.ts +21 -0
  211. package/dist/rules/md056.d.ts.map +1 -0
  212. package/dist/rules/md056.js +154 -0
  213. package/dist/rules/md056.js.map +1 -0
  214. package/dist/rules/md058.d.ts +27 -0
  215. package/dist/rules/md058.d.ts.map +1 -0
  216. package/dist/rules/md058.js +71 -0
  217. package/dist/rules/md058.js.map +1 -0
  218. package/dist/rules/md059.d.ts +22 -0
  219. package/dist/rules/md059.d.ts.map +1 -0
  220. package/dist/rules/md059.js +161 -0
  221. package/dist/rules/md059.js.map +1 -0
  222. package/dist/rules/rule-interface.d.ts +51 -0
  223. package/dist/rules/rule-interface.d.ts.map +1 -0
  224. package/dist/rules/rule-interface.js +2 -0
  225. package/dist/rules/rule-interface.js.map +1 -0
  226. package/dist/server.d.ts +59 -0
  227. package/dist/server.d.ts.map +1 -0
  228. package/dist/server.js +419 -0
  229. package/dist/server.js.map +1 -0
  230. package/dist/types.d.ts +74 -0
  231. package/dist/types.d.ts.map +1 -0
  232. package/dist/types.js +14 -0
  233. package/dist/types.js.map +1 -0
  234. package/dist/utils/file.d.ts +39 -0
  235. package/dist/utils/file.d.ts.map +1 -0
  236. package/dist/utils/file.js +124 -0
  237. package/dist/utils/file.js.map +1 -0
  238. package/dist/utils/logger.d.ts +61 -0
  239. package/dist/utils/logger.d.ts.map +1 -0
  240. package/dist/utils/logger.js +85 -0
  241. package/dist/utils/logger.js.map +1 -0
  242. package/dist/utils/safe-match.d.ts +4 -0
  243. package/dist/utils/safe-match.d.ts.map +1 -0
  244. package/dist/utils/safe-match.js +51 -0
  245. package/dist/utils/safe-match.js.map +1 -0
  246. 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":"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"}
@@ -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"}