(intent: &IntentReport)
| 453 | } |
| 454 | |
| 455 | fn render_intent(intent: &IntentReport) -> String { |
| 456 | let conform = if intent.conforms { |
| 457 | "conforms".to_string() |
| 458 | } else { |
| 459 | format!("{} violation(s)", intent.gate_violations.len()) |
| 460 | }; |
| 461 | let conform_class = if intent.conforms { "ok" } else { "bad" }; |
| 462 | let mut d = String::new(); |
| 463 | d.push_str("<details class=\"intent\">\n"); |
| 464 | d.push_str(&format!( |
| 465 | "<summary><span class=\"intent-id\">{}</span> <span class=\"badge {conform_class}\">{}</span></summary>\n", |
| 466 | html_escape(&intent.id), |
| 467 | html_escape(&conform) |
| 468 | )); |
| 469 | if let Some(reviewer) = &intent.reviewed_by { |
| 470 | d.push_str(&format!( |
| 471 | "<div class=\"reviewed-by\">reviewed by {}</div>\n", |
| 472 | html_escape(reviewer) |
| 473 | )); |
| 474 | } |
| 475 | if let Some(why) = &intent.why { |
| 476 | d.push_str(&format!("<p class=\"why\">{}</p>\n", html_escape(why))); |
| 477 | } |
| 478 | if !intent.gate_violations.is_empty() { |
| 479 | d.push_str("<ul class=\"violations\">\n"); |
| 480 | for v in &intent.gate_violations { |
| 481 | d.push_str(&format!("<li>{}</li>\n", html_escape(v))); |
| 482 | } |
| 483 | d.push_str("</ul>\n"); |
| 484 | } |
| 485 | if !intent.criteria.is_empty() { |
| 486 | d.push_str("<ul class=\"criteria\">\n"); |
| 487 | for c in &intent.criteria { |
| 488 | d.push_str(&render_criterion(c)); |
| 489 | } |
| 490 | d.push_str("</ul>\n"); |
| 491 | } |
| 492 | d.push_str("</details>\n"); |
| 493 | d |
| 494 | } |
| 495 | |
| 496 | fn render_criterion(c: &CriterionReport) -> String { |
| 497 | let met = c.status == "met"; |
no test coverage detected