Repository: HiDeoo/starlight-links-validator
Pull request #27 (2024-01-15 15:14:44)

Fixes validation of assets in the `public/` directory when using the Astro `base` option


Patch:
diff --git a/packages/starlight-links-validator/libs/validation.ts b/packages/starlight-links-validator/libs/validation.ts
index fcb8fbd..073364f 100644
--- a/packages/starlight-links-validator/libs/validation.ts
+++ b/packages/starlight-links-validator/libs/validation.ts
@@ -41,6 +41,7 @@ export function validateLinks(
   for (const [filePath, fileLinks] of links) {
     for (const link of fileLinks) {
       const validationContext: ValidationContext = {
+        base,
         errors,
         filePath,
         headings,
@@ -100,7 +101,7 @@ export function logErrors(pluginLogger: AstroIntegrationLogger, errors: Validati
  * Validate a link to another internal page that may or may not have a hash.
  */
 function validateLink(context: ValidationContext) {
-  const { errors, filePath, link, localeConfig, options, outputDir, pages } = context
+  const { errors, filePath, link, localeConfig, options, pages } = context
 
   const sanitizedLink = link.replace(/^\//, '')
   const segments = sanitizedLink.split('#')
@@ -120,7 +121,7 @@ function validateLink(context: ValidationContext) {
     return
   }
 
-  if (isValidAsset(path, outputDir)) {
+  if (isValidAsset(path, context)) {
     return
   }
 
@@ -173,8 +174,18 @@ function validateSelfAnchor({ errors, link, filePath, headings }: ValidationCont
 /**
  * Check if a link is a valid asset in the build output directory.
  */
-function isValidAsset(path: string, outputDir: URL) {
-  const filePath = fileURLToPath(new URL(path, outputDir))
+function isValidAsset(path: string, context: ValidationContext) {
+  if (context.base !== '/') {
+    const base = stripLeadingSlash(context.base)
+
+    if (path.startsWith(base)) {
+      path = path.replace(new RegExp(`^${stripLeadingSlash(base)}/?`), '')
+    } else {
+      return false
+    }
+  }
+
+  const filePath = fileURLToPath(new URL(path, context.outputDir))
 
   try {
     const stats = statSync(filePath)
@@ -213,6 +224,7 @@ interface PageData {
 type Pages = Set<PageData['pathname']>
 
 interface ValidationContext {
+  base: string
   errors: ValidationErrors
   filePath: string
   headings: Headings


Test patch:
diff --git a/packages/starlight-links-validator/tests/base-path.test.ts b/packages/starlight-links-validator/tests/base-path.test.ts
index eb26253..d37059d 100644
--- a/packages/starlight-links-validator/tests/base-path.test.ts
+++ b/packages/starlight-links-validator/tests/base-path.test.ts
@@ -10,7 +10,7 @@ test('should validate links when the `base` Astro option is set', async () => {
   try {
     await loadFixture('base-path')
   } catch (error) {
-    expectValidationErrorCount(error, 8, 1)
+    expectValidationErrorCount(error, 10, 1)
 
     expectValidationErrors(error, 'test/test/', [
       ['/guides/example', ValidationErrorType.InvalidLink],
@@ -21,6 +21,8 @@ test('should validate links when the `base` Astro option is set', async () => {
       ['/unknown/', ValidationErrorType.InvalidLink],
       ['/test/guides/example#unknown', ValidationErrorType.InvalidAnchor],
       ['/test/guides/example/#unknown', ValidationErrorType.InvalidAnchor],
+      ['/favicon.svg', ValidationErrorType.InvalidLink],
+      ['/guidelines/dummy.pdf', ValidationErrorType.InvalidLink],
     ])
   }
 })
diff --git a/packages/starlight-links-validator/tests/fixtures/base-path/src/content/docs/test.md b/packages/starlight-links-validator/tests/fixtures/base-path/src/content/docs/test.md
index e433187..b541dbd 100644
--- a/packages/starlight-links-validator/tests/fixtures/base-path/src/content/docs/test.md
+++ b/packages/starlight-links-validator/tests/fixtures/base-path/src/content/docs/test.md
@@ -23,3 +23,9 @@ title: Test
 
 - [Example page with unknown hash](/test/guides/example#unknown)
 - [Example page with unknown hash](/test/guides/example/#unknown)
+
+- [Link to an asset](/test/favicon.svg)
+- [Link to another asset](/test/guidelines/dummy.pdf)
+
+- [Link to an asset with missing base](/favicon.svg)
+- [Link to another asset with missing base](/guidelines/dummy.pdf)