UNPKG

5.38 kBJavaScriptView Raw
1import { format } from '../../utils/string'
2import { typeOf } from '../../utils/is'
3import { escapeLatex } from '../../utils/latex'
4import { factory } from '../../utils/factory'
5
6const name = 'ConstantNode'
7const dependencies = [
8 'Node'
9]
10
11export const createConstantNode = /* #__PURE__ */ factory(name, dependencies, ({ Node }) => {
12 /**
13 * A ConstantNode holds a constant value like a number or string.
14 *
15 * Usage:
16 *
17 * new ConstantNode(2.3)
18 * new ConstantNode('hello')
19 *
20 * @param {*} value Value can be any type (number, BigNumber, string, ...)
21 * @constructor ConstantNode
22 * @extends {Node}
23 */
24 function ConstantNode (value) {
25 if (!(this instanceof ConstantNode)) {
26 throw new SyntaxError('Constructor must be called with the new operator')
27 }
28
29 if (arguments.length === 2) {
30 // TODO: remove deprecation error some day (created 2018-01-23)
31 throw new SyntaxError('new ConstantNode(valueStr, valueType) is not supported anymore since math v4.0.0. Use new ConstantNode(value) instead, where value is a non-stringified value.')
32 }
33
34 this.value = value
35 }
36
37 ConstantNode.prototype = new Node()
38
39 ConstantNode.prototype.type = 'ConstantNode'
40
41 ConstantNode.prototype.isConstantNode = true
42
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 ConstantNode.prototype._compile = function (math, argNames) {
57 const value = this.value
58
59 return function evalConstantNode () {
60 return value
61 }
62 }
63
64 /**
65 * Execute a callback for each of the child nodes of this node
66 * @param {function(child: Node, path: string, parent: Node)} callback
67 */
68 ConstantNode.prototype.forEach = function (callback) {
69 // nothing to do, we don't have childs
70 }
71
72 /**
73 * Create a new ConstantNode having it's childs be the results of calling
74 * the provided callback function for each of the childs of the original node.
75 * @param {function(child: Node, path: string, parent: Node) : Node} callback
76 * @returns {ConstantNode} Returns a clone of the node
77 */
78 ConstantNode.prototype.map = function (callback) {
79 return this.clone()
80 }
81
82 /**
83 * Create a clone of this node, a shallow copy
84 * @return {ConstantNode}
85 */
86 ConstantNode.prototype.clone = function () {
87 return new ConstantNode(this.value)
88 }
89
90 /**
91 * Get string representation
92 * @param {Object} options
93 * @return {string} str
94 */
95 ConstantNode.prototype._toString = function (options) {
96 return format(this.value, options)
97 }
98
99 /**
100 * Get HTML representation
101 * @param {Object} options
102 * @return {string} str
103 */
104 ConstantNode.prototype.toHTML = function (options) {
105 const value = this._toString(options)
106
107 switch (typeOf(this.value)) {
108 case 'number':
109 case 'BigNumber':
110 case 'Fraction':
111 return '<span class="math-number">' + value + '</span>'
112 case 'string':
113 return '<span class="math-string">' + value + '</span>'
114 case 'boolean':
115 return '<span class="math-boolean">' + value + '</span>'
116 case 'null':
117 return '<span class="math-null-symbol">' + value + '</span>'
118 case 'undefined':
119 return '<span class="math-undefined">' + value + '</span>'
120
121 default:
122 return '<span class="math-symbol">' + value + '</span>'
123 }
124 }
125
126 /**
127 * Get a JSON representation of the node
128 * @returns {Object}
129 */
130 ConstantNode.prototype.toJSON = function () {
131 return {
132 mathjs: 'ConstantNode',
133 value: this.value
134 }
135 }
136
137 /**
138 * Instantiate a ConstantNode from its JSON representation
139 * @param {Object} json An object structured like
140 * `{"mathjs": "SymbolNode", value: 2.3}`,
141 * where mathjs is optional
142 * @returns {ConstantNode}
143 */
144 ConstantNode.fromJSON = function (json) {
145 return new ConstantNode(json.value)
146 }
147
148 /**
149 * Get LaTeX representation
150 * @param {Object} options
151 * @return {string} str
152 */
153 ConstantNode.prototype._toTex = function (options) {
154 const value = this._toString(options)
155
156 switch (typeOf(this.value)) {
157 case 'string':
158 return '\\mathtt{' + escapeLatex(value) + '}'
159
160 case 'number':
161 case 'BigNumber':
162 {
163 const index = value.toLowerCase().indexOf('e')
164 if (index !== -1) {
165 return value.substring(0, index) + '\\cdot10^{' +
166 value.substring(index + 1) + '}'
167 }
168 }
169 return value
170 case 'Fraction':
171 return this.value.toLatex()
172
173 default:
174 return value
175 }
176 }
177
178 return ConstantNode
179}, { isClass: true, isNode: true })