Background: The company launched a module in the middle platform, adding online code in the quick form building module. After saving the online editing code, you can view the effect on the corresponding page. After getting the requirements, I went to a project like CodePen. It was too difficult. It was a headache. Think of babel-standalone, an online compiled library that implements react components, ES6 code, and ES5 to support modern browsers. The implementation needs two parts: 1. Code editor: this website is more, I prefer vscode. 2. Parse code. Github and the createElement method of the NPM component. Finally, an object is returned. The object contains the transformCode and React component node.
import { transform as BabelTransform } from 'babel-standalone';
const getCodeFunc = (code: string, scope: { [key: string]: any }) = > {
const keys = Object.keys(scope);
const values = keys.map((key) = > scope[key]);
const res = new Function(... keys, code);returnres(... values); };const transform = (code: string) = > {
const text: string = ` () = > {${code}
}
`;
const option = {
presets: ['es2015'.'react'.'stage-1']};let transformCode = BabelTransform(text, option).code;
// Filter the transformed code
return transformCode
.replace(/(\(function \(\) \{)[\r\n]/.' ')
.replace(/ \} \ \; $/.' ');
};
/** * ES6 code is converted to ES5 */
interface transformReturns {transformCode: string; node:ReactNode; }; type FuncType =(code: string, scope: { [key: string]: any }) = > transformReturns;
/ / code code
// the scope function supports modules in its scope, such as passing React
export const createElement: FuncType = (code = ' ', scope = {}) = > {
const transformCode = transform(code.trim().replace(/; $/.' '));
return { transformCode, node: getCodeFunc(transformCode, scope) };
};
Copy the code
You can use the createElement method on the page to get the component and render it, while catching an error message in the code.
import React from 'react';
import { useMemo } from 'react';
const CodeNode = ({ code, scope={} }) = > {
const TransformNode = useMemo(() = > {
let currNode:any = null;
try {
let { transformCode, node } = createElement(code, scope);
currNode = node;
} catch (error) {
currNode = error.toString();
}
return currNode;
}, [code]);
if(! TransformNode)return null;
// Output information when an error is reported
if(typeof TransformNode === 'string') return TransformNode;
// Render component
return <TransformNode />
}
export default() = > {// Code string
const code = `() => { const {text, setText} = React.useState(''); React.useEffect(() => { setText('hello world'); } []); return
{text}
}`;
/ / scope
const scope = { React };
return <CodeNode code={code} scope={scope} />;
}
Copy the code
Existing disadvantages:
- Only modules that are available within a prepassed function are supported.
- Only inline styles are supported.
Such as leisure down to reform, pondering what a good way to solve the problem of the module.