// ========================================================= // 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ł? (→ 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 ─────────────────────────────────────────── 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: "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 { 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") show heading.where(level: 1): it => { raw-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")[Algorytm #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