1use maud::Markup;
4use maud::html;
5use wdl_ast::AstNode;
6use wdl_ast::AstToken;
7use wdl_ast::v1::Decl;
8use wdl_ast::v1::MetadataValue;
9
10use crate::callable::Group;
11use crate::meta::render_value;
12
13#[derive(Debug, Clone, Copy)]
15pub enum InputOutput {
16 Input,
18 Output,
20}
21
22#[derive(Debug)]
24pub struct Parameter {
25 decl: Decl,
27 meta: Option<MetadataValue>,
29 io: InputOutput,
31}
32
33impl Parameter {
34 pub fn new(decl: Decl, meta: Option<MetadataValue>, io: InputOutput) -> Self {
36 Self { decl, meta, io }
37 }
38
39 pub fn name(&self) -> String {
41 self.decl.name().text().to_owned()
42 }
43
44 pub fn ty(&self) -> String {
46 self.decl.ty().to_string()
47 }
48
49 pub fn io(&self) -> InputOutput {
51 self.io
52 }
53
54 pub fn expr(&self) -> String {
56 self.decl
57 .expr()
58 .map(|expr| expr.text().to_string())
59 .unwrap_or("None".to_string())
60 }
61
62 pub fn required(&self) -> Option<bool> {
66 match self.io {
67 InputOutput::Input => match self.decl.as_unbound_decl() {
68 Some(d) => Some(!d.ty().is_optional()),
69 _ => Some(false),
70 },
71 InputOutput::Output => None,
72 }
73 }
74
75 pub fn group(&self) -> Option<Group> {
77 if let Some(MetadataValue::Object(o)) = &self.meta {
78 for item in o.items() {
79 if item.name().text() == "group" {
80 if let MetadataValue::String(s) = item.value() {
81 return s.text().map(|t| t.text().to_string()).map(Group);
82 }
83 }
84 }
85 }
86 None
87 }
88
89 pub fn description(&self) -> Markup {
91 if let Some(meta) = &self.meta {
92 if let MetadataValue::String(_) = meta {
93 return render_value(meta);
94 } else if let MetadataValue::Object(o) = meta {
95 for item in o.items() {
96 if item.name().text() == "description" {
97 if let MetadataValue::String(_) = item.value() {
98 return render_value(&item.value());
99 }
100 }
101 }
102 }
103 }
104 html! {}
105 }
106
107 pub fn render_remaining_meta(&self) -> Markup {
111 if let Some(MetadataValue::Object(o)) = &self.meta {
112 let filtered_items = o.items().filter(|item| {
113 item.name().text() != "description" && item.name().text() != "group"
114 });
115 return html! {
116 ul {
117 @for item in filtered_items {
118 li {
119 b { (item.name().text()) ":" } " " (render_value(&item.value()))
120 }
121 }
122 }
123 };
124 }
125 html! {}
126 }
127
128 pub fn render(&self) -> Markup {
130 if self.required() == Some(true) {
131 html! {
132 tr class="border" {
133 td class="border" { (self.name()) }
134 td class="border" { code { (self.ty()) } }
135 td class="border" { (self.description()) }
136 td class="border" { (self.render_remaining_meta()) }
137 }
138 }
139 } else {
140 html! {
141 tr class="border" {
142 td class="border" { (self.name()) }
143 td class="border" { code { (self.ty()) } }
144 td class="border" { code { (self.expr()) } }
145 td class="border" { (self.description()) }
146 td class="border" { (self.render_remaining_meta()) }
147 }
148 }
149 }
150 }
151}