@vibe-agent-toolkit/resources 0.1.38 → 0.1.39-rc.10

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 (75) hide show
  1. package/README.md +33 -24
  2. package/dist/frontmatter-link-validator.d.ts +9 -9
  3. package/dist/frontmatter-link-validator.d.ts.map +1 -1
  4. package/dist/frontmatter-link-validator.js +28 -27
  5. package/dist/frontmatter-link-validator.js.map +1 -1
  6. package/dist/frontmatter-validator.d.ts +3 -2
  7. package/dist/frontmatter-validator.d.ts.map +1 -1
  8. package/dist/frontmatter-validator.js +8 -14
  9. package/dist/frontmatter-validator.js.map +1 -1
  10. package/dist/html-link-parser.d.ts +47 -0
  11. package/dist/html-link-parser.d.ts.map +1 -0
  12. package/dist/html-link-parser.js +111 -0
  13. package/dist/html-link-parser.js.map +1 -0
  14. package/dist/html-transform.d.ts +45 -0
  15. package/dist/html-transform.d.ts.map +1 -0
  16. package/dist/html-transform.js +116 -0
  17. package/dist/html-transform.js.map +1 -0
  18. package/dist/index.d.ts +5 -2
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +4 -2
  21. package/dist/index.js.map +1 -1
  22. package/dist/link-parser.d.ts +26 -2
  23. package/dist/link-parser.d.ts.map +1 -1
  24. package/dist/link-parser.js +40 -6
  25. package/dist/link-parser.js.map +1 -1
  26. package/dist/link-validator.d.ts +53 -6
  27. package/dist/link-validator.d.ts.map +1 -1
  28. package/dist/link-validator.js +100 -131
  29. package/dist/link-validator.js.map +1 -1
  30. package/dist/multi-schema-validator.d.ts.map +1 -1
  31. package/dist/multi-schema-validator.js +6 -8
  32. package/dist/multi-schema-validator.js.map +1 -1
  33. package/dist/resource-registry.d.ts +56 -13
  34. package/dist/resource-registry.d.ts.map +1 -1
  35. package/dist/resource-registry.js +165 -66
  36. package/dist/resource-registry.js.map +1 -1
  37. package/dist/schemas/link-auth.d.ts +382 -0
  38. package/dist/schemas/link-auth.d.ts.map +1 -0
  39. package/dist/schemas/link-auth.js +124 -0
  40. package/dist/schemas/link-auth.js.map +1 -0
  41. package/dist/schemas/project-config.d.ts +3277 -171
  42. package/dist/schemas/project-config.d.ts.map +1 -1
  43. package/dist/schemas/project-config.js +68 -0
  44. package/dist/schemas/project-config.js.map +1 -1
  45. package/dist/schemas/resource-metadata.d.ts +46 -10
  46. package/dist/schemas/resource-metadata.d.ts.map +1 -1
  47. package/dist/schemas/resource-metadata.js +14 -1
  48. package/dist/schemas/resource-metadata.js.map +1 -1
  49. package/dist/schemas/validation-result.d.ts +36 -57
  50. package/dist/schemas/validation-result.d.ts.map +1 -1
  51. package/dist/schemas/validation-result.js +5 -27
  52. package/dist/schemas/validation-result.js.map +1 -1
  53. package/dist/types/resources.d.ts +1 -1
  54. package/dist/types/resources.d.ts.map +1 -1
  55. package/dist/types/resources.js.map +1 -1
  56. package/dist/utils.d.ts +10 -0
  57. package/dist/utils.d.ts.map +1 -1
  58. package/dist/utils.js +14 -0
  59. package/dist/utils.js.map +1 -1
  60. package/package.json +4 -3
  61. package/src/frontmatter-link-validator.ts +28 -30
  62. package/src/frontmatter-validator.ts +19 -16
  63. package/src/html-link-parser.ts +140 -0
  64. package/src/html-transform.ts +157 -0
  65. package/src/index.ts +10 -1
  66. package/src/link-parser.ts +60 -11
  67. package/src/link-validator.ts +175 -145
  68. package/src/multi-schema-validator.ts +10 -8
  69. package/src/resource-registry.ts +205 -72
  70. package/src/schemas/link-auth.ts +146 -0
  71. package/src/schemas/project-config.ts +76 -0
  72. package/src/schemas/resource-metadata.ts +17 -1
  73. package/src/schemas/validation-result.ts +5 -29
  74. package/src/types/resources.ts +2 -1
  75. package/src/utils.ts +15 -0
package/README.md CHANGED
@@ -47,7 +47,7 @@ console.log(`Errors: ${result.errorCount}, Warnings: ${result.warningCount}`);
47
47
  // Show any issues
48
48
  for (const issue of result.issues) {
49
49
  console.log(`${issue.severity.toUpperCase()}: ${issue.message}`);
50
- if (issue.line) console.log(` at ${issue.resourcePath}:${issue.line}`);
50
+ if (issue.line) console.log(` at ${issue.location}:${issue.line}`);
51
51
  }
52
52
  ```
53
53
 
@@ -546,27 +546,35 @@ interface ValidationResult {
546
546
 
547
547
  A single validation issue found during link validation.
548
548
 
549
+ `ValidationIssue` is the unified issue shape every VAT validator emits (defined
550
+ in `@vibe-agent-toolkit/agent-schema`). Each issue carries a registry `code`
551
+ (see [Validation Codes](../../docs/validation-codes.md)) and a resolved
552
+ `severity`.
553
+
549
554
  ```typescript
