Skip to content

Commit ac45dbd

Browse files
authored
Fix link checking (#340)
* [bfops/check-links]: fix link checker * [bfops/check-links]: fix * [bfops/check-links]: fix broken links * [bfops/check-links]: fix logic * [bfops/check-links]: fix site links --------- Co-authored-by: Zeke Foppa <[email protected]>
1 parent d02c2a1 commit ac45dbd

File tree

5 files changed

+35
-38
lines changed

5 files changed

+35
-38
lines changed

docs/modules/c-sharp/index.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -223,9 +223,9 @@ However:
223223

224224
# Tables
225225

226-
Tables are declared using the [`[SpacetimeDB.Table]` attribute](#table-attribute).
226+
Tables are declared using the `[SpacetimeDB.Table]` attribute.
227227

228-
This macro is applied to a C# `partial class` or `partial struct` with named fields. (The `partial` modifier is required to allow code generation to add methods.) All of the fields of the table must be marked with [`[SpacetimeDB.Type]`](#type-attribute).
228+
This macro is applied to a C# `partial class` or `partial struct` with named fields. (The `partial` modifier is required to allow code generation to add methods.) All of the fields of the table must be marked with [`[SpacetimeDB.Type]`]( #attribute-spacetimedbtype).
229229

230230
The resulting type is used to store rows of the table. It's a normal class (or struct). Row values are not special -- operations on row types do not, by themselves, modify the table. Instead, a [`ReducerContext`](#class-reducercontext) is needed to get a handle to the table.
231231

docs/sql/index.md

+5-5
Original file line numberDiff line numberDiff line change
@@ -640,9 +640,9 @@ column
640640
```
641641

642642

643-
[sdk]: /docs/sdks/rust/index.md#subscribe-to-queries
644-
[http]: /docs/http/database#databasesqlname_or_address-post
645-
[cli]: /docs/cli-reference.md#spacetime-sql
643+
[sdk]: /docs/sdks/rust#subscribe-to-queries
644+
[http]: /docs/http/database#post-v1databasename_or_identitysql
645+
[cli]: /docs/cli-reference#spacetime-sql
646646

647-
[Identity]: /docs/index.md#identity
648-
[ConnectionId]: /docs/index.md#connectionid
647+
[Identity]: /docs#identity
648+
[ConnectionId]: /docs#connectionid

docs/webassembly-abi/index.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,7 @@ uint16_t _iter_start_filtered(
493493

494494
[`bindings_sys::raw`]: https://github.com/clockworklabs/SpacetimeDB/blob/master/crates/bindings-sys/src/lib.rs#L44-L215
495495
[`bindings`]: https://github.com/clockworklabs/SpacetimeDB/blob/master/crates/bindings/src/lib.rs
496-
[module_ref]: /docs/languages/rust/rust-module-reference
497-
[module_quick_start]: /docs/languages/rust/rust-module-quick-start
496+
[module_ref]: /docs/modules/rust
497+
[module_quick_start]: /docs/modules/rust/quickstart
498498
[wasm_c_abi]: https://github.com/WebAssembly/tool-conventions/blob/main/BasicCABI.md
499499
[c_header]: #appendix-bindingsh

package.json

+4-1
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,11 @@
88
},
99
"devDependencies": {
1010
"@types/node": "^22.10.2",
11+
"remark-parse": "^11.0.0",
1112
"tsx": "^4.19.2",
12-
"typescript": "^5.3.2"
13+
"typescript": "^5.3.2",
14+
"unified": "^11.0.5",
15+
"unist-util-visit": "^5.0.0"
1316
},
1417
"scripts": {
1518
"build": "tsc --project ./tsconfig.json",

scripts/checkLinks.ts

+22-28
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ import fs from 'fs';
22
import path from 'path';
33
import nav from '../nav'; // Import the nav object directly
44
import GitHubSlugger from 'github-slugger';
5+
import { unified } from 'unified';
6+
import remarkParse from 'remark-parse';
7+
import { visit } from 'unist-util-visit';
58

69
// Function to map slugs to file paths from nav.ts
710
function extractSlugToPathMap(nav: { items: any[] }): Map<string, string> {
@@ -33,34 +36,22 @@ function validatePathsExist(slugToPath: Map<string, string>): void {
3336

3437
// Function to extract links and images from markdown files with line numbers
3538
function extractLinksAndImagesFromMarkdown(filePath: string): { link: string; type: 'image' | 'link'; line: number }[] {
36-
const fileContent = fs.readFileSync(filePath, 'utf-8');
37-
const lines = fileContent.split('\n');
38-
const linkRegex = /\[([^\]]+)\]\(([^)]+)\)/g; // Matches standard Markdown links
39-
const imageRegex = /!\[([^\]]*)\]\(([^)]+)\)/g; // Matches image links in Markdown
40-
41-
const linksAndImages: { link: string; type: 'image' | 'link'; line: number }[] = [];
42-
const imageSet = new Set<string>(); // To store links that are classified as images
39+
const content = fs.readFileSync(filePath, 'utf-8');
40+
const tree = unified().use(remarkParse).parse(content);
4341

44-
lines.forEach((lineContent, index) => {
45-
let match: RegExpExecArray | null;
46-
47-
// Extract image links and add them to the imageSet
48-
while ((match = imageRegex.exec(lineContent)) !== null) {
49-
const link = match[2];
50-
linksAndImages.push({ link, type: 'image', line: index + 1 });
51-
imageSet.add(link);
52-
}
42+
const results: { link: string; type: 'image' | 'link'; line: number }[] = [];
5343

54-
// Extract standard links
55-
while ((match = linkRegex.exec(lineContent)) !== null) {
56-
const link = match[2];
57-
linksAndImages.push({ link, type: 'link', line: index + 1 });
44+
visit(tree, ['link', 'image', 'definition'], (node: any) => {
45+
const link = node.url;
46+
const line = node.position?.start?.line ?? 0;
47+
if (link) {
48+
results.push({ link, type: node.type === 'image' ? 'image' : 'link', line });
5849
}
5950
});
6051

61-
// Filter out links that exist as images
62-
return linksAndImages.filter(item => !(item.type === 'link' && imageSet.has(item.link)));
52+
return results;
6353
}
54+
6455
// Function to resolve relative links using slugs
6556
function resolveLink(link: string, currentSlug: string): string {
6657
if (link.startsWith('#')) {
@@ -101,6 +92,9 @@ function checkLinks(): void {
10192
// Extract valid slugs
10293
const validSlugs = Array.from(slugToPath.keys());
10394

95+
// Hacky workaround because the slug for the root is /docs/index. No other slugs have a /index at the end.
96+
validSlugs.push('/docs');
97+
10498
// Reverse map from file path to slug for current file resolution
10599
const pathToSlug = new Map<string, string>();
106100
slugToPath.forEach((filePath, slug) => {
@@ -124,11 +118,8 @@ function checkLinks(): void {
124118
return; // Skip external links
125119
}
126120

127-
const siteLinks = ['/install', '/images', '/profile'];
128-
for (const siteLink of siteLinks) {
129-
if (link.startsWith(siteLink)) {
130-
return; // Skip site links
131-
}
121+
if (!link.startsWith('/docs')) {
122+
return; // Skip site links
132123
}
133124

134125
// Resolve the link
@@ -149,7 +140,10 @@ function checkLinks(): void {
149140
}
150141

151142
// Split the resolved link into base and fragment
152-
const [baseLink, fragmentRaw] = resolvedLink.split('#');
143+
let [baseLink, fragmentRaw] = resolvedLink.split('#');
144+
if (baseLink.endsWith('/')) {
145+
baseLink = baseLink.slice(0, -1);
146+
}
153147
const fragment: string | null = fragmentRaw || null;
154148

155149
if (fragment) {

0 commit comments

Comments
 (0)