diff --git a/web/app/components/base/markdown-blocks/__tests__/think-block.spec.tsx b/web/app/components/base/markdown-blocks/__tests__/think-block.spec.tsx index 4f22468157..08b46863cf 100644 --- a/web/app/components/base/markdown-blocks/__tests__/think-block.spec.tsx +++ b/web/app/components/base/markdown-blocks/__tests__/think-block.spec.tsx @@ -74,6 +74,18 @@ describe('ThinkBlock', () => { expect(screen.getByText('Thinking content')).toBeInTheDocument() }) + it('should render think block when dataThink is true', () => { + renderWithContext( + +

Thinking content

+
, + true, + ) + + expect(screen.getByText(/Thinking\.\.\./)).toBeInTheDocument() + expect(screen.getByText('Thinking content')).toBeInTheDocument() + }) + it('should render thought state when content has ENDTHINKFLAG', () => { renderWithContext( diff --git a/web/app/components/base/markdown-blocks/think-block.tsx b/web/app/components/base/markdown-blocks/think-block.tsx index 184ed89274..c3bd411cbe 100644 --- a/web/app/components/base/markdown-blocks/think-block.tsx +++ b/web/app/components/base/markdown-blocks/think-block.tsx @@ -72,13 +72,15 @@ const useThinkTimer = (children: any) => { type ThinkBlockProps = React.ComponentProps<'details'> & { 'data-think'?: boolean + 'dataThink'?: boolean } const ThinkBlock = ({ children, ...props }: ThinkBlockProps) => { const { elapsedTime, isComplete } = useThinkTimer(children) const displayContent = removeEndThink(children) const { t } = useTranslation() - const { 'data-think': isThink = false, className, open, ...rest } = props + const { 'data-think': dataThinkAttr, dataThink: dataThinkProp, className, open, ...rest } = props + const isThink = Boolean(dataThinkAttr ?? dataThinkProp) if (!isThink) return (
{children}
) diff --git a/web/app/components/base/markdown/streamdown-wrapper.tsx b/web/app/components/base/markdown/streamdown-wrapper.tsx index 46db301adb..173923fdc7 100644 --- a/web/app/components/base/markdown/streamdown-wrapper.tsx +++ b/web/app/components/base/markdown/streamdown-wrapper.tsx @@ -43,8 +43,9 @@ const mathPlugin = createMathPlugin({ /** * Allowed HTML tags and their permitted data attributes for rehype-sanitize. - * Keys = tag names to allow; values = attribute names in **hast** property format - * (camelCase, e.g. `dataThink` for `data-think`). + * Keys = tag names to allow; values = attribute names used by the sanitize schema. + * Prefer **hast** property format (camelCase, e.g. `dataThink` for `data-think`), + * but include kebab-case variants when different parser paths can emit both forms. * * Prefer explicit attribute lists over wildcards (e.g. `data*`) to * minimise the attack surface when LLM-generated content is rendered. @@ -55,7 +56,7 @@ const ALLOWED_TAGS: Record = { input: ['type', 'name', 'value', 'placeholder', 'checked', 'dataTip', 'dataOptions'], textarea: ['name', 'placeholder', 'value'], label: ['htmlFor'], - details: ['dataThink'], + details: ['dataThink', 'data-think'], video: ['src'], audio: ['src'], source: ['src'],