550
555
  interface ValidationIssue {
551
- severity: ValidationSeverity; // Issue severity level
552
- resourcePath: string; // Absolute path to the resource containing the issue
553
- line?: number; // Line number where the issue occurs
554
- type: string; // Issue type identifier (e.g., 'broken_file', 'broken_anchor')
555
- link: string; // The problematic link
556
+ code: string; // Registry code, e.g. 'LINK_BROKEN_FILE', 'EXTERNAL_URL_DEAD'
557
+ severity: SeverityLevel; // Resolved severity (after config overrides)
556
558
  message: string; // Human-readable description
559
+ location?: string; // Project-relative path of the file containing the issue
560
+ line?: number; // Line number where the issue occurs
561
+ link?: string; // The problematic link (when applicable)
562
+ fix?: string; // Fix hint from the code registry
563
+ reference?: string; // Anchor into docs/validation-codes.md
557
564
  suggestion?: string; // Optional suggestion for fixing
558
565
  }
559
566
  ```
560
567
 
561
- ### ValidationSeverity
568
+ ### SeverityLevel
562
569
 
563
570
  ```typescript
564
- type ValidationSeverity = 'error' | 'warning' | 'info';
571
+ type SeverityLevel = 'error' | 'warning' | 'info' | 'ignore';
565
572
  ```
566
573
 
567
574
  - `error` - Critical issue that should block usage (e.g., broken file link)
568
- - `warning` - Non-critical issue that should be addressed (e.g., questionable link format)
569
- - `info` - Informational message (e.g., external URL not validated)
575
+ - `warning` - Non-critical issue that should be addressed (e.g., dead external URL)
576
+ - `info` - Informational message
577
+ - `ignore` - Suppressed; the issue is not emitted (set via `validation.severity` config)
570
578
 
571
579
  ## Frontmatter Support
572
580
 
@@ -721,19 +729,19 @@ vat resources validate docs/ --frontmatter-schema schema.json
721
729
 
722
730
  ### Validation Result
723
731
 
724
- Frontmatter validation results are included in `ValidationResult`:
732
+ Frontmatter findings are emitted into the same unified `result.issues` array as
733
+ link findings — each carries a `FRONTMATTER_*` registry code (e.g.
734
+ `FRONTMATTER_MISSING`, `FRONTMATTER_SCHEMA_ERROR`, `FRONTMATTER_INVALID_YAML`)
735
+ and a resolved `severity`. There is no separate `frontmatterValidation` field.
725
736
 
726
737
  ```typescript
