index.mjs 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /**
  2. * @module byte-size
  3. */
  4. let defaultOptions = {}
  5. const _options = new WeakMap()
  6. class ByteSize {
  7. constructor (bytes, options) {
  8. options = Object.assign({
  9. units: 'metric',
  10. precision: 1
  11. }, defaultOptions, options)
  12. _options.set(this, options)
  13. const tables = {
  14. metric: [
  15. { from: 0 , to: 1e3 , unit: 'B' , long: 'bytes' },
  16. { from: 1e3 , to: 1e6 , unit: 'kB', long: 'kilobytes' },
  17. { from: 1e6 , to: 1e9 , unit: 'MB', long: 'megabytes' },
  18. { from: 1e9 , to: 1e12, unit: 'GB', long: 'gigabytes' },
  19. { from: 1e12, to: 1e15, unit: 'TB', long: 'terabytes' },
  20. { from: 1e15, to: 1e18, unit: 'PB', long: 'petabytes' },
  21. { from: 1e18, to: 1e21, unit: 'EB', long: 'exabytes' },
  22. { from: 1e21, to: 1e24, unit: 'ZB', long: 'zettabytes' },
  23. { from: 1e24, to: 1e27, unit: 'YB', long: 'yottabytes' },
  24. ],
  25. metric_octet: [
  26. { from: 0 , to: 1e3 , unit: 'o' , long: 'octets' },
  27. { from: 1e3 , to: 1e6 , unit: 'ko', long: 'kilooctets' },
  28. { from: 1e6 , to: 1e9 , unit: 'Mo', long: 'megaoctets' },
  29. { from: 1e9 , to: 1e12, unit: 'Go', long: 'gigaoctets' },
  30. { from: 1e12, to: 1e15, unit: 'To', long: 'teraoctets' },
  31. { from: 1e15, to: 1e18, unit: 'Po', long: 'petaoctets' },
  32. { from: 1e18, to: 1e21, unit: 'Eo', long: 'exaoctets' },
  33. { from: 1e21, to: 1e24, unit: 'Zo', long: 'zettaoctets' },
  34. { from: 1e24, to: 1e27, unit: 'Yo', long: 'yottaoctets' },
  35. ],
  36. iec: [
  37. { from: 0 , to: Math.pow(1024, 1), unit: 'B' , long: 'bytes' },
  38. { from: Math.pow(1024, 1), to: Math.pow(1024, 2), unit: 'KiB', long: 'kibibytes' },
  39. { from: Math.pow(1024, 2), to: Math.pow(1024, 3), unit: 'MiB', long: 'mebibytes' },
  40. { from: Math.pow(1024, 3), to: Math.pow(1024, 4), unit: 'GiB', long: 'gibibytes' },
  41. { from: Math.pow(1024, 4), to: Math.pow(1024, 5), unit: 'TiB', long: 'tebibytes' },
  42. { from: Math.pow(1024, 5), to: Math.pow(1024, 6), unit: 'PiB', long: 'pebibytes' },
  43. { from: Math.pow(1024, 6), to: Math.pow(1024, 7), unit: 'EiB', long: 'exbibytes' },
  44. { from: Math.pow(1024, 7), to: Math.pow(1024, 8), unit: 'ZiB', long: 'zebibytes' },
  45. { from: Math.pow(1024, 8), to: Math.pow(1024, 9), unit: 'YiB', long: 'yobibytes' },
  46. ],
  47. iec_octet: [
  48. { from: 0 , to: Math.pow(1024, 1), unit: 'o' , long: 'octets' },
  49. { from: Math.pow(1024, 1), to: Math.pow(1024, 2), unit: 'Kio', long: 'kibioctets' },
  50. { from: Math.pow(1024, 2), to: Math.pow(1024, 3), unit: 'Mio', long: 'mebioctets' },
  51. { from: Math.pow(1024, 3), to: Math.pow(1024, 4), unit: 'Gio', long: 'gibioctets' },
  52. { from: Math.pow(1024, 4), to: Math.pow(1024, 5), unit: 'Tio', long: 'tebioctets' },
  53. { from: Math.pow(1024, 5), to: Math.pow(1024, 6), unit: 'Pio', long: 'pebioctets' },
  54. { from: Math.pow(1024, 6), to: Math.pow(1024, 7), unit: 'Eio', long: 'exbioctets' },
  55. { from: Math.pow(1024, 7), to: Math.pow(1024, 8), unit: 'Zio', long: 'zebioctets' },
  56. { from: Math.pow(1024, 8), to: Math.pow(1024, 9), unit: 'Yio', long: 'yobioctets' },
  57. ],
  58. }
  59. Object.assign(tables, options.customUnits)
  60. const prefix = bytes < 0 ? '-' : ''
  61. bytes = Math.abs(bytes)
  62. const table = tables[options.units]
  63. if (table) {
  64. const units = table.find(u => bytes >= u.from && bytes < u.to)
  65. if (units) {
  66. const value = units.from === 0
  67. ? prefix + bytes
  68. : prefix + (bytes / units.from).toFixed(options.precision)
  69. this.value = value
  70. this.unit = units.unit
  71. this.long = units.long
  72. } else {
  73. this.value = prefix + bytes
  74. this.unit = ''
  75. this.long = ''
  76. }
  77. } else {
  78. throw new Error(`Invalid units specified: ${options.units}`)
  79. }
  80. }
  81. toString () {
  82. const options = _options.get(this)
  83. return options.toStringFn ? options.toStringFn.bind(this)() : `${this.value} ${this.unit}`
  84. }
  85. }
  86. /**
  87. * Returns an object with the spec `{ value: string, unit: string, long: string }`. The returned object defines a `toString` method meaning it can be used in any string context.
  88. * @param {number} - The bytes value to convert.
  89. * @param [options] {object} - Optional config.
  90. * @param [options.precision] {number} - Number of decimal places. Defaults to `1`.
  91. * @param [options.units] {string} - Specify `'metric'`, `'iec'`, `'metric_octet'`, `'iec_octet'` or the name of a property from the custom units table in `options.customUnits`. Defaults to `metric`.
  92. * @param [options.customUnits] {object} - An object containing one or more custom unit lookup tables.
  93. * @param [options.toStringFn] {function} - A `toString` function to override the default.
  94. * @returns {object}
  95. * @alias module:byte-size
  96. */
  97. function byteSize (bytes, options) {
  98. return new ByteSize(bytes, options)
  99. }
  100. /**
  101. * Set the default `byteSize` options for the duration of the process.
  102. * @param options {object} - A `byteSize` options object.
  103. */
  104. byteSize.defaultOptions = function (options) {
  105. defaultOptions = options
  106. }
  107. export default byteSize