BlockNode.js (5883B)
1 import { isNode } from '../../utils/is.js'; 2 import { forEach, map } from '../../utils/array.js'; 3 import { factory } from '../../utils/factory.js'; 4 var name = 'BlockNode'; 5 var dependencies = ['ResultSet', 'Node']; 6 export var createBlockNode = /* #__PURE__ */factory(name, dependencies, _ref => { 7 var { 8 ResultSet, 9 Node 10 } = _ref; 11 12 /** 13 * @constructor BlockNode 14 * @extends {Node} 15 * Holds a set with blocks 16 * @param {Array.<{node: Node} | {node: Node, visible: boolean}>} blocks 17 * An array with blocks, where a block is constructed as an Object 18 * with properties block, which is a Node, and visible, which is 19 * a boolean. The property visible is optional and is true by default 20 */ 21 function BlockNode(blocks) { 22 if (!(this instanceof BlockNode)) { 23 throw new SyntaxError('Constructor must be called with the new operator'); 24 } // validate input, copy blocks 25 26 27 if (!Array.isArray(blocks)) throw new Error('Array expected'); 28 this.blocks = blocks.map(function (block) { 29 var node = block && block.node; 30 var visible = block && block.visible !== undefined ? block.visible : true; 31 if (!isNode(node)) throw new TypeError('Property "node" must be a Node'); 32 if (typeof visible !== 'boolean') throw new TypeError('Property "visible" must be a boolean'); 33 return { 34 node: node, 35 visible: visible 36 }; 37 }); 38 } 39 40 BlockNode.prototype = new Node(); 41 BlockNode.prototype.type = 'BlockNode'; 42 BlockNode.prototype.isBlockNode = true; 43 /** 44 * Compile a node into a JavaScript function. 45 * This basically pre-calculates as much as possible and only leaves open 46 * calculations which depend on a dynamic scope with variables. 47 * @param {Object} math Math.js namespace with functions and constants. 48 * @param {Object} argNames An object with argument names as key and `true` 49 * as value. Used in the SymbolNode to optimize 50 * for arguments from user assigned functions 51 * (see FunctionAssignmentNode) or special symbols 52 * like `end` (see IndexNode). 53 * @return {function} Returns a function which can be called like: 54 * evalNode(scope: Object, args: Object, context: *) 55 */ 56 57 BlockNode.prototype._compile = function (math, argNames) { 58 var evalBlocks = map(this.blocks, function (block) { 59 return { 60 evaluate: block.node._compile(math, argNames), 61 visible: block.visible 62 }; 63 }); 64 return function evalBlockNodes(scope, args, context) { 65 var results = []; 66 forEach(evalBlocks, function evalBlockNode(block) { 67 var result = block.evaluate(scope, args, context); 68 69 if (block.visible) { 70 results.push(result); 71 } 72 }); 73 return new ResultSet(results); 74 }; 75 }; 76 /** 77 * Execute a callback for each of the child blocks of this node 78 * @param {function(child: Node, path: string, parent: Node)} callback 79 */ 80 81 82 BlockNode.prototype.forEach = function (callback) { 83 for (var i = 0; i < this.blocks.length; i++) { 84 callback(this.blocks[i].node, 'blocks[' + i + '].node', this); 85 } 86 }; 87 /** 88 * Create a new BlockNode having it's childs be the results of calling 89 * the provided callback function for each of the childs of the original node. 90 * @param {function(child: Node, path: string, parent: Node): Node} callback 91 * @returns {BlockNode} Returns a transformed copy of the node 92 */ 93 94 95 BlockNode.prototype.map = function (callback) { 96 var blocks = []; 97 98 for (var i = 0; i < this.blocks.length; i++) { 99 var block = this.blocks[i]; 100 101 var node = this._ifNode(callback(block.node, 'blocks[' + i + '].node', this)); 102 103 blocks[i] = { 104 node: node, 105 visible: block.visible 106 }; 107 } 108 109 return new BlockNode(blocks); 110 }; 111 /** 112 * Create a clone of this node, a shallow copy 113 * @return {BlockNode} 114 */ 115 116 117 BlockNode.prototype.clone = function () { 118 var blocks = this.blocks.map(function (block) { 119 return { 120 node: block.node, 121 visible: block.visible 122 }; 123 }); 124 return new BlockNode(blocks); 125 }; 126 /** 127 * Get string representation 128 * @param {Object} options 129 * @return {string} str 130 * @override 131 */ 132 133 134 BlockNode.prototype._toString = function (options) { 135 return this.blocks.map(function (param) { 136 return param.node.toString(options) + (param.visible ? '' : ';'); 137 }).join('\n'); 138 }; 139 /** 140 * Get a JSON representation of the node 141 * @returns {Object} 142 */ 143 144 145 BlockNode.prototype.toJSON = function () { 146 return { 147 mathjs: 'BlockNode', 148 blocks: this.blocks 149 }; 150 }; 151 /** 152 * Instantiate an BlockNode from its JSON representation 153 * @param {Object} json An object structured like 154 * `{"mathjs": "BlockNode", blocks: [{node: ..., visible: false}, ...]}`, 155 * where mathjs is optional 156 * @returns {BlockNode} 157 */ 158 159 160 BlockNode.fromJSON = function (json) { 161 return new BlockNode(json.blocks); 162 }; 163 /** 164 * Get HTML representation 165 * @param {Object} options 166 * @return {string} str 167 * @override 168 */ 169 170 171 BlockNode.prototype.toHTML = function (options) { 172 return this.blocks.map(function (param) { 173 return param.node.toHTML(options) + (param.visible ? '' : '<span class="math-separator">;</span>'); 174 }).join('<span class="math-separator"><br /></span>'); 175 }; 176 /** 177 * Get LaTeX representation 178 * @param {Object} options 179 * @return {string} str 180 */ 181 182 183 BlockNode.prototype._toTex = function (options) { 184 return this.blocks.map(function (param) { 185 return param.node.toTex(options) + (param.visible ? '' : ';'); 186 }).join('\\;\\;\n'); 187 }; 188 189 return BlockNode; 190 }, { 191 isClass: true, 192 isNode: true 193 });