UNPKG

compassql

Version:

CompassQL visualization query language

1,410 lines (1,322 loc) 362 kB
(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