Skip to main content

merman_render/
model.rs

1use merman_core::ParseMetadata;
2use rustc_hash::FxHashMap;
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5use std::sync::Arc;
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct LayoutMeta {
9    pub diagram_type: String,
10    pub title: Option<String>,
11    pub config: Value,
12    pub effective_config: Value,
13}
14
15impl LayoutMeta {
16    pub fn from_parse_metadata(meta: &ParseMetadata) -> Self {
17        Self {
18            diagram_type: meta.diagram_type.clone(),
19            title: meta.title.clone(),
20            config: meta.config.as_value().clone(),
21            effective_config: meta.effective_config.as_value().clone(),
22        }
23    }
24}
25
26#[derive(Debug, Clone, Serialize, Deserialize)]
27pub struct Bounds {
28    pub min_x: f64,
29    pub min_y: f64,
30    pub max_x: f64,
31    pub max_y: f64,
32}
33
34impl Bounds {
35    pub fn from_points(points: impl IntoIterator<Item = (f64, f64)>) -> Option<Self> {
36        let mut it = points.into_iter();
37        let (x0, y0) = it.next()?;
38        let mut b = Self {
39            min_x: x0,
40            min_y: y0,
41            max_x: x0,
42            max_y: y0,
43        };
44        for (x, y) in it {
45            b.min_x = b.min_x.min(x);
46            b.min_y = b.min_y.min(y);
47            b.max_x = b.max_x.max(x);
48            b.max_y = b.max_y.max(y);
49        }
50        Some(b)
51    }
52}
53
54#[derive(Debug, Clone, Serialize, Deserialize)]
55pub struct LayoutPoint {
56    pub x: f64,
57    pub y: f64,
58}
59
60#[derive(Debug, Clone, Serialize, Deserialize)]
61pub struct LayoutLabel {
62    pub x: f64,
63    pub y: f64,
64    pub width: f64,
65    pub height: f64,
66}
67
68#[derive(Debug, Clone)]
69pub struct ClassNodeRowMetrics {
70    pub members: Vec<crate::text::TextMetrics>,
71    pub methods: Vec<crate::text::TextMetrics>,
72}
73
74#[derive(Debug, Clone, Serialize, Deserialize)]
75pub struct LayoutNode {
76    pub id: String,
77    pub x: f64,
78    pub y: f64,
79    pub width: f64,
80    pub height: f64,
81    pub is_cluster: bool,
82    #[serde(skip)]
83    pub label_width: Option<f64>,
84    #[serde(skip)]
85    pub label_height: Option<f64>,
86}
87
88#[derive(Debug, Clone, Serialize, Deserialize)]
89pub struct LayoutCluster {
90    pub id: String,
91    pub x: f64,
92    pub y: f64,
93    pub width: f64,
94    pub height: f64,
95    /// Mermaid cluster "diff" value used during cluster positioning.
96    pub diff: f64,
97    /// Mermaid cluster "offsetY" value: title bbox height minus half padding.
98    pub offset_y: f64,
99    pub title: String,
100    pub title_label: LayoutLabel,
101    pub requested_dir: Option<String>,
102    pub effective_dir: String,
103    pub padding: f64,
104    pub title_margin_top: f64,
105    pub title_margin_bottom: f64,
106}
107
108#[derive(Debug, Clone, Serialize, Deserialize)]
109pub struct LayoutEdge {
110    pub id: String,
111    pub from: String,
112    pub to: String,
113    #[serde(default)]
114    pub from_cluster: Option<String>,
115    #[serde(default)]
116    pub to_cluster: Option<String>,
117    pub points: Vec<LayoutPoint>,
118    pub label: Option<LayoutLabel>,
119    #[serde(default)]
120    pub start_label_left: Option<LayoutLabel>,
121    #[serde(default)]
122    pub start_label_right: Option<LayoutLabel>,
123    #[serde(default)]
124    pub end_label_left: Option<LayoutLabel>,
125    #[serde(default)]
126    pub end_label_right: Option<LayoutLabel>,
127    /// Optional SVG marker id for marker-start (e.g. ER cardinality markers).
128    #[serde(default)]
129    pub start_marker: Option<String>,
130    /// Optional SVG marker id for marker-end (e.g. ER cardinality markers).
131    #[serde(default)]
132    pub end_marker: Option<String>,
133    /// Optional SVG dash pattern (e.g. identifying vs non-identifying ER relationships).
134    #[serde(default)]
135    pub stroke_dasharray: Option<String>,
136}
137
138#[derive(Debug, Clone, Serialize, Deserialize)]
139pub struct BlockDiagramLayout {
140    pub nodes: Vec<LayoutNode>,
141    pub edges: Vec<LayoutEdge>,
142    pub bounds: Option<Bounds>,
143}
144
145#[derive(Debug, Clone, Serialize, Deserialize)]
146pub struct RequirementDiagramLayout {
147    pub nodes: Vec<LayoutNode>,
148    pub edges: Vec<LayoutEdge>,
149    pub bounds: Option<Bounds>,
150}
151
152#[derive(Debug, Clone, Serialize, Deserialize)]
153pub struct ArchitectureDiagramLayout {
154    pub nodes: Vec<LayoutNode>,
155    pub edges: Vec<LayoutEdge>,
156    /// Local Cytoscape child contribution phases for Architecture services.
157    ///
158    /// These bounds are exposed for source-backed group/content audits. SVG renderers should use
159    /// their own phase-specific logic instead of treating this as a generic root-bounds source.
160    #[serde(default, skip_serializing_if = "Vec::is_empty")]
161    pub cytoscape_service_bounds: Vec<ArchitectureCytoscapeServiceBounds>,
162    /// Final FCoSE compound rectangles exposed for source-backed Architecture audits.
163    ///
164    /// Renderers should not treat these as Mermaid SVG group rects without a phase-specific
165    /// source audit; they are layout-engine rects, not browser `node.boundingBox()` values.
166    #[serde(default, skip_serializing_if = "Vec::is_empty")]
167    pub fcose_compound_bounds: Vec<ArchitectureCompoundBounds>,
168    /// Optional local FCoSE phase trace for source-backed Architecture layout audits.
169    ///
170    /// This is populated only by explicit diagnostic runs and should stay out of normal rendering
171    /// decisions.
172    #[serde(default, skip_serializing_if = "Vec::is_empty")]
173    pub fcose_debug_stages: Vec<ArchitectureFcoseDebugStage>,
174    pub bounds: Option<Bounds>,
175}
176
177#[derive(Debug, Clone, Serialize, Deserialize)]
178pub struct ArchitectureCompoundBounds {
179    pub id: String,
180    pub bounds: Bounds,
181}
182
183#[derive(Debug, Clone, Serialize, Deserialize)]
184pub struct ArchitectureFcoseDebugStage {
185    pub run_index: usize,
186    pub tag: String,
187    #[serde(default, skip_serializing_if = "Option::is_none")]
188    pub iterations: Option<usize>,
189    #[serde(default, skip_serializing_if = "Option::is_none")]
190    pub bbox: Option<Bounds>,
191    #[serde(default, skip_serializing_if = "Vec::is_empty")]
192    pub nodes: Vec<ArchitectureFcoseDebugNodeBounds>,
193    #[serde(default, skip_serializing_if = "Vec::is_empty")]
194    pub compound_bounds: Vec<ArchitectureCompoundBounds>,
195    #[serde(default, skip_serializing_if = "Option::is_none")]
196    pub relocate: Option<ArchitectureFcoseRelocateDebug>,
197}
198
199#[derive(Debug, Clone, Serialize, Deserialize)]
200pub struct ArchitectureFcoseDebugNodeBounds {
201    pub id: String,
202    pub kind: String,
203    pub bounds: Bounds,
204    #[serde(default, skip_serializing_if = "Option::is_none")]
205    pub displacement: Option<LayoutPoint>,
206}
207
208#[derive(Debug, Clone, Serialize, Deserialize)]
209pub struct ArchitectureFcoseRelocateDebug {
210    pub original_center: LayoutPoint,
211    pub rect_center: LayoutPoint,
212    pub delta: LayoutPoint,
213}
214
215#[derive(Debug, Clone, Serialize, Deserialize)]
216pub struct ArchitectureCytoscapeServiceBounds {
217    pub id: String,
218    #[serde(default, skip_serializing_if = "Option::is_none")]
219    pub in_group: Option<String>,
220    pub body_bounds: Bounds,
221    #[serde(default, skip_serializing_if = "Option::is_none")]
222    pub label_bounds: Option<Bounds>,
223    #[serde(default, skip_serializing_if = "Option::is_none")]
224    pub label_metrics: Option<ArchitectureCytoscapeServiceLabelMetrics>,
225    pub union_bounds: Bounds,
226}
227
228#[derive(Debug, Clone, Serialize, Deserialize)]
229pub struct ArchitectureCytoscapeServiceLabelMetrics {
230    pub text_width: f64,
231    pub half_width: f64,
232    pub applied_scale: f64,
233}
234
235#[derive(Debug, Clone, Serialize, Deserialize)]
236pub struct MindmapDiagramLayout {
237    pub nodes: Vec<LayoutNode>,
238    pub edges: Vec<LayoutEdge>,
239    pub bounds: Option<Bounds>,
240}
241
242#[derive(Debug, Clone, Serialize, Deserialize)]
243pub struct SankeyNodeLayout {
244    pub id: String,
245    pub index: usize,
246    pub depth: usize,
247    pub height: usize,
248    pub layer: usize,
249    pub value: f64,
250    pub x0: f64,
251    pub x1: f64,
252    pub y0: f64,
253    pub y1: f64,
254}
255
256#[derive(Debug, Clone, Serialize, Deserialize)]
257pub struct SankeyLinkLayout {
258    pub index: usize,
259    pub source: String,
260    pub target: String,
261    pub value: f64,
262    pub width: f64,
263    pub y0: f64,
264    pub y1: f64,
265}
266
267#[derive(Debug, Clone, Serialize, Deserialize)]
268pub struct SankeyDiagramLayout {
269    pub bounds: Option<Bounds>,
270    pub width: f64,
271    pub height: f64,
272    pub node_width: f64,
273    pub node_padding: f64,
274    pub nodes: Vec<SankeyNodeLayout>,
275    pub links: Vec<SankeyLinkLayout>,
276}
277
278#[derive(Debug, Clone, Serialize, Deserialize)]
279pub struct RadarAxisLayout {
280    pub label: String,
281    pub angle: f64,
282    pub line_x2: f64,
283    pub line_y2: f64,
284    pub label_x: f64,
285    pub label_y: f64,
286}
287
288#[derive(Debug, Clone, Serialize, Deserialize)]
289pub struct RadarGraticuleShapeLayout {
290    pub kind: String,
291    pub r: Option<f64>,
292    #[serde(default)]
293    pub points: Vec<LayoutPoint>,
294}
295
296#[derive(Debug, Clone, Serialize, Deserialize)]
297pub struct RadarCurveLayout {
298    pub label: String,
299    pub class_index: i64,
300    #[serde(default)]
301    pub points: Vec<LayoutPoint>,
302    pub path_d: String,
303}
304
305#[derive(Debug, Clone, Serialize, Deserialize)]
306pub struct RadarLegendItemLayout {
307    pub label: String,
308    pub class_index: i64,
309    pub x: f64,
310    pub y: f64,
311}
312
313#[derive(Debug, Clone, Serialize, Deserialize)]
314pub struct RadarDiagramLayout {
315    pub bounds: Option<Bounds>,
316    pub svg_width: f64,
317    pub svg_height: f64,
318    pub center_x: f64,
319    pub center_y: f64,
320    pub radius: f64,
321    pub axis_label_factor: f64,
322    pub title_y: f64,
323    #[serde(default)]
324    pub axes: Vec<RadarAxisLayout>,
325    #[serde(default)]
326    pub graticules: Vec<RadarGraticuleShapeLayout>,
327    #[serde(default)]
328    pub curves: Vec<RadarCurveLayout>,
329    #[serde(default)]
330    pub legend_items: Vec<RadarLegendItemLayout>,
331}
332
333#[derive(Debug, Clone, Serialize, Deserialize)]
334pub struct TreemapSectionLayout {
335    pub name: String,
336    pub depth: i64,
337    pub value: f64,
338    pub x0: f64,
339    pub y0: f64,
340    pub x1: f64,
341    pub y1: f64,
342    #[serde(default)]
343    pub class_selector: Option<String>,
344    #[serde(default)]
345    pub css_compiled_styles: Option<Vec<String>>,
346}
347
348#[derive(Debug, Clone, Serialize, Deserialize)]
349pub struct TreemapLeafLayout {
350    pub name: String,
351    pub value: f64,
352    #[serde(default)]
353    pub parent_name: Option<String>,
354    pub x0: f64,
355    pub y0: f64,
356    pub x1: f64,
357    pub y1: f64,
358    #[serde(default)]
359    pub class_selector: Option<String>,
360    #[serde(default)]
361    pub css_compiled_styles: Option<Vec<String>>,
362}
363
364#[derive(Debug, Clone, Serialize, Deserialize)]
365pub struct TreemapDiagramLayout {
366    pub title_height: f64,
367    pub width: f64,
368    pub height: f64,
369    pub use_max_width: bool,
370    pub diagram_padding: f64,
371    pub show_values: bool,
372    pub value_format: String,
373    #[serde(default, rename = "accTitle")]
374    pub acc_title: Option<String>,
375    #[serde(default, rename = "accDescr")]
376    pub acc_descr: Option<String>,
377    #[serde(default)]
378    pub title: Option<String>,
379    #[serde(default)]
380    pub sections: Vec<TreemapSectionLayout>,
381    #[serde(default)]
382    pub leaves: Vec<TreemapLeafLayout>,
383}
384
385#[derive(Debug, Clone, Serialize, Deserialize)]
386pub struct XyChartRectData {
387    pub x: f64,
388    pub y: f64,
389    pub width: f64,
390    pub height: f64,
391    pub fill: String,
392    #[serde(rename = "strokeFill")]
393    pub stroke_fill: String,
394    #[serde(rename = "strokeWidth")]
395    pub stroke_width: f64,
396}
397
398#[derive(Debug, Clone, Serialize, Deserialize)]
399pub struct XyChartTextData {
400    pub text: String,
401    pub x: f64,
402    pub y: f64,
403    pub fill: String,
404    #[serde(rename = "fontSize")]
405    pub font_size: f64,
406    #[serde(default)]
407    pub rotation: f64,
408    #[serde(rename = "verticalPos")]
409    pub vertical_pos: String,
410    #[serde(rename = "horizontalPos")]
411    pub horizontal_pos: String,
412}
413
414#[derive(Debug, Clone, Serialize, Deserialize)]
415pub struct XyChartPathData {
416    pub path: String,
417    #[serde(default)]
418    pub fill: Option<String>,
419    #[serde(rename = "strokeFill")]
420    pub stroke_fill: String,
421    #[serde(rename = "strokeWidth")]
422    pub stroke_width: f64,
423}
424
425#[derive(Debug, Clone, Serialize, Deserialize)]
426#[serde(tag = "type")]
427pub enum XyChartDrawableElem {
428    #[serde(rename = "rect")]
429    Rect {
430        #[serde(rename = "groupTexts")]
431        group_texts: Vec<String>,
432        data: Vec<XyChartRectData>,
433    },
434    #[serde(rename = "text")]
435    Text {
436        #[serde(rename = "groupTexts")]
437        group_texts: Vec<String>,
438        data: Vec<XyChartTextData>,
439    },
440    #[serde(rename = "path")]
441    Path {
442        #[serde(rename = "groupTexts")]
443        group_texts: Vec<String>,
444        data: Vec<XyChartPathData>,
445    },
446}
447
448#[derive(Debug, Clone, Serialize, Deserialize)]
449pub struct XyChartDiagramLayout {
450    pub width: f64,
451    pub height: f64,
452    #[serde(rename = "chartOrientation")]
453    pub chart_orientation: String,
454    #[serde(rename = "showDataLabel")]
455    pub show_data_label: bool,
456    #[serde(rename = "backgroundColor")]
457    pub background_color: String,
458    #[serde(rename = "labelData")]
459    pub label_data: Vec<String>,
460    #[serde(default)]
461    pub drawables: Vec<XyChartDrawableElem>,
462}
463
464#[derive(Debug, Clone, Serialize, Deserialize)]
465pub struct QuadrantChartTextData {
466    pub text: String,
467    pub x: f64,
468    pub y: f64,
469    pub fill: String,
470    #[serde(rename = "fontSize")]
471    pub font_size: f64,
472    #[serde(default)]
473    pub rotation: f64,
474    #[serde(rename = "verticalPos")]
475    pub vertical_pos: String,
476    #[serde(rename = "horizontalPos")]
477    pub horizontal_pos: String,
478}
479
480pub type QuadrantChartAxisLabelData = QuadrantChartTextData;
481
482#[derive(Debug, Clone, Serialize, Deserialize)]
483pub struct QuadrantChartQuadrantData {
484    pub x: f64,
485    pub y: f64,
486    pub width: f64,
487    pub height: f64,
488    pub fill: String,
489    pub text: QuadrantChartTextData,
490}
491
492#[derive(Debug, Clone, Serialize, Deserialize)]
493pub struct QuadrantChartBorderLineData {
494    #[serde(rename = "strokeWidth")]
495    pub stroke_width: f64,
496    #[serde(rename = "strokeFill")]
497    pub stroke_fill: String,
498    pub x1: f64,
499    pub y1: f64,
500    pub x2: f64,
501    pub y2: f64,
502}
503
504#[derive(Debug, Clone, Serialize, Deserialize)]
505pub struct QuadrantChartPointData {
506    pub x: f64,
507    pub y: f64,
508    pub fill: String,
509    pub radius: f64,
510    #[serde(rename = "strokeColor")]
511    pub stroke_color: String,
512    #[serde(rename = "strokeWidth")]
513    pub stroke_width: String,
514    pub text: QuadrantChartTextData,
515}
516
517#[derive(Debug, Clone, Serialize, Deserialize)]
518pub struct QuadrantChartDiagramLayout {
519    pub width: f64,
520    pub height: f64,
521    #[serde(default)]
522    pub title: Option<QuadrantChartTextData>,
523    pub quadrants: Vec<QuadrantChartQuadrantData>,
524    #[serde(rename = "borderLines")]
525    pub border_lines: Vec<QuadrantChartBorderLineData>,
526    pub points: Vec<QuadrantChartPointData>,
527    #[serde(rename = "axisLabels")]
528    pub axis_labels: Vec<QuadrantChartAxisLabelData>,
529}
530
531#[derive(Debug, Clone, Serialize, Deserialize)]
532pub struct FlowchartV2Layout {
533    pub nodes: Vec<LayoutNode>,
534    pub edges: Vec<LayoutEdge>,
535    pub clusters: Vec<LayoutCluster>,
536    pub bounds: Option<Bounds>,
537    /// Mermaid's DOM insertion order for each extracted root graph (`""` = top-level root).
538    #[serde(skip)]
539    pub dom_node_order_by_root: std::collections::HashMap<String, Vec<String>>,
540}
541
542#[derive(Debug, Clone, Serialize, Deserialize)]
543pub struct StateDiagramV2Layout {
544    pub nodes: Vec<LayoutNode>,
545    pub edges: Vec<LayoutEdge>,
546    pub clusters: Vec<LayoutCluster>,
547    pub bounds: Option<Bounds>,
548}
549
550#[derive(Debug, Clone, Serialize, Deserialize)]
551pub struct ClassDiagramV2Layout {
552    pub nodes: Vec<LayoutNode>,
553    pub edges: Vec<LayoutEdge>,
554    pub clusters: Vec<LayoutCluster>,
555    pub bounds: Option<Bounds>,
556    #[serde(skip)]
557    pub class_row_metrics_by_id: FxHashMap<String, Arc<ClassNodeRowMetrics>>,
558}
559
560#[derive(Debug, Clone, Serialize, Deserialize)]
561pub struct ErDiagramLayout {
562    pub nodes: Vec<LayoutNode>,
563    pub edges: Vec<LayoutEdge>,
564    pub bounds: Option<Bounds>,
565}
566
567#[derive(Debug, Clone, Serialize, Deserialize)]
568pub struct SequenceDiagramLayout {
569    pub nodes: Vec<LayoutNode>,
570    pub edges: Vec<LayoutEdge>,
571    pub clusters: Vec<LayoutCluster>,
572    pub bounds: Option<Bounds>,
573}
574
575#[derive(Debug, Clone, Serialize, Deserialize)]
576pub struct InfoDiagramLayout {
577    pub bounds: Option<Bounds>,
578    pub version: String,
579}
580
581#[derive(Debug, Clone, Serialize, Deserialize)]
582pub struct PacketBlockLayout {
583    pub start: i64,
584    pub end: i64,
585    pub label: String,
586    pub x: f64,
587    pub y: f64,
588    pub width: f64,
589    pub height: f64,
590}
591
592#[derive(Debug, Clone, Serialize, Deserialize)]
593pub struct PacketWordLayout {
594    pub blocks: Vec<PacketBlockLayout>,
595}
596
597#[derive(Debug, Clone, Serialize, Deserialize)]
598pub struct PacketDiagramLayout {
599    pub bounds: Option<Bounds>,
600    pub width: f64,
601    pub height: f64,
602    pub row_height: f64,
603    pub padding_x: f64,
604    pub padding_y: f64,
605    pub bit_width: f64,
606    pub bits_per_row: i64,
607    pub show_bits: bool,
608    pub words: Vec<PacketWordLayout>,
609}
610
611#[derive(Debug, Clone, Serialize, Deserialize)]
612pub struct PieSliceLayout {
613    pub label: String,
614    pub value: f64,
615    pub start_angle: f64,
616    pub end_angle: f64,
617    pub is_full_circle: bool,
618    pub percent: i64,
619    pub text_x: f64,
620    pub text_y: f64,
621    pub fill: String,
622}
623
624#[derive(Debug, Clone, Serialize, Deserialize)]
625pub struct PieLegendItemLayout {
626    pub label: String,
627    pub value: f64,
628    pub fill: String,
629    pub y: f64,
630}
631
632#[derive(Debug, Clone, Serialize, Deserialize)]
633pub struct PieDiagramLayout {
634    pub bounds: Option<Bounds>,
635    pub center_x: f64,
636    pub center_y: f64,
637    pub radius: f64,
638    pub outer_radius: f64,
639    pub legend_x: f64,
640    pub legend_start_y: f64,
641    pub legend_step_y: f64,
642    pub slices: Vec<PieSliceLayout>,
643    pub legend_items: Vec<PieLegendItemLayout>,
644}
645
646#[derive(Debug, Clone, Serialize, Deserialize)]
647pub struct TimelineNodeLayout {
648    pub x: f64,
649    pub y: f64,
650    pub width: f64,
651    pub height: f64,
652    /// Width used for wrapping (excluding padding).
653    pub content_width: f64,
654    /// Padding used to compute `width` (Mermaid 11.12.2 uses 20).
655    pub padding: f64,
656    pub section_class: String,
657    pub label: String,
658    /// Wrapped lines as rendered into `<tspan>` nodes.
659    pub label_lines: Vec<String>,
660    pub kind: String,
661}
662
663#[derive(Debug, Clone, Serialize, Deserialize)]
664pub struct TimelineLineLayout {
665    pub kind: String,
666    pub x1: f64,
667    pub y1: f64,
668    pub x2: f64,
669    pub y2: f64,
670}
671
672#[derive(Debug, Clone, Serialize, Deserialize)]
673pub struct TimelineTaskLayout {
674    pub node: TimelineNodeLayout,
675    pub connector: TimelineLineLayout,
676    pub events: Vec<TimelineNodeLayout>,
677}
678
679#[derive(Debug, Clone, Serialize, Deserialize)]
680pub struct TimelineSectionLayout {
681    pub node: TimelineNodeLayout,
682    pub tasks: Vec<TimelineTaskLayout>,
683}
684
685#[derive(Debug, Clone, Serialize, Deserialize)]
686pub struct TimelineDiagramLayout {
687    pub bounds: Option<Bounds>,
688    pub left_margin: f64,
689    pub base_x: f64,
690    pub base_y: f64,
691    /// `svg.node().getBBox().width` computed *before* title/activity line are inserted.
692    pub pre_title_box_width: f64,
693    pub sections: Vec<TimelineSectionLayout>,
694    #[serde(default)]
695    pub orphan_tasks: Vec<TimelineTaskLayout>,
696    pub activity_line: TimelineLineLayout,
697    pub title: Option<String>,
698    pub title_x: f64,
699    pub title_y: f64,
700}
701
702#[derive(Debug, Clone, Serialize, Deserialize)]
703pub struct JourneyActorLegendLineLayout {
704    pub text: String,
705    pub x: f64,
706    pub y: f64,
707    pub tspan_x: f64,
708    pub text_margin: f64,
709}
710
711#[derive(Debug, Clone, Serialize, Deserialize)]
712pub struct JourneyActorLegendItemLayout {
713    pub actor: String,
714    pub pos: i64,
715    pub color: String,
716    pub circle_cx: f64,
717    pub circle_cy: f64,
718    pub circle_r: f64,
719    pub label_lines: Vec<JourneyActorLegendLineLayout>,
720}
721
722#[derive(Debug, Clone, Serialize, Deserialize)]
723pub enum JourneyMouthKind {
724    Smile,
725    Sad,
726    Ambivalent,
727}
728
729#[derive(Debug, Clone, Serialize, Deserialize)]
730pub struct JourneyTaskActorCircleLayout {
731    pub actor: String,
732    pub pos: i64,
733    pub color: String,
734    pub cx: f64,
735    pub cy: f64,
736    pub r: f64,
737}
738
739#[derive(Debug, Clone, Serialize, Deserialize)]
740pub struct JourneyTaskLayout {
741    pub index: i64,
742    pub section: String,
743    pub task: String,
744    pub score: i64,
745    pub x: f64,
746    pub y: f64,
747    pub width: f64,
748    pub height: f64,
749    pub fill: String,
750    pub num: i64,
751    pub people: Vec<String>,
752    pub actor_circles: Vec<JourneyTaskActorCircleLayout>,
753    pub line_id: String,
754    pub line_x1: f64,
755    pub line_y1: f64,
756    pub line_x2: f64,
757    pub line_y2: f64,
758    pub face_cx: f64,
759    pub face_cy: Option<f64>,
760    pub mouth: JourneyMouthKind,
761}
762
763#[derive(Debug, Clone, Serialize, Deserialize)]
764pub struct JourneySectionLayout {
765    pub section: String,
766    pub num: i64,
767    pub x: f64,
768    pub y: f64,
769    pub width: f64,
770    pub height: f64,
771    pub fill: String,
772    pub task_count: i64,
773}
774
775#[derive(Debug, Clone, Serialize, Deserialize)]
776pub struct JourneyLineLayout {
777    pub x1: f64,
778    pub y1: f64,
779    pub x2: f64,
780    pub y2: f64,
781}
782
783#[derive(Debug, Clone, Serialize, Deserialize)]
784pub struct JourneyDiagramLayout {
785    pub bounds: Option<Bounds>,
786    pub left_margin: f64,
787    pub max_actor_label_width: f64,
788    pub width: f64,
789    pub height: f64,
790    pub svg_height: f64,
791    pub title: Option<String>,
792    pub title_x: f64,
793    pub title_y: f64,
794    pub actor_legend: Vec<JourneyActorLegendItemLayout>,
795    pub sections: Vec<JourneySectionLayout>,
796    pub tasks: Vec<JourneyTaskLayout>,
797    pub activity_line: JourneyLineLayout,
798}
799
800#[derive(Debug, Clone, Serialize, Deserialize)]
801pub struct KanbanSectionLayout {
802    pub id: String,
803    pub label: String,
804    pub index: i64,
805    pub center_x: f64,
806    pub center_y: f64,
807    pub width: f64,
808    pub rect_y: f64,
809    pub rect_height: f64,
810    pub rx: f64,
811    pub ry: f64,
812    pub label_width: f64,
813    #[serde(skip)]
814    pub label_height: f64,
815}
816
817#[derive(Debug, Clone, Serialize, Deserialize)]
818pub struct KanbanItemLayout {
819    pub id: String,
820    pub label: String,
821    pub parent_id: String,
822    pub center_x: f64,
823    pub center_y: f64,
824    pub width: f64,
825    pub height: f64,
826    pub rx: f64,
827    pub ry: f64,
828    #[serde(default)]
829    pub ticket: Option<String>,
830    #[serde(default)]
831    pub assigned: Option<String>,
832    #[serde(default)]
833    pub priority: Option<String>,
834    #[serde(default)]
835    pub icon: Option<String>,
836}
837
838#[derive(Debug, Clone, Serialize, Deserialize)]
839pub struct KanbanDiagramLayout {
840    pub bounds: Option<Bounds>,
841    pub section_width: f64,
842    pub padding: f64,
843    pub max_label_height: f64,
844    pub viewbox_padding: f64,
845    pub sections: Vec<KanbanSectionLayout>,
846    pub items: Vec<KanbanItemLayout>,
847}
848
849#[derive(Debug, Clone, Serialize, Deserialize)]
850pub struct GitGraphBranchLayout {
851    pub name: String,
852    pub index: i64,
853    pub pos: f64,
854    pub bbox_width: f64,
855    pub bbox_height: f64,
856}
857
858#[derive(Debug, Clone, Serialize, Deserialize)]
859pub struct GitGraphCommitLayout {
860    pub id: String,
861    pub message: String,
862    pub seq: i64,
863    pub commit_type: i64,
864    #[serde(default)]
865    pub custom_type: Option<i64>,
866    #[serde(default)]
867    pub custom_id: Option<bool>,
868    #[serde(default)]
869    pub tags: Vec<String>,
870    #[serde(default)]
871    pub parents: Vec<String>,
872    pub branch: String,
873    pub pos: f64,
874    pub pos_with_offset: f64,
875    pub x: f64,
876    pub y: f64,
877}
878
879#[derive(Debug, Clone, Serialize, Deserialize)]
880pub struct GitGraphArrowLayout {
881    pub from: String,
882    pub to: String,
883    pub class_index: i64,
884    pub d: String,
885}
886
887#[derive(Debug, Clone, Serialize, Deserialize)]
888pub struct GitGraphDiagramLayout {
889    pub bounds: Option<Bounds>,
890    pub direction: String,
891    pub rotate_commit_label: bool,
892    pub show_branches: bool,
893    pub show_commit_label: bool,
894    pub parallel_commits: bool,
895    pub diagram_padding: f64,
896    pub max_pos: f64,
897    pub branches: Vec<GitGraphBranchLayout>,
898    pub commits: Vec<GitGraphCommitLayout>,
899    pub arrows: Vec<GitGraphArrowLayout>,
900}
901
902#[derive(Debug, Clone, Serialize, Deserialize)]
903pub struct TreeViewNodeLayout {
904    pub id: i64,
905    pub level: i64,
906    pub name: String,
907    pub depth: usize,
908    pub x: f64,
909    pub y: f64,
910    pub width: f64,
911    pub height: f64,
912    pub label_x: f64,
913    pub label_y: f64,
914    pub label_width: f64,
915    pub label_height: f64,
916}
917
918#[derive(Debug, Clone, Serialize, Deserialize)]
919pub struct TreeViewLineLayout {
920    pub x1: f64,
921    pub y1: f64,
922    pub x2: f64,
923    pub y2: f64,
924    pub stroke_width: f64,
925    pub kind: String,
926}
927
928#[derive(Debug, Clone, Serialize, Deserialize)]
929pub struct TreeViewDiagramLayout {
930    pub bounds: Option<Bounds>,
931    pub total_width: f64,
932    pub total_height: f64,
933    pub row_indent: f64,
934    pub padding_x: f64,
935    pub padding_y: f64,
936    pub line_thickness: f64,
937    pub use_max_width: bool,
938    pub label_font_size: f64,
939    pub nodes: Vec<TreeViewNodeLayout>,
940    pub lines: Vec<TreeViewLineLayout>,
941}
942
943#[derive(Debug, Clone, Serialize, Deserialize)]
944pub struct IshikawaLineLayout {
945    pub x1: f64,
946    pub y1: f64,
947    pub x2: f64,
948    pub y2: f64,
949    pub class_name: String,
950    pub marker_start: bool,
951}
952
953#[derive(Debug, Clone, Serialize, Deserialize)]
954pub struct IshikawaTextLayout {
955    pub text: String,
956    pub lines: Vec<String>,
957    pub class_name: String,
958    pub x: f64,
959    pub y: f64,
960    pub anchor: String,
961    pub line_height: f64,
962    pub font_size: f64,
963    pub bbox: Bounds,
964}
965
966#[derive(Debug, Clone, Serialize, Deserialize)]
967pub struct IshikawaLabelBoxLayout {
968    pub x: f64,
969    pub y: f64,
970    pub width: f64,
971    pub height: f64,
972}
973
974#[derive(Debug, Clone, Serialize, Deserialize)]
975pub struct IshikawaHeadLayout {
976    pub x: f64,
977    pub y: f64,
978    pub width: f64,
979    pub height: f64,
980    pub path_d: String,
981    pub label: IshikawaTextLayout,
982}
983
984#[derive(Debug, Clone, Serialize, Deserialize)]
985pub struct IshikawaDiagramLayout {
986    pub bounds: Option<Bounds>,
987    pub total_width: f64,
988    pub total_height: f64,
989    pub viewbox_x: f64,
990    pub viewbox_y: f64,
991    pub padding: f64,
992    pub use_max_width: bool,
993    pub font_size: f64,
994    pub head: Option<IshikawaHeadLayout>,
995    pub lines: Vec<IshikawaLineLayout>,
996    pub labels: Vec<IshikawaTextLayout>,
997    pub label_boxes: Vec<IshikawaLabelBoxLayout>,
998}
999
1000#[derive(Debug, Clone, Serialize, Deserialize)]
1001pub struct EventModelingSwimlaneLayout {
1002    pub index: i64,
1003    pub label: String,
1004    pub namespace: Option<String>,
1005    pub x: f64,
1006    pub y: f64,
1007    pub width: f64,
1008    pub height: f64,
1009}
1010
1011#[derive(Debug, Clone, Serialize, Deserialize)]
1012pub struct EventModelingBoxLayout {
1013    pub index: usize,
1014    pub frame_name: String,
1015    pub frame_kind: String,
1016    pub model_entity_type: String,
1017    pub entity_identifier: String,
1018    pub text: String,
1019    pub x: f64,
1020    pub y: f64,
1021    pub width: f64,
1022    pub height: f64,
1023    pub fill: String,
1024    pub stroke: String,
1025    pub swimlane_index: i64,
1026}
1027
1028#[derive(Debug, Clone, Serialize, Deserialize)]
1029pub struct EventModelingRelationLayout {
1030    pub source_frame: String,
1031    pub target_frame: String,
1032    pub x1: f64,
1033    pub y1: f64,
1034    pub x2: f64,
1035    pub y2: f64,
1036    pub stroke: String,
1037}
1038
1039#[derive(Debug, Clone, Serialize, Deserialize)]
1040pub struct EventModelingDiagramLayout {
1041    pub bounds: Option<Bounds>,
1042    pub total_width: f64,
1043    pub total_height: f64,
1044    pub viewbox_x: f64,
1045    pub viewbox_y: f64,
1046    pub padding: f64,
1047    pub use_max_width: bool,
1048    pub swimlanes: Vec<EventModelingSwimlaneLayout>,
1049    pub boxes: Vec<EventModelingBoxLayout>,
1050    pub relations: Vec<EventModelingRelationLayout>,
1051}
1052
1053#[derive(Debug, Clone, Serialize, Deserialize)]
1054pub struct GanttAxisTickLayout {
1055    pub time_ms: i64,
1056    pub x: f64,
1057    pub label: String,
1058}
1059
1060#[derive(Debug, Clone, Serialize, Deserialize)]
1061pub struct GanttExcludeRangeLayout {
1062    pub id: String,
1063    pub start_ms: i64,
1064    pub end_ms: i64,
1065    pub x: f64,
1066    pub y: f64,
1067    pub width: f64,
1068    pub height: f64,
1069}
1070
1071#[derive(Debug, Clone, Serialize, Deserialize)]
1072pub struct GanttSectionTitleLayout {
1073    pub section: String,
1074    pub index: i64,
1075    pub x: f64,
1076    pub y: f64,
1077    pub dy_em: f64,
1078    pub lines: Vec<String>,
1079    pub class: String,
1080}
1081
1082#[derive(Debug, Clone, Serialize, Deserialize)]
1083pub struct GanttRowLayout {
1084    pub index: i64,
1085    pub x: f64,
1086    pub y: f64,
1087    pub width: f64,
1088    pub height: f64,
1089    pub class: String,
1090}
1091
1092#[derive(Debug, Clone, Serialize, Deserialize)]
1093pub struct GanttTaskLabelLayout {
1094    pub id: String,
1095    pub text: String,
1096    pub font_size: f64,
1097    pub width: f64,
1098    pub x: f64,
1099    pub y: f64,
1100    pub class: String,
1101}
1102
1103#[derive(Debug, Clone, Serialize, Deserialize)]
1104pub struct GanttTaskBarLayout {
1105    pub id: String,
1106    pub x: f64,
1107    pub y: f64,
1108    pub width: f64,
1109    pub height: f64,
1110    pub rx: f64,
1111    pub ry: f64,
1112    pub class: String,
1113}
1114
1115#[derive(Debug, Clone, Serialize, Deserialize)]
1116pub struct GanttTaskLayout {
1117    pub id: String,
1118    pub task: String,
1119    pub section: String,
1120    pub task_type: String,
1121    pub order: i64,
1122    pub start_ms: i64,
1123    pub end_ms: i64,
1124    #[serde(default)]
1125    pub render_end_ms: Option<i64>,
1126    pub milestone: bool,
1127    pub vert: bool,
1128    pub bar: GanttTaskBarLayout,
1129    pub label: GanttTaskLabelLayout,
1130}
1131
1132#[derive(Debug, Clone, Serialize, Deserialize)]
1133pub struct GanttDiagramLayout {
1134    pub bounds: Option<Bounds>,
1135    pub width: f64,
1136    pub height: f64,
1137    pub left_padding: f64,
1138    pub right_padding: f64,
1139    pub top_padding: f64,
1140    pub grid_line_start_padding: f64,
1141    pub bar_height: f64,
1142    pub bar_gap: f64,
1143    pub title_top_margin: f64,
1144    pub font_size: f64,
1145    pub section_font_size: f64,
1146    pub number_section_styles: i64,
1147    pub display_mode: String,
1148    pub date_format: String,
1149    pub axis_format: String,
1150    #[serde(default)]
1151    pub tick_interval: Option<String>,
1152    pub top_axis: bool,
1153    pub today_marker: String,
1154    pub categories: Vec<String>,
1155    pub rows: Vec<GanttRowLayout>,
1156    pub section_titles: Vec<GanttSectionTitleLayout>,
1157    pub tasks: Vec<GanttTaskLayout>,
1158    pub excludes: Vec<GanttExcludeRangeLayout>,
1159    #[serde(default)]
1160    pub has_excludes_layer: bool,
1161    pub bottom_ticks: Vec<GanttAxisTickLayout>,
1162    #[serde(default)]
1163    pub top_ticks: Vec<GanttAxisTickLayout>,
1164    pub title: Option<String>,
1165    pub title_x: f64,
1166    pub title_y: f64,
1167}
1168
1169#[derive(Debug, Clone, Serialize, Deserialize)]
1170pub struct C4TextBlockLayout {
1171    pub text: String,
1172    pub y: f64,
1173    pub width: f64,
1174    pub height: f64,
1175    pub line_count: usize,
1176}
1177
1178#[derive(Debug, Clone, Serialize, Deserialize)]
1179pub struct C4ImageLayout {
1180    pub width: f64,
1181    pub height: f64,
1182    pub y: f64,
1183}
1184
1185#[derive(Debug, Clone, Serialize, Deserialize)]
1186pub struct C4ShapeLayout {
1187    pub alias: String,
1188    pub parent_boundary: String,
1189    pub type_c4_shape: String,
1190    pub x: f64,
1191    pub y: f64,
1192    pub width: f64,
1193    pub height: f64,
1194    pub margin: f64,
1195    pub image: C4ImageLayout,
1196    pub type_block: C4TextBlockLayout,
1197    pub label: C4TextBlockLayout,
1198    #[serde(default)]
1199    pub ty: Option<C4TextBlockLayout>,
1200    #[serde(default)]
1201    pub techn: Option<C4TextBlockLayout>,
1202    #[serde(default)]
1203    pub descr: Option<C4TextBlockLayout>,
1204}
1205
1206#[derive(Debug, Clone, Serialize, Deserialize)]
1207pub struct C4BoundaryLayout {
1208    pub alias: String,
1209    pub parent_boundary: String,
1210    pub x: f64,
1211    pub y: f64,
1212    pub width: f64,
1213    pub height: f64,
1214    pub image: C4ImageLayout,
1215    pub label: C4TextBlockLayout,
1216    #[serde(default)]
1217    pub ty: Option<C4TextBlockLayout>,
1218    #[serde(default)]
1219    pub descr: Option<C4TextBlockLayout>,
1220}
1221
1222#[derive(Debug, Clone, Serialize, Deserialize)]
1223pub struct C4RelLayout {
1224    pub from: String,
1225    pub to: String,
1226    pub rel_type: String,
1227    pub start_point: LayoutPoint,
1228    pub end_point: LayoutPoint,
1229    #[serde(default)]
1230    pub offset_x: Option<i64>,
1231    #[serde(default)]
1232    pub offset_y: Option<i64>,
1233    pub label: C4TextBlockLayout,
1234    #[serde(default)]
1235    pub techn: Option<C4TextBlockLayout>,
1236    #[serde(default)]
1237    pub descr: Option<C4TextBlockLayout>,
1238}
1239
1240#[derive(Debug, Clone, Serialize, Deserialize)]
1241pub struct C4DiagramLayout {
1242    pub bounds: Option<Bounds>,
1243    pub width: f64,
1244    pub height: f64,
1245    pub viewport_width: f64,
1246    pub viewport_height: f64,
1247    pub c4_type: String,
1248    pub title: Option<String>,
1249    pub boundaries: Vec<C4BoundaryLayout>,
1250    pub shapes: Vec<C4ShapeLayout>,
1251    pub rels: Vec<C4RelLayout>,
1252}
1253
1254#[derive(Debug, Clone, Serialize, Deserialize)]
1255pub struct ErrorDiagramLayout {
1256    pub viewbox_width: f64,
1257    pub viewbox_height: f64,
1258    pub max_width_px: f64,
1259}
1260
1261#[derive(Debug, Clone, Serialize, Deserialize)]
1262pub enum LayoutDiagram {
1263    BlockDiagram(Box<BlockDiagramLayout>),
1264    RequirementDiagram(Box<RequirementDiagramLayout>),
1265    ArchitectureDiagram(Box<ArchitectureDiagramLayout>),
1266    MindmapDiagram(Box<MindmapDiagramLayout>),
1267    SankeyDiagram(Box<SankeyDiagramLayout>),
1268    RadarDiagram(Box<RadarDiagramLayout>),
1269    TreemapDiagram(Box<TreemapDiagramLayout>),
1270    XyChartDiagram(Box<XyChartDiagramLayout>),
1271    QuadrantChartDiagram(Box<QuadrantChartDiagramLayout>),
1272    FlowchartV2(Box<FlowchartV2Layout>),
1273    StateDiagramV2(Box<StateDiagramV2Layout>),
1274    ClassDiagramV2(Box<ClassDiagramV2Layout>),
1275    ErDiagram(Box<ErDiagramLayout>),
1276    SequenceDiagram(Box<SequenceDiagramLayout>),
1277    InfoDiagram(Box<InfoDiagramLayout>),
1278    PacketDiagram(Box<PacketDiagramLayout>),
1279    TimelineDiagram(Box<TimelineDiagramLayout>),
1280    PieDiagram(Box<PieDiagramLayout>),
1281    JourneyDiagram(Box<JourneyDiagramLayout>),
1282    KanbanDiagram(Box<KanbanDiagramLayout>),
1283    GitGraphDiagram(Box<GitGraphDiagramLayout>),
1284    TreeViewDiagram(Box<TreeViewDiagramLayout>),
1285    IshikawaDiagram(Box<IshikawaDiagramLayout>),
1286    EventModelingDiagram(Box<EventModelingDiagramLayout>),
1287    GanttDiagram(Box<GanttDiagramLayout>),
1288    C4Diagram(Box<C4DiagramLayout>),
1289    ErrorDiagram(Box<ErrorDiagramLayout>),
1290}
1291
1292#[derive(Debug, Clone, Serialize, Deserialize)]
1293pub struct LayoutedDiagram {
1294    pub meta: LayoutMeta,
1295    pub semantic: Value,
1296    pub layout: LayoutDiagram,
1297}