{# 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 %} {% endfor %}
{{ row.label }}: {{ value(row) }}
{% 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. #}
{% for row in rows %} {% endfor %}
{{ title }}
{{ row.label }} {{ value(row) }}
{% 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 }} {% endfor %}
{{ row.count }}
{% for part in row.parts %} {% endfor %}
{% for item in legend.entries %} {{ item.label }} {% endfor %} {% if legend.caveat %}— {{ legend.caveat }}{% endif %}
{% endmacro %} {% macro grid(table) %} {% for column in table.columns %}{% endfor %} {% for row in table.rows %} {% for cell in row.cells %} {% endfor %} {% endfor %}
{{ column }}
{% if cell is mapping %}{{ value(cell) }}{% else %}{{ cell }}{% endif %}
{% endmacro %}