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