base64.mjs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. /**
  2. * base64.ts
  3. *
  4. * Licensed under the BSD 3-Clause License.
  5. * http://opensource.org/licenses/BSD-3-Clause
  6. *
  7. * References:
  8. * http://en.wikipedia.org/wiki/Base64
  9. *
  10. * @author Dan Kogai (https://github.com/dankogai)
  11. */
  12. const version = '3.3.3';
  13. /**
  14. * @deprecated use lowercase `version`.
  15. */
  16. const VERSION = version;
  17. const _b64chars = [
  18. ...'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
  19. ];
  20. const _b64tab = ((chars) => {
  21. let tab = {};
  22. _b64chars.forEach((c, i) => tab[c] = i);
  23. return tab;
  24. })(_b64chars);
  25. const _fromCharCode = String.fromCharCode;
  26. const _mkUriSafe = (src) => src
  27. .replace(/[+\/]/g, (m0) => m0 == '+' ? '-' : '_')
  28. .replace(/=+$/m, '');
  29. /**
  30. * converts a Uint8Array to a Base64 string.
  31. * @param {Boolean} [rfc4648] URL-and-filename-safe a la RFC4648
  32. * @returns {String} Base64 string
  33. */
  34. const fromUint8Array = (src, rfc4648 = false) => {
  35. let b64 = '';
  36. for (let i = 0, l = src.length; i < l; i += 3) {
  37. const [a0, a1, a2] = [src[i], src[i + 1], src[i + 2]];
  38. const ord = (a0 << 16) | (a1 << 8) | a2;
  39. b64 += _b64chars[(ord >>> 18)];
  40. b64 += _b64chars[(ord >>> 12) & 63];
  41. b64 += typeof a1 !== 'undefined' ? _b64chars[(ord >>> 6) & 63] : '=';
  42. b64 += typeof a2 !== 'undefined' ? _b64chars[ord & 63] : '=';
  43. }
  44. return rfc4648 ? _mkUriSafe(b64) : b64;
  45. };
  46. /**
  47. * does what `window.btoa` of web browsers does.
  48. * @param {String} src binary string
  49. * @returns {String} Base64-encoded string
  50. */
  51. const _btoa = typeof btoa === 'function'
  52. ? (s) => btoa(s)
  53. : (s) => {
  54. if (s.match(/[^\x00-\xFF]/))
  55. throw new RangeError('The string contains invalid characters.');
  56. return fromUint8Array(Uint8Array.from(s, c => c.charCodeAt(0)));
  57. };
  58. /**
  59. * @deprecated should have been internal use only.
  60. * @param {string} src UTF-8 string
  61. * @returns {string} UTF-16 string
  62. */
  63. const utob = (src) => unescape(encodeURIComponent(src));
  64. /**
  65. * converts a UTF-8-encoded string to a Base64 string.
  66. * @param {Boolean} [rfc4648] if `true` make the result URL-safe
  67. * @returns {String} Base64 string
  68. */
  69. const encode = (src, rfc4648 = false) => {
  70. const b64 = _btoa(utob(src));
  71. return rfc4648 ? _mkUriSafe(b64) : b64;
  72. };
  73. /**
  74. * converts a UTF-8-encoded string to URL-safe Base64 RFC4648.
  75. * @returns {String} Base64 string
  76. */
  77. const encodeURI = (src) => encode(src, true);
  78. /**
  79. * @deprecated should have been internal use only.
  80. * @param {string} src UTF-16 string
  81. * @returns {string} UTF-8 string
  82. */
  83. const btou = (src) => decodeURIComponent(escape(src));
  84. const _cb_decode = (cccc) => {
  85. let len = cccc.length, padlen = len % 4, n = (len > 0 ? _b64tab[cccc.charAt(0)] << 18 : 0)
  86. | (len > 1 ? _b64tab[cccc.charAt(1)] << 12 : 0)
  87. | (len > 2 ? _b64tab[cccc.charAt(2)] << 6 : 0)
  88. | (len > 3 ? _b64tab[cccc.charAt(3)] : 0), chars = [
  89. _fromCharCode(n >>> 16),
  90. _fromCharCode((n >>> 8) & 0xff),
  91. _fromCharCode(n & 0xff)
  92. ];
  93. chars.length -= [0, 0, 2, 1][padlen];
  94. return chars.join('');
  95. };
  96. /**
  97. * does what `window.atob` of web browsers does.
  98. * @param {String} src Base64-encoded string
  99. * @returns {String} binary string
  100. */
  101. const _atob = typeof atob === 'function'
  102. ? (a) => atob(a)
  103. : (a) => a.replace(/[^A-Za-z0-9\+\/]/g, '')
  104. .replace(/\S{1,4}/g, _cb_decode);
  105. const _decode = (a) => btou(_atob(a));
  106. const _unURI = (a) => {
  107. return a
  108. .replace(/[-_]/g, (m0) => m0 == '-' ? '+' : '/')
  109. .replace(/[^A-Za-z0-9\+\/]/g, '');
  110. };
  111. /**
  112. * converts a Base64 string to a UTF-8 string.
  113. * @param {String} src Base64 string. Both normal and URL-safe are supported
  114. * @returns {String} UTF-8 string
  115. */
  116. const decode = (src) => _decode(_unURI(src));
  117. /**
  118. * converts a Base64 string to a Uint8Array.
  119. */
  120. const toUint8Array = (a) => {
  121. return Uint8Array.from(_atob(_unURI(a)), c => c.charCodeAt(0));
  122. };
  123. const _noEnum = (v) => {
  124. return {
  125. value: v, enumerable: false, writable: true, configurable: true
  126. };
  127. };
  128. const extendString = function () {
  129. const _add = (name, body) => Object.defineProperty(String.prototype, name, _noEnum(body));
  130. _add('fromBase64', function () {
  131. return decode(this);
  132. });
  133. _add('toBase64', function (rfc4648) {
  134. return encode(this, rfc4648);
  135. });
  136. _add('toBase64URI', function () {
  137. return encode(this, true);
  138. });
  139. _add('toBase64URL', function () {
  140. return encode(this, true);
  141. });
  142. _add('toUint8Array', function () {
  143. return toUint8Array(this);
  144. });
  145. };
  146. const extendUint8Array = function () {
  147. const _add = (name, body) => Object.defineProperty(Uint8Array.prototype, name, _noEnum(body));
  148. _add('toBase64', function (rfc4648) {
  149. return fromUint8Array(this, rfc4648);
  150. });
  151. _add('toBase64URI', function () {
  152. return fromUint8Array(this, true);
  153. });
  154. _add('toBase64URL', function () {
  155. return fromUint8Array(this, true);
  156. });
  157. };
  158. const extendBuiltins = () => {
  159. extendString();
  160. extendUint8Array();
  161. };
  162. const gBase64 = {
  163. version: version,
  164. VERSION: VERSION,
  165. atob: _atob,
  166. btoa: _btoa,
  167. fromBase64: decode,
  168. toBase64: encode,
  169. encode: encode,
  170. encodeURI: encodeURI,
  171. encodeURL: encodeURI,
  172. utob: utob,
  173. btou: btou,
  174. decode: decode,
  175. fromUint8Array: fromUint8Array,
  176. toUint8Array: toUint8Array,
  177. extendString: extendString,
  178. extendUint8Array: extendUint8Array,
  179. extendBuiltins: extendBuiltins
  180. };
  181. // makecjs:CUT //
  182. export { version };
  183. export { VERSION };
  184. export { _atob as atob };
  185. export { _btoa as btoa };
  186. export { decode as fromBase64 };
  187. export { encode as toBase64 };
  188. export { utob };
  189. export { encode };
  190. export { encodeURI };
  191. export { encodeURI as encodeURL };
  192. export { btou };
  193. export { decode };
  194. export { fromUint8Array };
  195. export { toUint8Array };
  196. export { extendString };
  197. export { extendUint8Array };
  198. export { extendBuiltins };
  199. // and finally,
  200. export { gBase64 as Base64 };