twing
Version:
First-class Twig engine for Node.js
229 lines (228 loc) • 15.2 kB
JavaScript
"use strict";
/**
* Compare by conforming to PHP loose comparisons rules
*
* @see http://php.net/manual/en/types.comparisons.php
* @see https://stackoverflow.com/questions/47969711/php-algorithm-loose-equality-comparison
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.compare = compare;
const luxon_1 = require("luxon");
const map_like_1 = require("./map-like");
const markup_1 = require("../markup");
const iterator_to_map_1 = require("./iterator-to-map");
function compare(firstOperand, secondOperand) {
// Array<any>
if (Array.isArray(firstOperand)) {
firstOperand = (0, iterator_to_map_1.iteratorToMap)(firstOperand);
}
if (Array.isArray(secondOperand)) {
secondOperand = (0, iterator_to_map_1.iteratorToMap)(secondOperand);
}
// null
if (firstOperand === null) {
return compareToNull(secondOperand);
}
if (secondOperand === null) {
return compareToNull(firstOperand);
}
// boolean
if (typeof firstOperand === 'boolean') {
return compareToBoolean(firstOperand, secondOperand);
}
if (typeof secondOperand === 'boolean') {
return compareToBoolean(secondOperand, firstOperand);
}
// number
if (typeof firstOperand === 'number') {
return compareToNumber(firstOperand, secondOperand);
}
if (typeof secondOperand === 'number') {
return compareToNumber(secondOperand, firstOperand);
}
// TwingMarkup
if ((0, markup_1.isAMarkup)(firstOperand)) {
firstOperand = firstOperand.toString();
}
if ((0, markup_1.isAMarkup)(secondOperand)) {
secondOperand = secondOperand.toString();
}
// Buffer
if (Buffer.isBuffer(firstOperand)) {
firstOperand = firstOperand.toString();
}
if (Buffer.isBuffer(secondOperand)) {
secondOperand = secondOperand.toString();
}
// Map
if ((0, map_like_1.isAMapLike)(firstOperand)) {
return compareToMap(firstOperand, secondOperand);
}
// string
if (typeof firstOperand === 'string') {
return compareToString(firstOperand, secondOperand);
}
// date
if (firstOperand instanceof luxon_1.DateTime) {
return compareToDateTime(firstOperand, secondOperand);
}
// fallback to strict comparison
return firstOperand === secondOperand;
}
/**
* Compare a Map to something else by conforming to PHP loose comparisons rules
* ┌─────────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬─────────┬───────┬───────┐
* │ │ TRUE │ FALSE │ 1 │ 0 │ -1 │ "1" │ "0" │ "-1" │ NULL │ [] │ ["php"] | "php" │ "" │
* ├─────────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼─────────┼───────┼───────┤
* │ [] │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ TRUE │ FALSE │ FALSE │ FALSE |
* │ ["php"] │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE |
* └─────────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴─────────┴───────┴───────┘
*/
function compareToMap(firstOperand, secondOperand) {
if (firstOperand.size === 0) {
return (0, map_like_1.isAMapLike)(secondOperand) && (secondOperand.size === 0);
}
else {
if (!(0, map_like_1.isAMapLike)(secondOperand)) {
return false;
}
else if (firstOperand.size !== secondOperand.size) {
return false;
}
let result = false;
for (let [i, valueItem] of firstOperand) {
let compareItem = secondOperand.get(i);
result = compare(valueItem, compareItem);
if (!result) {
break;
}
}
return result;
}
}
/**
* Compare a boolean to something else by conforming to PHP loose comparisons rules
* ┌─────────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬─────────┬───────┬───────┐
* │ │ TRUE │ FALSE │ 1 │ 0 │ -1 │ "1" │ "0" │ "-1" │ NULL │ array() │ "php" │ "" │
* ├─────────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼─────── ─┼───────┼───────┤
* │ TRUE │ TRUE │ FALSE │ TRUE │ FALSE │ TRUE │ TRUE │ FALSE │ TRUE │ FALSE │ FALSE │ TRUE │ FALSE │
* │ FALSE │ FALSE │ TRUE │ FALSE │ TRUE │ FALSE │ FALSE │ TRUE │ FALSE │ TRUE │ TRUE │ FALSE │ TRUE │
* └─────────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴─────────┴───────┴───────┘
*/
function compareToBoolean(firstOperand, secondOperand) {
if (secondOperand instanceof luxon_1.DateTime) {
return firstOperand === true;
}
if (typeof secondOperand === 'boolean') {
return firstOperand === secondOperand;
}
if (typeof secondOperand === 'number') {
return firstOperand === (secondOperand !== 0);
}
if (typeof secondOperand === 'string') {
if (secondOperand.length > 1) {
return firstOperand;
}
else {
let float = parseFloat(secondOperand);
if (!isNaN(float)) {
return firstOperand === (float !== 0);
}
else {
return firstOperand === (secondOperand.length > 0);
}
}
}
if ((0, map_like_1.isAMapLike)(secondOperand)) {
return firstOperand === secondOperand.size > 0;
}
return firstOperand === true;
}
/**
* Compare a DateTime to something else by conforming to PHP loose comparisons rules
* ┌─────────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬─────────┬───────┬───────┬───────┬───────┐
* │ │ TRUE │ FALSE │ 1 │ 0 │ -1 │ "1" │ "0" │ "-1" │ NULL │ [] │ ["php"] | "php" │ "" │ NOW | LATER |
* ├─────────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼─────────┼───────┼───────┼───────┼───────┤
* │ NOW │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ FALSE │
* │ LATER │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │
* └─────────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴─────────┴───────┴───────┴───────┴───────┘
*/
function compareToDateTime(firstOperand, secondOperand) {
if (secondOperand instanceof luxon_1.DateTime) {
return firstOperand.valueOf() === secondOperand.valueOf();
}
return false;
}
/**
* Compare null to something else by conforming to PHP loose comparisons rules
* ┌─────────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬─────────┬───────┬───────┐
* │ │ TRUE │ FALSE │ 1 │ 0 │ -1 │ "1" │ "0" │ "-1" │ NULL │ [] │ ["php"] | "php" │ "" │
* ├─────────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼─────────┼───────┼───────┤
* │ NULL │ FALSE │ TRUE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ TRUE │ FALSE │ FALSE │ TRUE |
* └─────────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴─────────┴───────┴───────┘
*/
function compareToNull(value) {
if (typeof value === 'boolean') {
return (value === false);
}
if (typeof value === 'number') {
return value === 0;
}
if (typeof value === 'string') {
return value.length < 1;
}
if (value === null) {
return true;
}
if ((0, map_like_1.isAMapLike)(value)) {
return value.size < 1;
}
return false;
}
/**
* Compare a number to something else by conforming to PHP loose comparisons rules
* ┌─────────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬─────────┬───────┬───────┐
* │ │ TRUE │ FALSE │ 1 │ 0 │ -1 │ "1" │ "0" │ "-1" │ NULL │ array() │ "php" │ "" │
* ├─────────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼─────── ─┼───────┼───────┤
* │ 1 │ TRUE │ FALSE │ TRUE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │
* │ 0 │ FALSE │ TRUE │ FALSE │ TRUE │ FALSE │ FALSE │ TRUE │ FALSE │ TRUE │ FALSE │ TRUE │ TRUE │
* │ -1 │ TRUE │ FALSE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │
* └─────────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴─────────┴───────┴───────┘
*/
function compareToNumber(firstOperand, secondOperand) {
if (typeof secondOperand === 'number') {
return firstOperand === secondOperand;
}
if (typeof secondOperand === 'string') {
let float = parseFloat(secondOperand);
if (float) {
return firstOperand === float;
}
else {
return firstOperand === 0;
}
}
// date
if (secondOperand instanceof luxon_1.DateTime) {
return firstOperand === 1;
}
return false;
}
/**
* Compare a string to something else by conforming to PHP loose comparisons rules
* ┌─────────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬─────────┬───────┬───────┐
* │ │ TRUE │ FALSE │ 1 │ 0 │ -1 │ "1" │ "0" │ "-1" │ NULL │ array() │ "php" │ "" │
* ├─────────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼─────── ─┼───────┼───────┤
* │ "1" │ TRUE │ FALSE │ TRUE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │
* │ "0" │ FALSE │ TRUE │ FALSE │ TRUE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │
* │ "-1" │ TRUE │ FALSE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │
* │ "" │ FALSE │ TRUE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ TRUE │
* │ "php" │ TRUE │ FALSE │ FALSE │ TRUE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ FALSE │ TRUE │ FALSE │
* └─────────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴─────────┴───────┴───────┘
*/
function compareToString(firstOperand, secondOperand) {
if (typeof secondOperand === 'string') {
return firstOperand === secondOperand;
}
return false;
}