devexpress-richedit
Version:
DevExpress Rich Text Editor is an advanced word-processing tool designed for working with rich text documents.
149 lines (148 loc) • 5.8 kB
JavaScript
import { FieldName } from '../names';
import { FieldCodeParserClientUpdatingBase } from './field-code-parser-client-updating-base';
export class FieldCodeParserIf extends FieldCodeParserClientUpdatingBase {
get name() { return FieldName.If; }
fillResult() {
this.setInputPositionState();
let result = null;
try {
result = this.getResult();
}
catch (err) {
if (err instanceof IfExpressionError) {
result = err.message;
}
}
finally {
if (result) {
this.replaceTextByInterval(this.getTopField().getResultInterval(), result);
}
return true;
}
}
getResult() {
const expression = this.parseParameters(this.parameterInfoList);
return expression.evaluate();
}
parseParameters(parameters) {
if (parameters.length > 5)
throw new IfExpressionTooManyParametersError();
if (parameters.length === 0)
throw new IfExpressionMissingParametersError();
let leftExpression;
let operator;
let rightExpression;
let trueText;
let falseText;
if (parameters.length <= 3 && !IfExpression.isOperator(parameters[1]?.text)) {
leftExpression = new IfExpressionParameter(parameters[0]?.text, parameters[0]?.quoted);
trueText = parameters[1]?.text;
falseText = parameters[2]?.text;
}
else {
leftExpression = new IfExpressionParameter(parameters[0]?.text, parameters[0]?.quoted);
operator = parameters[1]?.text;
rightExpression = new IfExpressionParameter(parameters[2]?.text, parameters[2]?.quoted);
trueText = parameters[3]?.text;
falseText = parameters[4]?.text;
}
return new IfExpression(operator, leftExpression, rightExpression, trueText, falseText);
}
}
export class IfExpression {
operator;
leftExpression;
rightExpression;
trueText;
falseText;
static operators = ["<", ">", "=", "<=", ">=", "<>"];
constructor(operator, leftExpression, rightExpression, trueText = undefined, falseText = undefined) {
this.operator = operator;
this.leftExpression = leftExpression;
this.rightExpression = rightExpression;
this.trueText = trueText;
this.falseText = falseText;
}
static isOperator(operator) {
return IfExpression.operators.includes(operator);
}
evaluate() {
if (!this.operator && !this.leftExpression.isNumber) {
return this.leftExpression.text ? this.trueText : this.falseText;
}
if (!IfExpression.isOperator(this.operator)) {
throw new IfExpressionInvalidOperatorError();
}
let difference;
if (this.leftExpression.isNumber && this.rightExpression.isNumber) {
difference = this.leftExpression.number - this.rightExpression.number;
}
else {
const isEqualityOperator = this.operator === "=" || this.operator === "<>";
const compareFunction = isEqualityOperator ? IfExpression.compareStringsWithWildcards : IfExpression.compareStrings;
difference = compareFunction(this.leftExpression.text, this.rightExpression.text);
}
return this.evaluateComparison(difference) ? this.trueText : this.falseText;
}
evaluateComparison(comparisonResult) {
switch (this.operator) {
case "<":
return comparisonResult < 0;
case ">":
return comparisonResult > 0;
case "=":
return comparisonResult === 0;
case "<=":
return comparisonResult <= 0;
case ">=":
return comparisonResult >= 0;
case "<>":
return comparisonResult != 0;
default:
return false;
}
}
static compareStrings(leftValue, rightValue) {
return leftValue.localeCompare(rightValue);
}
static compareStringsWithWildcards(leftValue, rightValue) {
const escapedPattern = rightValue.replace(/[.+^${}()|[\]\\]/g, "\\$&");
const regexPattern = escapedPattern.replace(/\*/g, '.*').replace(/\?/g, '.');
const regex = new RegExp(`^${regexPattern}$`);
return regex.test(leftValue) ? 0 : 1;
}
}
export class IfExpressionParameter {
text;
number;
isNumber;
constructor(text, isQuoted = false) {
this.text = text;
this.number = parseFloat(text);
this.isNumber = !isQuoted && !Number.isNaN(this.number);
}
}
export class IfExpressionError extends Error {
constructor(message) {
super(message);
Object.setPrototypeOf(this, IfExpressionError.prototype);
}
}
export class IfExpressionInvalidOperatorError extends IfExpressionError {
constructor(message) {
super(message ?? "IF field error: Invalid comparison operator");
Object.setPrototypeOf(this, IfExpressionInvalidOperatorError.prototype);
}
}
export class IfExpressionTooManyParametersError extends IfExpressionError {
constructor(message) {
super(message ?? "IF field error: Too many parameters");
Object.setPrototypeOf(this, IfExpressionTooManyParametersError.prototype);
}
}
export class IfExpressionMissingParametersError extends IfExpressionError {
constructor(message) {
super(message ?? "IF field error: Missing parameter(s)");
Object.setPrototypeOf(this, IfExpressionMissingParametersError.prototype);
}
}