intent_render/
markdown.rs1use intent_parser::ast;
7
8use crate::format_type;
9
10pub fn render(file: &ast::File) -> String {
12 let mut out = String::new();
13 out.push_str(&format!("# {}\n\n", file.module.name));
14
15 if let Some(doc) = &file.doc {
16 for line in &doc.lines {
17 out.push_str(line);
18 out.push('\n');
19 }
20 out.push('\n');
21 }
22
23 for item in &file.items {
24 match item {
25 ast::TopLevelItem::Entity(e) => render_entity(&mut out, e),
26 ast::TopLevelItem::Action(a) => render_action(&mut out, a),
27 ast::TopLevelItem::Invariant(i) => render_invariant(&mut out, i),
28 ast::TopLevelItem::EdgeCases(ec) => render_edge_cases(&mut out, ec),
29 }
30 }
31
32 out
33}
34
35fn render_entity(out: &mut String, entity: &ast::EntityDecl) {
36 out.push_str(&format!("## Entity: {}\n\n", entity.name));
37 if let Some(doc) = &entity.doc {
38 for line in &doc.lines {
39 out.push_str(line);
40 out.push('\n');
41 }
42 out.push('\n');
43 }
44 out.push_str("| Field | Type |\n|-------|------|\n");
45 for field in &entity.fields {
46 out.push_str(&format!(
47 "| `{}` | `{}` |\n",
48 field.name,
49 format_type(&field.ty)
50 ));
51 }
52 out.push('\n');
53}
54
55fn render_action(out: &mut String, action: &ast::ActionDecl) {
56 out.push_str(&format!("## Action: {}\n\n", action.name));
57 if let Some(doc) = &action.doc {
58 for line in &doc.lines {
59 out.push_str(line);
60 out.push('\n');
61 }
62 out.push('\n');
63 }
64 if !action.params.is_empty() {
65 out.push_str("**Parameters:**\n\n");
66 for p in &action.params {
67 out.push_str(&format!("- `{}`: `{}`\n", p.name, format_type(&p.ty)));
68 }
69 out.push('\n');
70 }
71}
72
73fn render_invariant(out: &mut String, inv: &ast::InvariantDecl) {
74 out.push_str(&format!("## Invariant: {}\n\n", inv.name));
75 if let Some(doc) = &inv.doc {
76 for line in &doc.lines {
77 out.push_str(line);
78 out.push('\n');
79 }
80 out.push('\n');
81 }
82}
83
84fn render_edge_cases(out: &mut String, _ec: &ast::EdgeCasesDecl) {
85 out.push_str("## Edge Cases\n\n");
86}