727
- interface ValidationResult {
728
- // ... existing fields
729
- frontmatterValidation?: {
730
- valid: boolean;
731
- errors: Array<{
732
- resourcePath: string;
733
- message: string;
734
- field?: string;
735
- }>;
736
- };
738
+ const result = await registry.validate();
739
+
740
+ const frontmatterIssues = result.issues.filter((i) =>
741
+ i.code.startsWith('FRONTMATTER_'),
742
+ );
743
+ for (const issue of frontmatterIssues) {
744
+ console.log(`[${issue.severity}] ${issue.code} at ${issue.location}: ${issue.message}`);
737
745
  }
738
746
  ```
739
747
 
@@ -889,9 +897,10 @@ const warnings = result.issues.filter(i => i.severity === 'warning');
889
897
  // Group by resource
890
898
  const issuesByResource = new Map<string, ValidationIssue[]>();
891
899
  for (const issue of result.issues) {
892
- const issues = issuesByResource.get(issue.resourcePath) ?? [];
900
+ const key = issue.location ?? '(unknown)';
901
+ const issues = issuesByResource.get(key) ?? [];
893
902
  issues.push(issue);
894
- issuesByResource.set(issue.resourcePath, issues);
903
+ issuesByResource.set(key, issues);
895
904
  }
896
905
 
897
906
  // Show summary
@@ -926,7 +935,7 @@ async function validateDocs() {
926
935
  console.error(`\nValidation failed with ${result.errorCount} errors\n`);
927
936
 
928
937
  for (const issue of result.issues.filter(i => i.severity === 'error')) {
929
- console.error(`${issue.resourcePath}:${issue.line ?? '?'}`);
938
+ console.error(`${issue.location ?? '(unknown)'}:${issue.line ?? '?'}`);
930
939
  console.error(` ${issue.message}`);
931
940
  if (issue.suggestion) {
932
941
  console.error(` Suggestion: ${issue.suggestion}`);
@@ -7,18 +7,18 @@
7
7
  * frontmatter-specific type codes plus a list of external URLs the registry
8
8
  * can fold into its existing external URL collection.
9
9
  *
10
- * Type mapping:
11
- * broken_file -> frontmatter_link_broken
12
- * broken_anchor -> frontmatter_anchor_missing
13
- * link_to_gitignored -> frontmatter_link_to_gitignored
14
- * unknown_link -> frontmatter_unknown_link
10
+ * Code mapping:
11
+ * LINK_BROKEN_FILE -> FRONTMATTER_LINK_BROKEN
12
+ * LINK_BROKEN_ANCHOR -> FRONTMATTER_ANCHOR_MISSING
13
+ * LINK_TO_GITIGNORED -> FRONTMATTER_LINK_TO_GITIGNORED
14
+ * LINK_UNKNOWN -> FRONTMATTER_UNKNOWN_LINK
15
15
  *
16
16
  * Skipped (no issue, no external):
17
17
  * email (mailto:)
18
18
  * anchor-only (validated as anchor in current file via validateLink)
19
19
  */
20
- import { type ValidateLinkOptions } from './link-validator.js';
21
- import type { HeadingNode, ValidationIssue } from './types.js';
20
+ import { type FragmentIndex, type ValidateLinkOptions } from './link-validator.js';
21
+ import type { ValidationIssue } from './types.js';
22
22
  /** A frontmatter-sourced external URL captured for downstream health checking. */
23
23
  export interface FrontmatterExternalUrl {
24
24
  url: string;
@@ -35,8 +35,8 @@ export interface FrontmatterLinkValidationResult {
35
35
  * @param frontmatter - Parsed frontmatter (or undefined)
36
36
  * @param schema - JSON Schema for the collection
37
37
  * @param sourceFilePath - Absolute path to the source file
38
- * @param headingsByFile - Heading trees (for anchor validation)
38
+ * @param fragmentsByFile - Fragment index (file path → set of valid fragments) for anchor validation
39
39
  * @param options - Same shape as validateLink (projectRoot, gitTracker, ...)
40
40
  */
41
- export declare function validateFrontmatterLinks(frontmatter: Record<string, unknown> | undefined, schema: object, sourceFilePath: string, headingsByFile: Map<string, HeadingNode[]>, options?: ValidateLinkOptions): Promise<FrontmatterLinkValidationResult>;
41
+ export declare function validateFrontmatterLinks(frontmatter: Record<string, unknown> | undefined, schema: object, sourceFilePath: string, fragmentsByFile: FragmentIndex, options?: ValidateLinkOptions): Promise<FrontmatterLinkValidationResult>;
42
42
  //# sourceMappingURL=frontmatter-link-validator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"frontmatter-link-validator.d.ts","sourceRoot":"","sources":["../src/frontmatter-link-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,EAAgB,KAAK,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE7E,OAAO,KAAK,EAAE,WAAW,EAAgB,eAAe,EAAE,MAAM,YAAY,CAAC;AAE7E,kFAAkF;AAClF,MAAM,WAAW,sBAAsB;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,+BAA+B;IAC9C,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,YAAY,EAAE,sBAAsB,EAAE,CAAC;CACxC;AAED;;;;;;;;GAQG;AACH,wBAAsB,wBAAwB,CAC5C,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAChD,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,MAAM,EACtB,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,EAC1C,OAAO,CAAC,EAAE,mBAAmB,GAC5B,OAAO,CAAC,+BAA+B,CAAC,CAoC1C"}
1
+ {"version":3,"file":"frontmatter-link-validator.d.ts","sourceRoot":"","sources":["../src/frontmatter-link-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAKH,OAAO,EAAgB,KAAK,aAAa,EAAE,KAAK,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAEjG,OAAO,KAAK,EAAgB,eAAe,EAAE,MAAM,YAAY,CAAC;AAUhE,kFAAkF;AAClF,MAAM,WAAW,sBAAsB;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,+BAA+B;IAC9C,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,YAAY,EAAE,sBAAsB,EAAE,CAAC;CACxC;AAED;;;;;;;;GAQG;AACH,wBAAsB,wBAAwB,CAC5C,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAChD,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,MAAM,EACtB,eAAe,EAAE,aAAa,EAC9B,OAAO,CAAC,EAAE,mBAAmB,GAC5B,OAAO,CAAC,+BAA+B,CAAC,CAoC1C"}
@@ -7,29 +7,37 @@
7
7
  * frontmatter-specific type codes plus a list of external URLs the registry
8
8
  * can fold into its existing external URL collection.
9
9
  *
10
- * Type mapping:
11
- * broken_file -> frontmatter_link_broken
12
- * broken_anchor -> frontmatter_anchor_missing
13
- * link_to_gitignored -> frontmatter_link_to_gitignored
14
- * unknown_link -> frontmatter_unknown_link
10
+ * Code mapping:
11
+ * LINK_BROKEN_FILE -> FRONTMATTER_LINK_BROKEN
12
+ * LINK_BROKEN_ANCHOR -> FRONTMATTER_ANCHOR_MISSING
13
+ * LINK_TO_GITIGNORED -> FRONTMATTER_LINK_TO_GITIGNORED
14
+ * LINK_UNKNOWN -> FRONTMATTER_UNKNOWN_LINK
15
15
  *
16
16
  * Skipped (no issue, no external):
17
17
  * email (mailto:)
18
18
  * anchor-only (validated as anchor in current file via validateLink)
19
19
  */
20
+ import { createRegistryIssue } from '@vibe-agent-toolkit/agent-schema';
20
21
  import { classifyLink } from './link-parser.js';
21
22
  import { validateLink } from './link-validator.js';
22
23
  import { walkFrontmatterUriReferences } from './schema-uri-walker.js';
24
+ /** Map the link-level code emitted by validateLink to its frontmatter-scoped code. */
25
+ const LINK_CODE_TO_FRONTMATTER_CODE = {
26
+ LINK_BROKEN_FILE: 'FRONTMATTER_LINK_BROKEN',
27
+ LINK_BROKEN_ANCHOR: 'FRONTMATTER_ANCHOR_MISSING',
28
+ LINK_TO_GITIGNORED: 'FRONTMATTER_LINK_TO_GITIGNORED',
29
+ LINK_UNKNOWN: 'FRONTMATTER_UNKNOWN_LINK',
30
+ };
23
31
  /**
24
32
  * Validate every URI-family frontmatter value against the file system.
25
33
  *
26
34
  * @param frontmatter - Parsed frontmatter (or undefined)
27
35
  * @param schema - JSON Schema for the collection
28
36
  * @param sourceFilePath - Absolute path to the source file
29
- * @param headingsByFile - Heading trees (for anchor validation)
37
+ * @param fragmentsByFile - Fragment index (file path → set of valid fragments) for anchor validation
30
38
  * @param options - Same shape as validateLink (projectRoot, gitTracker, ...)
31
39
  */
32
- export async function validateFrontmatterLinks(frontmatter, schema, sourceFilePath, headingsByFile, options) {
40
+ export async function validateFrontmatterLinks(frontmatter, schema, sourceFilePath, fragmentsByFile, options) {
33
41
  if (!frontmatter)
34
42
  return { issues: [], externalUrls: [] };
35
43
  const captures = walkFrontmatterUriReferences(frontmatter, schema);
@@ -55,7 +63,7 @@ export async function validateFrontmatterLinks(frontmatter, schema, sourceFilePa
55
63
  type: linkType,
56
64
  line: 1, // Frontmatter per-field line numbers are post-v1.
57
65
  };
58
- const issue = await validateLink(syntheticLink, sourceFilePath, headingsByFile, options);
66
+ const issue = await validateLink(syntheticLink, sourceFilePath, fragmentsByFile, options);
59
67
  if (!issue)
60
68
  continue;
61
69
  issues.push(rewriteIssue(issue, capture.dottedPath));
@@ -63,24 +71,17 @@ export async function validateFrontmatterLinks(frontmatter, schema, sourceFilePa
63
71
  return { issues, externalUrls };
64
72
  }
65
73
  function rewriteIssue(issue, dottedPath) {
66
- return {
67
- ...issue,
68
- type: mapType(issue.type),
69
- message: `field \`${dottedPath}\`: ${issue.message}`,
70
- };
71
- }
72
- function mapType(originalType) {
73
- switch (originalType) {
74
- case 'broken_file':
75
- return 'frontmatter_link_broken';
76
- case 'broken_anchor':
77
- return 'frontmatter_anchor_missing';
78
- case 'link_to_gitignored':
79
- return 'frontmatter_link_to_gitignored';
80
- case 'unknown_link':
81
- return 'frontmatter_unknown_link';
82
- default:
83
- return originalType;
84
- }
74
+ const mappedCode = LINK_CODE_TO_FRONTMATTER_CODE[issue.code] ?? issue.code;
75
+ const message = `field \`${dottedPath}\`: ${issue.message}`;
76
+ const extras = {};
77
+ if (issue.location !== undefined)
78
+ extras.location = issue.location;
79
+ if (issue.line !== undefined)
80
+ extras.line = issue.line;
81
+ if (issue.link !== undefined)
82
+ extras.link = issue.link;
83
+ if (issue.suggestion !== undefined)
84
+ extras.suggestion = issue.suggestion;
85
+ return createRegistryIssue(mappedCode, message, extras);
85
86
  }
