UNPKG

datalib

Version:

JavaScript utilites for loading, summarizing and working with data.

1,767 lines (1,521 loc) 165 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.dl = factory()); }(this, (function () { 'use strict'; var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; function createCommonjsModule(fn, module) { return module = { exports: {} }, fn(module, module.exports), module.exports; } function getCjsExportFromNamespace (n) { return n && n.default || n; } var util = createCommonjsModule(function (module) { var u = module.exports; // utility functions var FNAME = '__name__'; u.namedfunc = function(name, f) { return (f[FNAME] = name, f); }; u.name = function(f) { return f==null ? null : f[FNAME]; }; u.identity = function(x) { return x; }; u.true = u.namedfunc('true', function() { return true; }); u.false = u.namedfunc('false', function() { return false; }); u.duplicate = function(obj) { return JSON.parse(JSON.stringify(obj)); }; u.equal = function(a, b) { return JSON.stringify(a) === JSON.stringify(b); }; u.extend = function(obj) { for (var x, name, i=1, len=arguments.length; i<len; ++i) { x = arguments[i]; for (name in x) { obj[name] = x[name]; } } return obj; }; u.length = function(x) { return x != null && x.length != null ? x.length : null; }; u.keys = function(x) { var keys = [], k; for (k in x) keys.push(k); return keys; }; u.vals = function(x) { var vals = [], k; for (k in x) vals.push(x[k]); return vals; }; u.toMap = function(list, f) { return (f = u.$(f)) ? list.reduce(function(obj, x) { return (obj[f(x)] = 1, obj); }, {}) : list.reduce(function(obj, x) { return (obj[x] = 1, obj); }, {}); }; u.keystr = function(values) { // use to ensure consistent key generation across modules var n = values.length; if (!n) return ''; for (var s=String(values[0]), i=1; i<n; ++i) { s += '|' + String(values[i]); } return s; }; // type checking functions var toString = Object.prototype.toString; u.isObject = function(obj) { return obj === Object(obj); }; u.isFunction = function(obj) { return toString.call(obj) === '[object Function]'; }; u.isString = function(obj) { return typeof value === 'string' || toString.call(obj) === '[object String]'; }; u.isArray = Array.isArray || function(obj) { return toString.call(obj) === '[object Array]'; }; u.isNumber = function(obj) { return typeof obj === 'number' || toString.call(obj) === '[object Number]'; }; u.isBoolean = function(obj) { return obj === true || obj === false || toString.call(obj) == '[object Boolean]'; }; u.isDate = function(obj) { return toString.call(obj) === '[object Date]'; }; u.isValid = function(obj) { return obj != null && obj === obj; }; u.isBuffer = (typeof Buffer === 'function' && Buffer.isBuffer) || u.false; // type coercion functions u.number = function(s) { return s == null || s === '' ? null : +s; }; u.boolean = function(s) { return s == null || s === '' ? null : s==='false' ? false : !!s; }; // parse a date with optional d3.time-format format u.date = function(s, format) { var d = format ? format : Date; return s == null || s === '' ? null : d.parse(s); }; u.array = function(x) { return x != null ? (u.isArray(x) ? x : [x]) : []; }; u.str = function(x) { return u.isArray(x) ? '[' + x.map(u.str) + ']' : u.isObject(x) || u.isString(x) ? // Output valid JSON and JS source strings. // See http://timelessrepo.com/json-isnt-a-javascript-subset JSON.stringify(x).replace('\u2028','\\u2028').replace('\u2029', '\\u2029') : x; }; // data access functions var field_re = /\[(.*?)\]|[^.\[]+/g; u.field = function(f) { return String(f).match(field_re).map(function(d) { return d[0] !== '[' ? d : d[1] !== "'" && d[1] !== '"' ? d.slice(1, -1) : d.slice(2, -2).replace(/\\(["'])/g, '$1'); }); }; u.accessor = function(f) { /* jshint evil: true */ return f==null || u.isFunction(f) ? f : u.namedfunc(f, Function('x', 'return x[' + u.field(f).map(u.str).join('][') + '];')); }; // short-cut for accessor u.$ = u.accessor; u.mutator = function(f) { var s; return u.isString(f) && (s=u.field(f)).length > 1 ? function(x, v) { for (var i=0; i<s.length-1; ++i) x = x[s[i]]; x[s[i]] = v; } : function(x, v) { x[f] = v; }; }; u.$func = function(name, op) { return function(f) { f = u.$(f) || u.identity; var n = name + (u.name(f) ? '_'+u.name(f) : ''); return u.namedfunc(n, function(d) { return op(f(d)); }); }; }; u.$valid = u.$func('valid', u.isValid); u.$length = u.$func('length', u.length); u.$in = function(f, values) { f = u.$(f); var map = u.isArray(values) ? u.toMap(values) : values; return function(d) { return !!map[f(d)]; }; }; // comparison / sorting functions u.comparator = function(sort) { var sign = []; if (sort === undefined) sort = []; sort = u.array(sort).map(function(f) { var s = 1; if (f[0] === '-') { s = -1; f = f.slice(1); } else if (f[0] === '+') { s = +1; f = f.slice(1); } sign.push(s); return u.accessor(f); }); return function(a, b) { var i, n, f, c; for (i=0, n=sort.length; i<n; ++i) { f = sort[i]; c = u.cmp(f(a), f(b)); if (c) return c * sign[i]; } return 0; }; }; u.cmp = function(a, b) { return (a < b || a == null) && b != null ? -1 : (a > b || b == null) && a != null ? 1 : ((b = b instanceof Date ? +b : b), (a = a instanceof Date ? +a : a)) !== a && b === b ? -1 : b !== b && a === a ? 1 : 0; }; u.numcmp = function(a, b) { return a - b; }; u.stablesort = function(array, sortBy, keyFn) { var indices = array.reduce(function(idx, v, i) { return (idx[keyFn(v)] = i, idx); }, {}); array.sort(function(a, b) { var sa = sortBy(a), sb = sortBy(b); return sa < sb ? -1 : sa > sb ? 1 : (indices[keyFn(a)] - indices[keyFn(b)]); }); return array; }; // permutes an array using a Knuth shuffle u.permute = function(a) { var m = a.length, swap, i; while (m) { i = Math.floor(Math.random() * m--); swap = a[m]; a[m] = a[i]; a[i] = swap; } }; // string functions u.pad = function(s, length, pos, padchar) { padchar = padchar || " "; var d = length - s.length; if (d <= 0) return s; switch (pos) { case 'left': return strrep(d, padchar) + s; case 'middle': case 'center': return strrep(Math.floor(d/2), padchar) + s + strrep(Math.ceil(d/2), padchar); default: return s + strrep(d, padchar); } }; function strrep(n, str) { var s = "", i; for (i=0; i<n; ++i) s += str; return s; } u.truncate = function(s, length, pos, word, ellipsis) { var len = s.length; if (len <= length) return s; ellipsis = ellipsis !== undefined ? String(ellipsis) : '\u2026'; var l = Math.max(0, length - ellipsis.length); switch (pos) { case 'left': return ellipsis + (word ? truncateOnWord(s,l,1) : s.slice(len-l)); case 'middle': case 'center': var l1 = Math.ceil(l/2), l2 = Math.floor(l/2); return (word ? truncateOnWord(s,l1) : s.slice(0,l1)) + ellipsis + (word ? truncateOnWord(s,l2,1) : s.slice(len-l2)); default: return (word ? truncateOnWord(s,l) : s.slice(0,l)) + ellipsis; } }; function truncateOnWord(s, len, rev) { var cnt = 0, tok = s.split(truncate_word_re); if (rev) { s = (tok = tok.reverse()) .filter(function(w) { cnt += w.length; return cnt <= len; }) .reverse(); } else { s = tok.filter(function(w) { cnt += w.length; return cnt <= len; }); } return s.length ? s.join('').trim() : tok[0].slice(0, len); } var truncate_word_re = /([\u0009\u000A\u000B\u000C\u000D\u0020\u00A0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u2028\u2029\u3000\uFEFF])/; }); var name = "datalib"; var version = "1.9.3"; var description = "JavaScript utilites for loading, summarizing and working with data."; var keywords = [ "data", "table", "statistics", "parse", "csv", "tsv", "json", "utility" ]; var repository = { type: "git", url: "http://github.com/vega/datalib.git" }; var author = { name: "Jeffrey Heer", url: "http://idl.cs.washington.edu" }; var contributors = [ { name: "Michael Correll", url: "http://pages.cs.wisc.edu/~mcorrell/" }, { name: "Ryan Russell", url: "https://github.com/RussellSprouts" }, { name: "Matthew Conlen", url: "https://github.com/mathisonian" } ]; var license = "BSD-3-Clause"; var dependencies = { "d3-dsv": "0.1", "d3-format": "0.4", "d3-time": "0.1", "d3-time-format": "0.2", request: "^2.67.0", "sync-request": "^6.0.0", "topojson-client": "^3.0.0" }; var devDependencies = { chai: "^4.1.2", istanbul: "latest", jshint: "^2.9.5", mocha: "^5.2.0", rollup: "^0.62.0", "rollup-plugin-commonjs": "^9.1.3", "rollup-plugin-json": "^3.0.0", "rollup-plugin-node-resolve": "^3.3.0", "uglify-js": "^3.4.3" }; var main = "src/index.js"; var unpkg = "datalib.min.js"; var jsdelivr = "datalib.min.js"; var scripts = { deploy: "npm run test && scripts/deploy.sh", lint: "jshint src/", test: "npm run lint && TZ=America/Los_Angeles mocha --recursive test/", cover: "TZ=America/Los_Angeles istanbul cover _mocha -- --recursive test/", build: "rollup -c", postbuild: "uglifyjs datalib.js -c -m -o datalib.min.js" }; var browser = { buffer: false, fs: false, http: false, request: false, "sync-request": false, url: false }; var _package = { name: name, version: version, description: description, keywords: keywords, repository: repository, author: author, contributors: contributors, license: license, dependencies: dependencies, devDependencies: devDependencies, main: main, unpkg: unpkg, jsdelivr: jsdelivr, scripts: scripts, browser: browser }; var _package$1 = /*#__PURE__*/Object.freeze({ name: name, version: version, description: description, keywords: keywords, repository: repository, author: author, contributors: contributors, license: license, dependencies: dependencies, devDependencies: devDependencies, main: main, unpkg: unpkg, jsdelivr: jsdelivr, scripts: scripts, browser: browser, default: _package }); var require$$3 = {}; // Matches absolute URLs with optional protocol // https://... file://... //... var protocol_re = /^([A-Za-z]+:)?\/\//; // Special treatment in node.js for the file: protocol var fileProtocol = 'file://'; // Validate and cleanup URL to ensure that it is allowed to be accessed // Returns cleaned up URL, or false if access is not allowed function sanitizeUrl(opt) { var url = opt.url; if (!url && opt.file) { return fileProtocol + opt.file; } // In case this is a relative url (has no host), prepend opt.baseURL if (opt.baseURL && !protocol_re.test(url)) { if (!startsWith(url, '/') && opt.baseURL[opt.baseURL.length-1] !== '/') { url = '/' + url; // Ensure that there is a slash between the baseURL (e.g. hostname) and url } url = opt.baseURL + url; } // relative protocol, starts with '//' if (!load.useXHR && startsWith(url, '//')) { url = (opt.defaultProtocol || 'http') + ':' + url; } // If opt.domainWhiteList is set, only allows url, whose hostname // * Is the same as the origin (window.location.hostname) // * Equals one of the values in the whitelist // * Is a proper subdomain of one of the values in the whitelist if (opt.domainWhiteList) { var domain, origin; if (load.useXHR) { var a = document.createElement('a'); a.href = url; // From http://stackoverflow.com/questions/736513/how-do-i-parse-a-url-into-hostname-and-path-in-javascript // IE doesn't populate all link properties when setting .href with a relative URL, // however .href will return an absolute URL which then can be used on itself // to populate these additional fields. if (a.host === '') { a.href = a.href; } domain = a.hostname.toLowerCase(); origin = window.location.hostname; } else { // relative protocol is broken: https://github.com/defunctzombie/node-url/issues/5 var parts = require$$3.parse(url); domain = parts.hostname; origin = null; } if (origin !== domain) { var whiteListed = opt.domainWhiteList.some(function(d) { var idx = domain.length - d.length; return d === domain || (idx > 1 && domain[idx-1] === '.' && domain.lastIndexOf(d) === idx); }); if (!whiteListed) { throw 'URL is not whitelisted: ' + url; } } } return url; } function load(opt, callback) { return load.loader(opt, callback); } function loader(opt, callback) { var error = callback || function(e) { throw e; }, url; try { url = load.sanitizeUrl(opt); // enable override } catch (err) { error(err); return; } if (!url) { error('Invalid URL: ' + opt.url); } else if (load.useXHR) { // on client, use xhr return load.xhr(url, opt, callback); } else if (startsWith(url, fileProtocol)) { // on server, if url starts with 'file://', strip it and load from file return load.file(url.slice(fileProtocol.length), opt, callback); } else if (url.indexOf('://') < 0) { // TODO better protocol check? // on server, if no protocol assume file return load.file(url, opt, callback); } else { // for regular URLs on server return load.http(url, opt, callback); } } function xhrHasResponse(request) { var type = request.responseType; return type && type !== 'text' ? request.response : // null on error request.responseText; // '' on error } function xhr(url, opt, callback) { var async = !!callback; var request = new XMLHttpRequest(); // If IE does not support CORS, use XDomainRequest (copied from d3.xhr) if (typeof XDomainRequest !== 'undefined' && !('withCredentials' in request) && /^(http(s)?:)?\/\//.test(url)) request = new XDomainRequest(); function respond() { var status = request.status; if (!status && xhrHasResponse(request) || status >= 200 && status < 300 || status === 304) { callback(null, request.responseText); } else { callback(request, null); } } if (async) { if ('onload' in request) { request.onload = request.onerror = respond; } else { request.onreadystatechange = function() { if (request.readyState > 3) respond(); }; } } request.open('GET', url, async); /* istanbul ignore else */ if (request.setRequestHeader) { var headers = util.extend({}, load.headers, opt.headers); for (var name in headers) { request.setRequestHeader(name, headers[name]); } } request.send(); if (!async && xhrHasResponse(request)) { return request.responseText; } } function file(filename, opt, callback) { var fs = require$$3; if (!callback) { return fs.readFileSync(filename, 'utf8'); } fs.readFile(filename, callback); } function http(url, opt, callback) { var headers = util.extend({}, load.headers, opt.headers); var options = {url: url, encoding: null, gzip: true, headers: headers}; if (!callback) { return require$$3('GET', url, options).getBody(); } require$$3(options, function(error, response, body) { if (!error && response.statusCode === 200) { callback(null, body); } else { error = error || 'Load failed with response code ' + response.statusCode + '.'; callback(error, null); } }); } function startsWith(string, searchString) { return string == null ? false : string.lastIndexOf(searchString, 0) === 0; } // Allow these functions to be overriden by the user of the library load.loader = loader; load.sanitizeUrl = sanitizeUrl; load.xhr = xhr; load.file = file; load.http = http; // Default settings load.useXHR = (typeof XMLHttpRequest !== 'undefined'); load.headers = {}; var load_1 = load; var TYPES = '__types__'; var PARSERS = { boolean: util.boolean, integer: util.number, number: util.number, date: util.date, string: function(x) { return x == null || x === '' ? null : x + ''; } }; var TESTS = { boolean: function(x) { return x==='true' || x==='false' || util.isBoolean(x); }, integer: function(x) { return TESTS.number(x) && (x=+x) === ~~x; }, number: function(x) { return !isNaN(+x) && !util.isDate(x); }, date: function(x) { return !isNaN(Date.parse(x)); } }; function annotation(data, types) { if (!types) return data && data[TYPES] || null; data[TYPES] = types; } function fieldNames(datum) { return util.keys(datum); } function bracket(fieldName) { return '[' + fieldName + ']'; } function type(values, f) { values = util.array(values); f = util.$(f); var v, i, n; // if data array has type annotations, use them if (values[TYPES]) { v = f(values[TYPES]); if (util.isString(v)) return v; } for (i=0, n=values.length; !util.isValid(v) && i<n; ++i) { v = f ? f(values[i]) : values[i]; } return util.isDate(v) ? 'date' : util.isNumber(v) ? 'number' : util.isBoolean(v) ? 'boolean' : util.isString(v) ? 'string' : null; } function typeAll(data, fields) { if (!data.length) return; var get = fields ? util.identity : (fields = fieldNames(data[0]), bracket); return fields.reduce(function(types, f) { return (types[f] = type(data, get(f)), types); }, {}); } function infer(values, f, ignore) { values = util.array(values); f = util.$(f); var i, j, v; // types to test for, in precedence order var types = ['boolean', 'integer', 'number', 'date']; for (i=0; i<values.length; ++i) { // get next value to test v = f ? f(values[i]) : values[i]; // test value against remaining types for (j=0; j<types.length; ++j) { if ((!ignore || !ignore.test(v)) && util.isValid(v) && !TESTS[types[j]](v)) { types.splice(j, 1); j -= 1; } } // if no types left, return 'string' if (types.length === 0) return 'string'; } return types[0]; } function inferAll(data, fields, ignore) { var get = fields ? util.identity : (fields = fieldNames(data[0]), bracket); return fields.reduce(function(types, f) { types[f] = infer(data, get(f), ignore); return types; }, {}); } type.annotation = annotation; type.all = typeAll; type.infer = infer; type.inferAll = inferAll; type.parsers = PARSERS; var type_1 = type; var d3Dsv = createCommonjsModule(function (module, exports) { (function (global, factory) { factory(exports); }(commonjsGlobal, function (exports) { function dsv(delimiter) { return new Dsv(delimiter); } function objectConverter(columns) { return new Function("d", "return {" + columns.map(function(name, i) { return JSON.stringify(name) + ": d[" + i + "]"; }).join(",") + "}"); } function customConverter(columns, f) { var object = objectConverter(columns); return function(row, i) { return f(object(row), i, columns); }; } // Compute unique columns in order of discovery. function inferColumns(rows) { var columnSet = Object.create(null), columns = []; rows.forEach(function(row) { for (var column in row) { if (!(column in columnSet)) { columns.push(columnSet[column] = column); } } }); return columns; } function Dsv(delimiter) { var reFormat = new RegExp("[\"" + delimiter + "\n]"), delimiterCode = delimiter.charCodeAt(0); this.parse = function(text, f) { var convert, columns, rows = this.parseRows(text, function(row, i) { if (convert) return convert(row, i - 1); columns = row, convert = f ? customConverter(row, f) : objectConverter(row); }); rows.columns = columns; return rows; }; this.parseRows = function(text, f) { var EOL = {}, // sentinel value for end-of-line EOF = {}, // sentinel value for end-of-file rows = [], // output rows N = text.length, I = 0, // current character index n = 0, // the current line number t, // the current token eol; // is the current token followed by EOL? function token() { if (I >= N) return EOF; // special case: end of file if (eol) return eol = false, EOL; // special case: end of line // special case: quotes var j = I, c; if (text.charCodeAt(j) === 34) { var i = j; while (i++ < N) { if (text.charCodeAt(i) === 34) { if (text.charCodeAt(i + 1) !== 34) break; ++i; } } I = i + 2; c = text.charCodeAt(i + 1); if (c === 13) { eol = true; if (text.charCodeAt(i + 2) === 10) ++I; } else if (c === 10) { eol = true; } return text.slice(j + 1, i).replace(/""/g, "\""); } // common case: find next delimiter or newline while (I < N) { var k = 1; c = text.charCodeAt(I++); if (c === 10) eol = true; // \n else if (c === 13) { eol = true; if (text.charCodeAt(I) === 10) ++I, ++k; } // \r|\r\n else if (c !== delimiterCode) continue; return text.slice(j, I - k); } // special case: last token before EOF return text.slice(j); } while ((t = token()) !== EOF) { var a = []; while (t !== EOL && t !== EOF) { a.push(t); t = token(); } if (f && (a = f(a, n++)) == null) continue; rows.push(a); } return rows; }; this.format = function(rows, columns) { if (columns == null) columns = inferColumns(rows); return [columns.map(formatValue).join(delimiter)].concat(rows.map(function(row) { return columns.map(function(column) { return formatValue(row[column]); }).join(delimiter); })).join("\n"); }; this.formatRows = function(rows) { return rows.map(formatRow).join("\n"); }; function formatRow(row) { return row.map(formatValue).join(delimiter); } function formatValue(text) { return reFormat.test(text) ? "\"" + text.replace(/\"/g, "\"\"") + "\"" : text; } } dsv.prototype = Dsv.prototype; var csv = dsv(","); var tsv = dsv("\t"); var version = "0.1.14"; exports.version = version; exports.dsv = dsv; exports.csv = csv; exports.tsv = tsv; })); }); function dsv(data, format) { if (data) { var h = format.header; data = (h ? h.join(format.delimiter) + '\n' : '') + data; } return d3Dsv.dsv(format.delimiter).parse(data); } dsv.delimiter = function(delim) { var fmt = {delimiter: delim}; return function(data, format) { return dsv(data, format ? util.extend(format, fmt) : fmt); }; }; var dsv_1 = dsv; var json = function(data, format) { var d = util.isObject(data) && !util.isBuffer(data) ? data : JSON.parse(data); if (format && format.property) { d = util.accessor(format.property)(d); } return d; }; function identity(x) { return x; } function transform(transform) { if (transform == null) return identity; var x0, y0, kx = transform.scale[0], ky = transform.scale[1], dx = transform.translate[0], dy = transform.translate[1]; return function(input, i) { if (!i) x0 = y0 = 0; var j = 2, n = input.length, output = new Array(n); output[0] = (x0 += input[0]) * kx + dx; output[1] = (y0 += input[1]) * ky + dy; while (j < n) output[j] = input[j], ++j; return output; }; } function bbox(topology) { var t = transform(topology.transform), key, x0 = Infinity, y0 = x0, x1 = -x0, y1 = -x0; function bboxPoint(p) { p = t(p); if (p[0] < x0) x0 = p[0]; if (p[0] > x1) x1 = p[0]; if (p[1] < y0) y0 = p[1]; if (p[1] > y1) y1 = p[1]; } function bboxGeometry(o) { switch (o.type) { case "GeometryCollection": o.geometries.forEach(bboxGeometry); break; case "Point": bboxPoint(o.coordinates); break; case "MultiPoint": o.coordinates.forEach(bboxPoint); break; } } topology.arcs.forEach(function(arc) { var i = -1, n = arc.length, p; while (++i < n) { p = t(arc[i], i); if (p[0] < x0) x0 = p[0]; if (p[0] > x1) x1 = p[0]; if (p[1] < y0) y0 = p[1]; if (p[1] > y1) y1 = p[1]; } }); for (key in topology.objects) { bboxGeometry(topology.objects[key]); } return [x0, y0, x1, y1]; } function reverse(array, n) { var t, j = array.length, i = j - n; while (i < --j) t = array[i], array[i++] = array[j], array[j] = t; } function feature(topology, o) { if (typeof o === "string") o = topology.objects[o]; return o.type === "GeometryCollection" ? {type: "FeatureCollection", features: o.geometries.map(function(o) { return feature$1(topology, o); })} : feature$1(topology, o); } function feature$1(topology, o) { var id = o.id, bbox = o.bbox, properties = o.properties == null ? {} : o.properties, geometry = object(topology, o); return id == null && bbox == null ? {type: "Feature", properties: properties, geometry: geometry} : bbox == null ? {type: "Feature", id: id, properties: properties, geometry: geometry} : {type: "Feature", id: id, bbox: bbox, properties: properties, geometry: geometry}; } function object(topology, o) { var transformPoint = transform(topology.transform), arcs = topology.arcs; function arc(i, points) { if (points.length) points.pop(); for (var a = arcs[i < 0 ? ~i : i], k = 0, n = a.length; k < n; ++k) { points.push(transformPoint(a[k], k)); } if (i < 0) reverse(points, n); } function point(p) { return transformPoint(p); } function line(arcs) { var points = []; for (var i = 0, n = arcs.length; i < n; ++i) arc(arcs[i], points); if (points.length < 2) points.push(points[0]); // This should never happen per the specification. return points; } function ring(arcs) { var points = line(arcs); while (points.length < 4) points.push(points[0]); // This may happen if an arc has only two points. return points; } function polygon(arcs) { return arcs.map(ring); } function geometry(o) { var type = o.type, coordinates; switch (type) { case "GeometryCollection": return {type: type, geometries: o.geometries.map(geometry)}; case "Point": coordinates = point(o.coordinates); break; case "MultiPoint": coordinates = o.coordinates.map(point); break; case "LineString": coordinates = line(o.arcs); break; case "MultiLineString": coordinates = o.arcs.map(line); break; case "Polygon": coordinates = polygon(o.arcs); break; case "MultiPolygon": coordinates = o.arcs.map(polygon); break; default: return null; } return {type: type, coordinates: coordinates}; } return geometry(o); } function stitch(topology, arcs) { var stitchedArcs = {}, fragmentByStart = {}, fragmentByEnd = {}, fragments = [], emptyIndex = -1; // Stitch empty arcs first, since they may be subsumed by other arcs. arcs.forEach(function(i, j) { var arc = topology.arcs[i < 0 ? ~i : i], t; if (arc.length < 3 && !arc[1][0] && !arc[1][1]) { t = arcs[++emptyIndex], arcs[emptyIndex] = i, arcs[j] = t; } }); arcs.forEach(function(i) { var e = ends(i), start = e[0], end = e[1], f, g; if (f = fragmentByEnd[start]) { delete fragmentByEnd[f.end]; f.push(i); f.end = end; if (g = fragmentByStart[end]) { delete fragmentByStart[g.start]; var fg = g === f ? f : f.concat(g); fragmentByStart[fg.start = f.start] = fragmentByEnd[fg.end = g.end] = fg; } else { fragmentByStart[f.start] = fragmentByEnd[f.end] = f; } } else if (f = fragmentByStart[end]) { delete fragmentByStart[f.start]; f.unshift(i); f.start = start; if (g = fragmentByEnd[start]) { delete fragmentByEnd[g.end]; var gf = g === f ? f : g.concat(f); fragmentByStart[gf.start = g.start] = fragmentByEnd[gf.end = f.end] = gf; } else { fragmentByStart[f.start] = fragmentByEnd[f.end] = f; } } else { f = [i]; fragmentByStart[f.start = start] = fragmentByEnd[f.end = end] = f; } }); function ends(i) { var arc = topology.arcs[i < 0 ? ~i : i], p0 = arc[0], p1; if (topology.transform) p1 = [0, 0], arc.forEach(function(dp) { p1[0] += dp[0], p1[1] += dp[1]; }); else p1 = arc[arc.length - 1]; return i < 0 ? [p1, p0] : [p0, p1]; } function flush(fragmentByEnd, fragmentByStart) { for (var k in fragmentByEnd) { var f = fragmentByEnd[k]; delete fragmentByStart[f.start]; delete f.start; delete f.end; f.forEach(function(i) { stitchedArcs[i < 0 ? ~i : i] = 1; }); fragments.push(f); } } flush(fragmentByEnd, fragmentByStart); flush(fragmentByStart, fragmentByEnd); arcs.forEach(function(i) { if (!stitchedArcs[i < 0 ? ~i : i]) fragments.push([i]); }); return fragments; } function mesh(topology) { return object(topology, meshArcs.apply(this, arguments)); } function meshArcs(topology, object$$1, filter) { var arcs, i, n; if (arguments.length > 1) arcs = extractArcs(topology, object$$1, filter); else for (i = 0, arcs = new Array(n = topology.arcs.length); i < n; ++i) arcs[i] = i; return {type: "MultiLineString", arcs: stitch(topology, arcs)}; } function extractArcs(topology, object$$1, filter) { var arcs = [], geomsByArc = [], geom; function extract0(i) { var j = i < 0 ? ~i : i; (geomsByArc[j] || (geomsByArc[j] = [])).push({i: i, g: geom}); } function extract1(arcs) { arcs.forEach(extract0); } function extract2(arcs) { arcs.forEach(extract1); } function extract3(arcs) { arcs.forEach(extract2); } function geometry(o) { switch (geom = o, o.type) { case "GeometryCollection": o.geometries.forEach(geometry); break; case "LineString": extract1(o.arcs); break; case "MultiLineString": case "Polygon": extract2(o.arcs); break; case "MultiPolygon": extract3(o.arcs); break; } } geometry(object$$1); geomsByArc.forEach(filter == null ? function(geoms) { arcs.push(geoms[0].i); } : function(geoms) { if (filter(geoms[0].g, geoms[geoms.length - 1].g)) arcs.push(geoms[0].i); }); return arcs; } function planarRingArea(ring) { var i = -1, n = ring.length, a, b = ring[n - 1], area = 0; while (++i < n) a = b, b = ring[i], area += a[0] * b[1] - a[1] * b[0]; return Math.abs(area); // Note: doubled area! } function merge(topology) { return object(topology, mergeArcs.apply(this, arguments)); } function mergeArcs(topology, objects) { var polygonsByArc = {}, polygons = [], groups = []; objects.forEach(geometry); function geometry(o) { switch (o.type) { case "GeometryCollection": o.geometries.forEach(geometry); break; case "Polygon": extract(o.arcs); break; case "MultiPolygon": o.arcs.forEach(extract); break; } } function extract(polygon) { polygon.forEach(function(ring) { ring.forEach(function(arc) { (polygonsByArc[arc = arc < 0 ? ~arc : arc] || (polygonsByArc[arc] = [])).push(polygon); }); }); polygons.push(polygon); } function area(ring) { return planarRingArea(object(topology, {type: "Polygon", arcs: [ring]}).coordinates[0]); } polygons.forEach(function(polygon) { if (!polygon._) { var group = [], neighbors = [polygon]; polygon._ = 1; groups.push(group); while (polygon = neighbors.pop()) { group.push(polygon); polygon.forEach(function(ring) { ring.forEach(function(arc) { polygonsByArc[arc < 0 ? ~arc : arc].forEach(function(polygon) { if (!polygon._) { polygon._ = 1; neighbors.push(polygon); } }); }); }); } } }); polygons.forEach(function(polygon) { delete polygon._; }); return { type: "MultiPolygon", arcs: groups.map(function(polygons) { var arcs = [], n; // Extract the exterior (unique) arcs. polygons.forEach(function(polygon) { polygon.forEach(function(ring) { ring.forEach(function(arc) { if (polygonsByArc[arc < 0 ? ~arc : arc].length < 2) { arcs.push(arc); } }); }); }); // Stitch the arcs into one or more rings. arcs = stitch(topology, arcs); // If more than one ring is returned, // at most one of these rings can be the exterior; // choose the one with the greatest absolute area. if ((n = arcs.length) > 1) { for (var i = 1, k = area(arcs[0]), ki, t; i < n; ++i) { if ((ki = area(arcs[i])) > k) { t = arcs[0], arcs[0] = arcs[i], arcs[i] = t, k = ki; } } } return arcs; }).filter(function(arcs) { return arcs.length > 0; }) }; } function bisect(a, x) { var lo = 0, hi = a.length; while (lo < hi) { var mid = lo + hi >>> 1; if (a[mid] < x) lo = mid + 1; else hi = mid; } return lo; } function neighbors(objects) { var indexesByArc = {}, // arc index -> array of object indexes neighbors = objects.map(function() { return []; }); function line(arcs, i) { arcs.forEach(function(a) { if (a < 0) a = ~a; var o = indexesByArc[a]; if (o) o.push(i); else indexesByArc[a] = [i]; }); } function polygon(arcs, i) { arcs.forEach(function(arc) { line(arc, i); }); } function geometry(o, i) { if (o.type === "GeometryCollection") o.geometries.forEach(function(o) { geometry(o, i); }); else if (o.type in geometryType) geometryType[o.type](o.arcs, i); } var geometryType = { LineString: line, MultiLineString: polygon, Polygon: polygon, MultiPolygon: function(arcs, i) { arcs.forEach(function(arc) { polygon(arc, i); }); } }; objects.forEach(geometry); for (var i in indexesByArc) { for (var indexes = indexesByArc[i], m = indexes.length, j = 0; j < m; ++j) { for (var k = j + 1; k < m; ++k) { var ij = indexes[j], ik = indexes[k], n; if ((n = neighbors[ij])[i = bisect(n, ik)] !== ik) n.splice(i, 0, ik); if ((n = neighbors[ik])[i = bisect(n, ij)] !== ij) n.splice(i, 0, ij); } } } return neighbors; } function untransform(transform) { if (transform == null) return identity; var x0, y0, kx = transform.scale[0], ky = transform.scale[1], dx = transform.translate[0], dy = transform.translate[1]; return function(input, i) { if (!i) x0 = y0 = 0; var j = 2, n = input.length, output = new Array(n), x1 = Math.round((input[0] - dx) / kx), y1 = Math.round((input[1] - dy) / ky); output[0] = x1 - x0, x0 = x1; output[1] = y1 - y0, y0 = y1; while (j < n) output[j] = input[j], ++j; return output; }; } function quantize(topology, transform) { if (topology.transform) throw new Error("already quantized"); if (!transform || !transform.scale) { if (!((n = Math.floor(transform)) >= 2)) throw new Error("n must be ≥2"); box = topology.bbox || bbox(topology); var x0 = box[0], y0 = box[1], x1 = box[2], y1 = box[3], n; transform = {scale: [x1 - x0 ? (x1 - x0) / (n - 1) : 1, y1 - y0 ? (y1 - y0) / (n - 1) : 1], translate: [x0, y0]}; } else { box = topology.bbox; } var t = untransform(transform), box, key, inputs = topology.objects, outputs = {}; function quantizePoint(point) { return t(point); } function quantizeGeometry(input) { var output; switch (input.type) { case "GeometryCollection": output = {type: "GeometryCollection", geometries: input.geometries.map(quantizeGeometry)}; break; case "Point": output = {type: "Point", coordinates: quantizePoint(input.coordinates)}; break; case "MultiPoint": output = {type: "MultiPoint", coordinates: input.coordinates.map(quantizePoint)}; break; default: return input; } if (input.id != null) output.id = input.id; if (input.bbox != null) output.bbox = input.bbox; if (input.properties != null) output.properties = input.properties; return output; } function quantizeArc(input) { var i = 0, j = 1, n = input.length, p, output = new Array(n); // pessimistic output[0] = t(input[0], 0); while (++i < n) if ((p = t(input[i], i))[0] || p[1]) output[j++] = p; // non-coincident points if (j === 1) output[j++] = [0, 0]; // an arc must have at least two points output.length = j; return output; } for (key in inputs) outputs[key] = quantizeGeometry(inputs[key]); return { type: "Topology", bbox: box, transform: transform, objects: outputs, arcs: topology.arcs.map(quantizeArc) }; } var src = /*#__PURE__*/Object.freeze({ bbox: bbox, feature: feature, mesh: mesh, meshArcs: meshArcs, merge: merge, mergeArcs: mergeArcs, neighbors: neighbors, quantize: quantize, transform: transform, untransform: untransform }); var reader = function(data, format) { var topojson = reader.topojson; if (topojson == null) { throw Error('TopoJSON library not loaded.'); } var t = json(data, format), obj; if (format && format.feature) { if ((obj = t.objects[format.feature])) { return topojson.feature(t, obj).features; } else { throw Error('Invalid TopoJSON object: ' + format.feature); } } else if (format && format.mesh) { if ((obj = t.objects[format.mesh])) { return [topojson.mesh(t, t.objects[format.mesh])]; } else { throw Error('Invalid TopoJSON object: ' + format.mesh); } } else { throw Error('Missing TopoJSON feature or mesh parameter.'); } }; reader.topojson = src; var topojson = reader; var treejson = function(tree, format) { return toTable(json(tree, format), format); }; function toTable(root, fields) { var childrenField = fields && fields.children || 'children', parentField = fields && fields.parent || 'parent', table = []; function visit(node, parent) { node[parentField] = parent; table.push(node); var children = node[childrenField]; if (children) { for (var i=0; i<children.length; ++i) { visit(children[i], node); } } } visit(root, null); return (table.root = root, table); } var formats = { json: json, topojson: topojson, treejson: treejson, dsv: dsv_1, csv: dsv_1.delimiter(','), tsv: dsv_1.delimiter('\t') }; var d3Time = createCommonjsModule(function (module, exports) { (function (global, factory) { factory(exports); }(commonjsGlobal, function (exports) { var t0 = new Date; var t1 = new Date; function newInterval(floori, offseti, count, field) { function interval(date) { return floori(date = new Date(+date)), date; } interval.floor = interval; interval.round = function(date) { var d0 = new Date(+date), d1 = new Date(date - 1); floori(d0), floori(d1), offseti(d1, 1); return date - d0 < d1 - date ? d0 : d1; }; interval.ceil = function(date) { return floori(date = new Date(date - 1)), offseti(date, 1), date; }; interval.offset = function(date, step) { return offseti(date = new Date(+date), step == null ? 1 : Math.floor(step)), date; }; interval.range = function(start, stop, step) { var range = []; start = new Date(start - 1); stop = new Date(+stop); step = step == null ? 1 : Math.floor(step); if (!(start < stop) || !(step > 0)) return range; // also handles Invalid Date offseti(start, 1), floori(start); if (start < stop) range.push(new Date(+start)); while (offseti(start, step), floori(start), start < stop) range.push(new Date(+start)); return range; }; interval.filter = function(test) { return newInterval(function(date) { while (floori(date), !test(date)) date.setTime(date - 1); }, function(date, step) { while (--step >= 0) while (offseti(date, 1), !test(date)); }); }; if (count) { interval.count = function(start, end) { t0.setTime(+start), t1.setTime(+end); floori(t0), floori(t1); return Math.floor(count(t0, t1)); }; interval.every = function(step) { step = Math.floor(step); return !isFinite(step) || !(step > 0) ? null : !(step > 1) ? interval : interval.filter(field ? function(d) { return field(d) % step === 0; } : function(d) { return interval.count(0, d) % step === 0; }); }; } return interval; } var millisecond = newInterval(function() { // noop }, function(date, step) { date.setTime(+date + step); }, function(start, end) { return end - start; }); // An optimized implementation for this simple case. millisecond.every = function(k) { k = Math.floor(k); if (!isFinite(k) || !(k > 0)) return null; if (!(k > 1)) return millisecond; return newInterval(function(date) { date.setTime(Math.floor(date / k) * k); }, function(date, step) { date.setTime(+date + step * k); }, function(start, end) { return (end - start) / k; }); }; var second = newInterval(function(date) { date.setMilliseconds(0); }, function(date, step) { date.setTime(+date + step * 1e3); }, function(start, end) { return (end - start) / 1e3; }, function(date) { return date.getSeconds(); }); var minute = newInterval(function(date) { date.setSeconds(0, 0); }, function(date, step) { date.setTime(+date + step * 6e4); }, function(start, end) { return (end - start) / 6e4; }, function(date) { return date.getMinutes(); }); var hour = newInterval(function(date) { date.setMinutes(0, 0, 0); }, function(date, step) { date.setTime(+date + step * 36e5); }, function(start, end) { return (end - start) / 36e5; }, function(date) { return date.getHours(); }); var day = newInterval(function(date) { date.setHours(0, 0, 0, 0); }, function(date, step) { date.setDate(date.getDate() + step); }, function(start, end) { return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * 6e4) / 864e5; }, function(date) { return date.getDate() - 1; }); function weekday(i) { return newInterval(function(date) { date.setHours(0, 0, 0, 0); date.setDate(date.getDate() - (date.getDay() + 7 - i) % 7); }, function(date, step) { date.setDate(date.getDate() + step * 7); }, function(start, end) { return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * 6e4) / 6048e5; }); } var sunday = weekday(0); var monday = weekday(1); var tuesday = weekday(2); var wednesday = weekday(3); var thursday = weekday(4); var friday = weekday(5); var saturday = weekday(6); var month = newInterval(function(date) { date.setHours(0, 0, 0, 0); date.setDate(1); }, function(date, step) { date.setMonth(date.getMonth() + step); }, function(start, end) { return end.getMonth() - start.getMonth() + (end.getFullYear() - start.getFullYear()) * 12; }, function(date) { return date.getMonth(); }); var year = newInterval(function(date) { date.setHours(0, 0, 0, 0); date.setMonth(0, 1); }, function(date, step) { date.setFullYear(date.getFullYear() + step); }, function(start, end) { return end.getFullYear() - start.getFullYear(); }, function(date) { return date.getFullYear(); }); var utcSecond = newInterval(function(date) { date.setUTCMilliseconds(0); }, function(date, step) { date.setTime(+date + step * 1e3); }, function(start, end) { return (end - start) / 1e3; }, function(date) { return date.getUTCSeconds(); }); var utcMinute = newInterval(function(date) { date.setUTCSeconds(0, 0); }, function(date, step) { date.setTime(+date + step * 6e4); }, function(start, end) { return (end - start) / 6e4; }, function(date) { return date.getUTCMinutes(); }); var utcHour = newInterval(function(date) { date.setUTCMinutes(0, 0, 0); }, function(date, step) { date.setTime(+date + step * 36e5); }, function(start, end) { return (end - start) / 36e5; }, function(date) { return date.getUTCHours(); }); var utcDay = newInterval(function(date) { date.setUTCHours(0, 0, 0, 0); }, function(date, step) { date.setUTCDate(date.getUTCDate() + step); }, function(start, end) { return (end - start) / 864e5; }, function(date) { return date.getUTCDate() - 1; }); function utcWeekday(i) { return newInterval(function(date) { date.setUTCHours(0, 0, 0, 0); date.setUTCDate(date.getUTCDate() - (date.getUTCDay() + 7 - i) % 7); }, function(date, step) { date.setUTCDate(date.getUTCDate() + step * 7); }, function(start, end) { return (end - start) / 6048e5; }); } var utcSunday = utcWeekday(0); var utcMonday = utcWeekday(1); var utcTuesday = utcWeekday(2); var utcWednesday = utcWeekday(3); var utcThursday = utcWeekday(4); var utcFriday = utcWeekday(5); var utcSaturday = utcWeekday(6); var utcMonth = newInterval(function(date) { date.setUTCHours(0, 0, 0, 0); date.setUTCDate(1); }, function(date, step) { date.setUTCMonth(date.getUTCMonth() + step); }, function(start, end) { return end.getUTCMonth() - start.getUTCMonth() + (end.getUTCFullYear() - start.getUTCFullYear()) * 12; }, function(date) { return date.getUTCMonth(); }); var utcYear = newInterval(function(date) { date.setUTCHours(0, 0, 0, 0); date.setUTCMonth(0, 1); }, function(date, step) { date.setUTCFullYear(date.getUTCFullYear() + step); }, function(start, end) { return end.getUTCFullYear() - start.getUTCFullYear(); }, function(date) { return date.getUTCFullYear(); }); var milliseconds = millisecond.range; var seconds = second.range; var minutes = minute.range; var hours = hour.range; var days = day.range; var sundays = sunday.range; var mondays = monday.range; var tuesdays = tuesday.range; var wednesdays = wednesday.range; var thursdays = thursday.range; var fridays = friday.range; var saturdays = saturday.range; var weeks = sunday.range; var months = month.range; var years = year.range; var utcMillisecond = millisecond; var utcMilliseconds = milliseconds; var utcSeconds = utcSecond.range; var utcMinutes = utcMinute.range; var utcHours = utcHour.range; var utcDays = utcDay.range; var utcSundays = utcSunday.range; var utcMondays = utcMonday.range; var utcTuesdays = utcTuesday.range; var utcWednesdays = utcWednesday.range; var utcThursdays = utcThursday.range; var utcFridays = utcFriday.range; var utcSaturdays = utcSaturday.range; var utcWeeks = utcSunday.range; var utcMonths = utcMonth.range; var utcYears = utcYear.range; var version = "0.1.1"; exports.version = version; exports.milliseconds = milliseconds; exports.seconds = seconds; exports.minutes = minutes; exports.hours = hours; exports.days = days; exports.sundays = sundays; exports.mondays = mondays; exports.tuesdays = tuesdays; exports.wednesdays = wednesdays; exports.thursdays = thursdays; exports.fridays = fridays; exports.saturdays = saturdays; exports.weeks = weeks; exports.months = months; exports.years = years; exports.utcMillisecond = utcMillisecond; exports.utcMilliseconds = utcMilliseconds; exports.utcSeconds = utcSeconds; exports.utcMinutes = utcMinutes; exports.utcHours = utcHours; exports.utcDays = utcDays; exports.utcSundays = utcSundays; exports.utcMondays = utcMondays; exports.utcTuesdays = utcTuesdays; exports.utcWednesdays = utcWednesdays; exports.utcThursdays = utcThursdays; exports.utcFridays = utcFridays;