Initial commit. monorepo deps are copied in a dirty way to the vendor folder
This commit is contained in:
commit
06593ac488
53 files changed
+7692
No files matched your search
@@ -0,0 +1,422 @@
|
||||
/* The print stylesheet of the SAST/SCA report.
|
||||
*
|
||||
* Follows the design sample in `sample_report_template/`. Everything is expressed here rather than
|
||||
* in the template: the template places content, this decides what it looks like, and the two are
|
||||
* changed for different reasons.
|
||||
*
|
||||
* Space Grotesk throughout, with a monospace face for anything a reader might have to type or
|
||||
* compare character by character -- identifiers, paths, package URLs, CVSS vectors, VEX
|
||||
* justifications. That distinction is the one typographic rule the whole report rests on.
|
||||
*/
|
||||
|
||||
@font-face {
|
||||
font-family: "Space Grotesk";
|
||||
font-weight: 400;
|
||||
src: url("fonts/SpaceGrotesk-Regular.ttf");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Space Grotesk";
|
||||
font-weight: 500;
|
||||
src: url("fonts/SpaceGrotesk-Medium.ttf");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Space Grotesk";
|
||||
font-weight: 700;
|
||||
src: url("fonts/SpaceGrotesk-Bold.ttf");
|
||||
}
|
||||
|
||||
/* Shipped rather than asked of the host. `monospace` resolves to whatever a machine happens to
|
||||
have -- DejaVu on one, Andale on another -- and a report whose identifiers change shape between
|
||||
two machines is a report nobody can compare. Space Mono is the companion face to Space Grotesk. */
|
||||
@font-face {
|
||||
font-family: "Space Mono";
|
||||
font-weight: 400;
|
||||
src: url("fonts/SpaceMono-Regular.ttf");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Space Mono";
|
||||
font-weight: 700;
|
||||
src: url("fonts/SpaceMono-Bold.ttf");
|
||||
}
|
||||
|
||||
:root {
|
||||
--ink: #1a1a1a;
|
||||
--muted: #55585c;
|
||||
--rule: #1a1a1a;
|
||||
--border: #c9cbcd;
|
||||
--header-fill: #e7e8ea;
|
||||
--label-fill: #f4f5f6;
|
||||
/* The filtering reason is the one row that argues rather than states, and it is tinted so that
|
||||
it reads as an aside even when the page is skimmed. */
|
||||
--aside-fill: #fdf5ea;
|
||||
--critical: #d0021b;
|
||||
--high: #e8710a;
|
||||
--medium: #f0ad20;
|
||||
--low: #1f9d55;
|
||||
}
|
||||
|
||||
@page {
|
||||
size: A4;
|
||||
margin: 22mm 18mm 18mm 18mm;
|
||||
|
||||
@bottom-left {
|
||||
content: string(scan-footer);
|
||||
font-family: "Space Grotesk", sans-serif;
|
||||
font-size: 6.5pt;
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
@bottom-center {
|
||||
content: counter(page);
|
||||
font-family: "Space Grotesk", sans-serif;
|
||||
font-size: 6.5pt;
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
@bottom-right {
|
||||
content: string(date-footer);
|
||||
font-family: "Space Grotesk", sans-serif;
|
||||
font-size: 6.5pt;
|
||||
color: var(--muted);
|
||||
}
|
||||
}
|
||||
|
||||
html {
|
||||
font-family: "Space Grotesk", sans-serif;
|
||||
font-size: 8.5pt;
|
||||
line-height: 1.45;
|
||||
color: var(--ink);
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
code,
|
||||
.mono {
|
||||
font-family: "Space Mono", monospace;
|
||||
font-size: 0.93em;
|
||||
}
|
||||
|
||||
/* Carried into the running footer on every page. Set once, on the cover. */
|
||||
.footer-scan {
|
||||
string-set: scan-footer content();
|
||||
}
|
||||
|
||||
.footer-date {
|
||||
string-set: date-footer content();
|
||||
}
|
||||
|
||||
.footer-scan,
|
||||
.footer-date {
|
||||
position: absolute;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
/* --- Cover ------------------------------------------------------------------------------- */
|
||||
|
||||
.cover-mark {
|
||||
text-align: right;
|
||||
margin-bottom: 42mm;
|
||||
}
|
||||
|
||||
.cover-mark img {
|
||||
height: 15mm;
|
||||
}
|
||||
|
||||
.cover-title {
|
||||
font-size: 19pt;
|
||||
font-weight: 400;
|
||||
margin: 0 0 9mm 0;
|
||||
}
|
||||
|
||||
/* --- Headings ---------------------------------------------------------------------------- */
|
||||
|
||||
/* A section heading and the rule under it are one thing, so the rule belongs to the heading and
|
||||
cannot be separated from it by a page break. */
|
||||
h1 {
|
||||
font-size: 12.5pt;
|
||||
font-weight: 700;
|
||||
margin: 12mm 0 4mm 0;
|
||||
padding-bottom: 1.6mm;
|
||||
border-bottom: 0.8pt solid var(--rule);
|
||||
break-after: avoid;
|
||||
}
|
||||
|
||||
h1:first-of-type {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 9pt;
|
||||
font-weight: 700;
|
||||
margin: 7mm 0 2.5mm 0;
|
||||
break-after: avoid;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 8.5pt;
|
||||
font-weight: 700;
|
||||
margin: 5mm 0 2mm 0;
|
||||
break-after: avoid;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0 0 2.5mm 0;
|
||||
}
|
||||
|
||||
p.note {
|
||||
color: var(--ink);
|
||||
max-width: 155mm;
|
||||
}
|
||||
|
||||
/* --- Definition rows --------------------------------------------------------------------- */
|
||||
|
||||
/* Label left, value right, on one grid so that every block of them lines up down the page even
|
||||
when they are separated by headings. */
|
||||
.facts {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-bottom: 3mm;
|
||||
}
|
||||
|
||||
.facts td {
|
||||
padding: 0.7mm 0;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.facts td:first-child {
|
||||
width: 46mm;
|
||||
padding-right: 4mm;
|
||||
}
|
||||
|
||||
.facts.wide td:first-child {
|
||||
width: 62mm;
|
||||
}
|
||||
|
||||
.facts tr.gap td {
|
||||
padding-top: 4mm;
|
||||
}
|
||||
|
||||
/* --- Ledger tables (severity counts, languages) ------------------------------------------- */
|
||||
|
||||
/* Ruled above and below with hairlines between, and a heavier line before the total: the shape a
|
||||
reader already knows from an invoice, used for the same reason -- the last row is a sum. */
|
||||
.ledger {
|
||||
width: 62%;
|
||||
border-collapse: collapse;
|
||||
margin-bottom: 4mm;
|
||||
}
|
||||
|
||||
.ledger th,
|
||||
.ledger td {
|
||||
padding: 1.4mm 1mm;
|
||||
border-bottom: 0.4pt solid var(--border);
|
||||
}
|
||||
|
||||
.ledger thead th {
|
||||
border-bottom: 0.8pt solid var(--rule);
|
||||
text-align: left;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.ledger td:last-child {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.ledger tr.total td {
|
||||
border-top: 0.8pt solid var(--rule);
|
||||
border-bottom: none;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
/* --- Grid tables -------------------------------------------------------------------------- */
|
||||
|
||||
.grid {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-bottom: 4mm;
|
||||
/* A table that splits across a page keeps its header on the second half. */
|
||||
break-inside: auto;
|
||||
}
|
||||
|
||||
.grid th,
|
||||
.grid td {
|
||||
border: 0.4pt solid var(--border);
|
||||
padding: 1.6mm 2mm;
|
||||
vertical-align: top;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.grid thead th {
|
||||
background: var(--header-fill);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.grid tr.total td {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.grid tr,
|
||||
.facts tr {
|
||||
break-inside: avoid;
|
||||
}
|
||||
|
||||
/* --- Cards -------------------------------------------------------------------------------- */
|
||||
|
||||
/* One finding, as a titled block of label/value rows. Kept on one page where it fits: a card split
|
||||
down the middle loses the thing that makes it a card. */
|
||||
.card {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-bottom: 3.5mm;
|
||||
break-inside: avoid;
|
||||
}
|
||||
|
||||
.card caption {
|
||||
background: var(--header-fill);
|
||||
border: 0.4pt solid var(--border);
|
||||
padding: 1.6mm 2mm;
|
||||
text-align: left;
|
||||
font-weight: 700;
|
||||
caption-side: top;
|
||||
}
|
||||
|
||||
.card th,
|
||||
.card td {
|
||||
border: 0.4pt solid var(--border);
|
||||
padding: 1.6mm 2mm;
|
||||
vertical-align: top;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.card th {
|
||||
width: 34mm;
|
||||
background: var(--label-fill);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.card tr.aside th,
|
||||
.card tr.aside td {
|
||||
background: var(--aside-fill);
|
||||
}
|
||||
|
||||
/* The justification itself, set as the token it is rather than as prose about a token. */
|
||||
.token {
|
||||
font-family: "Space Mono", monospace;
|
||||
font-size: 0.93em;
|
||||
background: #ffffff;
|
||||
border: 0.4pt solid var(--border);
|
||||
border-radius: 1mm;
|
||||
padding: 0.3mm 1.2mm;
|
||||
}
|
||||
|
||||
/* --- Severity ----------------------------------------------------------------------------- */
|
||||
|
||||
.sev {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.sev-critical {
|
||||
color: var(--critical);
|
||||
}
|
||||
|
||||
.sev-high {
|
||||
color: var(--high);
|
||||
}
|
||||
|
||||
.sev-medium {
|
||||
color: var(--medium);
|
||||
}
|
||||
|
||||
.sev-low {
|
||||
color: var(--low);
|
||||
}
|
||||
|
||||
/* --- Distribution bars --------------------------------------------------------------------- */
|
||||
|
||||
/* Label, count, then one bar made of stacked severity segments. The bar is scaled against the
|
||||
largest row rather than against the total, so the shape of the distribution is what is read and
|
||||
the busiest row fills the width. */
|
||||
.bars {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-bottom: 1.5mm;
|
||||
}
|
||||
|
||||
.bars td {
|
||||
border: 0.4pt solid var(--border);
|
||||
padding: 1.2mm 2mm;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.bars td.count {
|
||||
width: 12mm;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.bars td.track {
|
||||
width: 50%;
|
||||
padding: 1.2mm 2mm;
|
||||
}
|
||||
|
||||
.bar {
|
||||
height: 3mm;
|
||||
width: 100%;
|
||||
/* The segments are inline-block, so the newlines between them in the template would be
|
||||
rendered as spaces and push a full-width bar onto a second line. */
|
||||
font-size: 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.bar span {
|
||||
display: inline-block;
|
||||
height: 3mm;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.seg-critical {
|
||||
background: var(--critical);
|
||||
}
|
||||
|
||||
.seg-high {
|
||||
background: var(--high);
|
||||
}
|
||||
|
||||
.seg-medium {
|
||||
background: var(--medium);
|
||||
}
|
||||
|
||||
.seg-low {
|
||||
background: var(--low);
|
||||
}
|
||||
|
||||
/* A distribution and its legend travel together. Where the pair does not fit, it moves to the
|
||||
next page whole rather than leaving a stranded row and an orphaned key behind. */
|
||||
.block {
|
||||
break-inside: avoid;
|
||||
}
|
||||
|
||||
.legend {
|
||||
font-size: 7.5pt;
|
||||
color: var(--ink);
|
||||
margin-bottom: 5mm;
|
||||
}
|
||||
|
||||
.legend .key {
|
||||
display: inline-block;
|
||||
width: 2.4mm;
|
||||
height: 2.4mm;
|
||||
margin-right: 1.2mm;
|
||||
}
|
||||
|
||||
.legend .item {
|
||||
margin-right: 4mm;
|
||||
}
|
||||
|
||||
.legend .caveat {
|
||||
color: var(--muted);
|
||||
}
|
||||
Reference in new issue
Block a user