UNPKG

6.66 kBJavaScriptView Raw
1import { isNode } from '../../utils/is.js';
2import { escape, stringify } from '../../utils/string.js';
3import { isSafeProperty } from '../../utils/customs.js';
4import { hasOwnProperty } from '../../utils/object.js';
5import { factory } from '../../utils/factory.js';
6var name = 'ObjectNode';
7var dependencies = ['Node'];
8export var createObjectNode = /* #__PURE__ */factory(name, dependencies, (_ref) => {
9 var {
10 Node
11 } = _ref;
12
13 /**
14 * @constructor ObjectNode
15 * @extends {Node}
16 * Holds an object with keys/values
17 * @param {Object.<string, Node>} [properties] object with key/value pairs
18 */
19 function ObjectNode(properties) {
20 if (!(this instanceof ObjectNode)) {
21 throw new SyntaxError('Constructor must be called with the new operator');
22 }
23
24 this.properties = properties || {}; // validate input
25
26 if (properties) {
27 if (!(typeof properties === 'object') || !Object.keys(properties).every(function (key) {
28 return isNode(properties[key]);
29 })) {
30 throw new TypeError('Object containing Nodes expected');
31 }
32 }
33 }
34
35 ObjectNode.prototype = new Node();
36 ObjectNode.prototype.type = 'ObjectNode';
37 ObjectNode.prototype.isObjectNode = true;
38 /**
39 * Compile a node into a JavaScript function.
40 * This basically pre-calculates as much as possible and only leaves open
41 * calculations which depend on a dynamic scope with variables.
42 * @param {Object} math Math.js namespace with functions and constants.
43 * @param {Object} argNames An object with argument names as key and `true`
44 * as value. Used in the SymbolNode to optimize
45 * for arguments from user assigned functions
46 * (see FunctionAssignmentNode) or special symbols
47 * like `end` (see IndexNode).
48 * @return {function} Returns a function which can be called like:
49 * evalNode(scope: Object, args: Object, context: *)
50 */
51
52 ObjectNode.prototype._compile = function (math, argNames) {
53 var evalEntries = {};
54
55 for (var key in this.properties) {
56 if (hasOwnProperty(this.properties, key)) {
57 // we stringify/parse the key here to resolve unicode characters,
58 // so you cannot create a key like {"co\\u006Estructor": null}
59 var stringifiedKey = stringify(key);
60 var parsedKey = JSON.parse(stringifiedKey);
61
62 if (!isSafeProperty(this.properties, parsedKey)) {
63 throw new Error('No access to property "' + parsedKey + '"');
64 }
65
66 evalEntries[parsedKey] = this.properties[key]._compile(math, argNames);
67 }
68 }
69
70 return function evalObjectNode(scope, args, context) {
71 var obj = {};
72
73 for (var _key in evalEntries) {
74 if (hasOwnProperty(evalEntries, _key)) {
75 obj[_key] = evalEntries[_key](scope, args, context);
76 }
77 }
78
79 return obj;
80 };
81 };
82 /**
83 * Execute a callback for each of the child nodes of this node
84 * @param {function(child: Node, path: string, parent: Node)} callback
85 */
86
87
88 ObjectNode.prototype.forEach = function (callback) {
89 for (var key in this.properties) {
90 if (hasOwnProperty(this.properties, key)) {
91 callback(this.properties[key], 'properties[' + stringify(key) + ']', this);
92 }
93 }
94 };
95 /**
96 * Create a new ObjectNode having it's childs be the results of calling
97 * the provided callback function for each of the childs of the original node.
98 * @param {function(child: Node, path: string, parent: Node): Node} callback
99 * @returns {ObjectNode} Returns a transformed copy of the node
100 */
101
102
103 ObjectNode.prototype.map = function (callback) {
104 var properties = {};
105
106 for (var key in this.properties) {
107 if (hasOwnProperty(this.properties, key)) {
108 properties[key] = this._ifNode(callback(this.properties[key], 'properties[' + stringify(key) + ']', this));
109 }
110 }
111
112 return new ObjectNode(properties);
113 };
114 /**
115 * Create a clone of this node, a shallow copy
116 * @return {ObjectNode}
117 */
118
119
120 ObjectNode.prototype.clone = function () {
121 var properties = {};
122
123 for (var key in this.properties) {
124 if (hasOwnProperty(this.properties, key)) {
125 properties[key] = this.properties[key];
126 }
127 }
128
129 return new ObjectNode(properties);
130 };
131 /**
132 * Get string representation
133 * @param {Object} options
134 * @return {string} str
135 * @override
136 */
137
138
139 ObjectNode.prototype._toString = function (options) {
140 var entries = [];
141
142 for (var key in this.properties) {
143 if (hasOwnProperty(this.properties, key)) {
144 entries.push(stringify(key) + ': ' + this.properties[key].toString(options));
145 }
146 }
147
148 return '{' + entries.join(', ') + '}';
149 };
150 /**
151 * Get a JSON representation of the node
152 * @returns {Object}
153 */
154
155
156 ObjectNode.prototype.toJSON = function () {
157 return {
158 mathjs: 'ObjectNode',
159 properties: this.properties
160 };
161 };
162 /**
163 * Instantiate an OperatorNode from its JSON representation
164 * @param {Object} json An object structured like
165 * `{"mathjs": "ObjectNode", "properties": {...}}`,
166 * where mathjs is optional
167 * @returns {ObjectNode}
168 */
169
170
171 ObjectNode.fromJSON = function (json) {
172 return new ObjectNode(json.properties);
173 };
174 /**
175 * Get HTML representation
176 * @param {Object} options
177 * @return {string} str
178 * @override
179 */
180
181
182 ObjectNode.prototype.toHTML = function (options) {
183 var entries = [];
184
185 for (var key in this.properties) {
186 if (hasOwnProperty(this.properties, key)) {
187 entries.push('<span class="math-symbol math-property">' + escape(key) + '</span>' + '<span class="math-operator math-assignment-operator math-property-assignment-operator math-binary-operator">:</span>' + this.properties[key].toHTML(options));
188 }
189 }
190
191 return '<span class="math-parenthesis math-curly-parenthesis">{</span>' + entries.join('<span class="math-separator">,</span>') + '<span class="math-parenthesis math-curly-parenthesis">}</span>';
192 };
193 /**
194 * Get LaTeX representation
195 * @param {Object} options
196 * @return {string} str
197 */
198
199
200 ObjectNode.prototype._toTex = function (options) {
201 var entries = [];
202
203 for (var key in this.properties) {
204 if (hasOwnProperty(this.properties, key)) {
205 entries.push('\\mathbf{' + key + ':} & ' + this.properties[key].toTex(options) + '\\\\');
206 }
207 }
208
209 return "\\left\\{\\begin{array}{ll}".concat(entries.join('\n'), "\\end{array}\\right\\}");
210 };
211
212 return ObjectNode;
213}, {
214 isClass: true,
215 isNode: true
216});
\No newline at end of file