1use crate::model::{
2 ArchitectureDiagramLayout, BlockDiagramLayout, Bounds, ClassDiagramV2Layout, ErDiagramLayout,
3 ErrorDiagramLayout, FlowchartV2Layout, InfoDiagramLayout, LayoutCluster, LayoutNode,
4 MindmapDiagramLayout, PacketDiagramLayout, PieDiagramLayout, QuadrantChartDiagramLayout,
5 RadarDiagramLayout, RequirementDiagramLayout, SankeyDiagramLayout, SequenceDiagramLayout,
6 StateDiagramV2Layout, TimelineDiagramLayout, XyChartDiagramLayout,
7};
8use crate::text::{TextMeasurer, TextStyle, WrapMode};
9use crate::{Error, Result};
10use base64::Engine as _;
11use indexmap::IndexMap;
12use std::fmt::Write as _;
13
14mod architecture;
15mod block;
16mod c4;
17mod class;
18mod css;
19mod curve;
20mod er;
21mod error;
22mod flowchart;
23mod gantt;
24mod gitgraph;
25mod info;
26mod journey;
27mod kanban;
28mod layout_debug;
29mod mindmap;
30mod packet;
31mod path_bounds;
32mod pie;
33mod quadrantchart;
34mod radar;
35mod requirement;
36mod root_svg;
37mod roughjs46;
38mod roughjs_common;
39mod sankey;
40mod sequence;
41mod state;
42mod style;
43mod timeline;
44mod timing;
45mod treemap;
46mod util;
47mod xychart;
48use crate::math::MathRenderer;
49use css::{
50 er_css, gantt_css, info_css_parts_with_config, info_css_parts_with_theme_font_size_only,
51 info_css_with_config, pie_css, push_xychart_css, requirement_css, sankey_css, treemap_css,
52};
53use path_bounds::svg_path_bounds_from_d;
54pub(crate) fn mindmap_cloud_rendered_bbox_size_px(w: f64, h: f64) -> Option<(f64, f64)> {
55 mindmap::mindmap_cloud_rendered_bbox_size_px(w, h)
56}
57pub use state::{SvgEmittedBoundsContributor, SvgEmittedBoundsDebug, debug_svg_emitted_bounds};
58use state::{
59 roughjs_ops_to_svg_path_d, roughjs_parse_hex_color_to_srgba, roughjs_paths_for_rect,
60 svg_emitted_bounds_from_svg, svg_emitted_bounds_from_svg_inner,
61};
62use style::{is_rect_style_key, is_text_style_key, parse_style_decl};
63use util::{
64 apply_root_viewport_override, config_bool, config_f64, config_f64_css_px, config_string,
65 decode_mermaid_entities_for_render_text, escape_attr, escape_attr_display, escape_xml,
66 escape_xml_display, escape_xml_into, fmt, fmt_debug_3dp, fmt_display, fmt_into,
67 fmt_max_width_px, fmt_path, fmt_path_into, fmt_points, fmt_string, json_f64,
68 json_stringify_points, json_stringify_points_into, normalize_css_font_family, push_points_attr,
69 theme_color,
70};
71
72const MERMAID_SEQUENCE_BASE_DEFS_11_12_2: &str = include_str!(concat!(
73 env!("CARGO_MANIFEST_DIR"),
74 "/assets/sequence_base_defs_11_12_2.svgfrag"
75));
76
77#[derive(Debug, Clone)]
78pub struct SvgRenderOptions {
79 pub viewbox_padding: f64,
81 pub diagram_id: Option<String>,
83 pub aria_roledescription: Option<String>,
88 pub include_edges: bool,
90 pub include_nodes: bool,
92 pub include_clusters: bool,
94 pub include_cluster_debug_markers: bool,
96 pub include_edge_id_labels: bool,
98 pub now_ms_override: Option<i64>,
101 pub math_renderer: Option<std::sync::Arc<dyn MathRenderer + Send + Sync>>,
103 pub apply_root_overrides: bool,
105}
106
107impl Default for SvgRenderOptions {
108 fn default() -> Self {
109 Self {
110 viewbox_padding: 8.0,
111 diagram_id: None,
112 aria_roledescription: None,
113 include_edges: true,
114 include_nodes: true,
115 include_clusters: true,
116 include_cluster_debug_markers: false,
117 include_edge_id_labels: false,
118 now_ms_override: None,
119 math_renderer: None,
120 apply_root_overrides: true,
121 }
122 }
123}
124
125pub fn render_layouted_svg(
126 diagram: &crate::model::LayoutedDiagram,
127 measurer: &dyn TextMeasurer,
128 options: &SvgRenderOptions,
129) -> Result<String> {
130 render_layout_svg_parts(
131 &diagram.layout,
132 &diagram.semantic,
133 &diagram.meta.effective_config,
134 diagram.meta.title.as_deref(),
135 measurer,
136 options,
137 )
138}
139
140pub fn render_layout_svg_parts(
141 layout: &crate::model::LayoutDiagram,
142 semantic: &serde_json::Value,
143 effective_config: &serde_json::Value,
144 title: Option<&str>,
145 measurer: &dyn TextMeasurer,
146 options: &SvgRenderOptions,
147) -> Result<String> {
148 use crate::model::LayoutDiagram;
149
150 match layout {
151 LayoutDiagram::ErrorDiagram(layout) => {
152 render_error_diagram_svg(layout, semantic, effective_config, options)
153 }
154 LayoutDiagram::BlockDiagram(layout) => {
155 render_block_diagram_svg(layout, semantic, effective_config, options)
156 }
157 LayoutDiagram::RequirementDiagram(layout) => {
158 render_requirement_diagram_svg(layout, semantic, effective_config, title, options)
159 }
160 LayoutDiagram::ArchitectureDiagram(layout) => {
161 render_architecture_diagram_svg(layout, semantic, effective_config, options)
162 }
163 LayoutDiagram::MindmapDiagram(layout) => {
164 render_mindmap_diagram_svg(layout, semantic, effective_config, options)
165 }
166 LayoutDiagram::SankeyDiagram(layout) => {
167 render_sankey_diagram_svg(layout, semantic, effective_config, options)
168 }
169 LayoutDiagram::RadarDiagram(layout) => {
170 render_radar_diagram_svg(layout, semantic, effective_config, options)
171 }
172 LayoutDiagram::TreemapDiagram(layout) => {
173 render_treemap_diagram_svg(layout, semantic, effective_config, options)
174 }
175 LayoutDiagram::XyChartDiagram(layout) => {
176 render_xychart_diagram_svg(layout, semantic, effective_config, options)
177 }
178 LayoutDiagram::QuadrantChartDiagram(layout) => {
179 render_quadrantchart_diagram_svg(layout, semantic, effective_config, options)
180 }
181 LayoutDiagram::FlowchartV2(layout) => {
182 render_flowchart_v2_svg(layout, semantic, effective_config, title, measurer, options)
183 }
184 LayoutDiagram::StateDiagramV2(layout) => render_state_diagram_v2_svg(
185 layout,
186 semantic,
187 effective_config,
188 title,
189 measurer,
190 options,
191 ),
192 LayoutDiagram::ClassDiagramV2(layout) => render_class_diagram_v2_svg(
193 layout,
194 semantic,
195 effective_config,
196 title,
197 measurer,
198 options,
199 ),
200 LayoutDiagram::ErDiagram(layout) => {
201 render_er_diagram_svg(layout, semantic, effective_config, title, measurer, options)
202 }
203 LayoutDiagram::SequenceDiagram(layout) => render_sequence_diagram_svg(
204 layout,
205 semantic,
206 effective_config,
207 title,
208 measurer,
209 options,
210 ),
211 LayoutDiagram::InfoDiagram(layout) => {
212 render_info_diagram_svg(layout, semantic, effective_config, options)
213 }
214 LayoutDiagram::PacketDiagram(layout) => {
215 render_packet_diagram_svg(layout, semantic, effective_config, title, options)
216 }
217 LayoutDiagram::TimelineDiagram(layout) => render_timeline_diagram_svg(
218 layout,
219 semantic,
220 effective_config,
221 title,
222 measurer,
223 options,
224 ),
225 LayoutDiagram::PieDiagram(layout) => {
226 render_pie_diagram_svg(layout, semantic, effective_config, options)
227 }
228 LayoutDiagram::JourneyDiagram(layout) => {
229 render_journey_diagram_svg(layout, semantic, effective_config, title, measurer, options)
230 }
231 LayoutDiagram::KanbanDiagram(layout) => {
232 render_kanban_diagram_svg(layout, semantic, effective_config, options)
233 }
234 LayoutDiagram::GitGraphDiagram(layout) => render_gitgraph_diagram_svg(
235 layout,
236 semantic,
237 effective_config,
238 title,
239 measurer,
240 options,
241 ),
242 LayoutDiagram::GanttDiagram(layout) => {
243 render_gantt_diagram_svg(layout, semantic, effective_config, options)
244 }
245 LayoutDiagram::C4Diagram(layout) => {
246 render_c4_diagram_svg(layout, semantic, effective_config, title, measurer, options)
247 }
248 }
249}
250
251pub fn render_layout_svg_parts_with_config(
252 layout: &crate::model::LayoutDiagram,
253 semantic: &serde_json::Value,
254 effective_config: &merman_core::MermaidConfig,
255 title: Option<&str>,
256 measurer: &dyn TextMeasurer,
257 options: &SvgRenderOptions,
258) -> Result<String> {
259 use crate::model::LayoutDiagram;
260
261 let effective_config_value = effective_config.as_value();
262
263 match layout {
264 LayoutDiagram::ErrorDiagram(layout) => {
265 render_error_diagram_svg(layout, semantic, effective_config_value, options)
266 }
267 LayoutDiagram::BlockDiagram(layout) => {
268 render_block_diagram_svg(layout, semantic, effective_config_value, options)
269 }
270 LayoutDiagram::RequirementDiagram(layout) => {
271 render_requirement_diagram_svg(layout, semantic, effective_config_value, title, options)
272 }
273 LayoutDiagram::ArchitectureDiagram(layout) => {
274 architecture::render_architecture_diagram_svg_with_config(
275 layout,
276 semantic,
277 effective_config,
278 options,
279 )
280 }
281 LayoutDiagram::MindmapDiagram(layout) => {
282 render_mindmap_diagram_svg_with_config(layout, semantic, effective_config, options)
283 }
284 LayoutDiagram::SankeyDiagram(layout) => {
285 render_sankey_diagram_svg(layout, semantic, effective_config_value, options)
286 }
287 LayoutDiagram::RadarDiagram(layout) => {
288 render_radar_diagram_svg(layout, semantic, effective_config_value, options)
289 }
290 LayoutDiagram::TreemapDiagram(layout) => {
291 render_treemap_diagram_svg(layout, semantic, effective_config_value, options)
292 }
293 LayoutDiagram::XyChartDiagram(layout) => {
294 render_xychart_diagram_svg(layout, semantic, effective_config_value, options)
295 }
296 LayoutDiagram::QuadrantChartDiagram(layout) => {
297 render_quadrantchart_diagram_svg(layout, semantic, effective_config_value, options)
298 }
299 LayoutDiagram::FlowchartV2(layout) => render_flowchart_v2_svg_with_config(
300 layout,
301 semantic,
302 effective_config,
303 title,
304 measurer,
305 options,
306 ),
307 LayoutDiagram::StateDiagramV2(layout) => render_state_diagram_v2_svg(
308 layout,
309 semantic,
310 effective_config_value,
311 title,
312 measurer,
313 options,
314 ),
315 LayoutDiagram::ClassDiagramV2(layout) => {
316 let model = crate::json::from_value_ref(semantic)?;
317 class::render_class_diagram_v2_svg_model_with_config(
318 layout,
319 &model,
320 effective_config,
321 title,
322 measurer,
323 options,
324 )
325 }
326 LayoutDiagram::ErDiagram(layout) => render_er_diagram_svg(
327 layout,
328 semantic,
329 effective_config_value,
330 title,
331 measurer,
332 options,
333 ),
334 LayoutDiagram::SequenceDiagram(layout) => {
335 sequence::render_sequence_diagram_svg_with_config(
336 layout,
337 semantic,
338 effective_config,
339 title,
340 measurer,
341 options,
342 )
343 }
344 LayoutDiagram::InfoDiagram(layout) => {
345 render_info_diagram_svg(layout, semantic, effective_config_value, options)
346 }
347 LayoutDiagram::PacketDiagram(layout) => {
348 render_packet_diagram_svg(layout, semantic, effective_config_value, title, options)
349 }
350 LayoutDiagram::TimelineDiagram(layout) => render_timeline_diagram_svg(
351 layout,
352 semantic,
353 effective_config_value,
354 title,
355 measurer,
356 options,
357 ),
358 LayoutDiagram::PieDiagram(layout) => {
359 render_pie_diagram_svg(layout, semantic, effective_config_value, options)
360 }
361 LayoutDiagram::JourneyDiagram(layout) => render_journey_diagram_svg(
362 layout,
363 semantic,
364 effective_config_value,
365 title,
366 measurer,
367 options,
368 ),
369 LayoutDiagram::KanbanDiagram(layout) => {
370 render_kanban_diagram_svg(layout, semantic, effective_config_value, options)
371 }
372 LayoutDiagram::GitGraphDiagram(layout) => render_gitgraph_diagram_svg(
373 layout,
374 semantic,
375 effective_config_value,
376 title,
377 measurer,
378 options,
379 ),
380 LayoutDiagram::GanttDiagram(layout) => {
381 render_gantt_diagram_svg(layout, semantic, effective_config_value, options)
382 }
383 LayoutDiagram::C4Diagram(layout) => render_c4_diagram_svg(
384 layout,
385 semantic,
386 effective_config_value,
387 title,
388 measurer,
389 options,
390 ),
391 }
392}
393
394pub fn render_layout_svg_parts_for_render_model_with_config(
395 layout: &crate::model::LayoutDiagram,
396 semantic: &merman_core::RenderSemanticModel,
397 effective_config: &merman_core::MermaidConfig,
398 title: Option<&str>,
399 measurer: &dyn TextMeasurer,
400 options: &SvgRenderOptions,
401) -> Result<String> {
402 use crate::model::LayoutDiagram;
403 use merman_core::RenderSemanticModel;
404
405 match (layout, semantic) {
406 (LayoutDiagram::ArchitectureDiagram(layout), RenderSemanticModel::Architecture(model)) => {
407 architecture::render_architecture_diagram_svg_typed_with_config(
408 layout,
409 model,
410 effective_config,
411 options,
412 )
413 }
414 (LayoutDiagram::FlowchartV2(layout), RenderSemanticModel::Flowchart(model)) => {
415 render_flowchart_v2_svg_model_with_config(
416 layout,
417 model,
418 effective_config,
419 title,
420 measurer,
421 options,
422 )
423 }
424 (LayoutDiagram::MindmapDiagram(layout), RenderSemanticModel::Mindmap(model)) => {
425 mindmap::render_mindmap_diagram_svg_model_with_config(
426 layout,
427 model,
428 effective_config,
429 options,
430 )
431 }
432 (LayoutDiagram::StateDiagramV2(layout), RenderSemanticModel::State(model)) => {
433 state::render_state_diagram_v2_svg_model(
434 layout,
435 model,
436 effective_config.as_value(),
437 title,
438 measurer,
439 options,
440 )
441 }
442 (LayoutDiagram::ClassDiagramV2(layout), RenderSemanticModel::Class(model)) => {
443 class::render_class_diagram_v2_svg_model_with_config(
444 layout,
445 model,
446 effective_config,
447 title,
448 measurer,
449 options,
450 )
451 }
452 (LayoutDiagram::SequenceDiagram(layout), RenderSemanticModel::Sequence(model)) => {
453 sequence::render_sequence_diagram_svg_model_with_config(
454 layout,
455 model,
456 effective_config,
457 title,
458 measurer,
459 options,
460 )
461 }
462 (LayoutDiagram::KanbanDiagram(layout), RenderSemanticModel::Kanban(_)) => {
463 render_kanban_diagram_svg(
464 layout,
465 &serde_json::Value::Null,
466 effective_config.as_value(),
467 options,
468 )
469 }
470 (LayoutDiagram::GanttDiagram(layout), RenderSemanticModel::Gantt(model)) => {
471 gantt::render_gantt_diagram_svg_model(
472 layout,
473 model,
474 effective_config.as_value(),
475 options,
476 )
477 }
478 (LayoutDiagram::PieDiagram(layout), RenderSemanticModel::Pie(model)) => {
479 pie::render_pie_diagram_svg_model(layout, model, effective_config.as_value(), options)
480 }
481 (LayoutDiagram::PacketDiagram(layout), RenderSemanticModel::Packet(model)) => {
482 packet::render_packet_diagram_svg_model(
483 layout,
484 model,
485 effective_config.as_value(),
486 title,
487 options,
488 )
489 }
490 (LayoutDiagram::TimelineDiagram(layout), RenderSemanticModel::Timeline(model)) => {
491 timeline::render_timeline_diagram_svg_model(
492 layout,
493 model,
494 effective_config.as_value(),
495 title,
496 measurer,
497 options,
498 )
499 }
500 (LayoutDiagram::JourneyDiagram(layout), RenderSemanticModel::Journey(model)) => {
501 journey::render_journey_diagram_svg_model(
502 layout,
503 model,
504 effective_config.as_value(),
505 title,
506 measurer,
507 options,
508 )
509 }
510 (LayoutDiagram::RequirementDiagram(layout), RenderSemanticModel::Requirement(model)) => {
511 requirement::render_requirement_diagram_svg_model(
512 layout,
513 model,
514 effective_config.as_value(),
515 title,
516 options,
517 )
518 }
519 (LayoutDiagram::SankeyDiagram(layout), RenderSemanticModel::Sankey(_)) => {
520 render_sankey_diagram_svg(
521 layout,
522 &serde_json::Value::Null,
523 effective_config.as_value(),
524 options,
525 )
526 }
527 (LayoutDiagram::RadarDiagram(layout), RenderSemanticModel::Radar(model)) => {
528 radar::render_radar_diagram_svg_model(
529 layout,
530 model,
531 effective_config.as_value(),
532 options,
533 )
534 }
535 (LayoutDiagram::InfoDiagram(layout), RenderSemanticModel::Info(_)) => {
536 render_info_diagram_svg(
537 layout,
538 &serde_json::Value::Null,
539 effective_config.as_value(),
540 options,
541 )
542 }
543 (LayoutDiagram::TreemapDiagram(layout), RenderSemanticModel::Treemap(_)) => {
544 render_treemap_diagram_svg(
545 layout,
546 &serde_json::Value::Null,
547 effective_config.as_value(),
548 options,
549 )
550 }
551 (LayoutDiagram::BlockDiagram(layout), RenderSemanticModel::Block(model)) => {
552 render_block_diagram_svg_model(layout, model, effective_config.as_value(), options)
553 }
554 (LayoutDiagram::ErDiagram(layout), RenderSemanticModel::Er(model)) => {
555 render_er_diagram_svg_model(
556 layout,
557 model,
558 effective_config.as_value(),
559 title,
560 measurer,
561 options,
562 )
563 }
564 (LayoutDiagram::QuadrantChartDiagram(layout), RenderSemanticModel::QuadrantChart(_)) => {
565 render_quadrantchart_diagram_svg(
566 layout,
567 &serde_json::Value::Null,
568 effective_config.as_value(),
569 options,
570 )
571 }
572 (LayoutDiagram::XyChartDiagram(layout), RenderSemanticModel::XyChart(_)) => {
573 render_xychart_diagram_svg(
574 layout,
575 &serde_json::Value::Null,
576 effective_config.as_value(),
577 options,
578 )
579 }
580 (LayoutDiagram::GitGraphDiagram(layout), RenderSemanticModel::GitGraph(model)) => {
581 gitgraph::render_gitgraph_diagram_svg_model(
582 layout,
583 model,
584 effective_config.as_value(),
585 title,
586 measurer,
587 options,
588 )
589 }
590 (LayoutDiagram::C4Diagram(layout), RenderSemanticModel::C4(model)) => {
591 c4::render_c4_diagram_svg_typed(
592 layout,
593 model,
594 effective_config.as_value(),
595 title,
596 measurer,
597 options,
598 )
599 }
600 (_, RenderSemanticModel::Json(semantic)) => render_layout_svg_parts_with_config(
601 layout,
602 semantic,
603 effective_config,
604 title,
605 measurer,
606 options,
607 ),
608 _ => Err(Error::InvalidModel {
609 message: "semantic model does not match layout diagram type".to_string(),
610 }),
611 }
612}
613
614pub fn render_flowchart_v2_debug_svg(
615 layout: &FlowchartV2Layout,
616 options: &SvgRenderOptions,
617) -> String {
618 flowchart::render_flowchart_v2_debug_svg(layout, options)
619}
620
621pub fn render_sequence_diagram_debug_svg(
622 layout: &SequenceDiagramLayout,
623 options: &SvgRenderOptions,
624) -> String {
625 sequence::render_sequence_diagram_debug_svg(layout, options)
626}
627
628pub fn render_sequence_diagram_svg(
629 layout: &SequenceDiagramLayout,
630 semantic: &serde_json::Value,
631 effective_config: &serde_json::Value,
632 diagram_title: Option<&str>,
633 measurer: &dyn TextMeasurer,
634 options: &SvgRenderOptions,
635) -> Result<String> {
636 sequence::render_sequence_diagram_svg(
637 layout,
638 semantic,
639 effective_config,
640 diagram_title,
641 measurer,
642 options,
643 )
644}
645
646pub fn render_error_diagram_svg(
647 layout: &ErrorDiagramLayout,
648 _semantic: &serde_json::Value,
649 _effective_config: &serde_json::Value,
650 options: &SvgRenderOptions,
651) -> Result<String> {
652 error::render_error_diagram_svg(layout, _semantic, _effective_config, options)
653}
654
655pub fn render_info_diagram_svg(
656 layout: &InfoDiagramLayout,
657 _semantic: &serde_json::Value,
658 _effective_config: &serde_json::Value,
659 options: &SvgRenderOptions,
660) -> Result<String> {
661 info::render_info_diagram_svg(layout, _semantic, _effective_config, options)
662}
663
664pub fn render_pie_diagram_svg(
665 layout: &PieDiagramLayout,
666 semantic: &serde_json::Value,
667 _effective_config: &serde_json::Value,
668 options: &SvgRenderOptions,
669) -> Result<String> {
670 pie::render_pie_diagram_svg(layout, semantic, _effective_config, options)
671}
672
673pub fn render_requirement_diagram_svg(
674 layout: &RequirementDiagramLayout,
675 semantic: &serde_json::Value,
676 effective_config: &serde_json::Value,
677 diagram_title: Option<&str>,
678 options: &SvgRenderOptions,
679) -> Result<String> {
680 requirement::render_requirement_diagram_svg(
681 layout,
682 semantic,
683 effective_config,
684 diagram_title,
685 options,
686 )
687}
688
689pub fn render_block_diagram_svg(
690 layout: &BlockDiagramLayout,
691 semantic: &serde_json::Value,
692 effective_config: &serde_json::Value,
693 options: &SvgRenderOptions,
694) -> Result<String> {
695 block::render_block_diagram_svg(layout, semantic, effective_config, options)
696}
697
698pub fn render_block_diagram_svg_model(
699 layout: &BlockDiagramLayout,
700 model: &merman_core::diagrams::block::BlockDiagramRenderModel,
701 effective_config: &serde_json::Value,
702 options: &SvgRenderOptions,
703) -> Result<String> {
704 block::render_block_diagram_svg_model(layout, model, effective_config, options)
705}
706
707pub fn render_er_diagram_svg_model(
708 layout: &ErDiagramLayout,
709 model: &merman_core::diagrams::er::ErDiagramRenderModel,
710 effective_config: &serde_json::Value,
711 diagram_title: Option<&str>,
712 measurer: &dyn TextMeasurer,
713 options: &SvgRenderOptions,
714) -> Result<String> {
715 er::render_er_diagram_svg_model(
716 layout,
717 model,
718 effective_config,
719 diagram_title,
720 measurer,
721 options,
722 )
723}
724
725pub fn render_radar_diagram_svg(
726 layout: &RadarDiagramLayout,
727 semantic: &serde_json::Value,
728 effective_config: &serde_json::Value,
729 options: &SvgRenderOptions,
730) -> Result<String> {
731 radar::render_radar_diagram_svg(layout, semantic, effective_config, options)
732}
733
734pub fn render_quadrantchart_diagram_svg(
735 layout: &QuadrantChartDiagramLayout,
736 _semantic: &serde_json::Value,
737 _effective_config: &serde_json::Value,
738 options: &SvgRenderOptions,
739) -> Result<String> {
740 quadrantchart::render_quadrantchart_diagram_svg(layout, _semantic, _effective_config, options)
741}
742
743pub fn render_xychart_diagram_svg(
744 layout: &XyChartDiagramLayout,
745 _semantic: &serde_json::Value,
746 _effective_config: &serde_json::Value,
747 options: &SvgRenderOptions,
748) -> Result<String> {
749 xychart::render_xychart_diagram_svg(layout, _semantic, _effective_config, options)
750}
751
752pub fn render_treemap_diagram_svg(
753 layout: &crate::model::TreemapDiagramLayout,
754 _semantic: &serde_json::Value,
755 effective_config: &serde_json::Value,
756 options: &SvgRenderOptions,
757) -> Result<String> {
758 treemap::render_treemap_diagram_svg(layout, _semantic, effective_config, options)
759}
760
761pub fn render_packet_diagram_svg(
762 layout: &PacketDiagramLayout,
763 semantic: &serde_json::Value,
764 _effective_config: &serde_json::Value,
765 diagram_title: Option<&str>,
766 options: &SvgRenderOptions,
767) -> Result<String> {
768 packet::render_packet_diagram_svg(layout, semantic, _effective_config, diagram_title, options)
769}
770
771pub fn render_timeline_diagram_svg(
772 layout: &TimelineDiagramLayout,
773 semantic: &serde_json::Value,
774 effective_config: &serde_json::Value,
775 _diagram_title: Option<&str>,
776 _measurer: &dyn TextMeasurer,
777 options: &SvgRenderOptions,
778) -> Result<String> {
779 timeline::render_timeline_diagram_svg(
780 layout,
781 semantic,
782 effective_config,
783 _diagram_title,
784 _measurer,
785 options,
786 )
787}
788
789pub fn render_journey_diagram_svg(
790 layout: &crate::model::JourneyDiagramLayout,
791 semantic: &serde_json::Value,
792 effective_config: &serde_json::Value,
793 _diagram_title: Option<&str>,
794 _measurer: &dyn TextMeasurer,
795 options: &SvgRenderOptions,
796) -> Result<String> {
797 journey::render_journey_diagram_svg(
798 layout,
799 semantic,
800 effective_config,
801 _diagram_title,
802 _measurer,
803 options,
804 )
805}
806
807pub fn render_kanban_diagram_svg(
808 layout: &crate::model::KanbanDiagramLayout,
809 _semantic: &serde_json::Value,
810 _effective_config: &serde_json::Value,
811 options: &SvgRenderOptions,
812) -> Result<String> {
813 kanban::render_kanban_diagram_svg(layout, _semantic, _effective_config, options)
814}
815
816pub fn render_gitgraph_diagram_svg(
817 layout: &crate::model::GitGraphDiagramLayout,
818 semantic: &serde_json::Value,
819 _effective_config: &serde_json::Value,
820 diagram_title: Option<&str>,
821 measurer: &dyn TextMeasurer,
822 options: &SvgRenderOptions,
823) -> Result<String> {
824 gitgraph::render_gitgraph_diagram_svg(
825 layout,
826 semantic,
827 _effective_config,
828 diagram_title,
829 measurer,
830 options,
831 )
832}
833
834pub fn render_gantt_diagram_svg(
835 layout: &crate::model::GanttDiagramLayout,
836 semantic: &serde_json::Value,
837 _effective_config: &serde_json::Value,
838 options: &SvgRenderOptions,
839) -> Result<String> {
840 gantt::render_gantt_diagram_svg(layout, semantic, _effective_config, options)
841}
842
843pub fn render_mindmap_diagram_svg(
844 layout: &MindmapDiagramLayout,
845 semantic: &serde_json::Value,
846 _effective_config: &serde_json::Value,
847 options: &SvgRenderOptions,
848) -> Result<String> {
849 mindmap::render_mindmap_diagram_svg(layout, semantic, _effective_config, options)
850}
851
852pub fn render_mindmap_diagram_svg_with_config(
853 layout: &MindmapDiagramLayout,
854 semantic: &serde_json::Value,
855 effective_config: &merman_core::MermaidConfig,
856 options: &SvgRenderOptions,
857) -> Result<String> {
858 mindmap::render_mindmap_diagram_svg_with_config(layout, semantic, effective_config, options)
859}
860
861pub fn render_architecture_diagram_svg(
862 layout: &ArchitectureDiagramLayout,
863 semantic: &serde_json::Value,
864 effective_config: &serde_json::Value,
865 options: &SvgRenderOptions,
866) -> Result<String> {
867 architecture::render_architecture_diagram_svg(layout, semantic, effective_config, options)
868}
869
870pub fn render_c4_diagram_svg(
871 layout: &crate::model::C4DiagramLayout,
872 semantic: &serde_json::Value,
873 effective_config: &serde_json::Value,
874 diagram_title: Option<&str>,
875 _measurer: &dyn TextMeasurer,
876 options: &SvgRenderOptions,
877) -> Result<String> {
878 c4::render_c4_diagram_svg(
879 layout,
880 semantic,
881 effective_config,
882 diagram_title,
883 _measurer,
884 options,
885 )
886}
887
888pub fn render_flowchart_v2_svg(
889 layout: &FlowchartV2Layout,
890 semantic: &serde_json::Value,
891 effective_config: &serde_json::Value,
892 diagram_title: Option<&str>,
893 measurer: &dyn TextMeasurer,
894 options: &SvgRenderOptions,
895) -> Result<String> {
896 flowchart::render_flowchart_v2_svg(
897 layout,
898 semantic,
899 effective_config,
900 diagram_title,
901 measurer,
902 options,
903 )
904}
905
906pub fn render_flowchart_v2_svg_with_config(
907 layout: &FlowchartV2Layout,
908 semantic: &serde_json::Value,
909 effective_config: &merman_core::MermaidConfig,
910 diagram_title: Option<&str>,
911 measurer: &dyn TextMeasurer,
912 options: &SvgRenderOptions,
913) -> Result<String> {
914 flowchart::render_flowchart_v2_svg_with_config(
915 layout,
916 semantic,
917 effective_config,
918 diagram_title,
919 measurer,
920 options,
921 )
922}
923
924pub fn render_flowchart_v2_svg_model_with_config(
925 layout: &FlowchartV2Layout,
926 model: &merman_core::diagrams::flowchart::FlowchartV2Model,
927 effective_config: &merman_core::MermaidConfig,
928 diagram_title: Option<&str>,
929 measurer: &dyn TextMeasurer,
930 options: &SvgRenderOptions,
931) -> Result<String> {
932 flowchart::render_flowchart_v2_svg_model_with_config(
933 layout,
934 model,
935 effective_config,
936 diagram_title,
937 measurer,
938 options,
939 )
940}
941
942pub fn render_state_diagram_v2_svg(
943 layout: &StateDiagramV2Layout,
944 semantic: &serde_json::Value,
945 effective_config: &serde_json::Value,
946 diagram_title: Option<&str>,
947 measurer: &dyn TextMeasurer,
948 options: &SvgRenderOptions,
949) -> Result<String> {
950 state::render_state_diagram_v2_svg(
951 layout,
952 semantic,
953 effective_config,
954 diagram_title,
955 measurer,
956 options,
957 )
958}
959
960pub fn render_state_diagram_v2_debug_svg(
961 layout: &StateDiagramV2Layout,
962 options: &SvgRenderOptions,
963) -> String {
964 state::render_state_diagram_v2_debug_svg(layout, options)
965}
966
967pub fn render_class_diagram_v2_debug_svg(
968 layout: &ClassDiagramV2Layout,
969 options: &SvgRenderOptions,
970) -> String {
971 class::render_class_diagram_v2_debug_svg(layout, options)
972}
973
974pub fn render_class_diagram_v2_svg(
975 layout: &ClassDiagramV2Layout,
976 semantic: &serde_json::Value,
977 effective_config: &serde_json::Value,
978 diagram_title: Option<&str>,
979 measurer: &dyn TextMeasurer,
980 options: &SvgRenderOptions,
981) -> Result<String> {
982 class::render_class_diagram_v2_svg(
983 layout,
984 semantic,
985 effective_config,
986 diagram_title,
987 measurer,
988 options,
989 )
990}
991
992pub fn render_er_diagram_debug_svg(layout: &ErDiagramLayout, options: &SvgRenderOptions) -> String {
993 er::render_er_diagram_debug_svg(layout, options)
994}
995
996pub fn render_er_diagram_svg(
997 layout: &ErDiagramLayout,
998 semantic: &serde_json::Value,
999 effective_config: &serde_json::Value,
1000 diagram_title: Option<&str>,
1001 measurer: &dyn TextMeasurer,
1002 options: &SvgRenderOptions,
1003) -> Result<String> {
1004 er::render_er_diagram_svg(
1005 layout,
1006 semantic,
1007 effective_config,
1008 diagram_title,
1009 measurer,
1010 options,
1011 )
1012}
1013
1014pub fn render_sankey_diagram_svg(
1015 layout: &SankeyDiagramLayout,
1016 _semantic: &serde_json::Value,
1017 effective_config: &serde_json::Value,
1018 options: &SvgRenderOptions,
1019) -> Result<String> {
1020 sankey::render_sankey_diagram_svg(layout, _semantic, effective_config, options)
1021}
1022
1023fn curve_basis_path_d(points: &[crate::model::LayoutPoint]) -> String {
1025 curve::curve_basis_path_d(points)
1026}
1027fn render_node(out: &mut String, n: &LayoutNode) {
1028 layout_debug::render_node(out, n)
1029}
1030
1031fn render_state_node(out: &mut String, n: &LayoutNode) {
1032 layout_debug::render_state_node(out, n)
1033}
1034
1035fn render_cluster(out: &mut String, c: &LayoutCluster, include_markers: bool) {
1036 layout_debug::render_cluster(out, c, include_markers)
1037}
1038
1039fn compute_layout_bounds(
1040 clusters: &[LayoutCluster],
1041 nodes: &[LayoutNode],
1042 edges: &[crate::model::LayoutEdge],
1043) -> Option<Bounds> {
1044 layout_debug::compute_layout_bounds(clusters, nodes, edges)
1045}