refactor expression eval

This commit is contained in:
Yanzhen Yu 2021-07-26 16:30:16 +08:00
parent 7db050d812
commit df84613296
2 changed files with 44 additions and 29 deletions

View File

@ -11,7 +11,14 @@ const Button: ComponentImplementation<{
colorScheme?: Static<typeof ColorSchemePropertySchema>;
isLoading?: Static<typeof IsLoadingPropertySchema>;
onClick?: () => void;
}> = ({ text, mergeState, subscribeMethods, onClick, ...rest }) => {
}> = ({
text,
mergeState,
subscribeMethods,
onClick,
colorScheme,
isLoading,
}) => {
const raw = useExpression(text.raw);
useEffect(() => {
mergeState({ value: raw });
@ -28,7 +35,7 @@ const Button: ComponentImplementation<{
return (
<ChakraProvider>
<BaseButton {...rest} ref={ref} onClick={onClick}>
<BaseButton {...{ colorScheme, isLoading }} ref={ref} onClick={onClick}>
<Text value={{ ...text, raw }} />
</BaseButton>
</ChakraProvider>

View File

@ -7,9 +7,41 @@ export const useStore = create<Record<string, any>>(() => ({}));
export const setStore = useStore.setState;
export function parseExpression(raw: string): {
dynamic: boolean;
expression: string;
} {
if (!raw) {
return {
dynamic: false,
expression: raw,
};
}
const matchArr = raw.match(/{{(.+)}}/);
if (!matchArr) {
return {
dynamic: false,
expression: raw,
};
}
return {
dynamic: true,
expression: matchArr[1],
};
}
// TODO: use web worker
export function evalInContext(expression: string, ctx: Record<string, any>) {
export function evalInContext(raw: string, ctx: Record<string, any>) {
try {
const { dynamic, expression } = parseExpression(raw);
if (!dynamic) {
try {
// covert primitive types
return eval(expression);
} catch (error) {
return expression;
}
}
Object.keys(ctx).forEach((key) => {
// @ts-ignore
self[key] = ctx[key];
@ -26,40 +58,16 @@ export function evalInContext(expression: string, ctx: Record<string, any>) {
}
}
export function useExpression(raw: string) {
const { dynamic, expression } = useMemo(() => {
if (!raw) {
return {
dynamic: false,
expression: raw,
};
}
const matchArr = raw.match(/{{(.+)}}/);
if (!matchArr) {
return {
dynamic: false,
expression: raw,
};
}
return {
dynamic: true,
expression: matchArr[1],
};
}, [raw]);
const [state, setState] = useState<any>(
evalInContext(expression, useStore.getState())
evalInContext(raw, useStore.getState())
);
if (!dynamic) {
return state;
}
useStore.subscribe(
(value) => {
setState(value);
},
(state) => {
return evalInContext(expression, state);
return evalInContext(raw, state);
}
);