前端的代码编辑器选型主要有monaco-editor和CodeMirror两种,我司低代码实践中的代码编辑场景主要是函数设置,因此选择了更为轻量的CodeMirror。
CodeMirror使用
CodeMirror用法比较简单,核心代码如下(这里CodeMirror的版本是5.65)
kotlin
import codemirror from 'codemirror';
import 'codemirror/lib/codemirror.css';
import 'codemirror/mode/javascript/javascript.js';
class CodeEditor extends React.Component<Props> {
private ref = React.createRef<HTMLDivElement>();
private editor: codemirror.Editor | undefined;
setReadOnlyCodes = () => {
const { editor } = this;
if (editor) {
const firstLine = editor.firstLine();
const firstLineHandle = editor.getLineHandle(firstLine);
const lastLine = editor.lastLine();
editor.markText(
{ line: firstLine, ch: 0 },
{ line: firstLine, ch: firstLineHandle.text.length },
{ className: 'readonly' },
);
editor.markText(
{ line: lastLine, ch: 0 },
{ line: lastLine + 1, ch: 0 },
{ className: 'readonly' },
);
}
};
componentDidMount() {
const { value = '' } = this.props;
if (this.ref.current) {
const editor = codemirror(this.ref.current, {
lineWrapping: true,
indentWithTabs: true,
lineNumbers: true,
matchBrackets: true,
autofocus: true,
extraKeys: { Tab: 'autocomplete' },
hintOptions: {
completeSingle: false,
additionalContext: this.props.additionalContext || {},
},
mode: 'javascript',
value,
});
editor.on('change', this.changeDelay);
editor.on('inputRead', this.handleInputRead);
editor.on('beforeChange', this.handleBeforeChange);
this.editor = editor;
this.setReadOnlyCodes();
}
}
render() {
return <div className="code-editor" ref={this.ref}></div>;
}
}
语法提示、校验和转换
语法提示
CodeEditor自带js原生的语法提示
ini
<div>
<CodeEditor
additionalContext={{env:{app:'',pageCode:''}}}
value={currentCodes}
onChange={(data)=>{
setCurrentCodes(data)
}
}
errorInfo={codeErr}
/>
<Button type="primary" onClick={()=>{
console.log(transferCodes(currentCodes))
}}>语法校验和转换</Button>
</div>
但自定义的对象,需要通过additionalContext声明结构。
语法校验和转换
语法转换可以使用@babel/standalone,
typescript
import { transform } from '@babel/standalone';
export default function transformCode(code: string): string | undefined | null {
return transform(code, { presets: ['env'] }).code;
}
核心代码如下
scss
const useCodeTransfer = () => {
const [errorInfo, setErrorInfo] = useState('');
const transferCode = useCallback(
(code) => {
try {
if (errorInfo) {
setErrorInfo('');
}
return transfer(code);
} catch (e: any) {
setErrorInfo(e.message);
throw e;
}
},
[errorInfo],
);
return [transferCode, errorInfo, setErrorInfo];
};
转换前:
kotlin
(env) => {
const {app} = env
return null;
}
转换后:
javascript
"use strict";
(function (env) {
var app = env.app;
return null;
});
如果语法有问题,transform会抛出异常: