|
1 | 1 | import { Link } from '@tanstack/react-router' |
2 | 2 | import type { HTMLProps } from 'react' |
3 | 3 |
|
| 4 | +function isRelativeLink(link: string) { |
| 5 | + return ( |
| 6 | + !link.startsWith(`/`) && |
| 7 | + !link.startsWith('http://') && |
| 8 | + !link.startsWith('https://') && |
| 9 | + !link.startsWith('//') && |
| 10 | + !link.startsWith('#') && |
| 11 | + !link.startsWith('mailto:') |
| 12 | + ) |
| 13 | +} |
| 14 | + |
4 | 15 | export function MarkdownLink({ |
5 | 16 | href: hrefProp, |
6 | 17 | ...rest |
7 | 18 | }: HTMLProps<HTMLAnchorElement>) { |
8 | | - if ( |
9 | | - hrefProp?.startsWith('http') || |
10 | | - hrefProp?.startsWith('#') || |
11 | | - hrefProp?.startsWith('//') |
12 | | - ) { |
13 | | - // eslint-disable-next-line jsx-a11y/anchor-has-content |
| 19 | + if (!isRelativeLink(hrefProp ?? '')) { |
14 | 20 | return <a {...rest} href={hrefProp} /> |
15 | 21 | } |
16 | 22 |
|
17 | 23 | const [hrefWithoutHash, hash] = hrefProp?.split('#') ?? [] |
18 | | - let [to] = hrefWithoutHash?.split('.md') ?? [] |
| 24 | + let hrefWithoutMd = hrefWithoutHash.replace('.md', '') |
| 25 | + |
| 26 | + // Force relative links to resolve one level higher |
| 27 | + if (hrefWithoutMd.startsWith('../')) { |
| 28 | + hrefWithoutMd = hrefWithoutMd.replace(/^\.\.\//gm, '../../') |
| 29 | + } else if (hrefWithoutMd.startsWith('./')) { |
| 30 | + hrefWithoutMd = hrefWithoutMd.replace(/^\.\//gm, '../') |
| 31 | + } else { |
| 32 | + hrefWithoutMd = `../${hrefWithoutMd}` |
| 33 | + } |
19 | 34 |
|
20 | 35 | return ( |
21 | 36 | <Link |
22 | 37 | {...rest} |
23 | 38 | unsafeRelative="path" |
24 | | - to={to} |
| 39 | + to={hrefWithoutMd} |
25 | 40 | hash={hash} |
26 | 41 | preload={undefined} |
27 | 42 | ref={undefined} |
28 | 43 | /> |
29 | 44 | ) |
30 | 45 | } |
31 | | - |
32 | | -// function resolveRelativePath(routerHref: string, markdownPath: string): string { |
33 | | -// let hash = '' |
34 | | -// let basePath = routerHref |
35 | | -// let relativePath = markdownPath |
36 | | - |
37 | | -// // Check if the relative path starts with a hash |
38 | | -// if (relativePath.startsWith('#')) { |
39 | | -// // If the basePath already has a hash, remove it |
40 | | -// const hashIndex = basePath.indexOf('#') |
41 | | -// if (hashIndex !== -1) { |
42 | | -// basePath = basePath.substring(0, hashIndex) |
43 | | -// } |
44 | | - |
45 | | -// return basePath + relativePath |
46 | | -// } |
47 | | - |
48 | | -// // Remove hash from path if it exists, we'll add it back later |
49 | | -// if (hashIndex !== -1) { |
50 | | -// hash = relativePath.substring(hashIndex) |
51 | | -// relativePath = relativePath.substring(0, hashIndex) |
52 | | -// } |
53 | | - |
54 | | -// // Remove .md extension if it exists |
55 | | -// if (relativePath.endsWith('.md')) { |
56 | | -// relativePath = relativePath.substring(0, relativePath.length - 3) |
57 | | -// } else { |
58 | | -// // If the path doesn't end with .md, return the path as is |
59 | | -// return relativePath + hash |
60 | | -// } |
61 | | - |
62 | | -// const stack = basePath.split('/').filter(Boolean) |
63 | | -// const parts = relativePath.split('/') |
64 | | - |
65 | | -// let firstDoubleDotEncountered = false // Flag to track the first ".." |
66 | | - |
67 | | -// for (let i = 0; i < parts.length; i++) { |
68 | | -// const part = parts[i] |
69 | | -// if (part === '.') { |
70 | | -// continue |
71 | | -// } |
72 | | -// if (part === '..') { |
73 | | -// if (!firstDoubleDotEncountered) { |
74 | | -// // First time encountering ".." |
75 | | -// stack.pop() // First pop |
76 | | -// stack.pop() // Second pop |
77 | | -// firstDoubleDotEncountered = true // Set the flag |
78 | | -// } else { |
79 | | -// // Subsequent ".." |
80 | | -// stack.pop() |
81 | | -// } |
82 | | -// } else { |
83 | | -// stack.push(part) |
84 | | -// } |
85 | | -// } |
86 | | - |
87 | | -// let resolvedPath = '/' + stack.filter(Boolean).join('/') |
88 | | - |
89 | | -// // Add the hash back |
90 | | -// resolvedPath += hash |
91 | | - |
92 | | -// return resolvedPath |
93 | | -// } |
0 commit comments