feat: [CODE-25]: Handle relative links to repository files inside a README

This commit is contained in:
“tan-nhu” 2023-05-02 13:32:53 -07:00
parent 67048fb2c8
commit a1818991aa
4 changed files with 58 additions and 11 deletions

View File

@ -1,5 +1,5 @@
import { useHistory } from 'react-router-dom'
import React, { useCallback, useState } from 'react'
import React, { useCallback, useMemo, useState } from 'react'
import { Container } from '@harness/uicore'
import cx from 'classnames'
import MarkdownPreview from '@uiw/react-markdown-preview'
@ -19,9 +19,8 @@ export function MarkdownViewer({ source, className, maxHeight }: MarkdownViewerP
const [isOpen, setIsOpen] = useState<boolean>(false)
const history = useHistory()
const [zoomLevel, setZoomLevel] = useState(INITIAL_ZOOM_LEVEL)
const [imgEvent, setImageEvent] = useState<string[]>([])
const refRootHref = useMemo(() => document.getElementById('repository-ref-root')?.getAttribute('href'), [])
const interceptClickEventOnViewerContainer = useCallback(
event => {
const { target } = event
@ -31,19 +30,26 @@ export function MarkdownViewer({ source, className, maxHeight }: MarkdownViewerP
const imageSrc = string.split('![image]')[1]
return imageSrc.slice(1, imageSrc.length - 1)
})
setImageEvent(imageStringArray)
if (target?.tagName?.toLowerCase() === 'a') {
const { href } = target
const href = target.getAttribute('href')
// Intercept click event on internal links and navigate to pages to avoid full page reload
if (href && !href.startsWith('#')) {
if (href) {
try {
const url = new URL(href)
const url = new URL(target.href)
if (url.origin === window.location.origin) {
event.stopPropagation()
event.preventDefault()
history.push(url.pathname)
if (href.startsWith('#')) {
document.getElementById(href.slice(1))?.scrollIntoView()
} else {
history.push(url.pathname)
}
}
} catch (e) {
// eslint-disable-next-line no-console
@ -71,6 +77,43 @@ export function MarkdownViewer({ source, className, maxHeight }: MarkdownViewerP
if (parent && /^h(1|2|3|4|5|6)/.test((parent as unknown as HTMLDivElement).tagName)) {
parent.children = parent.children.slice(1)
}
// Rewrite a.href to point to the correct location for relative links to files inside repository.
// Relative links are defined as links that do not start with /, #, https:, http:, mailto:,
// tel:, data:, javascript:, sms:, or http(s):
if (refRootHref) {
const { properties } = node as unknown as { properties: { href: string } }
let href: string = properties.href
if (
href &&
!href.startsWith('/') &&
!href.startsWith('#') &&
!href.startsWith('https:') &&
!href.startsWith('http:') &&
!href.startsWith('mailto:') &&
!href.startsWith('tel:') &&
!href.startsWith('data:') &&
!href.startsWith('javascript:') &&
!href.startsWith('sms:') &&
!/^http(s)?:/.test(href)
) {
try {
// Some relative links are prefixed by `./`, normalize them
if (href.startsWith('./')) {
href = properties.href = properties.href.replace('./', '')
}
// Test if the link is relative to the current page.
// If true, rewrite it to point to the correct location
if (new URL(window.location.href + '/' + href).origin === window.location.origin) {
properties.href = (refRootHref + '/~/' + href).replace(/^\/ng\//, '/')
}
} catch (_exception) {
// eslint-disable-line no-empty
}
}
}
}
}}
rehypePlugins={[

View File

@ -68,7 +68,9 @@ export function ContentHeader({
/>
<Container>
<Layout.Horizontal spacing="small">
<Link to={routes.toCODERepository({ repoPath: repoMetadata.path as string, gitRef })}>
<Link
id="repository-ref-root"
to={routes.toCODERepository({ repoPath: repoMetadata.path as string, gitRef })}>
<Icon name={CodeIcon.Folder} />
</Link>
<Text color={Color.GREY_900}>/</Text>

View File

@ -8,8 +8,6 @@
.heading {
box-shadow: 0px 0px 1px rgba(40, 41, 61, 0.08), 0px 0.5px 2px rgba(96, 97, 112, 0.16);
// border-top: 1px solid var(--grey-200);
// border-bottom: 1px solid var(--grey-200);
align-items: center;
padding-left: var(--spacing-large) !important;
background-color: var(--grey-100);

View File

@ -1,4 +1,4 @@
import React from 'react'
import React, { useEffect } from 'react'
import { Container } from '@harness/uicore'
import { GitInfoProps, isDir } from 'utils/GitUtils'
import { ContentHeader } from './ContentHeader/ContentHeader'
@ -12,6 +12,10 @@ export function RepositoryContent({
resourcePath,
resourceContent
}: Pick<GitInfoProps, 'repoMetadata' | 'gitRef' | 'resourcePath' | 'resourceContent'>) {
useEffect(() => {
window.scroll({ top: 0 })
}, [gitRef, resourcePath])
return (
<Container className={css.resourceContent}>
<ContentHeader