starlight-links-validator 0.6.0 → 0.7.1

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/index.ts CHANGED
@@ -64,7 +64,7 @@ export default function starlightLinksValidatorPlugin(
64
64
  })
65
65
  },
66
66
  'astro:build:done': ({ dir, pages }) => {
67
- const errors = validateLinks(pages, dir, astroConfig.base, starlightConfig, options.data)
67
+ const errors = validateLinks(pages, dir, astroConfig, starlightConfig, options.data)
68
68
 
69
69
  logErrors(logger, errors)
70
70
 
@@ -3,7 +3,7 @@ import { posix } from 'node:path'
3
3
  import { fileURLToPath } from 'node:url'
4
4
 
5
5
  import type { StarlightPlugin } from '@astrojs/starlight/types'
6
- import type { AstroIntegrationLogger } from 'astro'
6
+ import type { AstroConfig, AstroIntegrationLogger } from 'astro'
7
7
  import { bgGreen, black, blue, dim, green, red } from 'kleur/colors'
8
8
 
9
9
  import type { StarlightLinksValidatorOptions } from '..'
@@ -17,12 +17,13 @@ export const ValidationErrorType = {
17
17
  InvalidAnchor: 'invalid anchor',
18
18
  InvalidLink: 'invalid link',
19
19
  RelativeLink: 'relative link',
20
+ TrailingSlash: 'trailing slash',
20
21
  } as const
21
22
 
22
23
  export function validateLinks(
23
24
  pages: PageData[],
24
25
  outputDir: URL,
25
- base: string,
26
+ astroConfig: AstroConfig,
26
27
  starlightConfig: StarlightUserConfig,
27
28
  options: StarlightLinksValidatorOptions,
28
29
  ): ValidationErrors {
@@ -33,7 +34,9 @@ export function validateLinks(
33
34
  const allPages: Pages = new Set(
34
35
  pages.map((page) =>
35
36
  ensureTrailingSlash(
36
- base === '/' ? stripLeadingSlash(page.pathname) : posix.join(stripLeadingSlash(base), page.pathname),
37
+ astroConfig.base === '/'
38
+ ? stripLeadingSlash(page.pathname)
39
+ : posix.join(stripLeadingSlash(astroConfig.base), page.pathname),
37
40
  ),
38
41
  ),
39
42
  )
@@ -43,7 +46,7 @@ export function validateLinks(
43
46
  for (const [filePath, fileLinks] of links) {
44
47
  for (const link of fileLinks) {
45
48
  const validationContext: ValidationContext = {
46
- base,
49
+ astroConfig,
47
50
  errors,
48
51
  filePath,
49
52
  headings,
@@ -103,12 +106,12 @@ export function logErrors(pluginLogger: AstroIntegrationLogger, errors: Validati
103
106
  * Validate a link to another internal page that may or may not have a hash.
104
107
  */
105
108
  function validateLink(context: ValidationContext) {
106
- const { errors, filePath, link, localeConfig, options, pages } = context
109
+ const { astroConfig, errors, filePath, link, localeConfig, options, pages } = context
107
110
 
108
111
  const sanitizedLink = link.replace(/^\//, '')
109
112
  const segments = sanitizedLink.split('#')
110
113
 
111
- let path = segments[0]
114
+ const path = segments[0]
112
115
  const hash = segments[1]
113
116
 
114
117
  if (path === undefined) {
@@ -127,10 +130,10 @@ function validateLink(context: ValidationContext) {
127
130
  return
128
131
  }
129
132
 
130
- path = ensureTrailingSlash(path)
133
+ const sanitizedPath = ensureTrailingSlash(path)
131
134
 
132
- const isValidPage = pages.has(path)
133
- const fileHeadings = getFileHeadings(path, context)
135
+ const isValidPage = pages.has(sanitizedPath)
136
+ const fileHeadings = getFileHeadings(sanitizedPath, context)
134
137
 
135
138
  if (!isValidPage || !fileHeadings) {
136
139
  addError(errors, filePath, link, ValidationErrorType.InvalidLink)
@@ -144,6 +147,16 @@ function validateLink(context: ValidationContext) {
144
147
 
145
148
  if (hash && !fileHeadings.includes(hash)) {
146
149
  addError(errors, filePath, link, ValidationErrorType.InvalidAnchor)
150
+ return
151
+ }
152
+
153
+ if (
154
+ path.length > 0 &&
155
+ ((astroConfig.trailingSlash === 'always' && !path.endsWith('/')) ||
156
+ (astroConfig.trailingSlash === 'never' && path.endsWith('/')))
157
+ ) {
158
+ addError(errors, filePath, link, ValidationErrorType.TrailingSlash)
159
+ return
147
160
  }
148
161
  }
149
162
 
@@ -177,8 +190,8 @@ function validateSelfAnchor({ errors, link, filePath, headings }: ValidationCont
177
190
  * Check if a link is a valid asset in the build output directory.
178
191
  */
179
192
  function isValidAsset(path: string, context: ValidationContext) {
180
- if (context.base !== '/') {
181
- const base = stripLeadingSlash(context.base)
193
+ if (context.astroConfig.base !== '/') {
194
+ const base = stripLeadingSlash(context.astroConfig.base)
182
195
 
183
196
  if (path.startsWith(base)) {
184
197
  path = path.replace(new RegExp(`^${stripLeadingSlash(base)}/?`), '')
@@ -226,7 +239,7 @@ interface PageData {
226
239
  type Pages = Set<PageData['pathname']>
227
240
 
228
241
  interface ValidationContext {
229
- base: string
242
+ astroConfig: AstroConfig
230
243
  errors: ValidationErrors
231
244
  filePath: string
232
245
  headings: Headings
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "starlight-links-validator",
3
- "version": "0.6.0",
3
+ "version": "0.7.1",
4
4
  "license": "MIT",
5
5
  "description": "Starlight plugin to validate internal links.",
6
6
  "author": "HiDeoo <github@hideoo.dev> (https://hideoo.dev)",