edgerender-yatl
Version:
Yet Another Template Language
130 lines • 4.56 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.str2stream = exports.remove_undefined = exports.smart_equals = exports.is_object = exports.has_property = exports.smart_typeof = exports.SmartType = exports.is_upper_case = exports.shouldnt_happen = void 0;
function shouldnt_happen(type) {
throw Error(`Internal Error: got unexpected type ${JSON.stringify(type)}`);
}
exports.shouldnt_happen = shouldnt_happen;
const is_upper_case = (name) => name == name.toUpperCase();
exports.is_upper_case = is_upper_case;
var SmartType;
(function (SmartType) {
SmartType["Null"] = "null";
SmartType["Undefined"] = "undefined";
SmartType["Number"] = "number";
SmartType["Boolean"] = "boolean";
SmartType["Date"] = "date";
SmartType["Regexp"] = "regexp";
SmartType["String"] = "string";
SmartType["Array"] = "array";
SmartType["Object"] = "object";
SmartType["Function"] = "function";
})(SmartType = exports.SmartType || (exports.SmartType = {}));
const smart_typeof = (obj) => {
/**
* Helper to get the type of objects, works even for primitives, see
* https://stackoverflow.com/questions/30476150/javascript-deep-comparison-recursively-objects-and-properties
*/
return Object.prototype.toString
.call(obj)
.replace(/\[object (.+)]/, '$1')
.toLowerCase();
};
exports.smart_typeof = smart_typeof;
const has_property = (obj, key) => Object.prototype.hasOwnProperty.call(obj, key);
exports.has_property = has_property;
const is_object = (v) => exports.smart_typeof(v) == SmartType.Object;
exports.is_object = is_object;
function smart_equals(a, b) {
/**
* Recursively check if two objects are equal
*/
// If a and b reference the same value, return true
if (a === b) {
return true;
}
// If a and b aren't the same type, return false
if (typeof a != typeof b) {
return false;
}
// Already know types are the same, so if type is number
// and both NaN, return true
if (typeof a == 'number' && isNaN(a) && isNaN(b)) {
return true;
}
const a_type = exports.smart_typeof(a);
const b_type = exports.smart_typeof(b);
// Return false if not same class
if (a_type != b_type) {
return false;
}
if (a_type == SmartType.Undefined || a_type == SmartType.Null) {
return a_type == b_type;
}
// If they're Boolean, String or Number objects, check values
if (a_type == SmartType.Boolean || a_type == SmartType.String || a_type == SmartType.Number) {
return a.valueOf() == b.valueOf();
}
if (a_type == SmartType.Date || a_type == SmartType.Regexp || a_type == SmartType.Function) {
return a.toString() == b.toString();
}
if (a_type == SmartType.Object) {
const a_obj = a;
const b_obj = b;
const a_keys = Object.keys(a_obj);
const b_keys = Object.keys(b_obj);
if (a_keys.length != b_keys.length) {
return false;
}
if (!a_keys.every(k => exports.has_property(b_obj, k))) {
return false;
}
return Object.entries(a_obj).every(([k, v]) => smart_equals(v, b_obj[k]));
}
else if (a_type == SmartType.Array) {
const a_array = a;
const b_array = b;
if (a_array.length != b_array.length) {
return false;
}
return a_array.every((aa, i) => smart_equals(aa, b_array[i]));
}
else {
return false;
}
}
exports.smart_equals = smart_equals;
function remove_undefined(obj) {
for (const [key, value] of Object.entries(obj)) {
if (value === undefined) {
delete obj[key];
}
}
return obj;
}
exports.remove_undefined = remove_undefined;
function str2ab(str) {
// this will required util.TextEncoder to be added to "global" in node, see tests
return new TextEncoder().encode(str);
}
function str2stream(str) {
// the object returned here smells roughly like a ReadableStream - enough to satisfy parse.ts
return {
getReader: () => {
let done = false;
return {
read: async () => {
if (done) {
return { done: true };
}
else {
done = true;
return { done: false, value: str2ab(str) };
}
},
};
},
};
}
exports.str2stream = str2stream;
//# sourceMappingURL=utils.js.map