UNPKG

@starzhuimeng/formula-editor

Version:

A configurable formula editor with customizable symbols

182 lines 6.78 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.FormulaValidator = void 0; const types_1 = require("../types"); /** * 公式验证器 */ class FormulaValidator { /** * 验证公式 * @param formula 公式字符串 * @param elements 公式元素 * @param rules 验证规则 * @returns 验证结果 */ static validate(formula, elements, rules) { const errors = []; // 应用所有规则 for (const rule of rules) { const validationError = this.applyRule(formula, elements, rule); if (validationError) { errors.push(validationError); } } return { valid: errors.length === 0, errors }; } /** * 应用单个验证规则 * @param formula 公式字符串 * @param elements 公式元素 * @param rule 验证规则 * @returns 验证错误,如果验证通过则返回undefined */ static applyRule(formula, elements, rule) { // 自定义验证函数 if (rule.type === types_1.ValidationRuleType.CUSTOM && rule.validate) { if (!rule.validate(formula, elements)) { return { message: rule.message || '验证失败', ruleType: rule.type }; } return undefined; } // 内置规则 let isValid = true; let elementIndex = undefined; switch (rule.type) { case types_1.ValidationRuleType.BRACKETS_MATCH: const bracketResult = this.validateBracketsMatch(formula); isValid = bracketResult.isValid; elementIndex = bracketResult.elementIndex; break; case types_1.ValidationRuleType.OPERATORS_SURROUNDED: const operatorResult = this.validateOperatorsSurrounded(elements); isValid = operatorResult.isValid; elementIndex = operatorResult.elementIndex; break; case types_1.ValidationRuleType.NON_EMPTY: isValid = formula.trim().length > 0; break; case types_1.ValidationRuleType.HAS_EQUALS: isValid = formula.includes('='); break; case types_1.ValidationRuleType.NO_CONSECUTIVE_OPERANDS: const consecutiveResult = this.validateNoConsecutiveOperands(elements); isValid = consecutiveResult.isValid; elementIndex = consecutiveResult.elementIndex; break; } if (!isValid) { return { message: rule.message || this.getDefaultMessage(rule.type), ruleType: rule.type, elementIndex }; } return undefined; } /** * 验证括号匹配 */ static validateBracketsMatch(formula) { const stack = []; const brackets = { '(': ')', '[': ']', '{': '}' }; for (let i = 0; i < formula.length; i++) { const char = formula[i]; // 左括号压栈 if (char === '(' || char === '[' || char === '{') { stack.push({ char, index: i }); } // 右括号出栈 else if (char === ')' || char === ']' || char === '}') { if (stack.length === 0) { return { isValid: false, elementIndex: i }; } const lastBracket = stack.pop(); if (!lastBracket || brackets[lastBracket.char] !== char) { return { isValid: false, elementIndex: i }; } } } // 如果栈不为空,说明有未匹配的左括号 if (stack.length > 0) { return { isValid: false, elementIndex: stack[0].index }; } return { isValid: true }; } /** * 验证操作符周围必须有操作数 */ static validateOperatorsSurrounded(elements) { for (let i = 0; i < elements.length; i++) { const element = elements[i]; if (element.type === 'operator' && element.value !== '=' && element.value !== '±') { // 检查前后是否有操作数 const hasPrev = i > 0 && this.isOperand(elements[i - 1]); const hasNext = i < elements.length - 1 && this.isOperand(elements[i + 1]); // 如果是一元操作符(如负号),只需检查后面有操作数 const isUnary = element.value === '-' || element.value === '+'; if ((!isUnary && (!hasPrev || !hasNext)) || (isUnary && !hasNext)) { return { isValid: false, elementIndex: i }; } } } return { isValid: true }; } /** * 判断元素是否为操作数(数字、变量等) */ static isOperand(element) { return element.type === 'number' || element.type === 'variable' || element.type === 'function' || element.type === 'bracket'; } /** * 验证操作数不能连续 */ static validateNoConsecutiveOperands(elements) { for (let i = 1; i < elements.length; i++) { const currentElement = elements[i]; const prevElement = elements[i - 1]; // 如果当前元素和前一个元素都是操作数(数字、变量) if (this.isOperand(currentElement) && this.isOperand(prevElement)) { return { isValid: false, elementIndex: i }; } } return { isValid: true }; } /** * 获取默认错误消息 */ static getDefaultMessage(ruleType) { switch (ruleType) { case types_1.ValidationRuleType.BRACKETS_MATCH: return '括号不匹配'; case types_1.ValidationRuleType.OPERATORS_SURROUNDED: return '操作符两侧必须有操作数'; case types_1.ValidationRuleType.NON_EMPTY: return '公式不能为空'; case types_1.ValidationRuleType.HAS_EQUALS: return '公式必须包含等号'; case types_1.ValidationRuleType.NO_CONSECUTIVE_OPERANDS: return '操作数不能连续出现,需要用运算符连接'; case types_1.ValidationRuleType.CUSTOM: return '自定义验证失败'; default: return '验证失败'; } } } exports.FormulaValidator = FormulaValidator; //# sourceMappingURL=validator.js.map