[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/microcisco/mathjs/develop/src/utils/string.js [Back]  [Original]

'use strict'

const formatNumber = require('./number').format
const formatBigNumber = require('./bignumber/formatter').format
const isBigNumber = require('./bignumber/isBigNumber')

/**
 * Test whether value is a string
 * @param {*} value
 * @return {boolean} isString
 */
exports.isString = function (value) {
  return typeof value === 'string'
}

/**
 * Check if a text ends with a certain string.
 * @param {string} text
 * @param {string} search
 */
exports.endsWith = function (text, search) {
  const start = text.length - search.length
  const end = text.length
  return (text.substring(start, end) === search)
}

/**
 * Format a value of any type into a string.
 *
 * Usage:
 *     math.format(value)
 *     math.format(value, precision)
 *
 * When value is a function:
 *
 * - When the function has a property `syntax`, it returns this
 *   syntax description.
 * - In other cases, a string `'function'` is returned.
 *
 * When `value` is an Object:
 *
 * - When the object contains a property `format` being a function, this
 *   function is invoked as `value.format(options)` and the result is returned.
 * - When the object has its own `toString` method, this method is invoked
 *   and the result is returned.
 * - In other cases the function will loop over all object properties and
 *   return JSON object notation like '{"a": 2, "b": 3}'.
 *
 * Example usage:
 *     math.format(2/7)                // '0.2857142857142857'
 *     math.format(math.pi, 3)         // '3.14'
 *     math.format(new Complex(2, 3))  // '2 + 3i'
 *     math.format('hello')            // '"hello"'
 *
 * @param {*} value             Value to be stringified
 * @param {Object | number | Function} [options]  Formatting options. See
 *                                                lib/utils/number:format for a
 *                                                description of the available
 *                                                options.
 * @return {string} str
 */
exports.format = function (value, options) {
  if (typeof value === 'number') {
    return formatNumber(value, options)
  }

  if (isBigNumber(value)) {
    return formatBigNumber(value, options)
  }

  // note: we use unsafe duck-typing here to check for Fractions, this is
  // ok here since we're only invoking toString or concatenating its values
  if (looksLikeFraction(value)) {
    if (!options || options.fraction !== 'decimal') {
      // output as ratio, like '1/3'
      return (value.s * value.n) + '/' + value.d
    } else {
      // output as decimal, like '0.(3)'
      return value.toString()
    }
  }

  if (Array.isArray(value)) {
    return formatArray(value, options)
  }

  if (exports.isString(value)) {
    return '"' + value + '"'
  }

  if (typeof value === 'function') {
    return value.syntax ? String(value.syntax) : 'function'
  }

  if (value && typeof value === 'object') {
    if (typeof value.format === 'function') {
      return value.format(options)
    } else if (value && value.toString() !== {}.toString()) {
      // this object has a non-native toString method, use that one
      return value.toString()
    } else {
      const entries = []

      for (const key in value) {
        if (value.hasOwnProperty(key)) {
          entries.push('"' + key + '": ' + exports.format(value[key], options))
        }
      }

      return '{' + entries.join(', ') + '}'
    }
  }

  return String(value)
}

/**
 * Stringify a value into a string enclosed in double quotes.
 * Unescaped double quotes and backslashes inside the value are escaped.
 * @param {*} value
 * @return {string}
 */
exports.stringify = function (value) {
  const text = String(value)
  let escaped = ''
  let i = 0
  while (i < text.length) {
    let c = text.charAt(i)

    if (c === '\\') {
      escaped += c
      i++

      c = text.charAt(i)
      if (c === '' || '"\\/bfnrtu'.indexOf(c) === -1) {
        escaped += '\\' // no valid escape character -> escape it
      }
      escaped += c
    } else if (c === '"') {
      escaped += '\\"'
    } else {
      escaped += c
    }
    i++
  }

  return '"' + escaped + '"'
}

/**
 * Escape special HTML characters
 * @param {*} value
 * @return {string}
 */
exports.escape = function (value) {
  let text = String(value)
  text = text.replace(/&/g, '&')
    .replace(/"/g, '"')
    .replace(/'/g, ''')
    .replace(//g, '>')

  return text
}

/**
 * Recursively format an n-dimensional matrix
 * Example output: "[[1, 2], [3, 4]]"
 * @param {Array} array
 * @param {Object | number | Function} [options]  Formatting options. See
 *                                                lib/utils/number:format for a
 *                                                description of the available
 *                                                options.
 * @returns {string} str
 */
function formatArray (array, options) {
  if (Array.isArray(array)) {
    let str = '['
    const len = array.length
    for (let i = 0; i < len; i++) {
      if (i !== 0) {
        str += ', '
      }
      str += formatArray(array[i], options)
    }
    str += ']'
    return str
  } else {
    return exports.format(array, options)
  }
}

/**
 * Check whether a value looks like a Fraction (unsafe duck-type check)
 * @param {*} value
 * @return {boolean}
 */
function looksLikeFraction (value) {
  return (value &&
      typeof value === 'object' &&
      typeof value.s === 'number' &&
      typeof value.n === 'number' &&
      typeof value.d === 'number') || false
}

Web Proxy Viewer  |  New URL  |  Original Page