gofish-ir 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +56 -0
- package/dist/frontend/examples.d.ts +48 -0
- package/dist/frontend/examples.d.ts.map +1 -0
- package/dist/frontend/examples.js +140 -0
- package/dist/frontend/index.d.ts +5 -0
- package/dist/frontend/index.d.ts.map +1 -0
- package/dist/frontend/index.js +4 -0
- package/dist/frontend/jsonSchema.d.ts +393 -0
- package/dist/frontend/jsonSchema.d.ts.map +1 -0
- package/dist/frontend/jsonSchema.js +288 -0
- package/dist/frontend/schema.d.ts +255 -0
- package/dist/frontend/schema.d.ts.map +1 -0
- package/dist/frontend/schema.js +69 -0
- package/dist/frontend/v0.json +506 -0
- package/dist/frontend/validate.d.ts +27 -0
- package/dist/frontend/validate.d.ts.map +1 -0
- package/dist/frontend/validate.js +591 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1 -0
- package/package.json +43 -0
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
// <gofish-wiki> AUTO-GENERATED — see covers: in the essay; run `pnpm --filter docs sync-backlinks`
|
|
2
|
+
// @wiki Frontend IR — /internals/frontend/serialization
|
|
3
|
+
// </gofish-wiki>
|
|
4
|
+
/**
|
|
5
|
+
* Hand-written JSON Schema for the GoFish frontend IR (v0).
|
|
6
|
+
*
|
|
7
|
+
* Structural only — defines the document shape, the discriminator unions
|
|
8
|
+
* for operators / marks / channel values, and the validity envelope. Full
|
|
9
|
+
* field-level coverage matches `validate.ts`; this file is the wire
|
|
10
|
+
* artifact (consumed by external tooling, language servers, and the
|
|
11
|
+
* Python wrapper's parity-test harness).
|
|
12
|
+
*/
|
|
13
|
+
export const FRONTEND_IR_JSON_SCHEMA = {
|
|
14
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
15
|
+
$id: "https://gofish.graphics/schema/frontend/v0.json",
|
|
16
|
+
title: "GoFish Frontend IR",
|
|
17
|
+
description: "Source-level chart specification produced by the v3 fluent API.",
|
|
18
|
+
type: "object",
|
|
19
|
+
required: ["irVersion", "ir", "root"],
|
|
20
|
+
additionalProperties: false,
|
|
21
|
+
properties: {
|
|
22
|
+
irVersion: { const: 0 },
|
|
23
|
+
ir: { const: "gofish-frontend" },
|
|
24
|
+
$schema: { type: "string" },
|
|
25
|
+
root: { $ref: "#/$defs/Root" },
|
|
26
|
+
},
|
|
27
|
+
$defs: {
|
|
28
|
+
Root: {
|
|
29
|
+
oneOf: [
|
|
30
|
+
{ $ref: "#/$defs/ChartIR" },
|
|
31
|
+
{ $ref: "#/$defs/LayerIR" },
|
|
32
|
+
{ $ref: "#/$defs/RawMarkIR" },
|
|
33
|
+
],
|
|
34
|
+
},
|
|
35
|
+
Origin: {
|
|
36
|
+
type: "object",
|
|
37
|
+
properties: {
|
|
38
|
+
name: { type: "string" },
|
|
39
|
+
stack: { type: "string" },
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
Meta: {
|
|
43
|
+
type: "object",
|
|
44
|
+
description: "Optional inline annotations populated by later passes. v0 emitters leave it absent.",
|
|
45
|
+
},
|
|
46
|
+
DataIR: {
|
|
47
|
+
oneOf: [
|
|
48
|
+
{
|
|
49
|
+
type: "object",
|
|
50
|
+
required: ["type", "rows"],
|
|
51
|
+
properties: {
|
|
52
|
+
type: { const: "inline" },
|
|
53
|
+
rows: { type: "array", items: { type: "object" } },
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
type: "object",
|
|
58
|
+
required: ["type", "layer"],
|
|
59
|
+
properties: {
|
|
60
|
+
type: { const: "select" },
|
|
61
|
+
layer: { type: "string" },
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
type: "object",
|
|
66
|
+
required: ["type"],
|
|
67
|
+
properties: {
|
|
68
|
+
type: { const: "external" },
|
|
69
|
+
id: { type: "string" },
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
},
|
|
74
|
+
ChartIR: {
|
|
75
|
+
type: "object",
|
|
76
|
+
required: ["type", "mark"],
|
|
77
|
+
properties: {
|
|
78
|
+
type: { const: "chart" },
|
|
79
|
+
data: { oneOf: [{ $ref: "#/$defs/DataIR" }, { type: "null" }] },
|
|
80
|
+
operators: { type: "array", items: { $ref: "#/$defs/OperatorIR" } },
|
|
81
|
+
mark: { $ref: "#/$defs/MarkIR" },
|
|
82
|
+
options: { type: "object" },
|
|
83
|
+
zOrder: { type: "number" },
|
|
84
|
+
origin: { $ref: "#/$defs/Origin" },
|
|
85
|
+
meta: { $ref: "#/$defs/Meta" },
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
LayerIR: {
|
|
89
|
+
type: "object",
|
|
90
|
+
required: ["type", "charts"],
|
|
91
|
+
properties: {
|
|
92
|
+
type: { const: "layer" },
|
|
93
|
+
charts: { type: "array", items: { $ref: "#/$defs/ChartIR" } },
|
|
94
|
+
options: { type: "object" },
|
|
95
|
+
origin: { $ref: "#/$defs/Origin" },
|
|
96
|
+
meta: { $ref: "#/$defs/Meta" },
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
RawMarkIR: {
|
|
100
|
+
type: "object",
|
|
101
|
+
required: ["type", "mark"],
|
|
102
|
+
properties: {
|
|
103
|
+
type: { const: "raw-mark" },
|
|
104
|
+
mark: { $ref: "#/$defs/MarkIR" },
|
|
105
|
+
options: { type: "object" },
|
|
106
|
+
origin: { $ref: "#/$defs/Origin" },
|
|
107
|
+
meta: { $ref: "#/$defs/Meta" },
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
OperatorIR: {
|
|
111
|
+
type: "object",
|
|
112
|
+
required: ["type"],
|
|
113
|
+
properties: {
|
|
114
|
+
type: {
|
|
115
|
+
enum: [
|
|
116
|
+
"derive",
|
|
117
|
+
"spread",
|
|
118
|
+
"stack",
|
|
119
|
+
"group",
|
|
120
|
+
"scatter",
|
|
121
|
+
"table",
|
|
122
|
+
"log",
|
|
123
|
+
],
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
MarkIR: {
|
|
128
|
+
oneOf: [
|
|
129
|
+
{ $ref: "#/$defs/LeafMarkIR" },
|
|
130
|
+
{ $ref: "#/$defs/CombinatorMarkIR" },
|
|
131
|
+
{ $ref: "#/$defs/RefMarkIR" },
|
|
132
|
+
],
|
|
133
|
+
},
|
|
134
|
+
LeafMarkIR: {
|
|
135
|
+
type: "object",
|
|
136
|
+
required: ["type"],
|
|
137
|
+
properties: {
|
|
138
|
+
type: {
|
|
139
|
+
enum: [
|
|
140
|
+
"rect",
|
|
141
|
+
"circle",
|
|
142
|
+
"line",
|
|
143
|
+
"area",
|
|
144
|
+
"blank",
|
|
145
|
+
"ellipse",
|
|
146
|
+
"petal",
|
|
147
|
+
"text",
|
|
148
|
+
"image",
|
|
149
|
+
"polygon",
|
|
150
|
+
"mark-fn",
|
|
151
|
+
],
|
|
152
|
+
},
|
|
153
|
+
name: { type: "string" },
|
|
154
|
+
label: { $ref: "#/$defs/LabelIR" },
|
|
155
|
+
constraints: {
|
|
156
|
+
type: "array",
|
|
157
|
+
items: { $ref: "#/$defs/ConstraintIR" },
|
|
158
|
+
},
|
|
159
|
+
zOrder: { type: "number" },
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
CombinatorMarkIR: {
|
|
163
|
+
type: "object",
|
|
164
|
+
required: ["type", "__combinator", "children"],
|
|
165
|
+
properties: {
|
|
166
|
+
type: {
|
|
167
|
+
enum: [
|
|
168
|
+
"spread",
|
|
169
|
+
"stack",
|
|
170
|
+
"scatter",
|
|
171
|
+
"group",
|
|
172
|
+
"table",
|
|
173
|
+
"layer",
|
|
174
|
+
"arrow",
|
|
175
|
+
"connect",
|
|
176
|
+
"treemap",
|
|
177
|
+
"over",
|
|
178
|
+
"inside",
|
|
179
|
+
"xor",
|
|
180
|
+
"out",
|
|
181
|
+
"atop",
|
|
182
|
+
"mask",
|
|
183
|
+
],
|
|
184
|
+
},
|
|
185
|
+
__combinator: { const: true },
|
|
186
|
+
options: { type: "object" },
|
|
187
|
+
children: { type: "array", items: { $ref: "#/$defs/MarkIR" } },
|
|
188
|
+
name: { type: "string" },
|
|
189
|
+
label: { $ref: "#/$defs/LabelIR" },
|
|
190
|
+
constraints: {
|
|
191
|
+
type: "array",
|
|
192
|
+
items: { $ref: "#/$defs/ConstraintIR" },
|
|
193
|
+
},
|
|
194
|
+
zOrder: { type: "number" },
|
|
195
|
+
},
|
|
196
|
+
},
|
|
197
|
+
RefMarkIR: {
|
|
198
|
+
type: "object",
|
|
199
|
+
required: ["type", "selection"],
|
|
200
|
+
properties: {
|
|
201
|
+
type: { const: "ref" },
|
|
202
|
+
selection: {
|
|
203
|
+
oneOf: [
|
|
204
|
+
{ type: "string" },
|
|
205
|
+
{
|
|
206
|
+
type: "array",
|
|
207
|
+
items: { oneOf: [{ type: "string" }, { type: "number" }] },
|
|
208
|
+
},
|
|
209
|
+
],
|
|
210
|
+
},
|
|
211
|
+
name: { type: "string" },
|
|
212
|
+
label: { $ref: "#/$defs/LabelIR" },
|
|
213
|
+
zOrder: { type: "number" },
|
|
214
|
+
},
|
|
215
|
+
},
|
|
216
|
+
LabelIR: {
|
|
217
|
+
// Three shapes: the canonical object form, a boolean shorthand
|
|
218
|
+
// (`label: true` — let the mark shape decide what to label), and
|
|
219
|
+
// a string shorthand (`label: "field"` — use this field accessor
|
|
220
|
+
// with default styling). All three match `LabelIR` in schema.ts.
|
|
221
|
+
oneOf: [
|
|
222
|
+
{ type: "boolean" },
|
|
223
|
+
{ type: "string" },
|
|
224
|
+
{
|
|
225
|
+
type: "object",
|
|
226
|
+
required: ["accessor"],
|
|
227
|
+
properties: {
|
|
228
|
+
accessor: { type: "string" },
|
|
229
|
+
position: { type: "string" },
|
|
230
|
+
fontSize: { type: "number" },
|
|
231
|
+
color: { type: "string" },
|
|
232
|
+
offset: { type: "number" },
|
|
233
|
+
minSpace: { type: "number" },
|
|
234
|
+
rotate: { type: "number" },
|
|
235
|
+
},
|
|
236
|
+
},
|
|
237
|
+
],
|
|
238
|
+
},
|
|
239
|
+
ConstraintIR: {
|
|
240
|
+
type: "object",
|
|
241
|
+
required: ["type", "refs"],
|
|
242
|
+
properties: {
|
|
243
|
+
type: { enum: ["align", "distribute", "zAbove", "zBelow"] },
|
|
244
|
+
options: { type: "object" },
|
|
245
|
+
refs: { type: "array", items: { type: "string" } },
|
|
246
|
+
},
|
|
247
|
+
},
|
|
248
|
+
ChannelValue: {
|
|
249
|
+
description: "Right-hand side of a channel slot. Bare primitives for the shorthand path; tagged objects for the explicit field/datum/literal constructors and Python-bridge sentinels.",
|
|
250
|
+
oneOf: [
|
|
251
|
+
{ type: "string" },
|
|
252
|
+
{ type: "number" },
|
|
253
|
+
{ type: "boolean" },
|
|
254
|
+
{ type: "null" },
|
|
255
|
+
{
|
|
256
|
+
type: "object",
|
|
257
|
+
required: ["type", "name"],
|
|
258
|
+
properties: {
|
|
259
|
+
type: { const: "field" },
|
|
260
|
+
name: { type: "string" },
|
|
261
|
+
},
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
type: "object",
|
|
265
|
+
required: ["type", "value"],
|
|
266
|
+
properties: {
|
|
267
|
+
type: { const: "literal" },
|
|
268
|
+
value: {},
|
|
269
|
+
},
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
type: "object",
|
|
273
|
+
required: ["type", "datum"],
|
|
274
|
+
properties: {
|
|
275
|
+
type: { const: "datum" },
|
|
276
|
+
datum: {},
|
|
277
|
+
measure: { type: "string" },
|
|
278
|
+
},
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
type: "object",
|
|
282
|
+
required: ["__gofish_lambda"],
|
|
283
|
+
properties: { __gofish_lambda: { type: "string" } },
|
|
284
|
+
},
|
|
285
|
+
],
|
|
286
|
+
},
|
|
287
|
+
},
|
|
288
|
+
};
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GoFish Frontend IR — schema types.
|
|
3
|
+
*
|
|
4
|
+
* The frontend IR captures a GoFish chart specification at the source level,
|
|
5
|
+
* before macro expansion and elaboration. v0 mirrors the existing widget
|
|
6
|
+
* wire format exactly (lowercase type tags, __combinator flag, channel
|
|
7
|
+
* slots accept strings/numbers/sentinels). See the architecture essay for
|
|
8
|
+
* the multi-stage design and the planned v0.1+ improvements.
|
|
9
|
+
*/
|
|
10
|
+
/** Top-level wrapper for a serialized GoFish chart. */
|
|
11
|
+
export interface FrontendIRDocument {
|
|
12
|
+
irVersion: 0;
|
|
13
|
+
ir: "gofish-frontend";
|
|
14
|
+
/** Optional URL of the JSON Schema this document claims to conform to. */
|
|
15
|
+
$schema?: string;
|
|
16
|
+
root: FrontendIR;
|
|
17
|
+
}
|
|
18
|
+
/** A frontend-IR root is a chart, a multi-chart layer, or a bare mark. */
|
|
19
|
+
export type FrontendIR = ChartIR | LayerIR | RawMarkIR;
|
|
20
|
+
/**
|
|
21
|
+
* Metadata that any node may carry. v0 emitters leave `meta` unset; later
|
|
22
|
+
* passes (underlying-space inference, scale resolution, etc.) populate the
|
|
23
|
+
* relevant fields. The slot is reserved so additive evolution doesn't
|
|
24
|
+
* require a schema bump.
|
|
25
|
+
*/
|
|
26
|
+
export interface Meta {
|
|
27
|
+
/** Source-position attribution — populated by future build-time hooks. */
|
|
28
|
+
loc?: SourceLocation;
|
|
29
|
+
/** Underlying-space classification — populated post-elaboration. */
|
|
30
|
+
space?: UnderlyingSpaceAnnotation;
|
|
31
|
+
/** Open extension for unknown pass-specific annotations. */
|
|
32
|
+
[key: string]: unknown;
|
|
33
|
+
}
|
|
34
|
+
export interface SourceLocation {
|
|
35
|
+
file: string;
|
|
36
|
+
line: number;
|
|
37
|
+
column: number;
|
|
38
|
+
}
|
|
39
|
+
export interface UnderlyingSpaceAnnotation {
|
|
40
|
+
type: "SIZE" | "POSITION" | "ORDINAL" | "DIFFERENCE" | "UNDEFINED";
|
|
41
|
+
}
|
|
42
|
+
/** Mixin properties available on every IR node. */
|
|
43
|
+
export interface BaseIRNode {
|
|
44
|
+
/** User-supplied origin metadata. Currently carries the `.name(...)` value if set. */
|
|
45
|
+
origin?: Origin;
|
|
46
|
+
/** Reserved for inline annotations attached by future passes. */
|
|
47
|
+
meta?: Meta;
|
|
48
|
+
}
|
|
49
|
+
export interface Origin {
|
|
50
|
+
/** User-supplied name via `.name("bars")` on the v3 fluent builder. */
|
|
51
|
+
name?: string;
|
|
52
|
+
/** Optional captured call-site stack — unset in v0. */
|
|
53
|
+
stack?: string;
|
|
54
|
+
}
|
|
55
|
+
/** A standard chart: data → operators → mark. */
|
|
56
|
+
export interface ChartIR extends BaseIRNode {
|
|
57
|
+
type: "chart";
|
|
58
|
+
data?: DataIR | null;
|
|
59
|
+
operators?: OperatorIR[];
|
|
60
|
+
mark: MarkIR;
|
|
61
|
+
options?: Record<string, unknown>;
|
|
62
|
+
zOrder?: number;
|
|
63
|
+
}
|
|
64
|
+
/** Multiple charts composed on the same canvas. */
|
|
65
|
+
export interface LayerIR extends BaseIRNode {
|
|
66
|
+
type: "layer";
|
|
67
|
+
charts: ChartIR[];
|
|
68
|
+
options?: Record<string, unknown>;
|
|
69
|
+
}
|
|
70
|
+
/** A bare mark, used when no chart-level wrapping is needed. */
|
|
71
|
+
export interface RawMarkIR extends BaseIRNode {
|
|
72
|
+
type: "raw-mark";
|
|
73
|
+
mark: MarkIR;
|
|
74
|
+
options?: Record<string, unknown>;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* The data field on a chart.
|
|
78
|
+
*
|
|
79
|
+
* - **Inline rows**: `{type: "inline", rows: [...]}` for charts whose data is
|
|
80
|
+
* embedded in the IR.
|
|
81
|
+
* - **Select reference**: `{type: "select", layer: "name"}` resolves a sibling
|
|
82
|
+
* chart's named-mark output at deserialize time.
|
|
83
|
+
* - **External**: `{type: "external", id?: "..."}` indicates data ships over a
|
|
84
|
+
* sidecar transport (anywidget's `arrow_data` trait) and the id keys into it.
|
|
85
|
+
*/
|
|
86
|
+
export type DataIR = {
|
|
87
|
+
type: "inline";
|
|
88
|
+
rows: Array<Record<string, unknown>>;
|
|
89
|
+
} | {
|
|
90
|
+
type: "select";
|
|
91
|
+
layer: string;
|
|
92
|
+
} | {
|
|
93
|
+
type: "external";
|
|
94
|
+
id?: string;
|
|
95
|
+
};
|
|
96
|
+
export type OperatorIR = DeriveOperator | SpreadOperator | StackOperator | GroupOperator | ScatterOperator | TableOperator | LogOperator;
|
|
97
|
+
/**
|
|
98
|
+
* `derive(fn)` — opaque user transformation. Function bodies are not
|
|
99
|
+
* serializable; the IR carries a bridge handle (`lambdaId`) when the
|
|
100
|
+
* Python widget is the producer, and is otherwise empty.
|
|
101
|
+
*/
|
|
102
|
+
export interface DeriveOperator extends BaseIRNode {
|
|
103
|
+
type: "derive";
|
|
104
|
+
lambdaId?: string;
|
|
105
|
+
}
|
|
106
|
+
export interface SpreadOperator extends BaseIRNode {
|
|
107
|
+
type: "spread";
|
|
108
|
+
by?: string;
|
|
109
|
+
dir?: "x" | "y";
|
|
110
|
+
spacing?: number;
|
|
111
|
+
alignment?: string;
|
|
112
|
+
sharedScale?: boolean;
|
|
113
|
+
mode?: "edge" | "center";
|
|
114
|
+
reverse?: boolean;
|
|
115
|
+
}
|
|
116
|
+
export interface StackOperator extends BaseIRNode {
|
|
117
|
+
type: "stack";
|
|
118
|
+
by?: string;
|
|
119
|
+
dir?: "x" | "y";
|
|
120
|
+
alignment?: string;
|
|
121
|
+
sharedScale?: boolean;
|
|
122
|
+
mode?: "edge" | "center";
|
|
123
|
+
reverse?: boolean;
|
|
124
|
+
}
|
|
125
|
+
export interface GroupOperator extends BaseIRNode {
|
|
126
|
+
type: "group";
|
|
127
|
+
by: string;
|
|
128
|
+
}
|
|
129
|
+
export interface ScatterOperator extends BaseIRNode {
|
|
130
|
+
type: "scatter";
|
|
131
|
+
by?: string;
|
|
132
|
+
x?: ChannelValue;
|
|
133
|
+
y?: ChannelValue;
|
|
134
|
+
xMin?: ChannelValue;
|
|
135
|
+
xMax?: ChannelValue;
|
|
136
|
+
yMin?: ChannelValue;
|
|
137
|
+
yMax?: ChannelValue;
|
|
138
|
+
alignment?: string;
|
|
139
|
+
}
|
|
140
|
+
export interface TableOperator extends BaseIRNode {
|
|
141
|
+
type: "table";
|
|
142
|
+
by: {
|
|
143
|
+
x: string;
|
|
144
|
+
y: string;
|
|
145
|
+
};
|
|
146
|
+
spacing?: number | [number, number];
|
|
147
|
+
numCols?: number;
|
|
148
|
+
}
|
|
149
|
+
export interface LogOperator extends BaseIRNode {
|
|
150
|
+
type: "log";
|
|
151
|
+
label?: string;
|
|
152
|
+
}
|
|
153
|
+
export type MarkIR = LeafMarkIR | CombinatorMarkIR | RefMarkIR;
|
|
154
|
+
export type LeafMarkType = "rect" | "circle" | "line" | "area" | "blank" | "ellipse" | "petal" | "text" | "image" | "polygon" | "mark-fn";
|
|
155
|
+
export type CombinatorMarkType = "spread" | "stack" | "scatter" | "group" | "table" | "layer" | "arrow" | "connect" | "treemap" | "over" | "inside" | "xor" | "out" | "atop" | "mask";
|
|
156
|
+
/**
|
|
157
|
+
* A leaf shape mark. Channel-valued props (`h`, `w`, `fill`, `x`, `y`, …)
|
|
158
|
+
* appear directly on the object alongside the well-known fields. TypeScript
|
|
159
|
+
* cannot precisely express the union of channel values per shape, so the
|
|
160
|
+
* index signature is permissive — mirrors the existing widget interface.
|
|
161
|
+
*/
|
|
162
|
+
export interface LeafMarkIR extends BaseIRNode {
|
|
163
|
+
type: LeafMarkType;
|
|
164
|
+
name?: string;
|
|
165
|
+
label?: LabelIR;
|
|
166
|
+
constraints?: ConstraintIR[];
|
|
167
|
+
zOrder?: number;
|
|
168
|
+
[key: string]: unknown;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* A combinator-form operator used as a mark (e.g. `spread([m1, m2])`).
|
|
172
|
+
* Distinguished from the operator-form by the `__combinator: true` flag
|
|
173
|
+
* and the presence of `children`.
|
|
174
|
+
*/
|
|
175
|
+
export interface CombinatorMarkIR extends BaseIRNode {
|
|
176
|
+
type: CombinatorMarkType;
|
|
177
|
+
__combinator: true;
|
|
178
|
+
options?: Record<string, unknown>;
|
|
179
|
+
children: MarkIR[];
|
|
180
|
+
name?: string;
|
|
181
|
+
label?: LabelIR;
|
|
182
|
+
constraints?: ConstraintIR[];
|
|
183
|
+
zOrder?: number;
|
|
184
|
+
}
|
|
185
|
+
/** A by-name reference to another named mark (`ref("bars")`). */
|
|
186
|
+
export interface RefMarkIR extends BaseIRNode {
|
|
187
|
+
type: "ref";
|
|
188
|
+
selection: string | Array<string | number>;
|
|
189
|
+
name?: string;
|
|
190
|
+
label?: LabelIR;
|
|
191
|
+
zOrder?: number;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* A channel value (the right-hand side of a mark or operator property like
|
|
195
|
+
* `h: …` or `fill: …`).
|
|
196
|
+
*
|
|
197
|
+
* Strings without explicit tagging disambiguate to field-accessor or
|
|
198
|
+
* literal at runtime by checking against `data[0]`. The explicit
|
|
199
|
+
* constructors `field(name)` / `datum(x)` / `literal(x)` emit their
|
|
200
|
+
* canonical tagged-object forms. `__gofish_lambda` is the one remaining
|
|
201
|
+
* Python-bridge sentinel — it encodes a remote callable that the widget
|
|
202
|
+
* resolves via the DeriveBridge.
|
|
203
|
+
*
|
|
204
|
+
* v0.1+ will move the v3 API to desugar string shorthand to explicit
|
|
205
|
+
* constructors eagerly, so the IR carries only canonical forms.
|
|
206
|
+
*/
|
|
207
|
+
export type ChannelValue = string | number | boolean | null | DatumValue | BridgeLambdaSentinel;
|
|
208
|
+
export interface DatumValue {
|
|
209
|
+
type: "datum";
|
|
210
|
+
[key: string]: unknown;
|
|
211
|
+
}
|
|
212
|
+
/** Python-bridge sentinel for a remote callable. The JS side issues an RPC for each datum. */
|
|
213
|
+
export interface BridgeLambdaSentinel {
|
|
214
|
+
__gofish_lambda: string;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Label specification.
|
|
218
|
+
*
|
|
219
|
+
* The canonical object form `{accessor, position?, fontSize?, ...}` is
|
|
220
|
+
* what `mark.label("field", options)` produces. Shorthand forms (matching
|
|
221
|
+
* the JS mark-kwarg API):
|
|
222
|
+
*
|
|
223
|
+
* label: true — show a label with default styling
|
|
224
|
+
* label: "field" — label using this field accessor, defaults elsewhere
|
|
225
|
+
*/
|
|
226
|
+
export type LabelIR = true | string | {
|
|
227
|
+
accessor: string;
|
|
228
|
+
position?: string;
|
|
229
|
+
fontSize?: number;
|
|
230
|
+
color?: string;
|
|
231
|
+
offset?: number;
|
|
232
|
+
minSpace?: number;
|
|
233
|
+
rotate?: number;
|
|
234
|
+
};
|
|
235
|
+
export interface ConstraintIR {
|
|
236
|
+
type: "align" | "distribute" | "zAbove" | "zBelow";
|
|
237
|
+
/** Positioning constraints carry `options`; z-order constraints don't. */
|
|
238
|
+
options?: Record<string, unknown>;
|
|
239
|
+
refs: string[];
|
|
240
|
+
}
|
|
241
|
+
/** Discriminate a root document. */
|
|
242
|
+
export declare function isChartIR(node: FrontendIR): node is ChartIR;
|
|
243
|
+
export declare function isLayerIR(node: FrontendIR): node is LayerIR;
|
|
244
|
+
export declare function isRawMarkIR(node: FrontendIR): node is RawMarkIR;
|
|
245
|
+
/** Discriminate a mark by family. */
|
|
246
|
+
export declare function isCombinatorMarkIR(mark: MarkIR): mark is CombinatorMarkIR;
|
|
247
|
+
export declare function isRefMarkIR(mark: MarkIR): mark is RefMarkIR;
|
|
248
|
+
export declare function isLeafMarkIR(mark: MarkIR): mark is LeafMarkIR;
|
|
249
|
+
/** The set of operator type discriminators recognized in v0. */
|
|
250
|
+
export declare const OPERATOR_TYPES: readonly ["derive", "spread", "stack", "group", "scatter", "table", "log"];
|
|
251
|
+
/** The set of leaf-mark type discriminators recognized in v0. */
|
|
252
|
+
export declare const LEAF_MARK_TYPES: readonly LeafMarkType[];
|
|
253
|
+
/** The set of combinator-mark type discriminators recognized in v0. */
|
|
254
|
+
export declare const COMBINATOR_MARK_TYPES: readonly CombinatorMarkType[];
|
|
255
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/frontend/schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// <gofish-wiki> AUTO-GENERATED — see covers: in the essay; run `pnpm --filter docs sync-backlinks`
|
|
2
|
+
// @wiki Frontend IR — /internals/frontend/serialization
|
|
3
|
+
// </gofish-wiki>
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
// Discriminator helpers (predicates)
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
/** Discriminate a root document. */
|
|
8
|
+
export function isChartIR(node) {
|
|
9
|
+
return node.type === "chart";
|
|
10
|
+
}
|
|
11
|
+
export function isLayerIR(node) {
|
|
12
|
+
return node.type === "layer";
|
|
13
|
+
}
|
|
14
|
+
export function isRawMarkIR(node) {
|
|
15
|
+
return node.type === "raw-mark";
|
|
16
|
+
}
|
|
17
|
+
/** Discriminate a mark by family. */
|
|
18
|
+
export function isCombinatorMarkIR(mark) {
|
|
19
|
+
return (mark.__combinator === true &&
|
|
20
|
+
Array.isArray(mark.children));
|
|
21
|
+
}
|
|
22
|
+
export function isRefMarkIR(mark) {
|
|
23
|
+
return mark.type === "ref";
|
|
24
|
+
}
|
|
25
|
+
export function isLeafMarkIR(mark) {
|
|
26
|
+
return !isCombinatorMarkIR(mark) && !isRefMarkIR(mark);
|
|
27
|
+
}
|
|
28
|
+
/** The set of operator type discriminators recognized in v0. */
|
|
29
|
+
export const OPERATOR_TYPES = [
|
|
30
|
+
"derive",
|
|
31
|
+
"spread",
|
|
32
|
+
"stack",
|
|
33
|
+
"group",
|
|
34
|
+
"scatter",
|
|
35
|
+
"table",
|
|
36
|
+
"log",
|
|
37
|
+
];
|
|
38
|
+
/** The set of leaf-mark type discriminators recognized in v0. */
|
|
39
|
+
export const LEAF_MARK_TYPES = [
|
|
40
|
+
"rect",
|
|
41
|
+
"circle",
|
|
42
|
+
"line",
|
|
43
|
+
"area",
|
|
44
|
+
"blank",
|
|
45
|
+
"ellipse",
|
|
46
|
+
"petal",
|
|
47
|
+
"text",
|
|
48
|
+
"image",
|
|
49
|
+
"polygon",
|
|
50
|
+
"mark-fn",
|
|
51
|
+
];
|
|
52
|
+
/** The set of combinator-mark type discriminators recognized in v0. */
|
|
53
|
+
export const COMBINATOR_MARK_TYPES = [
|
|
54
|
+
"spread",
|
|
55
|
+
"stack",
|
|
56
|
+
"scatter",
|
|
57
|
+
"group",
|
|
58
|
+
"table",
|
|
59
|
+
"layer",
|
|
60
|
+
"arrow",
|
|
61
|
+
"connect",
|
|
62
|
+
"treemap",
|
|
63
|
+
"over",
|
|
64
|
+
"inside",
|
|
65
|
+
"xor",
|
|
66
|
+
"out",
|
|
67
|
+
"atop",
|
|
68
|
+
"mask",
|
|
69
|
+
];
|