cgx_engine/docs/
wiki_link.rs1use super::WikiLinkStyle;
4
5pub fn format_link(target: &str, alias: &str, style: WikiLinkStyle) -> String {
9 match style {
10 WikiLinkStyle::Obsidian => format!("[[{}|{}]]", target, alias),
11 WikiLinkStyle::Markdown => format!("[{}]({}.md)", alias, target),
12 }
13}
14
15pub fn safe_filename(raw: &str) -> String {
19 let mut out = String::with_capacity(raw.len());
20 let mut last_dash = false;
21 for c in raw.chars() {
22 match c {
23 '/' | '\\' => {
24 out.push('/');
25 last_dash = false;
26 }
27 'a'..='z' | 'A'..='Z' | '0'..='9' | '_' | '.' => {
28 out.push(c);
29 last_dash = false;
30 }
31 '-' => {
32 if !last_dash {
33 out.push('-');
34 last_dash = true;
35 }
36 }
37 _ => {
38 if !last_dash {
39 out.push('-');
40 last_dash = true;
41 }
42 }
43 }
44 }
45 out.trim_matches('-').trim_start_matches('/').to_string()
46}
47
48pub fn module_note_target(community_slug: &str, file_path: &str) -> String {
50 format!("30-Modules/{}/{}", community_slug, safe_filename(file_path))
51}
52
53pub fn file_group(file_path: &str) -> String {
62 let parent = file_path.rsplit_once('/').map(|(p, _)| p).unwrap_or("");
63 if parent.is_empty() {
64 return "root".to_string();
65 }
66 let trimmed = parent
68 .trim_start_matches("./")
69 .trim_start_matches("crates/")
70 .trim_start_matches("packages/")
71 .trim_start_matches("apps/")
72 .trim_start_matches("services/");
73 let parts: Vec<&str> = trimmed
74 .split('/')
75 .filter(|s| !s.is_empty() && *s != "src")
76 .collect();
77 if parts.is_empty() {
78 return "root".to_string();
79 }
80 let take = parts.len().min(2);
82 let joined: String = parts[..take].join("/");
83 safe_filename(&joined)
84}
85
86pub fn file_group_slug(file_path: &str) -> String {
88 let g = file_group(file_path);
89 g.replace('/', "-")
90}
91
92pub fn public_api_target(community_slug: &str) -> String {
94 format!("10-PublicAPI/{}", community_slug)
95}
96
97pub fn community_slug(label: &str, id: i64) -> String {
100 let slug = safe_filename(label).to_lowercase().replace('/', "-");
101 let slug = slug.trim_matches('-').to_string();
102 if slug.is_empty() {
103 format!("community-{}", id)
104 } else {
105 slug
106 }
107}