// ========================================== // PRESENTATION: ОБЩАЯ ОСНОВА ВЁРСТКИ // ========================================== #let design-tokens(company, overrides: (:)) = { let defaults = ( brand-color: company.brand.at("color", default: rgb("e39f49")), text-font: "Times New Roman", sans-font: "Arial", text-size: 12pt, small-size: 8pt, line-height: 1.5em, compact-line-height: 0.65em, paper: "a4", page-margin: (left: 3cm, right: 1.5cm, top: 2cm, bottom: 2cm), ) let result = defaults for (key, value) in overrides { if key not in defaults { panic("Scientia / design-tokens: неизвестный token " + repr(key)) } result.insert(key, value) } result } #let watermark-layer(value, font: "Arial") = { if value == none { none } else { [ #place(center + horizon, dx: -4.8cm, dy: -8.5cm)[ #rotate(35deg)[#text(font: font, size: 40pt, weight: "bold", fill: rgb("e8c9c9").transparentize(65%))[#value]] ] #place(center + horizon)[ #rotate(35deg)[#text(font: font, size: 40pt, weight: "bold", fill: rgb("e8c9c9").transparentize(65%))[#value]] ] #place(center + horizon, dx: 4.8cm, dy: 8.5cm)[ #rotate(35deg)[#text(font: font, size: 40pt, weight: "bold", fill: rgb("e8c9c9").transparentize(65%))[#value]] ] ] } } #let render-media-slot( resource, policy: "placeholder", width: 4cm, height: 2cm, label: "РЕСУРС НЕ ЗАДАН", fit: "contain", ) = { if policy not in ("hide", "placeholder", "reserve-space") { panic("Scientia / media-slot: неизвестная политика " + repr(policy)) } if resource == none { if policy == "hide" { none } else if policy == "reserve-space" { box(width: width, height: height) } else { box( width: width, height: height, stroke: 0.6pt + luma(150), fill: luma(245), inset: 4pt, align(center + horizon)[ #text(font: "Arial", size: 7pt, fill: luma(110), weight: "bold")[#label] ], ) } } else if type(resource) == path { image(resource, width: width, height: height, fit: fit) } else if type(resource) == content { box(width: width, height: height, align(center + horizon, resource)) } else { panic("Scientia / media-slot: ожидались none, path или content") } } #let apply-foundation( body, ctx: none, tokens: (:), page-options: (:), text-options: (:), par-options: (:), ) = { if ctx == none { panic("Scientia / foundation: document context обязателен") } let tokens = design-tokens(ctx.company, overrides: tokens) let page-defaults = ( paper: tokens.paper, margin: tokens.at("page-margin"), foreground: watermark-layer(ctx.options.watermark, font: tokens.at("sans-font")), ) let resolved-page = page-defaults for (key, value) in page-options { resolved-page.insert(key, value) } set page(..resolved-page) set text( font: tokens.at("text-font"), size: tokens.at("text-size"), lang: "ru", ..text-options, ) set par( justify: true, first-line-indent: (amount: 1.25cm, all: true), leading: tokens.at("line-height"), ..par-options, ) show table.cell: set par(first-line-indent: 0pt) show figure.caption.where(kind: table): set par(first-line-indent: 0pt) body }