hella docs

This commit is contained in:
Nolan Lawson 2014-10-25 12:42:10 -04:00
parent 37b15fa26f
commit 696f340790
5 changed files with 413 additions and 89 deletions

2
.gitignore vendored
View File

@ -5,3 +5,5 @@ coverage
test/test-bundle.js
npm-debug.log
dist
doc
api.md

View File

@ -15,7 +15,7 @@
"globals": { "Pouch": true},
"white": true,
"indent": 2,
"maxlen": 100,
"maxlen": 120,
"predef": [
"process",
"global",

228
README.md
View File

@ -3,21 +3,26 @@ blob-util
[![Build Status](https://travis-ci.org/nolanlawson/blob-util.svg)](https://travis-ci.org/nolanlawson/blob-util)
You know what's cool? [HTML5 Blobs](https://developer.mozilla.org/en-US/docs/Web/API/Blob?redirectlocale=en-US&redirectslug=DOM%2FBlob).
`blob-util` is a [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob?redirectlocale=en-US&redirectslug=DOM%2FBlob) library for busy people.
You know what's hard to work with? Yeah, you guessed it.
If you want an easy way to work with binary data in the browser, or you don't even know what a Blob is, then this is the library for you.
If you just want to work with binary data in the browser and not pull your hair out, then this is the library for you.
`blob-util` offers cross-browser utilities for translating Blobs to and from different formats:
`blob-util` offers various utilities for transforming Blobs between different formats (base 64, data URL, image), and it works
cross-browser.
* `<img/>` tags
* base 64 strings
* binary strings
* ArrayBuffers
* data URLs
It's also a good pairing with the attachment API in [PouchDB](http://pouchdb.com).
Usage
`blob-util` is a browser library. If you need to work with binary data in Node.js, see [Buffers](http://nodejs.org/api/buffer.html).
Install
------
Grab it from the `dist/` folder above, or npm:
Grab it from the `dist/` folder above, or use NPM:
```
npm install blob-util
@ -39,19 +44,222 @@ Now you have a `window.blobUtil` object that contains the API. Or if you don't l
globals, you can use Browserify.
Building
Quick Start
--------
Here's Kirby. He's a famous little Blob.
<img id="kirby" alt="Kirby" src="./test/kirby.gif"/>
So let's fulfill his manifest destiny, and convert him to a real `Blob` object.
```js
var img = document.getElementById('kirby');
blobUtil.imgSrcToBlob(img.src).then(function (blob) {
// ladies and gents, we have a blob
}).catch(function (err) {
// image failed to load
})
```
(Don't worry, this won't download the image twice, because browsers are smart.)
Now that we have a `Blob`, we can convert it to a URL and use that as the source for another `<img/>` tag:
```js
var blobURL = blobUtil.createObjectURL(blob);
var newImg = document.createElement('img');
newImg.src = blobURL;
```
So now we have to Kirbys - one with a normal URL, and the other with a blob URL. Neato!
API
-------
Warning: this API uses [Promises](https://promisesaplus.com/), because it's not 2009 anymore.
###Overview
* [createBlob(parts, options)](#createBlob)
* [createObjectURL(blob)](#createObjectURL)
* [revokeObjectURL(url)](#revokeObjectURL)
* [blobToBinaryString(blob)](#blobToBinaryString)
* [base64StringToBlob(base64, type)](#base64StringToBlob)
* [binaryStringToBlob(binary, type)](#binaryStringToBlob)
* [blobToBase64String(blob)](#blobToBase64String)
* [dataURLToBlob(dataURL)](#dataURLToBlob)
* [imgSrcToDataURL(src, type)](#imgSrcToDataURL)
* [canvasToBlob(canvas, type)](#canvasToBlob)
* [imgSrcToBlob(src, type)](#imgSrcToBlob)
* [arrayBufferToBlob(buffer, type)](#arrayBufferToBlob)
* [blobToArrayBuffer(blob)](#blobToArrayBuffer)
<a name="createBlob"></a>
###createBlob(parts, options)
Shim for
[new Blob()](https://developer.mozilla.org/en-US/docs/Web/API/Blob.Blob)
to support
[older browsers that use the deprecated <code>BlobBuilder</code> API](http://caniuse.com/blob).
**Params**
- parts `Array` - content of the <code>Blob</code>
- options `Object` - usually just <code>{type: myContentType}</code>
**Returns**: `Blob`
<a name="createObjectURL"></a>
###createObjectURL(blob)
Shim for
[URL.createObjectURL()](https://developer.mozilla.org/en-US/docs/Web/API/URL.createObjectURL)
to support browsers that only have the prefixed
<code>webkitURL</code> (e.g. Android <4.4).
**Params**
- blob `Blob`
**Returns**: `string` - url
<a name="revokeObjectURL"></a>
###revokeObjectURL(url)
Shim for
[URL.revokeObjectURL()](https://developer.mozilla.org/en-US/docs/Web/API/URL.revokeObjectURL)
to support browsers that only have the prefixed
<code>webkitURL</code> (e.g. Android <4.4).
**Params**
- url `string`
<a name="blobToBinaryString"></a>
###blobToBinaryString(blob)
Convert a <code>Blob</code> to a binary string. Returns a Promise.
**Params**
- blob `Blob`
**Returns**: `Promise` - Promise that resolves with the binary string
<a name="base64StringToBlob"></a>
###base64StringToBlob(base64, type)
Convert a base64-encoded string to a <code>Blob</code>. Returns a Promise.
**Params**
- base64 `string`
- type `string` | `undefined` - the content type (optional)
**Returns**: `Promise` - Promise that resolves with the <code>Blob</code>
<a name="binaryStringToBlob"></a>
###binaryStringToBlob(binary, type)
Convert a binary string to a <code>Blob</code>. Returns a Promise.
**Params**
- binary `string`
- type `string` | `undefined` - the content type (optional)
**Returns**: `Promise` - Promise that resolves with the <code>Blob</code>
<a name="blobToBase64String"></a>
###blobToBase64String(blob)
Convert a <code>Blob</code> to a binary string. Returns a Promise.
**Params**
- blob `Blob`
**Returns**: `Promise` - Promise that resolves with the binary string
<a name="dataURLToBlob"></a>
###dataURLToBlob(dataURL)
Convert a data URL string
(e.g. <code>'data:image/png;base64,iVBORw0KG...'</code>)
to a <code>Blob</code>. Returns a Promise.
**Params**
- dataURL `string`
**Returns**: `Promise` - Promise that resolves with the <code>Blob</code>
<a name="imgSrcToDataURL"></a>
###imgSrcToDataURL(src, type)
Convert an image's <code>src</code> URL to a data URL by loading the image and painting
it to a <code>canvas</code>. Returns a Promise.
<p/>Note: this will coerce the image to the desired content type, and it
will only paint the first frame of an animated GIF.
**Params**
- src `string`
- type `string` | `undefined` - the content type (optional, defaults to 'image/png')
**Returns**: `Promise` - Promise that resolves with the data URL string
<a name="canvasToBlob"></a>
###canvasToBlob(canvas, type)
Convert a <code>canvas</code> to a <code>Blob</code>. Returns a Promise.
**Params**
- canvas `string`
- type `string` | `undefined` - the content type (optional, defaults to 'image/png')
**Returns**: `Promise` - Promise that resolves with the <code>Blob</code>
<a name="imgSrcToBlob"></a>
###imgSrcToBlob(src, type)
Convert an image's <code>src</code> URL to a <code>Blob</code> by loading the image and painting
it to a <code>canvas</code>. Returns a Promise.
<p/>Note: this will coerce the image to the desired content type, and it
will only paint the first frame of an animated GIF.
**Params**
- src `string`
- type `string` | `undefined` - the content type (optional, defaults to 'image/png')
**Returns**: `Promise` - Promise that resolves with the <code>Blob</code>
<a name="arrayBufferToBlob"></a>
###arrayBufferToBlob(buffer, type)
Convert an <code>ArrayBuffer</code> to a <code>Blob</code>. Returns a Promise.
**Params**
- buffer `ArrayBuffer`
- type `string` | `undefined` - the content type (optional)
**Returns**: `Promise` - Promise that resolves with the <code>Blob</code>
<a name="blobToArrayBuffer"></a>
###blobToArrayBuffer(blob)
Convert a <code>Blob</code> to an <code>ArrayBuffer</code>. Returns a Promise.
**Params**
- blob `Blob`
**Returns**: `Promise` - Promise that resolves with the <code>ArrayBuffer</code>
Building the library
----
npm install
npm run build
Your plugin is now located at `dist/pouchdb.mypluginname.js` and `dist/pouchdb.mypluginname.min.js` and is ready for distribution.
To generate documentation:
npm run jsdoc
Testing
Testing the library
----
### In the browser
Run `npm run dev` and then point your favorite browser to [http://127.0.0.1:8001/test/index.html](http://127.0.0.1:8001/test/index.html).

263
index.js
View File

@ -1,26 +1,23 @@
'use strict';
var utils = require('./utils');
var blob = require('blob');
/* jshint -W079 */
var Blob = require('blob');
var Promise = utils.Promise;
function createBlob(parts, opts) {
opts = opts || {};
if (typeof opts === 'string') {
opts = {type: opts}; // do you a solid here
}
return new blob(parts, opts);
}
//
// PRIVATE
//
// From http://stackoverflow.com/questions/14967647/ (continues on next line)
// encode-decode-image-with-base64-breaks-image (2013-04-21)
function binaryStringToArrayBuffer(bin) {
var length = bin.length;
function binaryStringToArrayBuffer(binary) {
var length = binary.length;
var buf = new ArrayBuffer(length);
var arr = new Uint8Array(buf);
var i = -1;
while (++i < length) {
arr[i] = bin.charCodeAt(i);
arr[i] = binary.charCodeAt(i);
}
return buf;
}
@ -39,46 +36,8 @@ function arrayBufferToBinaryString(buffer) {
return binary;
}
// shim for browsers that don't support it
function blobToBinaryString(blob) {
return new Promise(function (resolve, reject) {
var reader = new FileReader();
var hasBinaryString = typeof reader.readAsBinaryString === 'function';
reader.onloadend = function (e) {
var result = e.target.result || '';
if (hasBinaryString) {
return resolve(result);
}
resolve(arrayBufferToBinaryString(result));
};
reader.onerror = reject;
if (hasBinaryString) {
reader.readAsBinaryString(blob);
} else {
reader.readAsArrayBuffer(blob);
}
});
}
function base64StringToBlob(base64, type) {
return Promise.resolve().then(function () {
var parts = [binaryStringToArrayBuffer(atob(base64))];
return type ? createBlob(parts, {type: type}) : createBlob(parts);
});
}
function binaryStringToBlob(binary, type) {
return Promise.resolve().then(function () {
return base64StringToBlob(btoa(binary), type);
});
}
function blobToBase64String(blob) {
return blobToBinaryString(blob).then(function (binary) {
return btoa(binary);
});
}
// doesn't download the image more than once, because
// browsers aren't dumb. uses the cache
function loadImage(src) {
return new Promise(function (resolve, reject) {
var img = new Image();
@ -91,25 +50,6 @@ function loadImage(src) {
});
}
function dataURLToBlob(dataURL) {
return Promise.resolve().then(function () {
var type = dataURL.match(/data:([^;]+)/)[1];
var base64 = dataURL.replace(/^[^,]+,/, '');
return createBlob([binaryStringToArrayBuffer(atob(base64))], {type: type});
});
}
function createObjectURL(blob) {
var compatURL = window.URL || window.webkitURL;
return compatURL.createObjectURL(blob);
}
function revokeObjectURL(url) {
var compatURL = window.URL || window.webkitURL;
return compatURL.revokeObjectURL(url);
}
function imgToCanvas(img) {
var canvas = document.createElement('canvas');
@ -128,6 +68,141 @@ function imgToCanvas(img) {
return canvas;
}
//
// PUBLIC
//
/**
* Shim for
* [new Blob()]{@link https://developer.mozilla.org/en-US/docs/Web/API/Blob.Blob}
* to support
* [older browsers that use the deprecated <code>BlobBuilder</code> API]{@link http://caniuse.com/blob}.
*
* @param {Array} parts - content of the <code>Blob</code>
* @param {Object} options - usually just <code>{type: myContentType}</code>
* @returns {Blob}
*/
function createBlob(parts, options) {
options = options || {};
if (typeof options === 'string') {
options = {type: options}; // do you a solid here
}
return new Blob(parts, options);
}
/**
* Shim for
* [URL.createObjectURL()]{@link https://developer.mozilla.org/en-US/docs/Web/API/URL.createObjectURL}
* to support browsers that only have the prefixed
* <code>webkitURL</code> (e.g. Android <4.4).
* @param {Blob} blob
* @returns {string} url
*/
function createObjectURL(blob) {
return (window.URL || window.webkitURL).createObjectURL(blob);
}
/**
* Shim for
* [URL.revokeObjectURL()]{@link https://developer.mozilla.org/en-US/docs/Web/API/URL.revokeObjectURL}
* to support browsers that only have the prefixed
* <code>webkitURL</code> (e.g. Android <4.4).
* @param {string} url
*/
function revokeObjectURL(url) {
return (window.URL || window.webkitURL).revokeObjectURL(url);
}
/**
* Convert a <code>Blob</code> to a binary string. Returns a Promise.
*
* @param {Blob} blob
* @returns {Promise} Promise that resolves with the binary string
*/
function blobToBinaryString(blob) {
return new Promise(function (resolve, reject) {
var reader = new FileReader();
var hasBinaryString = typeof reader.readAsBinaryString === 'function';
reader.onloadend = function (e) {
var result = e.target.result || '';
if (hasBinaryString) {
return resolve(result);
}
resolve(arrayBufferToBinaryString(result));
};
reader.onerror = reject;
if (hasBinaryString) {
reader.readAsBinaryString(blob);
} else {
reader.readAsArrayBuffer(blob);
}
});
}
/**
* Convert a base64-encoded string to a <code>Blob</code>. Returns a Promise.
* @param {string} base64
* @param {string|undefined} type - the content type (optional)
* @returns {Promise} Promise that resolves with the <code>Blob</code>
*/
function base64StringToBlob(base64, type) {
return Promise.resolve().then(function () {
var parts = [binaryStringToArrayBuffer(atob(base64))];
return type ? createBlob(parts, {type: type}) : createBlob(parts);
});
}
/**
* Convert a binary string to a <code>Blob</code>. Returns a Promise.
* @param {string} binary
* @param {string|undefined} type - the content type (optional)
* @returns {Promise} Promise that resolves with the <code>Blob</code>
*/
function binaryStringToBlob(binary, type) {
return Promise.resolve().then(function () {
return base64StringToBlob(btoa(binary), type);
});
}
/**
* Convert a <code>Blob</code> to a binary string. Returns a Promise.
* @param {Blob} blob
* @returns {Promise} Promise that resolves with the binary string
*/
function blobToBase64String(blob) {
return blobToBinaryString(blob).then(function (binary) {
return btoa(binary);
});
}
/**
* Convert a data URL string
* (e.g. <code>'data:image/png;base64,iVBORw0KG...'</code>)
* to a <code>Blob</code>. Returns a Promise.
* @param {string} dataURL
* @returns {Promise} Promise that resolves with the <code>Blob</code>
*/
function dataURLToBlob(dataURL) {
return Promise.resolve().then(function () {
var type = dataURL.match(/data:([^;]+)/)[1];
var base64 = dataURL.replace(/^[^,]+,/, '');
var buff = binaryStringToArrayBuffer(atob(base64));
return createBlob([buff], {type: type});
});
}
/**
* Convert an image's <code>src</code> URL to a data URL by loading the image and painting
* it to a <code>canvas</code>. Returns a Promise.
*
* <p/>Note: this will coerce the image to the desired content type, and it
* will only paint the first frame of an animated GIF.
*
* @param {string} src
* @param {string|undefined} type - the content type (optional, defaults to 'image/png')
* @returns {Promise} Promise that resolves with the data URL string
*/
function imgSrcToDataURL(src, type) {
type = type || 'image/png';
@ -138,12 +213,14 @@ function imgSrcToDataURL(src, type) {
});
}
function imgSrcToBlob(src, type) {
type = type || 'image/png';
return loadImage(src).then(function (img) {
return imgToCanvas(img);
}).then(function (canvas) {
/**
* Convert a <code>canvas</code> to a <code>Blob</code>. Returns a Promise.
* @param {string} canvas
* @param {string|undefined} type - the content type (optional, defaults to 'image/png')
* @returns {Promise} Promise that resolves with the <code>Blob</code>
*/
function canvasToBlob(canvas, type) {
return Promise.resolve().then(function () {
if (typeof canvas.toBlob === 'function') {
return new Promise(function (resolve) {
canvas.toBlob(resolve, type);
@ -153,12 +230,45 @@ function imgSrcToBlob(src, type) {
});
}
/**
* Convert an image's <code>src</code> URL to a <code>Blob</code> by loading the image and painting
* it to a <code>canvas</code>. Returns a Promise.
*
* <p/>Note: this will coerce the image to the desired content type, and it
* will only paint the first frame of an animated GIF.
*
* @param {string} src
* @param {string|undefined} type - the content type (optional, defaults to 'image/png')
* @returns {Promise} Promise that resolves with the <code>Blob</code>
*/
function imgSrcToBlob(src, type) {
type = type || 'image/png';
return loadImage(src).then(function (img) {
return imgToCanvas(img);
}).then(function (canvas) {
return canvasToBlob(canvas, type);
});
}
/**
* Convert an <code>ArrayBuffer</code> to a <code>Blob</code>. Returns a Promise.
*
* @param {ArrayBuffer} buffer
* @param {string|undefined} type - the content type (optional)
* @returns {Promise} Promise that resolves with the <code>Blob</code>
*/
function arrayBufferToBlob(buffer, type) {
return Promise.resolve().then(function () {
return createBlob([buffer], type);
});
}
/**
* Convert a <code>Blob</code> to an <code>ArrayBuffer</code>. Returns a Promise.
* @param {Blob} blob
* @returns {Promise} Promise that resolves with the <code>ArrayBuffer</code>
*/
function blobToArrayBuffer(blob) {
return blobToBinaryString(blob).then(function (binary) {
return binaryStringToArrayBuffer(binary);
@ -171,6 +281,7 @@ module.exports = {
revokeObjectURL : revokeObjectURL,
imgSrcToBlob : imgSrcToBlob,
imgSrcToDataURL : imgSrcToDataURL,
canvasToBlob : canvasToBlob,
dataURLToBlob : dataURLToBlob,
blobToBase64String : blobToBase64String,
base64StringToBlob : base64StringToBlob,

View File

@ -20,7 +20,7 @@
"url": "https://github.com/nolanlawson/blob-util/issues"
},
"scripts": {
"test-node": "istanbul test ./node_modules/mocha/bin/_mocha test/test.js",
"test-node": "echo 'node tests disabled'",
"test-browser": "./bin/test-browser.js",
"jshint": "jshint -c .jshintrc *.js test/test.js",
"test": "npm run jshint && ./bin/run-test.sh",
@ -28,7 +28,8 @@
"min": "uglifyjs dist/blob-util.js -mc > dist/blob-util.min.js",
"dev": "browserify -s blobUtil test/test.js > test/test-bundle.js && npm run dev-server",
"dev-server": "./bin/dev-server.js",
"coverage": "npm test --coverage && istanbul check-coverage --lines 100 --function 100 --statements 100 --branches 100"
"coverage": "npm test --coverage && istanbul check-coverage --lines 100 --function 100 --statements 100 --branches 100",
"jsdoc": "jsdoc2md --heading-depth 3 ./index.js > api.md"
},
"dependencies": {
"blob": "0.0.4",
@ -42,6 +43,8 @@
"chai-as-promised": "~4.1.0",
"http-server": "~0.5.5",
"istanbul": "^0.2.7",
"jsdoc": "^3.3.0-alpha10",
"jsdoc-to-markdown": "^0.5.9",
"jshint": "~2.3.0",
"mocha": "~1.18",
"phantomjs": "^1.9.7-5",