0
# Specification Parsing
1
2
Vega's specification parsing system converts JSON specifications into executable runtime objects, manages configuration merging, and provides runtime context for expression evaluation.
3
4
## Capabilities
5
6
### Core Parsing
7
8
Main specification parser that converts JSON specs to runtime objects.
9
10
```typescript { .api }
11
/**
12
* Parse a Vega specification into executable runtime objects
13
* @param spec - Vega specification object
14
* @param config - Optional configuration object to merge
15
* @param options - Optional parsing configuration
16
* @returns Parsed runtime object ready for view creation
17
*/
18
function parse(spec: Spec, config?: Config, options?: ParseOptions): Runtime;
19
20
interface Spec {
21
/** Schema URL for specification version */
22
$schema?: string;
23
24
/** Visualization description */
25
description?: string;
26
27
/** Visualization configuration */
28
config?: Config;
29
30
/** Visualization width */
31
width?: number | SignalRef;
32
33
/** Visualization height */
34
height?: number | SignalRef;
35
36
/** Padding specification */
37
padding?: Padding | SignalRef;
38
39
/** Autosize configuration */
40
autosize?: AutoSize | SignalRef;
41
42
/** Background color */
43
background?: Color | SignalRef;
44
45
/** Data sources */
46
data?: Data[];
47
48
/** Scale definitions */
49
scales?: Scale[];
50
51
/** Mark definitions */
52
marks?: Mark[];
53
54
/** Signal definitions */
55
signals?: Signal[];
56
57
/** Axis definitions */
58
axes?: Axis[];
59
60
/** Legend definitions */
61
legends?: Legend[];
62
63
/** Title definition */
64
title?: Title;
65
66
/** Projection definitions */
67
projections?: Projection[];
68
69
/** Layout configuration */
70
layout?: Layout;
71
72
/** User metadata */
73
usermeta?: any;
74
}
75
76
interface Runtime {
77
/** Parsed specification definition */
78
definition: any;
79
80
/** Dataflow operators */
81
operators: Operator[];
82
83
/** Event streams */
84
streams: EventStream[];
85
86
/** Signal registry */
87
signals: { [name: string]: Signal };
88
89
/** Data registry */
90
data: { [name: string]: Data };
91
92
/** Scale registry */
93
scales: { [name: string]: Scale };
94
}
95
96
interface ParseOptions {
97
/** Return AST instead of compiled runtime */
98
ast?: boolean;
99
100
/** Expression function registry */
101
functions?: { [name: string]: Function };
102
103
/** Custom operator registry */
104
operators?: { [name: string]: any };
105
}
106
107
type SignalRef = { signal: string };
108
type Color = string;
109
110
interface Padding {
111
top?: number;
112
bottom?: number;
113
left?: number;
114
right?: number;
115
}
116
117
interface AutoSize {
118
type?: 'pad' | 'fit' | 'fit-x' | 'fit-y' | 'none';
119
resize?: boolean;
120
contains?: 'content' | 'padding';
121
}
122
```
123
124
### Configuration System
125
126
Configuration management and merging utilities.
127
128
```typescript { .api }
129
interface Config {
130
/** Global view configuration */
131
view?: ViewConfig;
132
133
/** Mark-specific configurations */
134
mark?: MarkConfig;
135
136
/** Axis configuration */
137
axis?: AxisConfig;
138
139
/** Legend configuration */
140
legend?: LegendConfig;
141
142
/** Title configuration */
143
title?: TitleConfig;
144
145
/** Scale configuration */
146
scale?: ScaleConfig;
147
148
/** Range configuration */
149
range?: RangeConfig;
150
151
/** Selection configuration */
152
selection?: SelectionConfig;
153
154
/** Event configuration */
155
events?: EventConfig;
156
157
/** Custom configuration sections */
158
[key: string]: any;
159
}
160
161
interface ViewConfig {
162
/** View width */
163
width?: number;
164
165
/** View height */
166
height?: number;
167
168
/** View background */
169
background?: Color;
170
171
/** View stroke */
172
stroke?: Color;
173
174
/** View stroke width */
175
strokeWidth?: number;
176
177
/** View fill */
178
fill?: Color;
179
180
/** View padding */
181
padding?: Padding;
182
183
/** Continuous size range */
184
continuousWidth?: number;
185
continuousHeight?: number;
186
187
/** Discrete size range */
188
discreteWidth?: number;
189
discreteHeight?: number;
190
}
191
192
interface MarkConfig {
193
/** Mark fill color */
194
fill?: Color;
195
196
/** Mark stroke color */
197
stroke?: Color;
198
199
/** Mark stroke width */
200
strokeWidth?: number;
201
202
/** Mark opacity */
203
opacity?: number;
204
205
/** Mark fill opacity */
206
fillOpacity?: number;
207
208
/** Mark stroke opacity */
209
strokeOpacity?: number;
210
211
/** Mark size */
212
size?: number;
213
214
/** Mark-specific configurations */
215
rect?: RectConfig;
216
circle?: CircleConfig;
217
line?: LineConfig;
218
text?: TextConfig;
219
[markType: string]: any;
220
}
221
222
interface AxisConfig {
223
/** Axis domain line configuration */
224
domain?: boolean;
225
domainColor?: Color;
226
domainWidth?: number;
227
228
/** Grid line configuration */
229
grid?: boolean;
230
gridColor?: Color;
231
gridWidth?: number;
232
gridDash?: number[];
233
234
/** Tick configuration */
235
ticks?: boolean;
236
tickColor?: Color;
237
tickWidth?: number;
238
tickSize?: number;
239
240
/** Label configuration */
241
labels?: boolean;
242
labelColor?: Color;
243
labelFont?: string;
244
labelFontSize?: number;
245
labelAngle?: number;
246
labelPadding?: number;
247
248
/** Title configuration */
249
title?: boolean;
250
titleColor?: Color;
251
titleFont?: string;
252
titleFontSize?: number;
253
titlePadding?: number;
254
}
255
256
interface RectConfig extends MarkConfig {
257
/** Rectangle corner radius */
258
cornerRadius?: number;
259
}
260
261
interface CircleConfig extends MarkConfig {
262
/** Circle radius */
263
radius?: number;
264
}
265
266
interface LineConfig extends MarkConfig {
267
/** Line interpolation */
268
interpolate?: string;
269
270
/** Line tension */
271
tension?: number;
272
273
/** Line stroke dash */
274
strokeDash?: number[];
275
}
276
277
interface TextConfig extends MarkConfig {
278
/** Text font family */
279
font?: string;
280
281
/** Text font size */
282
fontSize?: number;
283
284
/** Text font weight */
285
fontWeight?: string;
286
287
/** Text font style */
288
fontStyle?: string;
289
290
/** Text alignment */
291
align?: string;
292
293
/** Text baseline */
294
baseline?: string;
295
296
/** Text angle */
297
angle?: number;
298
}
299
```
300
301
### Data Definitions
302
303
Data source specification structures.
304
305
```typescript { .api }
306
interface Data {
307
/** Data source name */
308
name: string;
309
310
/** Data source type */
311
source?: string;
312
313
/** Inline data values */
314
values?: any[];
315
316
/** External data URL */
317
url?: string;
318
319
/** Data format specification */
320
format?: Format;
321
322
/** Data transforms */
323
transform?: Transform[];
324
325
/** Data selection listeners */
326
on?: EventListener[];
327
}
328
329
interface Format {
330
/** Data format type */
331
type?: 'json' | 'csv' | 'tsv' | 'dsv' | 'topojson' | 'geojson';
332
333
/** Parse configuration */
334
parse?: { [field: string]: string } | 'auto';
335
336
/** Property path for nested data */
337
property?: string;
338
339
/** Feature property for GeoJSON */
340
feature?: string;
341
342
/** Mesh property for TopoJSON */
343
mesh?: string;
344
345
/** Field delimiter for DSV */
346
delimiter?: string;
347
348
/** Header row indicator */
349
header?: boolean;
350
}
351
352
interface Transform {
353
/** Transform type */
354
type: string;
355
356
/** Transform-specific parameters */
357
[key: string]: any;
358
}
359
360
interface EventListener {
361
/** Event trigger */
362
trigger: string;
363
364
/** Event handler action */
365
update?: string;
366
367
/** Event handler expression */
368
encode?: string;
369
}
370
```
371
372
### Signal Definitions
373
374
Reactive signal specification structures.
375
376
```typescript { .api }
377
interface Signal {
378
/** Signal name */
379
name: string;
380
381
/** Initial signal value */
382
value?: any;
383
384
/** Signal expression */
385
update?: string;
386
387
/** Signal reaction triggers */
388
on?: SignalListener[];
389
390
/** Signal initialization */
391
init?: string;
392
393
/** Signal binding configuration */
394
bind?: Binding;
395
396
/** Signal description */
397
description?: string;
398
}
399
400
interface SignalListener {
401
/** Event source */
402
events: string | EventSelector[];
403
404
/** Update expression */
405
update?: string;
406
407
/** Encode expression */
408
encode?: string;
409
410
/** Force re-evaluation */
411
force?: boolean;
412
}
413
414
interface Binding {
415
/** Input type */
416
input: 'checkbox' | 'radio' | 'range' | 'select' | 'text' | 'number' | 'date' | 'time' | 'datetime-local' | 'tel' | 'url';
417
418
/** Input element attributes */
419
[attribute: string]: any;
420
}
421
422
interface EventSelector {
423
/** Event source */
424
source?: string;
425
426
/** Event type */
427
type: string;
428
429
/** Event filter */
430
filter?: string;
431
432
/** Debounce delay */
433
debounce?: number;
434
435
/** Throttle delay */
436
throttle?: number;
437
438
/** Event markname filter */
439
markname?: string;
440
441
/** Event marktype filter */
442
marktype?: string;
443
}
444
```
445
446
### Scale Definitions
447
448
Scale specification structures.
449
450
```typescript { .api }
451
interface Scale {
452
/** Scale name */
453
name: string;
454
455
/** Scale type */
456
type: ScaleType;
457
458
/** Scale domain */
459
domain?: Domain;
460
461
/** Scale range */
462
range?: Range;
463
464
/** Scale reverse flag */
465
reverse?: boolean;
466
467
/** Scale rounding */
468
round?: boolean;
469
470
/** Scale clamping */
471
clamp?: boolean;
472
473
/** Scale interpolation */
474
interpolate?: Interpolate;
475
476
/** Scale nice boundaries */
477
nice?: boolean | number;
478
479
/** Scale zero baseline */
480
zero?: boolean;
481
482
/** Scale padding (band/point) */
483
padding?: number;
484
485
/** Scale inner padding (band) */
486
paddingInner?: number;
487
488
/** Scale outer padding (band) */
489
paddingOuter?: number;
490
491
/** Scale alignment (band/point) */
492
align?: number;
493
}
494
495
type ScaleType = 'linear' | 'log' | 'pow' | 'sqrt' | 'symlog' | 'identity' | 'time' | 'utc' | 'sequential' | 'diverging' | 'quantile' | 'quantize' | 'threshold' | 'ordinal' | 'band' | 'point';
496
497
type Domain = any[] | DomainRef;
498
type Range = any[] | RangeRef | string;
499
500
interface DomainRef {
501
/** Data source reference */
502
data?: string;
503
504
/** Field reference */
505
field?: string;
506
507
/** Sort configuration */
508
sort?: boolean | SortOrder;
509
510
/** Union multiple data sources */
511
fields?: FieldRef[];
512
}
513
514
interface RangeRef {
515
/** Range scheme name */
516
scheme?: string;
517
518
/** Range extent */
519
extent?: number[];
520
521
/** Range count */
522
count?: number;
523
}
524
525
interface FieldRef {
526
/** Data source name */
527
data: string;
528
529
/** Field name */
530
field: string;
531
}
532
533
interface SortOrder {
534
/** Sort field */
535
field?: string;
536
537
/** Sort order direction */
538
order?: 'ascending' | 'descending';
539
}
540
541
interface Interpolate {
542
/** Interpolation type */
543
type?: string;
544
545
/** Interpolation gamma */
546
gamma?: number;
547
}
548
```
549
550
### Mark Definitions
551
552
Visual mark specification structures.
553
554
```typescript { .api }
555
interface Mark {
556
/** Mark type */
557
type: MarkType;
558
559
/** Mark name */
560
name?: string;
561
562
/** Mark description */
563
description?: string;
564
565
/** Mark role */
566
role?: string;
567
568
/** Mark style */
569
style?: string | string[];
570
571
/** Mark group/parent */
572
from?: MarkFrom;
573
574
/** Mark encoding */
575
encode?: MarkEncode;
576
577
/** Mark transforms */
578
transform?: Transform[];
579
580
/** Mark sort configuration */
581
sort?: SortOrder;
582
583
/** Clip mark to group bounds */
584
clip?: boolean;
585
586
/** Mark interactive flag */
587
interactive?: boolean;
588
589
/** Mark key field */
590
key?: string;
591
592
/** Nested marks (group marks) */
593
marks?: Mark[];
594
595
/** Group scales */
596
scales?: Scale[];
597
598
/** Group axes */
599
axes?: Axis[];
600
601
/** Group legends */
602
legends?: Legend[];
603
}
604
605
type MarkType = 'arc' | 'area' | 'image' | 'group' | 'line' | 'path' | 'rect' | 'rule' | 'shape' | 'symbol' | 'text' | 'trail';
606
607
interface MarkFrom {
608
/** Data source name */
609
data?: string;
610
611
/** Facet configuration */
612
facet?: FacetMapping;
613
}
614
615
interface FacetMapping {
616
/** Facet data source */
617
data: string;
618
619
/** Facet field */
620
field?: string;
621
622
/** Facet groupby */
623
groupby?: string | string[];
624
625
/** Facet aggregate */
626
aggregate?: AggregateOp;
627
}
628
629
interface MarkEncode {
630
/** Enter encoding set */
631
enter?: EncodeEntry;
632
633
/** Update encoding set */
634
update?: EncodeEntry;
635
636
/** Exit encoding set */
637
exit?: EncodeEntry;
638
639
/** Hover encoding set */
640
hover?: EncodeEntry;
641
642
/** Select encoding set */
643
select?: EncodeEntry;
644
}
645
646
interface EncodeEntry {
647
/** Visual property encodings */
648
[property: string]: ValueRef | ProductionRule[];
649
}
650
651
interface ValueRef {
652
/** Literal value */
653
value?: any;
654
655
/** Field reference */
656
field?: string;
657
658
/** Scale reference */
659
scale?: string;
660
661
/** Band reference */
662
band?: boolean | number;
663
664
/** Offset value */
665
offset?: number | ValueRef;
666
667
/** Multiplication factor */
668
mult?: number | ValueRef;
669
670
/** Signal reference */
671
signal?: string;
672
673
/** Color value reference */
674
color?: ColorRef;
675
676
/** Gradient reference */
677
gradient?: string;
678
679
/** Test condition */
680
test?: string;
681
}
682
683
interface ProductionRule {
684
/** Test condition */
685
test: string;
686
687
/** Value if test passes */
688
value?: any;
689
690
/** Field if test passes */
691
field?: string;
692
693
/** Scale if test passes */
694
scale?: string;
695
696
/** Band if test passes */
697
band?: boolean | number;
698
699
/** Signal if test passes */
700
signal?: string;
701
}
702
703
interface ColorRef {
704
/** Color value */
705
value?: Color;
706
707
/** Gradient definition */
708
gradient?: GradientRef;
709
710
/** Color field */
711
field?: string;
712
713
/** Color scale */
714
scale?: string;
715
}
716
717
interface GradientRef {
718
/** Gradient type */
719
gradient: 'linear' | 'radial';
720
721
/** Color stops */
722
stops: GradientStop[];
723
724
/** Gradient coordinates */
725
x1?: number;
726
y1?: number;
727
x2?: number;
728
y2?: number;
729
r1?: number;
730
r2?: number;
731
}
732
733
interface GradientStop {
734
/** Stop offset (0-1) */
735
offset: number;
736
737
/** Stop color */
738
color: string;
739
}
740
741
type AggregateOp = 'count' | 'mean' | 'average' | 'sum' | 'min' | 'max' | 'median' | 'q1' | 'q3' | 'variance' | 'stdev' | 'stderr' | 'distinct' | 'ci0' | 'ci1' | 'missing' | 'valid';
742
```
743
744
### Runtime Context
745
746
Runtime context creation for expression evaluation.
747
748
```typescript { .api }
749
/**
750
* Create runtime context for expression evaluation
751
* @param dataflow - Dataflow instance
752
* @param signals - Signal registry
753
* @param data - Data registry
754
* @param mutates - Mutation tracking function
755
* @returns Runtime context object
756
*/
757
function runtimeContext(
758
dataflow: Dataflow,
759
signals: { [name: string]: any },
760
data: { [name: string]: any },
761
mutates?: (name: string) => boolean
762
): RuntimeContext;
763
764
interface RuntimeContext {
765
/** Dataflow instance */
766
dataflow: Dataflow;
767
768
/** Signal accessor */
769
signals: { [name: string]: any };
770
771
/** Data accessor */
772
data: { [name: string]: any };
773
774
/** Mutation tracker */
775
mutates?: (name: string) => boolean;
776
777
/** Context functions */
778
functions: { [name: string]: Function };
779
}
780
```
781
782
## Usage Examples
783
784
### Basic Specification Parsing
785
786
```typescript
787
import { parse } from "vega";
788
789
const spec = {
790
"$schema": "https://vega.github.io/schema/vega/v5.json",
791
"width": 400,
792
"height": 200,
793
"data": [
794
{
795
"name": "table",
796
"values": [
797
{"category": "A", "amount": 28},
798
{"category": "B", "amount": 55},
799
{"category": "C", "amount": 43}
800
]
801
}
802
],
803
"scales": [
804
{
805
"name": "xscale",
806
"type": "band",
807
"domain": {"data": "table", "field": "category"},
808
"range": "width",
809
"padding": 0.1
810
},
811
{
812
"name": "yscale",
813
"type": "linear",
814
"domain": {"data": "table", "field": "amount"},
815
"range": "height"
816
}
817
],
818
"marks": [
819
{
820
"type": "rect",
821
"from": {"data": "table"},
822
"encode": {
823
"enter": {
824
"x": {"scale": "xscale", "field": "category"},
825
"width": {"scale": "xscale", "band": 1},
826
"y": {"scale": "yscale", "field": "amount"},
827
"y2": {"scale": "yscale", "value": 0},
828
"fill": {"value": "steelblue"}
829
}
830
}
831
}
832
]
833
};
834
835
const runtime = parse(spec);
836
console.log(runtime.operators.length); // Number of created operators
837
```
838
839
### Configuration Merging
840
841
```typescript
842
import { parse } from "vega";
843
844
const spec = {
845
// ... specification
846
};
847
848
const config = {
849
view: {
850
width: 600,
851
height: 400,
852
background: "#f5f5f5"
853
},
854
mark: {
855
fill: "steelblue",
856
stroke: "white",
857
strokeWidth: 2
858
},
859
axis: {
860
labelFont: "Arial",
861
labelFontSize: 12,
862
titleFont: "Arial",
863
titleFontSize: 14
864
}
865
};
866
867
const runtime = parse(spec, config);
868
```
869
870
### Custom Functions
871
872
```typescript
873
import { parse } from "vega";
874
875
const customFunctions = {
876
myCustomFunction: (value) => {
877
return value * 2 + 10;
878
},
879
formatCurrency: (value) => {
880
return new Intl.NumberFormat('en-US', {
881
style: 'currency',
882
currency: 'USD'
883
}).format(value);
884
}
885
};
886
887
const runtime = parse(spec, null, {
888
functions: customFunctions
889
});
890
```
891
892
### AST Mode
893
894
```typescript
895
import { parse } from "vega";
896
897
// Parse to AST instead of executable runtime
898
const ast = parse(spec, null, { ast: true });
899
console.log(ast); // Abstract syntax tree representation
900
```
901
902
### Complex Data Specification
903
904
```typescript
905
const spec = {
906
"data": [
907
{
908
"name": "source",
909
"url": "data/cars.json"
910
},
911
{
912
"name": "filtered",
913
"source": "source",
914
"transform": [
915
{"type": "filter", "expr": "datum.year > 1970"},
916
{"type": "aggregate", "groupby": ["origin"], "ops": ["mean"], "fields": ["mpg"], "as": ["avg_mpg"]}
917
]
918
}
919
],
920
"scales": [
921
{
922
"name": "x",
923
"type": "linear",
924
"domain": {"data": "filtered", "field": "avg_mpg"},
925
"range": "width"
926
},
927
{
928
"name": "y",
929
"type": "band",
930
"domain": {"data": "filtered", "field": "origin", "sort": {"field": "avg_mpg", "order": "descending"}},
931
"range": "height",
932
"padding": 0.1
933
}
934
]
935
// ... marks
936
};
937
938
const runtime = parse(spec);
939
```
940
941
### Signal-Driven Interactivity
942
943
```typescript
944
const interactiveSpec = {
945
"signals": [
946
{
947
"name": "selectedCategory",
948
"value": null,
949
"on": [
950
{"events": "rect:click", "update": "datum.category"}
951
]
952
},
953
{
954
"name": "highlightOpacity",
955
"value": 0.8,
956
"on": [
957
{"events": "rect:mouseover", "update": "1.0"},
958
{"events": "rect:mouseout", "update": "0.8"}
959
]
960
}
961
],
962
"marks": [
963
{
964
"type": "rect",
965
"encode": {
966
"enter": {
967
"fill": {"value": "steelblue"}
968
},
969
"update": {
970
"fillOpacity": [
971
{"test": "datum.category === selectedCategory", "value": 1.0},
972
{"signal": "highlightOpacity"}
973
]
974
}
975
}
976
}
977
]
978
};
979
980
const runtime = parse(interactiveSpec);
981
```
982
983
### Custom Mark Configuration
984
985
```typescript
986
const configuredSpec = {
987
"config": {
988
"mark": {
989
"tooltip": true
990
},
991
"rect": {
992
"fill": "lightblue",
993
"stroke": "navy",
994
"strokeWidth": 1,
995
"cornerRadius": 3
996
},
997
"text": {
998
"font": "Helvetica",
999
"fontSize": 12,
1000
"fill": "black"
1001
}
1002
},
1003
// ... rest of specification
1004
};
1005
1006
const runtime = parse(configuredSpec);
1007
```
1008
1009
### Runtime Context Usage
1010
1011
```typescript
1012
import { runtimeContext } from "vega";
1013
1014
// Create custom runtime context
1015
const context = runtimeContext(
1016
dataflow,
1017
signalRegistry,
1018
dataRegistry,
1019
(name) => mutatingOperators.has(name)
1020
);
1021
1022
// Use context for expression evaluation
1023
const expressionResult = evaluateExpression("datum.value * signal('multiplier')", context);
1024
```