diff --git a/README.md b/README.md
index df55004..032fa19 100644
--- a/README.md
+++ b/README.md
@@ -1,28 +1,60 @@
-Unibabel
-========
+# Unibabel
-Minimalistic **Base64**, **TypedArrays**, and **UTF-8** / **Unicode** conversions in Browser (and Node) JavaScript. Optional add-on support for **hex** and **base32**.
+Minimalistic **Base64**, **TypedArrays**, and **UTF-8** / **Unicode** conversions in Browser (and Node) JavaScript.
+Optional add-on support for **hex** and **base32**.
See
See also
- * [TextEncoder](https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder/encode) / [TextDecoder](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder/decode)
- * [DateView](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView)
- * [text-encoding](https://github.com/inexorabletash/text-encoding)
- * [TextEncoderLite (based on Buffer)](https://github.com/coolaj86/TextEncoderLite/tree/litest)
- * [TextEncoderLite (based on text-encoding)](https://github.com/coolaj86/TextEncoderLite/tree/lite)
- * [Beatgammit's base64-js](https://github.com/beatgammit/base64-js)
+- [TextEncoder](https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder/encode) / [TextDecoder](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder/decode)
+- [DateView](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView)
+- [text-encoding](https://github.com/inexorabletash/text-encoding)
+- [TextEncoderLite (based on Buffer)](https://github.com/coolaj86/TextEncoderLite/tree/litest)
+- [TextEncoderLite (based on text-encoding)](https://github.com/coolaj86/TextEncoderLite/tree/lite)
+- [Beatgammit's base64-js](https://github.com/beatgammit/base64-js)
-Are you in the right place?
-------------------------
+# Example (Unicode to ArrayBuffer):
-Dear Node.js Users:
+```js
+var unicodeString = "I'm a ☢ ☃ that plays 𝄢 guitar and spea̧͈͖ks Ar̽̾̈́͒͑ ̶̧̨̱̹̭̯ͧ̾ͬC̷̙̲̝͖ͭ̏ͥͮ͟Oͮ͏̮̪̝͍M̲̖͊̒ͪͩͬ̚̚͜!";
+var buf = Unibabel.utf8ToBuffer(unicodeString);
+```
-You SHOULD NOT use this module. You already have [`Buffer`](https://nodejs.org/api/buffer.html) and [`thirty-two`](https://github.com/chrisumbel/thirty-two):
+## Supported Environments
+
+- VanillaJS
+- Node.js
+- CommonJS
+- WebPack
+- ... everything?
+
+# Browser Usage
+
+## CDN
+
+-
+-
+
+## Bower
+
+```bash
+bower install --save unibabel
+```
+
+```html
+
+```
+
+# Node Usage
+
+You don't _need_ this module, as you already have
+[`Buffer`](https://nodejs.org/api/buffer.html) and [`thirty-two`](https://github.com/chrisumbel/thirty-two):
+
+For example:
```javascript
-var buf = new Buffer('I ½ ♥ 💩', 'utf8');
+var buf = Buffer.from('I ½ ♥ 💩', 'utf8');
buf.toString('hex');
buf.toString('base64');
buf.toString('ascii');
@@ -30,27 +62,9 @@ buf.toString('utf8');
buf.toString('binary'); // deprecated, do not use
```
-Install
--------
+However, you _can_ use it (perhaps for isomorphic js?)
-You just include the `index.js` in a lovely script tag.
-
-```bash
-bower install --save unibabel
-```
-
-```html
-
-```
-
-Dear WebPack / Broccoli, Gulp / Grunt Users:
-
-I don't know how your build systems work these days,
-but Unibabel is exported as `Unibabel`
-and you can access it as `window.Unibabel`.
-
-API
-===
+# API
```javascript
// TypedArray <--> UTF8
@@ -58,50 +72,53 @@ var uint8Array = Unibabel.strToUtf8Arr(str);
var str = Unibabel.utf8ArrToStr(uint8Array);
// TypedArray <--> Base64
-var base64 = Unibabel.arrToBase64(uint8Array)
-var uint8Array = Unibabel.base64ToArr(base64)
+var base64 = Unibabel.arrToBase64(uint8Array);
+var uint8Array = Unibabel.base64ToArr(base64);
```
**Normal APIs**
-`index.js`
+`unibabel.js`
-* utf8ToBuffer(utf8str) => array
-* bufferToUtf8(array) => string
-* utf8ToBase64(utf8str) => base64
-* base64ToUtf8(base64) => string
-* bufferToBase64(array) => base64
-* base64ToBuffer(base64) => array
+- utf8ToBuffer(utf8str) => array
+- bufferToUtf8(array) => string
+- utf8ToBase64(utf8str) => base64
+- base64ToUtf8(base64) => string
+- bufferToBase64(array) => base64
+- base64ToBuffer(base64) => array
**Hex APIs**
`unibabel.hex.js`
-* hexToBuffer(hexstr) => array
-* bufferToHex(array) => hexstr
+- hexToBuffer(hexstr) => array
+- bufferToHex(array) => hexstr
**Base32 APIs**
`unibabel.base32.js`
-* base32ToBuffer(b32str) => array
-* bufferToBase32(array) => b32str
+- base32ToBuffer(b32str) => array
+- bufferToBase32(array) => b32str
**Helper APIs**
-* utf8ToBinaryString(utf8str) => binstr
-* binaryStringToUtf8(binstr) => utf8str
-* bufferToBinaryString(buffer) => binstr
-* binaryStringToBuffer(binstr) => array
+- utf8ToBinaryString(utf8str) => binstr
+- binaryStringToUtf8(binstr) => utf8str
+- bufferToBinaryString(buffer) => binstr
+- binaryStringToBuffer(binstr) => array
-Examples
-========
+# Examples
```javascript
// Base64
-var myArray = Unibabel.base64ToArr("QmFzZSA2NCDigJQgTW96aWxsYSBEZXZlbG9wZXIgTmV0d29yaw=="); // "Base 64 \u2014 Mozilla Developer Network"
-var myBuffer = Unibabel.base64ToArr("QmFzZSA2NCDigJQgTW96aWxsYSBEZXZlbG9wZXIgTmV0d29yaw==").buffer; // "Base 64 \u2014 Mozilla Developer Network"
+var myArray = Unibabel.base64ToArr(
+ 'QmFzZSA2NCDigJQgTW96aWxsYSBEZXZlbG9wZXIgTmV0d29yaw=='
+); // "Base 64 \u2014 Mozilla Developer Network"
+var myBuffer = Unibabel.base64ToArr(
+ 'QmFzZSA2NCDigJQgTW96aWxsYSBEZXZlbG9wZXIgTmV0d29yaw=='
+).buffer; // "Base 64 \u2014 Mozilla Developer Network"
console.log(myBuffer.byteLength);
@@ -119,27 +136,28 @@ var sMyOutput = Unibabel.utf8ArrToStr(aMyUTF8Output);
alert(sMyOutput);
```
-License
-=======
+# License
-* `index.js` and `unibabel.hex.js` are dual-licensed as Apache 2.0 and MIT.
-* `unibabel.base32.js` is a modified version of [thirty-two](https://github.com/chrisumbel/thirty-two) and is therefore licensed MIT.
+- `index.js` and `unibabel.hex.js` are dual-licensed as Apache 2.0 and MIT.
+- `unibabel.base32.js` is a modified version of [thirty-two](https://github.com/chrisumbel/thirty-two) and is therefore licensed MIT.
Some parts of the code were taken from MDN, which Mozilla has licensed in the Public Domain,
which means that I am at liberty to re-license my copy under the Apache 2 and MIT licenses.
See
-ChangeLog
-====
+# ChangeLog
-v2.1.0
-------
+## v3.0.0
+
+- Proper node support (`unibabel.node.js`)
+- Various minor updates
+
+## v2.1.0
Added `unibabel.base32.js`
-v2.0.0
-------
+## v2.0.0
The new implementation is binary compatible with node.js, TextEncoder,
and other more-common UTF-8 encodings.
@@ -150,8 +168,7 @@ it happens to work).
See
-v1.0.0
-------
+## v1.0.0
This version was based on the work by good folks at the MDN, however,
the UTF-8 conversion was not byte-compatible with other UTF-8 conversions
diff --git a/base32.js b/base32.js
new file mode 100644
index 0000000..95b2b96
--- /dev/null
+++ b/base32.js
@@ -0,0 +1,215 @@
+/*
+Copyright (c) 2011, Chris Umbel
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+'use strict';
+
+var charTable = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';
+var byteTable = [
+ 0xff,
+ 0xff,
+ 0x1a,
+ 0x1b,
+ 0x1c,
+ 0x1d,
+ 0x1e,
+ 0x1f,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0x00,
+ 0x01,
+ 0x02,
+ 0x03,
+ 0x04,
+ 0x05,
+ 0x06,
+ 0x07,
+ 0x08,
+ 0x09,
+ 0x0a,
+ 0x0b,
+ 0x0c,
+ 0x0d,
+ 0x0e,
+ 0x0f,
+ 0x10,
+ 0x11,
+ 0x12,
+ 0x13,
+ 0x14,
+ 0x15,
+ 0x16,
+ 0x17,
+ 0x18,
+ 0x19,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0x00,
+ 0x01,
+ 0x02,
+ 0x03,
+ 0x04,
+ 0x05,
+ 0x06,
+ 0x07,
+ 0x08,
+ 0x09,
+ 0x0a,
+ 0x0b,
+ 0x0c,
+ 0x0d,
+ 0x0e,
+ 0x0f,
+ 0x10,
+ 0x11,
+ 0x12,
+ 0x13,
+ 0x14,
+ 0x15,
+ 0x16,
+ 0x17,
+ 0x18,
+ 0x19,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff,
+ 0xff
+];
+
+function quintetCount(buff) {
+ var quintets = Math.floor(buff.length / 5);
+ return buff.length % 5 === 0 ? quintets : quintets + 1;
+}
+
+exports.bufferToBase32 = function(plain) {
+ // plain MUST come in either as Array or Uint8Array
+ if ('undefined' !== typeof Uint8Array) {
+ if (!(plain instanceof Uint8Array)) {
+ plain = new Uint8Array(plain);
+ }
+ }
+ var i = 0;
+ var j = 0;
+ var shiftIndex = 0;
+ var digit = 0;
+ var encoded = new Array(quintetCount(plain) * 8);
+
+ /* byte by byte isn't as pretty as quintet by quintet but tests a bit
+ faster. will have to revisit. */
+ while (i < plain.length) {
+ var current = plain[i];
+
+ if (shiftIndex > 3) {
+ digit = current & (0xff >> shiftIndex);
+ shiftIndex = (shiftIndex + 5) % 8;
+ digit =
+ (digit << shiftIndex) |
+ ((i + 1 < plain.length ? plain[i + 1] : 0) >> (8 - shiftIndex));
+ i++;
+ } else {
+ digit = (current >> (8 - (shiftIndex + 5))) & 0x1f;
+ shiftIndex = (shiftIndex + 5) % 8;
+ if (shiftIndex === 0) {
+ i++;
+ }
+ }
+
+ encoded[j] = charTable[digit];
+ j++;
+ }
+
+ for (i = j; i < encoded.length; i++) {
+ encoded[i] = '=';
+ }
+
+ return encoded.join('');
+};
+
+exports.base32ToBuffer = function(encoded) {
+ var shiftIndex = 0;
+ var plainDigit = 0;
+ var plainChar;
+ var plainPos = 0;
+ var len = Math.ceil((encoded.length * 5) / 8);
+ var decoded;
+ encoded = encoded.split('').map(function(ch) {
+ return ch.charCodeAt(0);
+ });
+ if ('undefined' !== typeof Uint8Array) {
+ encoded = new Uint8Array(encoded);
+ decoded = new Uint8Array(len);
+ } else {
+ decoded = new Array(len);
+ }
+
+ /* byte by byte isn't as pretty as octet by octet but tests a bit
+ faster. will have to revisit. */
+ for (var i = 0; i < encoded.length; i++) {
+ if (encoded[i] === 0x3d) {
+ //'='
+ break;
+ }
+
+ var encodedByte = encoded[i] - 0x30;
+
+ if (encodedByte < byteTable.length) {
+ plainDigit = byteTable[encodedByte];
+
+ if (shiftIndex <= 3) {
+ shiftIndex = (shiftIndex + 5) % 8;
+
+ if (shiftIndex === 0) {
+ plainChar |= plainDigit;
+ decoded[plainPos] = plainChar;
+ plainPos++;
+ plainChar = 0;
+ } else {
+ plainChar |= 0xff & (plainDigit << (8 - shiftIndex));
+ }
+ } else {
+ shiftIndex = (shiftIndex + 5) % 8;
+ plainChar |= 0xff & (plainDigit >>> shiftIndex);
+ decoded[plainPos] = plainChar;
+ plainPos++;
+
+ plainChar = 0xff & (plainDigit << (8 - shiftIndex));
+ }
+ } else {
+ throw new Error('Invalid input - it is not base32 encoded string');
+ }
+ }
+
+ if (decoded.slice) {
+ // Array or TypedArray
+ return decoded.slice(0, plainPos);
+ } else {
+ // Mobile Safari TypedArray
+ return new Uint8Array(Array.prototype.slice.call(decoded, 0, plainPos));
+ }
+};
diff --git a/bin/build.js b/bin/build.js
new file mode 100644
index 0000000..01848f9
--- /dev/null
+++ b/bin/build.js
@@ -0,0 +1,62 @@
+#!/usr/bin/env node
+(async function() {
+ 'use strict';
+
+ var UglifyJS = require('uglify-js');
+ var path = require('path');
+ var fs = require('fs');
+ var promisify = require('util').promisify;
+ var readFile = promisify(fs.readFile);
+ var writeFile = promisify(fs.writeFile);
+ var gzip = promisify(require('zlib').gzip);
+ var name = require('../package.json').name;
+
+ // The order is specific, and it matters
+ var files = await Promise.all(
+ ['../unibabel.js', '../hex.js', '../base32.js'].map(
+ async function(file) {
+ return (await readFile(
+ path.join(__dirname, file),
+ 'utf8'
+ )).trim();
+ }
+ )
+ );
+
+ var license =
+ [
+ '// Unibabel Copyright 2015-2019 AJ ONeal. All rights reserved.',
+ '/* License at http://mozilla.org/MPL/2.0/ */',
+ '// Thirty-Two Copyright (c) 2011, Chris Umbel. All rights reserved.',
+ '/* License at https://github.com/chrisumbel/thirty-two */'
+ ].join('\n') + '\n';
+ var header = ['var Unibabel = {};', ';(function () {'].join('\n') + '\n';
+ var footer = ['}());'].join('\n') + '\n';
+
+ var file = (
+ (license + header + files.join('\n') + '\n' + footer).trim() + '\n'
+ )
+ .replace(/\bmodule.exports\b/g, 'Unibabel')
+ .replace(/\bexports\b/g, 'Unibabel');
+ await writeFile(path.join(__dirname, '../dist', name + '.all.js'), file);
+ await writeFile(
+ path.join(__dirname, '../dist', name + '.all.js.gz'),
+ await gzip(file)
+ );
+
+ // TODO source maps?
+ var result = UglifyJS.minify(file, {
+ compress: true,
+ // mangling doesn't save significant
+ mangle: false
+ });
+ if (result.error) {
+ throw result.error;
+ }
+ file = license + result.code;
+ await writeFile(path.join(__dirname, '../dist', name + '.all.min.js'), file);
+ await writeFile(
+ path.join(__dirname, '../dist', name + '.all.min.js.gz'),
+ await gzip(file)
+ );
+})();
diff --git a/examples/index.html b/examples/index.html
index d56f98a..4013b59 100644
--- a/examples/index.html
+++ b/examples/index.html
@@ -4,9 +4,12 @@
This is for testing. Look in the console.
+
+
+