@vibe-agent-toolkit/resources 0.1.4 → 0.1.5
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/dist/link-validator.d.ts.map +1 -1
- package/dist/link-validator.js +27 -13
- package/dist/link-validator.js.map +1 -1
- package/package.json +2 -2
- package/src/link-validator.ts +35 -13
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"link-validator.d.ts","sourceRoot":"","sources":["../src/link-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;
|
|
1
|
+
{"version":3,"file":"link-validator.d.ts","sourceRoot":"","sources":["../src/link-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,OAAO,EAEL,KAAK,UAAU,EAEhB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG5D;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,uDAAuD;IACvD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0EAA0E;IAC1E,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,qFAAqF;IACrF,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,YAAY,CAChC,IAAI,EAAE,YAAY,EAClB,cAAc,EAAE,MAAM,EACtB,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,EAC1C,OAAO,CAAC,EAAE,mBAAmB,GAC5B,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CA+BjC"}
|
package/dist/link-validator.js
CHANGED
|
@@ -14,9 +14,8 @@
|
|
|
14
14
|
* - Ignored files CAN link to non-ignored files (no error)
|
|
15
15
|
* - External resources (outside project) skip git-ignore checks
|
|
16
16
|
*/
|
|
17
|
-
import fs from 'node:fs/promises';
|
|
18
17
|
import path from 'node:path';
|
|
19
|
-
import { isGitIgnored } from '@vibe-agent-toolkit/utils';
|
|
18
|
+
import { isGitIgnored, verifyCaseSensitiveFilename, } from '@vibe-agent-toolkit/utils';
|
|
20
19
|
import { isWithinProject, splitHrefAnchor } from './utils.js';
|
|
21
20
|
/**
|
|
22
21
|
* Validate a single link in a markdown resource.
|
|
@@ -74,6 +73,18 @@ async function validateLocalFileLink(link, sourceFilePath, headingsByFile, optio
|
|
|
74
73
|
// Validate the file exists
|
|
75
74
|
const fileResult = await validateLocalFile(filePath, sourceFilePath);
|
|
76
75
|
if (!fileResult.exists) {
|
|
76
|
+
// Check if it's a case mismatch
|
|
77
|
+
if (fileResult.actualName) {
|
|
78
|
+
const expectedName = path.basename(fileResult.resolvedPath);
|
|
79
|
+
return {
|
|
80
|
+
resourcePath: sourceFilePath,
|
|
81
|
+
line: link.line,
|
|
82
|
+
type: 'broken_file',
|
|
83
|
+
link: link.href,
|
|
84
|
+
message: `File found but case mismatch: expected "${expectedName}" but found "${fileResult.actualName}". This will fail on case-sensitive filesystems (Linux). Update the link to match the actual filename.`,
|
|
85
|
+
suggestion: `Use "${fileResult.actualName}" instead of "${expectedName}"`,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
77
88
|
return {
|
|
78
89
|
resourcePath: sourceFilePath,
|
|
79
90
|
line: link.line,
|
|
@@ -147,17 +158,19 @@ async function validateAnchorLink(link, sourceFilePath, headingsByFile) {
|
|
|
147
158
|
return null;
|
|
148
159
|
}
|
|
149
160
|
/**
|
|
150
|
-
* Validate that a local file exists.
|
|
161
|
+
* Validate that a local file exists with the correct case.
|
|
151
162
|
*
|
|
152
163
|
* @param href - The href to the file (relative or absolute)
|
|
153
164
|
* @param sourceFilePath - Absolute path to the source file
|
|
154
|
-
* @returns Object with exists flag
|
|
165
|
+
* @returns Object with exists flag, resolved absolute path, and optional case mismatch info
|
|
155
166
|
*
|
|
156
167
|
* @example
|
|
157
168
|
* ```typescript
|
|
158
169
|
* const result = await validateLocalFile('./docs/guide.md', '/project/README.md');
|
|
159
170
|
* if (result.exists) {
|
|
160
171
|
* console.log('File exists at:', result.resolvedPath);
|
|
172
|
+
* } else if (result.actualName) {
|
|
173
|
+
* console.log('Case mismatch:', result.actualName);
|
|
161
174
|
* }
|
|
162
175
|
* ```
|
|
163
176
|
*/
|
|
@@ -165,16 +178,17 @@ async function validateLocalFile(href, sourceFilePath) {
|
|
|
165
178
|
// Resolve the path relative to the source file's directory
|
|
166
179
|
const sourceDir = path.dirname(sourceFilePath);
|
|
167
180
|
const resolvedPath = path.resolve(sourceDir, href);
|
|
168
|
-
// Check if file exists
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
exists
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
181
|
+
// Check if file exists with correct case
|
|
182
|
+
const verification = await verifyCaseSensitiveFilename(resolvedPath);
|
|
183
|
+
// Build result with optional actualName (only include if present)
|
|
184
|
+
const result = {
|
|
185
|
+
exists: verification.exists,
|
|
186
|
+
resolvedPath,
|
|
187
|
+
};
|
|
188
|
+
if (verification.actualName) {
|
|
189
|
+
result.actualName = verification.actualName;
|
|
176
190
|
}
|
|
177
|
-
return
|
|
191
|
+
return result;
|
|
178
192
|
}
|
|
179
193
|
/**
|
|
180
194
|
* Validate that an anchor (heading slug) exists in a file.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"link-validator.js","sourceRoot":"","sources":["../src/link-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"link-validator.js","sourceRoot":"","sources":["../src/link-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EACL,YAAY,EAEZ,2BAA2B,GAC5B,MAAM,2BAA2B,CAAC;AAInC,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAc9D;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,IAAkB,EAClB,cAAsB,EACtB,cAA0C,EAC1C,OAA6B;IAE7B,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,YAAY;YACf,OAAO,MAAM,qBAAqB,CAAC,IAAI,EAAE,cAAc,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;QAEpF,KAAK,QAAQ;YACX,OAAO,MAAM,kBAAkB,CAAC,IAAI,EAAE,cAAc,EAAE,cAAc,CAAC,CAAC;QAExE,KAAK,UAAU;YACb,sDAAsD;YACtD,OAAO,IAAI,CAAC;QAEd,KAAK,OAAO;YACV,mCAAmC;YACnC,OAAO,IAAI,CAAC;QAEd,KAAK,SAAS;YACZ,OAAO;gBACL,YAAY,EAAE,cAAc;gBAC5B,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,IAAI,EAAE,cAAc;gBACpB,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,OAAO,EAAE,mBAAmB;aAC7B,CAAC;QAEJ,OAAO,CAAC,CAAC,CAAC;YACR,kCAAkC;YAClC,MAAM,WAAW,GAAU,IAAI,CAAC,IAAI,CAAC;YACrC,OAAO,WAAW,CAAC;QACrB,CAAC;IACH,CAAC;AACH,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,qBAAqB,CAClC,IAAkB,EAClB,cAAsB,EACtB,cAA0C,EAC1C,OAA6B;IAE7B,yCAAyC;IACzC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEtD,2BAA2B;IAC3B,MAAM,UAAU,GAAG,MAAM,iBAAiB,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;IAErE,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC;QACvB,gCAAgC;QAChC,IAAI,UAAU,CAAC,UAAU,EAAE,CAAC;YAC1B,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;YAC5D,OAAO;gBACL,YAAY,EAAE,cAAc;gBAC5B,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,IAAI,EAAE,aAAa;gBACnB,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,OAAO,EAAE,2CAA2C,YAAY,gBAAgB,UAAU,CAAC,UAAU,wGAAwG;gBAC7M,UAAU,EAAE,QAAQ,UAAU,CAAC,UAAU,iBAAiB,YAAY,GAAG;aAC1E,CAAC;QACJ,CAAC;QAED,OAAO;YACL,YAAY,EAAE,cAAc;YAC5B,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,aAAa;YACnB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,OAAO,EAAE,mBAAmB,UAAU,CAAC,YAAY,EAAE;YACrD,UAAU,EAAE,EAAE;SACf,CAAC;IACJ,CAAC;IAED,oCAAoC;IACpC,iBAAiB;IACjB,oCAAoC;IACpC,6BAA6B;IAC7B,4DAA4D;IAC5D,IACE,OAAO,EAAE,kBAAkB,KAAK,IAAI;QACpC,OAAO,EAAE,WAAW,KAAK,SAAS;QAClC,eAAe,CAAC,UAAU,CAAC,YAAY,EAAE,OAAO,CAAC,WAAW,CAAC,EAC7D,CAAC;QACD,4EAA4E;QAC5E,MAAM,eAAe,GAAG,OAAO,CAAC,UAAU;YACxC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,cAAc,CAAC;YAC9C,CAAC,CAAC,YAAY,CAAC,cAAc,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;QACtD,MAAM,eAAe,GAAG,OAAO,CAAC,UAAU;YACxC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,UAAU,CAAC,YAAY,CAAC;YACvD,CAAC,CAAC,YAAY,CAAC,UAAU,CAAC,YAAY,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;QAE/D,6DAA6D;QAC7D,IAAI,CAAC,eAAe,IAAI,eAAe,EAAE,CAAC;YACxC,OAAO;gBACL,YAAY,EAAE,cAAc;gBAC5B,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,IAAI,EAAE,oBAAoB;gBAC1B,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,OAAO,EAAE,8CAA8C,UAAU,CAAC,YAAY,uHAAuH;gBACrM,UAAU,EAAE,EAAE;aACf,CAAC;QACJ,CAAC;IACH,CAAC;IAED,wCAAwC;IACxC,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,WAAW,GAAG,MAAM,cAAc,CACtC,MAAM,EACN,UAAU,CAAC,YAAY,EACvB,cAAc,CACf,CAAC;QAEF,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,OAAO;gBACL,YAAY,EAAE,cAAc;gBAC5B,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,IAAI,EAAE,eAAe;gBACrB,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,OAAO,EAAE,sBAAsB,MAAM,OAAO,UAAU,CAAC,YAAY,EAAE;gBACrE,UAAU,EAAE,EAAE;aACf,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,kBAAkB,CAC/B,IAAkB,EAClB,cAAsB,EACtB,cAA0C;IAE1C,mCAAmC;IACnC,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;IAE1E,yCAAyC;IACzC,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,MAAM,EAAE,cAAc,EAAE,cAAc,CAAC,CAAC;IAE7E,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO;YACL,YAAY,EAAE,cAAc;YAC5B,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,eAAe;YACrB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,OAAO,EAAE,qBAAqB,IAAI,CAAC,IAAI,EAAE;YACzC,UAAU,EAAE,EAAE;SACf,CAAC;IACJ,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAGD;;;;;;;;;;;;;;;;GAgBG;AACH,KAAK,UAAU,iBAAiB,CAC9B,IAAY,EACZ,cAAsB;IAEtB,2DAA2D;IAC3D,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IAC/C,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAEnD,yCAAyC;IACzC,MAAM,YAAY,GAAG,MAAM,2BAA2B,CAAC,YAAY,CAAC,CAAC;IAErE,kEAAkE;IAClE,MAAM,MAAM,GAAmE;QAC7E,MAAM,EAAE,YAAY,CAAC,MAAM;QAC3B,YAAY;KACb,CAAC;IAEF,IAAI,YAAY,CAAC,UAAU,EAAE,CAAC;QAC5B,MAAM,CAAC,UAAU,GAAG,YAAY,CAAC,UAAU,CAAC;IAC9C,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,KAAK,UAAU,cAAc,CAC3B,MAAc,EACd,cAAsB,EACtB,cAA0C;IAE1C,+BAA+B;IAC/B,MAAM,QAAQ,GAAG,cAAc,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACpD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,KAAK,CAAC;IACf,CAAC;IAED,8CAA8C;IAC9C,OAAO,iBAAiB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;AAC7C,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,SAAS,iBAAiB,CACxB,QAAuB,EACvB,UAAkB;IAElB,MAAM,gBAAgB,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;IAElD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,wBAAwB;QACxB,IAAI,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,gBAAgB,EAAE,CAAC;YACpD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,6BAA6B;QAC7B,IAAI,OAAO,CAAC,QAAQ,IAAI,iBAAiB,CAAC,OAAO,CAAC,QAAQ,EAAE,UAAU,CAAC,EAAE,CAAC;YACxE,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibe-agent-toolkit/resources",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Markdown resource parsing, validation, and link integrity checking",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"author": "Jeff Dutton",
|
|
34
34
|
"license": "MIT",
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@vibe-agent-toolkit/utils": "0.1.
|
|
36
|
+
"@vibe-agent-toolkit/utils": "0.1.5",
|
|
37
37
|
"ajv": "^8.17.1",
|
|
38
38
|
"js-yaml": "^4.1.1",
|
|
39
39
|
"picomatch": "^4.0.3",
|
package/src/link-validator.ts
CHANGED
|
@@ -15,10 +15,13 @@
|
|
|
15
15
|
* - External resources (outside project) skip git-ignore checks
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
import fs from 'node:fs/promises';
|
|
19
18
|
import path from 'node:path';
|
|
20
19
|
|
|
21
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
isGitIgnored,
|
|
22
|
+
type GitTracker,
|
|
23
|
+
verifyCaseSensitiveFilename,
|
|
24
|
+
} from '@vibe-agent-toolkit/utils';
|
|
22
25
|
|
|
23
26
|
import type { ValidationIssue } from './schemas/validation-result.js';
|
|
24
27
|
import type { HeadingNode, ResourceLink } from './types.js';
|
|
@@ -110,6 +113,19 @@ async function validateLocalFileLink(
|
|
|
110
113
|
const fileResult = await validateLocalFile(filePath, sourceFilePath);
|
|
111
114
|
|
|
112
115
|
if (!fileResult.exists) {
|
|
116
|
+
// Check if it's a case mismatch
|
|
117
|
+
if (fileResult.actualName) {
|
|
118
|
+
const expectedName = path.basename(fileResult.resolvedPath);
|
|
119
|
+
return {
|
|
120
|
+
resourcePath: sourceFilePath,
|
|
121
|
+
line: link.line,
|
|
122
|
+
type: 'broken_file',
|
|
123
|
+
link: link.href,
|
|
124
|
+
message: `File found but case mismatch: expected "${expectedName}" but found "${fileResult.actualName}". This will fail on case-sensitive filesystems (Linux). Update the link to match the actual filename.`,
|
|
125
|
+
suggestion: `Use "${fileResult.actualName}" instead of "${expectedName}"`,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
113
129
|
return {
|
|
114
130
|
resourcePath: sourceFilePath,
|
|
115
131
|
line: link.line,
|
|
@@ -204,38 +220,44 @@ async function validateAnchorLink(
|
|
|
204
220
|
|
|
205
221
|
|
|
206
222
|
/**
|
|
207
|
-
* Validate that a local file exists.
|
|
223
|
+
* Validate that a local file exists with the correct case.
|
|
208
224
|
*
|
|
209
225
|
* @param href - The href to the file (relative or absolute)
|
|
210
226
|
* @param sourceFilePath - Absolute path to the source file
|
|
211
|
-
* @returns Object with exists flag
|
|
227
|
+
* @returns Object with exists flag, resolved absolute path, and optional case mismatch info
|
|
212
228
|
*
|
|
213
229
|
* @example
|
|
214
230
|
* ```typescript
|
|
215
231
|
* const result = await validateLocalFile('./docs/guide.md', '/project/README.md');
|
|
216
232
|
* if (result.exists) {
|
|
217
233
|
* console.log('File exists at:', result.resolvedPath);
|
|
234
|
+
* } else if (result.actualName) {
|
|
235
|
+
* console.log('Case mismatch:', result.actualName);
|
|
218
236
|
* }
|
|
219
237
|
* ```
|
|
220
238
|
*/
|
|
221
239
|
async function validateLocalFile(
|
|
222
240
|
href: string,
|
|
223
241
|
sourceFilePath: string
|
|
224
|
-
): Promise<{ exists: boolean; resolvedPath: string }> {
|
|
242
|
+
): Promise<{ exists: boolean; resolvedPath: string; actualName?: string }> {
|
|
225
243
|
// Resolve the path relative to the source file's directory
|
|
226
244
|
const sourceDir = path.dirname(sourceFilePath);
|
|
227
245
|
const resolvedPath = path.resolve(sourceDir, href);
|
|
228
246
|
|
|
229
|
-
// Check if file exists
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
247
|
+
// Check if file exists with correct case
|
|
248
|
+
const verification = await verifyCaseSensitiveFilename(resolvedPath);
|
|
249
|
+
|
|
250
|
+
// Build result with optional actualName (only include if present)
|
|
251
|
+
const result: { exists: boolean; resolvedPath: string; actualName?: string } = {
|
|
252
|
+
exists: verification.exists,
|
|
253
|
+
resolvedPath,
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
if (verification.actualName) {
|
|
257
|
+
result.actualName = verification.actualName;
|
|
236
258
|
}
|
|
237
259
|
|
|
238
|
-
return
|
|
260
|
+
return result;
|
|
239
261
|
}
|
|
240
262
|
|
|
241
263
|
/**
|