Files
praca_inzynierska/Thesis/style.typ
T
2026-03-17 20:45:41 +01:00

375 lines
12 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+
// =========================================================
// ╔═══════════════════════════════════════════════════════╗
// ║ 1. KOLORY ║
// ╚═══════════════════════════════════════════════════════╝
#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
outside: 2.5cm,
),
// ── Nagłówek ─────────────────────────────────────────
// Strony nieparzyste (prawe): tytuł rozdziału + numer strony
// Strony parzyste (lewe): numer strony + shorttitle
// Strony otwierające rozdział: nagłówek ukryty (styl "plain")
header: context {
let pg = counter(page).get().first()
let is-odd = calc.odd(pg)
// Czy ta strona otwiera rozdział? (→ plain style: 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 ───────────────────────────────────────────
// Widoczna tylko na stronach otwierających rozdział (plain style).
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 {
set text(font: "Fira Sans", size: 10pt)
align(right,
box(fill: blue-zut, inset: (x: 7pt, y: 4pt))[
#text(fill: white, weight: "bold")[#pg]
]
)
}
},
numbering: "1",
) // /set page
// ── 3.2 TEKST ───────────────────────────────────────────
set text(font: "Fira Sans", size: 12pt, lang: "pl")
set par(justify: true, leading: 0.65em)
// ── 3.3 LISTY ───────────────────────────────────────────
// \setlist{nolistsep} → spacing: 0.4em
// \setlist[itemize]{label=--}
set list(marker: [--], spacing: 0.4em, indent: 1em)
set enum(spacing: 0.4em, indent: 1em)
// ── 3.4 NAGŁÓWKI ────────────────────────────────────────
// Rozdział (\chapter) level 1
// {\huge\sffamily\color{blueZUT}} + numer wysuniẹty o \hspace{-3ex}
show heading.where(level: 1): it => {
pagebreak(weak: true)
v(1cm)
context {
set text(size: 24pt, weight: "bold", font: "Fira Sans", fill: blue-zut)
if it.numbering != none {
block(below: 0.6em)[
// Numer wysuniẹty w lewo (odpowiednik \hspace{-3ex})
#box(width: 0pt)[
#place(dx: -2em)[#counter(heading).display().]
]
#h(1.2em)
#it.body
]
} else {
block(below: 0.6em)[#it.body]
}
}
}
// Sekcja (\section) level 2, wiszący numer w marginesie
// \large\sffamily\bfseries + \llap{\color{blueZUT}{numer}\hspace{1em}}
show heading.where(level: 2): it => {
v(1.5em, weak: true)
context {
block(below: 0.5em, above: 0pt)[
#set text(size: 13pt, weight: "bold", font: "Fira Sans")
#if it.numbering != none {
// Numer wysuniẹty w lewo (llap)
box(width: 0pt)[
#place(dx: -3em)[
#text(fill: blue-zut)[#counter(heading).display()]
]
]
}
#it.body
]
}
v(0.4em, weak: true)
}
// Podsekcja (\subsection) level 3
show heading.where(level: 3): it => {
v(1.2em, weak: true)
context {
block(below: 0.4em, above: 0pt)[
#set text(size: 12pt, weight: "bold", font: "Fira Sans")
#if it.numbering != none {
box(width: 0pt)[
#place(dx: -3em)[
#text(fill: blue-zut)[#counter(heading).display()]
]
]
}
#it.body
]
}
v(0.3em, weak: true)
}
// Podpodsekcja (\subsubsection) level 4
show heading.where(level: 4): it => {
v(1em, weak: true)
context {
block(below: 0.3em, above: 0pt)[
#set text(size: 11pt, weight: "bold", font: "Fira Sans")
#if it.numbering != none {
box(width: 0pt)[
#place(dx: -3em)[
#text(fill: blue-zut)[#counter(heading).display()]
]
]
}
#it.body
]
}
}
// Paragraf (\paragraph) level 5, inline
show heading.where(level: 5): it => {
v(0.8em, weak: true)
text(size: 11pt, weight: "bold", font: "Fira Sans")[#it.body]
v(0.15em, weak: true)
}
// ── 3.5 SPIS TREŚCI ─────────────────────────────────────
// \titlecontents numery, wcięcia, kolory, linie kropkowane
set outline(indent: auto)
show outline.entry: it => {
if it.level == 1 {
// Rozdział: +12pt przerwy, \large, blueZUT, pogrubiony
v(12pt, weak: true)
text(size: 11pt, weight: "bold", font: "Fira Sans", fill: blue-zut)[
#h(1.25cm)
#it
]
} else if it.level == 2 {
// Sekcja: wcięcie 1.25cm, normalny
v(3pt, weak: true)
text(size: 10pt, font: "Fira Sans")[
#h(1.25cm)
#it
]
} else if it.level == 3 {
// Podsekcja: wcięcie 2.5cm, small
v(1pt, weak: true)
text(size: 9pt, font: "Fira Sans")[
#h(2.5cm)
#it
]
} else {
it
}
}
// ── 3.6 BLOKI KODU ──────────────────────────────────────
// Odpowiednik lstdefinestyle{mystyle}:
// • małe litery, font monospace
// • lewa kreska w kolorze blueWI
// • wcięcia x: 5ex
// • numery linii (Typst 0.12+: set raw(numbering: "1"))
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", "monospace"))
#it
]
}
// Kod inline dyskretne tło
show raw.where(block: false): it => {
box(
fill: gray-zut.lighten(93%),
inset: (x: 3pt, y: 1pt),
radius: 2pt,
)[
#set text(size: 10pt, font: ("Fira Mono", "Courier New", "monospace"))
#it
]
}
// ── 3.7 PODPISY RYSUNKÓW I TABEL ────────────────────────
// \captionsetup[figure]{name={\small\sffamily\color{blueZUT} Rysunek}}
// \captionsetup[table] {name={\small\sffamily\color{blueZUT} Tabela}}
set figure(gap: 0.8em)
show figure.caption: it => {
set text(size: 9.5pt, font: "Fira Sans")
let kind-label = if it.kind == image { [Rysunek] }
else if it.kind == table { [Tabela] }
else { [Algorytm] }
[
#text(fill: blue-zut, weight: "bold")[
#kind-label #it.counter.display()
]#it.separator#it.body
]
}
// ── 3.8 TABELE ──────────────────────────────────────────
// \usepackage{booktabs} poziome linie tabel
set table(
stroke: none,
inset: (x: 8pt, y: 5pt),
)
// Linie nagłówka i dołu tabeli (booktabs-style)
show table.cell.where(y: 0): set text(weight: "bold")
show table: set block(above: 8pt, below: 8pt)
// ── Treść dokumentu ─────────────────────────────────────
body
} // /zut-template