1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#![cfg_attr(coverage_nightly, coverage(off))]
//! Formatting utilities for Mermaid diagram output
use super::types::MermaidGenerator;
use crate::models::dag::{EdgeType, NodeType};
impl MermaidGenerator {
#[inline]
/// Returns the appropriate Mermaid arrow syntax for an edge type
///
/// # Examples
///
/// ```rust
/// use pmat::services::mermaid_generator::{MermaidGenerator, MermaidOptions};
/// use pmat::models::dag::EdgeType;
///
/// let generator = MermaidGenerator::new(MermaidOptions::default());
/// assert_eq!(generator.get_edge_arrow(&EdgeType::Calls), "-->");
/// assert_eq!(generator.get_edge_arrow(&EdgeType::Imports), "-.->");
/// ```
#[must_use]
pub fn get_edge_arrow(&self, edge_type: &EdgeType) -> &'static str {
match edge_type {
EdgeType::Calls => "-->",
EdgeType::Imports => "-.->",
EdgeType::Inherits => "-->|inherits|",
EdgeType::Implements => "-->|implements|",
EdgeType::Uses => "---",
}
}
#[inline]
/// Returns a color for visualizing complexity levels
///
/// # Examples
///
/// ```rust
/// use pmat::services::mermaid_generator::{MermaidGenerator, MermaidOptions};
///
/// let generator = MermaidGenerator::new(MermaidOptions::default());
/// assert_eq!(generator.get_complexity_color(2), "#90EE90"); // Light green
/// assert_eq!(generator.get_complexity_color(5), "#FFD700"); // Gold
/// assert_eq!(generator.get_complexity_color(10), "#FFA500"); // Orange
/// assert_eq!(generator.get_complexity_color(15), "#FF6347"); // Tomato
/// ```
#[must_use]
pub fn get_complexity_color(&self, complexity: u32) -> &'static str {
match complexity {
1..=3 => "#90EE90", // Light green for low complexity
4..=7 => "#FFD700", // Gold for medium complexity
8..=12 => "#FFA500", // Orange for high complexity
_ => "#FF6347", // Tomato for very high complexity
}
}
pub(super) fn get_node_stroke_style(&self, node_type: &NodeType) -> (&'static str, u32) {
match node_type {
NodeType::Function => (",stroke:#333,stroke-dasharray: 5 5", 2), // Dashed border for functions
NodeType::Trait => (",stroke:#663399", 3), // Purple border for traits
NodeType::Interface => (",stroke:#4169E1", 3), // Blue border for interfaces
_ => ("", 2), // Default for others
}
}
#[inline]
#[must_use]
pub fn sanitize_id(&self, id: &str) -> String {
// First replace common multi-character patterns
let sanitized = id.replace("::", "_").replace(['/', '.', '-', ' '], "_");
// Then replace any remaining non-alphanumeric characters with underscores
let sanitized: String = sanitized
.chars()
.map(|c| {
if c.is_ascii_alphanumeric() || c == '_' {
c
} else {
'_'
}
})
.collect();
// Ensure it starts with a letter or underscore
if sanitized.is_empty() {
"_empty".to_string()
} else if sanitized
.chars()
.next()
.expect("sanitized is non-empty (checked at line 347)")
.is_numeric()
{
format!("_{sanitized}")
} else {
sanitized
}
}
#[inline]
#[must_use]
pub fn escape_mermaid_label(&self, label: &str) -> String {
// For IntelliJ compatibility, use simple character replacements instead of HTML entities
label
.replace('&', " and ")
.replace('"', "'")
.replace('<', "(")
.replace('>', ")")
.replace('|', " - ")
.replace('[', "(")
.replace(']', ")")
.replace('{', "(")
.replace('}', ")")
.replace('\n', " ")
}
}