import { isNode } from '../../utils/is.js'; import { escape, stringify } from '../../utils/string.js'; import { isSafeProperty } from '../../utils/customs.js'; import { hasOwnProperty } from '../../utils/object.js'; import { factory } from '../../utils/factory.js'; var name = 'ObjectNode'; var dependencies = ['Node']; export var createObjectNode = /* #__PURE__ */factory(name, dependencies, _ref => { var { Node } = _ref; /** * @constructor ObjectNode * @extends {Node} * Holds an object with keys/values * @param {Object.} [properties] object with key/value pairs */ function ObjectNode(properties) { if (!(this instanceof ObjectNode)) { throw new SyntaxError('Constructor must be called with the new operator'); } this.properties = properties || {}; // validate input if (properties) { if (!(typeof properties === 'object') || !Object.keys(properties).every(function (key) { return isNode(properties[key]); })) { throw new TypeError('Object containing Nodes expected'); } } } ObjectNode.prototype = new Node(); ObjectNode.prototype.type = 'ObjectNode'; ObjectNode.prototype.isObjectNode = true; /** * Compile a node into a JavaScript function. * This basically pre-calculates as much as possible and only leaves open * calculations which depend on a dynamic scope with variables. * @param {Object} math Math.js namespace with functions and constants. * @param {Object} argNames An object with argument names as key and `true` * as value. Used in the SymbolNode to optimize * for arguments from user assigned functions * (see FunctionAssignmentNode) or special symbols * like `end` (see IndexNode). * @return {function} Returns a function which can be called like: * evalNode(scope: Object, args: Object, context: *) */ ObjectNode.prototype._compile = function (math, argNames) { var evalEntries = {}; for (var key in this.properties) { if (hasOwnProperty(this.properties, key)) { // we stringify/parse the key here to resolve unicode characters, // so you cannot create a key like {"co\\u006Estructor": null} var stringifiedKey = stringify(key); var parsedKey = JSON.parse(stringifiedKey); if (!isSafeProperty(this.properties, parsedKey)) { throw new Error('No access to property "' + parsedKey + '"'); } evalEntries[parsedKey] = this.properties[key]._compile(math, argNames); } } return function evalObjectNode(scope, args, context) { var obj = {}; for (var _key in evalEntries) { if (hasOwnProperty(evalEntries, _key)) { obj[_key] = evalEntries[_key](scope, args, context); } } return obj; }; }; /** * Execute a callback for each of the child nodes of this node * @param {function(child: Node, path: string, parent: Node)} callback */ ObjectNode.prototype.forEach = function (callback) { for (var key in this.properties) { if (hasOwnProperty(this.properties, key)) { callback(this.properties[key], 'properties[' + stringify(key) + ']', this); } } }; /** * Create a new ObjectNode having it's childs be the results of calling * the provided callback function for each of the childs of the original node. * @param {function(child: Node, path: string, parent: Node): Node} callback * @returns {ObjectNode} Returns a transformed copy of the node */ ObjectNode.prototype.map = function (callback) { var properties = {}; for (var key in this.properties) { if (hasOwnProperty(this.properties, key)) { properties[key] = this._ifNode(callback(this.properties[key], 'properties[' + stringify(key) + ']', this)); } } return new ObjectNode(properties); }; /** * Create a clone of this node, a shallow copy * @return {ObjectNode} */ ObjectNode.prototype.clone = function () { var properties = {}; for (var key in this.properties) { if (hasOwnProperty(this.properties, key)) { properties[key] = this.properties[key]; } } return new ObjectNode(properties); }; /** * Get string representation * @param {Object} options * @return {string} str * @override */ ObjectNode.prototype._toString = function (options) { var entries = []; for (var key in this.properties) { if (hasOwnProperty(this.properties, key)) { entries.push(stringify(key) + ': ' + this.properties[key].toString(options)); } } return '{' + entries.join(', ') + '}'; }; /** * Get a JSON representation of the node * @returns {Object} */ ObjectNode.prototype.toJSON = function () { return { mathjs: 'ObjectNode', properties: this.properties }; }; /** * Instantiate an OperatorNode from its JSON representation * @param {Object} json An object structured like * `{"mathjs": "ObjectNode", "properties": {...}}`, * where mathjs is optional * @returns {ObjectNode} */ ObjectNode.fromJSON = function (json) { return new ObjectNode(json.properties); }; /** * Get HTML representation * @param {Object} options * @return {string} str * @override */ ObjectNode.prototype.toHTML = function (options) { var entries = []; for (var key in this.properties) { if (hasOwnProperty(this.properties, key)) { entries.push('' + escape(key) + '' + ':' + this.properties[key].toHTML(options)); } } return '{' + entries.join(',') + '}'; }; /** * Get LaTeX representation * @param {Object} options * @return {string} str */ ObjectNode.prototype._toTex = function (options) { var entries = []; for (var key in this.properties) { if (hasOwnProperty(this.properties, key)) { entries.push('\\mathbf{' + key + ':} & ' + this.properties[key].toTex(options) + '\\\\'); } } return "\\left\\{\\begin{array}{ll}".concat(entries.join('\n'), "\\end{array}\\right\\}"); }; return ObjectNode; }, { isClass: true, isNode: true });