86
87
  //# sourceMappingURL=frontmatter-link-validator.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"frontmatter-link-validator.js","sourceRoot":"","sources":["../src/frontmatter-link-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,YAAY,EAA4B,MAAM,qBAAqB,CAAC;AAC7E,OAAO,EAAE,4BAA4B,EAAE,MAAM,wBAAwB,CAAC;AAetE;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,WAAgD,EAChD,MAAc,EACd,cAAsB,EACtB,cAA0C,EAC1C,OAA6B;IAE7B,IAAI,CAAC,WAAW;QAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC;IAE1D,MAAM,QAAQ,GAAG,4BAA4B,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IACnE,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC;IAEnE,MAAM,MAAM,GAAsB,EAAE,CAAC;IACrC,MAAM,YAAY,GAA6B,EAAE,CAAC;IAElD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAE7C,IAAI,QAAQ,KAAK,UAAU,EAAE,CAAC;YAC5B,YAAY,CAAC,IAAI,CAAC;gBAChB,GAAG,EAAE,OAAO,CAAC,KAAK;gBAClB,UAAU,EAAE,cAAc;gBAC1B,UAAU,EAAE,OAAO,CAAC,UAAU;aAC/B,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QACD,IAAI,QAAQ,KAAK,OAAO;YAAE,SAAS;QAEnC,MAAM,aAAa,GAAiB;YAClC,IAAI,EAAE,OAAO,CAAC,UAAU;YACxB,IAAI,EAAE,OAAO,CAAC,KAAK;YACnB,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,CAAC,EAAE,kDAAkD;SAC5D,CAAC;QAEF,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,aAAa,EAAE,cAAc,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;QACzF,IAAI,CAAC,KAAK;YAAE,SAAS;QAErB,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;IACvD,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;AAClC,CAAC;AAED,SAAS,YAAY,CAAC,KAAsB,EAAE,UAAkB;IAC9D,OAAO;QACL,GAAG,KAAK;QACR,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC;QACzB,OAAO,EAAE,WAAW,UAAU,OAAO,KAAK,CAAC,OAAO,EAAE;KACrD,CAAC;AACJ,CAAC;AAED,SAAS,OAAO,CAAC,YAAoB;IACnC,QAAQ,YAAY,EAAE,CAAC;QACrB,KAAK,aAAa;YAChB,OAAO,yBAAyB,CAAC;QACnC,KAAK,eAAe;YAClB,OAAO,4BAA4B,CAAC;QACtC,KAAK,oBAAoB;YACvB,OAAO,gCAAgC,CAAC;QAC1C,KAAK,cAAc;YACjB,OAAO,0BAA0B,CAAC;QACpC;YACE,OAAO,YAAY,CAAC;IACxB,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"frontmatter-link-validator.js","sourceRoot":"","sources":["../src/frontmatter-link-validator.ts"],"names":[],"mappings":"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"}
@@ -12,8 +12,8 @@
12
12
  *
13
13
  * This is the ONLY place in the codebase that should use AJV.
14
14
  */
15
+ import { type ValidationIssue } from '@vibe-agent-toolkit/agent-schema';
15
16
  import type { ValidationMode } from './schemas/project-config.js';
