Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 23 additions & 71 deletions src/components/MarkdownLink.tsx
Original file line number Diff line number Diff line change
@@ -1,93 +1,45 @@
import { Link } from '@tanstack/react-router'
import type { HTMLProps } from 'react'

function isRelativeLink(link: string) {
return (
!link.startsWith(`/`) &&
!link.startsWith('http://') &&
!link.startsWith('https://') &&
!link.startsWith('//') &&
!link.startsWith('#') &&
!link.startsWith('mailto:')
)
}

export function MarkdownLink({
href: hrefProp,
...rest
}: HTMLProps<HTMLAnchorElement>) {
if (
hrefProp?.startsWith('http') ||
hrefProp?.startsWith('#') ||
hrefProp?.startsWith('//')
) {
// eslint-disable-next-line jsx-a11y/anchor-has-content
if (!isRelativeLink(hrefProp ?? '')) {
return <a {...rest} href={hrefProp} />

Check warning on line 20 in src/components/MarkdownLink.tsx

View workflow job for this annotation

GitHub Actions / PR

Anchors must have content and the content must be accessible by a screen reader
}

const [hrefWithoutHash, hash] = hrefProp?.split('#') ?? []
let [to] = hrefWithoutHash?.split('.md') ?? []
let hrefWithoutMd = hrefWithoutHash.replace('.md', '')

// Force relative links to resolve one level higher
if (hrefWithoutMd.startsWith('../')) {
hrefWithoutMd = hrefWithoutMd.replace(/^\.\.\//gm, '../../')
} else if (hrefWithoutMd.startsWith('./')) {
hrefWithoutMd = hrefWithoutMd.replace(/^\.\//gm, '../')
} else {
hrefWithoutMd = `../${hrefWithoutMd}`
}

return (
<Link
{...rest}
unsafeRelative="path"
to={to}
to={hrefWithoutMd}
hash={hash}
preload={undefined}
ref={undefined}
/>
)
}

// function resolveRelativePath(routerHref: string, markdownPath: string): string {
// let hash = ''
// let basePath = routerHref
// let relativePath = markdownPath

// // Check if the relative path starts with a hash
// if (relativePath.startsWith('#')) {
// // If the basePath already has a hash, remove it
// const hashIndex = basePath.indexOf('#')
// if (hashIndex !== -1) {
// basePath = basePath.substring(0, hashIndex)
// }

// return basePath + relativePath
// }

// // Remove hash from path if it exists, we'll add it back later
// if (hashIndex !== -1) {
// hash = relativePath.substring(hashIndex)
// relativePath = relativePath.substring(0, hashIndex)
// }

// // Remove .md extension if it exists
// if (relativePath.endsWith('.md')) {
// relativePath = relativePath.substring(0, relativePath.length - 3)
// } else {
// // If the path doesn't end with .md, return the path as is
// return relativePath + hash
// }

// const stack = basePath.split('/').filter(Boolean)
// const parts = relativePath.split('/')

// let firstDoubleDotEncountered = false // Flag to track the first ".."

// for (let i = 0; i < parts.length; i++) {
// const part = parts[i]
// if (part === '.') {
// continue
// }
// if (part === '..') {
// if (!firstDoubleDotEncountered) {
// // First time encountering ".."
// stack.pop() // First pop
// stack.pop() // Second pop
// firstDoubleDotEncountered = true // Set the flag
// } else {
// // Subsequent ".."
// stack.pop()
// }
// } else {
// stack.push(part)
// }
// }

// let resolvedPath = '/' + stack.filter(Boolean).join('/')

// // Add the hash back
// resolvedPath += hash

// return resolvedPath
// }
Loading