@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,124 @@
1
+ /**
2
+ * File utility functions
3
+ */
4
+ import { promises as fs } from 'fs';
5
+ import path from 'path';
6
+ /**
7
+ * Default markdownlint configuration
8
+ * Used when no custom configuration is found
9
+ */
10
+ const DEFAULT_CONFIG = {
11
+ default: true,
12
+ MD013: { line_length: 120 }, // Allow longer lines for modern displays
13
+ MD033: false, // Allow HTML
14
+ MD041: false, // Allow files to not start with H1
15
+ };
16
+ /**
17
+ * Read a file's content
18
+ * @param filePath Path to the file
19
+ * @returns File content as a string
20
+ * @throws Error if file cannot be read
21
+ */
22
+ export async function readFile(filePath) {
23
+ try {
24
+ // Check if file exists first
25
+ await fs.access(filePath);
26
+ return await fs.readFile(filePath, 'utf8');
27
+ }
28
+ catch (err) {
29
+ if (err &&
30
+ typeof err === 'object' &&
31
+ 'code' in err &&
32
+ err.code === 'ENOENT') {
33
+ throw new Error(`File not found: ${filePath}`);
34
+ }
35
+ throw err;
36
+ }
37
+ }
38
+ /**
39
+ * Write content to a file
40
+ * @param filePath Path to the file
41
+ * @param content Content to write
42
+ * @throws Error if file cannot be written
43
+ */
44
+ export async function writeFile(filePath, content) {
45
+ return await fs.writeFile(filePath, content, 'utf8');
46
+ }
47
+ /**
48
+ * Load markdownlint configuration from file or use defaults
49
+ * @param directory Directory to look for .markdownlint.json
50
+ * @returns Configuration object
51
+ */
52
+ export async function loadConfiguration(directory) {
53
+ // Basic validation
54
+ if (!directory || typeof directory !== 'string' || directory.includes('\0')) {
55
+ return { ...DEFAULT_CONFIG };
56
+ }
57
+ const workspaceRoot = await fs.realpath(process.cwd());
58
+ // Canonicalize path safely without calling path.resolve on raw user input
59
+ let resolvedReal;
60
+ if (path.isAbsolute(directory)) {
61
+ // Absolute paths: canonicalize and ensure they are inside the workspace
62
+ try {
63
+ resolvedReal = await fs.realpath(directory);
64
+ }
65
+ catch {
66
+ return { ...DEFAULT_CONFIG };
67
+ }
68
+ if (resolvedReal !== workspaceRoot && !resolvedReal.startsWith(workspaceRoot + path.sep)) {
69
+ return { ...DEFAULT_CONFIG };
70
+ }
71
+ }
72
+ else {
73
+ // Relative paths: reject suspicious segments and build a safe candidate
74
+ const segments = directory.split(/[\\/]+/).filter(Boolean);
75
+ // Disallow traversal segments or very long paths
76
+ if (segments.some(s => s === '..') || directory.length > 1024) {
77
+ return { ...DEFAULT_CONFIG };
78
+ }
79
+ const candidate = workspaceRoot + path.sep + segments.join(path.sep);
80
+ try {
81
+ resolvedReal = await fs.realpath(candidate);
82
+ }
83
+ catch {
84
+ return { ...DEFAULT_CONFIG };
85
+ }
86
+ if (resolvedReal !== workspaceRoot && !resolvedReal.startsWith(workspaceRoot + path.sep)) {
87
+ return { ...DEFAULT_CONFIG };
88
+ }
89
+ }
90
+ const configPath = path.join(resolvedReal, '.markdownlint.json');
91
+ try {
92
+ await fs.access(configPath);
93
+ const configContent = await fs.readFile(configPath, 'utf8');
94
+ return JSON.parse(configContent);
95
+ }
96
+ catch {
97
+ // Fall back to default configuration if file not found or invalid
98
+ return { ...DEFAULT_CONFIG };
99
+ }
100
+ }
101
+ /**
102
+ * Get the default markdownlint configuration
103
+ * @returns Default configuration object
104
+ */
105
+ export function getDefaultConfig() {
106
+ return { ...DEFAULT_CONFIG };
107
+ }
108
+ /**
109
+ * Convert string content to an array of lines
110
+ * @param content String content to split into lines
111
+ * @returns Array of lines
112
+ */
113
+ export function contentToLines(content) {
114
+ return content.split('\n');
115
+ }
116
+ /**
117
+ * Join an array of lines into a single string
118
+ * @param lines Array of lines to join
119
+ * @returns Joined string
120
+ */
121
+ export function linesToContent(lines) {
122
+ return lines.join('\n');
123
+ }
124
+ //# sourceMappingURL=file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file.js","sourceRoot":"","sources":["../../src/utils/file.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Logger utility for consistent logging throughout the application
3
+ */
4
+ /**
5
+ * Log levels
6
+ */
7
+ export declare enum LogLevel {
8
+ DEBUG = 0,
9
+ INFO = 1,
10
+ WARN = 2,
11
+ ERROR = 3,
12
+ NONE = 4
13
+ }
14
+ /**
15
+ * Set the current log level
16
+ * @param level Log level to set
17
+ */
18
+ export declare function setLogLevel(level: LogLevel): void;
19
+ /**
20
+ * Get the current log level
21
+ * @returns The current log level
22
+ */
23
+ export declare function getLogLevel(): LogLevel;
24
+ /**
25
+ * Log a debug message (only displayed if log level is DEBUG)
26
+ * @param message Message to log
27
+ * @param meta Optional metadata to include
28
+ */
29
+ export declare function debug(message: string, meta?: unknown): void;
30
+ /**
31
+ * Log an info message (displayed if log level is INFO or lower)
32
+ * @param message Message to log
33
+ * @param meta Optional metadata to include
34
+ */
35
+ export declare function info(message: string, meta?: unknown): void;
36
+ /**
37
+ * Log a warning message (displayed if log level is WARN or lower)
38
+ * @param message Message to log
39
+ * @param meta Optional metadata to include
40
+ */
41
+ export declare function warn(message: string, meta?: unknown): void;
42
+ /**
43
+ * Log an error message (displayed if log level is ERROR or lower)
44
+ * @param message Message to log
45
+ * @param error Optional error to include
46
+ */
47
+ export declare function error(message: string, error?: unknown): void;
48
+ /**
49
+ * Default export for the logger
50
+ */
51
+ declare const _default: {
52
+ setLogLevel: typeof setLogLevel;
53
+ getLogLevel: typeof getLogLevel;
54
+ debug: typeof debug;
55
+ info: typeof info;
56
+ warn: typeof warn;
57
+ error: typeof error;
58
+ LogLevel: typeof LogLevel;
59
+ };
60
+ export default _default;
61
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,oBAAY,QAAQ;IAClB,KAAK,IAAI;IACT,IAAI,IAAI;IACR,IAAI,IAAI;IACR,KAAK,IAAI;IACT,IAAI,IAAI;CACT;AAOD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,CAEjD;AAED;;;GAGG;AACH,wBAAgB,WAAW,IAAI,QAAQ,CAEtC;AAED;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAI3D;AAED;;;;GAIG;AACH,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAI1D;AAED;;;;GAIG;AACH,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAI1D;AAED;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,IAAI,CAI5D;AAED;;GAEG;;;;;;;;;;AACH,wBAQE"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Logger utility for consistent logging throughout the application
3
+ */
4
+ /**
5
+ * Log levels
6
+ */
7
+ export var LogLevel;
8
+ (function (LogLevel) {
9
+ LogLevel[LogLevel["DEBUG"] = 0] = "DEBUG";
10
+ LogLevel[LogLevel["INFO"] = 1] = "INFO";
11
+ LogLevel[LogLevel["WARN"] = 2] = "WARN";
12
+ LogLevel[LogLevel["ERROR"] = 3] = "ERROR";
13
+ LogLevel[LogLevel["NONE"] = 4] = "NONE";
14
+ })(LogLevel || (LogLevel = {}));
15
+ /**
16
+ * Current log level (can be changed at runtime)
17
+ */
18
+ let currentLogLevel = LogLevel.INFO;
19
+ /**
20
+ * Set the current log level
21
+ * @param level Log level to set
22
+ */
23
+ export function setLogLevel(level) {
24
+ currentLogLevel = level;
25
+ }
26
+ /**
27
+ * Get the current log level
28
+ * @returns The current log level
29
+ */
30
+ export function getLogLevel() {
31
+ return currentLogLevel;
32
+ }
33
+ /**
34
+ * Log a debug message (only displayed if log level is DEBUG)
35
+ * @param message Message to log
36
+ * @param meta Optional metadata to include
37
+ */
38
+ export function debug(message, meta) {
39
+ if (currentLogLevel <= LogLevel.DEBUG) {
40
+ console.info(`[DEBUG] ${message}`, meta ? meta : '');
41
+ }
42
+ }
43
+ /**
44
+ * Log an info message (displayed if log level is INFO or lower)
45
+ * @param message Message to log
46
+ * @param meta Optional metadata to include
47
+ */
48
+ export function info(message, meta) {
49
+ if (currentLogLevel <= LogLevel.INFO) {
50
+ console.info(`[INFO] ${message}`, meta ? meta : '');
51
+ }
52
+ }
53
+ /**
54
+ * Log a warning message (displayed if log level is WARN or lower)
55
+ * @param message Message to log
56
+ * @param meta Optional metadata to include
57
+ */
58
+ export function warn(message, meta) {
59
+ if (currentLogLevel <= LogLevel.WARN) {
60
+ console.warn(`[WARN] ${message}`, meta ? meta : '');
61
+ }
62
+ }
63
+ /**
64
+ * Log an error message (displayed if log level is ERROR or lower)
65
+ * @param message Message to log
66
+ * @param error Optional error to include
67
+ */
68
+ export function error(message, error) {
69
+ if (currentLogLevel <= LogLevel.ERROR) {
70
+ console.error(`[ERROR] ${message}`, error ? error : '');
71
+ }
72
+ }
73
+ /**
74
+ * Default export for the logger
75
+ */
76
+ export default {
77
+ setLogLevel,
78
+ getLogLevel,
79
+ debug,
80
+ info,
81
+ warn,
82
+ error,
83
+ LogLevel,
84
+ };
85
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,CAAN,IAAY,QAMX;AAND,WAAY,QAAQ;IAClB,yCAAS,CAAA;IACT,uCAAQ,CAAA;IACR,uCAAQ,CAAA;IACR,yCAAS,CAAA;IACT,uCAAQ,CAAA;AACV,CAAC,EANW,QAAQ,KAAR,QAAQ,QAMnB;AAED;;GAEG;AACH,IAAI,eAAe,GAAa,QAAQ,CAAC,IAAI,CAAC;AAE9C;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,KAAe;IACzC,eAAe,GAAG,KAAK,CAAC;AAC1B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW;IACzB,OAAO,eAAe,CAAC;AACzB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,KAAK,CAAC,OAAe,EAAE,IAAc;IACnD,IAAI,eAAe,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;QACtC,OAAO,CAAC,IAAI,CAAC,WAAW,OAAO,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACvD,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,IAAI,CAAC,OAAe,EAAE,IAAc;IAClD,IAAI,eAAe,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;QACrC,OAAO,CAAC,IAAI,CAAC,UAAU,OAAO,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACtD,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,IAAI,CAAC,OAAe,EAAE,IAAc;IAClD,IAAI,eAAe,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;QACrC,OAAO,CAAC,IAAI,CAAC,UAAU,OAAO,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACtD,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,KAAK,CAAC,OAAe,EAAE,KAAe;IACpD,IAAI,eAAe,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;QACtC,OAAO,CAAC,KAAK,CAAC,WAAW,OAAO,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAC1D,CAAC;AACH,CAAC;AAED;;GAEG;AACH,eAAe;IACb,WAAW;IACX,WAAW;IACX,KAAK;IACL,IAAI;IACJ,IAAI;IACJ,KAAK;IACL,QAAQ;CACT,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function findWordMatches(line: string, search: string): number[];
2
+ export declare function hasFrontMatterTitle(line: string, pattern?: string): boolean;
3
+ export declare function endsWithPunctuation(content: string, punctuation?: string): boolean;
4
+ //# sourceMappingURL=safe-match.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safe-match.d.ts","sourceRoot":"","sources":["../../src/utils/safe-match.ts"],"names":[],"mappings":"AAAA,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CA2BtE;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAmB3E;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAOlF"}
@@ -0,0 +1,51 @@
1
+ export function findWordMatches(line, search) {
2
+ const results = [];
3
+ if (!search)
4
+ return results;
5
+ const lowerLine = line.toLowerCase();
6
+ const lowerSearch = search.toLowerCase();
7
+ let start = 0;
8
+ while (true) {
9
+ const idx = lowerLine.indexOf(lowerSearch, start);
10
+ if (idx === -1)
11
+ break;
12
+ // Check boundaries: before and after should not be word characters
13
+ const before = line[idx - 1];
14
+ const after = line[idx + lowerSearch.length];
15
+ const beforeIsWord = before ? /[A-Za-z0-9_]/.test(before) : false;
16
+ const afterIsWord = after ? /[A-Za-z0-9_]/.test(after) : false;
17
+ if (!beforeIsWord && !afterIsWord) {
18
+ results.push(idx);
19
+ }
20
+ start = idx + 1; // continue searching
21
+ }
22
+ return results;
23
+ }
24
+ export function hasFrontMatterTitle(line, pattern) {
25
+ const trimmed = line.trim();
26
+ if (!pattern) {
27
+ // default behavior: match `title:` or `title =` case-insensitive with optional whitespace
28
+ return /^title\s*[:=]/i.test(trimmed);
29
+ }
30
+ // If pattern is a simple substring, use includes/startsWith checks
31
+ const normalized = pattern.trim().toLowerCase();
32
+ if (normalized.length > 200)
33
+ return false; // avoid pathological patterns
34
+ // Simple heuristic: if pattern contains regex meta, fallback to substring match
35
+ if (/[\\\[\]\^\$\.|?*+()]/.test(normalized)) {
36
+ // fall back to simple includes for safety
37
+ return trimmed.toLowerCase().includes(normalized.replace(/[\\\[\]\^\$\.|?*+()]/g, ''));
38
+ }
39
+ return trimmed.toLowerCase().includes(normalized);
40
+ }
41
+ export function endsWithPunctuation(content, punctuation) {
42
+ if (!punctuation)
43
+ return /[.,;:!?]$/.test(content);
44
+ if (punctuation.length === 0)
45
+ return false;
46
+ if (punctuation.length > 200)
47
+ return false; // avoid pathological configs
48
+ const lastChar = content.charAt(content.length - 1);
49
+ return punctuation.includes(lastChar);
50
+ }
51
+ //# sourceMappingURL=safe-match.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safe-match.js","sourceRoot":"","sources":["../../src/utils/safe-match.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,MAAc;IAC1D,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,CAAC,MAAM;QAAE,OAAO,OAAO,CAAC;IAE5B,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACrC,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;IAEzC,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,GAAG,GAAG,SAAS,CAAC,OAAO,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;QAClD,IAAI,GAAG,KAAK,CAAC,CAAC;YAAE,MAAM;QAEtB,mEAAmE;QACnE,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;QAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;QAE7C,MAAM,YAAY,GAAG,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QAClE,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QAE/D,IAAI,CAAC,YAAY,IAAI,CAAC,WAAW,EAAE,CAAC;YAClC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC;QAED,KAAK,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,qBAAqB;IACxC,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,IAAY,EAAE,OAAgB;IAChE,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAE5B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,0FAA0F;QAC1F,OAAO,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACxC,CAAC;IAED,mEAAmE;IACnE,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAChD,IAAI,UAAU,CAAC,MAAM,GAAG,GAAG;QAAE,OAAO,KAAK,CAAC,CAAC,8BAA8B;IAEzE,gFAAgF;IAChF,IAAI,sBAAsB,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5C,0CAA0C;QAC1C,OAAO,OAAO,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,uBAAuB,EAAE,EAAE,CAAC,CAAC,CAAC;IACzF,CAAC;IAED,OAAO,OAAO,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,OAAe,EAAE,WAAoB;IACvE,IAAI,CAAC,WAAW;QAAE,OAAO,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACnD,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC3C,IAAI,WAAW,CAAC,MAAM,GAAG,GAAG;QAAE,OAAO,KAAK,CAAC,CAAC,6BAA6B;IAEzE,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACpD,OAAO,WAAW,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACxC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,85 @@
1
+ {
2
+ "name": "@dougis/markdown-lint-mcp",
3
+ "version": "1.0.0",
4
+ "description": "Model Context Protocol server for markdown linting and formatting, forked from ernestgwilsonii/markdownlint-mcp",
5
+ "main": "dist/index.js",
6
+ "type": "module",
7
+ "scripts": {
8
+ "build": "tsc",
9
+ "start": "node dist/index.js",
10
+ "dev": "tsc --watch & node --watch dist/index.js",
11
+ "test": "jest",
12
+ "test:watch": "jest --watch",
13
+ "test:coverage": "jest --coverage",
14
+ "lint": "eslint src --ext .ts",
15
+ "lint:fix": "eslint src --ext .ts --fix",
16
+ "format": "prettier --write 'src/**/*.ts'",
17
+ "prepare": "npm run build",
18
+ "prepublishOnly": "npm test && npm run lint",
19
+ "preversion": "npm run lint",
20
+ "version": "npm run format && git add -A src",
21
+ "postversion": "git push && git push --tags"
22
+ },
23
+ "keywords": [
24
+ "mcp",
25
+ "markdown",
26
+ "lint",
27
+ "markdownlint",
28
+ "formatting",
29
+ "validation",
30
+ "model-context-protocol",
31
+ "ai-tools",
32
+ "claude",
33
+ "openai",
34
+ "documentation"
35
+ ],
36
+ "author": "Doug Hubbard",
37
+ "license": "MIT",
38
+ "bin": {
39
+ "markdown-lint-mcp": "dist/index.js"
40
+ },
41
+ "repository": {
42
+ "type": "git",
43
+ "url": "https://github.com/dougis-org/markdown-lint-mcp.git"
44
+ },
45
+ "homepage": "https://github.com/dougis-org/markdown-lint-mcp#readme",
46
+ "bugs": {
47
+ "url": "https://github.com/dougis-org/markdown-lint-mcp/issues"
48
+ },
49
+ "engines": {
50
+ "node": ">=20.0.0",
51
+ "npm": ">=7.0.0"
52
+ },
53
+ "files": [
54
+ "dist",
55
+ "README.md",
56
+ "USAGE.md",
57
+ "LICENSE",
58
+ "CHANGELOG.md",
59
+ "CONTRIBUTING.md"
60
+ ],
61
+ "dependencies": {
62
+ "@modelcontextprotocol/sdk": "^1.25.2",
63
+ "body-parser": "^2.2.2",
64
+ "markdownlint": "^0.40.0",
65
+ "qs": "^6.14.1"
66
+ },
67
+ "devDependencies": {
68
+ "@babel/core": "^7.22.0",
69
+ "@babel/preset-env": "^7.22.0",
70
+ "@jest/globals": "^30.2.0",
71
+ "@types/jest": "^30.0.0",
72
+ "@types/node": "^25.0.0",
73
+ "@typescript-eslint/eslint-plugin": "^8.53.0",
74
+ "@typescript-eslint/parser": "^8.53.0",
75
+ "babel-jest": "^30.2.0",
76
+ "eslint": "^9.0.0",
77
+ "eslint-config-prettier": "^10.0.0",
78
+ "eslint-plugin-jest": "^29.12.0",
79
+ "eslint-plugin-prettier": "^5.5.0",
80
+ "jest": "^30.2.0",
81
+ "prettier": "^3.7.0",
82
+ "ts-jest": "^29.4.0",
83
+ "typescript": "^5.9.0"
84
+ }
85
+ }