Files
praca_inzynierska/Thesis/style.typ
T
2026-06-05 13:34:58 +02:00

470 lines
14 KiB
Typst
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// =========================================================
// style.typ Szablon Pracy Dyplomowej
// Wydział Informatyki, ZUT w Szczecinie
// Typst 0.12+
// =========================================================
//
#let blue-wi = cmyk(60%, 20%, 0%, 0%) // blueWI jasny niebieski WI
#let blue-zut = cmyk(100%, 75%, 0%, 20%) // blueZUT granatowy ZUT
#let gray-zut = cmyk(0%, 0%, 0%, 40%) // grayZUT szary ZUT
// Pochodne (odpowiedniki blueWI!20, blueZUT!60 itp.)
#let blue-wi-20 = blue-wi.lighten(80%)
#let blue-zut-60 = blue-zut.lighten(40%)
#let gray-zut-10 = gray-zut.lighten(90%)
// Kolory kodu źródłowego
#let code-green = rgb(0, 154, 0)
#let code-gray = rgb(128, 128, 128)
#let code-violet = rgb(148, 0, 211)
#let theorem(title: none, body) = block(
width: 100%,
fill: luma(97%),
stroke: (top: 1.2pt + blue-zut, bottom: 1.2pt + blue-zut, left: 1.2pt + blue-zut, right: 1.2pt + blue-zut),
inset: 8pt,
above: 8pt,
below: 8pt,
)[
#text(size: 10pt, weight: "bold", font: "Fira Sans", fill: blue-zut)[
Twierdzenie#if title != none [ #title]
]
#parbreak()
#body
]
/// Definicja lewa kreska 2pt blueZUT (dBox)
#let definition(title: none, body) = block(
width: 100%,
stroke: (left: 2pt + blue-zut),
inset: (left: 10pt, right: 8pt, top: 4pt, bottom: 4pt),
above: 8pt,
below: 8pt,
)[
#text(size: 10pt, weight: "bold", font: "Fira Sans")[
Definicja#if title != none [ #title]
]
#parbreak()
#body
]
#let example(title: none, body) = block(
above: 6pt,
below: 6pt,
)[
#text(size: 10pt, weight: "bold", font: "Fira Sans", fill: blue-zut)[
Przykład#if title != none [ #title]
]
#parbreak()
#body #h(1fr) $blacksquare$
]
// ╔═══════════════════════════════════════════════════════╗
// ║ 3. GŁÓWNA FUNKCJA SZABLONU ║
// ╚═══════════════════════════════════════════════════════╝
/// Główna funkcja opakowująca dokument.
///
/// Parametry:
/// shorttitle krótki tytuł pracy wyświetlany w nagłówku parzystych stron
/// body treść dokumentu
#let zut-template(
shorttitle: "",
body,
) = {
// ── 3.1 STRONA ──────────────────────────────────────────
set page(
paper: "a4",
margin: (
top: 3.2cm,
bottom: 3.5cm,
inside: 3.5cm, // 2.5cm tekst + 1cm bindingoffset (rozwiązuje problem marginesu z lewej z Twojego kodu)
outside: 2.5cm,
),
// ── Nagłówek ─────────────────────────────────────────
header: context {
let pg = counter(page).get().first()
let is-odd = calc.odd(pg)
// Czy ta strona otwiera rozdział? (brak nagłówka)
let chapter-locs = query(heading.where(level: 1))
let is-chapter-page = chapter-locs.any(h => counter(page).at(h.location()).first() == pg)
if not is-chapter-page {
// Tytuł bieżącego rozdziału do nagłówka
let prev = query(heading.where(level: 1).before(here()))
let ch-label = if prev.len() > 0 {
let h = prev.last()
let num = counter(heading).at(h.location())
[#num.first().#h.body]
} else { [] }
set text(font: "Fira Sans", size: 10pt)
if is-odd {
// ── Nieparzysta (prawa) ──────────────────────────
grid(
columns: (1fr, auto),
align: horizon,
box(
fill: blue-wi-20,
width: 100%,
inset: (x: 7pt, y: 4pt),
)[#ch-label],
box(
fill: blue-zut,
inset: (x: 7pt, y: 4pt),
)[#text(fill: white, weight: "bold")[#pg]],
)
} else {
// ── Parzysta (lewa) ──────────────────────────────
grid(
columns: (auto, 1fr),
align: horizon,
box(
fill: blue-zut,
inset: (x: 7pt, y: 4pt),
)[#text(fill: white, weight: "bold")[#pg]],
box(
fill: blue-wi-20,
width: 100%,
inset: (x: 7pt, y: 4pt),
)[#shorttitle],
)
}
}
}, // /header
// ── Stopka ───────────────────────────────────────────
footer: context {
let pg = counter(page).get().first()
let chapter-locs = query(heading.where(level: 1))
let is-chapter-page = chapter-locs.any(h => counter(page).at(h.location()).first() == pg)
if is-chapter-page {
align(right, box(fill: blue-zut, inset: (x: 7pt, y: 4pt))[
#text(font: "Fira Sans", size: 10pt, fill: white, weight: "bold")[#pg]
])
}
},
numbering: "1",
) // /set page
// ── 3.2 TEKST ───────────────────────────────────────────
set text(font: "New Computer Modern", size: 12pt, lang: "pl")
set par(justify: true, leading: 0.65em)
// ── 3.3 LISTY ───────────────────────────────────────────
set list(marker: [--], spacing: 0.4em, indent: 1em)
set enum(spacing: 0.4em, indent: 1em)
// ── 3.4 NAGŁÓWKI ─────────────
set heading(numbering: "1.1")
show heading: it => {
let num = if it.numbering != none and it.outlined {
counter(heading).display(it.numbering)
}
if it.level == 1 {
// Wymuszenie nowej strony dla głównego rozdziału
pagebreak(weak: true)
v(1.5em, weak: true)
block(width: 100%, inset: (bottom: 1em, top: 7em))[
#if num != none {
place(left + top, dx: -1.5cm, dy: 0.1em)[
#text(size: 26pt, fill: blue-zut, weight: "bold", font: "Fira Sans", num)
]
}
#align(left)[
#text(size: 26pt, fill: blue-zut, weight: "bold", font: "Fira Sans", it.body)
]
]
} else {
let txt-size = if it.level == 2 { 14pt } else if it.level == 3 { 12pt } else { 11pt }
let spacing-top = if it.level == 2 { 1.5em } else if it.level == 3 { 1.2em } else { 1em }
let spacing-bottom = if it.level == 2 { 0.5em } else { 0.4em }
v(spacing-top, weak: true)
block(width: 100%, inset: (bottom: spacing-bottom))[
#if num != none {
let dy-val = if it.level == 2 { 0.0em } else { 0.05em }
place(left + top, dx: -1.5cm, dy: dy-val)[
#text(size: txt-size, fill: blue-zut, weight: "bold", font: "Fira Sans", num)
]
}
// Tytuł na czarno, dopasowany do tekstu
#text(size: txt-size, fill: black, weight: "bold", font: "Fira Sans", it.body)
]
}
}
// ── 3.5 SPIS TREŚCI ─────────────────────────────────────
set outline(indent: auto)
show outline.entry: it => {
if it.level == 1 {
v(12pt, weak: true)
text(size: 11pt, weight: "bold", font: "Fira Sans", fill: blue-zut)[
#h(1.25cm)
#it
]
} else if it.level == 2 {
v(3pt, weak: true)
text(size: 10pt, font: "Fira Sans")[
#h(1.25cm)
#it
]
} else if it.level == 3 {
v(1pt, weak: true)
text(size: 9pt, font: "Fira Sans")[
#h(2.5cm)
#it
]
} else {
it
}
}
// ── 3.6 BLOKI KODU ──────────────────────────────────────
show raw.where(block: true): it => {
block(
width: 100%,
fill: gray-zut.lighten(93%),
stroke: (left: 2pt + blue-wi),
inset: (x: 12pt, y: 9pt),
above: 9pt,
below: 9pt,
radius: (right: 2pt),
)[
#set text(size: 9.5pt, font: ("Fira Mono", "Courier New"))
#it
]
}
set raw(theme: "zut.tmTheme")
show raw.where(block: true): it => {
let lines = it.lines
block(
fill: gray-zut.lighten(100%),
radius: 4pt,
clip: true,
width: 100%,
)[
#set text(size: 10pt, font: ("Fira Mono", "Courier New"))
#grid(
columns: (auto, 1fr),
inset: (left: 10pt, right: 10pt, top: 2pt, bottom: 2pt),
align: (x, y) => if x == 0 { right + top } else { left + top },
grid.vline(x: 1, stroke: (paint: luma(160), thickness: 1pt)),
..lines
.map(line => (
text(fill: luma(160), size: 9pt)[#line.number],
line.body,
))
.flatten(),
)
]
}
// ── 3.7 PODPISY RYSUNKÓW I TABEL ────────────────────────
set figure(gap: 0.8em)
let raw-fig-counter = counter("raw-fig")
let img-fig-counter = counter("img-fig")
show heading.where(level: 1): it => {
raw-fig-counter.update(1)
img-fig-counter.update(1)
it
}
show figure.where(kind: raw): it => {
// Step the custom counter
raw-fig-counter.step()
// Build the number: heading-index.figure-index
let heading-num = counter(heading.where(level: 1)).display()
let fig-num = raw-fig-counter.display("1")
let full-number = heading-num + "." + fig-num
it.body
v(10pt, weak: true)
align(center, block(width: auto)[
#text(weight: "bold", fill: blue-zut, font: "Fira Sans")[Program #full-number:]
#text(font: "Fira Sans")[#it.caption.body]
])
}
show figure.where(kind: image): it => {
// Step the custom counter
img-fig-counter.step()
// Build the number: heading-index.figure-index
let heading-num = counter(heading.where(level: 1)).display()
let fig-num = img-fig-counter.display("1")
let full-number = heading-num + "." + fig-num
it.body
v(10pt, weak: true)
align(center, block(width: auto)[
#text(weight: "bold", fill: blue-zut, font: "Fira Sans")[Rysunek #full-number:]
#text(font: "Fira Sans")[#it.caption.body]
])
}
// ── 3.8 TABELE ──────────────────────────────────────────
set table(
stroke: none,
inset: (x: 8pt, y: 5pt),
)
show table.cell.where(y: 0): set text(weight: "bold")
show table: set block(above: 8pt, below: 8pt)
body
} // /zut-template
/// Spis rysunków wywołaj jako ostatni element wewnątrz zut-template.
///
/// Wyszukuje wszystkie figure(kind: image) w dokumencie i odtwarza
/// numery X.Y identyczne z tymi generowanymi przez show figure.where(kind: image)
/// w zut-template.
#let list-of-figures() = {
[
#set heading(numbering: none)
#show heading: it => {
v(1em)
block(width: 100%, inset: (bottom: 3em, top: 7em, left: 2em))[
#align(left)[
#text(size: 25pt, fill: blue-zut, weight: "regular", font: "Fira Sans", it.body)
]
]
}
#heading(level: 1, outlined: false)[Spis rysunków]
]
context {
let all-figs = query(figure.where(kind: image))
let local = 1
let prev-ch = -1
for fig in all-figs {
let ch = counter(heading.where(level: 1)).at(fig.location()).first()
if ch != prev-ch {
local = 0
prev-ch = ch
}
local = local + 1
let full-number = str(ch) + "." + str(local)
let pg = counter(page).at(fig.location()).first()
let cap = fig.caption.body
v(8pt, weak: true)
link(fig.location())[
#grid(
columns: (3em, 1fr, auto),
align: (left, left, right),
text(
size: 11pt,
weight: "regular",
font: "Fira Sans",
)[#full-number],
// Podpis + wypełnienie kropkami
[
#text(size: 11pt, font: "Fira Sans")[#cap]
#box(width: 1fr, inset: (x: 0pt))[
#text[#repeat[ . ]]
]
],
// Numer strony
text(
size: 10pt,
weight: "regular",
font: "Fira Sans",
)[#pg],
)
]
}
}
}
/// Funkcja rysująca abstrakt polska wersja u góry, angielska na dole, jedna strona A4.
///
/// Parametry:
/// pl-title nagłówek sekcji polskiej (domyślnie "Streszczenie")
/// pl-body treść streszczenia po polsku
/// pl-keywords słowa kluczowe (pojedynczy ciąg, np. "A, B, C")
/// en-title nagłówek sekcji angielskiej (domyślnie "Abstract")
/// en-body treść abstraktu po angielsku
/// en-keywords keywords (pojedynczy ciąg, np. "A, B, C")
#let abstract(
pl-title: "Streszczenie",
pl-body: str,
pl-keywords: "",
en-title: "Abstract",
en-body: str,
en-keywords: "",
) = {
set page(
paper: "a4",
margin: (
top: 3.2cm,
bottom: 3.5cm,
inside: 3.5cm,
outside: 2.5cm,
),
header: none,
footer: none,
numbering: none,
)
set text(font: "New Computer Modern", size: 12pt, lang: "pl")
set par(justify: true, leading: 0.65em)
set heading(numbering: none, outlined: false)
show heading: it => {
if it.level == 1 {
align(center)[
#text(size: 17pt, fill: blue-zut, weight: "regular", font: "Fira Sans", it.body)
]
}
}
// polish version of the abstract
v(0.7cm)
[= #pl-title]
v(0.5cm)
par(pl-body, first-line-indent: 2em)
if pl-keywords != "" {
[*słowa kluczowe:* #pl-keywords]
}
v(1fr)
// english version
[= #en-title]
set text(lang: "en")
v(0.5cm)
par(en-body)
if en-keywords != "" {
[*keywords:* #en-keywords]
}
}