251def generate_block_markdown(block_info: Dict[str, Any]) -> str:
252 """
253 Generate Markdown documentation for a single block.
254
255 Args:
256 block_info: Dictionary containing block information with keys:
257 - class: Block class name
258 - module: Module containing the block
259 - options: List of option dictionaries
260 - output_variables: List of output variable dictionaries
261
262 Returns:
263 Markdown string for this block
264 """
265 markdown = ""
266
267
268 if block_info.get("options"):
269 for opt in block_info["options"]:
270 name = opt["label"]
271
272
273 if name in ["skipOnData", "skipOnMC"]:
274 if not opt["default"] is True:
275 continue
276
277 if name in ["onlyForDSIDs"]:
278 if not opt["default"] is []:
279 continue
280
281
282 label = f"`{opt['label']}` ({opt['type']})"
283 if opt["expertMode"] is not None:
284 expertOptions = list(opt["expertMode"])
285 label += f" **[expert-only options: {','.join(['`' + str(x) + '`' for x in expertOptions])}]**"
286 if opt["required"] is True or opt["noneAction"] != "ignore":
287 label += " **[REQUIRED]**"
288
289 markdown += f"{label}\n"
290 info_string = opt["info"]
291 info_string = process_info_links(info_string)
292 info_string = link_jira_tickets(info_string)
293 markdown += f": {info_string}"
294
295 if opt.get("default") != "":
296 default_val = opt["default"]
297 default_str = repr(default_val)
298
299
300 unit = opt.get("physicalUnit")
301 if unit is None or default_val is None:
302 default_display = f"`{default_str}`"
303 elif unit == "GeV":
304 default_display = f"`{default_str}` GeV"
305 elif unit == "MeV":
306
307 try:
308 if isinstance(default_val, (list, tuple)):
309 converted = [float(x) / 1000 for x in default_val]
310 converted_str = (
311 "[" + ", ".join(f"{x}" for x in converted) + "]"
312 )
313 else:
314 converted = float(default_val) / 1000
315 converted_str = f"{converted}"
316 except (TypeError, ValueError):
317 converted_str = "?"
318 default_display = f"`{default_str}` MeV (`{converted_str}` GeV)"
319 else:
320 default_display = f"`{default_str}` {unit}"
321
322 markdown += f" Default: {default_display}."
323
324 markdown += "\n\n"
325
326
327 if block_info.get("output_variables"):
328
329 always_saved = []
330 toggled_vars = {}
331
332 for var in block_info["output_variables"]:
333 if var.get("toggled_by"):
334 condition = var["toggled_by"]
335 if condition not in toggled_vars:
336 toggled_vars[condition] = []
337 toggled_vars[condition].append(var)
338 else:
339 always_saved.append(var)
340
341
342 if always_saved:
343 markdown += '!!! success "Registers the following variables:"\n'
344 for var in always_saved:
345 var_name = var.get("name", "N/A")
346 var_desc = var.get("description", "")
347 markdown += f" - `{var_name}`: {var_desc}\n"
348 markdown += "\n"
349
350
351 for condition, vars_list in toggled_vars.items():
352 markdown += (
353 f'!!! success "Additional variables toggled by `{condition}`:"\n'
354 )
355 for var in vars_list:
356 var_name = var.get("name", "N/A")
357 var_desc = var.get("description", "")
358 markdown += f" - `{var_name}`: {var_desc}\n"
359 markdown += "\n"
360 else:
362 f" Block {block_info.get('class')} didn't register any output variables."
363 )
364
365 return markdown
366
367