16
- import type { ValidationIssue } from './schemas/validation-result.js';
17
17
  /**
18
18
  * Validate frontmatter against a JSON Schema.
19
19
  *
@@ -28,6 +28,7 @@ import type { ValidationIssue } from './schemas/validation-result.js';
28
28
  * @param resourcePath - File path for error reporting
29
29
  * @param mode - Validation mode: 'strict' (default) or 'permissive'
30
30
  * @param schemaPath - Path to schema file (for error context)
31
+ * @param projectRoot - Project root for computing relative issue locations
31
32
  * @returns Array of validation issues (empty if valid)
32
33
  *
33
34
  * @example
@@ -46,5 +47,5 @@ import type { ValidationIssue } from './schemas/validation-result.js';
46
47
  * );
47
48
  * ```
48
49
  */
49
- export declare function validateFrontmatter(frontmatter: Record<string, unknown> | undefined, schema: object, resourcePath: string, mode?: ValidationMode, schemaPath?: string): ValidationIssue[];
50
+ export declare function validateFrontmatter(frontmatter: Record<string, unknown> | undefined, schema: object, resourcePath: string, mode?: ValidationMode, schemaPath?: string, projectRoot?: string): ValidationIssue[];
50
51
  //# sourceMappingURL=frontmatter-validator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"frontmatter-validator.d.ts","sourceRoot":"","sources":["../src/frontmatter-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAEtE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAChD,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,IAAI,GAAE,cAAyB,EAC/B,UAAU,CAAC,EAAE,MAAM,GAClB,eAAe,EAAE,CA+DnB"}
