mirror of
https://github.com/langgenius/dify.git
synced 2026-04-16 02:16:57 +08:00
chore: url in tool description support clicking jump directly (#35163)
This commit is contained in:
parent
736880e046
commit
d4783e8c14
@ -78,6 +78,7 @@ describe('tool/tool-form/item', () => {
|
||||
mockUseLanguage.mockReturnValue('en_US')
|
||||
})
|
||||
|
||||
// Text input fields render their descriptions inline above the input.
|
||||
it('should render text input labels and forward props to form input item', () => {
|
||||
const handleChange = vi.fn()
|
||||
const handleManageInputField = vi.fn()
|
||||
@ -121,6 +122,31 @@ describe('tool/tool-form/item', () => {
|
||||
})
|
||||
})
|
||||
|
||||
// URL fragments inside descriptions should be rendered as external links.
|
||||
it('should render URLs in descriptions as external links', () => {
|
||||
render(
|
||||
<ToolFormItem
|
||||
readOnly={false}
|
||||
nodeId="tool-node"
|
||||
schema={createSchema({
|
||||
tooltip: {
|
||||
en_US: 'Visit https://docs.dify.ai/tools for docs',
|
||||
zh_Hans: 'Visit https://docs.dify.ai/tools for docs',
|
||||
},
|
||||
})}
|
||||
value={{}}
|
||||
onChange={vi.fn()}
|
||||
/>,
|
||||
)
|
||||
|
||||
const link = screen.getByRole('link', { name: 'https://docs.dify.ai/tools' })
|
||||
expect(link).toHaveAttribute('href', 'https://docs.dify.ai/tools')
|
||||
expect(link).toHaveAttribute('target', '_blank')
|
||||
expect(link).toHaveAttribute('rel', 'noopener noreferrer')
|
||||
expect(link.parentElement).toHaveTextContent('Visit https://docs.dify.ai/tools for docs')
|
||||
})
|
||||
|
||||
// Non-text fields keep their descriptions inside the tooltip and support JSON schema preview.
|
||||
it('should show tooltip for non-description fields and open the schema modal', () => {
|
||||
const objectSchema = createSchema({
|
||||
name: 'tool_config',
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import type { FC, ReactNode } from 'react'
|
||||
import type { ToolVarInputs } from '../../types'
|
||||
import type { CredentialFormSchema } from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||
import type { Tool } from '@/app/components/tools/types'
|
||||
@ -15,6 +15,45 @@ import { useLanguage } from '@/app/components/header/account-setting/model-provi
|
||||
import { SchemaModal } from '@/app/components/plugins/plugin-detail-panel/tool-selector/components'
|
||||
import FormInputItem from '@/app/components/workflow/nodes/_base/components/form-input-item'
|
||||
|
||||
const URL_REGEX = /(https?:\/\/\S+)/g
|
||||
|
||||
const renderDescriptionWithLinks = (description: string): ReactNode => {
|
||||
const matches = [...description.matchAll(URL_REGEX)]
|
||||
|
||||
if (!matches.length)
|
||||
return description
|
||||
|
||||
const parts: ReactNode[] = []
|
||||
let currentIndex = 0
|
||||
|
||||
matches.forEach((match, index) => {
|
||||
const [url] = match
|
||||
const start = match.index ?? 0
|
||||
|
||||
if (start > currentIndex)
|
||||
parts.push(description.slice(currentIndex, start))
|
||||
|
||||
parts.push(
|
||||
<a
|
||||
key={`${url}-${index}`}
|
||||
href={url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-text-accent hover:underline"
|
||||
>
|
||||
{url}
|
||||
</a>,
|
||||
)
|
||||
|
||||
currentIndex = start + url.length
|
||||
})
|
||||
|
||||
if (currentIndex < description.length)
|
||||
parts.push(description.slice(currentIndex))
|
||||
|
||||
return parts
|
||||
}
|
||||
|
||||
type Props = {
|
||||
readOnly: boolean
|
||||
nodeId: string
|
||||
@ -87,7 +126,9 @@ const ToolFormItem: FC<Props> = ({
|
||||
)}
|
||||
</div>
|
||||
{showDescription && tooltip && (
|
||||
<div className="body-xs-regular pb-0.5 text-text-tertiary">{tooltip[language] || tooltip.en_US}</div>
|
||||
<div className="body-xs-regular break-words pb-0.5 text-text-tertiary">
|
||||
{renderDescriptionWithLinks(tooltip[language] || tooltip.en_US)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<FormInputItem
|
||||
|
||||
Loading…
Reference in New Issue
Block a user