diff --git a/packages/starlight-links-validator/libs/validation.ts b/packages/starlight-links-validator/libs/validation.ts
index cbc08bf..dbbc970 100644
--- a/packages/starlight-links-validator/libs/validation.ts
+++ b/packages/starlight-links-validator/libs/validation.ts
@@ -58,7 +58,7 @@ export function validateLinks(
pages: allPages,
}
- if (link.startsWith('#')) {
+ if (link.startsWith('#') || link.startsWith('?')) {
if (options.errorOnInvalidHashes) {
validateSelfHash(validationContext)
}
@@ -125,7 +125,7 @@ function validateLink(context: ValidationContext) {
throw new Error('Failed to validate a link with no path.')
}
- if (path.startsWith('.') || !link.startsWith('/')) {
+ if (path.startsWith('.') || (!link.startsWith('/') && !link.startsWith('?'))) {
if (options.errorOnRelativeLinks) {
addError(errors, filePath, link, ValidationErrorType.RelativeLink)
}
@@ -137,7 +137,7 @@ function validateLink(context: ValidationContext) {
return
}
- const sanitizedPath = ensureTrailingSlash(path)
+ const sanitizedPath = ensureTrailingSlash(stripQueryString(path))
const isValidPage = pages.has(sanitizedPath)
const fileHeadings = getFileHeadings(sanitizedPath, context)
@@ -183,7 +183,8 @@ function getFileHeadings(path: string, { headings, localeConfig, options }: Vali
* Validate a link to an hash in the same page.
*/
function validateSelfHash({ errors, link, filePath, headings }: ValidationContext) {
- const sanitizedHash = link.replace(/^#/, '')
+ const hash = link.split('#')[1] ?? link
+ const sanitizedHash = hash.replace(/^#/, '')
const fileHeadings = headings.get(filePath)
if (!fileHeadings) {
@@ -226,6 +227,10 @@ function isExcludedLink(link: string, context: ValidationContext) {
return picomatch(context.options.exclude)(link)
}
+function stripQueryString(path: string): string {
+ return path.split('?')[0] ?? path
+}
+
function addError(errors: ValidationErrors, filePath: string, link: string, type: ValidationErrorType) {
const fileErrors = errors.get(filePath) ?? []
fileErrors.push({ link, type })
diff --git a/packages/starlight-links-validator/tests/basics.test.ts b/packages/starlight-links-validator/tests/basics.test.ts
index c63bbe3..4021023 100644
--- a/packages/starlight-links-validator/tests/basics.test.ts
+++ b/packages/starlight-links-validator/tests/basics.test.ts
@@ -21,7 +21,7 @@ test('does not build with invalid links', async () => {
expect(status).toBe('error')
- expectValidationErrorCount(output, 35, 4)
+ expectValidationErrorCount(output, 59, 4)
expectValidationErrors(output, 'test/', [
['/https://starlight.astro.build/', ValidationErrorType.InvalidLink],
@@ -39,6 +39,17 @@ test('does not build with invalid links', async () => {
['#anotherDiv', ValidationErrorType.InvalidHash],
['/guides/page-with-custom-slug', ValidationErrorType.InvalidLink],
['/release/@pkg/v0.2.0', ValidationErrorType.InvalidLink],
+ ['/?query=string', ValidationErrorType.InvalidLink],
+ ['/unknown?query=string', ValidationErrorType.InvalidLink],
+ ['/unknown/?query=string', ValidationErrorType.InvalidLink],
+ ['/unknown?query=string#title', ValidationErrorType.InvalidLink],
+ ['/unknown/?query=string#title', ValidationErrorType.InvalidLink],
+ ['?query=string#links', ValidationErrorType.InvalidHash],
+ ['/guides/example/?query=string#links', ValidationErrorType.InvalidHash],
+ ['/icon.svg?query=string', ValidationErrorType.InvalidLink],
+ ['/guidelines/ui.pdf?query=string', ValidationErrorType.InvalidLink],
+ ['/unknown-ref?query=string', ValidationErrorType.InvalidLink],
+ ['?query=string#unknown-ref', ValidationErrorType.InvalidHash],
])
expectValidationErrors(output, 'guides/example/', [
@@ -54,6 +65,13 @@ test('does not build with invalid links', async () => {
['/linkbutton/', ValidationErrorType.InvalidLink],
['/linkbutton/#links', ValidationErrorType.InvalidLink],
['#linkbutton', ValidationErrorType.InvalidHash],
+ ['?query=string#links', ValidationErrorType.InvalidHash],
+ ['/unknown/?query=string#links', ValidationErrorType.InvalidLink],
+ ['/unknown?query=string', ValidationErrorType.InvalidLink],
+ ['/icon.svg?query=string', ValidationErrorType.InvalidLink],
+ ['/guidelines/ui.pdf?query=string', ValidationErrorType.InvalidLink],
+ ['/linkcard/?query=string', ValidationErrorType.InvalidLink],
+ ['/linkbutton/?query=string', ValidationErrorType.InvalidLink],
])
expectValidationErrors(output, 'guides/namespacetest/', [
@@ -68,5 +86,11 @@ test('does not build with invalid links', async () => {
['./guides/example', ValidationErrorType.RelativeLink],
['../test', ValidationErrorType.RelativeLink],
['test', ValidationErrorType.RelativeLink],
+ ['.?query=string', ValidationErrorType.RelativeLink],
+ ['./relative?query=string', ValidationErrorType.RelativeLink],
+ ['./test?query=string', ValidationErrorType.RelativeLink],
+ ['./guides/example?query=string', ValidationErrorType.RelativeLink],
+ ['../test?query=string', ValidationErrorType.RelativeLink],
+ ['test?query=string', ValidationErrorType.RelativeLink],
])
})
diff --git a/packages/starlight-links-validator/tests/fixtures/invalid-links/src/content/docs/guides/example.mdx b/packages/starlight-links-validator/tests/fixtures/invalid-links/src/content/docs/guides/example.mdx
index 972f2b1..66dacab 100644
--- a/packages/starlight-links-validator/tests/fixtures/invalid-links/src/content/docs/guides/example.mdx
+++ b/packages/starlight-links-validator/tests/fixtures/invalid-links/src/content/docs/guides/example.mdx
@@ -44,3 +44,19 @@ some content
LinkButton: unknown page
LinkButton: unknown page and hash
LinkButton: unknown hash
+
+## Query strings
+
+- [Link with query string to invalid hash in the same page](?query=string#links)
+- [Link with query string to invalid hash in another page](/unknown/?query=string#links)
+
+HTML link with query string to unknown page
+
+Link with query string to invalid asset
+Link with query string to another invalid asset
+
+
+
+
+
+LinkButton: unknown page with query string
diff --git a/packages/starlight-links-validator/tests/fixtures/invalid-links/src/content/docs/relative.md b/packages/starlight-links-validator/tests/fixtures/invalid-links/src/content/docs/relative.md
index f03f0c3..de78a65 100644
--- a/packages/starlight-links-validator/tests/fixtures/invalid-links/src/content/docs/relative.md
+++ b/packages/starlight-links-validator/tests/fixtures/invalid-links/src/content/docs/relative.md
@@ -8,3 +8,12 @@ title: Relative
- [Link to another page in another directory](./guides/example)
- [Link to another page in a parent directory](../test)
- [Another link to another page in the same directory](test)
+
+## Query strings
+
+- [Link with query string to the same page](.?query=string)
+- [Link with query string to the same page with its name](./relative?query=string)
+- [Link with query string to another page in the same directory](./test?query=string)
+- [Link with query string to another page in another directory](./guides/example?query=string)
+- [Link with query string to another page in a parent directory](../test?query=string)
+- [Another link with query string to another page in the same directory](test?query=string)
diff --git a/packages/starlight-links-validator/tests/fixtures/invalid-links/src/content/docs/test.md b/packages/starlight-links-validator/tests/fixtures/invalid-links/src/content/docs/test.md
index 5150ea5..235b987 100644
--- a/packages/starlight-links-validator/tests/fixtures/invalid-links/src/content/docs/test.md
+++ b/packages/starlight-links-validator/tests/fixtures/invalid-links/src/content/docs/test.md
@@ -51,3 +51,26 @@ some content
- [Link to page not using its custom slug](/guides/page-with-custom-slug)
- [Link to page using an invalid custom slug](/release/@pkg/v0.2.0)
+
+## Query strings
+
+- [Home page with query string](/?query=string)
+
+- [Unknown page with query string](/unknown?query=string)
+- [Unknown page with query string](/unknown/?query=string)
+
+- [Unknown page with query string and hash](/unknown?query=string#title)
+- [Unknown page with query string and hash](/unknown/?query=string#title)
+
+- [Link with query string to valid hash in this page](?query=string#some-links)
+- [Link with query string to invalid hash in this page](?query=string#links)
+- [Link with query string to valid hash in another MDX page](/guides/example/?query=string#some-links)
+- [Link with query string to invalid hash in another MDX page](/guides/example/?query=string#links)
+- [Link with query string to invalid asset](/icon.svg?query=string)
+- [Link with query string to another invalid asset](/guidelines/ui.pdf?query=string)
+
+- [Link reference with query string to unknwon page][ref-with-query-string-unknown-page]
+- [Link reference with query string to invalid hash][ref-with-query-string-invalid-hash]
+
+[ref-with-query-string-unknown-page]: /unknown-ref?query=string
+[ref-with-query-string-invalid-hash]: ?query=string#unknown-ref
diff --git a/packages/starlight-links-validator/tests/fixtures/valid-links/src/content/docs/index.md b/packages/starlight-links-validator/tests/fixtures/valid-links/src/content/docs/index.md
index 06af854..7ad6ba6 100644
--- a/packages/starlight-links-validator/tests/fixtures/valid-links/src/content/docs/index.md
+++ b/packages/starlight-links-validator/tests/fixtures/valid-links/src/content/docs/index.md
@@ -44,3 +44,27 @@ title: Index
## Link to page with custom slug
- [A page with custom slug](/release/@pkg/v0.1.0)
+
+## Query strings
+
+- [Home page with query string](/?query=string)
+
+- [Test page with query string](/test?query=string)
+- [Test page with query string](/test/?query=string)
+
+- [Test page with query string and hash](/test?query=string#title)
+- [Test page with query string and hash](/test/?query=string#title)
+
+- [Link to hash in this page with query string](?query=string#some-links)
+
+- [Link to an asset with query string](/favicon.svg?query=string)
+- [Link to another asset with query string](/guidelines/dummy.pdf?query=string)
+
+- [ref-with-query-string]
+- [Link reference with query string][ref-with-query-string]
+- [Link reference with query string and hash in this page][ref-with-query-string-and-hash-internal]
+- [Link reference with query string and hash in another page][ref-with-query-string-and-hash-external]
+
+[ref-with-query-string]: /test?query=string
+[ref-with-query-string-and-hash-internal]: ?query=string#some-links
+[ref-with-query-string-and-hash-external]: /test?query=string#title
diff --git a/packages/starlight-links-validator/tests/utils.ts b/packages/starlight-links-validator/tests/utils.ts
index 269555f..e8b65b2 100644
--- a/packages/starlight-links-validator/tests/utils.ts
+++ b/packages/starlight-links-validator/tests/utils.ts
@@ -50,7 +50,10 @@ export function expectValidationErrors(
expect(output).toMatch(
new RegExp(`▶ ${path}
${validationErrors
- .map(([link, type], index) => `.* ${index < validationErrors.length - 1 ? '├' : '└'}─ ${link} - ${type}`)
+ .map(
+ ([link, type], index) =>
+ `.* ${index < validationErrors.length - 1 ? '├' : '└'}─ ${link.replaceAll('?', '\\?')} - ${type}`,
+ )
.join('\n')}`),
)
}