{# Single source of truth for rendering a PanelOutput dict (figure/table/ markdown/html/grid, incl. nested grid items). Shared by run.html, study.html, and kept in lockstep with analysis/report.py's _render_output and the watch JS renderPanel(). Any output type must render on all surfaces or none. #} {% macro render_output(output, grid_class='stat-grid') -%} {%- if output.type == 'figure' -%}
{%- elif output.type == 'table' -%} {# Mapping cells are references: {"text", "href"} renders a link (Studio's run-link resolution emits these); {"text"} alone renders muted text (the reference did not resolve to a link on this surface) — so the same panel output stays portable on link-less surfaces (static reports). #}
{% for column in output.columns %}{% endfor %}{% for row in output.rows %}{% for column in output.columns %}{% set cell = row[column if column is string else column.name] %}{% endfor %}{% endfor %}
{{ column if column is string else column.name }}
{% if cell is mapping %}{% if cell.href %}{{ cell.text }}{% else %}{{ cell.text }}{% endif %}{% else %}{{ cell }}{% endif %}
{%- elif output.type == 'markdown' -%}

{{ output.text }}

{%- elif output.type == 'html' -%} {{ output.html|safe }} {%- elif output.type == 'grid' -%} {% set rich = output['items']|rejectattr('type', 'equalto', 'markdown')|list %}
{% for item in output['items'] %}{{ render_grid_item(item) }}{% endfor %}
{%- endif -%} {%- endmacro %} {% macro render_grid_item(item) -%} {%- if item.type == 'markdown' -%}
{% for line in item.text.split('\n') %}{% if loop.first %}{{ line|replace('**','') }}{% else %}{{ line }}{% endif %}{% endfor %}
{%- elif item.type == 'html' -%} {{ item.html|safe }} {%- else -%} {{ render_output(item) }} {%- endif -%} {%- endmacro %}