compassql
Version:
CompassQL visualization query language
1,410 lines (1,322 loc) • 362 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(global = global || self, factory(global.cql = {}));
}(this, function (exports) { 'use strict';
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
function __rest(s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0)
t[p[i]] = s[p[i]];
return t;
}
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : 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;
}
var clone_1 = createCommonjsModule(function (module) {
var clone = (function() {
function _instanceof(obj, type) {
return type != null && obj instanceof type;
}
var nativeMap;
try {
nativeMap = Map;
} catch(_) {
// maybe a reference error because no `Map`. Give it a dummy value that no
// value will ever be an instanceof.
nativeMap = function() {};
}
var nativeSet;
try {
nativeSet = Set;
} catch(_) {
nativeSet = function() {};
}
var nativePromise;
try {
nativePromise = Promise;
} catch(_) {
nativePromise = function() {};
}
/**
* Clones (copies) an Object using deep copying.
*
* This function supports circular references by default, but if you are certain
* there are no circular references in your object, you can save some CPU time
* by calling clone(obj, false).
*
* Caution: if `circular` is false and `parent` contains circular references,
* your program may enter an infinite loop and crash.
*
* @param `parent` - the object to be cloned
* @param `circular` - set to true if the object to be cloned may contain
* circular references. (optional - true by default)
* @param `depth` - set to a number if the object is only to be cloned to
* a particular depth. (optional - defaults to Infinity)
* @param `prototype` - sets the prototype to be used when cloning an object.
* (optional - defaults to parent prototype).
* @param `includeNonEnumerable` - set to true if the non-enumerable properties
* should be cloned as well. Non-enumerable properties on the prototype
* chain will be ignored. (optional - false by default)
*/
function clone(parent, circular, depth, prototype, includeNonEnumerable) {
if (typeof circular === 'object') {
depth = circular.depth;
prototype = circular.prototype;
includeNonEnumerable = circular.includeNonEnumerable;
circular = circular.circular;
}
// maintain two arrays for circular references, where corresponding parents
// and children have the same index
var allParents = [];
var allChildren = [];
var useBuffer = typeof Buffer != 'undefined';
if (typeof circular == 'undefined')
circular = true;
if (typeof depth == 'undefined')
depth = Infinity;
// recurse this function so we don't reset allParents and allChildren
function _clone(parent, depth) {
// cloning null always returns null
if (parent === null)
return null;
if (depth === 0)
return parent;
var child;
var proto;
if (typeof parent != 'object') {
return parent;
}
if (_instanceof(parent, nativeMap)) {
child = new nativeMap();
} else if (_instanceof(parent, nativeSet)) {
child = new nativeSet();
} else if (_instanceof(parent, nativePromise)) {
child = new nativePromise(function (resolve, reject) {
parent.then(function(value) {
resolve(_clone(value, depth - 1));
}, function(err) {
reject(_clone(err, depth - 1));
});
});
} else if (clone.__isArray(parent)) {
child = [];
} else if (clone.__isRegExp(parent)) {
child = new RegExp(parent.source, __getRegExpFlags(parent));
if (parent.lastIndex) child.lastIndex = parent.lastIndex;
} else if (clone.__isDate(parent)) {
child = new Date(parent.getTime());
} else if (useBuffer && Buffer.isBuffer(parent)) {
if (Buffer.allocUnsafe) {
// Node.js >= 4.5.0
child = Buffer.allocUnsafe(parent.length);
} else {
// Older Node.js versions
child = new Buffer(parent.length);
}
parent.copy(child);
return child;
} else if (_instanceof(parent, Error)) {
child = Object.create(parent);
} else {
if (typeof prototype == 'undefined') {
proto = Object.getPrototypeOf(parent);
child = Object.create(proto);
}
else {
child = Object.create(prototype);
proto = prototype;
}
}
if (circular) {
var index = allParents.indexOf(parent);
if (index != -1) {
return allChildren[index];
}
allParents.push(parent);
allChildren.push(child);
}
if (_instanceof(parent, nativeMap)) {
parent.forEach(function(value, key) {
var keyChild = _clone(key, depth - 1);
var valueChild = _clone(value, depth - 1);
child.set(keyChild, valueChild);
});
}
if (_instanceof(parent, nativeSet)) {
parent.forEach(function(value) {
var entryChild = _clone(value, depth - 1);
child.add(entryChild);
});
}
for (var i in parent) {
var attrs;
if (proto) {
attrs = Object.getOwnPropertyDescriptor(proto, i);
}
if (attrs && attrs.set == null) {
continue;
}
child[i] = _clone(parent[i], depth - 1);
}
if (Object.getOwnPropertySymbols) {
var symbols = Object.getOwnPropertySymbols(parent);
for (var i = 0; i < symbols.length; i++) {
// Don't need to worry about cloning a symbol because it is a primitive,
// like a number or string.
var symbol = symbols[i];
var descriptor = Object.getOwnPropertyDescriptor(parent, symbol);
if (descriptor && !descriptor.enumerable && !includeNonEnumerable) {
continue;
}
child[symbol] = _clone(parent[symbol], depth - 1);
if (!descriptor.enumerable) {
Object.defineProperty(child, symbol, {
enumerable: false
});
}
}
}
if (includeNonEnumerable) {
var allPropertyNames = Object.getOwnPropertyNames(parent);
for (var i = 0; i < allPropertyNames.length; i++) {
var propertyName = allPropertyNames[i];
var descriptor = Object.getOwnPropertyDescriptor(parent, propertyName);
if (descriptor && descriptor.enumerable) {
continue;
}
child[propertyName] = _clone(parent[propertyName], depth - 1);
Object.defineProperty(child, propertyName, {
enumerable: false
});
}
}
return child;
}
return _clone(parent, depth);
}
/**
* Simple flat clone using prototype, accepts only objects, usefull for property
* override on FLAT configuration object (no nested props).
*
* USE WITH CAUTION! This may not behave as you wish if you do not know how this
* works.
*/
clone.clonePrototype = function clonePrototype(parent) {
if (parent === null)
return null;
var c = function () {};
c.prototype = parent;
return new c();
};
// private utility functions
function __objToStr(o) {
return Object.prototype.toString.call(o);
}
clone.__objToStr = __objToStr;
function __isDate(o) {
return typeof o === 'object' && __objToStr(o) === '[object Date]';
}
clone.__isDate = __isDate;
function __isArray(o) {
return typeof o === 'object' && __objToStr(o) === '[object Array]';
}
clone.__isArray = __isArray;
function __isRegExp(o) {
return typeof o === 'object' && __objToStr(o) === '[object RegExp]';
}
clone.__isRegExp = __isRegExp;
function __getRegExpFlags(re) {
var flags = '';
if (re.global) flags += 'g';
if (re.ignoreCase) flags += 'i';
if (re.multiline) flags += 'm';
return flags;
}
clone.__getRegExpFlags = __getRegExpFlags;
return clone;
})();
if (module.exports) {
module.exports = clone;
}
});
var fastJsonStableStringify = function (data, opts) {
if (!opts) opts = {};
if (typeof opts === 'function') opts = { cmp: opts };
var cycles = (typeof opts.cycles === 'boolean') ? opts.cycles : false;
var cmp = opts.cmp && (function (f) {
return function (node) {
return function (a, b) {
var aobj = { key: a, value: node[a] };
var bobj = { key: b, value: node[b] };
return f(aobj, bobj);
};
};
})(opts.cmp);
var seen = [];
return (function stringify (node) {
if (node && node.toJSON && typeof node.toJSON === 'function') {
node = node.toJSON();
}
if (node === undefined) return;
if (typeof node == 'number') return isFinite(node) ? '' + node : 'null';
if (typeof node !== 'object') return JSON.stringify(node);
var i, out;
if (Array.isArray(node)) {
out = '[';
for (i = 0; i < node.length; i++) {
if (i) out += ',';
out += stringify(node[i]) || 'null';
}
return out + ']';
}
if (node === null) return 'null';
if (seen.indexOf(node) !== -1) {
if (cycles) return JSON.stringify('__cycle__');
throw new TypeError('Converting circular structure to JSON');
}
var seenIndex = seen.push(node) - 1;
var keys = Object.keys(node).sort(cmp && cmp(node));
out = '';
for (i = 0; i < keys.length; i++) {
var key = keys[i];
var value = stringify(node[key]);
if (!value) continue;
if (out) out += ',';
out += JSON.stringify(key) + ':' + value;
}
seen.splice(seenIndex, 1);
return '{' + out + '}';
})(data);
};
function accessor(fn, fields, name) {
fn.fields = fields || [];
fn.fname = name;
return fn;
}
function error(message) {
throw Error(message);
}
function splitAccessPath(p) {
var path = [],
q = null,
b = 0,
n = p.length,
s = '',
i, j, c;
p = p + '';
function push() {
path.push(s + p.substring(i, j));
s = '';
i = j + 1;
}
for (i=j=0; j<n; ++j) {
c = p[j];
if (c === '\\') {
s += p.substring(i, j);
i = ++j;
} else if (c === q) {
push();
q = null;
b = -1;
} else if (q) {
continue;
} else if (i === b && c === '"') {
i = j + 1;
q = c;
} else if (i === b && c === "'") {
i = j + 1;
q = c;
} else if (c === '.' && !b) {
if (j > i) {
push();
} else {
i = j + 1;
}
} else if (c === '[') {
if (j > i) push();
b = i = j + 1;
} else if (c === ']') {
if (!b) error('Access path missing open bracket: ' + p);
if (b > 0) push();
b = 0;
i = j + 1;
}
}
if (b) error('Access path missing closing bracket: ' + p);
if (q) error('Access path missing closing quote: ' + p);
if (j > i) {
j++;
push();
}
return path;
}
var isArray = Array.isArray;
function isObject(_) {
return _ === Object(_);
}
function isString(_) {
return typeof _ === 'string';
}
function $(x) {
return isArray(x) ? '[' + x.map($) + ']'
: isObject(x) || 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;
}
function field(field, name) {
var path = splitAccessPath(field),
code = 'return _[' + path.map($).join('][') + '];';
return accessor(
Function('_', code),
[(field = path.length===1 ? path[0] : field)],
name || field
);
}
var empty = [];
var id = field('id');
var identity = accessor(function(_) { return _; }, empty, 'identity');
var zero = accessor(function() { return 0; }, empty, 'zero');
var one = accessor(function() { return 1; }, empty, 'one');
var truthy = accessor(function() { return true; }, empty, 'true');
var falsy = accessor(function() { return false; }, empty, 'false');
function log(method, level, input) {
var msg = [level].concat([].slice.call(input));
console[method](...msg); // eslint-disable-line no-console
}
var None = 0;
var Error$1 = 1;
var Warn = 2;
var Info = 3;
var Debug = 4;
function logger(_, method) {
var level = _ || None;
return {
level: function(_) {
if (arguments.length) {
level = +_;
return this;
} else {
return level;
}
},
error: function() {
if (level >= Error$1) log(method || 'error', 'ERROR', arguments);
return this;
},
warn: function() {
if (level >= Warn) log(method || 'warn', 'WARN', arguments);
return this;
},
info: function() {
if (level >= Info) log(method || 'log', 'INFO', arguments);
return this;
},
debug: function() {
if (level >= Debug) log(method || 'log', 'DEBUG', arguments);
return this;
}
}
}
/**
* Span-preserving range clamp. If the span of the input range is less
* than (max - min) and an endpoint exceeds either the min or max value,
* the range is translated such that the span is preserved and one
* endpoint touches the boundary of the min/max range.
* If the span exceeds (max - min), the range [min, max] is returned.
*/
/**
* Return an array with minimum and maximum values, in the
* form [min, max]. Ignores null, undefined, and NaN values.
*/
/**
* Predicate that returns true if the value lies within the span
* of the given range. The left and right flags control the use
* of inclusive (true) or exclusive (false) comparisons.
*/
function isBoolean(_) {
return typeof _ === 'boolean';
}
function isNumber(_) {
return typeof _ === 'number';
}
function toSet(_) {
for (var s={}, i=0, n=_.length; i<n; ++i) s[_[i]] = true;
return s;
}
const duplicate = clone_1;
/**
* Monkey patch Set so that `stringify` produces a string representation of sets.
*/
Set.prototype['toJSON'] = function () {
return `Set(${[...this].map(x => fastJsonStableStringify(x)).join(',')})`;
};
/**
* Converts any object to a string representation that can be consumed by humans.
*/
const stringify = fastJsonStableStringify;
function contains(array, item) {
return array.indexOf(item) > -1;
}
/**
* Returns true if any item returns true.
*/
function some(arr, f) {
let i = 0;
for (const [k, a] of arr.entries()) {
if (f(a, k, i++)) {
return true;
}
}
return false;
}
// This is a stricter version of Object.keys but with better types. See https://github.com/Microsoft/TypeScript/pull/12253#issuecomment-263132208
const keys = Object.keys;
function flagKeys(f) {
return keys(f);
}
/**
* Convert a string into a valid variable name
*/
function varName(s) {
// Replace non-alphanumeric characters (anything besides a-zA-Z0-9_) with _
const alphanumericS = s.replace(/\W/g, '_');
// Add _ if the string has leading numbers.
return (s.match(/^\d+/) ? '_' : '') + alphanumericS;
}
function titlecase(s) {
return s.charAt(0).toUpperCase() + s.substr(1);
}
/**
* Return access with datum to the flattened field.
*
* @param path The field name.
* @param datum The string to use for `datum`.
*/
function flatAccessWithDatum(path, datum = 'datum') {
return `${datum}[${$(splitAccessPath(path).join('.'))}]`;
}
/**
* Replaces path accesses with access to non-nested field.
* For example, `foo["bar"].baz` becomes `foo\\.bar\\.baz`.
*/
function replacePathInField(path) {
return `${splitAccessPath(path)
.map(p => p.replace('.', '\\.'))
.join('\\.')}`;
}
/**
* This is a replacement for chained || for numeric properties or properties that respect null so that 0 will be included.
*/
function getFirstDefined(...args) {
for (const arg of args) {
if (arg !== undefined) {
return arg;
}
}
return undefined;
}
function internalField(name) {
return isInternalField(name) ? name : `__${name}`;
}
function isInternalField(name) {
return name.indexOf('__') === 0;
}
/*
* Constants and utilities for encoding channels (Visual variables)
* such as 'x', 'y', 'color'.
*/
// Facet
const ROW = 'row';
const COLUMN = 'column';
const FACET = 'facet';
// Position
const X = 'x';
const Y = 'y';
const X2 = 'x2';
const Y2 = 'y2';
// Geo Position
const LATITUDE = 'latitude';
const LONGITUDE = 'longitude';
const LATITUDE2 = 'latitude2';
const LONGITUDE2 = 'longitude2';
// Mark property with scale
const COLOR = 'color';
const FILL = 'fill';
const STROKE = 'stroke';
const SHAPE = 'shape';
const SIZE = 'size';
const OPACITY = 'opacity';
const FILLOPACITY = 'fillOpacity';
const STROKEOPACITY = 'strokeOpacity';
const STROKEWIDTH = 'strokeWidth';
// Non-scale channel
const TEXT = 'text';
const ORDER = 'order';
const DETAIL = 'detail';
const KEY = 'key';
const TOOLTIP = 'tooltip';
const HREF = 'href';
const GEOPOSITION_CHANNEL_INDEX = {
longitude: 1,
longitude2: 1,
latitude: 1,
latitude2: 1
};
const UNIT_CHANNEL_INDEX = Object.assign({
// position
x: 1, y: 1, x2: 1, y2: 1 }, GEOPOSITION_CHANNEL_INDEX, {
// color
color: 1, fill: 1, stroke: 1,
// other non-position with scale
opacity: 1, fillOpacity: 1, strokeOpacity: 1, strokeWidth: 1, size: 1, shape: 1,
// channels without scales
order: 1, text: 1, detail: 1, key: 1, tooltip: 1, href: 1 });
function isColorChannel(channel) {
return channel === 'color' || channel === 'fill' || channel === 'stroke';
}
const FACET_CHANNEL_INDEX = {
row: 1,
column: 1,
facet: 1
};
const CHANNEL_INDEX = Object.assign({}, UNIT_CHANNEL_INDEX, FACET_CHANNEL_INDEX);
const CHANNELS = flagKeys(CHANNEL_INDEX);
const SINGLE_DEF_CHANNEL_INDEX = __rest(CHANNEL_INDEX, ["order", "detail"]);
const SINGLE_DEF_UNIT_CHANNEL_INDEX = __rest(CHANNEL_INDEX, ["order", "detail", "row", "column", "facet"]);
function isChannel(str) {
return !!CHANNEL_INDEX[str];
}
function isSecondaryRangeChannel(c) {
const main = getMainRangeChannel(c);
return main !== c;
}
function getMainRangeChannel(channel) {
switch (channel) {
case 'x2':
return 'x';
case 'y2':
return 'y';
case 'latitude2':
return 'latitude';
case 'longitude2':
return 'longitude';
}
return channel;
}
// NONPOSITION_CHANNELS = UNIT_CHANNELS without X, Y, X2, Y2;
const // The rest of unit channels then have scale
NONPOSITION_CHANNEL_INDEX = __rest(UNIT_CHANNEL_INDEX, ["x", "y", "x2", "y2", "latitude", "longitude", "latitude2", "longitude2"]);
const NONPOSITION_CHANNELS = flagKeys(NONPOSITION_CHANNEL_INDEX);
// POSITION_SCALE_CHANNELS = X and Y;
const POSITION_SCALE_CHANNEL_INDEX = { x: 1, y: 1 };
const POSITION_SCALE_CHANNELS = flagKeys(POSITION_SCALE_CHANNEL_INDEX);
// NON_POSITION_SCALE_CHANNEL = SCALE_CHANNELS without X, Y
const NONPOSITION_SCALE_CHANNEL_INDEX = __rest(NONPOSITION_CHANNEL_INDEX, ["text", "tooltip", "href", "detail", "key", "order"]);
// Declare SCALE_CHANNEL_INDEX
const SCALE_CHANNEL_INDEX = Object.assign({}, POSITION_SCALE_CHANNEL_INDEX, NONPOSITION_SCALE_CHANNEL_INDEX);
function isScaleChannel(channel) {
return !!SCALE_CHANNEL_INDEX[channel];
}
/**
* Return whether a channel supports a particular mark type.
* @param channel channel name
* @param mark the mark type
* @return whether the mark supports the channel
*/
function supportMark(channel, mark) {
return getSupportedMark(channel)[mark];
}
/**
* Return a dictionary showing whether a channel supports mark type.
* @param channel
* @return A dictionary mapping mark types to 'always', 'binned', or undefined
*/
function getSupportedMark(channel) {
switch (channel) {
case COLOR:
case FILL:
case STROKE:
// falls through
case DETAIL:
case KEY:
case TOOLTIP:
case HREF:
case ORDER: // TODO: revise (order might not support rect, which is not stackable?)
case OPACITY:
case FILLOPACITY:
case STROKEOPACITY:
case STROKEWIDTH:
// falls through
case FACET:
case ROW: // falls through
case COLUMN:
return {
// all marks
point: 'always',
tick: 'always',
rule: 'always',
circle: 'always',
square: 'always',
bar: 'always',
rect: 'always',
line: 'always',
trail: 'always',
area: 'always',
text: 'always',
geoshape: 'always'
};
case X:
case Y:
case LATITUDE:
case LONGITUDE:
return {
// all marks except geoshape. geoshape does not use X, Y -- it uses a projection
point: 'always',
tick: 'always',
rule: 'always',
circle: 'always',
square: 'always',
bar: 'always',
rect: 'always',
line: 'always',
trail: 'always',
area: 'always',
text: 'always'
};
case X2:
case Y2:
case LATITUDE2:
case LONGITUDE2:
return {
rule: 'always',
bar: 'always',
rect: 'always',
area: 'always',
circle: 'binned',
point: 'binned',
square: 'binned',
tick: 'binned'
};
case SIZE:
return {
point: 'always',
tick: 'always',
rule: 'always',
circle: 'always',
square: 'always',
bar: 'always',
text: 'always',
line: 'always',
trail: 'always'
};
case SHAPE:
return { point: 'always', geoshape: 'always' };
case TEXT:
return { text: 'always' };
}
}
function rangeType(channel) {
switch (channel) {
case X:
case Y:
case SIZE:
case STROKEWIDTH:
case OPACITY:
case FILLOPACITY:
case STROKEOPACITY:
// X2 and Y2 use X and Y scales, so they similarly have continuous range. [falls through]
case X2:
case Y2:
return undefined;
case FACET:
case ROW:
case COLUMN:
case SHAPE:
// TEXT, TOOLTIP, and HREF have no scale but have discrete output [falls through]
case TEXT:
case TOOLTIP:
case HREF:
return 'discrete';
// Color can be either continuous or discrete, depending on scale type.
case COLOR:
case FILL:
case STROKE:
return 'flexible';
// No scale, no range type.
case LATITUDE:
case LONGITUDE:
case LATITUDE2:
case LONGITUDE2:
case DETAIL:
case KEY:
case ORDER:
return undefined;
}
/* istanbul ignore next: should never reach here. */
throw new Error('rangeType not implemented for ' + channel);
}
const COMMON_AXIS_PROPERTIES_INDEX = {
orient: 1,
bandPosition: 1,
domain: 1,
domainColor: 1,
domainDash: 1,
domainDashOffset: 1,
domainOpacity: 1,
domainWidth: 1,
format: 1,
formatType: 1,
grid: 1,
gridColor: 1,
gridDash: 1,
gridDashOffset: 1,
gridOpacity: 1,
gridWidth: 1,
labelAlign: 1,
labelAngle: 1,
labelBaseline: 1,
labelBound: 1,
labelColor: 1,
labelFlush: 1,
labelFlushOffset: 1,
labelFont: 1,
labelFontSize: 1,
labelFontStyle: 1,
labelFontWeight: 1,
labelLimit: 1,
labelOpacity: 1,
labelOverlap: 1,
labelPadding: 1,
labels: 1,
labelSeparation: 1,
maxExtent: 1,
minExtent: 1,
offset: 1,
position: 1,
tickColor: 1,
tickCount: 1,
tickDash: 1,
tickDashOffset: 1,
tickExtra: 1,
tickMinStep: 1,
tickOffset: 1,
tickOpacity: 1,
tickRound: 1,
ticks: 1,
tickSize: 1,
tickWidth: 1,
title: 1,
titleAlign: 1,
titleAnchor: 1,
titleAngle: 1,
titleBaseline: 1,
titleColor: 1,
titleFont: 1,
titleFontSize: 1,
titleFontStyle: 1,
titleFontWeight: 1,
titleLimit: 1,
titleOpacity: 1,
titlePadding: 1,
titleX: 1,
titleY: 1,
values: 1,
zindex: 1
};
const AXIS_PROPERTIES_INDEX = Object.assign({}, COMMON_AXIS_PROPERTIES_INDEX, { encoding: 1 });
const VG_AXIS_PROPERTIES_INDEX = Object.assign({ gridScale: 1, scale: 1 }, COMMON_AXIS_PROPERTIES_INDEX, { encode: 1 });
// Export for dependent projects
const AXIS_PROPERTIES = flagKeys(AXIS_PROPERTIES_INDEX);
const COMMON_LEGEND_PROPERTY_INDEX = {
clipHeight: 1,
columnPadding: 1,
columns: 1,
cornerRadius: 1,
direction: 1,
fillColor: 1,
format: 1,
formatType: 1,
gradientLength: 1,
gradientOpacity: 1,
gradientStrokeColor: 1,
gradientStrokeWidth: 1,
gradientThickness: 1,
gridAlign: 1,
labelAlign: 1,
labelBaseline: 1,
labelColor: 1,
labelFont: 1,
labelFontSize: 1,
labelFontStyle: 1,
labelFontWeight: 1,
labelLimit: 1,
labelOffset: 1,
labelOpacity: 1,
labelOverlap: 1,
labelPadding: 1,
labelSeparation: 1,
legendX: 1,
legendY: 1,
offset: 1,
orient: 1,
padding: 1,
rowPadding: 1,
strokeColor: 1,
symbolDash: 1,
symbolDashOffset: 1,
symbolFillColor: 1,
symbolOffset: 1,
symbolOpacity: 1,
symbolSize: 1,
symbolStrokeColor: 1,
symbolStrokeWidth: 1,
symbolType: 1,
tickCount: 1,
tickMinStep: 1,
title: 1,
titleAlign: 1,
titleAnchor: 1,
titleBaseline: 1,
titleColor: 1,
titleFont: 1,
titleFontSize: 1,
titleFontStyle: 1,
titleFontWeight: 1,
titleLimit: 1,
titleOpacity: 1,
titleOrient: 1,
titlePadding: 1,
type: 1,
values: 1,
zindex: 1
};
const VG_LEGEND_PROPERTY_INDEX = Object.assign({}, COMMON_LEGEND_PROPERTY_INDEX, {
// channel scales
opacity: 1, shape: 1, stroke: 1, fill: 1, size: 1, strokeWidth: 1,
// encode
encode: 1 });
const LEGEND_PROPERTIES = flagKeys(COMMON_LEGEND_PROPERTY_INDEX);
/**
* Collection of all Vega-Lite Error Messages
*/
const INVALID_SPEC = 'Invalid spec';
// FIT
const FIT_NON_SINGLE = 'Autosize "fit" only works for single views and layered views.';
const CANNOT_FIX_RANGE_STEP_WITH_FIT = 'Cannot use a fixed value of "rangeStep" when "autosize" is "fit".';
// SELECTION
function cannotProjectOnChannelWithoutField(channel) {
return `Cannot project a selection on encoding channel "${channel}", which has no field.`;
}
function nearestNotSupportForContinuous(mark) {
return `The "nearest" transform is not supported for ${mark} marks.`;
}
function selectionNotSupported(mark) {
return `Selection not supported for ${mark} yet`;
}
function selectionNotFound(name) {
return `Cannot find a selection named "${name}"`;
}
const SCALE_BINDINGS_CONTINUOUS = 'Scale bindings are currently only supported for scales with unbinned, continuous domains.';
const NO_INIT_SCALE_BINDINGS = 'Selections bound to scales cannot be separately initialized.';
// REPEAT
function noSuchRepeatedValue(field) {
return `Unknown repeated value "${field}".`;
}
function columnsNotSupportByRowCol(type) {
return `The "columns" property cannot be used when "${type}" has nested row/column.`;
}
// CONCAT
const CONCAT_CANNOT_SHARE_AXIS = 'Axes cannot be shared in concatenated views yet (https://github.com/vega/vega-lite/issues/2415).';
// REPEAT
const REPEAT_CANNOT_SHARE_AXIS = 'Axes cannot be shared in repeated views yet (https://github.com/vega/vega-lite/issues/2415).';
// DATA
function unrecognizedParse(p) {
return `Unrecognized parse "${p}".`;
}
function differentParse(field, local, ancestor) {
return `An ancestor parsed field "${field}" as ${ancestor} but a child wants to parse the field as ${local}.`;
}
// TRANSFORMS
function invalidTransformIgnored(transform) {
return `Ignoring an invalid transform: ${stringify(transform)}.`;
}
const NO_FIELDS_NEEDS_AS = 'If "from.fields" is not specified, "as" has to be a string that specifies the key to be used for the data from the secondary source.';
// ENCODING & FACET
function encodingOverridden(channels) {
return `Layer's shared ${channels.join(',')} channel ${channels.length === 1 ? 'is' : 'are'} overriden`;
}
function projectionOverridden(opt) {
const { parentProjection, projection } = opt;
return `Layer's shared projection ${stringify(parentProjection)} is overridden by a child projection ${stringify(projection)}.`;
}
function primitiveChannelDef(channel, type, value) {
return `Channel ${channel} is a ${type}. Converted to {value: ${stringify(value)}}.`;
}
function invalidFieldType(type) {
return `Invalid field type "${type}"`;
}
function nonZeroScaleUsedWithLengthMark(mark, channel, opt) {
const scaleText = opt.scaleType
? `${opt.scaleType} scale`
: opt.zeroFalse
? 'scale with zero=false'
: 'scale with custom domain that excludes zero';
return `A ${scaleText} is used to encode ${mark}'s ${channel}. This can be misleading as the ${channel === 'x' ? 'width' : 'height'} of the ${mark} can be arbitrary based on the scale domain. You may want to use point mark instead.`;
}
function invalidFieldTypeForCountAggregate(type, aggregate) {
return `Invalid field type "${type}" for aggregate: "${aggregate}", using "quantitative" instead.`;
}
function invalidAggregate(aggregate) {
return `Invalid aggregation operator "${aggregate}"`;
}
function missingFieldType(channel, newType) {
return `Missing type for channel "${channel}", using "${newType}" instead.`;
}
function droppingColor(type, opt) {
const { fill, stroke } = opt;
return (`Dropping color ${type} as the plot also has ` + (fill && stroke ? 'fill and stroke' : fill ? 'fill' : 'stroke'));
}
function emptyFieldDef(fieldDef, channel) {
return `Dropping ${stringify(fieldDef)} from channel "${channel}" since it does not contain data field or value.`;
}
function latLongDeprecated(channel, type, newChannel) {
return `${channel}-encoding with type ${type} is deprecated. Replacing with ${newChannel}-encoding.`;
}
const LINE_WITH_VARYING_SIZE = 'Line marks cannot encode size with a non-groupby field. You may want to use trail marks instead.';
function incompatibleChannel(channel, markOrFacet, when) {
return `${channel} dropped as it is incompatible with "${markOrFacet}"${when ? ` when ${when}` : ''}.`;
}
function invalidEncodingChannel(channel) {
return `${channel}-encoding is dropped as ${channel} is not a valid encoding channel.`;
}
function facetChannelShouldBeDiscrete(channel) {
return `${channel} encoding should be discrete (ordinal / nominal / binned).`;
}
function facetChannelDropped(channels) {
return `Facet encoding dropped as ${channels.join(' and ')} ${channels.length > 1 ? 'are' : 'is'} also specified.`;
}
function discreteChannelCannotEncode(channel, type) {
return `Using discrete channel "${channel}" to encode "${type}" field can be misleading as it does not encode ${type === 'ordinal' ? 'order' : 'magnitude'}.`;
}
// Mark
const BAR_WITH_POINT_SCALE_AND_RANGESTEP_NULL = 'Bar mark should not be used with point scale when rangeStep is null. Please use band scale instead.';
function lineWithRange(hasX2, hasY2) {
const channels = hasX2 && hasY2 ? 'x2 and y2' : hasX2 ? 'x2' : 'y2';
return `Line mark is for continuous lines and thus cannot be used with ${channels}. We will use the rule mark (line segments) instead.`;
}
function orientOverridden(original, actual) {
return `Specified orient "${original}" overridden with "${actual}"`;
}
// SCALE
const CANNOT_UNION_CUSTOM_DOMAIN_WITH_FIELD_DOMAIN = 'custom domain scale cannot be unioned with default field-based domain';
function cannotUseScalePropertyWithNonColor(prop) {
return `Cannot use the scale property "${prop}" with non-color channel.`;
}
function unaggregateDomainHasNoEffectForRawField(fieldDef) {
return `Using unaggregated domain with raw field has no effect (${stringify(fieldDef)}).`;
}
function unaggregateDomainWithNonSharedDomainOp(aggregate) {
return `Unaggregated domain not applicable for "${aggregate}" since it produces values outside the origin domain of the source data.`;
}
function unaggregatedDomainWithLogScale(fieldDef) {
return `Unaggregated domain is currently unsupported for log scale (${stringify(fieldDef)}).`;
}
function cannotApplySizeToNonOrientedMark(mark) {
return `Cannot apply size to non-oriented mark "${mark}".`;
}
function rangeStepDropped(channel) {
return `rangeStep for "${channel}" is dropped as top-level ${channel === 'x' ? 'width' : 'height'} is provided.`;
}
function scaleTypeNotWorkWithChannel(channel, scaleType, defaultScaleType) {
return `Channel "${channel}" does not work with "${scaleType}" scale. We are using "${defaultScaleType}" scale instead.`;
}
function scaleTypeNotWorkWithFieldDef(scaleType, defaultScaleType) {
return `FieldDef does not work with "${scaleType}" scale. We are using "${defaultScaleType}" scale instead.`;
}
function scalePropertyNotWorkWithScaleType(scaleType, propName, channel) {
return `${channel}-scale's "${propName}" is dropped as it does not work with ${scaleType} scale.`;
}
function scaleTypeNotWorkWithMark(mark, scaleType) {
return `Scale type "${scaleType}" does not work with mark "${mark}".`;
}
function mergeConflictingProperty(property, propertyOf, v1, v2) {
return `Conflicting ${propertyOf.toString()} property "${property.toString()}" (${stringify(v1)} and ${stringify(v2)}). Using ${stringify(v1)}.`;
}
function independentScaleMeansIndependentGuide(channel) {
return `Setting the scale to be independent for "${channel}" means we also have to set the guide (axis or legend) to be independent.`;
}
function domainSortDropped(sort) {
return `Dropping sort property ${stringify(sort)} as unioned domains only support boolean or op 'count'.`;
}
const UNABLE_TO_MERGE_DOMAINS = 'Unable to merge domains';
const MORE_THAN_ONE_SORT = 'Domains that should be unioned has conflicting sort properties. Sort will be set to true.';
// AXIS
const INVALID_CHANNEL_FOR_AXIS = 'Invalid channel for axis.';
// STACK
function cannotStackRangedMark(channel) {
return `Cannot stack "${channel}" if there is already "${channel}2"`;
}
function cannotStackNonLinearScale(scaleType) {
return `Cannot stack non-linear scale (${scaleType})`;
}
function stackNonSummativeAggregate(aggregate) {
return `Stacking is applied even though the aggregate function is non-summative ("${aggregate}")`;
}
// TIMEUNIT
function invalidTimeUnit(unitName, value) {
return `Invalid ${unitName}: ${stringify(value)}`;
}
function dayReplacedWithDate(fullTimeUnit) {
return `Time unit "${fullTimeUnit}" is not supported. We are replacing it with ${fullTimeUnit.replace('day', 'date')}.`;
}
function droppedDay(d) {
return `Dropping day from datetime ${stringify(d)} as day cannot be combined with other units.`;
}
function errorBarCenterAndExtentAreNotNeeded(center, extent) {
return `${extent ? 'extent ' : ''}${extent && center ? 'and ' : ''}${center ? 'center ' : ''}${extent && center ? 'are ' : 'is '}not needed when data are aggregated.`;
}
function errorBarCenterIsUsedWithWrongExtent(center, extent, mark) {
return `${center} is not usually used with ${extent} for ${mark}.`;
}
function errorBarContinuousAxisHasCustomizedAggregate(aggregate, compositeMark) {
return `Continuous axis should not have customized aggregation function ${aggregate}; ${compositeMark} already agregates the axis.`;
}
function errorBarCenterIsNotNeeded(extent, mark) {
return `Center is not needed to be specified in ${mark} when extent is ${extent}.`;
}
function errorBand1DNotSupport(property) {
return `1D error band does not support ${property}`;
}
// CHANNEL
function channelRequiredForBinned(channel) {
return `Channel ${channel} is required for "binned" bin`;
}
function domainRequiredForThresholdScale(channel) {
return `Domain for ${channel} is required for threshold scale`;
}
var message_ = /*#__PURE__*/Object.freeze({
INVALID_SPEC: INVALID_SPEC,
FIT_NON_SINGLE: FIT_NON_SINGLE,
CANNOT_FIX_RANGE_STEP_WITH_FIT: CANNOT_FIX_RANGE_STEP_WITH_FIT,
cannotProjectOnChannelWithoutField: cannotProjectOnChannelWithoutField,
nearestNotSupportForContinuous: nearestNotSupportForContinuous,
selectionNotSupported: selectionNotSupported,
selectionNotFound: selectionNotFound,
SCALE_BINDINGS_CONTINUOUS: SCALE_BINDINGS_CONTINUOUS,
NO_INIT_SCALE_BINDINGS: NO_INIT_SCALE_BINDINGS,
noSuchRepeatedValue: noSuchRepeatedValue,
columnsNotSupportByRowCol: columnsNotSupportByRowCol,
CONCAT_CANNOT_SHARE_AXIS: CONCAT_CANNOT_SHARE_AXIS,
REPEAT_CANNOT_SHARE_AXIS: REPEAT_CANNOT_SHARE_AXIS,
unrecognizedParse: unrecognizedParse,
differentParse: differentParse,
invalidTransformIgnored: invalidTransformIgnored,
NO_FIELDS_NEEDS_AS: NO_FIELDS_NEEDS_AS,
encodingOverridden: encodingOverridden,
projectionOverridden: projectionOverridden,
primitiveChannelDef: primitiveChannelDef,
invalidFieldType: invalidFieldType,
nonZeroScaleUsedWithLengthMark: nonZeroScaleUsedWithLengthMark,
invalidFieldTypeForCountAggregate: invalidFieldTypeForCountAggregate,
invalidAggregate: invalidAggregate,
missingFieldType: missingFieldType,
droppingColor: droppingColor,
emptyFieldDef: emptyFieldDef,
latLongDeprecated: latLongDeprecated,
LINE_WITH_VARYING_SIZE: LINE_WITH_VARYING_SIZE,
incompatibleChannel: incompatibleChannel,
invalidEncodingChannel: invalidEncodingChannel,
facetChannelShouldBeDiscrete: facetChannelShouldBeDiscrete,
facetChannelDropped: facetChannelDropped,
discreteChannelCannotEncode: discreteChannelCannotEncode,
BAR_WITH_POINT_SCALE_AND_RANGESTEP_NULL: BAR_WITH_POINT_SCALE_AND_RANGESTEP_NULL,
lineWithRange: lineWithRange,
orientOverridden: orientOverridden,
CANNOT_UNION_CUSTOM_DOMAIN_WITH_FIELD_DOMAIN: CANNOT_UNION_CUSTOM_DOMAIN_WITH_FIELD_DOMAIN,
cannotUseScalePropertyWithNonColor: cannotUseScalePropertyWithNonColor,
unaggregateDomainHasNoEffectForRawField: unaggregateDomainHasNoEffectForRawField,
unaggregateDomainWithNonSharedDomainOp: unaggregateDomainWithNonSharedDomainOp,
unaggregatedDomainWithLogScale: unaggregatedDomainWithLogScale,
cannotApplySizeToNonOrientedMark: cannotApplySizeToNonOrientedMark,
rangeStepDropped: rangeStepDropped,
scaleTypeNotWorkWithChannel: scaleTypeNotWorkWithChannel,
scaleTypeNotWorkWithFieldDef: scaleTypeNotWorkWithFieldDef,
scalePropertyNotWorkWithScaleType: scalePropertyNotWorkWithScaleType,
scaleTypeNotWorkWithMark: scaleTypeNotWorkWithMark,
mergeConflictingProperty: mergeConflictingProperty,
independentScaleMeansIndependentGuide: independentScaleMeansIndependentGuide,
domainSortDropped: domainSortDropped,
UNABLE_TO_MERGE_DOMAINS: UNABLE_TO_MERGE_DOMAINS,
MORE_THAN_ONE_SORT: MORE_THAN_ONE_SORT,
INVALID_CHANNEL_FOR_AXIS: INVALID_CHANNEL_FOR_AXIS,
cannotStackRangedMark: cannotStackRangedMark,
cannotStackNonLinearScale: cannotStackNonLinearScale,
stackNonSummativeAggregate: stackNonSummativeAggregate,
invalidTimeUnit: invalidTimeUnit,
dayReplacedWithDate: dayReplacedWithDate,
droppedDay: droppedDay,
errorBarCenterAndExtentAreNotNeeded: errorBarCenterAndExtentAreNotNeeded,
errorBarCenterIsUsedWithWrongExtent: errorBarCenterIsUsedWithWrongExtent,
errorBarContinuousAxisHasCustomizedAggregate: errorBarContinuousAxisHasCustomizedAggregate,
errorBarCenterIsNotNeeded: errorBarCenterIsNotNeeded,
errorBand1DNotSupport: errorBand1DNotSupport,
channelRequiredForBinned: channelRequiredForBinned,
domainRequiredForThresholdScale: domainRequiredForThresholdScale
});
/**
* Vega-Lite's singleton logger utility.
*/
const message = message_;
/**
* Main (default) Vega Logger instance for Vega-Lite
*/
const main = logger(Warn);
let current = main;
/**
* Logger tool for checking if the code throws correct warning
*/
class LocalLogger {
constructor() {
this.warns = [];
this.infos = [];
this.debugs = [];
}
level() {
return this;
}
warn(...args) {
this.warns.push(...args);
return this;
}
info(...args) {
this.infos.push(...args);
return this;
}
debug(...args) {
this.debugs.push(...args);
return this;
}
error(...args) {
throw Error(...args);
return this; // @ts-ignore
}
}
function wrap(f) {
return () => {
current = new LocalLogger();
f(current);
reset();
};
}
/**
* Set the singleton logger to be a custom logger
*/
function set(newLogger) {
current = newLogger;
return current;
}
/**
* Reset the main logger to use the default Vega Logger
*/
function reset() {
current = main;
return current;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function warn(..._) {
current.warn.apply(current, arguments);
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function info(..._) {
current.info.apply(current, arguments);
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function debug(..._) {
current.debug.apply(current, arguments);
}
var log$1 = /*#__PURE__*/Object.freeze({
message: message,
LocalLogger: LocalLogger,
wrap: wrap,
set: set,
reset: reset,
warn: warn,
info: info,
debug: debug
});
/** Constants and utilities for data type */
/** Data type based on level of measurement */
const TYPE_INDEX = {
quantitative: 1,
ordinal: 1,
temporal: 1,
nominal: 1,
geojson: 1
};
const QUANTITATIVE = 'quantitative';
const ORDINAL = 'ordinal';
const TEMPORAL = 'temporal';
const NOMINAL = 'nominal';
const GEOJSON = 'geojson';
/**
* Get full, lowercase type name for a given type.
* @param type
* @return Full type name.
*/
function getFullName(type) {
if (type) {
type = type.toLowerCase();
switch (type) {
case 'q':
case QUANTITATIVE:
return 'quantitative';
case 't':
case TEMPORAL:
return 'temporal';
case 'o':
case ORDINAL:
return 'ordinal';
case 'n':
case NOMINAL:
return 'nominal';
case GEOJSON:
return 'geojson';
}
}
// If we get invalid input, return undefined type.
return undefined;
}
var ScaleType;
(function (ScaleType) {
// Continuous - Quantitative
ScaleType.LINEAR = 'linear';
ScaleType.LOG = 'log';
ScaleType.POW = 'pow';
ScaleType.SQRT = 'sqrt';
ScaleType.SYMLOG = 'symlog';
// Continuous - Time
ScaleType.TIME = 'time';
ScaleType.UTC = 'utc';
// Discretizing scales
ScaleType.QUANTILE = 'quantile';
ScaleType.QUANTIZE = 'quantize';
ScaleType.THRESHOLD = 'threshold';
ScaleType.B