├── .gitignore ├── lib ├── raw.js ├── csv.js └── geojson.js ├── readme.md ├── package.json └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /lib/raw.js: -------------------------------------------------------------------------------- 1 | var streamToBlobURL = require('stream-to-blob-url') 2 | 3 | module.exports = function (file, el, cb) { 4 | var elem = document.createElement('iframe') 5 | streamToBlobURL(file.createReadStream(), function (err, url) { 6 | if (err) return cb(err) 7 | elem.src = url 8 | elem.sandbox = 'allow-forms allow-scripts' 9 | el.appendChild(elem) 10 | return cb(null, elem) 11 | }) 12 | } 13 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # render-data 2 | 3 | Show a data stream in a browser. This automatically detects the extension, and displays the data intelligently, supporting video, audio, and images (thanks to [render-media](http://npmjs.com/package/render-media)). 4 | 5 | It will attempt to display filetypes intelligently, like .csv, .json, and .geojson! 6 | 7 | 8 | ### install 9 | 10 | ``` 11 | npm install render-data 12 | ``` 13 | 14 | ### usage 15 | 16 | ```js 17 | var data = require('render-data') 18 | var file = { 19 | name: 'stuff.R', 20 | createReadStream: function () { 21 | return fs.createReadStream('/path/to/my/data/and/stuff') 22 | } 23 | } 24 | data.render(file, elem, opts, function (err) { 25 | console.log('done rendering') 26 | }) 27 | ``` 28 | 29 | ### example 30 | 31 | Example in [yo-fs](http://github.com/karissa/yo-fs). 32 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "render-data", 3 | "version": "2.2.4", 4 | "description": "Automagically render data files in the browser, like render-media", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/karissa/render-data.git" 12 | }, 13 | "author": "Karissa McKelvey (http://karissamck.com/)", 14 | "license": "MIT", 15 | "bugs": { 16 | "url": "https://github.com/karissa/render-data/issues" 17 | }, 18 | "homepage": "https://github.com/karissa/render-data#readme", 19 | "dependencies": { 20 | "csv-parser": "^1.9.3", 21 | "geojson-stream": "0.0.1", 22 | "leaflet": "^0.7.7", 23 | "leaflet-default": "^1.0.0", 24 | "leaflet-geojson-stream": "0.0.0", 25 | "leaflet-stream": "^1.1.0", 26 | "pump": "^1.0.1", 27 | "render-media": "^2.0.2", 28 | "stream-to-blob-url": "^2.1.0" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var media = require('render-media') 3 | 4 | var raw = require('./lib/raw') 5 | var csv = require('./lib/csv') 6 | var geojson = (typeof window !== 'undefined') ? require('./lib/geojson') : null 7 | 8 | var exts = { 9 | '.csv': 'csv', 10 | '.tsv': 'csv', 11 | '.json': 'raw', 12 | '.tex': 'raw', 13 | '.bib': 'raw', 14 | '.R': 'raw', 15 | '.py': 'raw', 16 | '.geojson': 'geojson' 17 | } 18 | 19 | module.exports = { render: render, append: append } 20 | 21 | function render (entry, el, cb) { 22 | if (typeof el === 'string') el = document.querySelector(el) 23 | el.innerHTML = '' 24 | append(entry, el, cb) 25 | } 26 | 27 | function append (file, el, cb) { 28 | validateFile(file) 29 | if (typeof el === 'string') el = document.querySelector(el) 30 | if (!cb) cb = function () {} 31 | 32 | var filetype = exts[path.extname(file.name).toLowerCase()] 33 | if (filetype === 'csv') return csv(file, el, cb) 34 | if (filetype === 'geojson' && geojson) return geojson(file, el, cb) 35 | if (filetype === 'raw') return raw(file, el, cb) 36 | media.append(file, el, cb) 37 | } 38 | 39 | function validateFile (file) { 40 | if (file == null) { 41 | throw new Error('file cannot be null or undefined') 42 | } 43 | if (typeof file.name !== 'string') { 44 | throw new Error('missing or invalid file.name property') 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /lib/csv.js: -------------------------------------------------------------------------------- 1 | var csv = require('csv-parser') 2 | 3 | module.exports = function (file, el, cb) { 4 | if (!el) return callbackOnce(new Error('el is undefined')) 5 | 6 | var t = document.createElement('table') 7 | var more = document.createElement('a') 8 | more.innerText = 'load 10 more' 9 | more.onclick = function () { 10 | parser.resume() 11 | } 12 | more.href = 'javascript:void(0)' 13 | 14 | var stream = file.createReadStream() 15 | var parser = stream.pipe(csv()) 16 | var inc = 0 17 | var incrBy = 10 18 | parser.on('data', function (data) { 19 | var tr 20 | if (!inc++) { 21 | tr = document.createElement('tr') 22 | Object.keys(data).forEach(function (name) { 23 | var th = document.createElement('th') 24 | th.innerText = name 25 | tr.appendChild(th) 26 | }) 27 | t.appendChild(tr) 28 | } 29 | tr = document.createElement('tr') 30 | Object.keys(data).forEach(function (name) { 31 | var td = document.createElement('td') 32 | td.innerText = data[name] 33 | tr.appendChild(td) 34 | }) 35 | el.appendChild(t) 36 | t.appendChild(tr) 37 | if (inc % incrBy === 0) { 38 | el.appendChild(more) 39 | parser.pause() 40 | callbackOnce(null, t) 41 | } 42 | }) 43 | 44 | parser.on('error', function (err) { 45 | callbackOnce(err) 46 | }) 47 | 48 | parser.on('end', function () { 49 | if (inc >= incrBy) el.removeChild(more) 50 | else callbackOnce(null, t) 51 | }) 52 | 53 | function callbackOnce (err, elem) { 54 | cb(err, elem) 55 | cb = function () {} 56 | } 57 | return el 58 | } 59 | -------------------------------------------------------------------------------- /lib/geojson.js: -------------------------------------------------------------------------------- 1 | var pump = require('pump') 2 | var L = require('leaflet') 3 | var geoJsonStream = require('geojson-stream') 4 | var leafletStream = require('leaflet-stream') 5 | 6 | module.exports = function (file, el, opts, cb) { 7 | if ((typeof opts) === 'function') { 8 | cb = opts 9 | opts = {} 10 | } 11 | if (!opts) opts = {} 12 | var elem = document.createElement('div') 13 | elem.setAttribute('style','width:100%;height:500px;') 14 | el.appendChild(elem) 15 | 16 | var stream = leafletStream(leafletMap(elem, opts)) 17 | pump(file.createReadStream(), geoJsonStream.parse(), stream, function (err) { 18 | if (err) return cb(err) 19 | return cb(null, elem) 20 | }) 21 | } 22 | 23 | function leafletMap (mapEl, opts) { 24 | if (!opts) opts = {} 25 | opts.defaultStyle = opts.defaultStyle || true, 26 | opts.center = opts.center || [0, 0] 27 | opts.zoom = opts.zoom || 3 28 | 29 | if (opts.defaultStyle) { 30 | L.Icon.Default.imagePath = '//cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images' 31 | ensureStyle() 32 | } 33 | map = L.map(mapEl, opts) 34 | map.setView(opts.center, opts.zoom) 35 | 36 | if (opts.tiles !== false) { 37 | // add an OpenStreetMap tile layer 38 | L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', { 39 | attribution: '© OpenStreetMap contributors' 40 | }).addTo(map) 41 | } 42 | 43 | return map 44 | } 45 | 46 | function ensureStyle () { 47 | document.documentElement.style.height = '100%' 48 | document.body.style.height = '100%' 49 | document.body.style.margin = '0' 50 | 51 | var mapStyle = document.createElement('link') 52 | mapStyle.setAttribute('rel', 'stylesheet') 53 | mapStyle.setAttribute('href', '//cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/leaflet.css') 54 | document.body.appendChild(mapStyle) 55 | } 56 | --------------------------------------------------------------------------------