@inflexa-ai/harness 0.42.2 → 0.43.1
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 +2 -2
- package/dist/agents/sandbox/shared.d.ts +1 -6
- package/dist/agents/sandbox/shared.js +0 -15
- package/dist/app/chat-turn.js +13 -1
- package/dist/config/environment-stores.d.ts +4 -2
- package/dist/contracts/chat-events.d.ts +9 -1
- package/dist/contracts/chat-frame.d.ts +3 -3
- package/dist/contracts/chat-frame.js +8 -3
- package/dist/contracts/chat-parts.d.ts +4 -1
- package/dist/contracts/data-profile.d.ts +4 -6
- package/dist/contracts/index.d.ts +1 -1
- package/dist/contracts/report-blocks.d.ts +1364 -75
- package/dist/contracts/report-blocks.js +221 -29
- package/dist/contracts/report-reference.js +1 -1
- package/dist/contracts/schemas/chat-events.d.ts +13 -0
- package/dist/contracts/schemas/chat-events.js +5 -0
- package/dist/contracts/schemas/chat-parts.d.ts +2 -2
- package/dist/contracts/schemas/index.d.ts +1 -1
- package/dist/contracts/schemas/index.js +1 -1
- package/dist/execution/input-signature.d.ts +7 -13
- package/dist/execution/input-signature.js +0 -0
- package/dist/execution/run-canceler.d.ts +3 -2
- package/dist/execution/run-canceler.js +3 -2
- package/dist/execution/run-event-stream.d.ts +16 -2
- package/dist/execution/run-event-stream.js +54 -3
- package/dist/index.d.ts +1 -8
- package/dist/index.js +5 -16
- package/dist/input-scan/enrich.d.ts +0 -2
- package/dist/input-scan/enrich.js +0 -1
- package/dist/lib/metrics.js +6 -7
- package/dist/lib/otel-spans.d.ts +4 -9
- package/dist/lib/otel-spans.js +3 -8
- package/dist/loop/run-agent.d.ts +4 -2
- package/dist/loop/run-agent.js +38 -23
- package/dist/memory/thread-history.d.ts +1 -1
- package/dist/prompts/report-session.d.ts +1 -1
- package/dist/prompts/report-session.js +17 -0
- package/dist/provenance/exec-frame.d.ts +1 -1
- package/dist/report-model/authoring-grammar.d.ts +416 -17
- package/dist/report-model/authoring-grammar.js +25 -4
- package/dist/report-model/block-walk.d.ts +20 -4
- package/dist/report-model/block-walk.js +64 -7
- package/dist/report-model/draft-finish.d.ts +6 -2
- package/dist/report-model/draft-finish.js +6 -1
- package/dist/report-model/production-resolver.d.ts +8 -0
- package/dist/report-model/production-resolver.js +1 -1
- package/dist/report-model/validate.d.ts +20 -10
- package/dist/report-model/validate.js +29 -13
- package/dist/report-render/chart-export.d.ts +52 -0
- package/dist/report-render/chart-export.js +192 -0
- package/dist/report-render/chart-presets.d.ts +46 -47
- package/dist/report-render/chart-presets.js +31 -101
- package/dist/report-render/chart-renderers.d.ts +163 -0
- package/dist/report-render/chart-renderers.js +1055 -0
- package/dist/report-render/chart-toolbox.d.ts +124 -0
- package/dist/report-render/chart-toolbox.js +595 -0
- package/dist/report-render/chart.d.ts +60 -27
- package/dist/report-render/chart.js +2323 -524
- package/dist/report-render/design.d.ts +476 -16
- package/dist/report-render/design.js +390 -56
- package/dist/report-render/figures/common.d.ts +321 -0
- package/dist/report-render/figures/common.js +759 -0
- package/dist/report-render/figures/dendrogram.d.ts +36 -0
- package/dist/report-render/figures/dendrogram.js +130 -0
- package/dist/report-render/figures/dense.d.ts +111 -0
- package/dist/report-render/figures/dense.js +204 -0
- package/dist/report-render/figures/dotplot.d.ts +28 -0
- package/dist/report-render/figures/dotplot.js +234 -0
- package/dist/report-render/figures/embedding.d.ts +43 -0
- package/dist/report-render/figures/embedding.js +360 -0
- package/dist/report-render/figures/equal-units.d.ts +101 -0
- package/dist/report-render/figures/equal-units.js +215 -0
- package/dist/report-render/figures/forest.d.ts +20 -0
- package/dist/report-render/figures/forest.js +398 -0
- package/dist/report-render/figures/gsea.d.ts +30 -0
- package/dist/report-render/figures/gsea.js +391 -0
- package/dist/report-render/figures/heatmap.d.ts +40 -0
- package/dist/report-render/figures/heatmap.js +395 -0
- package/dist/report-render/figures/index.d.ts +135 -0
- package/dist/report-render/figures/index.js +100 -0
- package/dist/report-render/figures/km.d.ts +16 -0
- package/dist/report-render/figures/km.js +406 -0
- package/dist/report-render/figures/label-room.d.ts +130 -0
- package/dist/report-render/figures/label-room.js +341 -0
- package/dist/report-render/figures/locuszoom.d.ts +50 -0
- package/dist/report-render/figures/locuszoom.js +675 -0
- package/dist/report-render/figures/lollipop.d.ts +16 -0
- package/dist/report-render/figures/lollipop.js +247 -0
- package/dist/report-render/figures/ma.d.ts +20 -0
- package/dist/report-render/figures/ma.js +114 -0
- package/dist/report-render/figures/manhattan.d.ts +60 -0
- package/dist/report-render/figures/manhattan.js +343 -0
- package/dist/report-render/figures/oncoprint.d.ts +41 -0
- package/dist/report-render/figures/oncoprint.js +420 -0
- package/dist/report-render/figures/pca.d.ts +37 -0
- package/dist/report-render/figures/pca.js +241 -0
- package/dist/report-render/figures/qq.d.ts +30 -0
- package/dist/report-render/figures/qq.js +182 -0
- package/dist/report-render/figures/roc.d.ts +17 -0
- package/dist/report-render/figures/roc.js +116 -0
- package/dist/report-render/figures/sankey.d.ts +48 -0
- package/dist/report-render/figures/sankey.js +353 -0
- package/dist/report-render/figures/upset.d.ts +60 -0
- package/dist/report-render/figures/upset.js +316 -0
- package/dist/report-render/figures/volcano.d.ts +25 -0
- package/dist/report-render/figures/volcano.js +166 -0
- package/dist/report-render/hybrid-svg.d.ts +75 -0
- package/dist/report-render/hybrid-svg.js +504 -0
- package/dist/report-render/number-format.d.ts +19 -0
- package/dist/report-render/number-format.js +25 -1
- package/dist/report-render/page.d.ts +41 -4
- package/dist/report-render/page.js +247 -12
- package/dist/report-render/render.d.ts +13 -4
- package/dist/report-render/render.js +37 -6
- package/dist/report-render/types.d.ts +23 -2
- package/dist/report-render/value-bridge.d.ts +38 -3
- package/dist/report-render/value-bridge.js +137 -6
- package/dist/report-render/views/chart-view.d.ts +42 -6
- package/dist/report-render/views/chart-view.js +70 -9
- package/dist/report-render/views/page-view.js +9 -10
- package/dist/runtime/assemble.js +2 -2
- package/dist/sandbox/client.d.ts +23 -32
- package/dist/sandbox/client.js +3 -11
- package/dist/sandbox/create-sandbox.d.ts +9 -24
- package/dist/sandbox/create-sandbox.js +15 -30
- package/dist/sandbox/docker-client.d.ts +12 -22
- package/dist/sandbox/docker-client.js +29 -43
- package/dist/sandbox/exec.d.ts +58 -0
- package/dist/sandbox/exec.js +197 -0
- package/dist/sandbox/identity.d.ts +5 -5
- package/dist/sandbox/identity.js +7 -10
- package/dist/sandbox/k8s-client.d.ts +4 -10
- package/dist/sandbox/k8s-client.js +5 -12
- package/dist/sandbox/liveness.d.ts +5 -12
- package/dist/sandbox/liveness.js +5 -12
- package/dist/sandbox/notification-sweep.d.ts +4 -7
- package/dist/sandbox/notification-sweep.js +4 -7
- package/dist/sandbox/reaper.d.ts +3 -3
- package/dist/sandbox/reaper.js +3 -3
- package/dist/sandbox/sandbox-error.d.ts +10 -11
- package/dist/sandbox/sandbox-error.js +10 -11
- package/dist/sandbox/sandbox-step-translate.d.ts +1 -1
- package/dist/sandbox/sandbox-step-translate.js +1 -1
- package/dist/sandbox/types.d.ts +31 -99
- package/dist/sandbox/types.js +17 -84
- package/dist/state/active-sandboxes.d.ts +7 -32
- package/dist/state/active-sandboxes.js +11 -46
- package/dist/state/index.d.ts +1 -2
- package/dist/state/index.js +1 -1
- package/dist/state/migrations/20261005120000_drop_the_active_exec_tracking.d.ts +7 -0
- package/dist/state/migrations/20261005120000_drop_the_active_exec_tracking.js +12 -0
- package/dist/state/migrations/index.js +2 -0
- package/dist/state/schema.d.ts +1 -5
- package/dist/state/schema.js +1 -6
- package/dist/state/step-executions.js +1 -2
- package/dist/tasks/data-profile.js +7 -20
- package/dist/tasks/derive-table-exec.d.ts +4 -14
- package/dist/tasks/derive-table-exec.js +9 -24
- package/dist/tasks/extract-values.d.ts +2 -2
- package/dist/tasks/extract-values.js +4 -7
- package/dist/tools/define-tool.d.ts +56 -13
- package/dist/tools/define-tool.js +28 -1
- package/dist/tools/execute-analysis.js +3 -3
- package/dist/tools/report-session/derive-table.d.ts +8 -9
- package/dist/tools/report-session/derive-table.js +3 -4
- package/dist/tools/report-session/preview-report.js +4 -49
- package/dist/tools/sandbox/list-available-packages.d.ts +1 -1
- package/dist/tools/sandbox/list-available-packages.js +5 -4
- package/dist/tools/workspace/edit-file.d.ts +5 -4
- package/dist/tools/workspace/edit-file.js +10 -13
- package/dist/tools/workspace/execute-command.d.ts +27 -42
- package/dist/tools/workspace/execute-command.js +42 -38
- package/dist/tools/workspace/index.d.ts +5 -6
- package/dist/tools/workspace/index.js +5 -6
- package/dist/tools/workspace/mutator.d.ts +43 -8
- package/dist/tools/workspace/mutator.js +45 -34
- package/dist/tools/workspace/run-exec.d.ts +3 -12
- package/dist/tools/workspace/run-exec.js +7 -24
- package/dist/tools/workspace/scan-inputs.d.ts +0 -3
- package/dist/tools/workspace/scan-inputs.js +0 -1
- package/dist/tools/workspace/write-file.d.ts +12 -3
- package/dist/tools/workspace/write-file.js +17 -13
- package/dist/workflows/sandbox-step.d.ts +7 -11
- package/dist/workflows/sandbox-step.js +24 -27
- package/package.json +5 -3
- package/dist/sandbox/await-exec.d.ts +0 -143
- package/dist/sandbox/await-exec.js +0 -417
- package/dist/sandbox/deliver-exec-event.d.ts +0 -25
- package/dist/sandbox/deliver-exec-event.js +0 -29
- package/dist/sandbox/digest.d.ts +0 -14
- package/dist/sandbox/digest.js +0 -17
- package/dist/sandbox/exec-id.d.ts +0 -12
- package/dist/sandbox/exec-id.js +0 -20
- package/dist/sandbox/hmac.d.ts +0 -62
- package/dist/sandbox/hmac.js +0 -72
- package/dist/sandbox/submit-exec.d.ts +0 -38
- package/dist/sandbox/submit-exec.js +0 -80
- package/dist/sandbox/watchdog.d.ts +0 -71
- package/dist/sandbox/watchdog.js +0 -161
|
@@ -7,7 +7,10 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { AG_GRID_ASSET, assetSource, ECHARTS_ASSET, TSPROV_ASSET } from "./assets.js";
|
|
9
9
|
import { CHART_SOURCE_MEMBER, POINT_LABEL } from "./chart.js";
|
|
10
|
-
import {
|
|
10
|
+
import { CHART_RENDERERS_SOURCE } from "./chart-renderers.js";
|
|
11
|
+
import { CHART_TOOLBOX_SOURCE, TOOLBOX_ZLEVEL } from "./chart-toolbox.js";
|
|
12
|
+
import { CHART_EXPORT_SIZES, ECHARTS_THEME_NAME, GRID_HEADER_BORDER_PX, GRID_HEADER_HEIGHT_PX, GRID_MIN_COLUMN_WIDTH_PX, GRID_PRINT_ROW_CAP, GRID_ROW_HEIGHT_PX, GRID_THEME_PARAMS, GRID_TOOLTIP_DELAY_MS, GRID_VISIBLE_ROWS, } from "./design.js";
|
|
13
|
+
import { HYBRID_SVG_SOURCE } from "./hybrid-svg.js";
|
|
11
14
|
import { REPORT_PROVENANCE_GLOBAL } from "./provenance-data.js";
|
|
12
15
|
import { scriptJson } from "./script-json.js";
|
|
13
16
|
import { TABLE_DATA_GLOBAL } from "./table-data.js";
|
|
@@ -90,8 +93,9 @@ const SPY_BOTTOM_MARGIN_PERCENT = 70;
|
|
|
90
93
|
*
|
|
91
94
|
* The fragment writes its own constants, because a page script reads no module binding. Each rule here is
|
|
92
95
|
* the twin of one rule of the server derivation: the number read of a cell, the four transforms, the
|
|
93
|
-
* competition rank, the compare of a sort,
|
|
94
|
-
*
|
|
96
|
+
* competition rank, the compare of a sort, the classification of a preset, and the item that adds
|
|
97
|
+
* the member of a continuous color and of a size after the pair. A shared test vector runs the transforms
|
|
98
|
+
* and the items of both sides over one set of cells, thus the two cannot drift in silence.
|
|
95
99
|
*
|
|
96
100
|
* The build reads the decoded rows of the payload. The decoder runs before this script, thus a row is a
|
|
97
101
|
* record and a cell reads by its column name.
|
|
@@ -174,7 +178,17 @@ function reportColumn(payload, index) {
|
|
|
174
178
|
}
|
|
175
179
|
function reportChannel(payload, spec) {
|
|
176
180
|
var cells = reportColumn(payload, spec.column);
|
|
177
|
-
|
|
181
|
+
if (spec.transform !== undefined) {
|
|
182
|
+
return reportTransform(cells, spec.transform);
|
|
183
|
+
}
|
|
184
|
+
if (spec.numeric !== true) {
|
|
185
|
+
return cells;
|
|
186
|
+
}
|
|
187
|
+
var numbers = [];
|
|
188
|
+
for (var c = 0; c < cells.length; c++) {
|
|
189
|
+
numbers.push(cells[c] === null ? null : reportNumber(cells[c]));
|
|
190
|
+
}
|
|
191
|
+
return numbers;
|
|
178
192
|
}
|
|
179
193
|
function reportCompare(a, b) {
|
|
180
194
|
var left = reportNumber(a);
|
|
@@ -189,7 +203,7 @@ function reportCompare(a, b) {
|
|
|
189
203
|
}
|
|
190
204
|
return x > y ? 1 : 0;
|
|
191
205
|
}
|
|
192
|
-
function reportCategory(rule, xValue, yValue) {
|
|
206
|
+
function reportCategory(rule, xValue, yValue, pValue) {
|
|
193
207
|
// The rule gives the place of the category, and the descriptor of a series names the same place. Thus
|
|
194
208
|
// the two sides compare numbers and no category name rides the page.
|
|
195
209
|
var x = reportNumber(xValue);
|
|
@@ -197,6 +211,13 @@ function reportCategory(rule, xValue, yValue) {
|
|
|
197
211
|
if (!rule || x === null || y === null) {
|
|
198
212
|
return -1;
|
|
199
213
|
}
|
|
214
|
+
if (rule.kind === "ma") {
|
|
215
|
+
if (x <= 0) {
|
|
216
|
+
return -1;
|
|
217
|
+
}
|
|
218
|
+
var p = reportNumber(pValue);
|
|
219
|
+
return p !== null && p < rule.cut ? 0 : 1;
|
|
220
|
+
}
|
|
200
221
|
if (y <= rule.cut) {
|
|
201
222
|
return 2;
|
|
202
223
|
}
|
|
@@ -208,8 +229,11 @@ function reportCategory(rule, xValue, yValue) {
|
|
|
208
229
|
function reportSeriesData(payload, source, rule) {
|
|
209
230
|
var x = reportChannel(payload, source.x);
|
|
210
231
|
var y = reportChannel(payload, source.y);
|
|
232
|
+
var color = source.color === undefined ? null : reportChannel(payload, source.color);
|
|
233
|
+
var size = source.size === undefined ? null : reportChannel(payload, source.size);
|
|
211
234
|
var group = source.group === undefined ? null : reportChannel(payload, source.group);
|
|
212
235
|
var labels = source.label === undefined ? null : reportColumn(payload, source.label);
|
|
236
|
+
var ruleCells = rule && rule.kind === "ma" ? reportColumn(payload, payload.columns.indexOf(rule.column)) : null;
|
|
213
237
|
var flags = Object.create(null);
|
|
214
238
|
var declared = source.flags || [];
|
|
215
239
|
for (var f = 0; f < declared.length; f++) {
|
|
@@ -223,20 +247,35 @@ function reportSeriesData(payload, source, rule) {
|
|
|
223
247
|
if (group !== null && group[r] !== source.value) {
|
|
224
248
|
continue;
|
|
225
249
|
}
|
|
226
|
-
if (source.category !== undefined && reportCategory(rule, x[r], y[r]) !== source.category) {
|
|
250
|
+
if (source.category !== undefined && reportCategory(rule, x[r], y[r], ruleCells === null ? null : ruleCells[r]) !== source.category) {
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
var shade = color === null ? null : reportNumber(color[r]);
|
|
254
|
+
var weight = size === null ? null : reportNumber(size[r]);
|
|
255
|
+
if ((color !== null && shade === null) || (size !== null && weight === null)) {
|
|
227
256
|
continue;
|
|
228
257
|
}
|
|
229
|
-
points.push({ index: r, x: x[r], y: y[r] });
|
|
258
|
+
points.push({ index: r, x: x[r], y: y[r], color: shade, size: weight });
|
|
230
259
|
}
|
|
231
260
|
if (source.sort) {
|
|
232
261
|
points.sort(function (a, b) {
|
|
233
262
|
return reportCompare(a.x, b.x);
|
|
234
263
|
});
|
|
264
|
+
} else if (source.rise) {
|
|
265
|
+
points.sort(function (a, b) {
|
|
266
|
+
return a.color - b.color;
|
|
267
|
+
});
|
|
235
268
|
}
|
|
236
269
|
var data = [];
|
|
237
270
|
for (var p = 0; p < points.length; p++) {
|
|
238
271
|
var point = points[p];
|
|
239
272
|
var pair = source.swap ? [point.y, point.x] : [point.x, point.y];
|
|
273
|
+
if (point.color !== null) {
|
|
274
|
+
pair.push(point.color);
|
|
275
|
+
}
|
|
276
|
+
if (point.size !== null) {
|
|
277
|
+
pair.push(point.size);
|
|
278
|
+
}
|
|
240
279
|
var label = labels === null ? null : labels[point.index];
|
|
241
280
|
var named = label !== null && label !== undefined;
|
|
242
281
|
if (!named && flags[point.index] !== true) {
|
|
@@ -251,17 +290,73 @@ function reportSeriesData(payload, source, rule) {
|
|
|
251
290
|
}
|
|
252
291
|
return data;
|
|
253
292
|
}`;
|
|
293
|
+
/**
|
|
294
|
+
* The window global that holds the option of each chart, keyed by the id of its container.
|
|
295
|
+
*
|
|
296
|
+
* The option is plain data: its rows are built, and each renderer is still a name. The export of a chart
|
|
297
|
+
* draws it again from this entry, thus the page and each exported file read one option.
|
|
298
|
+
*/
|
|
299
|
+
export const CHART_OPTIONS_GLOBAL = "__REPORT_CHART_OPTIONS";
|
|
300
|
+
/**
|
|
301
|
+
* The export sizes that the page draws, keyed by the name of the menu entry: the theme, the text size, the CSS
|
|
302
|
+
* box, the millimeter box of a column, and the pixel ratio of each export.
|
|
303
|
+
*/
|
|
304
|
+
const PAGE_EXPORT_SIZES = Object.fromEntries(Object.entries(CHART_EXPORT_SIZES).map(([kind, size]) => [
|
|
305
|
+
kind,
|
|
306
|
+
{
|
|
307
|
+
theme: size.theme,
|
|
308
|
+
textPx: size.textPx,
|
|
309
|
+
width: size.widthPx,
|
|
310
|
+
height: size.heightPx,
|
|
311
|
+
...("widthMm" in size ? { widthMm: size.widthMm, heightMm: size.heightMm } : {}),
|
|
312
|
+
pixelRatio: size.pixelRatio,
|
|
313
|
+
},
|
|
314
|
+
]));
|
|
315
|
+
/**
|
|
316
|
+
* The time that the object URL of a built SVG file stays alive after its download starts, in milliseconds. The
|
|
317
|
+
* browser reads the URL when the download starts, and the page then frees the text.
|
|
318
|
+
*/
|
|
319
|
+
const DOWNLOAD_URL_LIFETIME_MS = 60_000;
|
|
254
320
|
/**
|
|
255
321
|
* The page-side script that wires each chart. It finds every chart container, reads the option JSON from
|
|
256
322
|
* the sibling `<script type="application/json">` element, and initializes ECharts with the registered
|
|
257
323
|
* theme. The skeleton registers the theme before this script runs. A resize handler keeps each chart
|
|
258
|
-
* fit to the window.
|
|
324
|
+
* fit to the window. It draws a chart again only when the container of the chart changes size. A capture past
|
|
325
|
+
* the viewport resizes the window and keeps each container, and a redraw there restarts the chunked render of
|
|
326
|
+
* a dense chart. A container of zero width or height keeps its chart as it is: ECharts 6.1.0 throws when a
|
|
327
|
+
* Sankey draws at a zero size (apache/echarts#21706), and a capture can give a container a zero width for one
|
|
328
|
+
* resize.
|
|
329
|
+
*
|
|
330
|
+
* A custom series names its renderer as a string, because the option is JSON. The script registers each named
|
|
331
|
+
* renderer with the chart runtime before the first chart initializes, and it keeps the option under the
|
|
332
|
+
* container id.
|
|
333
|
+
*
|
|
334
|
+
* The option carries the toolbox of the chart. Each handler of the toolbox is the name of a page function, and
|
|
335
|
+
* the script binds each function after the parse and before the chart initializes. The formatter of a genome axis
|
|
336
|
+
* is such a name too. After the init the script attaches the zoom handler of the toolbox to the chart. The
|
|
337
|
+
* download control opens the download menu of the card. The print hides the canvas layer of the toolbox of each
|
|
338
|
+
* chart, because the runtime draws the toolbox inside the chart body, and the end of the print shows the layer
|
|
339
|
+
* again. The print sets no option, because a new option starts the chunked draw of a dense chart again.
|
|
340
|
+
*
|
|
341
|
+
* A click on a PNG entry of the menu draws the kept option again on a detached element, at the CSS size of the
|
|
342
|
+
* export and its pixel ratio, in the theme of its text size. The entry states the height of its export, because
|
|
343
|
+
* a taller chart body grows the height of a column export. Each series draws in one pass, because the script
|
|
344
|
+
* reads the PNG in the same task and a chunked draw ends in a later frame. Then the script reads the PNG and
|
|
345
|
+
* downloads it through an anchor. An entry that names no kept chart, or no export size, draws nothing.
|
|
346
|
+
*
|
|
347
|
+
* A click on a hybrid SVG entry builds the SVG of a dense chart from the kept option: the vector draw, the raster
|
|
348
|
+
* draw of the point layer at 300 DPI, and the composition. Then the script downloads the text through an anchor.
|
|
349
|
+
* A build that gives no file keeps the menu open and shows its fault note, thus the reader sees why the entry gave
|
|
350
|
+
* no file and can take a PNG.
|
|
259
351
|
*
|
|
260
352
|
* An option that carries the data-source member holds no row. The script then reads the registered payload
|
|
261
353
|
* of the artifact and builds the data of each series from the descriptors. A mount whose payload the
|
|
262
354
|
* registry does not hold keeps its empty card, and the walk continues.
|
|
263
355
|
*
|
|
264
|
-
* The script signals readiness when
|
|
356
|
+
* The script signals readiness when each chart that it set fires its first `finished` event, and immediately
|
|
357
|
+
* when no chart exists. A dense scatter draws in chunks over some frames, and the runtime fires `finished`
|
|
358
|
+
* after the last chunk. Thus a capture that keys on the signal sees each point. A chart whose option throws
|
|
359
|
+
* counts as finished, thus one fault never withholds the signal. It sets
|
|
265
360
|
* the `window.__inflexaThemeReady` sentinel and dispatches the `inflexa-theme-ready` event on the document.
|
|
266
361
|
* A reader that captures the page keys on this signal, thus the capture returns when the page is ready and
|
|
267
362
|
* not at a timeout. The sentinel guards a listener that registers after the dispatch, thus a late listener
|
|
@@ -275,6 +370,9 @@ function reportSeriesData(payload, source, rule) {
|
|
|
275
370
|
*/
|
|
276
371
|
export const CHART_BOOTSTRAP = `(function () {
|
|
277
372
|
${CHART_SERIES_BUILDER}
|
|
373
|
+
${CHART_RENDERERS_SOURCE}
|
|
374
|
+
${HYBRID_SVG_SOURCE}
|
|
375
|
+
${CHART_TOOLBOX_SOURCE}
|
|
278
376
|
function signalReady() {
|
|
279
377
|
window.${THEME_READY_SENTINEL} = true;
|
|
280
378
|
document.dispatchEvent(new Event(${JSON.stringify(THEME_READY_EVENT)}));
|
|
@@ -291,7 +389,31 @@ export const CHART_BOOTSTRAP = `(function () {
|
|
|
291
389
|
whenRevealed(signalReady);
|
|
292
390
|
return;
|
|
293
391
|
}
|
|
392
|
+
reportRegisterRenderers(echarts);
|
|
393
|
+
var pending = 0;
|
|
394
|
+
var walked = false;
|
|
395
|
+
var signalled = false;
|
|
396
|
+
function settle() {
|
|
397
|
+
if (!signalled && walked && pending === 0) {
|
|
398
|
+
signalled = true;
|
|
399
|
+
whenRevealed(signalReady);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
function track(chart) {
|
|
403
|
+
var done = false;
|
|
404
|
+
pending += 1;
|
|
405
|
+
function finish() {
|
|
406
|
+
if (!done) {
|
|
407
|
+
done = true;
|
|
408
|
+
pending -= 1;
|
|
409
|
+
settle();
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
chart.on("finished", finish);
|
|
413
|
+
return finish;
|
|
414
|
+
}
|
|
294
415
|
var registry = window.${TABLE_DATA_GLOBAL};
|
|
416
|
+
var kept = window.${CHART_OPTIONS_GLOBAL} = window.${CHART_OPTIONS_GLOBAL} || Object.create(null);
|
|
295
417
|
var containers = document.querySelectorAll("[data-echarts-id]");
|
|
296
418
|
for (var i = 0; i < containers.length; i++) {
|
|
297
419
|
var container = containers[i];
|
|
@@ -314,8 +436,17 @@ export const CHART_BOOTSTRAP = `(function () {
|
|
|
314
436
|
series[s].data = reportSeriesData(payload, source.series[s], source.rule);
|
|
315
437
|
}
|
|
316
438
|
}
|
|
439
|
+
reportBindToolbox(option);
|
|
317
440
|
var chart = echarts.init(container, ${JSON.stringify(ECHARTS_THEME_NAME)});
|
|
318
|
-
chart
|
|
441
|
+
reportWatchZoom(chart, option);
|
|
442
|
+
kept[container.getAttribute("id") || ""] = option;
|
|
443
|
+
var finish = track(chart);
|
|
444
|
+
try {
|
|
445
|
+
chart.setOption(option);
|
|
446
|
+
} catch (fault) {
|
|
447
|
+
finish();
|
|
448
|
+
throw fault;
|
|
449
|
+
}
|
|
319
450
|
} catch (cause) {
|
|
320
451
|
console.error("chart bootstrap failed for " + (container.getAttribute("data-echarts-id") || "(no id)") + ": " + (cause && cause.message ? cause.message : cause));
|
|
321
452
|
}
|
|
@@ -324,12 +455,116 @@ export const CHART_BOOTSTRAP = `(function () {
|
|
|
324
455
|
var nodes = document.querySelectorAll("[data-echarts-id]");
|
|
325
456
|
for (var j = 0; j < nodes.length; j++) {
|
|
326
457
|
var instance = echarts.getInstanceByDom(nodes[j]);
|
|
327
|
-
|
|
458
|
+
var width = nodes[j].clientWidth;
|
|
459
|
+
var height = nodes[j].clientHeight;
|
|
460
|
+
if (instance && width > 0 && height > 0 && (instance.getWidth() !== width || instance.getHeight() !== height)) {
|
|
328
461
|
instance.resize();
|
|
329
462
|
}
|
|
330
463
|
}
|
|
331
464
|
});
|
|
332
|
-
|
|
465
|
+
function toolboxShown(shown) {
|
|
466
|
+
function place(layer) {
|
|
467
|
+
if (layer.zlevel === ${TOOLBOX_ZLEVEL} && layer.dom) {
|
|
468
|
+
layer.dom.style.visibility = shown ? "" : "hidden";
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
var nodes = document.querySelectorAll("[data-echarts-id]");
|
|
472
|
+
for (var n = 0; n < nodes.length; n++) {
|
|
473
|
+
var instance = echarts.getInstanceByDom(nodes[n]);
|
|
474
|
+
var painter = instance ? instance.getZr().painter : null;
|
|
475
|
+
if (painter && typeof painter.eachLayer === "function") {
|
|
476
|
+
painter.eachLayer(place);
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
window.addEventListener("beforeprint", function () {
|
|
481
|
+
reportCloseExportMenu(false);
|
|
482
|
+
toolboxShown(false);
|
|
483
|
+
});
|
|
484
|
+
window.addEventListener("afterprint", function () {
|
|
485
|
+
toolboxShown(true);
|
|
486
|
+
});
|
|
487
|
+
var exportSizes = ${JSON.stringify(PAGE_EXPORT_SIZES)};
|
|
488
|
+
function reportOnePassOption(option) {
|
|
489
|
+
var out = Object.assign({}, option);
|
|
490
|
+
var series = reportList(option.series);
|
|
491
|
+
var drawn = [];
|
|
492
|
+
for (var s = 0; s < series.length; s++) {
|
|
493
|
+
drawn.push(Object.assign({}, series[s], { progressive: 0 }));
|
|
494
|
+
}
|
|
495
|
+
out.series = drawn;
|
|
496
|
+
return out;
|
|
497
|
+
}
|
|
498
|
+
function reportExportPng(control) {
|
|
499
|
+
var kind = control.getAttribute("data-export") || "";
|
|
500
|
+
var chartId = control.getAttribute("data-chart") || "";
|
|
501
|
+
if (!Object.prototype.hasOwnProperty.call(exportSizes, kind) || !Object.prototype.hasOwnProperty.call(kept, chartId)) {
|
|
502
|
+
return;
|
|
503
|
+
}
|
|
504
|
+
var size = exportSizes[kind];
|
|
505
|
+
var height = Number(control.getAttribute("data-height")) || size.height;
|
|
506
|
+
var host = document.createElement("div");
|
|
507
|
+
var offscreen = echarts.init(host, size.theme, { renderer: "canvas", width: size.width, height: height, devicePixelRatio: size.pixelRatio });
|
|
508
|
+
try {
|
|
509
|
+
offscreen.setOption(reportOnePassOption(reportExportOption(kept[chartId], size.textPx, size.width, height)));
|
|
510
|
+
var link = document.createElement("a");
|
|
511
|
+
link.href = offscreen.getDataURL({ type: "png", pixelRatio: size.pixelRatio, backgroundColor: "#ffffff" });
|
|
512
|
+
link.download = control.getAttribute("data-file") || "chart.png";
|
|
513
|
+
document.body.appendChild(link);
|
|
514
|
+
link.click();
|
|
515
|
+
document.body.removeChild(link);
|
|
516
|
+
} finally {
|
|
517
|
+
offscreen.dispose();
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
function reportExportHybrid(control) {
|
|
521
|
+
var kind = control.getAttribute("data-hybrid") || "";
|
|
522
|
+
var chartId = control.getAttribute("data-chart") || "";
|
|
523
|
+
if (!Object.prototype.hasOwnProperty.call(exportSizes, kind) || !Object.prototype.hasOwnProperty.call(kept, chartId)) {
|
|
524
|
+
return true;
|
|
525
|
+
}
|
|
526
|
+
var size = Object.assign({}, exportSizes[kind]);
|
|
527
|
+
size.height = Number(control.getAttribute("data-height")) || size.height;
|
|
528
|
+
size.heightMm = Number(control.getAttribute("data-height-mm")) || size.heightMm;
|
|
529
|
+
var svg = null;
|
|
530
|
+
try {
|
|
531
|
+
svg = reportHybridSvg(echarts, kept[chartId], size);
|
|
532
|
+
} catch (cause) {
|
|
533
|
+
console.error("hybrid svg failed for " + chartId + ": " + (cause && cause.message ? cause.message : cause));
|
|
534
|
+
return false;
|
|
535
|
+
}
|
|
536
|
+
if (svg === null) {
|
|
537
|
+
console.error("hybrid svg failed for " + chartId + ": the chart holds no point layer inside a grid");
|
|
538
|
+
return false;
|
|
539
|
+
}
|
|
540
|
+
var url = URL.createObjectURL(new Blob([svg], { type: "image/svg+xml" }));
|
|
541
|
+
var link = document.createElement("a");
|
|
542
|
+
link.href = url;
|
|
543
|
+
link.download = control.getAttribute("data-file") || "chart.svg";
|
|
544
|
+
document.body.appendChild(link);
|
|
545
|
+
link.click();
|
|
546
|
+
document.body.removeChild(link);
|
|
547
|
+
setTimeout(function () {
|
|
548
|
+
URL.revokeObjectURL(url);
|
|
549
|
+
}, ${DOWNLOAD_URL_LIFETIME_MS});
|
|
550
|
+
return true;
|
|
551
|
+
}
|
|
552
|
+
document.addEventListener("click", function (event) {
|
|
553
|
+
var target = event.target;
|
|
554
|
+
var control = target && typeof target.closest === "function" ? target.closest("[data-export], [data-hybrid]") : null;
|
|
555
|
+
if (control) {
|
|
556
|
+
if (control.getAttribute("data-export") !== null) {
|
|
557
|
+
reportExportPng(control);
|
|
558
|
+
} else if (reportExportHybrid(control) === false) {
|
|
559
|
+
reportMenuFault(control);
|
|
560
|
+
return;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
reportMenuClick(event);
|
|
564
|
+
});
|
|
565
|
+
document.addEventListener("keydown", reportMenuKey);
|
|
566
|
+
walked = true;
|
|
567
|
+
settle();
|
|
333
568
|
})();`;
|
|
334
569
|
/**
|
|
335
570
|
* The page-side script that reveals each `fade-in` element as it enters the viewport. The `data-delay`
|
|
@@ -17,20 +17,23 @@
|
|
|
17
17
|
import { type Result } from "neverthrow";
|
|
18
18
|
import type { ReportDocument } from "../contracts/report-blocks.js";
|
|
19
19
|
import { type CitationRecords } from "../report-model/reference-resolver.js";
|
|
20
|
+
import { type ChartOpts } from "./chart.js";
|
|
20
21
|
import { type DerivationChain } from "./references.js";
|
|
21
22
|
import { type ProvenanceExport } from "./provenance-data.js";
|
|
22
23
|
import type { RenderedPage, RenderProblem, RenderValues } from "./types.js";
|
|
23
24
|
/**
|
|
24
|
-
* The optional inputs of one render: the bibliography of the pin, the chains of the session,
|
|
25
|
-
* provenance of the analysis.
|
|
25
|
+
* The optional inputs of one render: the bibliography of the pin, the chains of the session, the frozen
|
|
26
|
+
* provenance of the analysis, and the options of the chart derivation.
|
|
26
27
|
*
|
|
27
28
|
* Each member is absent on its own, and a caller gives the members that it holds. A positional tail of
|
|
28
|
-
* three optional inputs made a caller of the last one pad the two before it, thus the
|
|
29
|
+
* three optional inputs made a caller of the last one pad the two before it, thus the inputs ride one bag.
|
|
30
|
+
* An absent `chart` member derives each chart with the registered figure modules.
|
|
29
31
|
*/
|
|
30
32
|
export interface RenderOptions {
|
|
31
33
|
readonly records?: CitationRecords;
|
|
32
34
|
readonly derivations?: readonly DerivationChain[];
|
|
33
35
|
readonly provenance?: ProvenanceExport;
|
|
36
|
+
readonly chart?: ChartOpts;
|
|
34
37
|
}
|
|
35
38
|
/**
|
|
36
39
|
* Render a report document, its value map, and the pinned citation records to one page and its data assets.
|
|
@@ -56,7 +59,13 @@ export interface RenderOptions {
|
|
|
56
59
|
* The renderer writes no file. The data assets ride the result, and the caller stages them beside the page.
|
|
57
60
|
* Thus the render stays pure, and two renders of one document give byte-identical assets.
|
|
58
61
|
*
|
|
62
|
+
* Each chart gives two SVG files beside the data assets, and its card links them. The page loads each table
|
|
63
|
+
* payload as a script, and it loads no SVG. Thus the SVG files ride the staged list of the result alone.
|
|
64
|
+
*
|
|
59
65
|
* One artifact gives one payload. A table block and a chart block that bind it read that one asset, and a
|
|
60
66
|
* chart under the inline bound carries its rows in its own option and registers none.
|
|
67
|
+
*
|
|
68
|
+
* The render is asynchronous because it loads the chart runtime of the SVG export. Each other step is
|
|
69
|
+
* synchronous.
|
|
61
70
|
*/
|
|
62
|
-
export declare function renderReportPage(document: ReportDocument, values: RenderValues, { records, derivations, provenance }?: RenderOptions): Result<RenderedPage, RenderProblem[]
|
|
71
|
+
export declare function renderReportPage(document: ReportDocument, values: RenderValues, { records, derivations, provenance, chart }?: RenderOptions): Promise<Result<RenderedPage, RenderProblem[]>>;
|
|
@@ -18,7 +18,8 @@ import { err, ok } from "neverthrow";
|
|
|
18
18
|
import { serializeReference } from "../contracts/report-reference.js";
|
|
19
19
|
import { citationRecordOf } from "../report-model/reference-resolver.js";
|
|
20
20
|
import { renderChart } from "./views/chart-view.js";
|
|
21
|
-
import { deriveChartRender } from "./chart.js";
|
|
21
|
+
import { DEFAULT_CHART_OPTS, deriveChartRender } from "./chart.js";
|
|
22
|
+
import { chartSvgAssets, loadChartRuntime } from "./chart-export.js";
|
|
22
23
|
import { assemblePage, renderBand, renderReferenceSection } from "./views/page-view.js";
|
|
23
24
|
import { renderClaim, renderNav, renderSection, renderText } from "./views/prose.js";
|
|
24
25
|
import { citationKeyOf, derivationChains, ReferenceLedger } from "./references.js";
|
|
@@ -49,13 +50,26 @@ import { renderCitation, renderFigure, renderMetric, renderMetricGrid, renderTab
|
|
|
49
50
|
* The renderer writes no file. The data assets ride the result, and the caller stages them beside the page.
|
|
50
51
|
* Thus the render stays pure, and two renders of one document give byte-identical assets.
|
|
51
52
|
*
|
|
53
|
+
* Each chart gives two SVG files beside the data assets, and its card links them. The page loads each table
|
|
54
|
+
* payload as a script, and it loads no SVG. Thus the SVG files ride the staged list of the result alone.
|
|
55
|
+
*
|
|
52
56
|
* One artifact gives one payload. A table block and a chart block that bind it read that one asset, and a
|
|
53
57
|
* chart under the inline bound carries its rows in its own option and registers none.
|
|
58
|
+
*
|
|
59
|
+
* The render is asynchronous because it loads the chart runtime of the SVG export. Each other step is
|
|
60
|
+
* synchronous.
|
|
54
61
|
*/
|
|
55
|
-
export function renderReportPage(document, values, { records, derivations, provenance } = {}) {
|
|
62
|
+
export async function renderReportPage(document, values, { records, derivations, provenance, chart = DEFAULT_CHART_OPTS } = {}) {
|
|
56
63
|
const problems = [];
|
|
57
64
|
const ledger = new ReferenceLedger();
|
|
58
|
-
const data = {
|
|
65
|
+
const data = {
|
|
66
|
+
payloads: new Map(),
|
|
67
|
+
mounts: 0,
|
|
68
|
+
svgs: [],
|
|
69
|
+
view: { lineage: provenance !== undefined },
|
|
70
|
+
chart,
|
|
71
|
+
chartRuntime: await loadChartRuntime(),
|
|
72
|
+
};
|
|
59
73
|
const content = [];
|
|
60
74
|
for (const [index, section] of document.sections.entries()) {
|
|
61
75
|
content.push(renderBand(index, renderBlock(section, values, ledger, records, data, 0, problems)));
|
|
@@ -71,7 +85,7 @@ export function renderReportPage(document, values, { records, derivations, prove
|
|
|
71
85
|
const references = renderReferenceSection(ledger, document.sections.length, records, derivationChains(derivations));
|
|
72
86
|
return ok({
|
|
73
87
|
html: assemblePage(document.title, nav, content.join(""), references, { dataAssets: tableAssets, grids: data.mounts > 0, provenanceAssets }),
|
|
74
|
-
dataAssets: [...provenanceAssets, ...tableAssets],
|
|
88
|
+
dataAssets: [...provenanceAssets, ...tableAssets, ...data.svgs],
|
|
75
89
|
});
|
|
76
90
|
}
|
|
77
91
|
/**
|
|
@@ -159,7 +173,11 @@ function renderBlock(block, values, ledger, records, data, depth, problems) {
|
|
|
159
173
|
// under two ids. One binding resolves one row set, thus the column places and the row places of
|
|
160
174
|
// the descriptors address the registered payload whichever block encoded it.
|
|
161
175
|
const columns = tableColumns(entry);
|
|
162
|
-
const derived = deriveChartRender(block, entry.rows, entry.columns, { key: block.id, columns }
|
|
176
|
+
const derived = deriveChartRender(block, entry.rows, entry.columns, { key: block.id, columns }, {
|
|
177
|
+
...(entry.statistics !== undefined ? { statistics: entry.statistics } : {}),
|
|
178
|
+
...(entry.track !== undefined ? { track: entry.track } : {}),
|
|
179
|
+
...(entry.trees !== undefined ? { trees: entry.trees } : {}),
|
|
180
|
+
}, data.chart);
|
|
163
181
|
if (derived.isErr()) {
|
|
164
182
|
problems.push(derived.error);
|
|
165
183
|
return "";
|
|
@@ -167,7 +185,20 @@ function renderBlock(block, values, ledger, records, data, depth, problems) {
|
|
|
167
185
|
if (derived.value.readsPayload) {
|
|
168
186
|
registerPayload(data, block.binding, block.id, () => payloadOf(block.binding, entry, columns));
|
|
169
187
|
}
|
|
170
|
-
|
|
188
|
+
// The export reads the chart with every row inline, thus a dense chart exports each point.
|
|
189
|
+
const svgs = chartSvgAssets(data.chartRuntime, block.id, derived.value.inline, derived.value.bodyPx);
|
|
190
|
+
if (svgs.isErr()) {
|
|
191
|
+
problems.push(svgs.error);
|
|
192
|
+
return "";
|
|
193
|
+
}
|
|
194
|
+
if (svgs.value !== undefined) {
|
|
195
|
+
data.svgs.push(svgs.value.single, svgs.value.double);
|
|
196
|
+
}
|
|
197
|
+
return renderChart(block, ledger, derived.value.option, data.view, {
|
|
198
|
+
bodyPx: derived.value.bodyPx,
|
|
199
|
+
...(derived.value.widthPx !== undefined ? { widthPx: derived.value.widthPx } : {}),
|
|
200
|
+
...(svgs.value !== undefined ? { svg: { single: svgs.value.single.name, double: svgs.value.double.name } } : {}),
|
|
201
|
+
});
|
|
171
202
|
}
|
|
172
203
|
case "section":
|
|
173
204
|
return renderSection(block, depth, renderChildren(block.blocks, values, ledger, records, data, depth + 1, problems));
|
|
@@ -8,6 +8,21 @@
|
|
|
8
8
|
* image bytes.
|
|
9
9
|
*/
|
|
10
10
|
import type { DataAsset } from "./table-data.js";
|
|
11
|
+
/** One statistic of a chart: the label of the block, and the value of the cell that the statistic binds. */
|
|
12
|
+
export interface RenderStatistic {
|
|
13
|
+
label: string;
|
|
14
|
+
value: string | number;
|
|
15
|
+
}
|
|
16
|
+
/** The second table of a chart: the rows of the track binding, and the optional column order. */
|
|
17
|
+
export interface RenderTrack {
|
|
18
|
+
rows: Array<Record<string, string | number>>;
|
|
19
|
+
columns?: string[];
|
|
20
|
+
}
|
|
21
|
+
/** The trees of the category axes of a chart: the rows of the tree binding of each axis, with its optional column order. */
|
|
22
|
+
export interface RenderTrees {
|
|
23
|
+
x?: RenderTrack;
|
|
24
|
+
y?: RenderTrack;
|
|
25
|
+
}
|
|
11
26
|
/**
|
|
12
27
|
* The value that one block resolves to, as a closed union. A `scalar` gives one number or one string. A
|
|
13
28
|
* `table` gives the rows and the optional column order. A `figure` gives a ready source string. A
|
|
@@ -15,6 +30,9 @@ import type { DataAsset } from "./table-data.js";
|
|
|
15
30
|
*
|
|
16
31
|
* A `table` carries `total` when a row bound cut the rows of the artifact. The renderer states the shown
|
|
17
32
|
* count against it. A table with no bound carries none, and the row count answers for it.
|
|
33
|
+
*
|
|
34
|
+
* The `table` of a chart also carries the value of each statistic, in block order, the track, and the tree of
|
|
35
|
+
* each axis, where the block declares them. A table block declares none of them.
|
|
18
36
|
*/
|
|
19
37
|
export type RenderValue = {
|
|
20
38
|
type: "scalar";
|
|
@@ -24,6 +42,9 @@ export type RenderValue = {
|
|
|
24
42
|
rows: Array<Record<string, string | number>>;
|
|
25
43
|
columns?: string[];
|
|
26
44
|
total?: number;
|
|
45
|
+
statistics?: RenderStatistic[];
|
|
46
|
+
track?: RenderTrack;
|
|
47
|
+
trees?: RenderTrees;
|
|
27
48
|
} | {
|
|
28
49
|
type: "figure";
|
|
29
50
|
src: string;
|
|
@@ -48,8 +69,8 @@ export type RenderValues = Record<string, RenderValue>;
|
|
|
48
69
|
* The renderer writes no file. Thus it gives the asset bytes back to the caller, and the caller stages
|
|
49
70
|
* them beside the page. A document with no table gives an empty list, and its page references none.
|
|
50
71
|
*
|
|
51
|
-
* The list holds the provenance assets of the render beside the table payloads
|
|
52
|
-
* file that the page loads and the caller sorts nothing.
|
|
72
|
+
* The list holds the provenance assets of the render beside the table payloads and the SVG files of each
|
|
73
|
+
* chart, thus one stage writes each file that the page loads or links, and the caller sorts nothing.
|
|
53
74
|
*/
|
|
54
75
|
export interface RenderedPage {
|
|
55
76
|
html: string;
|
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
* one call reports each fault at one time.
|
|
14
14
|
*/
|
|
15
15
|
import { type Result } from "neverthrow";
|
|
16
|
+
import type { Block } from "../contracts/report-blocks.js";
|
|
17
|
+
import { type ChartSlot } from "../report-model/block-walk.js";
|
|
16
18
|
import type { ResolvedValue } from "../report-model/reference-resolver.js";
|
|
17
19
|
import type { RenderValues } from "./types.js";
|
|
18
20
|
/** The block kinds that carry no render value. Each one renders from the block and the ledger alone. */
|
|
@@ -25,28 +27,46 @@ export type ResolvedFile = Extract<ResolvedValue, {
|
|
|
25
27
|
}>;
|
|
26
28
|
/** The policy that turns a resolved file echo into a figure `src` string. The caller owns the policy. */
|
|
27
29
|
export type FigureSourcePolicy = (file: ResolvedFile) => string;
|
|
30
|
+
/** One resolved statistic of a chart: the label of the block, and the resolved value of its cell. */
|
|
31
|
+
export interface StatisticResolution {
|
|
32
|
+
label: string;
|
|
33
|
+
resolved: ResolvedValue;
|
|
34
|
+
}
|
|
28
35
|
/**
|
|
29
36
|
* The resolution result of one block: the block id, the block kind, and the resolved value of its binding.
|
|
30
37
|
*
|
|
31
38
|
* A value-bearing kind carries the resolved value. A no-value kind carries none, thus a text block with
|
|
32
|
-
* no binding is representable and a value on it is not.
|
|
39
|
+
* no binding is representable and a value on it is not. A chart also carries the resolved track, the resolved
|
|
40
|
+
* tree of each axis, and each resolved statistic, in block order, where the block declares them.
|
|
33
41
|
*/
|
|
34
42
|
export type BlockResolution = {
|
|
35
43
|
blockId: string;
|
|
36
44
|
kind: NoValueKind;
|
|
37
45
|
} | {
|
|
38
46
|
blockId: string;
|
|
39
|
-
kind: ValueBearingKind
|
|
47
|
+
kind: Exclude<ValueBearingKind, "chart">;
|
|
48
|
+
resolved: ResolvedValue;
|
|
49
|
+
} | {
|
|
50
|
+
blockId: string;
|
|
51
|
+
kind: "chart";
|
|
40
52
|
resolved: ResolvedValue;
|
|
53
|
+
track?: ResolvedValue;
|
|
54
|
+
trees?: {
|
|
55
|
+
x?: ResolvedValue;
|
|
56
|
+
y?: ResolvedValue;
|
|
57
|
+
};
|
|
58
|
+
statistics?: StatisticResolution[];
|
|
41
59
|
};
|
|
42
60
|
/**
|
|
43
61
|
* One typed mismatch between a block kind and a resolved value type. `blockId` names the block, and
|
|
44
62
|
* `blockKind` names the kind that sets the expectation. `expected` names the resolved type that the kind
|
|
45
|
-
* needs, and `actual` names the resolved type that arrived.
|
|
63
|
+
* needs, and `actual` names the resolved type that arrived. `slot` names the track or the statistic of a
|
|
64
|
+
* chart whose value has the wrong type.
|
|
46
65
|
*/
|
|
47
66
|
export interface BridgeMismatch {
|
|
48
67
|
blockId: string;
|
|
49
68
|
blockKind: ValueBearingKind;
|
|
69
|
+
slot?: ChartSlot;
|
|
50
70
|
expected: ResolvedValue["type"];
|
|
51
71
|
actual: ResolvedValue["type"];
|
|
52
72
|
}
|
|
@@ -59,4 +79,19 @@ export interface BridgeMismatch {
|
|
|
59
79
|
* complete map.
|
|
60
80
|
*/
|
|
61
81
|
export declare function bridgeValues(resolutions: readonly BlockResolution[], figureSrc: FigureSourcePolicy): Result<RenderValues, BridgeMismatch[]>;
|
|
82
|
+
/**
|
|
83
|
+
* Pair each block with the resolved value of its binding, in document order.
|
|
84
|
+
*
|
|
85
|
+
* A value-bearing kind carries the resolved value of its binding, looked up by the block id from the map
|
|
86
|
+
* that the resolution pass filled. A chart also carries the value of its track, of each tree, and of each statistic, looked
|
|
87
|
+
* up by the block id and the slot. The label of a statistic comes from the block, because the render value
|
|
88
|
+
* prints it. A no-value kind carries none. Where a reference sits in a block is the knowledge of
|
|
89
|
+
* `block-walk.ts`, thus this walk reads the slots that the walk names and never a binding field.
|
|
90
|
+
*
|
|
91
|
+
* The switch is exhaustive over the eight block kinds. A ninth kind reaches the end with no return, and
|
|
92
|
+
* the declared return type fails the build. Thus the walk cannot drop a kind in silence. A value-bearing
|
|
93
|
+
* block reaches here only when its reference resolved, because an unresolved reference short-circuits
|
|
94
|
+
* before this walk.
|
|
95
|
+
*/
|
|
96
|
+
export declare function collectResolutions(blocks: readonly Block[], resolvedByBlock: ReadonlyMap<string, ResolvedValue>, resolvedBySlot: ReadonlyMap<string, ReadonlyMap<ChartSlot, ResolvedValue>>): BlockResolution[];
|
|
62
97
|
export {};
|