refactor: replace react markdown with streamdown (#32971)

Co-authored-by: Stephen Zhou <hi@hyoban.cc>
Co-authored-by: Stephen Zhou <38493346+hyoban@users.noreply.github.com>
Co-authored-by: yyh <92089059+lyzno1@users.noreply.github.com>
This commit is contained in:
Wu Tianwei
2026-03-10 17:02:37 +08:00
committed by GitHub
parent 2a468da440
commit 75bbb616ea
36 changed files with 1055 additions and 753 deletions

View File

@ -2,7 +2,6 @@
import type { FC } from 'react'
import type { FormInputItem, UserAction } from '../types'
import type { ButtonProps } from '@/app/components/base/button'
import { RiCloseLine } from '@remixicon/react'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
import ActionButton from '@/app/components/base/action-button'
@ -14,6 +13,7 @@ import { useStore } from '@/app/components/workflow/store'
import useNodes from '@/app/components/workflow/store/workflow/use-nodes'
import { Note, rehypeNotes, rehypeVariable, Variable } from './variable-in-markdown'
const NODE_ID_RE = /#([^#.]+)([.#])/g
const i18nPrefix = 'nodes.humanInput'
type FormContentPreviewProps = {
@ -47,25 +47,25 @@ const FormContentPreview: FC<FormContentPreviewProps> = ({
>
<div className="flex h-[26px] items-center justify-between px-4">
<Badge uppercase className="border-text-accent-secondary text-text-accent-secondary">{t(`${i18nPrefix}.formContent.preview`, { ns: 'workflow' })}</Badge>
<ActionButton onClick={onClose}><RiCloseLine className="w-5 text-text-tertiary" /></ActionButton>
<ActionButton onClick={onClose}><span className="i-ri-close-line size-5 text-text-tertiary" /></ActionButton>
</div>
<div className="max-h-[calc(100vh-167px)] overflow-y-auto px-4">
<Markdown
content={content}
rehypePlugins={[rehypeVariable, rehypeNotes]}
customComponents={{
variable: ({ node }: { node: { properties?: { [key: string]: string } } }) => {
const path = node.properties?.['data-path'] as string
variable: ({ node }) => {
const path = String(node?.properties?.dataPath ?? '')
let newPath = path
if (path) {
newPath = path.replace(/#([^#.]+)([.#])/g, (match, nodeId, sep) => {
newPath = path.replace(NODE_ID_RE, (match, nodeId, sep) => {
return `#${nodeName(nodeId)}${sep}`
})
}
return <Variable path={newPath} />
},
section: ({ node }: { node: { properties?: { [key: string]: string } } }) => (() => {
const name = node.properties?.['data-name'] as string
section: ({ node }) => (() => {
const name = String(node?.properties?.dataName ?? '')
const input = formInputs.find(i => i.output_variable_name === name)
if (!input) {
return (
@ -92,7 +92,7 @@ const FormContentPreview: FC<FormContentPreviewProps> = ({
</Button>
))}
</div>
<div className="system-xs-regular mt-1 text-text-tertiary">{t('nodes.humanInput.editor.previewTip', { ns: 'workflow' })}</div>
<div className="mt-1 text-text-tertiary system-xs-regular">{t('nodes.humanInput.editor.previewTip', { ns: 'workflow' })}</div>
</div>
</div>
)

View File

@ -24,7 +24,7 @@ export function rehypeVariable() {
parts.push({
type: 'element',
tagName: 'variable',
properties: { 'data-path': m[0].trim() },
properties: { dataPath: m[0].trim() },
children: [],
})
@ -77,7 +77,7 @@ export function rehypeNotes() {
parts.push({
type: 'element',
tagName: 'section',
properties: { 'data-name': name },
properties: { dataName: name },
children: [],
})