Spaces:
Sleeping
Sleeping
nova-right-nav / node_modules /@plotly /mapbox-gl /src /style-spec /expression /definitions /index.js
| // @flow | |
| import { | |
| type Type, | |
| NumberType, | |
| StringType, | |
| BooleanType, | |
| ColorType, | |
| ObjectType, | |
| ValueType, | |
| ErrorType, | |
| CollatorType, | |
| array, | |
| toString as typeToString | |
| } from '../types'; | |
| import {typeOf, Color, validateRGBA, toString as valueToString} from '../values'; | |
| import CompoundExpression from '../compound_expression'; | |
| import RuntimeError from '../runtime_error'; | |
| import Let from './let'; | |
| import Var from './var'; | |
| import Literal from './literal'; | |
| import Assertion from './assertion'; | |
| import Coercion from './coercion'; | |
| import At from './at'; | |
| import In from './in'; | |
| import IndexOf from './index_of'; | |
| import Match from './match'; | |
| import Case from './case'; | |
| import Slice from './slice'; | |
| import Step from './step'; | |
| import Interpolate from './interpolate'; | |
| import Coalesce from './coalesce'; | |
| import { | |
| Equals, | |
| NotEquals, | |
| LessThan, | |
| GreaterThan, | |
| LessThanOrEqual, | |
| GreaterThanOrEqual | |
| } from './comparison'; | |
| import CollatorExpression from './collator'; | |
| import NumberFormat from './number_format'; | |
| import FormatExpression from './format'; | |
| import ImageExpression from './image'; | |
| import Length from './length'; | |
| import Within from './within'; | |
| import type {Varargs} from '../compound_expression'; | |
| import type {ExpressionRegistry} from '../expression'; | |
| const expressions: ExpressionRegistry = { | |
| // special forms | |
| '==': Equals, | |
| '!=': NotEquals, | |
| '>': GreaterThan, | |
| '<': LessThan, | |
| '>=': GreaterThanOrEqual, | |
| '<=': LessThanOrEqual, | |
| 'array': Assertion, | |
| 'at': At, | |
| 'boolean': Assertion, | |
| 'case': Case, | |
| 'coalesce': Coalesce, | |
| 'collator': CollatorExpression, | |
| 'format': FormatExpression, | |
| 'image': ImageExpression, | |
| 'in': In, | |
| 'index-of': IndexOf, | |
| 'interpolate': Interpolate, | |
| 'interpolate-hcl': Interpolate, | |
| 'interpolate-lab': Interpolate, | |
| 'length': Length, | |
| 'let': Let, | |
| 'literal': Literal, | |
| 'match': Match, | |
| 'number': Assertion, | |
| 'number-format': NumberFormat, | |
| 'object': Assertion, | |
| 'slice': Slice, | |
| 'step': Step, | |
| 'string': Assertion, | |
| 'to-boolean': Coercion, | |
| 'to-color': Coercion, | |
| 'to-number': Coercion, | |
| 'to-string': Coercion, | |
| 'var': Var, | |
| 'within': Within | |
| }; | |
| function rgba(ctx, [r, g, b, a]) { | |
| r = r.evaluate(ctx); | |
| g = g.evaluate(ctx); | |
| b = b.evaluate(ctx); | |
| const alpha = a ? a.evaluate(ctx) : 1; | |
| const error = validateRGBA(r, g, b, alpha); | |
| if (error) throw new RuntimeError(error); | |
| return new Color(r / 255 * alpha, g / 255 * alpha, b / 255 * alpha, alpha); | |
| } | |
| function has(key, obj) { | |
| return key in obj; | |
| } | |
| function get(key, obj) { | |
| const v = obj[key]; | |
| return typeof v === 'undefined' ? null : v; | |
| } | |
| function binarySearch(v, a, i, j) { | |
| while (i <= j) { | |
| const m = (i + j) >> 1; | |
| if (a[m] === v) | |
| return true; | |
| if (a[m] > v) | |
| j = m - 1; | |
| else | |
| i = m + 1; | |
| } | |
| return false; | |
| } | |
| function varargs(type: Type): Varargs { | |
| return {type}; | |
| } | |
| CompoundExpression.register(expressions, { | |
| 'error': [ | |
| ErrorType, | |
| [StringType], | |
| (ctx, [v]) => { throw new RuntimeError(v.evaluate(ctx)); } | |
| ], | |
| 'typeof': [ | |
| StringType, | |
| [ValueType], | |
| (ctx, [v]) => typeToString(typeOf(v.evaluate(ctx))) | |
| ], | |
| 'to-rgba': [ | |
| array(NumberType, 4), | |
| [ColorType], | |
| (ctx, [v]) => { | |
| return v.evaluate(ctx).toArray(); | |
| } | |
| ], | |
| 'rgb': [ | |
| ColorType, | |
| [NumberType, NumberType, NumberType], | |
| rgba | |
| ], | |
| 'rgba': [ | |
| ColorType, | |
| [NumberType, NumberType, NumberType, NumberType], | |
| rgba | |
| ], | |
| 'has': { | |
| type: BooleanType, | |
| overloads: [ | |
| [ | |
| [StringType], | |
| (ctx, [key]) => has(key.evaluate(ctx), ctx.properties()) | |
| ], [ | |
| [StringType, ObjectType], | |
| (ctx, [key, obj]) => has(key.evaluate(ctx), obj.evaluate(ctx)) | |
| ] | |
| ] | |
| }, | |
| 'get': { | |
| type: ValueType, | |
| overloads: [ | |
| [ | |
| [StringType], | |
| (ctx, [key]) => get(key.evaluate(ctx), ctx.properties()) | |
| ], [ | |
| [StringType, ObjectType], | |
| (ctx, [key, obj]) => get(key.evaluate(ctx), obj.evaluate(ctx)) | |
| ] | |
| ] | |
| }, | |
| 'feature-state': [ | |
| ValueType, | |
| [StringType], | |
| (ctx, [key]) => get(key.evaluate(ctx), ctx.featureState || {}) | |
| ], | |
| 'properties': [ | |
| ObjectType, | |
| [], | |
| (ctx) => ctx.properties() | |
| ], | |
| 'geometry-type': [ | |
| StringType, | |
| [], | |
| (ctx) => ctx.geometryType() | |
| ], | |
| 'id': [ | |
| ValueType, | |
| [], | |
| (ctx) => ctx.id() | |
| ], | |
| 'zoom': [ | |
| NumberType, | |
| [], | |
| (ctx) => ctx.globals.zoom | |
| ], | |
| 'heatmap-density': [ | |
| NumberType, | |
| [], | |
| (ctx) => ctx.globals.heatmapDensity || 0 | |
| ], | |
| 'line-progress': [ | |
| NumberType, | |
| [], | |
| (ctx) => ctx.globals.lineProgress || 0 | |
| ], | |
| 'accumulated': [ | |
| ValueType, | |
| [], | |
| (ctx) => ctx.globals.accumulated === undefined ? null : ctx.globals.accumulated | |
| ], | |
| '+': [ | |
| NumberType, | |
| varargs(NumberType), | |
| (ctx, args) => { | |
| let result = 0; | |
| for (const arg of args) { | |
| result += arg.evaluate(ctx); | |
| } | |
| return result; | |
| } | |
| ], | |
| '*': [ | |
| NumberType, | |
| varargs(NumberType), | |
| (ctx, args) => { | |
| let result = 1; | |
| for (const arg of args) { | |
| result *= arg.evaluate(ctx); | |
| } | |
| return result; | |
| } | |
| ], | |
| '-': { | |
| type: NumberType, | |
| overloads: [ | |
| [ | |
| [NumberType, NumberType], | |
| (ctx, [a, b]) => a.evaluate(ctx) - b.evaluate(ctx) | |
| ], [ | |
| [NumberType], | |
| (ctx, [a]) => -a.evaluate(ctx) | |
| ] | |
| ] | |
| }, | |
| '/': [ | |
| NumberType, | |
| [NumberType, NumberType], | |
| (ctx, [a, b]) => a.evaluate(ctx) / b.evaluate(ctx) | |
| ], | |
| '%': [ | |
| NumberType, | |
| [NumberType, NumberType], | |
| (ctx, [a, b]) => a.evaluate(ctx) % b.evaluate(ctx) | |
| ], | |
| 'ln2': [ | |
| NumberType, | |
| [], | |
| () => Math.LN2 | |
| ], | |
| 'pi': [ | |
| NumberType, | |
| [], | |
| () => Math.PI | |
| ], | |
| 'e': [ | |
| NumberType, | |
| [], | |
| () => Math.E | |
| ], | |
| '^': [ | |
| NumberType, | |
| [NumberType, NumberType], | |
| (ctx, [b, e]) => Math.pow(b.evaluate(ctx), e.evaluate(ctx)) | |
| ], | |
| 'sqrt': [ | |
| NumberType, | |
| [NumberType], | |
| (ctx, [x]) => Math.sqrt(x.evaluate(ctx)) | |
| ], | |
| 'log10': [ | |
| NumberType, | |
| [NumberType], | |
| (ctx, [n]) => Math.log(n.evaluate(ctx)) / Math.LN10 | |
| ], | |
| 'ln': [ | |
| NumberType, | |
| [NumberType], | |
| (ctx, [n]) => Math.log(n.evaluate(ctx)) | |
| ], | |
| 'log2': [ | |
| NumberType, | |
| [NumberType], | |
| (ctx, [n]) => Math.log(n.evaluate(ctx)) / Math.LN2 | |
| ], | |
| 'sin': [ | |
| NumberType, | |
| [NumberType], | |
| (ctx, [n]) => Math.sin(n.evaluate(ctx)) | |
| ], | |
| 'cos': [ | |
| NumberType, | |
| [NumberType], | |
| (ctx, [n]) => Math.cos(n.evaluate(ctx)) | |
| ], | |
| 'tan': [ | |
| NumberType, | |
| [NumberType], | |
| (ctx, [n]) => Math.tan(n.evaluate(ctx)) | |
| ], | |
| 'asin': [ | |
| NumberType, | |
| [NumberType], | |
| (ctx, [n]) => Math.asin(n.evaluate(ctx)) | |
| ], | |
| 'acos': [ | |
| NumberType, | |
| [NumberType], | |
| (ctx, [n]) => Math.acos(n.evaluate(ctx)) | |
| ], | |
| 'atan': [ | |
| NumberType, | |
| [NumberType], | |
| (ctx, [n]) => Math.atan(n.evaluate(ctx)) | |
| ], | |
| 'min': [ | |
| NumberType, | |
| varargs(NumberType), | |
| (ctx, args) => Math.min(...args.map(arg => arg.evaluate(ctx))) | |
| ], | |
| 'max': [ | |
| NumberType, | |
| varargs(NumberType), | |
| (ctx, args) => Math.max(...args.map(arg => arg.evaluate(ctx))) | |
| ], | |
| 'abs': [ | |
| NumberType, | |
| [NumberType], | |
| (ctx, [n]) => Math.abs(n.evaluate(ctx)) | |
| ], | |
| 'round': [ | |
| NumberType, | |
| [NumberType], | |
| (ctx, [n]) => { | |
| const v = n.evaluate(ctx); | |
| // Javascript's Math.round() rounds towards +Infinity for halfway | |
| // values, even when they're negative. It's more common to round | |
| // away from 0 (e.g., this is what python and C++ do) | |
| return v < 0 ? -Math.round(-v) : Math.round(v); | |
| } | |
| ], | |
| 'floor': [ | |
| NumberType, | |
| [NumberType], | |
| (ctx, [n]) => Math.floor(n.evaluate(ctx)) | |
| ], | |
| 'ceil': [ | |
| NumberType, | |
| [NumberType], | |
| (ctx, [n]) => Math.ceil(n.evaluate(ctx)) | |
| ], | |
| 'filter-==': [ | |
| BooleanType, | |
| [StringType, ValueType], | |
| (ctx, [k, v]) => ctx.properties()[(k: any).value] === (v: any).value | |
| ], | |
| 'filter-id-==': [ | |
| BooleanType, | |
| [ValueType], | |
| (ctx, [v]) => ctx.id() === (v: any).value | |
| ], | |
| 'filter-type-==': [ | |
| BooleanType, | |
| [StringType], | |
| (ctx, [v]) => ctx.geometryType() === (v: any).value | |
| ], | |
| 'filter-<': [ | |
| BooleanType, | |
| [StringType, ValueType], | |
| (ctx, [k, v]) => { | |
| const a = ctx.properties()[(k: any).value]; | |
| const b = (v: any).value; | |
| return typeof a === typeof b && a < b; | |
| } | |
| ], | |
| 'filter-id-<': [ | |
| BooleanType, | |
| [ValueType], | |
| (ctx, [v]) => { | |
| const a = ctx.id(); | |
| const b = (v: any).value; | |
| return typeof a === typeof b && a < b; | |
| } | |
| ], | |
| 'filter->': [ | |
| BooleanType, | |
| [StringType, ValueType], | |
| (ctx, [k, v]) => { | |
| const a = ctx.properties()[(k: any).value]; | |
| const b = (v: any).value; | |
| return typeof a === typeof b && a > b; | |
| } | |
| ], | |
| 'filter-id->': [ | |
| BooleanType, | |
| [ValueType], | |
| (ctx, [v]) => { | |
| const a = ctx.id(); | |
| const b = (v: any).value; | |
| return typeof a === typeof b && a > b; | |
| } | |
| ], | |
| 'filter-<=': [ | |
| BooleanType, | |
| [StringType, ValueType], | |
| (ctx, [k, v]) => { | |
| const a = ctx.properties()[(k: any).value]; | |
| const b = (v: any).value; | |
| return typeof a === typeof b && a <= b; | |
| } | |
| ], | |
| 'filter-id-<=': [ | |
| BooleanType, | |
| [ValueType], | |
| (ctx, [v]) => { | |
| const a = ctx.id(); | |
| const b = (v: any).value; | |
| return typeof a === typeof b && a <= b; | |
| } | |
| ], | |
| 'filter->=': [ | |
| BooleanType, | |
| [StringType, ValueType], | |
| (ctx, [k, v]) => { | |
| const a = ctx.properties()[(k: any).value]; | |
| const b = (v: any).value; | |
| return typeof a === typeof b && a >= b; | |
| } | |
| ], | |
| 'filter-id->=': [ | |
| BooleanType, | |
| [ValueType], | |
| (ctx, [v]) => { | |
| const a = ctx.id(); | |
| const b = (v: any).value; | |
| return typeof a === typeof b && a >= b; | |
| } | |
| ], | |
| 'filter-has': [ | |
| BooleanType, | |
| [ValueType], | |
| (ctx, [k]) => (k: any).value in ctx.properties() | |
| ], | |
| 'filter-has-id': [ | |
| BooleanType, | |
| [], | |
| (ctx) => (ctx.id() !== null && ctx.id() !== undefined) | |
| ], | |
| 'filter-type-in': [ | |
| BooleanType, | |
| [array(StringType)], | |
| (ctx, [v]) => (v: any).value.indexOf(ctx.geometryType()) >= 0 | |
| ], | |
| 'filter-id-in': [ | |
| BooleanType, | |
| [array(ValueType)], | |
| (ctx, [v]) => (v: any).value.indexOf(ctx.id()) >= 0 | |
| ], | |
| 'filter-in-small': [ | |
| BooleanType, | |
| [StringType, array(ValueType)], | |
| // assumes v is an array literal | |
| (ctx, [k, v]) => (v: any).value.indexOf(ctx.properties()[(k: any).value]) >= 0 | |
| ], | |
| 'filter-in-large': [ | |
| BooleanType, | |
| [StringType, array(ValueType)], | |
| // assumes v is a array literal with values sorted in ascending order and of a single type | |
| (ctx, [k, v]) => binarySearch(ctx.properties()[(k: any).value], (v: any).value, 0, (v: any).value.length - 1) | |
| ], | |
| 'all': { | |
| type: BooleanType, | |
| overloads: [ | |
| [ | |
| [BooleanType, BooleanType], | |
| (ctx, [a, b]) => a.evaluate(ctx) && b.evaluate(ctx) | |
| ], | |
| [ | |
| varargs(BooleanType), | |
| (ctx, args) => { | |
| for (const arg of args) { | |
| if (!arg.evaluate(ctx)) | |
| return false; | |
| } | |
| return true; | |
| } | |
| ] | |
| ] | |
| }, | |
| 'any': { | |
| type: BooleanType, | |
| overloads: [ | |
| [ | |
| [BooleanType, BooleanType], | |
| (ctx, [a, b]) => a.evaluate(ctx) || b.evaluate(ctx) | |
| ], | |
| [ | |
| varargs(BooleanType), | |
| (ctx, args) => { | |
| for (const arg of args) { | |
| if (arg.evaluate(ctx)) | |
| return true; | |
| } | |
| return false; | |
| } | |
| ] | |
| ] | |
| }, | |
| '!': [ | |
| BooleanType, | |
| [BooleanType], | |
| (ctx, [b]) => !b.evaluate(ctx) | |
| ], | |
| 'is-supported-script': [ | |
| BooleanType, | |
| [StringType], | |
| // At parse time this will always return true, so we need to exclude this expression with isGlobalPropertyConstant | |
| (ctx, [s]) => { | |
| const isSupportedScript = ctx.globals && ctx.globals.isSupportedScript; | |
| if (isSupportedScript) { | |
| return isSupportedScript(s.evaluate(ctx)); | |
| } | |
| return true; | |
| } | |
| ], | |
| 'upcase': [ | |
| StringType, | |
| [StringType], | |
| (ctx, [s]) => s.evaluate(ctx).toUpperCase() | |
| ], | |
| 'downcase': [ | |
| StringType, | |
| [StringType], | |
| (ctx, [s]) => s.evaluate(ctx).toLowerCase() | |
| ], | |
| 'concat': [ | |
| StringType, | |
| varargs(ValueType), | |
| (ctx, args) => args.map(arg => valueToString(arg.evaluate(ctx))).join('') | |
| ], | |
| 'resolved-locale': [ | |
| StringType, | |
| [CollatorType], | |
| (ctx, [collator]) => collator.evaluate(ctx).resolvedLocale() | |
| ] | |
| }); | |
| export default expressions; | |