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