artoo-js
Version:
The client-side scraping companion.
295 lines (242 loc) • 7.43 kB
JavaScript
;(function(undefined) {
'use strict';
/**
* artoo save methods
* ===================
*
* Some helpers to save data to a file that will be downloaded by the
* browser. Works mainly with chrome for the time being.
*
*/
var _root = this,
helpers = artoo.helpers;
// Polyfills
var URL = _root.URL || _root.webkitURL || _root;
// Utilities
function selectorOuterHTML($sel) {
return ($sel[0].documentElement && $sel[0].documentElement.outerHTML) ||
$sel[0].outerHTML;
}
function filenamePolymorphism(params) {
return (typeof params === 'string') ? {filename: params} : params || {};
}
// Main abstraction
function Saver() {
var _saver;
// Properties
this.defaultFilename = 'artoo_data';
this.defaultEncoding = 'utf-8';
this.xmlns = 'http://www.w3.org/1999/xhtml';
this.mimeShortcuts = {
csv: 'text/csv',
tsv: 'text/tab-separated-values',
json: 'application/json',
txt: 'text/plain',
html: 'text/html',
yaml: 'text/yaml'
};
// Methods
this.createBlob = function(data, mime, encoding) {
mime = this.mimeShortcuts[mime] || mime || this.defaultMime;
return new Blob(
[data],
{type: mime + ';charset=' + encoding || this.defaultEncoding}
);
};
this.createBlobFromDataURL = function(url) {
var byteString = atob(url.split(',')[1]),
ba = new Uint8Array(byteString.length),
i,
l;
for (i = 0, l = byteString.length; i < l; i++)
ba[i] = byteString.charCodeAt(i);
return new Blob([ba.buffer], {
type: url.split(',')[0].split(':')[1].split(';')[0]
});
};
this.blobURL = function(blob) {
var oURL = URL.createObjectURL(blob);
return oURL;
};
this.saveResource = function(href, params) {
var a = document.createElementNS(this.xmlns, 'a');
a.href = href;
a.setAttribute('download', params.filename || '');
// Firefox needs the link attached to the page's DOM
if ('document' in _root)
document.body.appendChild(a);
a.click();
if ('document' in _root)
document.body.removeChild(a);
a = null;
// Revoking the object URL if we want to
if (params.revoke)
setTimeout(function() {
URL.revokeObjectURL(href);
});
};
// Main interface
this.saveData = function(data, params) {
params = params || {};
// Creating the blob
var blob = this.createBlob(data, params.mime, params.encoding);
// Saving the blob
this.saveResource(
this.blobURL(blob),
{
filename: params.filename || this.defaultFilename,
revoke: params.revoke || true
}
);
};
this.saveDataURL = function(url, params) {
params = params || {};
// Creating the blob
var blob = this.createBlobFromDataURL(url);
// Saving the blob
this.saveResource(
blob,
{filename: params.filename || this.defaultFilename}
);
};
}
var _saver = new Saver();
// Exporting
artoo.save = function(data, params) {
_saver.saveData(data, filenamePolymorphism(params));
};
artoo.saveJson = function(data, params) {
params = filenamePolymorphism(params);
// Enforcing json
if (typeof data !== 'string') {
if (params.pretty || params.indent)
data = JSON.stringify(data, undefined, params.indent || 2);
else
data = JSON.stringify(data);
}
else {
if (params.pretty || params.indent)
data = JSON.stringify(JSON.parse(data), undefined, params.indent || 2);
}
// Extending params
artoo.save(
data,
helpers.extend(params, {filename: 'data.json', mime: 'json'})
);
};
artoo.savePrettyJson = function(data, params) {
params = filenamePolymorphism(params);
artoo.saveJson(data, helpers.extend(params, {pretty: true}));
};
artoo.saveYaml = function(data, params) {
params = filenamePolymorphism(params);
artoo.save(
artoo.writers.yaml(data),
helpers.extend(params, {filename: 'data.yml', mime: 'yaml'})
);
};
artoo.saveCsv = function(data, params) {
params = filenamePolymorphism(params);
data = (typeof data !== 'string') ?
artoo.writers.csv(data, params) :
data;
artoo.save(
data,
helpers.extend(params, {mime: 'csv', filename: 'data.csv'})
);
};
artoo.saveTsv = function(data, params) {
artoo.saveCsv(
data,
helpers.extend(filenamePolymorphism(params), {
mime: 'tsv',
delimiter: '\t',
filename: 'data.tsv'
})
);
};
artoo.saveXml = function(data, params) {
params = filenamePolymorphism(params);
var s = (helpers.isSelector(data) && selectorOuterHTML(data)) ||
(helpers.isDocument(data) && data.documentElement.outerHTML) ||
data,
type = params.type || 'xml',
header = '';
// Determining doctype
if (type === 'html' && helpers.isDocument(data)) {
var dt = data.doctype;
if (dt)
header = '<!DOCTYPE ' + (dt.name || 'html') +
(dt.publicId ? ' PUBLIC "' + dt.publicId + '"' : '') +
(dt.systemId ? ' "' + dt.systemId + '"' : '') + '>\n';
}
else if (type === 'xml' || type === 'svg') {
if (!~s.search(/<\?xml/))
header = '<?xml version="1.0" encoding="' +
(params.encoding || 'utf-8') +
'" standalone="yes"?>\n';
}
if (type === 'svg') {
header += '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" ' +
'"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n';
}
artoo.save(
header + s,
helpers.extend(
params,
{mime: 'html', filename: 'document.xml'})
);
};
artoo.saveHtml = function(data, params) {
artoo.saveXml(
data,
helpers.extend(
filenamePolymorphism(params),
{filename: 'document.html', type: 'html'}
)
);
};
artoo.savePageHtml = function(params) {
artoo.saveHtml(
document,
helpers.extend(filenamePolymorphism(params), {filename: 'page.html'})
);
};
artoo.saveSvg = function(sel, params) {
params = filenamePolymorphism(params);
var $sel = artoo.$(sel);
if (!$sel.is('svg'))
throw Error('artoo.saveSvg: selector is not svg.');
artoo.saveXml(
$sel,
helpers.extend(params, {filename: 'drawing.svg', type: 'svg'})
);
};
artoo.saveStore = function(params) {
params = filenamePolymorphism(params);
artoo.savePrettyJson(
artoo.store.get(params.key),
helpers.extend(params, {filename: 'store.json'})
);
};
artoo.saveResource = function(url, params) {
_saver.saveResource(url, filenamePolymorphism(params));
};
artoo.saveImage = function(sel, params) {
params = filenamePolymorphism(params);
var $sel = artoo.$(sel);
if (!$sel.is('img') && !$sel.attr('src'))
throw Error('artoo.saveImage: selector is not an image.');
var ext = helpers.getExtension($sel.attr('src')),
alt = $sel.attr('alt');
artoo.saveResource(
$sel.attr('src'),
helpers.extend(
params,
{
filename: alt ? alt + (ext ? '.' + ext : '') : false
}
)
);
};
}).call(this);