Просмотр исходного кода

fix(material): json-editor-with-variables grammar hint (#517)

Yiwei Mao 6 месяцев назад
Родитель
Сommit
0e20665a8e

+ 16 - 1
packages/materials/form-materials/src/components/code-editor/index.tsx

@@ -5,7 +5,12 @@
 
 import React, { useEffect, useRef } from 'react';
 
-import { ActiveLinePlaceholder, createRenderer, EditorProvider } from '@coze-editor/editor/react';
+import {
+  ActiveLinePlaceholder,
+  createRenderer,
+  EditorProvider,
+  InferValues,
+} from '@coze-editor/editor/react';
 import preset, { type EditorAPI } from '@coze-editor/editor/preset-code';
 import { EditorView } from '@codemirror/view';
 
@@ -22,6 +27,9 @@ const OriginCodeEditor = createRenderer(preset, [
   }),
 ]);
 
+type Preset = typeof preset;
+type Options = Partial<InferValues<Preset[number]>>;
+
 export interface CodeEditorPropsType extends React.PropsWithChildren<{}> {
   value?: string;
   onChange?: (value: string) => void;
@@ -29,6 +37,8 @@ export interface CodeEditorPropsType extends React.PropsWithChildren<{}> {
   theme?: 'dark' | 'light';
   placeholder?: string;
   activeLinePlaceholder?: string;
+  readonly?: boolean;
+  options?: Options;
 }
 
 export function CodeEditor({
@@ -39,6 +49,8 @@ export function CodeEditor({
   children,
   placeholder,
   activeLinePlaceholder,
+  options,
+  readonly,
 }: CodeEditorPropsType) {
   const editorRef = useRef<EditorAPI | null>(null);
 
@@ -58,6 +70,9 @@ export function CodeEditor({
           languageId,
           theme,
           placeholder,
+          readOnly: readonly,
+          editable: !readonly,
+          ...(options || {}),
         }}
         didMount={(editor: EditorAPI) => {
           editorRef.current = editor;

+ 1 - 1
packages/materials/form-materials/src/components/code-editor/theme/light.ts

@@ -30,7 +30,7 @@ export const lightTheme: Extension = createTheme({
     gutterBorderColor: 'transparent',
     gutterBorderWidth: 0,
     lineHighlight: '#f0f0f0',
-    bracketColors: ['#FFEF61', '#DD99FF', '#78B0FF'],
+    bracketColors: ['#FFD700', '#DD99FF', '#78B0FF'],
     tooltip: {
       backgroundColor: '#f0f0f0',
       color: '#000',

+ 47 - 1
packages/materials/form-materials/src/components/json-editor-with-variables/index.tsx

@@ -5,13 +5,59 @@
 
 import React from 'react';
 
+import { transformerCreator } from '@coze-editor/editor/preset-code';
+import { Text } from '@coze-editor/editor/language-json';
+
 import { VariableTree } from './extensions/variable-tree';
 import { VariableTagInject } from './extensions/variable-tag';
 import { CodeEditor, type CodeEditorPropsType } from '../code-editor';
 
+type Match = { match: string; range: [number, number] };
+function findAllMatches(inputString: string, regex: RegExp): Match[] {
+  const globalRegex = new RegExp(
+    regex,
+    regex.flags.includes('g') ? regex.flags : regex.flags + 'g'
+  );
+  let match;
+  const matches: Match[] = [];
+
+  while ((match = globalRegex.exec(inputString)) !== null) {
+    if (match.index === globalRegex.lastIndex) {
+      globalRegex.lastIndex++;
+    }
+    matches.push({
+      match: match[0],
+      range: [match.index, match.index + match[0].length],
+    });
+  }
+
+  return matches;
+}
+
+const transformer = transformerCreator((text: Text) => {
+  const originalSource = text.toString();
+  const matches = findAllMatches(originalSource, /\{\{([^\}]*)\}\}/g);
+
+  if (matches.length > 0) {
+    matches.forEach(({ range }) => {
+      text.replaceRange(range[0], range[1], 'null');
+    });
+  }
+
+  return text;
+});
+
 export function JsonEditorWithVariables(props: Omit<CodeEditorPropsType, 'languageId'>) {
   return (
-    <CodeEditor languageId="json" activeLinePlaceholder="Press '@' to Select variable" {...props}>
+    <CodeEditor
+      languageId="json"
+      activeLinePlaceholder="Press '@' to Select variable"
+      {...props}
+      options={{
+        transformer,
+        ...(props.options || {}),
+      }}
+    >
       <VariableTree />
       <VariableTagInject />
     </CodeEditor>