string.js (6726B)
1 "use strict"; 2 3 var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); 4 5 Object.defineProperty(exports, "__esModule", { 6 value: true 7 }); 8 exports.compareText = compareText; 9 exports.endsWith = endsWith; 10 exports.escape = escape; 11 exports.format = format; 12 exports.stringify = stringify; 13 14 var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof")); 15 16 var _is = require("./is.js"); 17 18 var _number = require("./number.js"); 19 20 var _formatter = require("./bignumber/formatter.js"); 21 22 /** 23 * Check if a text ends with a certain string. 24 * @param {string} text 25 * @param {string} search 26 */ 27 function endsWith(text, search) { 28 var start = text.length - search.length; 29 var end = text.length; 30 return text.substring(start, end) === search; 31 } 32 /** 33 * Format a value of any type into a string. 34 * 35 * Usage: 36 * math.format(value) 37 * math.format(value, precision) 38 * math.format(value, options) 39 * 40 * When value is a function: 41 * 42 * - When the function has a property `syntax`, it returns this 43 * syntax description. 44 * - In other cases, a string `'function'` is returned. 45 * 46 * When `value` is an Object: 47 * 48 * - When the object contains a property `format` being a function, this 49 * function is invoked as `value.format(options)` and the result is returned. 50 * - When the object has its own `toString` method, this method is invoked 51 * and the result is returned. 52 * - In other cases the function will loop over all object properties and 53 * return JSON object notation like '{"a": 2, "b": 3}'. 54 * 55 * Example usage: 56 * math.format(2/7) // '0.2857142857142857' 57 * math.format(math.pi, 3) // '3.14' 58 * math.format(new Complex(2, 3)) // '2 + 3i' 59 * math.format('hello') // '"hello"' 60 * 61 * @param {*} value Value to be stringified 62 * @param {Object | number | Function} [options] 63 * Formatting options. See src/utils/number.js:format for a 64 * description of the available options controlling number output. 65 * This generic "format" also supports the option property `truncate: NN` 66 * giving the maximum number NN of characters to return (if there would 67 * have been more, they are deleted and replaced by an ellipsis). 68 * @return {string} str 69 */ 70 71 72 function format(value, options) { 73 var result = _format(value, options); 74 75 if (options && (0, _typeof2.default)(options) === 'object' && 'truncate' in options && result.length > options.truncate) { 76 return result.substring(0, options.truncate - 3) + '...'; 77 } 78 79 return result; 80 } 81 82 function _format(value, options) { 83 if (typeof value === 'number') { 84 return (0, _number.format)(value, options); 85 } 86 87 if ((0, _is.isBigNumber)(value)) { 88 return (0, _formatter.format)(value, options); 89 } // note: we use unsafe duck-typing here to check for Fractions, this is 90 // ok here since we're only invoking toString or concatenating its values 91 92 93 if (looksLikeFraction(value)) { 94 if (!options || options.fraction !== 'decimal') { 95 // output as ratio, like '1/3' 96 return value.s * value.n + '/' + value.d; 97 } else { 98 // output as decimal, like '0.(3)' 99 return value.toString(); 100 } 101 } 102 103 if (Array.isArray(value)) { 104 return formatArray(value, options); 105 } 106 107 if ((0, _is.isString)(value)) { 108 return '"' + value + '"'; 109 } 110 111 if (typeof value === 'function') { 112 return value.syntax ? String(value.syntax) : 'function'; 113 } 114 115 if (value && (0, _typeof2.default)(value) === 'object') { 116 if (typeof value.format === 'function') { 117 return value.format(options); 118 } else if (value && value.toString(options) !== {}.toString()) { 119 // this object has a non-native toString method, use that one 120 return value.toString(options); 121 } else { 122 var entries = Object.keys(value).map(function (key) { 123 return '"' + key + '": ' + format(value[key], options); 124 }); 125 return '{' + entries.join(', ') + '}'; 126 } 127 } 128 129 return String(value); 130 } 131 /** 132 * Stringify a value into a string enclosed in double quotes. 133 * Unescaped double quotes and backslashes inside the value are escaped. 134 * @param {*} value 135 * @return {string} 136 */ 137 138 139 function stringify(value) { 140 var text = String(value); 141 var escaped = ''; 142 var i = 0; 143 144 while (i < text.length) { 145 var c = text.charAt(i); 146 147 if (c === '\\') { 148 escaped += c; 149 i++; 150 c = text.charAt(i); 151 152 if (c === '' || '"\\/bfnrtu'.indexOf(c) === -1) { 153 escaped += '\\'; // no valid escape character -> escape it 154 } 155 156 escaped += c; 157 } else if (c === '"') { 158 escaped += '\\"'; 159 } else { 160 escaped += c; 161 } 162 163 i++; 164 } 165 166 return '"' + escaped + '"'; 167 } 168 /** 169 * Escape special HTML characters 170 * @param {*} value 171 * @return {string} 172 */ 173 174 175 function escape(value) { 176 var text = String(value); 177 text = text.replace(/&/g, '&').replace(/"/g, '"').replace(/'/g, ''').replace(/</g, '<').replace(/>/g, '>'); 178 return text; 179 } 180 /** 181 * Recursively format an n-dimensional matrix 182 * Example output: "[[1, 2], [3, 4]]" 183 * @param {Array} array 184 * @param {Object | number | Function} [options] Formatting options. See 185 * lib/utils/number:format for a 186 * description of the available 187 * options. 188 * @returns {string} str 189 */ 190 191 192 function formatArray(array, options) { 193 if (Array.isArray(array)) { 194 var str = '['; 195 var len = array.length; 196 197 for (var i = 0; i < len; i++) { 198 if (i !== 0) { 199 str += ', '; 200 } 201 202 str += formatArray(array[i], options); 203 } 204 205 str += ']'; 206 return str; 207 } else { 208 return format(array, options); 209 } 210 } 211 /** 212 * Check whether a value looks like a Fraction (unsafe duck-type check) 213 * @param {*} value 214 * @return {boolean} 215 */ 216 217 218 function looksLikeFraction(value) { 219 return value && (0, _typeof2.default)(value) === 'object' && typeof value.s === 'number' && typeof value.n === 'number' && typeof value.d === 'number' || false; 220 } 221 /** 222 * Compare two strings 223 * @param {string} x 224 * @param {string} y 225 * @returns {number} 226 */ 227 228 229 function compareText(x, y) { 230 // we don't want to convert numbers to string, only accept string input 231 if (!(0, _is.isString)(x)) { 232 throw new TypeError('Unexpected type of argument in function compareText ' + '(expected: string or Array or Matrix, actual: ' + (0, _is.typeOf)(x) + ', index: 0)'); 233 } 234 235 if (!(0, _is.isString)(y)) { 236 throw new TypeError('Unexpected type of argument in function compareText ' + '(expected: string or Array or Matrix, actual: ' + (0, _is.typeOf)(y) + ', index: 1)'); 237 } 238 239 return x === y ? 0 : x > y ? 1 : -1; 240 }