mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-08 20:42:30 +08:00
### What problem does this PR solve? Feat: Configure structured data output for agent forms #10866 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
208
web/src/components/jsonjoy-builder/hooks/use-monaco-theme.ts
Normal file
208
web/src/components/jsonjoy-builder/hooks/use-monaco-theme.ts
Normal file
@ -0,0 +1,208 @@
|
||||
import type * as Monaco from 'monaco-editor';
|
||||
import { useEffect, useState } from 'react';
|
||||
import type { JSONSchema } from '../types/jsonSchema.ts';
|
||||
|
||||
export interface MonacoEditorOptions {
|
||||
minimap?: { enabled: boolean };
|
||||
fontSize?: number;
|
||||
fontFamily?: string;
|
||||
lineNumbers?: 'on' | 'off';
|
||||
roundedSelection?: boolean;
|
||||
scrollBeyondLastLine?: boolean;
|
||||
readOnly?: boolean;
|
||||
automaticLayout?: boolean;
|
||||
formatOnPaste?: boolean;
|
||||
formatOnType?: boolean;
|
||||
tabSize?: number;
|
||||
insertSpaces?: boolean;
|
||||
detectIndentation?: boolean;
|
||||
folding?: boolean;
|
||||
foldingStrategy?: 'auto' | 'indentation';
|
||||
renderLineHighlight?: 'all' | 'line' | 'none' | 'gutter';
|
||||
matchBrackets?: 'always' | 'near' | 'never';
|
||||
autoClosingBrackets?:
|
||||
| 'always'
|
||||
| 'languageDefined'
|
||||
| 'beforeWhitespace'
|
||||
| 'never';
|
||||
autoClosingQuotes?:
|
||||
| 'always'
|
||||
| 'languageDefined'
|
||||
| 'beforeWhitespace'
|
||||
| 'never';
|
||||
guides?: {
|
||||
bracketPairs?: boolean;
|
||||
indentation?: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
export const defaultEditorOptions: MonacoEditorOptions = {
|
||||
minimap: { enabled: false },
|
||||
fontSize: 14,
|
||||
fontFamily: "var(--font-sans), 'SF Mono', Monaco, Menlo, Consolas, monospace",
|
||||
lineNumbers: 'on',
|
||||
roundedSelection: false,
|
||||
scrollBeyondLastLine: false,
|
||||
readOnly: false,
|
||||
automaticLayout: true,
|
||||
formatOnPaste: true,
|
||||
formatOnType: true,
|
||||
tabSize: 2,
|
||||
insertSpaces: true,
|
||||
detectIndentation: true,
|
||||
folding: true,
|
||||
foldingStrategy: 'indentation',
|
||||
renderLineHighlight: 'all',
|
||||
matchBrackets: 'always',
|
||||
autoClosingBrackets: 'always',
|
||||
autoClosingQuotes: 'always',
|
||||
guides: {
|
||||
bracketPairs: true,
|
||||
indentation: true,
|
||||
},
|
||||
};
|
||||
|
||||
export function useMonacoTheme() {
|
||||
const [isDarkMode, setIsDarkMode] = useState(false);
|
||||
|
||||
// Check for dark mode by examining CSS variables
|
||||
useEffect(() => {
|
||||
const checkDarkMode = () => {
|
||||
// Get the current background color value
|
||||
const backgroundColor = getComputedStyle(document.documentElement)
|
||||
.getPropertyValue('--background')
|
||||
.trim();
|
||||
|
||||
// If the background color HSL has a low lightness value, it's likely dark mode
|
||||
const isDark =
|
||||
backgroundColor.includes('222.2') ||
|
||||
backgroundColor.includes('84% 4.9%');
|
||||
|
||||
setIsDarkMode(isDark);
|
||||
};
|
||||
|
||||
// Check initially
|
||||
checkDarkMode();
|
||||
|
||||
// Set up a mutation observer to detect theme changes
|
||||
const observer = new MutationObserver(checkDarkMode);
|
||||
observer.observe(document.documentElement, {
|
||||
attributes: true,
|
||||
attributeFilter: ['class', 'style'],
|
||||
});
|
||||
|
||||
return () => observer.disconnect();
|
||||
}, []);
|
||||
|
||||
const defineMonacoThemes = (monaco: typeof Monaco) => {
|
||||
// Define custom light theme that matches app colors
|
||||
monaco.editor.defineTheme('appLightTheme', {
|
||||
base: 'vs',
|
||||
inherit: true,
|
||||
rules: [
|
||||
// JSON syntax highlighting based on utils.ts type colors
|
||||
{ token: 'string', foreground: '3B82F6' }, // text-blue-500
|
||||
{ token: 'number', foreground: 'A855F7' }, // text-purple-500
|
||||
{ token: 'keyword', foreground: '3B82F6' }, // text-blue-500
|
||||
{ token: 'delimiter', foreground: '0F172A' }, // text-slate-900
|
||||
{ token: 'keyword.json', foreground: 'A855F7' }, // text-purple-500
|
||||
{ token: 'string.key.json', foreground: '2563EB' }, // text-blue-600
|
||||
{ token: 'string.value.json', foreground: '3B82F6' }, // text-blue-500
|
||||
{ token: 'boolean', foreground: '22C55E' }, // text-green-500
|
||||
{ token: 'null', foreground: '64748B' }, // text-gray-500
|
||||
],
|
||||
colors: {
|
||||
// Light theme colors (using hex values instead of CSS variables)
|
||||
'editor.background': '#f8fafc', // --background
|
||||
'editor.foreground': '#0f172a', // --foreground
|
||||
'editorCursor.foreground': '#0f172a', // --foreground
|
||||
'editor.lineHighlightBackground': '#f1f5f9', // --muted
|
||||
'editorLineNumber.foreground': '#64748b', // --muted-foreground
|
||||
'editor.selectionBackground': '#e2e8f0', // --accent
|
||||
'editor.inactiveSelectionBackground': '#e2e8f0', // --accent
|
||||
'editorIndentGuide.background': '#e2e8f0', // --border
|
||||
'editor.findMatchBackground': '#cbd5e1', // --accent
|
||||
'editor.findMatchHighlightBackground': '#cbd5e133', // --accent with opacity
|
||||
},
|
||||
});
|
||||
|
||||
// Define custom dark theme that matches app colors
|
||||
monaco.editor.defineTheme('appDarkTheme', {
|
||||
base: 'vs-dark',
|
||||
inherit: true,
|
||||
rules: [
|
||||
// JSON syntax highlighting based on utils.ts type colors
|
||||
{ token: 'string', foreground: '3B82F6' }, // text-blue-500
|
||||
{ token: 'number', foreground: 'A855F7' }, // text-purple-500
|
||||
{ token: 'keyword', foreground: '3B82F6' }, // text-blue-500
|
||||
{ token: 'delimiter', foreground: 'F8FAFC' }, // text-slate-50
|
||||
{ token: 'keyword.json', foreground: 'A855F7' }, // text-purple-500
|
||||
{ token: 'string.key.json', foreground: '60A5FA' }, // text-blue-400
|
||||
{ token: 'string.value.json', foreground: '3B82F6' }, // text-blue-500
|
||||
{ token: 'boolean', foreground: '22C55E' }, // text-green-500
|
||||
{ token: 'null', foreground: '94A3B8' }, // text-gray-400
|
||||
],
|
||||
colors: {
|
||||
// Dark theme colors (using hex values instead of CSS variables)
|
||||
'editor.background': '#0f172a', // --background
|
||||
'editor.foreground': '#f8fafc', // --foreground
|
||||
'editorCursor.foreground': '#f8fafc', // --foreground
|
||||
'editor.lineHighlightBackground': '#1e293b', // --muted
|
||||
'editorLineNumber.foreground': '#64748b', // --muted-foreground
|
||||
'editor.selectionBackground': '#334155', // --accent
|
||||
'editor.inactiveSelectionBackground': '#334155', // --accent
|
||||
'editorIndentGuide.background': '#1e293b', // --border
|
||||
'editor.findMatchBackground': '#475569', // --accent
|
||||
'editor.findMatchHighlightBackground': '#47556933', // --accent with opacity
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// Helper to configure JSON language validation
|
||||
const configureJsonDefaults = (
|
||||
monaco: typeof Monaco,
|
||||
schema?: JSONSchema,
|
||||
) => {
|
||||
// Create a new diagnostics options object
|
||||
const diagnosticsOptions: Monaco.languages.json.DiagnosticsOptions = {
|
||||
validate: true,
|
||||
allowComments: false,
|
||||
schemaValidation: 'error',
|
||||
enableSchemaRequest: true,
|
||||
schemas: schema
|
||||
? [
|
||||
{
|
||||
uri:
|
||||
typeof schema === 'object' && schema.$id
|
||||
? schema.$id
|
||||
: 'https://jsonjoy-builder/schema',
|
||||
fileMatch: ['*'],
|
||||
schema,
|
||||
},
|
||||
]
|
||||
: [
|
||||
{
|
||||
uri: 'http://json-schema.org/draft-07/schema',
|
||||
fileMatch: ['*'],
|
||||
schema: {
|
||||
$schema: 'http://json-schema.org/draft-07/schema',
|
||||
type: 'object',
|
||||
additionalProperties: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
monaco.languages.json.jsonDefaults.setDiagnosticsOptions(
|
||||
diagnosticsOptions,
|
||||
);
|
||||
};
|
||||
|
||||
return {
|
||||
isDarkMode,
|
||||
currentTheme: isDarkMode ? 'appDarkTheme' : 'appLightTheme',
|
||||
defineMonacoThemes,
|
||||
configureJsonDefaults,
|
||||
defaultEditorOptions,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user