Improve content formatting

This commit is contained in:
2026-05-05 22:14:54 +02:00
parent 5c0f6c30e0
commit 9ecbfeb99d
10 changed files with 126 additions and 155 deletions
+1 -4
View File
@@ -1,5 +1,2 @@
#set heading(numbering: "1.1")
= Wstęp <wstep>
== Cel i zakres pracy <cel>
== Struktura pracy <struktura>
Tu będzie dopiero treść :)
+1 -1
View File
@@ -40,4 +40,4 @@ W przypadku oparcia aplikacji komunikujacej się peer to peer z innymi urządzen
== Istniejące rozwiązania i ich problemy
Dwoma najpopularniejszymi aplikacjami do współtworzenia notatek w czasie rzeczywistym Google Docs i Microsoft Word Online. Ich zakres funkcjonalności jest bardzo podobny - złożone formatowanie tekstu; możliwość dodawania załączników, tabel; historia wersji dokumentu; obecność publicznego API; wykorzystanie nowoczesnych standardów szyfrowania komunikacji; eksport dokumentu w postaci innego rodzaju pliku oraz wymagają konta do możliwości ich użycia. Google Docs korzysta ze swojego algorytmu Operational Transformation do synchronizacji zmian między użytkownikami, sposób przechowywania dokumentów nie jest jasny, nie wiemy w jakiej postaci są one przechowywane na serwerach Google, a dostęp do aplikacji jest darmowy. Microsoft Word Online nie udostępnia publicznie informacji o stosowanym podejściu do synchronizacji danych, dokumenty przechowywane w postaci plików docx, a dostęp do aplikacji jest również darmowy.
Głównym problemem większości dzisiejszych narzędzi do tworzenia dokumentów jest uzależnienie od dostawcy. Każda z wymienionych aplikacji, jak i wiele innych dostępnych na rynku do skorzystania ze swoich usług wymaga założenia konta na platformie dostawcy, a w czasie współpracy wymagany jest ciągły dostęp do Internetu. W momencie gdy pracujemy nad jednym dokumentem z innymi użytkownikami w tym samym pomieszczeniu i nasze urządzenia podłączone do tej samej sieci, opóźnienie w nanoszeniu zmian między użytkownikami zawsze uwzględnia dostęp do scentralizowanych serwerów. W momencie gdy zostaniemy odcięci od dostępu do Internetu, ale nadal będąc w tej samej sieci lokalnej, tracimy możliwość dalszej pracy. Szczególnie widać to w przypadku Google Docs, którego algorytm synchronizujący narzuca obecność serwera wybierającego kolejność nanoszenia zmian w dokumentach.
Głównym problemem większości dzisiejszych narzędzi do tworzenia dokumentów jest uzależnienie od dostawcy. Każda z wymienionych aplikacji, jak i wiele innych dostępnych na rynku do skorzystania ze swoich usług wymaga założenia konta na platformie dostawcy, a w czasie współpracy wymagany jest ciągły dostęp do Internetu. W momencie gdy pracujemy nad jednym dokumentem z innymi użytkownikami w tym samym pomieszczeniu i nasze urządzenia podłączone do tej samej sieci, opóźnienie w nanoszeniu zmian między użytkownikami zawsze uwzględnia dostęp do scentralizowanych serwerów. W momencie gdy zostaniemy odcięci od dostępu do Internetu, ale nadal będąc w tej samej sieci lokalnej, tracimy możliwość dalszej pracy. Szczególnie widać to w przypadku Google Docs, którego algorytm synchronizujący narzuca obecność serwera wybierającego kolejność nanoszenia zmian w dokumentach.
+2
View File
@@ -1,3 +1,5 @@
#set heading(numbering: "1.1")
= Wymagania systemowe <wymagania>
== Wymagania funkcjonalne
== Wymagania niefunkcjonalne
+2
View File
@@ -1,3 +1,5 @@
#set heading(numbering: "1.1")
= Implementacja <implementacja>
== Projekt architektury systemu <projekt>
== Model danych
+2
View File
@@ -1,3 +1,5 @@
#set heading(numbering: "1.1")
= Testowanie i weryfikacja <testy>
== Metodologia testowania
== Scenariusze testowe
+2 -2
View File
@@ -1,6 +1,6 @@
#set heading(numbering: "1.1")
= Podsumowanie i kierunki rozwoju <podsumowanie>
== Osiągnięte cele
== Ocena spełnienia wymagań
== Możliwości dalszej rozbudowy
=== Szyfrowanie end-to-end
=== Optymalizacja dużych dokumentów
BIN
View File
Binary file not shown.
+1
View File
@@ -11,6 +11,7 @@
#pagebreak()
#zut-template([
#include "Chapters/0. Introduction.typ"
#include "Chapters/1. Theoretical Scope.typ"
#include "Chapters/2. Requirements.typ"
#include "Chapters/3. Implementation.typ"
+62 -144
View File
@@ -3,29 +3,26 @@
// Wydział Informatyki, ZUT w Szczecinie
// Typst 0.12+
// =========================================================
// ╔═══════════════════════════════════════════════════════╗
// ║ 1. KOLORY ║
// ╚═══════════════════════════════════════════════════════╝
//
#let blue-wi = cmyk(60%, 20%, 0%, 0%) // blueWI jasny niebieski WI
#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
#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%)
#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-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),
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,
@@ -63,7 +60,6 @@
#body #h(1fr) $blacksquare$
]
// ╔═══════════════════════════════════════════════════════╗
// ║ 3. GŁÓWNA FUNKCJA SZABLONU ║
// ╚═══════════════════════════════════════════════════════╝
@@ -77,36 +73,30 @@
shorttitle: "",
body,
) = {
// ── 3.1 STRONA ──────────────────────────────────────────
set page(
paper: "a4",
margin: (
top: 3.2cm,
bottom: 3.5cm,
inside: 3.5cm, // 2.5cm tekst + 1cm bindingoffset
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 ─────────────────────────────────────────
// 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)
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
)
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 h = prev.last()
let num = counter(heading).at(h.location())
[#num.first().#h.body]
} else { [] }
@@ -119,12 +109,12 @@
columns: (1fr, auto),
align: horizon,
box(
fill: blue-wi-20,
fill: blue-wi-20,
width: 100%,
inset: (x: 7pt, y: 4pt),
)[#ch-label],
box(
fill: blue-zut,
fill: blue-zut,
inset: (x: 7pt, y: 4pt),
)[#text(fill: white, weight: "bold")[#pg]],
)
@@ -134,11 +124,11 @@
columns: (auto, 1fr),
align: horizon,
box(
fill: blue-zut,
fill: blue-zut,
inset: (x: 7pt, y: 4pt),
)[#text(fill: white, weight: "bold")[#pg]],
box(
fill: blue-wi-20,
fill: blue-wi-20,
width: 100%,
inset: (x: 7pt, y: 4pt),
)[#shorttitle],
@@ -148,20 +138,15 @@
}, // /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
)
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]
]
)
align(right, box(fill: blue-zut, inset: (x: 7pt, y: 4pt))[
#text(fill: white, weight: "bold")[#pg]
])
}
},
@@ -170,129 +155,77 @@
// ── 3.2 TEKST ───────────────────────────────────────────
set text(font: "Fira Sans", size: 12pt, lang: "pl")
set text(font: "New Computer Modern", 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 ────────────────────────────────────────
// ── 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().]
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)
]
#h(1.2em)
#it.body
}
#align(left)[
#text(size: 26pt, fill: blue-zut, weight: "bold", font: "Fira Sans", it.body)
]
} else {
block(below: 0.6em)[#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 }
// 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()]
]
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)
]
}
#it.body
// Tytuł na czarno, dopasowany do tekstu
#text(size: txt-size, fill: black, weight: "bold", font: "Fira Sans", 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)
@@ -305,12 +238,6 @@
// ── 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%,
@@ -321,34 +248,29 @@
below: 9pt,
radius: (right: 2pt),
)[
#set text(size: 9.5pt, font: ("Fira Mono", "Courier New", "monospace"))
#set text(size: 9.5pt, font: ("Fira Mono", "Courier New"))
#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"))
#set text(size: 10pt, font: ("Fira Mono", "Courier New"))
#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] }
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()
@@ -358,17 +280,13 @@
// ── 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
+51 -2
View File
@@ -1,6 +1,55 @@
#import "style.typ": definition, example, theorem, zut-template
#set heading(numbering: "1.")
#set par(first-line-indent: 0pt)
#let color-dark-blue = rgb("#223d73")
#let color-page-num = rgb("#6b7b96")
#let color-dots = rgb("#a0aabf")
#set heading(numbering: "1.1")
#set text(font: "Fira Sans")
#set outline(title: text(size: 24pt, fill: color-dark-blue, weight: "regular")[Spis treści])
#show outline.entry: it => {
let is-lvl-1 = it.level == 1
let num = it.prefix()
let title = it.body()
let page-num = it.page()
let num-style = if is-lvl-1 {
text(size: 14pt, fill: color-dark-blue, num)
} else {
text(size: 12pt, fill: black, num)
}
let title-style = if is-lvl-1 {
text(size: 14pt, fill: color-dark-blue, title)
} else {
text(size: 12pt, fill: black, title)
}
let page-style = text(size: 10pt, fill: color-page-num, weight: "medium", page-num)
v(if is-lvl-1 { 14pt } else { 6pt }, weak: true)
link(it.element.location())[
#grid(
columns: (3em, 1fr, auto),
align: (left, left, right),
// Kolumna 1: Numery rozdziałów w jednej linii
num-style,
// Kolumna 2: Tytuł oraz kropki
[
#title-style
#box(width: 1fr, inset: (x: 5pt))[
#text(fill: color-dots)[#repeat[ . ]]
]
],
// Kolumna 3: Numer strony
page-style,
)
]
}
#outline()
#pagebreak()