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)]
1035#[allow(clippy::large_enum_variant)]
1036pub enum LayoutDiagram {
1037    BlockDiagram(BlockDiagramLayout),
1038    RequirementDiagram(RequirementDiagramLayout),
1039    ArchitectureDiagram(ArchitectureDiagramLayout),
1040    MindmapDiagram(MindmapDiagramLayout),
1041    SankeyDiagram(SankeyDiagramLayout),
1042    RadarDiagram(RadarDiagramLayout),
1043    TreemapDiagram(TreemapDiagramLayout),
1044    XyChartDiagram(XyChartDiagramLayout),
1045    QuadrantChartDiagram(QuadrantChartDiagramLayout),
1046    FlowchartV2(FlowchartV2Layout),
1047    StateDiagramV2(StateDiagramV2Layout),
1048    ClassDiagramV2(ClassDiagramV2Layout),
1049    ErDiagram(ErDiagramLayout),
1050    SequenceDiagram(SequenceDiagramLayout),
1051    InfoDiagram(InfoDiagramLayout),
1052    PacketDiagram(PacketDiagramLayout),
1053    TimelineDiagram(TimelineDiagramLayout),
1054    PieDiagram(PieDiagramLayout),
1055    JourneyDiagram(JourneyDiagramLayout),
1056    KanbanDiagram(KanbanDiagramLayout),
1057    GitGraphDiagram(GitGraphDiagramLayout),
1058    GanttDiagram(GanttDiagramLayout),
1059    C4Diagram(C4DiagramLayout),
1060    ErrorDiagram(ErrorDiagramLayout),
1061}
1062
1063#[derive(Debug, Clone, Serialize, Deserialize)]
1064pub struct LayoutedDiagram {
1065    pub meta: LayoutMeta,
1066    pub semantic: Value,
1067    pub layout: LayoutDiagram,
1068}