Render one command and its subcommands as HTML.
A subcommand heading carries its full invocation path. Rendering status on its own would sit indistinguishably beside the top-level status-source, and a reader scanning headings could not tell which command a flag table belongs to.
156def render_command(command: dict, depth: int = 0, prefix: str = "") -> list:
157 """!
158 @brief Render one command and its subcommands as HTML.
159
160 @details A subcommand heading carries its full invocation path. Rendering `status`
161 on its own would sit indistinguishably beside the top-level
162 `status-source`, and a reader scanning headings could not tell which
163 command a flag table belongs to.
164 @param[in] command Command description.
165 @param[in] depth Nesting depth.
166 @param[in] prefix Invocation path of the parent command, empty at the top level.
167 @return HTML lines.
168 """
169 heading = "h3" if depth == 0 else "h4"
170 invocation = f"{prefix}{command['name']}"
171 slug = invocation.replace("-", "_").replace(" ", "_")
172 out = [f'<{heading} id="cli_{slug}"><code>picurv {escape(invocation)}</code></{heading}>']
173 if command["help"]:
174 out.append(f"<p>{escape(command['help'])}</p>")
175 for title, actions in command["groups"].items():
176 if not actions:
177 continue
178 out.append(f"<p><b>{escape(title)}</b></p>")
179 out.append('<table class="markdownTable"><tr>'
180 '<th class="markdownTableHeadNone">Flag</th>'
181 '<th class="markdownTableHeadNone">Required</th>'
182 '<th class="markdownTableHeadNone">Choices</th>'
183 '<th class="markdownTableHeadNone">Default</th>'
184 '<th class="markdownTableHeadNone">Description</th></tr>')
185 for action in actions:
186 flags = ", ".join(f"<code>{escape(flag)}</code>" for flag in action["flags"]) or \
187 f"<code>{escape(action['dest'])}</code> (positional)"
188 choices = ", ".join(f"<code>{escape(c)}</code>" for c in action["choices"]) or "—"
189 default = f"<code>{escape(action['default'])}</code>" if action["default"] else "—"
190 out.append(
191 "<tr>"
192 f'<td class="markdownTableBodyNone">{flags}</td>'
193 f'<td class="markdownTableBodyNone">{"yes" if action["required"] else "no"}</td>'
194 f'<td class="markdownTableBodyNone">{choices}</td>'
195 f'<td class="markdownTableBodyNone">{default}</td>'
196 f'<td class="markdownTableBodyNone">{escape(action["help"])}</td>'
197 "</tr>"
198 )
199 out.append("</table>")
200 for child in command["subcommands"].values():
201 out += render_command(child, depth + 1, f"{invocation} ")
202 return out
203
204