Skip to content

Commit a3d26ac

Browse files
committed
feat: implement rewriteExerciseLinks function for relative exercise links
1 parent 7da6efc commit a3d26ac

File tree

2 files changed

+30
-2
lines changed

2 files changed

+30
-2
lines changed

docs/.vitepress/plugins/md-expand-tutorials.test.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { describe, it, expect, beforeEach } from 'vitest'
2-
import { expandTutorialsInSource } from './md-expand-tutorials.js'
2+
import { expandTutorialsInSource, rewriteExerciseLinks } from './md-expand-tutorials.js'
33

44
// Simulates the in-memory cache for testing (no Vite context needed)
55
const fakeCache = new Map<string, string>([
@@ -81,3 +81,20 @@ describe('expandTutorialsInSource', () => {
8181
expect(result).toBe(src)
8282
})
8383
})
84+
85+
describe('rewriteExerciseLinks', () => {
86+
it('rewrites ../exN/README.md to /exercises/exN/', () => {
87+
const src = '👉 [Exercise 2](../ex2/README.md)'
88+
expect(rewriteExerciseLinks(src)).toBe('👉 [Exercise 2](/exercises/ex2/)')
89+
})
90+
91+
it('rewrites all occurrences in a document', () => {
92+
const src = 'See [ex1](../ex1/README.md) and [ex8](../ex8/README.md).'
93+
expect(rewriteExerciseLinks(src)).toBe('See [ex1](/exercises/ex1/) and [ex8](/exercises/ex8/).')
94+
})
95+
96+
it('does not modify unrelated links', () => {
97+
const src = '[GitHub](https://github.com) and [prereqs](../prerequisites.md)'
98+
expect(rewriteExerciseLinks(src)).toBe(src)
99+
})
100+
})

docs/.vitepress/plugins/md-expand-tutorials.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,16 @@ import { getTutorialContent } from './external-tutorials.js'
44
/** URL prefix all SAP tutorial links share. */
55
const SAP_TUTORIAL_PATTERN = /https:\/\/developers\.sap\.com\/tutorials\/([a-z0-9-]+)\.html/g
66

7+
/**
8+
* Rewrites relative exercise README links to VitePress clean URLs.
9+
* e.g. ../ex2/README.md → /exercises/ex2/
10+
* These links are valid on GitHub but 404 in the VitePress site because
11+
* the wrapper pages live at docs/exercises/exN/index.md, not README.md.
12+
*/
13+
export function rewriteExerciseLinks(src: string): string {
14+
return src.replace(/\.\.\/(ex\d)\/README\.md/g, '/exercises/$1/')
15+
}
16+
717
/**
818
* Performs pre-parse source substitution on a single markdown source string.
919
* Exported separately so it can be unit-tested without a MarkdownIt instance.
@@ -63,7 +73,8 @@ export function expandTutorialsInSource(
6373
export function expandTutorialsPlugin(md: MarkdownIt): void {
6474
const originalRender = md.render.bind(md)
6575
md.render = function (src: string, env?: unknown): string {
66-
const expanded = expandTutorialsInSource(src, getTutorialContent)
76+
const rewritten = rewriteExerciseLinks(src)
77+
const expanded = expandTutorialsInSource(rewritten, getTutorialContent)
6778
return originalRender(expanded, env)
6879
}
6980
}

0 commit comments

Comments
 (0)