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    pub bounds: Option<Bounds>,
157}
158
159#[derive(Debug, Clone, Serialize, Deserialize)]
160pub struct MindmapDiagramLayout {
161    pub nodes: Vec<LayoutNode>,
162    pub edges: Vec<LayoutEdge>,
163    pub bounds: Option<Bounds>,
164}
165
166#[derive(Debug, Clone, Serialize, Deserialize)]
167pub struct SankeyNodeLayout {
168    pub id: String,
169    pub index: usize,
170    pub depth: usize,
171    pub height: usize,
172    pub layer: usize,
173    pub value: f64,
174    pub x0: f64,
175    pub x1: f64,
176    pub y0: f64,
177    pub y1: f64,
178}
179
180#[derive(Debug, Clone, Serialize, Deserialize)]
181pub struct SankeyLinkLayout {
182    pub index: usize,
183    pub source: String,
184    pub target: String,
185    pub value: f64,
186    pub width: f64,
187    pub y0: f64,
188    pub y1: f64,
189}
190
191#[derive(Debug, Clone, Serialize, Deserialize)]
192pub struct SankeyDiagramLayout {
193    pub bounds: Option<Bounds>,
194    pub width: f64,
195    pub height: f64,
196    pub node_width: f64,
197    pub node_padding: f64,
198    pub nodes: Vec<SankeyNodeLayout>,
199    pub links: Vec<SankeyLinkLayout>,
200}
201
202#[derive(Debug, Clone, Serialize, Deserialize)]
203pub struct RadarAxisLayout {
204    pub label: String,
205    pub angle: f64,
206    pub line_x2: f64,
207    pub line_y2: f64,
208    pub label_x: f64,
209    pub label_y: f64,
210}
211
212#[derive(Debug, Clone, Serialize, Deserialize)]
213pub struct RadarGraticuleShapeLayout {
214    pub kind: String,
215    pub r: Option<f64>,
216    #[serde(default)]
217    pub points: Vec<LayoutPoint>,
218}
219
220#[derive(Debug, Clone, Serialize, Deserialize)]
221pub struct RadarCurveLayout {
222    pub label: String,
223    pub class_index: i64,
224    #[serde(default)]
225    pub points: Vec<LayoutPoint>,
226    pub path_d: String,
227}
228
229#[derive(Debug, Clone, Serialize, Deserialize)]
230pub struct RadarLegendItemLayout {
231    pub label: String,
232    pub class_index: i64,
233    pub x: f64,
234    pub y: f64,
235}
236
237#[derive(Debug, Clone, Serialize, Deserialize)]
238pub struct RadarDiagramLayout {
239    pub bounds: Option<Bounds>,
240    pub svg_width: f64,
241    pub svg_height: f64,
242    pub center_x: f64,
243    pub center_y: f64,
244    pub radius: f64,
245    pub axis_label_factor: f64,
246    pub title_y: f64,
247    #[serde(default)]
248    pub axes: Vec<RadarAxisLayout>,
249    #[serde(default)]
250    pub graticules: Vec<RadarGraticuleShapeLayout>,
251    #[serde(default)]
252    pub curves: Vec<RadarCurveLayout>,
253    #[serde(default)]
254    pub legend_items: Vec<RadarLegendItemLayout>,
255}
256
257#[derive(Debug, Clone, Serialize, Deserialize)]
258pub struct TreemapSectionLayout {
259    pub name: String,
260    pub depth: i64,
261    pub value: f64,
262    pub x0: f64,
263    pub y0: f64,
264    pub x1: f64,
265    pub y1: f64,
266    #[serde(default)]
267    pub class_selector: Option<String>,
268    #[serde(default)]
269    pub css_compiled_styles: Option<Vec<String>>,
270}
271
272#[derive(Debug, Clone, Serialize, Deserialize)]
273pub struct TreemapLeafLayout {
274    pub name: String,
275    pub value: f64,
276    #[serde(default)]
277    pub parent_name: Option<String>,
278    pub x0: f64,
279    pub y0: f64,
280    pub x1: f64,
281    pub y1: f64,
282    #[serde(default)]
283    pub class_selector: Option<String>,
284    #[serde(default)]
285    pub css_compiled_styles: Option<Vec<String>>,
286}
287
288#[derive(Debug, Clone, Serialize, Deserialize)]
289pub struct TreemapDiagramLayout {
290    pub title_height: f64,
291    pub width: f64,
292    pub height: f64,
293    pub use_max_width: bool,
294    pub diagram_padding: f64,
295    pub show_values: bool,
296    pub value_format: String,
297    #[serde(default, rename = "accTitle")]
298    pub acc_title: Option<String>,
299    #[serde(default, rename = "accDescr")]
300    pub acc_descr: Option<String>,
301    #[serde(default)]
302    pub title: Option<String>,
303    #[serde(default)]
304    pub sections: Vec<TreemapSectionLayout>,
305    #[serde(default)]
306    pub leaves: Vec<TreemapLeafLayout>,
307}
308
309#[derive(Debug, Clone, Serialize, Deserialize)]
310pub struct XyChartRectData {
311    pub x: f64,
312    pub y: f64,
313    pub width: f64,
314    pub height: f64,
315    pub fill: String,
316    #[serde(rename = "strokeFill")]
317    pub stroke_fill: String,
318    #[serde(rename = "strokeWidth")]
319    pub stroke_width: f64,
320}
321
322#[derive(Debug, Clone, Serialize, Deserialize)]
323pub struct XyChartTextData {
324    pub text: String,
325    pub x: f64,
326    pub y: f64,
327    pub fill: String,
328    #[serde(rename = "fontSize")]
329    pub font_size: f64,
330    #[serde(default)]
331    pub rotation: f64,
332    #[serde(rename = "verticalPos")]
333    pub vertical_pos: String,
334    #[serde(rename = "horizontalPos")]
335    pub horizontal_pos: String,
336}
337
338#[derive(Debug, Clone, Serialize, Deserialize)]
339pub struct XyChartPathData {
340    pub path: String,
341    #[serde(default)]
342    pub fill: Option<String>,
343    #[serde(rename = "strokeFill")]
344    pub stroke_fill: String,
345    #[serde(rename = "strokeWidth")]
346    pub stroke_width: f64,
347}
348
349#[derive(Debug, Clone, Serialize, Deserialize)]
350#[serde(tag = "type")]
351pub enum XyChartDrawableElem {
352    #[serde(rename = "rect")]
353    Rect {
354        #[serde(rename = "groupTexts")]
355        group_texts: Vec<String>,
356        data: Vec<XyChartRectData>,
357    },
358    #[serde(rename = "text")]
359    Text {
360        #[serde(rename = "groupTexts")]
361        group_texts: Vec<String>,
362        data: Vec<XyChartTextData>,
363    },
364    #[serde(rename = "path")]
365    Path {
366        #[serde(rename = "groupTexts")]
367        group_texts: Vec<String>,
368        data: Vec<XyChartPathData>,
369    },
370}
371
372#[derive(Debug, Clone, Serialize, Deserialize)]
373pub struct XyChartDiagramLayout {
374    pub width: f64,
375    pub height: f64,
376    #[serde(rename = "chartOrientation")]
377    pub chart_orientation: String,
378    #[serde(rename = "showDataLabel")]
379    pub show_data_label: bool,
380    #[serde(rename = "backgroundColor")]
381    pub background_color: String,
382    #[serde(rename = "labelData")]
383    pub label_data: Vec<String>,
384    #[serde(default)]
385    pub drawables: Vec<XyChartDrawableElem>,
386}
387
388#[derive(Debug, Clone, Serialize, Deserialize)]
389pub struct QuadrantChartTextData {
390    pub text: String,
391    pub x: f64,
392    pub y: f64,
393    pub fill: String,
394    #[serde(rename = "fontSize")]
395    pub font_size: f64,
396    #[serde(default)]
397    pub rotation: f64,
398    #[serde(rename = "verticalPos")]
399    pub vertical_pos: String,
400    #[serde(rename = "horizontalPos")]
401    pub horizontal_pos: String,
402}
403
404pub type QuadrantChartAxisLabelData = QuadrantChartTextData;
405
406#[derive(Debug, Clone, Serialize, Deserialize)]
407pub struct QuadrantChartQuadrantData {
408    pub x: f64,
409    pub y: f64,
410    pub width: f64,
411    pub height: f64,
412    pub fill: String,
413    pub text: QuadrantChartTextData,
414}
415
416#[derive(Debug, Clone, Serialize, Deserialize)]
417pub struct QuadrantChartBorderLineData {
418    #[serde(rename = "strokeWidth")]
419    pub stroke_width: f64,
420    #[serde(rename = "strokeFill")]
421    pub stroke_fill: String,
422    pub x1: f64,
423    pub y1: f64,
424    pub x2: f64,
425    pub y2: f64,
426}
427
428#[derive(Debug, Clone, Serialize, Deserialize)]
429pub struct QuadrantChartPointData {
430    pub x: f64,
431    pub y: f64,
432    pub fill: String,
433    pub radius: f64,
434    #[serde(rename = "strokeColor")]
435    pub stroke_color: String,
436    #[serde(rename = "strokeWidth")]
437    pub stroke_width: String,
438    pub text: QuadrantChartTextData,
439}
440
441#[derive(Debug, Clone, Serialize, Deserialize)]
442pub struct QuadrantChartDiagramLayout {
443    pub width: f64,
444    pub height: f64,
445    #[serde(default)]
446    pub title: Option<QuadrantChartTextData>,
447    pub quadrants: Vec<QuadrantChartQuadrantData>,
448    #[serde(rename = "borderLines")]
449    pub border_lines: Vec<QuadrantChartBorderLineData>,
450    pub points: Vec<QuadrantChartPointData>,
451    #[serde(rename = "axisLabels")]
452    pub axis_labels: Vec<QuadrantChartAxisLabelData>,
453}
454
455#[derive(Debug, Clone, Serialize, Deserialize)]
456pub struct FlowchartV2Layout {
457    pub nodes: Vec<LayoutNode>,
458    pub edges: Vec<LayoutEdge>,
459    pub clusters: Vec<LayoutCluster>,
460    pub bounds: Option<Bounds>,
461    /// Mermaid's DOM insertion order for each extracted root graph (`""` = top-level root).
462    #[serde(skip)]
463    pub dom_node_order_by_root: std::collections::HashMap<String, Vec<String>>,
464}
465
466#[derive(Debug, Clone, Serialize, Deserialize)]
467pub struct StateDiagramV2Layout {
468    pub nodes: Vec<LayoutNode>,
469    pub edges: Vec<LayoutEdge>,
470    pub clusters: Vec<LayoutCluster>,
471    pub bounds: Option<Bounds>,
472}
473
474#[derive(Debug, Clone, Serialize, Deserialize)]
475pub struct ClassDiagramV2Layout {
476    pub nodes: Vec<LayoutNode>,
477    pub edges: Vec<LayoutEdge>,
478    pub clusters: Vec<LayoutCluster>,
479    pub bounds: Option<Bounds>,
480    #[serde(skip)]
481    pub class_row_metrics_by_id: FxHashMap<String, Arc<ClassNodeRowMetrics>>,
482}
483
484#[derive(Debug, Clone, Serialize, Deserialize)]
485pub struct ErDiagramLayout {
486    pub nodes: Vec<LayoutNode>,
487    pub edges: Vec<LayoutEdge>,
488    pub bounds: Option<Bounds>,
489}
490
491#[derive(Debug, Clone, Serialize, Deserialize)]
492pub struct SequenceDiagramLayout {
493    pub nodes: Vec<LayoutNode>,
494    pub edges: Vec<LayoutEdge>,
495    pub clusters: Vec<LayoutCluster>,
496    pub bounds: Option<Bounds>,
497}
498
499#[derive(Debug, Clone, Serialize, Deserialize)]
500pub struct InfoDiagramLayout {
501    pub bounds: Option<Bounds>,
502    pub version: String,
503}
504
505#[derive(Debug, Clone, Serialize, Deserialize)]
506pub struct PacketBlockLayout {
507    pub start: i64,
508    pub end: i64,
509    pub label: String,
510    pub x: f64,
511    pub y: f64,
512    pub width: f64,
513    pub height: f64,
514}
515
516#[derive(Debug, Clone, Serialize, Deserialize)]
517pub struct PacketWordLayout {
518    pub blocks: Vec<PacketBlockLayout>,
519}
520
521#[derive(Debug, Clone, Serialize, Deserialize)]
522pub struct PacketDiagramLayout {
523    pub bounds: Option<Bounds>,
524    pub width: f64,
525    pub height: f64,
526    pub row_height: f64,
527    pub padding_x: f64,
528    pub padding_y: f64,
529    pub bit_width: f64,
530    pub bits_per_row: i64,
531    pub show_bits: bool,
532    pub words: Vec<PacketWordLayout>,
533}
534
535#[derive(Debug, Clone, Serialize, Deserialize)]
536pub struct PieSliceLayout {
537    pub label: String,
538    pub value: f64,
539    pub start_angle: f64,
540    pub end_angle: f64,
541    pub is_full_circle: bool,
542    pub percent: i64,
543    pub text_x: f64,
544    pub text_y: f64,
545    pub fill: String,
546}
547
548#[derive(Debug, Clone, Serialize, Deserialize)]
549pub struct PieLegendItemLayout {
550    pub label: String,
551    pub value: f64,
552    pub fill: String,
553    pub y: f64,
554}
555
556#[derive(Debug, Clone, Serialize, Deserialize)]
557pub struct PieDiagramLayout {
558    pub bounds: Option<Bounds>,
559    pub center_x: f64,
560    pub center_y: f64,
561    pub radius: f64,
562    pub outer_radius: f64,
563    pub legend_x: f64,
564    pub legend_start_y: f64,
565    pub legend_step_y: f64,
566    pub slices: Vec<PieSliceLayout>,
567    pub legend_items: Vec<PieLegendItemLayout>,
568}
569
570#[derive(Debug, Clone, Serialize, Deserialize)]
571pub struct TimelineNodeLayout {
572    pub x: f64,
573    pub y: f64,
574    pub width: f64,
575    pub height: f64,
576    /// Width used for wrapping (excluding padding).
577    pub content_width: f64,
578    /// Padding used to compute `width` (Mermaid 11.12.2 uses 20).
579    pub padding: f64,
580    pub section_class: String,
581    pub label: String,
582    /// Wrapped lines as rendered into `<tspan>` nodes.
583    pub label_lines: Vec<String>,
584    pub kind: String,
585}
586
587#[derive(Debug, Clone, Serialize, Deserialize)]
588pub struct TimelineLineLayout {
589    pub kind: String,
590    pub x1: f64,
591    pub y1: f64,
592    pub x2: f64,
593    pub y2: f64,
594}
595
596#[derive(Debug, Clone, Serialize, Deserialize)]
597pub struct TimelineTaskLayout {
598    pub node: TimelineNodeLayout,
599    pub connector: TimelineLineLayout,
600    pub events: Vec<TimelineNodeLayout>,
601}
602
603#[derive(Debug, Clone, Serialize, Deserialize)]
604pub struct TimelineSectionLayout {
605    pub node: TimelineNodeLayout,
606    pub tasks: Vec<TimelineTaskLayout>,
607}
608
609#[derive(Debug, Clone, Serialize, Deserialize)]
610pub struct TimelineDiagramLayout {
611    pub bounds: Option<Bounds>,
612    pub left_margin: f64,
613    pub base_x: f64,
614    pub base_y: f64,
615    /// `svg.node().getBBox().width` computed *before* title/activity line are inserted.
616    pub pre_title_box_width: f64,
617    pub sections: Vec<TimelineSectionLayout>,
618    #[serde(default)]
619    pub orphan_tasks: Vec<TimelineTaskLayout>,
620    pub activity_line: TimelineLineLayout,
621    pub title: Option<String>,
622    pub title_x: f64,
623    pub title_y: f64,
624}
625
626#[derive(Debug, Clone, Serialize, Deserialize)]
627pub struct JourneyActorLegendLineLayout {
628    pub text: String,
629    pub x: f64,
630    pub y: f64,
631    pub tspan_x: f64,
632    pub text_margin: f64,
633}
634
635#[derive(Debug, Clone, Serialize, Deserialize)]
636pub struct JourneyActorLegendItemLayout {
637    pub actor: String,
638    pub pos: i64,
639    pub color: String,
640    pub circle_cx: f64,
641    pub circle_cy: f64,
642    pub circle_r: f64,
643    pub label_lines: Vec<JourneyActorLegendLineLayout>,
644}
645
646#[derive(Debug, Clone, Serialize, Deserialize)]
647pub enum JourneyMouthKind {
648    Smile,
649    Sad,
650    Ambivalent,
651}
652
653#[derive(Debug, Clone, Serialize, Deserialize)]
654pub struct JourneyTaskActorCircleLayout {
655    pub actor: String,
656    pub pos: i64,
657    pub color: String,
658    pub cx: f64,
659    pub cy: f64,
660    pub r: f64,
661}
662
663#[derive(Debug, Clone, Serialize, Deserialize)]
664pub struct JourneyTaskLayout {
665    pub index: i64,
666    pub section: String,
667    pub task: String,
668    pub score: i64,
669    pub x: f64,
670    pub y: f64,
671    pub width: f64,
672    pub height: f64,
673    pub fill: String,
674    pub num: i64,
675    pub people: Vec<String>,
676    pub actor_circles: Vec<JourneyTaskActorCircleLayout>,
677    pub line_id: String,
678    pub line_x1: f64,
679    pub line_y1: f64,
680    pub line_x2: f64,
681    pub line_y2: f64,
682    pub face_cx: f64,
683    pub face_cy: Option<f64>,
684    pub mouth: JourneyMouthKind,
685}
686
687#[derive(Debug, Clone, Serialize, Deserialize)]
688pub struct JourneySectionLayout {
689    pub section: String,
690    pub num: i64,
691    pub x: f64,
692    pub y: f64,
693    pub width: f64,
694    pub height: f64,
695    pub fill: String,
696    pub task_count: i64,
697}
698
699#[derive(Debug, Clone, Serialize, Deserialize)]
700pub struct JourneyLineLayout {
701    pub x1: f64,
702    pub y1: f64,
703    pub x2: f64,
704    pub y2: f64,
705}
706
707#[derive(Debug, Clone, Serialize, Deserialize)]
708pub struct JourneyDiagramLayout {
709    pub bounds: Option<Bounds>,
710    pub left_margin: f64,
711    pub max_actor_label_width: f64,
712    pub width: f64,
713    pub height: f64,
714    pub svg_height: f64,
715    pub title: Option<String>,
716    pub title_x: f64,
717    pub title_y: f64,
718    pub actor_legend: Vec<JourneyActorLegendItemLayout>,
719    pub sections: Vec<JourneySectionLayout>,
720    pub tasks: Vec<JourneyTaskLayout>,
721    pub activity_line: JourneyLineLayout,
722}
723
724#[derive(Debug, Clone, Serialize, Deserialize)]
725pub struct KanbanSectionLayout {
726    pub id: String,
727    pub label: String,
728    pub index: i64,
729    pub center_x: f64,
730    pub center_y: f64,
731    pub width: f64,
732    pub rect_y: f64,
733    pub rect_height: f64,
734    pub rx: f64,
735    pub ry: f64,
736    pub label_width: f64,
737    #[serde(skip)]
738    pub label_height: f64,
739}
740
741#[derive(Debug, Clone, Serialize, Deserialize)]
742pub struct KanbanItemLayout {
743    pub id: String,
744    pub label: String,
745    pub parent_id: String,
746    pub center_x: f64,
747    pub center_y: f64,
748    pub width: f64,
749    pub height: f64,
750    pub rx: f64,
751    pub ry: f64,
752    #[serde(default)]
753    pub ticket: Option<String>,
754    #[serde(default)]
755    pub assigned: Option<String>,
756    #[serde(default)]
757    pub priority: Option<String>,
758    #[serde(default)]
759    pub icon: Option<String>,
760}
761
762#[derive(Debug, Clone, Serialize, Deserialize)]
763pub struct KanbanDiagramLayout {
764    pub bounds: Option<Bounds>,
765    pub section_width: f64,
766    pub padding: f64,
767    pub max_label_height: f64,
768    pub viewbox_padding: f64,
769    pub sections: Vec<KanbanSectionLayout>,
770    pub items: Vec<KanbanItemLayout>,
771}
772
773#[derive(Debug, Clone, Serialize, Deserialize)]
774pub struct GitGraphBranchLayout {
775    pub name: String,
776    pub index: i64,
777    pub pos: f64,
778    pub bbox_width: f64,
779    pub bbox_height: f64,
780}
781
782#[derive(Debug, Clone, Serialize, Deserialize)]
783pub struct GitGraphCommitLayout {
784    pub id: String,
785    pub message: String,
786    pub seq: i64,
787    pub commit_type: i64,
788    #[serde(default)]
789    pub custom_type: Option<i64>,
790    #[serde(default)]
791    pub custom_id: Option<bool>,
792    #[serde(default)]
793    pub tags: Vec<String>,
794    #[serde(default)]
795    pub parents: Vec<String>,
796    pub branch: String,
797    pub pos: f64,
798    pub pos_with_offset: f64,
799    pub x: f64,
800    pub y: f64,
801}
802
803#[derive(Debug, Clone, Serialize, Deserialize)]
804pub struct GitGraphArrowLayout {
805    pub from: String,
806    pub to: String,
807    pub class_index: i64,
808    pub d: String,
809}
810
811#[derive(Debug, Clone, Serialize, Deserialize)]
812pub struct GitGraphDiagramLayout {
813    pub bounds: Option<Bounds>,
814    pub direction: String,
815    pub rotate_commit_label: bool,
816    pub show_branches: bool,
817    pub show_commit_label: bool,
818    pub parallel_commits: bool,
819    pub diagram_padding: f64,
820    pub max_pos: f64,
821    pub branches: Vec<GitGraphBranchLayout>,
822    pub commits: Vec<GitGraphCommitLayout>,
823    pub arrows: Vec<GitGraphArrowLayout>,
824}
825
826#[derive(Debug, Clone, Serialize, Deserialize)]
827pub struct GanttAxisTickLayout {
828    pub time_ms: i64,
829    pub x: f64,
830    pub label: String,
831}
832
833#[derive(Debug, Clone, Serialize, Deserialize)]
834pub struct GanttExcludeRangeLayout {
835    pub id: String,
836    pub start_ms: i64,
837    pub end_ms: i64,
838    pub x: f64,
839    pub y: f64,
840    pub width: f64,
841    pub height: f64,
842}
843
844#[derive(Debug, Clone, Serialize, Deserialize)]
845pub struct GanttSectionTitleLayout {
846    pub section: String,
847    pub index: i64,
848    pub x: f64,
849    pub y: f64,
850    pub dy_em: f64,
851    pub lines: Vec<String>,
852    pub class: String,
853}
854
855#[derive(Debug, Clone, Serialize, Deserialize)]
856pub struct GanttRowLayout {
857    pub index: i64,
858    pub x: f64,
859    pub y: f64,
860    pub width: f64,
861    pub height: f64,
862    pub class: String,
863}
864
865#[derive(Debug, Clone, Serialize, Deserialize)]
866pub struct GanttTaskLabelLayout {
867    pub id: String,
868    pub text: String,
869    pub font_size: f64,
870    pub width: f64,
871    pub x: f64,
872    pub y: f64,
873    pub class: String,
874}
875
876#[derive(Debug, Clone, Serialize, Deserialize)]
877pub struct GanttTaskBarLayout {
878    pub id: String,
879    pub x: f64,
880    pub y: f64,
881    pub width: f64,
882    pub height: f64,
883    pub rx: f64,
884    pub ry: f64,
885    pub class: String,
886}
887
888#[derive(Debug, Clone, Serialize, Deserialize)]
889pub struct GanttTaskLayout {
890    pub id: String,
891    pub task: String,
892    pub section: String,
893    pub task_type: String,
894    pub order: i64,
895    pub start_ms: i64,
896    pub end_ms: i64,
897    #[serde(default)]
898    pub render_end_ms: Option<i64>,
899    pub milestone: bool,
900    pub vert: bool,
901    pub bar: GanttTaskBarLayout,
902    pub label: GanttTaskLabelLayout,
903}
904
905#[derive(Debug, Clone, Serialize, Deserialize)]
906pub struct GanttDiagramLayout {
907    pub bounds: Option<Bounds>,
908    pub width: f64,
909    pub height: f64,
910    pub left_padding: f64,
911    pub right_padding: f64,
912    pub top_padding: f64,
913    pub grid_line_start_padding: f64,
914    pub bar_height: f64,
915    pub bar_gap: f64,
916    pub title_top_margin: f64,
917    pub font_size: f64,
918    pub section_font_size: f64,
919    pub number_section_styles: i64,
920    pub display_mode: String,
921    pub date_format: String,
922    pub axis_format: String,
923    #[serde(default)]
924    pub tick_interval: Option<String>,
925    pub top_axis: bool,
926    pub today_marker: String,
927    pub categories: Vec<String>,
928    pub rows: Vec<GanttRowLayout>,
929    pub section_titles: Vec<GanttSectionTitleLayout>,
930    pub tasks: Vec<GanttTaskLayout>,
931    pub excludes: Vec<GanttExcludeRangeLayout>,
932    #[serde(default)]
933    pub has_excludes_layer: bool,
934    pub bottom_ticks: Vec<GanttAxisTickLayout>,
935    #[serde(default)]
936    pub top_ticks: Vec<GanttAxisTickLayout>,
937    pub title: Option<String>,
938    pub title_x: f64,
939    pub title_y: f64,
940}
941
942#[derive(Debug, Clone, Serialize, Deserialize)]
943pub struct C4TextBlockLayout {
944    pub text: String,
945    pub y: f64,
946    pub width: f64,
947    pub height: f64,
948    pub line_count: usize,
949}
950
951#[derive(Debug, Clone, Serialize, Deserialize)]
952pub struct C4ImageLayout {
953    pub width: f64,
954    pub height: f64,
955    pub y: f64,
956}
957
958#[derive(Debug, Clone, Serialize, Deserialize)]
959pub struct C4ShapeLayout {
960    pub alias: String,
961    pub parent_boundary: String,
962    pub type_c4_shape: String,
963    pub x: f64,
964    pub y: f64,
965    pub width: f64,
966    pub height: f64,
967    pub margin: f64,
968    pub image: C4ImageLayout,
969    pub type_block: C4TextBlockLayout,
970    pub label: C4TextBlockLayout,
971    #[serde(default)]
972    pub ty: Option<C4TextBlockLayout>,
973    #[serde(default)]
974    pub techn: Option<C4TextBlockLayout>,
975    #[serde(default)]
976    pub descr: Option<C4TextBlockLayout>,
977}
978
979#[derive(Debug, Clone, Serialize, Deserialize)]
980pub struct C4BoundaryLayout {
981    pub alias: String,
982    pub parent_boundary: String,
983    pub x: f64,
984    pub y: f64,
985    pub width: f64,
986    pub height: f64,
987    pub image: C4ImageLayout,
988    pub label: C4TextBlockLayout,
989    #[serde(default)]
990    pub ty: Option<C4TextBlockLayout>,
991    #[serde(default)]
992    pub descr: Option<C4TextBlockLayout>,
993}
994
995#[derive(Debug, Clone, Serialize, Deserialize)]
996pub struct C4RelLayout {
997    pub from: String,
998    pub to: String,
999    pub rel_type: String,
1000    pub start_point: LayoutPoint,
1001    pub end_point: LayoutPoint,
1002    #[serde(default)]
1003    pub offset_x: Option<i64>,
1004    #[serde(default)]
1005    pub offset_y: Option<i64>,
1006    pub label: C4TextBlockLayout,
1007    #[serde(default)]
1008    pub techn: Option<C4TextBlockLayout>,
1009    #[serde(default)]
1010    pub descr: Option<C4TextBlockLayout>,
1011}
1012
1013#[derive(Debug, Clone, Serialize, Deserialize)]
1014pub struct C4DiagramLayout {
1015    pub bounds: Option<Bounds>,
1016    pub width: f64,
1017    pub height: f64,
1018    pub viewport_width: f64,
1019    pub viewport_height: f64,
1020    pub c4_type: String,
1021    pub title: Option<String>,
1022    pub boundaries: Vec<C4BoundaryLayout>,
1023    pub shapes: Vec<C4ShapeLayout>,
1024    pub rels: Vec<C4RelLayout>,
1025}
1026
1027#[derive(Debug, Clone, Serialize, Deserialize)]
1028pub struct ErrorDiagramLayout {
1029    pub viewbox_width: f64,
1030    pub viewbox_height: f64,
1031    pub max_width_px: f64,
1032}
1033
1034#[derive(Debug, Clone, Serialize, Deserialize)]
1035pub enum LayoutDiagram {
1036    BlockDiagram(Box<BlockDiagramLayout>),
1037    RequirementDiagram(Box<RequirementDiagramLayout>),
1038    ArchitectureDiagram(Box<ArchitectureDiagramLayout>),
1039    MindmapDiagram(Box<MindmapDiagramLayout>),
1040    SankeyDiagram(Box<SankeyDiagramLayout>),
1041    RadarDiagram(Box<RadarDiagramLayout>),
1042    TreemapDiagram(Box<TreemapDiagramLayout>),
1043    XyChartDiagram(Box<XyChartDiagramLayout>),
1044    QuadrantChartDiagram(Box<QuadrantChartDiagramLayout>),
1045    FlowchartV2(Box<FlowchartV2Layout>),
1046    StateDiagramV2(Box<StateDiagramV2Layout>),
1047    ClassDiagramV2(Box<ClassDiagramV2Layout>),
1048    ErDiagram(Box<ErDiagramLayout>),
1049    SequenceDiagram(Box<SequenceDiagramLayout>),
1050    InfoDiagram(Box<InfoDiagramLayout>),
1051    PacketDiagram(Box<PacketDiagramLayout>),
1052    TimelineDiagram(Box<TimelineDiagramLayout>),
1053    PieDiagram(Box<PieDiagramLayout>),
1054    JourneyDiagram(Box<JourneyDiagramLayout>),
1055    KanbanDiagram(Box<KanbanDiagramLayout>),
1056    GitGraphDiagram(Box<GitGraphDiagramLayout>),
1057    GanttDiagram(Box<GanttDiagramLayout>),
1058    C4Diagram(Box<C4DiagramLayout>),
1059    ErrorDiagram(Box<ErrorDiagramLayout>),
1060}
1061
1062#[derive(Debug, Clone, Serialize, Deserialize)]
1063pub struct LayoutedDiagram {
1064    pub meta: LayoutMeta,
1065    pub semantic: Value,
1066    pub layout: LayoutDiagram,
1067}