🌗 refactor: Consistent Mermaid Theming for Inline and Artifact Renderers (#12055)

* refactor: consistent theming between inline and Artifacts Mermaid Diagram

* refactor: Enhance Mermaid component with improved theming and security features

- Updated Mermaid component to utilize useCallback for performance optimization.
- Increased maximum zoom level from 4 to 10 for better diagram visibility.
- Added security level configuration to Mermaid initialization for enhanced security.
- Refactored theme handling to ensure consistent theming between inline and artifact diagrams.
- Introduced unit tests for Mermaid configuration to validate flowchart settings and theme behavior.

* refactor: Improve theme handling in useMermaid hook

- Enhanced theme variable management by merging custom theme variables with default values for dark mode.
- Ensured consistent theming across Mermaid diagrams by preserving existing theme configurations while applying new defaults.

* refactor: Consolidate imports in mermaid test file

- Combined multiple imports from the mermaid utility into a single statement for improved readability and organization in the test file.

* feat: Add subgraph title contrast adjustment for Mermaid diagrams

- Introduced a utility function to enhance text visibility on subgraph titles by adjusting the fill color based on background luminance.
- Updated the Mermaid component to utilize this function, ensuring better contrast in rendered SVGs.
- Added comprehensive unit tests to validate the contrast adjustment logic across various scenarios.

* refactor: Update MermaidHeader component for improved button accessibility and styling

- Replaced Button components with TooltipAnchor for better accessibility and user experience.
- Consolidated button styles into a single class for consistency.
- Enhanced the layout and spacing of the header for a cleaner appearance.

* fix: hex color handling and improve contrast adjustment in Mermaid diagrams

- Updated hexLuminance function to support 3-character hex shorthand by expanding it to 6 characters.
- Refined the fixSubgraphTitleContrast function to avoid double semicolons in style attributes and ensure proper fill color adjustments based on background luminance.
- Added unit tests to validate the handling of 3-character hex fills and the prevention of double semicolons in text styles.

* chore: Simplify Virtual Scrolling Performance tests by removing performance timing checks

- Removed performance timing checks and associated console logs from tests handling 1000 and 5000 agents.
- Focused tests on verifying the correct rendering of virtual list items without measuring render time.
This commit is contained in:
Danny Avila 2026-03-04 08:25:57 -05:00
parent 6ebee069c7
commit f1eabdbdb7
No known key found for this signature in database
GPG key ID: BF31EEB2C5CA0956
8 changed files with 671 additions and 309 deletions

View file

@ -1,17 +1,21 @@
import { useMemo } from 'react';
import { useContext, useMemo } from 'react';
import { ThemeContext, isDark } from '@librechat/client';
import { removeNullishValues } from 'librechat-data-provider';
import type { Artifact } from '~/common';
import { getKey, getProps, getTemplate, getArtifactFilename } from '~/utils/artifacts';
import { getMermaidFiles } from '~/utils/mermaid';
import { getMarkdownFiles } from '~/utils/markdown';
import { getMermaidFiles } from '~/utils/mermaid';
export default function useArtifactProps({ artifact }: { artifact: Artifact }) {
const { theme } = useContext(ThemeContext);
const isDarkMode = isDark(theme);
const [fileKey, files] = useMemo(() => {
const key = getKey(artifact.type ?? '', artifact.language);
const type = artifact.type ?? '';
if (key.includes('mermaid')) {
return ['diagram.mmd', getMermaidFiles(artifact.content ?? '')];
return ['diagram.mmd', getMermaidFiles(artifact.content ?? '', isDarkMode)];
}
if (type === 'text/markdown' || type === 'text/md' || type === 'text/plain') {
@ -23,7 +27,7 @@ export default function useArtifactProps({ artifact }: { artifact: Artifact }) {
[fileKey]: artifact.content,
});
return [fileKey, files];
}, [artifact.type, artifact.content, artifact.language]);
}, [artifact.type, artifact.content, artifact.language, isDarkMode]);
const template = useMemo(
() => getTemplate(artifact.type ?? '', artifact.language),

View file

@ -1,9 +1,10 @@
import { useContext, useMemo, useState } from 'react';
import DOMPurify from 'dompurify';
import useSWR from 'swr';
import { Md5 } from 'ts-md5';
import DOMPurify from 'dompurify';
import { ThemeContext, isDark } from '@librechat/client';
import type { MermaidConfig } from 'mermaid';
import { inlineFlowchartConfig } from '~/utils/mermaid';
// Constants
const MD5_LENGTH_THRESHOLD = 10_000;
@ -85,12 +86,12 @@ export const useMermaid = ({
return {
startOnLoad: false,
theme: (customTheme as MermaidConfig['theme']) || defaultTheme,
// Spread custom config but override security settings after
...config,
// Security hardening - these MUST come last to prevent override
securityLevel: 'strict', // Highest security: disables click, sanitizes text
maxTextSize: config?.maxTextSize ?? 50000, // Limit text size to prevent DoS
maxEdges: config?.maxEdges ?? 500, // Limit edges to prevent DoS
flowchart: { ...inlineFlowchartConfig, ...config?.flowchart, htmlLabels: false },
// Security hardening: MUST come after ...config spread to prevent override
securityLevel: 'strict',
maxTextSize: config?.maxTextSize ?? 50000,
maxEdges: config?.maxEdges ?? 500,
};
}, [customTheme, isDarkMode, config]);