diff --git a/src/components/repositories/ContributingViewer.tsx b/src/components/repositories/ContributingViewer.tsx index cc3b110e..01d59abd 100644 --- a/src/components/repositories/ContributingViewer.tsx +++ b/src/components/repositories/ContributingViewer.tsx @@ -5,6 +5,7 @@ import remarkGfm from 'remark-gfm'; import rehypeRaw from 'rehype-raw'; import axios from 'axios'; import { STATUS_COLORS } from '../../theme'; +import { resolveRelativeUrl } from './MarkdownRenderers'; interface ContributingViewerProps { repositoryFullName: string; // e.g., "opentensor/bittensor" @@ -81,35 +82,6 @@ const ContributingViewer: React.FC = ({ ); } - // Custom renderer for images to handle relative paths - const ImageRenderer = (props: any) => { - const { src, alt, ...rest } = props; - let finalSrc = src; - - if (src && !src.startsWith('http') && !src.startsWith('//')) { - const cleanPath = src.startsWith('./') - ? src.slice(2) - : src.startsWith('/') - ? src.slice(1) - : src; - finalSrc = `https://cdn.jsdelivr.net/gh/${repositoryFullName}@${defaultBranch}/${cleanPath}`; - } - - return ( - {alt} - ); - }; - return ( = ({ ( + + {children} + + ), + img: ({ src, alt, ...rest }: any) => ( + {alt} + ), + }} > {content || ''} diff --git a/src/components/repositories/MarkdownRenderers.tsx b/src/components/repositories/MarkdownRenderers.tsx new file mode 100644 index 00000000..94406f09 --- /dev/null +++ b/src/components/repositories/MarkdownRenderers.tsx @@ -0,0 +1,30 @@ +/** + * Resolve a relative URL to an absolute GitHub URL. + * Returns the original URL if it's already absolute. + */ +export const resolveRelativeUrl = ( + url: string | undefined, + repositoryFullName: string, + defaultBranch: string, + type: 'blob' | 'cdn' = 'blob', +): string | undefined => { + if ( + !url || + url.startsWith('http') || + url.startsWith('//') || + url.startsWith('#') || + url.startsWith('mailto:') + ) { + return url; + } + + const cleanPath = url.replace(/^\.\//, '').replace(/^\//, ''); + + if (type === 'cdn') { + return `https://cdn.jsdelivr.net/gh/${repositoryFullName}@${defaultBranch}/${cleanPath}`; + } + + const hasExtension = /\.[a-zA-Z0-9]+$/.test(cleanPath.replace(/\/$/, '')); + const ghType = cleanPath.endsWith('/') || !hasExtension ? 'tree' : 'blob'; + return `https://github.com/${repositoryFullName}/${ghType}/${defaultBranch}/${cleanPath.replace(/\/$/, '')}`; +}; diff --git a/src/components/repositories/ReadmeViewer.tsx b/src/components/repositories/ReadmeViewer.tsx index 7dcee7b9..98be1556 100644 --- a/src/components/repositories/ReadmeViewer.tsx +++ b/src/components/repositories/ReadmeViewer.tsx @@ -5,6 +5,7 @@ import remarkGfm from 'remark-gfm'; import rehypeRaw from 'rehype-raw'; import axios from 'axios'; import { STATUS_COLORS } from '../../theme'; +import { resolveRelativeUrl } from './MarkdownRenderers'; interface ReadmeViewerProps { repositoryFullName: string; // e.g., "opentensor/bittensor" @@ -68,37 +69,6 @@ const ReadmeViewer: React.FC = ({ repositoryFullName }) => { ); } - // Custom renderer for images to handle relative paths - const ImageRenderer = (props: any) => { - const { src, alt, ...rest } = props; - let finalSrc = src; - - if (src && !src.startsWith('http') && !src.startsWith('//')) { - // Convert relative path to absolute GitHub user content path - // e.g. ./assets/img.png -> https://raw.githubusercontent.com/user/repo/branch/assets/img.png - const cleanPath = src.startsWith('./') - ? src.slice(2) - : src.startsWith('/') - ? src.slice(1) - : src; - finalSrc = `https://cdn.jsdelivr.net/gh/${repositoryFullName}@${defaultBranch}/${cleanPath}`; - } - - return ( - {alt} - ); - }; - return ( = ({ repositoryFullName }) => { borderBottom: '1px solid #30363d', pb: 0.3, mb: 3, - mt: 1, // Reduced from 4 + mt: 1, fontWeight: 600, color: '#ffffff', }, @@ -126,7 +96,7 @@ const ReadmeViewer: React.FC = ({ repositoryFullName }) => { borderBottom: '1px solid #30363d', pb: 0.3, mb: 3, - mt: 2, // Reduced from 4 + mt: 2, fontWeight: 600, color: '#ffffff', }, @@ -209,7 +179,34 @@ const ReadmeViewer: React.FC = ({ repositoryFullName }) => { remarkPlugins={[remarkGfm]} rehypePlugins={[rehypeRaw]} components={{ - img: ImageRenderer, + a: ({ href, children, ...rest }: any) => ( + + {children} + + ), + img: ({ src, alt, ...rest }: any) => ( + {alt} + ), }} > {content || ''} diff --git a/src/components/repositories/index.ts b/src/components/repositories/index.ts index eb2b16a3..a3c79d90 100644 --- a/src/components/repositories/index.ts +++ b/src/components/repositories/index.ts @@ -11,3 +11,4 @@ export { default as ReadmeViewer } from './ReadmeViewer'; export { default as RepositoryCodeBrowser } from './RepositoryCodeBrowser'; export { default as RepositoryMaintainers } from './RepositoryMaintainers'; export { default as RepositoryCheckTab } from './RepositoryCheckTab'; +export { resolveRelativeUrl } from './MarkdownRenderers';