1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
//! Three-stage rendering pipeline types (chartml 5.0 phase 2).
//!
//! The pipeline splits chart rendering into three explicit stages so each
//! has a single typed responsibility:
//!
//! ```text
//! YAML ──► FETCH ──► FetchedChart ──► TRANSFORM ──► PreparedChart ──► render ──► SVG
//! (async) (async) (sync)
//! ```
//!
//! Phase 2 introduces the type shapes and exposes the explicit
//! `ChartML::fetch` / `transform` / `render_prepared_to_svg` /
//! `render_to_svg_async` methods. No provider trait yet — `fetch` reads
//! from pre-registered sources only. Phase 3 adds the provider trait,
//! resolver, cache, and parallel fetch.
//!
//! All types derive `Clone` because:
//! - `DataTable` is `Arc`-backed internally, so cloning sources is cheap;
//! - `Clone` enables the "fetch + transform once, resize-render N times"
//! use case (e.g. responsive layouts) without re-running upstream stages.
use HashMap;
// `web_time::SystemTime` is a wasm32-compatible drop-in for `std::time::SystemTime`.
use SystemTime;
use IndexMap;
use crateDataTable;
use crateChartSpec;
pub use RenderOptions;
/// Stage 1 output: the spec plus every named source resolved to a `DataTable`.
///
/// `sources` always has at least one entry. The key is the user-chosen name
/// from the YAML `data:` map; for unnamed flat data the canonical key is
/// `"source"`. Insertion order matches the YAML — preserved via `IndexMap`
/// so transform middleware can rely on stable ordering.
/// Stage 2 output: spec plus the single transformed table the renderer will consume.
///
/// `data` is either the lone source (passthrough when no transform is declared)
/// or the result of running registered `TransformMiddleware` over the
/// fetched sources.
/// Per-fetch telemetry. `per_source` stays empty in phase 2 (no provider
/// dispatch yet); phase 3 populates it from `FetchResult.metadata` per
/// declared source.
/// Per-transform telemetry. Captures whether the middleware actually ran
/// (vs. passthrough) plus the names of the sources the transform consumed.