integrate tern

This commit is contained in:
Yanzhen Yu 2021-12-06 23:54:25 +08:00
parent f7f604516a
commit 7d34972861
6 changed files with 188 additions and 17 deletions

View File

@ -45,13 +45,15 @@
"mobx": "^6.3.8",
"mobx-react-lite": "^3.2.2",
"react": "^17.0.2",
"react-dom": "^17.0.2"
"react-dom": "^17.0.2",
"tern": "^0.24.3"
},
"devDependencies": {
"@babel/preset-react": "^7.14.5",
"@sunmao-ui/vite-plugins": "^1.0.2",
"@types/codemirror": "^5.60.5",
"@types/lodash-es": "^4.17.5",
"@types/tern": "^0.23.4",
"@vitejs/plugin-react": "^1.0.1",
"@vitejs/plugin-react-refresh": "^1.3.6",
"babel-jest": "^27.2.1",

View File

@ -0,0 +1,84 @@
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/ayu-mirage.css';
// tern
import 'codemirror/addon/tern/tern';
import 'tern/plugin/doc_comment';
import 'tern/plugin/complete_strings';
import ecma from 'tern/defs/ecmascript.json';
import { Def } from 'tern';
function installTern(cm: CodeMirror.Editor) {
const tern = new CodeMirror.TernServer({ defs: [ecma as unknown as Def] });
cm.on('cursorActivity', cm => tern.updateArgHints(cm));
cm.on('change', (_instance, change) => {
if (change.text.length === 1 && change.text[0] === '.') {
tern.complete(cm);
}
});
return tern;
}
export const TernEditor: React.FC<{
defaultCode: string;
onChange?: (v: string) => void;
onBlur?: (v: string) => void;
lineNumbers?: boolean;
}> = ({ defaultCode, onChange, onBlur, lineNumbers = true }) => {
const style = css`
.CodeMirror {
width: 100%;
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: defaultCode,
mode: {
name: 'javascript',
json: true,
},
foldGutter: true,
lineWrapping: true,
lineNumbers,
gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
foldOptions: {
widget: () => {
return '\u002E\u002E\u002E';
},
},
theme: 'ayu-mirage',
viewportMargin: Infinity,
});
installTern(cm.current);
}
const changeHandler = (instance: CodeMirror.Editor) => {
onChange?.(instance.getValue());
};
const blurHandler = (instance: CodeMirror.Editor) => {
onBlur?.(instance.getValue());
};
cm.current.on('change', changeHandler);
cm.current.on('blur', blurHandler);
return () => {
cm.current?.off('change', changeHandler);
cm.current?.off('blur', blurHandler);
};
}, [defaultCode]);
return <Box css={style} ref={wrapperEl} height="100%" width="100%"></Box>;
};

View File

@ -1,3 +1,4 @@
export * from './StateEditor';
export * from './SchemaEditor';
export * from './CssEditor';
export * from './TernEditor';

View File

@ -1,6 +1,6 @@
import React from 'react';
import { FieldProps } from '../fields';
import { SchemaEditor } from 'components/CodeEditor';
import { TernEditor } from 'components/CodeEditor';
type Props = FieldProps;
@ -8,7 +8,7 @@ const GeneralWidget: React.FC<Props> = props => {
const { formData, onChange } = props;
return (
<SchemaEditor
<TernEditor
defaultCode={String(formData)}
lineNumbers={false}
onBlur={v => {

View File

@ -32,25 +32,32 @@ export const StyleTraitForm: React.FC<Props> = props => {
</Box>
{styleSlots.map(styleSlot => {
const styleTrait = styles.find(s => s.properties.styleSlot === styleSlot);
if (!styleTrait) {
return null;
}
const defaultCode = (styleTrait?.properties?.style as string) || '';
return (
<FormControl id={styleSlot} key={styleSlot}>
<FormLabel>{styleSlot}</FormLabel>
<CssEditor
defaultCode={styleTrait.properties.style as string}
defaultCode={defaultCode}
onBlur={v =>
eventBus.send(
'operation',
genOperation('modifyTraitProperty', {
componentId: component.id,
traitIndex: component.traits.indexOf(styleTrait),
properties: {
styleSlot,
style: v,
},
})
styleTrait
? genOperation('modifyTraitProperty', {
componentId: component.id,
traitIndex: component.traits.indexOf(styleTrait),
properties: {
styleSlot,
style: v,
},
})
: genOperation('createTrait', {
componentId: component.id,
traitType: 'core/v1/style',
properties: {
styleSlot,
style: v,
},
})
)
}
/>

View File

@ -3122,6 +3122,13 @@
dependencies:
"@types/estree" "*"
"@types/tern@^0.23.4":
version "0.23.4"
resolved "http://192.168.26.29:7001/@types/tern/download/@types/tern-0.23.4.tgz#03926eb13dbeaf3ae0d390caf706b2643a0127fb"
integrity sha1-A5JusT2+rzrg05DK9wayZDoBJ/s=
dependencies:
"@types/estree" "*"
"@types/unist@*", "@types/unist@^2.0.0":
version "2.0.6"
resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d"
@ -3289,11 +3296,28 @@ acorn-jsx@^5.3.1:
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
acorn-loose@^6.0.0:
version "6.1.0"
resolved "http://192.168.26.29:7001/acorn-loose/download/acorn-loose-6.1.0.tgz#3b2de5b3fc64f811c7b6c07cd9128d1476817f94"
integrity sha1-Oy3ls/xk+BHHtsB82RKNFHaBf5Q=
dependencies:
acorn "^6.2.0"
acorn-walk@^6.0.0:
version "6.2.0"
resolved "http://192.168.26.29:7001/acorn-walk/download/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c"
integrity sha1-Ejy487hMIXHx9/slJhWxx4prGow=
acorn-walk@^7.1.1:
version "7.2.0"
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc"
integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==
acorn@^6.0.0, acorn@^6.2.0:
version "6.4.2"
resolved "http://192.168.26.29:7001/acorn/download/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6"
integrity sha1-NYZv1xBSjpLeEM8GAWSY5H454eY=
acorn@^7.1.1, acorn@^7.4.0:
version "7.4.1"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
@ -4505,6 +4529,16 @@ encoding@^0.1.12:
dependencies:
iconv-lite "^0.6.2"
enhanced-resolve@^2.2.2:
version "2.3.0"
resolved "http://192.168.26.29:7001/enhanced-resolve/download/enhanced-resolve-2.3.0.tgz#a115c32504b6302e85a76269d7a57ccdd962e359"
integrity sha1-oRXDJQS2MC6Fp2Jp16V8zdli41k=
dependencies:
graceful-fs "^4.1.2"
memory-fs "^0.3.0"
object-assign "^4.0.1"
tapable "^0.2.3"
enquirer@^2.3.5, enquirer@^2.3.6:
version "2.3.6"
resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d"
@ -4527,6 +4561,13 @@ err-code@^2.0.2:
resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9"
integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==
errno@^0.1.3:
version "0.1.8"
resolved "http://192.168.26.29:7001/errno/download/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f"
integrity sha1-i7Ppx9Rjvkl2/4iPdrSAnrwugR8=
dependencies:
prr "~1.0.1"
error-ex@^1.3.1:
version "1.3.2"
resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
@ -6915,6 +6956,14 @@ memoize-one@^5.0.0:
resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e"
integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==
memory-fs@^0.3.0:
version "0.3.0"
resolved "http://192.168.26.29:7001/memory-fs/download/memory-fs-0.3.0.tgz#7bcc6b629e3a43e871d7e29aca6ae8a7f15cbb20"
integrity sha1-e8xrYp46Q+hx1+Kaymrop/FcuyA=
dependencies:
errno "^0.1.3"
readable-stream "^2.0.1"
meow@^8.0.0:
version "8.1.2"
resolved "https://registry.yarnpkg.com/meow/-/meow-8.1.2.tgz#bcbe45bda0ee1729d350c03cffc8395a36c4e897"
@ -7167,7 +7216,7 @@ min-indent@^1.0.0:
resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869"
integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==
minimatch@^3.0.4:
minimatch@^3.0.3, minimatch@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
@ -8109,6 +8158,11 @@ protocols@^1.1.0, protocols@^1.4.0:
resolved "https://registry.yarnpkg.com/protocols/-/protocols-1.4.8.tgz#48eea2d8f58d9644a4a32caae5d5db290a075ce8"
integrity sha512-IgjKyaUSjsROSO8/D49Ab7hP8mJgTYcqApOqdPhLoPxAplXmkp+zRvsrSQjFn5by0rhm4VH0GAUELIPpx7B1yg==
prr@~1.0.1:
version "1.0.1"
resolved "http://192.168.26.29:7001/prr/download/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY=
psl@^1.1.28, psl@^1.1.33:
version "1.8.0"
resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24"
@ -8441,7 +8495,7 @@ readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.0.2:
string_decoder "^1.1.1"
util-deprecate "^1.0.1"
readable-stream@^2.0.6, readable-stream@~2.3.6:
readable-stream@^2.0.1, readable-stream@^2.0.6, readable-stream@~2.3.6:
version "2.3.7"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
@ -8617,6 +8671,11 @@ resolve-cwd@^3.0.0:
dependencies:
resolve-from "^5.0.0"
resolve-from@2.0.0:
version "2.0.0"
resolved "http://192.168.26.29:7001/resolve-from/download/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57"
integrity sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=
resolve-from@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
@ -9215,6 +9274,11 @@ table@^6.0.9:
string-width "^4.2.3"
strip-ansi "^6.0.1"
tapable@^0.2.3:
version "0.2.9"
resolved "http://192.168.26.29:7001/tapable/download/tapable-0.2.9.tgz#af2d8bbc9b04f74ee17af2b4d9048f807acd18a8"
integrity sha1-ry2LvJsE907hevK02QSPgHrNGKg=
tar@^4.4.12:
version "4.4.19"
resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.19.tgz#2e4d7263df26f2b914dee10c825ab132123742f3"
@ -9264,6 +9328,19 @@ terminal-link@^2.0.0:
ansi-escapes "^4.2.1"
supports-hyperlinks "^2.0.0"
tern@^0.24.3:
version "0.24.3"
resolved "http://192.168.26.29:7001/tern/download/tern-0.24.3.tgz#da0d9118490c15af4b1c94553d5f0fafc77a0977"
integrity sha1-2g2RGEkMFa9LHJRVPV8Pr8d6CXc=
dependencies:
acorn "^6.0.0"
acorn-loose "^6.0.0"
acorn-walk "^6.0.0"
enhanced-resolve "^2.2.2"
glob "^7.1.1"
minimatch "^3.0.3"
resolve-from "2.0.0"
test-exclude@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e"