120 lines
3.4 KiB
Typst
120 lines
3.4 KiB
Typst
// ==========================================
|
|
// 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
|
|
}
|