feat: introduce trigger functionality (#27644)
Signed-off-by: lyzno1 <yuanyouhuilyz@gmail.com> Co-authored-by: Stream <Stream_2@qq.com> Co-authored-by: lyzno1 <92089059+lyzno1@users.noreply.github.com> Co-authored-by: zhsama <torvalds@linux.do> Co-authored-by: Harry <xh001x@hotmail.com> Co-authored-by: lyzno1 <yuanyouhuilyz@gmail.com> Co-authored-by: yessenia <yessenia.contact@gmail.com> Co-authored-by: hjlarry <hjlarry@163.com> Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: WTW0313 <twwu@dify.ai> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -5,9 +5,11 @@
|
||||
|
||||
export { default as AudioBlock } from './audio-block'
|
||||
export { default as CodeBlock } from './code-block'
|
||||
export * from './plugin-img'
|
||||
export * from './plugin-paragraph'
|
||||
export { default as Img } from './img'
|
||||
export { default as Link } from './link'
|
||||
export { default as Paragraph } from './paragraph'
|
||||
export { default as Link } from './link'
|
||||
export { default as PreCode } from './pre-code'
|
||||
export { default as ScriptBlock } from './script-block'
|
||||
export { default as VideoBlock } from './video-block'
|
||||
|
||||
48
web/app/components/base/markdown-blocks/plugin-img.tsx
Normal file
48
web/app/components/base/markdown-blocks/plugin-img.tsx
Normal file
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* @fileoverview Img component for rendering <img> tags in Markdown.
|
||||
* Extracted from the main markdown renderer for modularity.
|
||||
* Uses the ImageGallery component to display images.
|
||||
*/
|
||||
import React, { useEffect, useMemo, useState } from 'react'
|
||||
import ImageGallery from '@/app/components/base/image-gallery'
|
||||
import { getMarkdownImageURL } from './utils'
|
||||
import { usePluginReadmeAsset } from '@/service/use-plugins'
|
||||
import type { SimplePluginInfo } from '../markdown/react-markdown-wrapper'
|
||||
|
||||
type ImgProps = {
|
||||
src: string
|
||||
pluginInfo?: SimplePluginInfo
|
||||
}
|
||||
|
||||
export const PluginImg: React.FC<ImgProps> = ({ src, pluginInfo }) => {
|
||||
const { pluginUniqueIdentifier, pluginId } = pluginInfo || {}
|
||||
const { data: assetData } = usePluginReadmeAsset({ plugin_unique_identifier: pluginUniqueIdentifier, file_name: src })
|
||||
const [blobUrl, setBlobUrl] = useState<string>()
|
||||
|
||||
useEffect(() => {
|
||||
if (!assetData) {
|
||||
setBlobUrl(undefined)
|
||||
return
|
||||
}
|
||||
|
||||
const objectUrl = URL.createObjectURL(assetData)
|
||||
setBlobUrl(objectUrl)
|
||||
|
||||
return () => {
|
||||
URL.revokeObjectURL(objectUrl)
|
||||
}
|
||||
}, [assetData])
|
||||
|
||||
const imageUrl = useMemo(() => {
|
||||
if (blobUrl)
|
||||
return blobUrl
|
||||
|
||||
return getMarkdownImageURL(src, pluginId)
|
||||
}, [blobUrl, pluginId, src])
|
||||
|
||||
return (
|
||||
<div className="markdown-img-wrapper">
|
||||
<ImageGallery srcs={[imageUrl]} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
69
web/app/components/base/markdown-blocks/plugin-paragraph.tsx
Normal file
69
web/app/components/base/markdown-blocks/plugin-paragraph.tsx
Normal file
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* @fileoverview Paragraph component for rendering <p> tags in Markdown.
|
||||
* Extracted from the main markdown renderer for modularity.
|
||||
* Handles special rendering for paragraphs that directly contain an image.
|
||||
*/
|
||||
import ImageGallery from '@/app/components/base/image-gallery'
|
||||
import { usePluginReadmeAsset } from '@/service/use-plugins'
|
||||
import React, { useEffect, useMemo, useState } from 'react'
|
||||
import type { SimplePluginInfo } from '../markdown/react-markdown-wrapper'
|
||||
import { getMarkdownImageURL } from './utils'
|
||||
|
||||
type PluginParagraphProps = {
|
||||
pluginInfo?: SimplePluginInfo
|
||||
node?: any
|
||||
children?: React.ReactNode
|
||||
}
|
||||
|
||||
export const PluginParagraph: React.FC<PluginParagraphProps> = ({ pluginInfo, node, children }) => {
|
||||
const { pluginUniqueIdentifier, pluginId } = pluginInfo || {}
|
||||
const childrenNode = node?.children as Array<any> | undefined
|
||||
const firstChild = childrenNode?.[0]
|
||||
const isImageParagraph = firstChild?.tagName === 'img'
|
||||
const imageSrc = isImageParagraph ? firstChild?.properties?.src : undefined
|
||||
|
||||
const { data: assetData } = usePluginReadmeAsset({
|
||||
plugin_unique_identifier: pluginUniqueIdentifier,
|
||||
file_name: isImageParagraph && imageSrc ? imageSrc : '',
|
||||
})
|
||||
|
||||
const [blobUrl, setBlobUrl] = useState<string>()
|
||||
|
||||
useEffect(() => {
|
||||
if (!assetData) {
|
||||
setBlobUrl(undefined)
|
||||
return
|
||||
}
|
||||
|
||||
const objectUrl = URL.createObjectURL(assetData)
|
||||
setBlobUrl(objectUrl)
|
||||
|
||||
return () => {
|
||||
URL.revokeObjectURL(objectUrl)
|
||||
}
|
||||
}, [assetData])
|
||||
|
||||
const imageUrl = useMemo(() => {
|
||||
if (blobUrl)
|
||||
return blobUrl
|
||||
|
||||
if (isImageParagraph && imageSrc)
|
||||
return getMarkdownImageURL(imageSrc, pluginId)
|
||||
|
||||
return ''
|
||||
}, [blobUrl, imageSrc, isImageParagraph, pluginId])
|
||||
|
||||
if (isImageParagraph) {
|
||||
const remainingChildren = Array.isArray(children) && children.length > 1 ? children.slice(1) : undefined
|
||||
|
||||
return (
|
||||
<div className="markdown-img-wrapper">
|
||||
<ImageGallery srcs={[imageUrl]} />
|
||||
{remainingChildren && (
|
||||
<div className="mt-2">{remainingChildren}</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
return <p>{children}</p>
|
||||
}
|
||||
@@ -1,7 +1,14 @@
|
||||
import { ALLOW_UNSAFE_DATA_SCHEME } from '@/config'
|
||||
import { ALLOW_UNSAFE_DATA_SCHEME, MARKETPLACE_API_PREFIX } from '@/config'
|
||||
|
||||
export const isValidUrl = (url: string): boolean => {
|
||||
const validPrefixes = ['http:', 'https:', '//', 'mailto:']
|
||||
if (ALLOW_UNSAFE_DATA_SCHEME) validPrefixes.push('data:')
|
||||
return validPrefixes.some(prefix => url.startsWith(prefix))
|
||||
}
|
||||
|
||||
export const getMarkdownImageURL = (url: string, pathname?: string) => {
|
||||
const regex = /(^\.\/_assets|^_assets)/
|
||||
if (regex.test(url))
|
||||
return `${MARKETPLACE_API_PREFIX}${MARKETPLACE_API_PREFIX.endsWith('/') ? '' : '/'}plugins/${pathname ?? ''}${url.replace(regex, '/_assets')}`
|
||||
return url
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user