1
+ {"version":3,"file":"frontmatter-validator.d.ts","sourceRoot":"","sources":["../src/frontmatter-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAuB,KAAK,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAG7F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAGlE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAChD,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,IAAI,GAAE,cAAyB,EAC/B,UAAU,CAAC,EAAE,MAAM,EACnB,WAAW,CAAC,EAAE,MAAM,GACnB,eAAe,EAAE,CA8DnB"}
@@ -12,7 +12,9 @@
12
12
  *
13
13
  * This is the ONLY place in the codebase that should use AJV.
14
14
  */
15
+ import { createRegistryIssue } from '@vibe-agent-toolkit/agent-schema';
15
16
  import { createAjvWithUriFormats } from './ajv-factory.js';
17
+ import { issueLocation } from './utils.js';
16
18
  /**
17
19
  * Validate frontmatter against a JSON Schema.
18
20
  *
@@ -27,6 +29,7 @@ import { createAjvWithUriFormats } from './ajv-factory.js';
27
29
  * @param resourcePath - File path for error reporting
28
30
  * @param mode - Validation mode: 'strict' (default) or 'permissive'
29
31
  * @param schemaPath - Path to schema file (for error context)
32
+ * @param projectRoot - Project root for computing relative issue locations
30
33
  * @returns Array of validation issues (empty if valid)
31
34
  *
32
35
  * @example
@@ -45,7 +48,7 @@ import { createAjvWithUriFormats } from './ajv-factory.js';
45
48
  * );
46
49
  * ```
47
50
  */
48
- export function validateFrontmatter(frontmatter, schema, resourcePath, mode = 'strict', schemaPath) {
51
+ export function validateFrontmatter(frontmatter, schema, resourcePath, mode = 'strict', schemaPath, projectRoot) {
49
52
  const issues = [];
50
53
  // In permissive mode, clone schema and set additionalProperties: true
51
54
  let effectiveSchema = schema;
@@ -72,13 +75,7 @@ export function validateFrontmatter(frontmatter, schema, resourcePath, mode = 's
72
75
  // Build context message with schema path and validation mode
73
76
  const schemaContext = schemaPath ? ` (schema: ${schemaPath}, mode: ${mode})` : '';
74
77
  const requiredFields = schemaRequires.join(', ');
75
- issues.push({
76
- resourcePath,
77
- line: 1,
78
- type: 'frontmatter_missing',
79
- link: '',
80
- message: `No frontmatter found in file. Schema requires: ${requiredFields}${schemaContext}`,
81
- });
78
+ issues.push(createRegistryIssue('FRONTMATTER_MISSING', `No frontmatter found in file. Schema requires: ${requiredFields}${schemaContext}`, { location: issueLocation(resourcePath, projectRoot), line: 1 }));
82
79
  }
83
80
  return issues;
84
81
  }
@@ -90,13 +87,10 @@ export function validateFrontmatter(frontmatter, schema, resourcePath, mode = 's
90
87
  // Format validation errors with helpful messages
91
88
  for (const error of validate.errors) {
92
89
  const message = formatValidationError(error, frontmatter, mode, schemaPath);
93
- issues.push({
94
- resourcePath,
90
+ issues.push(createRegistryIssue('FRONTMATTER_SCHEMA_ERROR', message, {
91
+ location: issueLocation(resourcePath, projectRoot),
95
92
  line: 1,
96
- type: 'frontmatter_schema_error',
97
- link: '',
98
- message,
99
- });
93
+ }));
100
94
  }
101
95
  return issues;
102
96
  }
@@ -1 +1 @@
1
- {"version":3,"file":"frontmatter-validator.js","sourceRoot":"","sources":["../src/frontmatter-validator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"frontmatter-validator.js","sourceRoot":"","sources":["../src/frontmatter-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,mBAAmB,EAAwB,MAAM,kCAAkC,CAAC;AAE7F,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAE3D,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,MAAM,UAAU,mBAAmB,CACjC,WAAgD,EAChD,MAAc,EACd,YAAoB,EACpB,OAAuB,QAAQ,EAC/B,UAAmB,EACnB,WAAoB;IAEpB,MAAM,MAAM,GAAsB,EAAE,CAAC;IAErC,sEAAsE;IACtE,IAAI,eAAe,GAAG,MAAM,CAAC;IAC7B,IAAI,IAAI,KAAK,YAAY,EAAE,CAAC;QAC1B,eAAe,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAC;IACjD,CAAC;IAED,uEAAuE;IACvE,qEAAqE;IACrE,oEAAoE;IACpE,4EAA4E;IAC5E,iEAAiE;IACjE,iEAAiE;IACjE,MAAM,GAAG,GAAG,uBAAuB,CAAC;QAClC,MAAM,EAAE,KAAK;QACb,SAAS,EAAE,IAAI;QACf,eAAe,EAAE,IAAI;KACtB,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;IAE9C,iCAAiC;IACjC,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,sCAAsC;QACtC,MAAM,cAAc,GAAI,MAAkC,CAAC,QAAQ,CAAC;QACpE,IAAI,cAAc,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChD,6DAA6D;YAC7D,MAAM,aAAa,GAAG,UAAU,CAAC,CAAC,CAAC,aAAa,UAAU,WAAW,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAClF,MAAM,cAAc,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAEjD,MAAM,CAAC,IAAI,CACT,mBAAmB,CACjB,qBAAqB,EACrB,kDAAkD,cAAc,GAAG,aAAa,EAAE,EAClF,EAAE,QAAQ,EAAE,aAAa,CAAC,YAAY,EAAE,WAAW,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAChE,CACF,CAAC;QACJ,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,uDAAuD;IACvD,MAAM,KAAK,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC;IAEpC,IAAI,KAAK,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;QAC9B,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,iDAAiD;IACjD,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,qBAAqB,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;QAC5E,MAAM,CAAC,IAAI,CACT,mBAAmB,CAAC,0BAA0B,EAAE,OAAO,EAAE;YACvD,QAAQ,EAAE,aAAa,CAAC,YAAY,EAAE,WAAW,CAAC;YAClD,IAAI,EAAE,CAAC;SACR,CAAC,CACH,CAAC;IACJ,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,qBAAqB,CAC5B,KAAoG,EACpG,WAAoC,EACpC,IAAoB,EACpB,UAAmB;IAEnB,MAAM,KAAK,GAAG,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,MAAM,CAAC;IAC9D,MAAM,SAAS,GAAG,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC;IAEtD,+BAA+B;IAC/B,MAAM,WAAW,GAAG,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,cAAc,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;IACxF,MAAM,cAAc,GAAG,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IAE7F,IAAI,OAAO,GAAG,sCAAsC,SAAS,WAAW,cAAc,GAAG,CAAC;IAE1F,kCAAkC;IAClC,IAAI,KAAK,CAAC,OAAO,KAAK,MAAM,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC,eAAe,CAAC,EAAE,CAAC;QAChE,MAAM,OAAO,GAAI,KAAK,CAAC,MAAM,CAAC,eAAe,CAAe;aACzD,GAAG,CAAC,CAAC,CAAU,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;aACtC,IAAI,CAAC,IAAI,CAAC,CAAC;QACd,OAAO,IAAI,sBAAsB,OAAO,EAAE,CAAC;IAC7C,CAAC;SAAM,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC;QACpE,oEAAoE;QACpE,OAAO,IAAI,yBAAyB,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC;IAChF,CAAC;SAAM,IAAI,KAAK,CAAC,OAAO,KAAK,MAAM,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC;QAC9D,oEAAoE;QACpE,OAAO,IAAI,oBAAoB,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;IACxE,CAAC;SAAM,IAAI,KAAK,CAAC,OAAO,KAAK,UAAU,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC,iBAAiB,CAAC,EAAE,CAAC;QAC7E,oEAAoE;QACpE,OAAO,IAAI,gCAAgC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,EAAE,CAAC;IAC/F,CAAC;SAAM,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QACzB,OAAO,IAAI,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC;IAClC,CAAC;IAED,8DAA8D;IAC9D,MAAM,aAAa,GAAG,UAAU,CAAC,CAAC,CAAC,aAAa,UAAU,WAAW,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAClF,OAAO,IAAI,aAAa,CAAC;IAEzB,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;GAMG;AACH,SAAS,cAAc,CAAC,GAA4B,EAAE,IAAY;IAChE,2HAA2H;IAC3H,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC9C,IAAI,OAAO,GAAY,GAAG,CAAC;IAE3B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YACpD,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO,GAAI,OAAmC,CAAC,IAAI,CAAC,CAAC;IACvD,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,oBAAoB,CAAC,MAAc;IAC1C,wCAAwC;IACxC,MAAM,MAAM,GAAG,eAAe,CAAC,MAAM,CAA4B,CAAC;IAElE,+DAA+D;IAC/D,wBAAwB,CAAC,MAAM,CAAC,CAAC;IAEjC,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;GAIG;AACH,SAAS,wBAAwB,CAAC,GAA4B;IAC5D,8DAA8D;IAC9D,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QAC5C,OAAO;IACT,CAAC;IAED,6DAA6D;IAC7D,MAAM,SAAS,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9B,MAAM,YAAY,GAAG,SAAS,KAAK,QAAQ,CAAC;IAC5C,MAAM,aAAa,GAAG,YAAY,IAAI,GAAG,CAAC;IAE1C,IAAI,YAAY,IAAI,aAAa,EAAE,CAAC;QAClC,GAAG,CAAC,sBAAsB,CAAC,GAAG,IAAI,CAAC;IACrC,CAAC;IAED,0BAA0B;IAC1B,uBAAuB,CAAC,GAAG,CAAC,CAAC;IAE7B,2DAA2D;IAC3D,oBAAoB,CAAC,GAAG,CAAC,CAAC;AAC5B,CAAC;AAED;;;;GAIG;AACH,SAAS,uBAAuB,CAAC,GAA4B;IAC3D,IAAI,GAAG,CAAC,YAAY,CAAC,KAAK,SAAS,IAAI,OAAO,GAAG,CAAC,YAAY,CAAC,KAAK,QAAQ,EAAE,CAAC;QAC7E,OAAO;IACT,CAAC;IAED,MAAM,UAAU,GAAG,GAAG,CAAC,YAAY,CAA4B,CAAC;IAChE,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YAChD,wBAAwB,CAAC,KAAgC,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,SAAS,oBAAoB,CAAC,GAA4B;IACxD,MAAM,UAAU,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAExD,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QACvB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,SAAS;QACX,CAAC;QAED,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACzB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;oBAC9C,wBAAwB,CAAC,IAA+B,CAAC,CAAC;gBAC5D,CAAC;YACH,CAAC;QACH,CAAC;aAAM,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACvD,wBAAwB,CAAC,KAAgC,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * HTML resource parser.
3
+ *
4
+ * Parses local HTML files into the shared `ParseResult` shape:
5
+ * - `<a href>` and `<img src>` links (classified by `classifyLink`)
6
+ * - `id` / `name` attributes as fragment anchors
7
+ * - well-formedness diagnostics from parse5's `onParseError`
8
+ *
9
+ * Uses parse5 (WHATWG-conformant). The parse5 document + element walker are
10
+ * exported so the link rewriter (html-transform.ts) shares one parser path.
11
+ *
12
+ * Non-goal: `<base href>` is not honored — relative links are resolved against
13
+ * the file's own directory, not a document base.
14
+ */
15
+ import { type DefaultTreeAdapterMap } from 'parse5';
16
+ import { type ParseResult } from './link-parser.js';
17
+ import type { HtmlParseError } from './schemas/resource-metadata.js';
18
+ type P5Node = DefaultTreeAdapterMap['node'];
19
+ type P5Element = DefaultTreeAdapterMap['element'];
20
+ /** A parsed parse5 document together with any well-formedness diagnostics. */
21
+ export interface HtmlDocument {
22
+ document: DefaultTreeAdapterMap['document'];
23
+ parseErrors: HtmlParseError[];
24
+ }
25
+ /**
26
+ * Parse an HTML source string with source-location info and collect parser
27
+ * errors. Shared by `parseHtml` (link/anchor extraction) and `rewriteHtmlLinks`
28
+ * (attribute offset splicing).
29
+ */
30
+ export declare function parseHtmlDocument(source: string): HtmlDocument;
31
+ /**
32
+ * Depth-first walk yielding every element node in the tree.
33
+ *
34
+ * Deliberate gap: a `<template>` element's content lives in its separate
35
+ * `content` fragment (not `childNodes`), so links inside `<template>` are not
36
+ * walked, and foreign-content (SVG/MathML) subtrees are not special-cased.
37
+ * Both are rare in the content link graph we rewrite.
38
+ */
39
+ export declare function walkElements(node: P5Node): Generator<P5Element>;
40
+ /**
41
+ * Parse an HTML file into a `ParseResult`.
42
+ *
43
+ * @param filePath - Absolute path to the HTML file.
44
+ */
45
+ export declare function parseHtml(filePath: string): Promise<ParseResult>;
46
+ export {};
47
+ //# sourceMappingURL=html-link-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html-link-parser.d.ts","sourceRoot":"","sources":["../src/html-link-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,EAAS,KAAK,qBAAqB,EAAE,MAAM,QAAQ,CAAC;AAE3D,OAAO,EAAgB,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAGrE,KAAK,MAAM,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC;AAC5C,KAAK,SAAS,GAAG,qBAAqB,CAAC,SAAS,CAAC,CAAC;AAGlD,8EAA8E;AAC9E,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,qBAAqB,CAAC,UAAU,CAAC,CAAC;IAC5C,WAAW,EAAE,cAAc,EAAE,CAAC;CAC/B;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAW9D;AAED;;;;;;;GAOG;AACH,wBAAiB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC,SAAS,CAAC,CAShE;AAuCD;;;;GAIG;AACH,wBAAsB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CA2BtE"}
@@ -0,0 +1,111 @@
1
+ /**
2
+ * HTML resource parser.
3
+ *
4
+ * Parses local HTML files into the shared `ParseResult` shape:
5
+ * - `<a href>` and `<img src>` links (classified by `classifyLink`)
6
+ * - `id` / `name` attributes as fragment anchors
7
+ * - well-formedness diagnostics from parse5's `onParseError`
8
+ *
9
+ * Uses parse5 (WHATWG-conformant). The parse5 document + element walker are
10
+ * exported so the link rewriter (html-transform.ts) shares one parser path.
11
+ *
12
+ * Non-goal: `<base href>` is not honored — relative links are resolved against
13
+ * the file's own directory, not a document base.
14
+ */
15
+ import { readFile, stat } from 'node:fs/promises';
16
+ import { parse } from 'parse5';
17
+ import { classifyLink } from './link-parser.js';
18
+ /**
19
+ * Parse an HTML source string with source-location info and collect parser
20
+ * errors. Shared by `parseHtml` (link/anchor extraction) and `rewriteHtmlLinks`
21
+ * (attribute offset splicing).
22
+ */
23
+ export function parseHtmlDocument(source) {
24
+ const parseErrors = [];
25
+ const document = parse(source, {
26
+ sourceCodeLocationInfo: true,
27
+ onParseError: (err) => {
28
+ // parse5's ParserError extends Location which always has startLine: number.
29
+ // We always include line since it is always present.
30
+ parseErrors.push({ message: err.code, line: err.startLine });
31
+ },
32
+ });
33
+ return { document, parseErrors };
34
+ }
35
+ /**
36
+ * Depth-first walk yielding every element node in the tree.
37
+ *
38
+ * Deliberate gap: a `<template>` element's content lives in its separate
39
+ * `content` fragment (not `childNodes`), so links inside `<template>` are not
40
+ * walked, and foreign-content (SVG/MathML) subtrees are not special-cased.
41
+ * Both are rare in the content link graph we rewrite.
42
+ */
43
+ export function* walkElements(node) {
44
+ if ('tagName' in node) {
45
+ yield node;
46
+ }
47
+ if ('childNodes' in node) {
48
+ for (const child of node.childNodes) {
49
+ yield* walkElements(child);
50
+ }
51
+ }
52
+ }
53
+ function getAttr(element, name) {
54
+ return element.attrs.find((a) => a.name === name)?.value;
55
+ }
56
+ function makeLink(href, line) {
57
+ return { text: '', href, type: classifyLink(href), ...(line !== undefined && { line }) };
58
+ }
59
+ function visitElement(element, links, anchors) {
60
+ const line = element.sourceCodeLocation?.startLine;
61
+ if (element.tagName === 'a') {
62
+ const href = getAttr(element, 'href');
63
+ if (href !== undefined) {
64
+ links.push(makeLink(href, line));
65
+ }
66
+ const name = getAttr(element, 'name');
67
+ if (name !== undefined && name !== '') {
68
+ anchors.add(name);
69
+ }
70
+ }
71
+ else if (element.tagName === 'img') {
72
+ const src = getAttr(element, 'src');
73
+ if (src !== undefined) {
74
+ links.push(makeLink(src, line));
75
+ }
76
+ }
77
+ const id = getAttr(element, 'id');
78
+ if (id !== undefined && id !== '') {
79
+ anchors.add(id);
80
+ }
81
+ }
82
+ /**
83
+ * Parse an HTML file into a `ParseResult`.
84
+ *
85
+ * @param filePath - Absolute path to the HTML file.
86
+ */
87
+ export async function parseHtml(filePath) {
88
+ const [content, stats] = await Promise.all([
89
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- filePath is a user-provided path parameter
90
+ readFile(filePath, 'utf-8'),
91
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- filePath is a user-provided path parameter
92
+ stat(filePath),
93
+ ]);
94
+ const { document, parseErrors } = parseHtmlDocument(content);
95
+ const links = [];
96
+ const anchors = new Set();
97
+ for (const element of walkElements(document)) {
98
+ visitElement(element, links, anchors);
99
+ }
100
+ const anchorList = [...anchors];
101
+ return {
102
+ links,
103
+ headings: [],
104
+ content,
105
+ sizeBytes: stats.size,
106
+ estimatedTokenCount: Math.ceil(content.length / 4),
107
+ ...(anchorList.length > 0 && { anchors: anchorList }),
108
+ ...(parseErrors.length > 0 && { parseErrors }),
109
+ };
110
+ }
111
+ //# sourceMappingURL=html-link-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html-link-parser.js","sourceRoot":"","sources":["../src/html-link-parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Structure-preserving HTML link rewriter.
3
+ *
4
+ * Rewrites `<a href>` and `<img src>` attribute VALUES in place by splicing the
5
+ * original source string at parse5-reported offsets. The document is never
6
+ * re-serialized (parse5's serializer normalizes whitespace, quotes, void
7
+ * elements, and the doctype), so unchanged input round-trips byte-for-byte.
8
+ *
9
+ * Uses the same `RewriteHref` callback model as `rewriteBodyLinks` — callers
10
+ * supply per-href target resolution; this module owns only the splice mechanics.
11
+ *
12
+ * Non-goal: `<base href>` is not honored. Relative hrefs are resolved by the
13
+ * caller against the file's own directory; a `<base>` element that would
14
+ * override that in a browser is ignored.
15
+ */
16
+ import type { RewriteHref } from './rewriter-helpers.js';
17
+ /** A wanted link rewrite that could not be spliced back into the source. */
18
+ export interface UnappliedRewrite {
19
+ tagName: string;
20
+ attr: string;
21
+ /** The original attribute value the rewrite targeted. */
22
+ from: string;
23
+ /** The value the rewrite wanted to write. */
24
+ to: string;
25
+ /**
26
+ * Why the splice could not be located:
27
+ * - `no-source-location` — parse5 omitted the attribute's offsets (synthesized
28
+ * during error recovery on malformed input).
29
+ * - `unparseable-attribute` — the attribute's source span had no locatable
30
+ * value (e.g. an unterminated quote).
31
+ */
32
+ reason: 'no-source-location' | 'unparseable-attribute';
33
+ }
34
+ /**
35
+ * Rewrite `<a href>` / `<img src>` values in `source` using `rewriteHref`.
36
+ * Returns `source` unchanged (byte-for-byte) when no value changes.
37
+ *
38
+ * A rewrite that is wanted (the href resolves to a new value) but cannot be
39
+ * spliced back — because parse5 omitted the source location or the attribute
40
+ * span is unparseable — is reported via `onUnapplied` rather than dropped
41
+ * silently. Malformed pages are exactly the ones that hit this path, so the
42
+ * caller can surface it instead of shipping a stale link.
43
+ */
44
+ export declare function rewriteHtmlLinks(source: string, rewriteHref: RewriteHref, onUnapplied?: (info: UnappliedRewrite) => void): string;
45
+ //# sourceMappingURL=html-transform.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html-transform.d.ts","sourceRoot":"","sources":["../src/html-transform.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAqEzD,4EAA4E;AAC5E,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,EAAE,EAAE,MAAM,CAAC;IACX;;;;;;OAMG;IACH,MAAM,EAAE,oBAAoB,GAAG,uBAAuB,CAAC;CACxD;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,WAAW,EACxB,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,gBAAgB,KAAK,IAAI,GAC7C,MAAM,CAsCR"}