UNPKG

vega-lite

Version:

Vega-Lite is a concise high-level language for interactive visualization.

430 lines (342 loc) 16.9 kB
/** * Collection of all Vega-Lite Error Messages */ import {AggregateOp, SignalRef, stringValue} from 'vega'; import {Aggregate} from '../aggregate.js'; import { Channel, ExtendedChannel, FacetChannel, getSizeChannel, OffsetScaleChannel, PositionScaleChannel, ScaleChannel, SingleDefUnitChannel, } from '../channel.js'; import {HiddenCompositeAggregate, TypedFieldDef, Value} from '../channeldef.js'; import {SplitParentProperty} from '../compile/split.js'; import {CompositeMark} from '../compositemark/index.js'; import {ErrorBarCenter, ErrorBarExtent} from '../compositemark/errorbar.js'; import {DateTime, DateTimeExpr} from '../datetime.js'; import {ExprRef} from '../expr.js'; import {Mark} from '../mark.js'; import {Projection} from '../projection.js'; import {ScaleType} from '../scale.js'; import {GenericSpec} from '../spec/index.js'; import {Type} from '../type.js'; import {stringify} from '../util.js'; import {VgSortField} from '../vega.schema.js'; import {SelectionProjection} from '../compile/selection/project.js'; import {ParameterExtent} from '../selection.js'; export function invalidSpec(spec: GenericSpec<any, any, any, any>) { return `Invalid specification ${stringify( spec, )}. Make sure the specification includes at least one of the following properties: "mark", "layer", "facet", "hconcat", "vconcat", "concat", or "repeat".`; } // FIT export const FIT_NON_SINGLE = 'Autosize "fit" only works for single views and layered views.'; export function containerSizeNonSingle(name: 'width' | 'height') { const uName = name == 'width' ? 'Width' : 'Height'; return `${uName} "container" only works for single views and layered views.`; } export function containerSizeNotCompatibleWithAutosize(name: 'width' | 'height') { const uName = name == 'width' ? 'Width' : 'Height'; const fitDirection = name == 'width' ? 'x' : 'y'; return `${uName} "container" only works well with autosize "fit" or "fit-${fitDirection}".`; } export function droppingFit(channel?: PositionScaleChannel) { return channel ? `Dropping "fit-${channel}" because spec has discrete ${getSizeChannel(channel)}.` : `Dropping "fit" because spec has discrete size.`; } // VIEW SIZE export function unknownField(channel: Channel) { return `Unknown field for ${channel}. Cannot calculate view size.`; } // SELECTION export function cannotProjectOnChannelWithoutField(channel: Channel) { return `Cannot project a selection on encoding channel "${channel}", which has no field.`; } export function cannotProjectAggregate(channel: Channel, aggregate: Aggregate | HiddenCompositeAggregate) { return `Cannot project a selection on encoding channel "${channel}" as it uses an aggregate function ("${aggregate}").`; } export function nearestNotSupportForContinuous(mark: string) { return `The "nearest" transform is not supported for ${mark} marks.`; } export function selectionNotSupported(mark: CompositeMark) { return `Selection not supported for ${mark} yet.`; } export function selectionNotFound(name: string) { return `Cannot find a selection named "${name}".`; } export const SCALE_BINDINGS_CONTINUOUS = 'Scale bindings are currently only supported for scales with unbinned, continuous domains.'; export const SEQUENTIAL_SCALE_DEPRECATED = 'Sequntial scales are deprecated. The available quantitative scale type values are linear, log, pow, sqrt, symlog, time and utc'; export const LEGEND_BINDINGS_MUST_HAVE_PROJECTION = 'Legend bindings are only supported for selections over an individual field or encoding channel.'; export function cannotLookupVariableParameter(name: string) { return `Lookups can only be performed on selection parameters. "${name}" is a variable parameter.`; } export function noSameUnitLookup(name: string) { return ( `Cannot define and lookup the "${name}" selection in the same view. ` + `Try moving the lookup into a second, layered view?` ); } export const NEEDS_SAME_SELECTION = 'The same selection must be used to override scale domains in a layered view.'; export const INTERVAL_INITIALIZED_WITH_POS = 'Interval selections should be initialized using "x", "y", "longitude", or "latitude" keys.'; // REPEAT export function noSuchRepeatedValue(field: string) { return `Unknown repeated value "${field}".`; } export function columnsNotSupportByRowCol(type: 'facet' | 'repeat') { return `The "columns" property cannot be used when "${type}" has nested row/column.`; } export const MULTIPLE_TIMER_ANIMATION_SELECTION = 'Multiple timer selections in one unit spec are not supported. Ignoring all but the first.'; export const MULTI_VIEW_ANIMATION_UNSUPPORTED = 'Animation involving facet, layer, or concat is currently unsupported.'; export function selectionAsScaleDomainWithoutField(field: string) { return ( 'A "field" or "encoding" must be specified when using a selection as a scale domain. ' + `Using "field": ${stringValue(field)}.` ); } export function selectionAsScaleDomainWrongEncodings( encodings: SelectionProjection[], encoding: SingleDefUnitChannel, extent: ParameterExtent, field: string, ) { return ( `${ !encodings.length ? 'No ' : 'Multiple ' }matching ${stringValue(encoding)} encoding found for selection ${stringValue(extent.param)}. ` + `Using "field": ${stringValue(field)}.` ); } // CONCAT / REPEAT export const CONCAT_CANNOT_SHARE_AXIS = 'Axes cannot be shared in concatenated or repeated views yet (https://github.com/vega/vega-lite/issues/2415).'; // DATA export function unrecognizedParse(p: string) { return `Unrecognized parse "${p}".`; } export function differentParse(field: string, local: string, ancestor: string) { return `An ancestor parsed field "${field}" as ${ancestor} but a child wants to parse the field as ${local}.`; } export const ADD_SAME_CHILD_TWICE = 'Attempt to add the same child twice.'; // TRANSFORMS export function invalidTransformIgnored(transform: any) { return `Ignoring an invalid transform: ${stringify(transform)}.`; } export 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 export function customFormatTypeNotAllowed(channel: ExtendedChannel) { return `Config.customFormatTypes is not true, thus custom format type and format for channel ${channel} are dropped.`; } export function projectionOverridden<ES extends ExprRef | SignalRef>(opt: { parentProjection: Projection<ES>; projection: Projection<ES>; }) { const {parentProjection, projection} = opt; return `Layer's shared projection ${stringify(parentProjection)} is overridden by a child projection ${stringify( projection, )}.`; } export const REPLACE_ANGLE_WITH_THETA = 'Arc marks uses theta channel rather than angle, replacing angle with theta.'; export function offsetNestedInsideContinuousPositionScaleDropped(mainChannel: PositionScaleChannel) { return `${mainChannel}Offset dropped because ${mainChannel} is continuous`; } export function primitiveChannelDef( channel: ExtendedChannel, type: 'string' | 'number' | 'boolean', value: Exclude<Value, null>, ) { return `Channel ${channel} is a ${type}. Converted to {value: ${stringify(value)}}.`; } export function invalidFieldType(type: Type) { return `Invalid field type "${type}".`; } export function invalidFieldTypeForCountAggregate(type: Type, aggregate: Aggregate | string) { return `Invalid field type "${type}" for aggregate: "${aggregate}", using "quantitative" instead.`; } export function invalidAggregate(aggregate: AggregateOp | string) { return `Invalid aggregation operator "${aggregate}".`; } export function missingFieldType(channel: Channel, newType: Type) { return `Missing type for channel "${channel}", using "${newType}" instead.`; } export function droppingColor(type: 'encoding' | 'property', opt: {fill?: boolean; stroke?: boolean}) { const {fill, stroke} = opt; return `Dropping color ${type} as the plot also has ${ fill && stroke ? 'fill and stroke' : fill ? 'fill' : 'stroke' }.`; } export function relativeBandSizeNotSupported(sizeChannel: 'width' | 'height') { return `Position range does not support relative band size for ${sizeChannel}.`; } export function emptyFieldDef(fieldDef: unknown, channel: ExtendedChannel) { return `Dropping ${stringify( fieldDef, )} from channel "${channel}" since it does not contain any data field, datum, value, or signal.`; } export const LINE_WITH_VARYING_SIZE = 'Line marks cannot encode size with a non-groupby field. You may want to use trail marks instead.'; export function incompatibleChannel( channel: ExtendedChannel, markOrFacet: Mark | 'facet' | CompositeMark, when?: string, ) { return `${channel} dropped as it is incompatible with "${markOrFacet}"${when ? ` when ${when}` : ''}.`; } export function offsetEncodingScaleIgnored(channel: OffsetScaleChannel) { return `${channel} encoding has no scale, so specified scale is ignored.`; } export function invalidEncodingChannel(channel: ExtendedChannel) { return `${channel}-encoding is dropped as ${channel} is not a valid encoding channel.`; } export function channelShouldBeDiscrete(channel: ExtendedChannel) { return `${channel} encoding should be discrete (ordinal / nominal / binned).`; } export function channelShouldBeDiscreteOrDiscretizing(channel: ExtendedChannel) { return `${channel} encoding should be discrete (ordinal / nominal / binned) or use a discretizing scale (e.g. threshold).`; } export function facetChannelDropped(channels: FacetChannel[]) { return `Facet encoding dropped as ${channels.join(' and ')} ${channels.length > 1 ? 'are' : 'is'} also specified.`; } export function discreteChannelCannotEncode(channel: Channel, type: Type) { return `Using discrete channel "${channel}" to encode "${type}" field can be misleading as it does not encode ${ type === 'ordinal' ? 'order' : 'magnitude' }.`; } // MARK export function rangeMarkAlignmentCannotBeExpression(align: 'align' | 'baseline') { return `The ${align} for range marks cannot be an expression`; } export function lineWithRange(hasX2: boolean, hasY2: boolean) { 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.`; } export function orientOverridden(original: string, actual: string) { return `Specified orient "${original}" overridden with "${actual}".`; } // SCALE export const CANNOT_UNION_CUSTOM_DOMAIN_WITH_FIELD_DOMAIN = 'Custom domain scale cannot be unioned with default field-based domain.'; export function cannotUseScalePropertyWithNonColor(prop: string) { return `Cannot use the scale property "${prop}" with non-color channel.`; } export function cannotUseRelativeBandSizeWithNonBandScale(scaleType: ScaleType) { return `Cannot use the relative band size with ${scaleType} scale.`; } export function unaggregateDomainHasNoEffectForRawField(fieldDef: TypedFieldDef<string>) { return `Using unaggregated domain with raw field has no effect (${stringify(fieldDef)}).`; } export function unaggregateDomainWithNonSharedDomainOp(aggregate: Aggregate | string) { return `Unaggregated domain not applicable for "${aggregate}" since it produces values outside the origin domain of the source data.`; } export function unaggregatedDomainWithLogScale(fieldDef: TypedFieldDef<string>) { return `Unaggregated domain is currently unsupported for log scale (${stringify(fieldDef)}).`; } export function cannotApplySizeToNonOrientedMark(mark: Mark) { return `Cannot apply size to non-oriented mark "${mark}".`; } export function scaleTypeNotWorkWithChannel(channel: Channel, scaleType: ScaleType, defaultScaleType: ScaleType) { return `Channel "${channel}" does not work with "${scaleType}" scale. We are using "${defaultScaleType}" scale instead.`; } export function scaleTypeNotWorkWithFieldDef(scaleType: ScaleType, defaultScaleType: ScaleType) { return `FieldDef does not work with "${scaleType}" scale. We are using "${defaultScaleType}" scale instead.`; } export function scalePropertyNotWorkWithScaleType(scaleType: ScaleType, propName: string, channel: Channel) { return `${channel}-scale's "${propName}" is dropped as it does not work with ${scaleType} scale.`; } export function scaleTypeNotWorkWithMark(mark: Mark, scaleType: ScaleType) { return `Scale type "${scaleType}" does not work with mark "${mark}".`; } export function stepDropped(channel: 'width' | 'height') { return `The step for "${channel}" is dropped because the ${channel === 'width' ? 'x' : 'y'} is continuous.`; } export function mergeConflictingProperty<T>( property: string | number | symbol, propertyOf: SplitParentProperty, v1: T, v2: T, ) { return `Conflicting ${propertyOf.toString()} property "${property.toString()}" (${stringify(v1)} and ${stringify( v2, )}). Using ${stringify(v1)}.`; } export function mergeConflictingDomainProperty<T>(property: 'domains', propertyOf: SplitParentProperty, v1: T, v2: T) { return `Conflicting ${propertyOf.toString()} property "${property.toString()}" (${stringify(v1)} and ${stringify( v2, )}). Using the union of the two domains.`; } export function independentScaleMeansIndependentGuide(channel: Channel) { return `Setting the scale to be independent for "${channel}" means we also have to set the guide (axis or legend) to be independent.`; } export function domainSortDropped(sort: VgSortField) { return `Dropping sort property ${stringify( sort, )} as unioned domains only support boolean or op "count", "min", and "max".`; } export const MORE_THAN_ONE_SORT = 'Domains that should be unioned has conflicting sort properties. Sort will be set to true.'; export const FACETED_INDEPENDENT_DIFFERENT_SOURCES = 'Detected faceted independent scales that union domain of multiple fields from different data sources. We will use the first field. The result view size may be incorrect.'; export const FACETED_INDEPENDENT_SAME_FIELDS_DIFFERENT_SOURCES = 'Detected faceted independent scales that union domain of the same fields from different source. We will assume that this is the same field from a different fork of the same data source. However, if this is not the case, the result view size may be incorrect.'; export const FACETED_INDEPENDENT_SAME_SOURCE = 'Detected faceted independent scales that union domain of multiple fields from the same data source. We will use the first field. The result view size may be incorrect.'; // AXIS export const INVALID_CHANNEL_FOR_AXIS = 'Invalid channel for axis.'; // STACK export function cannotStackRangedMark(channel: Channel) { return `Cannot stack "${channel}" if there is already "${channel}2".`; } export function stackNonLinearScale(scaleType: ScaleType) { return `Stack is applied to a non-linear scale (${scaleType}).`; } export function stackNonSummativeAggregate(aggregate: Aggregate | string) { return `Stacking is applied even though the aggregate function is non-summative ("${aggregate}").`; } // TIMEUNIT export function invalidTimeUnit(unitName: string, value: string | number) { return `Invalid ${unitName}: ${stringify(value)}.`; } export function droppedDay(d: DateTime | DateTimeExpr) { return `Dropping day from datetime ${stringify(d)} as day cannot be combined with other units.`; } export function errorBarCenterAndExtentAreNotNeeded(center: ErrorBarCenter, extent: ErrorBarExtent) { return `${extent ? 'extent ' : ''}${extent && center ? 'and ' : ''}${center ? 'center ' : ''}${ extent && center ? 'are ' : 'is ' }not needed when data are aggregated.`; } export function errorBarCenterIsUsedWithWrongExtent( center: ErrorBarCenter, extent: ErrorBarExtent, mark: 'errorbar' | 'errorband', ) { return `${center} is not usually used with ${extent} for ${mark}.`; } export function errorBarContinuousAxisHasCustomizedAggregate( aggregate: Aggregate | string, compositeMark: CompositeMark, ) { return `Continuous axis should not have customized aggregation function ${aggregate}; ${compositeMark} already agregates the axis.`; } export function errorBand1DNotSupport(property: 'interpolate' | 'tension') { return `1D error band does not support ${property}.`; } // CHANNEL export function channelRequiredForBinned(channel: Channel) { return `Channel ${channel} is required for "binned" bin.`; } export function channelShouldNotBeUsedForBinned(channel: ExtendedChannel) { return `Channel ${channel} should not be used with "binned" bin.`; } export function domainRequiredForThresholdScale(channel: ScaleChannel) { return `Domain for ${channel} is required for threshold scale.`; }