introduce CodeMirror to implement code editors

This commit is contained in:
Yanzhen Yu 2021-10-19 00:14:44 +08:00
parent 54fbe286ed
commit 3be10c22a7
6 changed files with 80 additions and 3 deletions

View File

@ -5,7 +5,7 @@
"singleQuote": true, "singleQuote": true,
"trailingComma": "es5", "trailingComma": "es5",
"bracketSpacing": true, "bracketSpacing": true,
"jsxBracketSameLine": true, "jsxBracketSameLine": false,
"arrowParens": "avoid", "arrowParens": "avoid",
"endOfLine": "lf", "endOfLine": "lf",
"printWidth": 90 "printWidth": 90

View File

@ -28,6 +28,7 @@
"@meta-ui/core": "^0.1.0", "@meta-ui/core": "^0.1.0",
"@meta-ui/runtime": "^0.0.0", "@meta-ui/runtime": "^0.0.0",
"@sinclair/typebox": "^0.20.5", "@sinclair/typebox": "^0.20.5",
"codemirror": "^5.63.3",
"framer-motion": "^4", "framer-motion": "^4",
"immer": "^9.0.6", "immer": "^9.0.6",
"lodash": "^4.17.21", "lodash": "^4.17.21",
@ -36,6 +37,7 @@
}, },
"devDependencies": { "devDependencies": {
"@babel/preset-react": "^7.14.5", "@babel/preset-react": "^7.14.5",
"@types/codemirror": "^5.60.5",
"@vitejs/plugin-react": "^1.0.1", "@vitejs/plugin-react": "^1.0.1",
"@vitejs/plugin-react-refresh": "^1.3.6", "@vitejs/plugin-react-refresh": "^1.3.6",
"babel-jest": "^27.2.1", "babel-jest": "^27.2.1",

View File

@ -0,0 +1,48 @@
import React, { useEffect, useRef } from 'react';
import CodeMirror from 'codemirror';
import { Box } from '@chakra-ui/react';
import { css } from '@emotion/react';
import 'codemirror/mode/javascript/javascript';
import 'codemirror/addon/fold/brace-fold';
import 'codemirror/addon/fold/foldgutter';
import 'codemirror/addon/fold/foldgutter.css';
import 'codemirror/lib/codemirror.css';
import 'codemirror/theme/duotone-dark.css';
export const StateEditor: React.FC<{ code: string }> = ({ code }) => {
const style = css`
.CodeMirror {
height: 100%;
}
`;
const wrapperEl = useRef<HTMLDivElement>(null);
const cm = useRef<CodeMirror.Editor | null>(null);
useEffect(() => {
if (!wrapperEl.current) {
return;
}
if (!cm.current) {
cm.current = CodeMirror(wrapperEl.current, {
value: code,
mode: {
name: 'javascript',
json: true,
},
foldGutter: true,
lineWrapping: true,
lineNumbers: true,
gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
foldOptions: {
widget: () => {
return '\u002E\u002E\u002E';
},
},
});
} else {
cm.current.setValue(code);
}
}, [code]);
return <Box css={style} ref={wrapperEl} height="100%"></Box>;
};

View File

@ -0,0 +1 @@
export * from './StateEditor';

View File

@ -16,6 +16,7 @@ import { EditorHeader } from './EditorHeader';
import { PreviewModal } from './PreviewModal'; import { PreviewModal } from './PreviewModal';
import { KeyboardEventWrapper } from './KeyboardEventWrapper'; import { KeyboardEventWrapper } from './KeyboardEventWrapper';
import { ComponentWrapper } from './ComponentWrapper'; import { ComponentWrapper } from './ComponentWrapper';
import { StateEditor } from './CodeEditor';
export const Editor = () => { export const Editor = () => {
const [selectedComponentId, setSelectedComponentId] = useState(''); const [selectedComponentId, setSelectedComponentId] = useState('');
@ -89,6 +90,7 @@ export const Editor = () => {
display="flex" display="flex"
flexDirection="column" flexDirection="column"
textAlign="left" textAlign="left"
isLazy
> >
<TabList background="gray.50"> <TabList background="gray.50">
<Tab>UI Tree</Tab> <Tab>UI Tree</Tab>
@ -102,8 +104,8 @@ export const Editor = () => {
onSelectComponent={id => setSelectedComponentId(id)} onSelectComponent={id => setSelectedComponentId(id)}
/> />
</TabPanel> </TabPanel>
<TabPanel p={0}> <TabPanel p={0} height="100%">
<pre>{JSON.stringify(stateStore, null, 2)}</pre> <StateEditor code={JSON.stringify(stateStore, null, 2)} />
</TabPanel> </TabPanel>
</TabPanels> </TabPanels>
</Tabs> </Tabs>

View File

@ -2893,6 +2893,18 @@
dependencies: dependencies:
"@babel/types" "^7.3.0" "@babel/types" "^7.3.0"
"@types/codemirror@^5.60.5":
version "5.60.5"
resolved "https://registry.yarnpkg.com/@types/codemirror/-/codemirror-5.60.5.tgz#5b989a3b4bbe657458cf372c92b6bfda6061a2b7"
integrity sha512-TiECZmm8St5YxjFUp64LK0c8WU5bxMDt9YaAek1UqUb9swrSCoJhh92fWu1p3mTEqlHjhB5sY7OFBhWroJXZVg==
dependencies:
"@types/tern" "*"
"@types/estree@*":
version "0.0.50"
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.50.tgz#1e0caa9364d3fccd2931c3ed96fdbeaa5d4cca83"
integrity sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==
"@types/graceful-fs@^4.1.2": "@types/graceful-fs@^4.1.2":
version "4.1.5" version "4.1.5"
resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15" resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15"
@ -3031,6 +3043,13 @@
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c"
integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==
"@types/tern@*":
version "0.23.4"
resolved "https://registry.yarnpkg.com/@types/tern/-/tern-0.23.4.tgz#03926eb13dbeaf3ae0d390caf706b2643a0127fb"
integrity sha512-JAUw1iXGO1qaWwEOzxTKJZ/5JxVeON9kvGZ/osgZaJImBnyjyn0cjovPsf6FNLmyGY8Vw9DoXZCMlfMkMwHRWg==
dependencies:
"@types/estree" "*"
"@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2", "@types/unist@^2.0.3": "@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2", "@types/unist@^2.0.3":
version "2.0.6" version "2.0.6"
resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d" resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d"
@ -3839,6 +3858,11 @@ code-point-at@^1.0.0:
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
codemirror@^5.63.3:
version "5.63.3"
resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.63.3.tgz#97042a242027fe0c87c09b36bc01931d37b76527"
integrity sha512-1C+LELr+5grgJYqwZKqxrcbPsHFHapVaVAloBsFBASbpLnQqLw1U8yXJ3gT5D+rhxIiSpo+kTqN+hQ+9ialIXw==
collect-v8-coverage@^1.0.0: collect-v8-coverage@^1.0.0:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59"