diff --git a/public/locales/en.json b/public/locales/en.json index fa4521e..da3855e 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -98,6 +98,7 @@ "node.id": "Node id", "node.inputVariable": "Input variables", "node.invalidValue": "Invalid value", + "node.invalidVariableName": "Invalid variable name, should start with a letter or underscore", "node.name": "Node name", "node.noNodeSelected": "No node selected", "node.oneof.error": "Only one is allowed between input '{{input}}' and argument '{{arg}}({{desc}})'", diff --git a/public/locales/zh.json b/public/locales/zh.json index b6c0753..cedcea8 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -98,6 +98,7 @@ "node.id": "节点标识", "node.inputVariable": "输入变量", "node.invalidValue": "无效的值", + "node.invalidVariableName": "变量名必须以字母或下划线开头", "node.name": "节点名称", "node.noNodeSelected": "未选择任务节点", "node.oneof.error": "输入项 “{{input}}” 和参数 “{{arg}}({{desc}})” 之中,只能选择设置其中之一", diff --git a/src/components/inspector.tsx b/src/components/inspector.tsx index 2d61a07..552476c 100644 --- a/src/components/inspector.tsx +++ b/src/components/inspector.tsx @@ -16,6 +16,7 @@ import { getNodeArgRawType, isNodeArgArray, isNodeArgOptional, + isValidVariableName, } from "@/misc/b3util"; import { Hotkey, isMacos } from "@/misc/keys"; import { mergeClassNames } from "@/misc/util"; @@ -436,6 +437,18 @@ const NodeInspector: FC = () => { name={field.name} validateTrigger={["onChange", "onBlur"]} style={{ width: "100%", marginBottom: 5 }} + rules={[ + { + validator(_, value) { + if (value && !isValidVariableName(value)) { + return Promise.reject( + new Error(t("node.invalidVariableName")) + ); + } + return Promise.resolve(); + }, + }, + ]} > { { required, message: t("node.fileRequired", { field: desc }) }, ({ getFieldValue, setFieldValue, isFieldValidating, validateFields }) => ({ validator(_, value) { + if (value && !isValidVariableName(value)) { + return Promise.reject(new Error(t("node.invalidVariableName"))); + } const arg = def.args?.find( (a) => a.oneof && v.replace("?", "") === a.oneof ); @@ -792,6 +808,18 @@ const NodeInspector: FC = () => { name={field.name} validateTrigger={["onChange", "onBlur"]} style={{ width: "100%", marginBottom: 5 }} + rules={[ + { + validator(_, value) { + if (value && !isValidVariableName(value)) { + return Promise.reject( + new Error(t("node.invalidVariableName")) + ); + } + return Promise.resolve(); + }, + }, + ]} > { label={desc} name={`output.${i}`} key={`output.${i}`} - rules={[{ required, message: t("node.fileRequired", { field: desc }) }]} + rules={[ + { required, message: t("node.fileRequired", { field: desc }) }, + { + validator(_, value) { + if (value && !isValidVariableName(value)) { + return Promise.reject(new Error(t("node.invalidVariableName"))); + } + return Promise.resolve(); + }, + }, + ]} > { + return /^[a-zA-Z_]/.test(name); +}; + export const isSubtreeRoot = (data: TreeGraphData) => { return data.path && data.id.toString() !== "1"; }; @@ -229,6 +233,14 @@ export const checkNodeData = (data: NodeModel | null | undefined) => { if (!data.input[i]) { data.input[i] = ""; } + if (data.input[i] && !isValidVariableName(data.input[i])) { + error( + data, + `input field '${data.input[i]}' is not a valid variable name,` + + `should start with a letter or underscore` + ); + hasError = true; + } if (!isValidInputOrOutput(conf.input, data.input, i)) { error(data, `intput field '${conf.input[i]}' is required`); hasError = true; @@ -251,6 +263,14 @@ export const checkNodeData = (data: NodeModel | null | undefined) => { if (!data.output[i]) { data.output[i] = ""; } + if (data.output[i] && !isValidVariableName(data.output[i])) { + error( + data, + `output field '${data.output[i]}' is not a valid variable name,` + + `should start with a letter or underscore` + ); + hasError = true; + } if (!isValidInputOrOutput(conf.output, data.output, i)) { error(data, `output field '${conf.output[i]}' is required`); hasError = true;