From caa411504c224dd4506e7c52086f97a8c380afe3 Mon Sep 17 00:00:00 2001 From: HiDeoo <494699+HiDeoo@users.noreply.github.com> Date: Sat, 25 May 2024 18:53:44 +0200 Subject: [PATCH] feat: adds support for glob patterns with the `exclude` option --- docs/src/content/docs/configuration.md | 14 +++++++++----- packages/starlight-links-validator/index.ts | 3 +-- .../starlight-links-validator/libs/validation.ts | 5 +++-- packages/starlight-links-validator/package.json | 2 ++ .../tests/exclude.test.ts | 6 ++++-- .../tests/fixtures/exclude/astro.config.ts | 4 +++- .../fixtures/exclude/src/content/docs/index.md | 9 +++++++++ pnpm-lock.yaml | 15 +++++++++++++++ 8 files changed, 46 insertions(+), 12 deletions(-) diff --git a/docs/src/content/docs/configuration.md b/docs/src/content/docs/configuration.md index 455e01f..9b10fae 100644 --- a/docs/src/content/docs/configuration.md +++ b/docs/src/content/docs/configuration.md @@ -106,11 +106,9 @@ export default defineConfig({ **Type:** `string[]` **Default:** `[]` -A list of links that should be excluded from validation. +A list of links or [glob patterns](https://github.com/micromatch/picomatch#globbing-features) that should be excluded from validation. -The links in this list must exactly match links as they appear in Markdown and will be ignored by the plugin. - -This option should be used with caution but can be useful to exclude links that are not meant to be validated like redirects only existing in production or links to [custom pages](https://starlight.astro.build/guides/pages/#custom-pages) that are not part of your documentation. +This option should be used with caution but can be useful to exclude links that are not meant to be validated like redirects only existing in production or links to [custom pages](https://starlight.astro.build/guides/pages/#custom-pages) that are automatically generated or not part of your documentation. ```js {6} export default defineConfig({ @@ -118,10 +116,16 @@ export default defineConfig({ starlight({ plugins: [ starlightLinksValidator({ - exclude: ['/social/discord', '/social/twitter'], + exclude: ['/social/twitter', '/api/{interface,functions}/**/*'], }), ], }), ], }) ``` + +:::tip + +You can use this [webpage](https://www.digitalocean.com/community/tools/glob) to generate and test glob patterns. + +::: diff --git a/packages/starlight-links-validator/index.ts b/packages/starlight-links-validator/index.ts index 2c9ee45..7939cf1 100644 --- a/packages/starlight-links-validator/index.ts +++ b/packages/starlight-links-validator/index.ts @@ -34,10 +34,9 @@ const starlightLinksValidatorOptionsSchema = z */ errorOnRelativeLinks: z.boolean().default(true), /** - * Defines a list of links that should be excluded from validation. + * Defines a list of links or glob patterns that should be excluded from validation. * * The links in this list will be ignored by the plugin and will not be validated. - * The list must exactly match links as they appear in Markdown. * * @default [] */ diff --git a/packages/starlight-links-validator/libs/validation.ts b/packages/starlight-links-validator/libs/validation.ts index 94fd81b..14cda25 100644 --- a/packages/starlight-links-validator/libs/validation.ts +++ b/packages/starlight-links-validator/libs/validation.ts @@ -5,6 +5,7 @@ import { fileURLToPath } from 'node:url' import type { StarlightPlugin } from '@astrojs/starlight/types' import type { AstroConfig, AstroIntegrationLogger } from 'astro' import { bgGreen, black, blue, dim, green, red } from 'kleur/colors' +import picomatch from 'picomatch' import type { StarlightLinksValidatorOptions } from '..' @@ -216,10 +217,10 @@ function isValidAsset(path: string, context: ValidationContext) { } /** - * Check if a link is explicitly excluded from validation by the user. + * Check if a link is excluded from validation by the user. */ function isExcludedLink(link: string, context: ValidationContext) { - return context.options.exclude.includes(link) + return picomatch(context.options.exclude)(link) } function addError(errors: ValidationErrors, filePath: string, link: string, type: ValidationErrorType) { diff --git a/packages/starlight-links-validator/package.json b/packages/starlight-links-validator/package.json index faa513f..331de19 100644 --- a/packages/starlight-links-validator/package.json +++ b/packages/starlight-links-validator/package.json @@ -20,6 +20,7 @@ "is-absolute-url": "4.0.1", "kleur": "4.1.5", "mdast-util-to-string": "4.0.0", + "picomatch": "4.0.2", "unist-util-visit": "5.0.0" }, "devDependencies": { @@ -27,6 +28,7 @@ "@types/hast": "3.0.3", "@types/mdast": "4.0.3", "@types/node": "18.17.18", + "@types/picomatch": "2.3.3", "astro": "4.0.4", "mdast-util-mdx-jsx": "3.0.0", "typescript": "5.1.3", diff --git a/packages/starlight-links-validator/tests/exclude.test.ts b/packages/starlight-links-validator/tests/exclude.test.ts index 5ed065b..ecb8614 100644 --- a/packages/starlight-links-validator/tests/exclude.test.ts +++ b/packages/starlight-links-validator/tests/exclude.test.ts @@ -4,19 +4,21 @@ import { ValidationErrorType } from '../libs/validation' import { expectValidationErrorCount, expectValidationErrors, loadFixture } from './utils' -test('should ignore links that are explicitly excluded from validation', async () => { +test('should ignore links that are excluded from validation', async () => { expect.assertions(2) try { await loadFixture('exclude') } catch (error) { - expectValidationErrorCount(error, 4, 1) + expectValidationErrorCount(error, 6, 1) expectValidationErrors(error, '/', [ ['/excluded/', ValidationErrorType.InvalidLink], ['/excluded#test', ValidationErrorType.InvalidLink], ['/test/excluded', ValidationErrorType.InvalidLink], ['/test/excluded/test', ValidationErrorType.InvalidLink], + ['/api/getting-started', ValidationErrorType.InvalidLink], + ['/api/class/baz', ValidationErrorType.InvalidLink], ]) } }) diff --git a/packages/starlight-links-validator/tests/fixtures/exclude/astro.config.ts b/packages/starlight-links-validator/tests/fixtures/exclude/astro.config.ts index 97d7c02..e525aac 100644 --- a/packages/starlight-links-validator/tests/fixtures/exclude/astro.config.ts +++ b/packages/starlight-links-validator/tests/fixtures/exclude/astro.config.ts @@ -6,7 +6,9 @@ import starlightLinksValidator from '../..' export default defineConfig({ integrations: [ starlight({ - plugins: [starlightLinksValidator({ exclude: ['/excluded'] })], + plugins: [ + starlightLinksValidator({ exclude: ['/excluded', '/glob/*', '/api/{interface,functions}/**/*', '/tests/**'] }), + ], title: 'Starlight Links Validator Tests - exclude', }), ], diff --git a/packages/starlight-links-validator/tests/fixtures/exclude/src/content/docs/index.md b/packages/starlight-links-validator/tests/fixtures/exclude/src/content/docs/index.md index 753609c..a1aae79 100644 --- a/packages/starlight-links-validator/tests/fixtures/exclude/src/content/docs/index.md +++ b/packages/starlight-links-validator/tests/fixtures/exclude/src/content/docs/index.md @@ -18,3 +18,12 @@ title: Index - [More non-excluded link](/excluded#test) - [Another non-excluded link](/test/excluded) - [And another non-excluded link](/test/excluded/test) + +# Glob exclude + +- [Glob excluded link](/glob/test/) +- [Another glob excluded link](/api/interface/foo) +- [More glob excluded link](/api/functions/bar) +- [And another glob excluded link](/tests/e2e/thing) +- [Glob non-excluded link](/api/getting-started) +- [Another glob non-excluded link](/api/class/baz) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4641de2..c2accff 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -80,6 +80,9 @@ importers: mdast-util-to-string: specifier: 4.0.0 version: 4.0.0 + picomatch: + specifier: 4.0.2 + version: 4.0.2 unist-util-visit: specifier: 5.0.0 version: 5.0.0 @@ -96,6 +99,9 @@ importers: '@types/node': specifier: 18.17.18 version: 18.17.18 + '@types/picomatch': + specifier: 2.3.3 + version: 2.3.3 astro: specifier: 4.0.4 version: 4.0.4(@types/node@18.17.18)(typescript@5.1.3) @@ -1114,6 +1120,10 @@ packages: /@types/parse5@6.0.3: resolution: {integrity: sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==} + /@types/picomatch@2.3.3: + resolution: {integrity: sha512-Yll76ZHikRFCyz/pffKGjrCwe/le2CDwOP5F210KQo27kpRE46U2rDnzikNlVn6/ezH3Mhn46bJMTfeVTtcYMg==} + dev: true + /@types/sax@1.2.4: resolution: {integrity: sha512-pSAff4IAxJjfAXUG6tFkO7dsSbTmf8CtUpfhhZ5VhkRpC4628tJhh3+V6H1E+/Gs9piSzYKT5yzHO5M4GG9jkw==} dependencies: @@ -4798,6 +4808,11 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} + /picomatch@4.0.2: + resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + engines: {node: '>=12'} + dev: false + /pidtree@0.6.0: resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} engines: {node: '>=0.10'}