vega-functions
Version:
Custom functions for the Vega expression language.
375 lines (334 loc) • 7 kB
JavaScript
import {
codegenExpression,
constants,
functions
} from 'vega-expression';
import {
isTuple
} from 'vega-dataflow';
import {
selectionIdTest,
selectionResolve,
selectionTest,
selectionTuples,
selectionVisitor
} from 'vega-selections';
import {
cumulativeLogNormal,
cumulativeNormal,
cumulativeUniform,
densityLogNormal,
densityNormal,
densityUniform,
quantileLogNormal,
quantileNormal,
quantileUniform,
random,
sampleLogNormal,
sampleNormal,
sampleUniform
} from 'vega-statistics';
import {
dayofyear,
timeOffset,
timeSequence,
timeUnitSpecifier,
utcOffset,
utcSequence,
utcdayofyear,
utcweek,
week
} from 'vega-time';
import {
clampRange,
extend,
extent,
flush,
inrange,
isArray,
isBoolean,
isDate,
isNumber,
isObject,
isRegExp,
isString,
lerp,
pad,
panLinear,
panLog,
panPow,
panSymlog,
peek,
quarter,
span,
stringValue,
toBoolean,
toDate,
toNumber,
toString,
truncate,
utcquarter,
zoomLinear,
zoomLog,
zoomPow,
zoomSymlog
} from 'vega-util';
import {
range as sequence
} from 'd3-array';
import {
hcl,
hsl,
lab,
rgb
} from 'd3-color';
import {
contrast,
luminance
} from './functions/luminance';
import {
data,
indata,
setdata
} from './functions/data';
import encode from './functions/encode';
import {
dayAbbrevFormat,
dayFormat,
format,
monthAbbrevFormat,
monthFormat,
timeFormat,
timeParse,
utcFormat,
utcParse
} from './functions/format';
import {
geoArea,
geoBounds,
geoCentroid,
geoScale
} from './functions/geo';
import inScope from './functions/inscope';
import intersect from './functions/intersect';
import {
debug,
info,
warn
} from './functions/log';
import merge from './functions/merge';
import modify from './functions/modify';
import {
pinchAngle,
pinchDistance
} from './functions/pinch';
import pluck from './functions/pluck';
import {
indexof,
join,
lastindexof,
replace,
reverse,
slice,
sort
} from './functions/sequence';
import {
intersectLasso,
lassoAppend,
lassoPath
} from './functions/lasso';
import {
bandspace,
bandwidth,
copy,
domain,
invert,
range,
scale
} from './functions/scale';
import scaleGradient from './functions/scale-gradient';
import {
geoShape,
pathShape
} from './functions/shape';
import {
treeAncestors,
treePath
} from './functions/tree';
import {
containerSize,
screen,
windowSize
} from './functions/window';
import {
SignalPrefix
} from './constants';
import {
internalScaleFunctions
} from './scales';
import {
dataVisitor,
indataVisitor,
scaleVisitor
} from './visitors';
// Expression function context object
export const functionContext = {
random() { return random(); }, // override default
cumulativeNormal,
cumulativeLogNormal,
cumulativeUniform,
densityNormal,
densityLogNormal,
densityUniform,
quantileNormal,
quantileLogNormal,
quantileUniform,
sampleNormal,
sampleLogNormal,
sampleUniform,
isArray,
isBoolean,
isDate,
isDefined(_) { return _ !== undefined; },
isNumber,
isObject,
isRegExp,
isString,
isTuple,
isValid(_) { return _ != null && _ === _; },
toBoolean,
toDate(_) { return toDate(_); }, // suppress extra arguments
toNumber,
toString,
indexof,
join,
lastindexof,
replace,
reverse,
sort,
slice,
flush,
lerp,
merge,
pad,
peek,
pluck,
span,
inrange,
truncate,
rgb,
lab,
hcl,
hsl,
luminance,
contrast,
sequence,
format,
utcFormat,
utcParse,
utcOffset,
utcSequence,
timeFormat,
timeParse,
timeOffset,
timeSequence,
timeUnitSpecifier,
monthFormat,
monthAbbrevFormat,
dayFormat,
dayAbbrevFormat,
quarter,
utcquarter,
week,
utcweek,
dayofyear,
utcdayofyear,
warn,
info,
debug,
extent(_) { return extent(_); }, // suppress extra arguments
inScope,
intersect,
clampRange,
pinchDistance,
pinchAngle,
screen,
containerSize,
windowSize,
bandspace,
setdata,
pathShape,
panLinear,
panLog,
panPow,
panSymlog,
zoomLinear,
zoomLog,
zoomPow,
zoomSymlog,
encode,
modify,
lassoAppend,
lassoPath,
intersectLasso
};
const eventFunctions = ['view', 'item', 'group', 'xy', 'x', 'y'], // event functions
eventPrefix = 'event.vega.', // event function prefix
thisPrefix = 'this.', // function context prefix
astVisitors = {}; // AST visitors for dependency analysis
// export code generator parameters
export const codegenParams = {
forbidden: ['_'],
allowed: ['datum', 'event', 'item'],
fieldvar: 'datum',
globalvar: id => `_[${stringValue(SignalPrefix + id)}]`,
functions: buildFunctions,
constants: constants,
visitors: astVisitors
};
// export code generator
export const codeGenerator = codegenExpression(codegenParams);
// Build expression function registry
function buildFunctions(codegen) {
const fn = functions(codegen);
eventFunctions.forEach(name => fn[name] = eventPrefix + name);
for (const name in functionContext) { fn[name] = thisPrefix + name; }
extend(fn, internalScaleFunctions(codegen, functionContext, astVisitors));
return fn;
}
// Register an expression function
export function expressionFunction(name, fn, visitor) {
if (arguments.length === 1) {
return functionContext[name];
}
// register with the functionContext
functionContext[name] = fn;
// if there is an astVisitor register that, too
if (visitor) astVisitors[name] = visitor;
// if the code generator has already been initialized,
// we need to also register the function with it
if (codeGenerator) codeGenerator.functions[name] = thisPrefix + name;
return this;
}
// register expression functions with ast visitors
expressionFunction('bandwidth', bandwidth, scaleVisitor);
expressionFunction('copy', copy, scaleVisitor);
expressionFunction('domain', domain, scaleVisitor);
expressionFunction('range', range, scaleVisitor);
expressionFunction('invert', invert, scaleVisitor);
expressionFunction('scale', scale, scaleVisitor);
expressionFunction('gradient', scaleGradient, scaleVisitor);
expressionFunction('geoArea', geoArea, scaleVisitor);
expressionFunction('geoBounds', geoBounds, scaleVisitor);
expressionFunction('geoCentroid', geoCentroid, scaleVisitor);
expressionFunction('geoShape', geoShape, scaleVisitor);
expressionFunction('geoScale', geoScale, scaleVisitor);
expressionFunction('indata', indata, indataVisitor);
expressionFunction('data', data, dataVisitor);
expressionFunction('treePath', treePath, dataVisitor);
expressionFunction('treeAncestors', treeAncestors, dataVisitor);
// register Vega-Lite selection functions
expressionFunction('vlSelectionTest', selectionTest, selectionVisitor);
expressionFunction('vlSelectionIdTest', selectionIdTest, selectionVisitor);
expressionFunction('vlSelectionResolve', selectionResolve, selectionVisitor);
expressionFunction('vlSelectionTuples', selectionTuples);