mirror of
https://github.com/langgenius/dify.git
synced 2026-07-29 08:19:34 +08:00
fix(web): download markdown file-preview links as attachments (#38030)
This commit is contained in:
parent
8d09b32cd5
commit
449b46b863
@ -170,6 +170,57 @@ describe('Link component', () => {
|
||||
expect(link).toHaveAttribute('rel', 'noopener noreferrer')
|
||||
})
|
||||
|
||||
it('adds attachment mode to file-preview links by default', () => {
|
||||
mockIsValidUrl.mockReturnValue(true)
|
||||
|
||||
const node = {
|
||||
properties: {
|
||||
href: 'http://localhost:5001/files/123/file-preview?timestamp=1&nonce=2&sign=3',
|
||||
},
|
||||
}
|
||||
|
||||
render(<Link node={node}>doc.pdf</Link>)
|
||||
|
||||
expect(screen.getByText('doc.pdf')).toHaveAttribute(
|
||||
'href',
|
||||
'http://localhost:5001/files/123/file-preview?timestamp=1&nonce=2&sign=3&as_attachment=true',
|
||||
)
|
||||
})
|
||||
|
||||
it('does not duplicate attachment mode for file-preview links', () => {
|
||||
mockIsValidUrl.mockReturnValue(true)
|
||||
|
||||
const node = {
|
||||
properties: {
|
||||
href: 'http://localhost:5001/files/123/file-preview?timestamp=1&nonce=2&sign=3&as_attachment=true',
|
||||
},
|
||||
}
|
||||
|
||||
render(<Link node={node}>doc.pdf</Link>)
|
||||
|
||||
expect(screen.getByText('doc.pdf')).toHaveAttribute(
|
||||
'href',
|
||||
'http://localhost:5001/files/123/file-preview?timestamp=1&nonce=2&sign=3&as_attachment=true',
|
||||
)
|
||||
})
|
||||
|
||||
it('keeps protocol-relative file-preview links protocol-relative', () => {
|
||||
mockIsValidUrl.mockReturnValue(true)
|
||||
|
||||
const node = {
|
||||
properties: {
|
||||
href: '//localhost:5001/files/123/file-preview?timestamp=1#page',
|
||||
},
|
||||
}
|
||||
|
||||
render(<Link node={node}>doc.pdf</Link>)
|
||||
|
||||
expect(screen.getByText('doc.pdf')).toHaveAttribute(
|
||||
'href',
|
||||
'//localhost:5001/files/123/file-preview?timestamp=1&as_attachment=true#page',
|
||||
)
|
||||
})
|
||||
|
||||
// --------------------------
|
||||
// NO HREF
|
||||
// --------------------------
|
||||
|
||||
@ -7,6 +7,19 @@ import * as React from 'react'
|
||||
import { useChatContext } from '@/app/components/base/chat/chat/context'
|
||||
import { isValidUrl } from './utils'
|
||||
|
||||
const filePreviewPathPattern = /\/files\/[^/?#]+\/file-preview(?:[?#]|$)/
|
||||
const asAttachmentParamPattern = /[?&]as_attachment=/
|
||||
|
||||
const withFilePreviewAttachment = (href: string) => {
|
||||
if (!filePreviewPathPattern.test(href) || asAttachmentParamPattern.test(href))
|
||||
return href
|
||||
|
||||
const url = new URL(href, 'http://dify.local')
|
||||
url.searchParams.set('as_attachment', 'true')
|
||||
|
||||
return href.startsWith('//') ? url.href.replace(url.protocol, '') : url.href
|
||||
}
|
||||
|
||||
const Link = ({ node, children, ...props }: any) => {
|
||||
const { onSend } = useChatContext()
|
||||
const commonClassName = 'cursor-pointer underline decoration-primary-700! decoration-dashed'
|
||||
@ -16,8 +29,9 @@ const Link = ({ node, children, ...props }: any) => {
|
||||
return <abbr className={commonClassName} onClick={() => onSend?.(hidden_text)} title={node.children[0]?.value || ''}>{node.children[0]?.value || ''}</abbr>
|
||||
}
|
||||
else {
|
||||
const href = props.href || node.properties?.href
|
||||
if (href && /^#[\w-]+$/.test(href.toString())) {
|
||||
const rawHref = props.href || node.properties?.href
|
||||
const href = rawHref?.toString()
|
||||
if (href && /^#[\w-]+$/.test(href)) {
|
||||
const handleClick = (e: React.MouseEvent<HTMLAnchorElement>) => {
|
||||
e.preventDefault()
|
||||
// scroll to target element if exists within the answer container
|
||||
@ -36,7 +50,7 @@ const Link = ({ node, children, ...props }: any) => {
|
||||
if (!href || !isValidUrl(href))
|
||||
return <span>{children}</span>
|
||||
|
||||
return <a href={href} target="_blank" rel="noopener noreferrer" className={commonClassName}>{children || 'Download'}</a>
|
||||
return <a href={withFilePreviewAttachment(href)} target="_blank" rel="noopener noreferrer" className={commonClassName}>{children || 'Download'}</a>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user