{#
The pieces the report templates share: `report.html.j2`, the full report, and `summary.html.j2`,
the summary set from Markdown. Kept apart so that the two documents draw a label, a value or a
table the same way, and a change to one is a change to both.
#}
{# A value is drawn by what it is, not by where it sits: an identifier, a path or a CVSS vector is
set in the monospace face wherever it appears, and a severity carries its colour. #}
{% macro value(row) %}
{% if row.token %}{{ row.token }} — {% endif %}
{% if row.kind == "severity" %}
{{ row.value }}
{% elif row.kind == "mono" %}
{{ row.value }}
{% else %}
{{ row.value }}
{% endif %}
{% endmacro %}
{% macro facts(rows, wide=false) %}
{% for row in rows %}
| {{ row.label }}: |
{{ value(row) }} |
{% endfor %}
{% endmacro %}
{% macro card(title, rows, note="") %}
{# Wrapped, because break-inside on the table does not hold its caption: the title would stay on
one page while the rows it titles moved to the next. #}
{{ title }}
{% for row in rows %}
| {{ row.label }} |
{{ value(row) }} |
{% endfor %}
{% if note %}
{{ note }}
{% endif %}
{% endmacro %}
{# Scaled against the busiest row, not against the total: what is read off a row of these is which
one is the outlier, and a scale set by the sum flattens all of them. #}
{% macro distribution(rows, legend) %}
{# The bars and the legend that decodes them are one thing; a break between them leaves a reader
with coloured segments and no key. #}
{% for row in rows %}
| {{ row.label }} |
{{ row.count }} |
{% for part in row.parts %}
{% endfor %}
|
{% endfor %}
{% for item in legend.entries %}
{{ item.label }}
{% endfor %}
{% if legend.caveat %}— {{ legend.caveat }}{% endif %}
{% endmacro %}
{% macro grid(table) %}
{% for column in table.columns %}| {{ column }} | {% endfor %}
{% for row in table.rows %}
{% for cell in row.cells %}
| {% if cell is mapping %}{{ value(cell) }}{% else %}{{ cell }}{% endif %} |
{% endfor %}
{% endfor %}
{% endmacro %}