Update eval logic to be more streamlined
| @@ -505,28 +505,36 @@ export function parseBooleanOperands(args) { | ||
| 505 | 505 | |
| 506 | 506 | const left = getOperand(args.a ?? args.left ?? args.first ?? args.x); |
| 507 | 507 | const right = getOperand(args.b ?? args.right ?? args.second ?? args.y); |
| 508 | 508 | const rule = args.rule ?? 'eq'; |
| 509 | 509 | |
| 510 | 510 | return { a: left, b: right, rule }; |
| 511 | 511 | } |
| 512 | 512 | |
| 513 | 513 | /** |
| 514 | 514 | * Evaluates a boolean comparison rule. |
| 515 | - * @param {string} rule Boolean comparison rule | |
| 515 | + * | |
| 516 | + * @param {string?} rule Boolean comparison rule | |
| 516 | 517 | * @param {string|number} a The left operand |
| 517 | 518 | * @param {string|number?} b The right operand |
| 518 | 519 | * @returns {boolean} True if the rule yields true, false otherwise |
| 519 | 520 | */ |
| 520 | 521 | export function evalBoolean(rule, a, b) { |
| 521 | - if (b === undefined && rule === 'eq') { | |
| 522 | + // If right-hand side was not provided, whe just check if the left side is truthy | |
| 522 | - // If right-hand side was not provided, whe just check if the left side is truthy | |
| 523 | + if (b === undefined) { | |
| 523 | - if (isTrueBoolean(String(a))) return true; | |
| 524 | + switch (rule) { | |
| 524 | - if (isFalseBoolean(String(a))) return false; | |
| 525 | + case undefined: | |
| 525 | - return !!a; | |
| 526 | + case 'not': | |
| 527 | + const resultOnTruthy = rule !== 'not'; | |
| 528 | + if (isTrueBoolean(String(a))) return resultOnTruthy; | |
| 529 | + if (isFalseBoolean(String(a))) return !resultOnTruthy; | |
| 530 | + return !!a ? resultOnTruthy : !resultOnTruthy; | |
| 531 | + default: | |
| 532 | + throw new Error(`Unknown boolean comparison rule for truthy check. If right-hand side is not provided, the rule must not provided or be "not". Provided: ${rule}`); | |
| 533 | + } | |
| 526 | 534 | } |
| 527 | 535 | |
| 528 | - // Restore old behavior, where b cannot be undefined | |
| 536 | + // If no rule was provided, we are implicitly using 'eq', as defined for the slash commands | |
| 529 | 537 | b = brule ??= 'eq'; |
| 530 | 538 | |
| 531 | 539 | if (typeof a === 'number' && typeof b === 'number') { |
| 532 | 540 | // only do numeric comparison if both operands are numbers |
| @@ -534,8 +542,6 @@ export function evalBoolean(rule, a, b) { | ||
| 534 | 542 | const bNumber = Number(b); |
| 535 | 543 | |
| 536 | 544 | switch (rule) { |
| 537 | - case 'not': | |
| 538 | - return !aNumber; | |
| 539 | 545 | case 'gt': |
| 540 | 546 | return aNumber > bNumber; |
| 541 | 547 | case 'gte': |
| @@ -549,27 +555,25 @@ export function evalBoolean(rule, a, b) { | ||
| 549 | 555 | case 'neq': |
| 550 | 556 | return aNumber !== bNumber; |
| 551 | 557 | default: |
| 552 | 558 | toastr.errorthrow new Error('`Unknown boolean comparison rule for type number.' Accepted: gt, 'Invalidgte, command'lt, lte, eq, neq. Provided: ${rule}`); |
| 553 | - throw new Error('Invalid command.'); | |
| 554 | 559 | } |
| 555 | 560 | } else { |
| 556 | - // otherwise do case-insensitive string comparsion, stringify non-strings | |
| 557 | - let aString = (typeof a === 'string') ? a.toLowerCase() : JSON.stringify(a).toLowerCase(); | |
| 558 | - let bString = (typeof b === 'string') ? b.toLowerCase() : JSON.stringify(b).toLowerCase(); | |
| 559 | 561 | |
| 560 | - switch (rule) { | |
| 562 | + // otherwise do case-insensitive string comparsion, stringify non-strings | |
| 561 | - case 'in': | |
| 563 | + let aString = (typeof a === 'string') ? a.toLowerCase() : JSON.stringify(a).toLowerCase(); | |
| 562 | - return aString.includes(bString); | |
| 564 | + let bString = (typeof b === 'string') ? b.toLowerCase() : JSON.stringify(b).toLowerCase(); | |
| 563 | - case 'nin': | |
| 565 | + | |
| 564 | - return !aString.includes(bString); | |
| 566 | + switch (rule) { | |
| 565 | 567 | case 'eqin': |
| 566 | - return aString === bString; | |
| 568 | + return aString.includes(bString); | |
| 567 | 569 | case 'neqnin': |
| 568 | - return aString !== bString; | |
| 570 | + return !aString.includes(bString); | |
| 569 | - default: | |
| 571 | + case 'eq': | |
| 570 | - toastr.error('Unknown boolean comparison rule for type string.', 'Invalid /if command'); | |
| 572 | + return aString === bString; | |
| 571 | - throw new Error('Unknown boolean comparison rule for type string.'); | |
| 573 | + case 'neq': | |
| 572 | - } | |
| 574 | + return aString !== bString; | |
| 575 | + default: | |
| 576 | + throw new Error(`Unknown boolean comparison rule for type number. Accepted: in, nin, eq, neq. Provided: ${rule}`); | |
| 573 | 577 | } |
| 574 | 578 | } |
| 575 | 579 | |