From 8f86a303ad6d8d6cd4b56e943fdc64df1d821fc5 Mon Sep 17 00:00:00 2001 From: Lachlan Collins <1667261+lachlancollins@users.noreply.github.com> Date: Fri, 5 Dec 2025 18:45:11 +1100 Subject: [PATCH 1/2] docs: correct local relative links --- docs/framework/angular/reference/index.md | 2 +- docs/framework/preact/reference/index.md | 4 +- docs/framework/react/reference/index.md | 4 +- docs/framework/solid/reference/index.md | 4 +- docs/framework/svelte/reference/index.md | 4 +- docs/framework/vue/reference/index.md | 4 +- docs/reference/classes/Derived.md | 8 +- docs/reference/classes/Store.md | 2 +- docs/reference/functions/isUpdaterFunction.md | 2 +- docs/reference/index.md | 26 +++---- docs/reference/interfaces/DerivedFnProps.md | 4 +- docs/reference/interfaces/DerivedOptions.md | 8 +- docs/reference/interfaces/StoreOptions.md | 2 +- eslint.config.js | 2 +- nx.json | 4 + package.json | 14 ++-- packages/preact-store/vite.config.ts | 2 +- packages/react-store/vite.config.ts | 2 +- packages/solid-store/vite.config.ts | 2 +- packages/store/vite.config.ts | 2 +- packages/vue-store/vite.config.ts | 2 +- pnpm-lock.yaml | 38 +++------- scripts/{generateDocs.ts => generate-docs.ts} | 31 +------- scripts/publish.ts | 4 +- scripts/tsconfig.json | 4 - scripts/verify-links.ts | 75 +++++++++---------- tsconfig.json | 2 +- 27 files changed, 104 insertions(+), 154 deletions(-) rename scripts/{generateDocs.ts => generate-docs.ts} (71%) delete mode 100644 scripts/tsconfig.json diff --git a/docs/framework/angular/reference/index.md b/docs/framework/angular/reference/index.md index 8f338bf9..b77cf408 100644 --- a/docs/framework/angular/reference/index.md +++ b/docs/framework/angular/reference/index.md @@ -7,4 +7,4 @@ title: "@tanstack/angular-store" ## Functions -- [injectStore](../functions/injectStore.md) +- [injectStore](functions/injectStore.md) diff --git a/docs/framework/preact/reference/index.md b/docs/framework/preact/reference/index.md index 8ec275bf..1ef55ff2 100644 --- a/docs/framework/preact/reference/index.md +++ b/docs/framework/preact/reference/index.md @@ -7,5 +7,5 @@ title: "@tanstack/preact-store" ## Functions -- [shallow](../functions/shallow.md) -- [useStore](../functions/useStore.md) +- [shallow](functions/shallow.md) +- [useStore](functions/useStore.md) diff --git a/docs/framework/react/reference/index.md b/docs/framework/react/reference/index.md index 0b18df2e..11b180f1 100644 --- a/docs/framework/react/reference/index.md +++ b/docs/framework/react/reference/index.md @@ -7,5 +7,5 @@ title: "@tanstack/react-store" ## Functions -- [shallow](../functions/shallow.md) -- [useStore](../functions/useStore.md) +- [shallow](functions/shallow.md) +- [useStore](functions/useStore.md) diff --git a/docs/framework/solid/reference/index.md b/docs/framework/solid/reference/index.md index a262b507..71951743 100644 --- a/docs/framework/solid/reference/index.md +++ b/docs/framework/solid/reference/index.md @@ -7,5 +7,5 @@ title: "@tanstack/solid-store" ## Functions -- [shallow](../functions/shallow.md) -- [useStore](../functions/useStore.md) +- [shallow](functions/shallow.md) +- [useStore](functions/useStore.md) diff --git a/docs/framework/svelte/reference/index.md b/docs/framework/svelte/reference/index.md index 45dfadef..a423979e 100644 --- a/docs/framework/svelte/reference/index.md +++ b/docs/framework/svelte/reference/index.md @@ -7,5 +7,5 @@ title: "@tanstack/svelte-store" ## Functions -- [shallow](../functions/shallow.md) -- [useStore](../functions/useStore.md) +- [shallow](functions/shallow.md) +- [useStore](functions/useStore.md) diff --git a/docs/framework/vue/reference/index.md b/docs/framework/vue/reference/index.md index 308df8d8..63b86320 100644 --- a/docs/framework/vue/reference/index.md +++ b/docs/framework/vue/reference/index.md @@ -7,5 +7,5 @@ title: "@tanstack/vue-store" ## Functions -- [shallow](../functions/shallow.md) -- [useStore](../functions/useStore.md) +- [shallow](functions/shallow.md) +- [useStore](functions/useStore.md) diff --git a/docs/reference/classes/Derived.md b/docs/reference/classes/Derived.md index 63328e04..ef453e6a 100644 --- a/docs/reference/classes/Derived.md +++ b/docs/reference/classes/Derived.md @@ -15,7 +15,7 @@ Defined in: [derived.ts:61](https://github.com/TanStack/store/blob/main/packages ### TArr -`TArr` *extends* `ReadonlyArray`\<`Derived`\<`any`\> \| [`Store`](../Store.md)\<`any`\>\> = `ReadonlyArray`\<`any`\> +`TArr` *extends* `ReadonlyArray`\<`Derived`\<`any`\> \| [`Store`](Store.md)\<`any`\>\> = `ReadonlyArray`\<`any`\> ## Constructors @@ -31,7 +31,7 @@ Defined in: [derived.ts:96](https://github.com/TanStack/store/blob/main/packages ##### options -[`DerivedOptions`](../../interfaces/DerivedOptions.md)\<`TState`, `TArr`\> +[`DerivedOptions`](../interfaces/DerivedOptions.md)\<`TState`, `TArr`\> #### Returns @@ -183,7 +183,7 @@ Defined in: [derived.ts:105](https://github.com/TanStack/store/blob/main/package readonly ( \| `Derived`\<`any`, readonly `any`[]\> - \| [`Store`](../Store.md)\<`any`, (`cb`) => `any`\>)[] = `...` + \| [`Store`](Store.md)\<`any`, (`cb`) => `any`\>)[] = `...` #### Returns @@ -231,7 +231,7 @@ Defined in: [derived.ts:147](https://github.com/TanStack/store/blob/main/package readonly ( \| `Derived`\<`any`, readonly `any`[]\> - \| [`Store`](../Store.md)\<`any`, (`cb`) => `any`\>)[] = `...` + \| [`Store`](Store.md)\<`any`, (`cb`) => `any`\>)[] = `...` #### Returns diff --git a/docs/reference/classes/Store.md b/docs/reference/classes/Store.md index 91d5a16e..c0b8080c 100644 --- a/docs/reference/classes/Store.md +++ b/docs/reference/classes/Store.md @@ -35,7 +35,7 @@ Defined in: [store.ts:37](https://github.com/TanStack/store/blob/main/packages/s ##### options? -[`StoreOptions`](../../interfaces/StoreOptions.md)\<`TState`, `TUpdater`\> +[`StoreOptions`](../interfaces/StoreOptions.md)\<`TState`, `TUpdater`\> #### Returns diff --git a/docs/reference/functions/isUpdaterFunction.md b/docs/reference/functions/isUpdaterFunction.md index 1214e490..6b544c1b 100644 --- a/docs/reference/functions/isUpdaterFunction.md +++ b/docs/reference/functions/isUpdaterFunction.md @@ -23,7 +23,7 @@ Type guard to check if updater is a function ### updater -[`Updater`](../../type-aliases/Updater.md)\<`T`\> +[`Updater`](../type-aliases/Updater.md)\<`T`\> ## Returns diff --git a/docs/reference/index.md b/docs/reference/index.md index 39a9931c..39a015bf 100644 --- a/docs/reference/index.md +++ b/docs/reference/index.md @@ -7,28 +7,28 @@ title: "@tanstack/store" ## Classes -- [Derived](../classes/Derived.md) -- [Effect](../classes/Effect.md) -- [Store](../classes/Store.md) +- [Derived](classes/Derived.md) +- [Effect](classes/Effect.md) +- [Store](classes/Store.md) ## Interfaces -- [DerivedFnProps](../interfaces/DerivedFnProps.md) -- [DerivedOptions](../interfaces/DerivedOptions.md) -- [StoreOptions](../interfaces/StoreOptions.md) +- [DerivedFnProps](interfaces/DerivedFnProps.md) +- [DerivedOptions](interfaces/DerivedOptions.md) +- [StoreOptions](interfaces/StoreOptions.md) ## Type Aliases -- [UnwrapDerivedOrStore](../type-aliases/UnwrapDerivedOrStore.md) -- [Updater](../type-aliases/Updater.md) +- [UnwrapDerivedOrStore](type-aliases/UnwrapDerivedOrStore.md) +- [Updater](type-aliases/Updater.md) ## Variables -- [\_\_depsThatHaveWrittenThisTick](../variables/depsThatHaveWrittenThisTick.md) -- [\_\_derivedToStore](../variables/derivedToStore.md) -- [\_\_storeToDerived](../variables/storeToDerived.md) +- [\_\_depsThatHaveWrittenThisTick](variables/depsThatHaveWrittenThisTick.md) +- [\_\_derivedToStore](variables/derivedToStore.md) +- [\_\_storeToDerived](variables/storeToDerived.md) ## Functions -- [batch](../functions/batch.md) -- [isUpdaterFunction](../functions/isUpdaterFunction.md) +- [batch](functions/batch.md) +- [isUpdaterFunction](functions/isUpdaterFunction.md) diff --git a/docs/reference/interfaces/DerivedFnProps.md b/docs/reference/interfaces/DerivedFnProps.md index 588ee766..6b652b2c 100644 --- a/docs/reference/interfaces/DerivedFnProps.md +++ b/docs/reference/interfaces/DerivedFnProps.md @@ -12,8 +12,8 @@ Defined in: [derived.ts:30](https://github.com/TanStack/store/blob/main/packages ### TArr `TArr` *extends* `ReadonlyArray`\< - \| [`Derived`](../../classes/Derived.md)\<`any`\> - \| [`Store`](../../classes/Store.md)\<`any`\>\> = `ReadonlyArray`\<`any`\> + \| [`Derived`](../classes/Derived.md)\<`any`\> + \| [`Store`](../classes/Store.md)\<`any`\>\> = `ReadonlyArray`\<`any`\> ### TUnwrappedArr diff --git a/docs/reference/interfaces/DerivedOptions.md b/docs/reference/interfaces/DerivedOptions.md index 81f5f4cf..584b4fd8 100644 --- a/docs/reference/interfaces/DerivedOptions.md +++ b/docs/reference/interfaces/DerivedOptions.md @@ -16,8 +16,8 @@ Defined in: [derived.ts:45](https://github.com/TanStack/store/blob/main/packages ### TArr `TArr` *extends* `ReadonlyArray`\< - \| [`Derived`](../../classes/Derived.md)\<`any`\> - \| [`Store`](../../classes/Store.md)\<`any`\>\> = `ReadonlyArray`\<`any`\> + \| [`Derived`](../classes/Derived.md)\<`any`\> + \| [`Store`](../classes/Store.md)\<`any`\>\> = `ReadonlyArray`\<`any`\> ## Properties @@ -45,7 +45,7 @@ Values of the `deps` from before and after the current invocation of `fn` ##### props -[`DerivedFnProps`](../DerivedFnProps.md)\<`TArr`\> +[`DerivedFnProps`](DerivedFnProps.md)\<`TArr`\> #### Returns @@ -69,7 +69,7 @@ Defined in: [derived.ts:49](https://github.com/TanStack/store/blob/main/packages ##### derived -[`Derived`](../../classes/Derived.md)\<`TState`\> +[`Derived`](../classes/Derived.md)\<`TState`\> #### Returns diff --git a/docs/reference/interfaces/StoreOptions.md b/docs/reference/interfaces/StoreOptions.md index 8fcf4b01..c20094c3 100644 --- a/docs/reference/interfaces/StoreOptions.md +++ b/docs/reference/interfaces/StoreOptions.md @@ -37,7 +37,7 @@ Called when a listener subscribes to the store. ##### store -[`Store`](../../classes/Store.md)\<`TState`, `TUpdater`\> +[`Store`](../classes/Store.md)\<`TState`, `TUpdater`\> #### Returns diff --git a/eslint.config.js b/eslint.config.js index 73630e63..ff189dd2 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,5 +1,5 @@ // @ts-check -import { tanstackConfig } from '@tanstack/config/eslint' +import { tanstackConfig } from '@tanstack/eslint-config' export default [...tanstackConfig] diff --git a/nx.json b/nx.json index 5ecf4847..5518446f 100644 --- a/nx.json +++ b/nx.json @@ -22,6 +22,10 @@ ] }, "targetDefaults": { + "test:docs": { + "cache": true, + "inputs": ["{workspaceRoot}/docs/**/*"] + }, "test:knip": { "cache": true, "inputs": ["{workspaceRoot}/**/*"] diff --git a/package.json b/package.json index 22f3817c..d877b392 100644 --- a/package.json +++ b/package.json @@ -5,11 +5,10 @@ "type": "git", "url": "https://github.com/tanstack/store.git" }, - "packageManager": "pnpm@10.18.2", + "packageManager": "pnpm@10.24.0", "type": "module", "scripts": { "clean": "pnpm --filter \"./packages/**\" run clean", - "preinstall": "node -e \"if(process.env.CI == 'true') {console.log('Skipping preinstall...')} else {process.exit(1)}\" || npx -y only-allow pnpm", "test": "pnpm run test:ci", "test:pr": "nx affected --targets=test:sherif,test:knip,test:eslint,test:lib,test:types,test:build,build", "test:ci": "nx run-many --targets=test:sherif,test:knip,test:eslint,test:lib,test:types,test:build,build", @@ -21,26 +20,30 @@ "test:build": "nx affected --target=test:build --exclude=examples/**", "test:types": "nx affected --target=test:types --exclude=examples/**", "test:knip": "knip", + "test:docs": "node scripts/verify-links.ts", "build": "nx affected --target=build --exclude=examples/**", "build:all": "nx run-many --target=build --exclude=examples/**", "watch": "pnpm run build:all && nx watch --all -- pnpm run build:all", "dev": "pnpm run watch", "prettier": "prettier --experimental-cli --ignore-unknown '**/*'", "prettier:write": "pnpm run prettier --write", - "docs:generate": "pnpm exec tsx scripts/generateDocs.ts", - "verify-links": "node scripts/verify-links.ts", + "generate-docs": "node scripts/generate-docs.ts", "cipublish": "node scripts/publish.ts", "cipublishforce": "CI=true pnpm cipublish" }, "nx": { "includedScripts": [ + "test:docs", "test:knip", "test:sherif" ] }, "devDependencies": { "@eslint-react/eslint-plugin": "^1.53.1", - "@tanstack/config": "^0.22.1", + "@tanstack/eslint-config": "0.3.3", + "@tanstack/publish-config": "0.2.2", + "@tanstack/typedoc-config": "0.3.1", + "@tanstack/vite-config": "0.4.1", "@testing-library/jest-dom": "^6.9.1", "@testing-library/user-event": "^14.6.1", "@types/node": "^24.1.0", @@ -57,7 +60,6 @@ "publint": "^0.3.15", "sherif": "^1.9.0", "tinyglobby": "^0.2.15", - "tsx": "^4.21.0", "typescript": "5.6.3", "typescript50": "npm:typescript@5.0", "typescript51": "npm:typescript@5.1", diff --git a/packages/preact-store/vite.config.ts b/packages/preact-store/vite.config.ts index a72fe5f6..8d27d210 100644 --- a/packages/preact-store/vite.config.ts +++ b/packages/preact-store/vite.config.ts @@ -1,5 +1,5 @@ import { defineConfig, mergeConfig } from 'vitest/config' -import { tanstackViteConfig } from '@tanstack/config/vite' +import { tanstackViteConfig } from '@tanstack/vite-config' import preact from '@preact/preset-vite' import packageJson from './package.json' diff --git a/packages/react-store/vite.config.ts b/packages/react-store/vite.config.ts index a77ecf53..6c5f6ed9 100644 --- a/packages/react-store/vite.config.ts +++ b/packages/react-store/vite.config.ts @@ -1,5 +1,5 @@ import { defineConfig, mergeConfig } from 'vitest/config' -import { tanstackViteConfig } from '@tanstack/config/vite' +import { tanstackViteConfig } from '@tanstack/vite-config' import react from '@vitejs/plugin-react' import packageJson from './package.json' diff --git a/packages/solid-store/vite.config.ts b/packages/solid-store/vite.config.ts index 14ab01c1..048f2cc9 100644 --- a/packages/solid-store/vite.config.ts +++ b/packages/solid-store/vite.config.ts @@ -1,5 +1,5 @@ import { defineConfig, mergeConfig } from 'vitest/config' -import { tanstackViteConfig } from '@tanstack/config/vite' +import { tanstackViteConfig } from '@tanstack/vite-config' import solid from 'vite-plugin-solid' import packageJson from './package.json' diff --git a/packages/store/vite.config.ts b/packages/store/vite.config.ts index 6334a53d..94d53421 100644 --- a/packages/store/vite.config.ts +++ b/packages/store/vite.config.ts @@ -1,5 +1,5 @@ import { defineConfig, mergeConfig } from 'vitest/config' -import { tanstackViteConfig } from '@tanstack/config/vite' +import { tanstackViteConfig } from '@tanstack/vite-config' import packageJson from './package.json' const config = defineConfig({ diff --git a/packages/vue-store/vite.config.ts b/packages/vue-store/vite.config.ts index 33d59f5f..6dbe2d19 100644 --- a/packages/vue-store/vite.config.ts +++ b/packages/vue-store/vite.config.ts @@ -1,5 +1,5 @@ import { defineConfig, mergeConfig } from 'vitest/config' -import { tanstackViteConfig } from '@tanstack/config/vite' +import { tanstackViteConfig } from '@tanstack/vite-config' import vue from '@vitejs/plugin-vue' import packageJson from './package.json' diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a45c5778..120f3807 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,9 +11,18 @@ importers: '@eslint-react/eslint-plugin': specifier: ^1.53.1 version: 1.53.1(eslint@9.39.1(jiti@2.6.1))(ts-api-utils@2.1.0(typescript@5.6.3))(typescript@5.6.3) - '@tanstack/config': - specifier: ^0.22.1 - version: 0.22.1(@types/node@24.9.2)(@typescript-eslint/utils@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.6.3))(eslint@9.39.1(jiti@2.6.1))(rollup@4.52.5)(typescript@5.6.3)(vite@6.4.1(@types/node@24.9.2)(jiti@2.6.1)(less@4.4.2)(sass@1.93.3)(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.1)) + '@tanstack/eslint-config': + specifier: 0.3.3 + version: 0.3.3(@typescript-eslint/utils@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.6.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.6.3) + '@tanstack/publish-config': + specifier: 0.2.2 + version: 0.2.2 + '@tanstack/typedoc-config': + specifier: 0.3.1 + version: 0.3.1(typescript@5.6.3) + '@tanstack/vite-config': + specifier: 0.4.1 + version: 0.4.1(@types/node@24.9.2)(rollup@4.52.5)(typescript@5.6.3)(vite@6.4.1(@types/node@24.9.2)(jiti@2.6.1)(less@4.4.2)(sass@1.93.3)(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.1)) '@testing-library/jest-dom': specifier: ^6.9.1 version: 6.9.1 @@ -62,9 +71,6 @@ importers: tinyglobby: specifier: ^0.2.15 version: 0.2.15 - tsx: - specifier: ^4.21.0 - version: 4.21.0 typescript: specifier: 5.6.3 version: 5.6.3 @@ -2942,10 +2948,6 @@ packages: svelte: ^5.0.0 vite: ^6.0.0 - '@tanstack/config@0.22.1': - resolution: {integrity: sha512-0m+gqjrIE6el20VpGIzT54SIjvu27lDRHr+9NiK2nYya5fm0e/19+NfKRoDekZhSBfjaGytUaSpbofzvbSw8zw==} - engines: {node: '>=18'} - '@tanstack/eslint-config@0.3.3': resolution: {integrity: sha512-8VFyAaIFV9onJcfc5yVj5WWl6DmN3W4m+t0Mb+nZrQmqHy+kDndw5O5Xv2BHVWRRPTqnhlJYh6wHWGh0R81ZzQ==} engines: {node: '>=18'} @@ -10458,22 +10460,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@tanstack/config@0.22.1(@types/node@24.9.2)(@typescript-eslint/utils@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.6.3))(eslint@9.39.1(jiti@2.6.1))(rollup@4.52.5)(typescript@5.6.3)(vite@6.4.1(@types/node@24.9.2)(jiti@2.6.1)(less@4.4.2)(sass@1.93.3)(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.1))': - dependencies: - '@tanstack/eslint-config': 0.3.3(@typescript-eslint/utils@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.6.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.6.3) - '@tanstack/publish-config': 0.2.2 - '@tanstack/typedoc-config': 0.3.1(typescript@5.6.3) - '@tanstack/vite-config': 0.4.1(@types/node@24.9.2)(rollup@4.52.5)(typescript@5.6.3)(vite@6.4.1(@types/node@24.9.2)(jiti@2.6.1)(less@4.4.2)(sass@1.93.3)(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.1)) - transitivePeerDependencies: - - '@types/node' - - '@typescript-eslint/utils' - - eslint - - eslint-import-resolver-node - - rollup - - supports-color - - typescript - - vite - '@tanstack/eslint-config@0.3.3(@typescript-eslint/utils@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.6.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.6.3)': dependencies: '@eslint/js': 9.39.1 diff --git a/scripts/generateDocs.ts b/scripts/generate-docs.ts similarity index 71% rename from scripts/generateDocs.ts rename to scripts/generate-docs.ts index 9790cbc6..5f669557 100644 --- a/scripts/generateDocs.ts +++ b/scripts/generate-docs.ts @@ -1,8 +1,6 @@ import { resolve } from 'node:path' import { fileURLToPath } from 'node:url' -import { readFileSync, writeFileSync } from 'node:fs' -import { generateReferenceDocs } from '@tanstack/config/typedoc' -import { glob } from 'tinyglobby' +import { generateReferenceDocs } from '@tanstack/typedoc-config' const __dirname = fileURLToPath(new URL('.', import.meta.url)) @@ -82,33 +80,6 @@ await generateReferenceDocs({ ], }) -// Find all markdown files matching the pattern -const markdownFiles = [ - ...(await glob('docs/reference/**/*.md')), - ...(await glob('docs/framework/*/reference/**/*.md')), -] - -console.log(`Found ${markdownFiles.length} markdown files to process\n`) - -// Process each markdown file -markdownFiles.forEach((file) => { - const content = readFileSync(file, 'utf-8') - let updatedContent = content - updatedContent = updatedContent.replaceAll(/\]\(\.\.\//gm, '](../../') - // updatedContent = content.replaceAll(/\]\(\.\//gm, '](../') - updatedContent = updatedContent.replaceAll( - /\]\((?!https?:\/\/|\/\/|\/|\.\/|\.\.\/|#)([^)]+)\)/gm, - // @ts-expect-error - (match, p1) => `](../${p1})`, - ) - - // Write the updated content back to the file - if (updatedContent !== content) { - writeFileSync(file, updatedContent, 'utf-8') - console.log(`Processed file: ${file}`) - } -}) - console.log('\n✅ All markdown files have been processed!') process.exit(0) diff --git a/scripts/publish.ts b/scripts/publish.ts index 36232f79..68b58624 100644 --- a/scripts/publish.ts +++ b/scripts/publish.ts @@ -1,8 +1,6 @@ -// @ts-check - import { resolve } from 'node:path' import { fileURLToPath } from 'node:url' -import { publish } from '@tanstack/config/publish' +import { publish } from '@tanstack/publish-config' const __dirname = fileURLToPath(new URL('.', import.meta.url)) diff --git a/scripts/tsconfig.json b/scripts/tsconfig.json deleted file mode 100644 index a32dd4f2..00000000 --- a/scripts/tsconfig.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "extends": "../tsconfig.json", - "include": ["**/*"] -} diff --git a/scripts/verify-links.ts b/scripts/verify-links.ts index 268a0ac9..ebfa412c 100644 --- a/scripts/verify-links.ts +++ b/scripts/verify-links.ts @@ -1,12 +1,19 @@ import { existsSync, readFileSync, statSync } from 'node:fs' -import path, { resolve } from 'node:path' +import { extname, resolve } from 'node:path' import { glob } from 'tinyglobby' // @ts-ignore Could not find a declaration file for module 'markdown-link-extractor'. import markdownLinkExtractor from 'markdown-link-extractor' +const errors: Array<{ + file: string + link: string + resolvedPath: string + reason: string +}> = [] + function isRelativeLink(link: string) { return ( - link && + !link.startsWith(`/`) && !link.startsWith('http://') && !link.startsWith('https://') && !link.startsWith('//') && @@ -15,39 +22,33 @@ function isRelativeLink(link: string) { ) } -function normalizePath(p: string): string { - // Remove any trailing .md - p = p.replace(`${path.extname(p)}`, '') - return p +/** Remove any trailing .md */ +function stripExtension(p: string): string { + return p.replace(`${extname(p)}`, '') } -function fileExistsForLink( - link: string, - markdownFile: string, - errors: Array, -): boolean { +function relativeLinkExists(link: string, file: string): boolean { // Remove hash if present - const filePart = link.split('#')[0] + const linkWithoutHash = link.split('#')[0] // If the link is empty after removing hash, it's not a file - if (!filePart) return false - - // Normalize the markdown file path - markdownFile = normalizePath(markdownFile) + if (!linkWithoutHash) return false - // Normalize the path - const normalizedPath = normalizePath(filePart) + // Strip the file/link extensions + const filePath = stripExtension(file) + const linkPath = stripExtension(linkWithoutHash) // Resolve the path relative to the markdown file's directory - let absPath = resolve(markdownFile, normalizedPath) + // Nav up a level to simulate how links are resolved on the web + let absPath = resolve(filePath, '..', linkPath) // Ensure the resolved path is within /docs const docsRoot = resolve('docs') if (!absPath.startsWith(docsRoot)) { errors.push({ link, - markdownFile, + file, resolvedPath: absPath, - reason: 'navigates above /docs, invalid', + reason: 'Path outside /docs', }) return false } @@ -76,15 +77,15 @@ function fileExistsForLink( if (!exists) { errors.push({ link, - markdownFile, + file, resolvedPath: absPath, - reason: 'not found', + reason: 'Not found', }) } return exists } -async function findMarkdownLinks() { +async function verifyMarkdownLinks() { // Find all markdown files in docs directory const markdownFiles = await glob('docs/**/*.md', { ignore: ['**/node_modules/**'], @@ -92,26 +93,18 @@ async function findMarkdownLinks() { console.log(`Found ${markdownFiles.length} markdown files\n`) - const errors: Array = [] - // Process each file for (const file of markdownFiles) { const content = readFileSync(file, 'utf-8') - const links: Array = markdownLinkExtractor(content) - - const filteredLinks = links.filter((link: any) => { - if (typeof link === 'string') { - return isRelativeLink(link) - } else if (link && typeof link.href === 'string') { - return isRelativeLink(link.href) - } - return false + const links: Array = markdownLinkExtractor(content) + + const relativeLinks = links.filter((link: string) => { + return isRelativeLink(link) }) - if (filteredLinks.length > 0) { - filteredLinks.forEach((link) => { - const href = typeof link === 'string' ? link : link.href - fileExistsForLink(href, file, errors) + if (relativeLinks.length > 0) { + relativeLinks.forEach((link) => { + relativeLinkExists(link, file) }) } } @@ -120,7 +113,7 @@ async function findMarkdownLinks() { console.log(`\n❌ Found ${errors.length} broken links:`) errors.forEach((err) => { console.log( - `${err.link}\n in: ${err.markdownFile}\n path: ${err.resolvedPath}\n why: ${err.reason}\n`, + `${err.file}\n link: ${err.link}\n resolved: ${err.resolvedPath}\n why: ${err.reason}\n`, ) }) process.exit(1) @@ -129,4 +122,4 @@ async function findMarkdownLinks() { } } -findMarkdownLinks().catch(console.error) +verifyMarkdownLinks().catch(console.error) diff --git a/tsconfig.json b/tsconfig.json index cb591d67..77fa511c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -23,5 +23,5 @@ "strict": true, "target": "ES2020" }, - "include": ["*.config.*"] + "include": ["scripts", "*.config.*"] } From 8f22b2e706332c056e3f224cacfc7f6ec7d5c218 Mon Sep 17 00:00:00 2001 From: Lachlan Collins <1667261+lachlancollins@users.noreply.github.com> Date: Fri, 5 Dec 2025 19:02:00 +1100 Subject: [PATCH 2/2] Small change --- .github/workflows/autofix.yml | 2 +- scripts/verify-links.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/autofix.yml b/.github/workflows/autofix.yml index e2f239bb..dd212ebe 100644 --- a/.github/workflows/autofix.yml +++ b/.github/workflows/autofix.yml @@ -26,7 +26,7 @@ jobs: - name: Fix formatting run: pnpm prettier:write - name: Generate Docs - run: pnpm docs:generate + run: pnpm generate-docs - name: Apply fixes uses: autofix-ci/action@635ffb0c9798bd160680f18fd73371e355b85f27 with: diff --git a/scripts/verify-links.ts b/scripts/verify-links.ts index ebfa412c..8a1c40dd 100644 --- a/scripts/verify-links.ts +++ b/scripts/verify-links.ts @@ -13,7 +13,7 @@ const errors: Array<{ function isRelativeLink(link: string) { return ( - !link.startsWith(`/`) && + !link.startsWith('/') && !link.startsWith('http://') && !link.startsWith('https://') && !link.startsWith('//') &&