simple-squiggle

A restricted subset of Squiggle
Log | Files | Refs | README

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, '&amp;').replace(/"/g, '&quot;').replace(/'/g, '&#39;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
    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 }