diff --git a/packages/preview/vintage-fiit-thesis/1.1.0/LICENSE b/packages/preview/vintage-fiit-thesis/1.1.0/LICENSE new file mode 100644 index 0000000000..11f98088c6 --- /dev/null +++ b/packages/preview/vintage-fiit-thesis/1.1.0/LICENSE @@ -0,0 +1,15 @@ +MIT No Attribution + +Permission is hereby granted, free of charge, to any person obtaining a copy of this +software and associated documentation files (the "Software"), to deal in the Software +without restriction, including without limitation the rights to use, copy, modify, +merge, publish, distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/packages/preview/vintage-fiit-thesis/1.1.0/README.md b/packages/preview/vintage-fiit-thesis/1.1.0/README.md new file mode 100644 index 0000000000..da74989d0d --- /dev/null +++ b/packages/preview/vintage-fiit-thesis/1.1.0/README.md @@ -0,0 +1,282 @@ + +# Faculty of Informatics and Information Technologies (FIIT) Thesis Template + +This is a Typst template for writing bachelor's and master's thesis at the +Faculty of Informatics and Information Technologies (FIIT) in Slovak Technical +University in Bratislava (STU). The template was crafted using the for the +[official requirements and conditions, as of December 2025] provided by the faculty, +with [this LaTeX template] being the basis for how the document looks. + +[official requirements and conditions, as of May 2025]: https://www.fiit.stuba.sk/studium/bakalarsky-projekt/bp.html?page_id=1862 +[this LaTeX template]: https://www.overleaf.com/latex/templates/stu-fiit-bachelor-thesis-template-slovak-university-of-technology/pppyykvvhqgq + +**This template also supports the new format of Bachelor's thesis!** + +The template is available in these languages: **Slovak** (sk), **English** (en) + +Theses that already use this template: + +- [Extending a RISC-V processor with bit instructions, Kirill Putiatin] +- [Development of an Adverse Media Screening System using Face Recognition via Existing APIs, Illia Chaban] + +[Extending a RISC-V processor with bit instructions, Kirill Putiatin]: https://opac.crzp.sk/?fn=detailBiblioForm&sid=BBB70232DB8D19E5F026BDDCF3EF +[Development of an Adverse Media Screening System using Face Recognition via Existing APIs, Illia Chaban]: https://opac.crzp.sk/?fn=detailBiblioForm&sid=BBB70232DB8D19E5F027B5DCF3EF + +# Showcase + +Here's a quick look on different template **styles**. You can choose any one of +these styles, it's up to your personal preference. The previews are just for +visual clarity, they are going to be slightly different from the final +documents. + +| `legacy` | `regular` | `compact` | +| ------------- | -------------- | -------------- | +| ![Legacy style of the template, resized to an A6 paper sheet.](/build/legacy1.png) ![Legacy style of the template, resized to an A6 paper sheet.](/build/legacy2.png) | ![Legacy style of the template, resized to an A6 paper sheet.](/build/regular1.png) ![Legacy style of the template, resized to an A6 paper sheet.](/build/regular2.png) | ![Legacy style of the template, resized to an A6 paper sheet.](/build/compact1.png) ![Legacy style of the template, resized to an A6 paper sheet.](/build/compact2.png) | + +# Usage + +You can use [Typst's online editor](https://typst.app/) to edit and display +your thesis. [Sign up](https://typst.app/signup), sign in and click "Start from +template". Search for "vintage-fiit-thesis" and start writing! + +## Building your thesis locally + +1. [Install Typst][typst]. +If you're on Linux, it should be pretty easy. + +[typst]: https://github.com/typst/typst?tab=readme-ov-file#installation + +2. Next, initialize the template using: + +```bash +typst init @preview/vintage-fiit-thesis +``` + +3. Start watching the changes of your thesis using: +```bash +typst watch main.typ --watch +``` + +4. Begin writing your thesis! + +If you're new to Typst, we recommend to start reading the [Typst +tutorial][typst-tutorial]. + +[typst-tutorial]: https://typst.app/docs/tutorial/ + +Don't forget to intialize a Git repository and backup your work somewhere! + +## Cheatsheet + +| Option | Type | Example/Default | Description | Possible values | +| ------------- | -------------- | -------------- | -------------- | -------------- | +| title | `str` | `"Moja záverečná práca"` | thesis title | | +| thesis | enum (`str`) | `"bp2"` | type of your thesis | `"bp1"`, `"bp2"`, `"dp1"`, `"dp2"`, `"dp3"` | +| author | `str` | `"Jožko Mrkvička"` | your name | | +| supervisor | `str` or `dictionary` of `array` | `"prof. Jozef Mrkva, PhD."` | your supervisor | `str` if you have one supervisor, localized `dictionary` if many | +| abstract | `dict` | `( sk: lorem(150), en: lorem(150) )` | abstract in two languages | keys are the language, with `str` as values | +| id | `str` | `"FIIT-12345-123456"` | id from AIS | | +| lang | enum(`str`) | `"en"` | language of your thesis | `"sk"`, `"en"` | +| month | `int` | `5` | month of the hand-in | 1-12 | +| current-date | `datetime` | `datetime.today()` | declaration date and year of the work | | +| acknowledgment | `str` or `none` | `"Omitted"` | thanks at the start of the thesis | | +| assignment | `content` | `none` | see "How to insert the thesis assignment?" | | +| tables-outline | `bool` | `false` | enable tables outline | | +| figures-outline | `bool` | `false` | enable figures outline | | +| abbreviations-outline | `array` | `( ("SSL", "Secure socket layer"), ... )` | list of abbreviations, if you need one | | +| disable-cover | `bool` | `false` | disable cover page (the first one) | | +| style | enum (`str`) | `regular` | select style of the document | `"regular"`, `"legacy"`, `"compact"`, `"pagecount"`, `"legacy-noncompliant"` | + +## Template + +The template supports general customization options. First, you should choose +the language that you are writing this paper in using `lang` argument. +Currently supported languages are listed at the top of this page. If you choose +an unsupported language, the template will generate a compile error. + +Next, you should insert general info for your thesis: `title`, `author`, `id`, +`supervisor`. They are pretty straight-forward, so just write the correct data +into them. `id` is your thesis ID number from the informational system. + +`supervisor` supports two options: either one supervisor's name as a string, +or multiple supervisors with localization. The latter option is achieved using +a localized array of pairs. Example: + +```typst + // ... + supervisor: ( + sk: ( + ("Vedúci práce", "Ing. John Doe"), + ("Fakultný vedúci", "prof. Jozef Mrkva, PhD."), + // ... + ), + en: ( + ("Supervisor", "Ing. John Doe"), + ("Faculty advisor", "prof. Jozef Mrkva, PhD."), + // ... + ), + ), + // ... +``` + +`thesis` selects the type of your work. The allowed values are: `bp1`, `bp2`, +`dp1`, `dp2`, `dp3`. These values control what text is displayed on the title +and cover pages. Sometimes, you might get an error while upgrading your thesis +to the final stage. Pay attention to those errors, as they tell you how exactly +your work should be structured. + +`abstract` is a dictionary of the translated abstracts that you provide with +your work. The keys are the language identifiers, like the `lang` argument. +The values are the abstract text. `en` and `sk` keys are required for thesis +to compile. The template shows an example of how the dictionaries are created +in Typst. + +`acknowledgment` sets the acknowledgment text. You can write anything you want +here. + +`month` lets you select which month you hand in the thesis. For most people +it's May (5), but if you selected the new format with an article, you may need +to choose a different month. Just pick a number and it will automatically +insert the correct month for you. + +`current-date` is Typst's `datetime` that tells when the declaration will be +signed, and which year the thesis is being written. + +`assignment` sets the assignment content. This is the recommended way to +insert your AIS assignment, see "How to insert the thesis assignment?" + +`table-outline` is a boolean, set it to true to enable list of tables. + +`figures-outline` enables list of figures (pictures). + +`abbreviations-outline` is an array of pairs, where each pair contains an +abbreviation and its explanation. If you leave this argument as default or +explicitly empty, the list of abbreviations will not show. + +`disable-cover` lets you disable the first (cover) page of the thesis. That's +it. + +`style` selects the style of the document. The style affects mostly cosmetic +parameters. Here are the possible options: + +- `regular`: the default, inspired by the LaTeX template, embraces the digital format +- `legacy`: fully devoted to imitating the old LaTeX template, virtually no differences +- `compact`: tighter layout with less empty space wasted, useful if your thesis is long +- `pagecount`: apply this one to estimate how many pages of pure text you got +- `legacy-noncompliant`: **don't use this one.** It uses the same citation standard (IEEE) that the old LaTeX template used, but it is not approved by FIIT STU + +## Appendices + +To style the appendices correctly, you need to use a simple `show` rule with a +special function: `section-appendices`. Every heading you put after this will +be considered an appendix and numbered accordingly. You can add nested headings +as usual, they will be numbered and labeled correctly. + +```typst +#show: section-appendices +``` + +To reference the appendix, just use regular Typst referencing. The word +"Appendix" will be inserted automatically with regard to your language of +choice. + +## Resumé + +The resumé chapter is a chapter that is needed only when you write your thesis +in a language other from Slovak. There is a special function for that: +`resume`. Here's how to use it: + +```typst +#resume()[ + #lorem(250) // any resume content should go here +] +``` + +## Assertions + +This template has integrated a few useful assertions that will help you to +remember important points about your thesis. For example, if you forget to +write a resumé and your language is set to English, the assertion will refuse +all compilation attempts. This particular assertion is set only for BP2/DP3. + +The assertion will give you a helpful error message. If for some reason, you +think an assertion is wrong, please open an issue in our GitHub repository. + +## How to hand in the thesis? + +To hand in the thesis, it needs to be separated into two parts, and your thesis +assignment needs to be inserted into the final PDF. + +### How to separate the thesis? + +The file needs to be separated into the main part, and the appendices part. +You can use external tools for that, or settle for Typst compiler arguments. +The `--pages` argument to the CLI compiler can be used to specify which pages +should be rendered for the output. In the examples, we use page 29 as the first +appendix page. + +Here's an example how to split just your main part: + +```bash +typst compile --pages=1-28 main.typ BP_JozkoMrkvicka.pdf +``` + +And your appendices part: + +```bash +typst compile --pages=29- main.typ BP_prilohy_JozkoMrkvicka.pdf +``` + +If you're not using a local Typst setup, use external tools to separate the +thesis into multiple parts. We can recommend `pdfarrange` (GUI) and `pdftk` +(CLI). + +### How to insert the thesis assignment? + +You might notice the warning page in the thesis right after you load the +template. This page can be removed by specifying your thesis assignment. Typst +supports importing PDFs as images as of version `0.14.0`, including the +embedded text. Since version `1.1.0` of this template, you can use `assignment` +option to specify your assignment from AIS. You can download it from the +thesis' page, choose the print option. Assignment should be passed like this: +`assignment: image("topic.pdf")`. Ensure it is exactly one page! If you are +using an older Typst version, you'll have to use external tools to insert the +assignment. + +# Developing + +To develop the template, you should install [Task](https://taskfile.dev/). Here +are the tasks that you can run: + +- `push`: run this before pushing +- `build`: compile the template example +- `watch`: watch the template example +- `open`: open the template example in your system default viewer +- `thumbnail`: compile the template thumbnail +- `install-local`: install the package into @local namespace +- `uninstall-local`: uninstall the package from @local namespace +- `install-preview`: install the package into @preview namespace +- `uninstall-preview`: uninstall the package from @preview namespace + +If you want to help, you can take a look at the GitHub issues in the template +repository. If anything goes wrong, feel free to open a new issue or contact +me directly. + +# Changelog + +### v1.1.0 + +- replaced `muchpdf` assignment rendering with Typst's 0.14 PDF image rendering. Now it is the preferred way to include assignments +- the template now requires Typst 0.14 +- added binding to all styles, as per the new requirements +- chapters now always start on new odd pages, as per the new requirements +- empty pages do not contain page number, as per the new requirements +- fixed annotation localization +- various formatting fixes and compliance improvements (thanks @Ddystopia) + +# Contact + +If you have any questions, feel free to contact me: [Sasetz][sasetz] + +[sasetz]: https://github.com/sasetz/ + diff --git a/packages/preview/vintage-fiit-thesis/1.1.0/_pkgs.typ b/packages/preview/vintage-fiit-thesis/1.1.0/_pkgs.typ new file mode 100644 index 0000000000..3c21cf532e --- /dev/null +++ b/packages/preview/vintage-fiit-thesis/1.1.0/_pkgs.typ @@ -0,0 +1,2 @@ +#import "@preview/hydra:0.6.2" + diff --git a/packages/preview/vintage-fiit-thesis/1.1.0/build/compact1.png b/packages/preview/vintage-fiit-thesis/1.1.0/build/compact1.png new file mode 100644 index 0000000000..ca135c06fc Binary files /dev/null and b/packages/preview/vintage-fiit-thesis/1.1.0/build/compact1.png differ diff --git a/packages/preview/vintage-fiit-thesis/1.1.0/build/compact2.png b/packages/preview/vintage-fiit-thesis/1.1.0/build/compact2.png new file mode 100644 index 0000000000..62660857b1 Binary files /dev/null and b/packages/preview/vintage-fiit-thesis/1.1.0/build/compact2.png differ diff --git a/packages/preview/vintage-fiit-thesis/1.1.0/build/legacy1.png b/packages/preview/vintage-fiit-thesis/1.1.0/build/legacy1.png new file mode 100644 index 0000000000..cfec13df26 Binary files /dev/null and b/packages/preview/vintage-fiit-thesis/1.1.0/build/legacy1.png differ diff --git a/packages/preview/vintage-fiit-thesis/1.1.0/build/legacy2.png b/packages/preview/vintage-fiit-thesis/1.1.0/build/legacy2.png new file mode 100644 index 0000000000..1601b83333 Binary files /dev/null and b/packages/preview/vintage-fiit-thesis/1.1.0/build/legacy2.png differ diff --git a/packages/preview/vintage-fiit-thesis/1.1.0/build/regular1.png b/packages/preview/vintage-fiit-thesis/1.1.0/build/regular1.png new file mode 100644 index 0000000000..19776a7680 Binary files /dev/null and b/packages/preview/vintage-fiit-thesis/1.1.0/build/regular1.png differ diff --git a/packages/preview/vintage-fiit-thesis/1.1.0/build/regular2.png b/packages/preview/vintage-fiit-thesis/1.1.0/build/regular2.png new file mode 100644 index 0000000000..2560eeb617 Binary files /dev/null and b/packages/preview/vintage-fiit-thesis/1.1.0/build/regular2.png differ diff --git a/packages/preview/vintage-fiit-thesis/1.1.0/lib.typ b/packages/preview/vintage-fiit-thesis/1.1.0/lib.typ new file mode 100644 index 0000000000..db8ce00fe9 --- /dev/null +++ b/packages/preview/vintage-fiit-thesis/1.1.0/lib.typ @@ -0,0 +1,656 @@ +#import "pages.typ": * +#import "_pkgs.typ": hydra.hydra +#import "localization.typ": localization + +#let _lang = state("lang") +#let _style = state("style") +#let _appendix-numbering = "A.1" + +#let fiit-thesis( + // title of your thesis + title: "Záverečná práca", + // type of the thesis: "bp1", "bp2", "dp1", "dp2", "dp3" + thesis: "bp2", + // a dictionary of type: : . Both "en" and "sk" are + // mandatory + abstract: ( + sk: lorem(150), + en: lorem(150), + ), // abstract + // your full name + author: "Jožko Mrkvička", + // ID that you copied from AIS + id: "FIIT-12345-123456", + // full name of your thesis supervisor + supervisor: "prof. Jozef Mrkva, PhD.", + // supported values: "en", "sk" + lang: "en", + // month of the hand-in + month: 5, + // current date for declaration and year of handing-in + current-date: datetime.today(), + // acknowledgment text + acknowledgment: none, + // assignment from AIS file path. + assignment: none, + // enable list of tables + tables-outline: false, + // enable list of images (figures) + figures-outline: false, + // if this array is empty, the list of abbreviations does not appear + abbreviations-outline: (), + // set to "true" to disable the first (cover) sheet + disable-cover: false, + // style of the thesis + // options: "regular", "compact", "legacy", "legacy-noncompliant", + // "pagecount" + style: "regular", + body, +) = { + //////////////////////////////// + // style handling + let is-legacy = style == "legacy" or style == "legacy-noncompliant" + + // regular style + let text-size = 1.1em + let page-margins = 3cm + let bibliography-style = "iso-690-numeric" + let use-binding = true + let regular-headings = true + + let first-line-indent = 1em + let leading = 1.3em + let spacing = 1.5em + let footer-descent = 30% + 0pt + let header-ascent = 30% + 0pt + let header-margin = if is-legacy { -1.6em } else { -1em } + let header = context { + let hdr = hydra(1) + if hdr != none and style != "pagecount" { + if is-legacy { + hydra( + display: (_, current-heading) => if current-heading.numbering + != none { + current-heading.supplement + [ ] + numbering( + current-heading.numbering, + counter(heading).at(current-heading.location()).at(0), + ) + [. ] + current-heading.body + } else { + current-heading.body + }, + skip-starting: false, + ) + } else { + emph(hdr) + } + v(header-margin) + line(length: 100%) + } + } + let footer-with-bound-numbering = context { + let (n,) = counter(page).get() + set align(if calc.even(n) { left } else { right }) + if page.numbering != none { counter(page).display(page.numbering) } + } + + if style == "compact" { + page-margins = 2.5cm + regular-headings = false + leading = 0.8em + spacing = 1.5em + text-size = 1.2em + } else if is-legacy { + // general legacy styles + page-margins = ( + inside: 1.5in, + outside: 1in, + top: 1.5in, + bottom: 2in, + ) + use-binding = true + first-line-indent = 0em + leading = 1.1em + spacing = 2em + footer-descent = 2em + header-ascent = 2em + } else if style == "pagecount" { + leading = 1.2em + spacing = leading + first-line-indent = 0em + } + + if style == "legacy-noncompliant" { + bibliography-style = "ieee" + } + + //////////////////////////////// + // locale + let locale = localization(lang: lang) + let slovak = localization(lang: "sk") + let english = localization(lang: "en") + _lang.update(lang) + _style.update(style) + + assert( + type(month) == int and month >= 1 and month <= 12, + message: "Month should be an integer between 1 and 12", + ) + month = month - 1 // convert to array index + + //////////////////////////////// + // pagecount handling + show pagebreak: it => if style == "pagecount" { none } else { it } + show bibliography: it => if style == "pagecount" { none } else { it } + show outline: it => if style == "pagecount" { none } else { it } + show figure: it => if style == "pagecount" { none } else { it } + show colbreak: it => if style == "pagecount" { none } else { it } + + show list.item: it => if style == "pagecount" { it.body } else { it } + show list: it => if style == "pagecount" { it.body } else { it } + show columns: it => if style == "pagecount" { it.body } else { it } + show align: it => if style == "pagecount" { it.body } else { it } + + //////////////////////////////// + // page setup + + set document(author: author, title: title) + set text(font: "New Computer Modern", lang: lang) + show math.equation: set text(weight: 400) + set bibliography(style: bibliography-style, title: locale.bibliography) + + //////////////////////////////// + // setup headings + set heading(numbering: "1.1", supplement: locale.chapter.title) + show heading: it => block({ + if style != "pagecount" { + if style != "compact" { + set text(1.1em, weight: "semibold") + numbering(it.numbering, ..counter(heading).at(it.location())) + h(0.3cm) + it.body + v(0.2cm) + } else { + it + } + } + }) + show heading.where(level: 1): it => { + if style == "pagecount" { + return + } + if regular-headings { + // regular, legacy and legacy-noncompliant + set text(1.6em, weight: if is-legacy { "medium" } else { "bold" }) + set par(first-line-indent: 0em) + + { + set page(header: none, numbering: none) + pagebreak(to: if use-binding { "odd" } else { none }, weak: true) + } + if counter(heading).get().at(0) == 1 { + counter(page).update(1) + } + if it.numbering == _appendix-numbering { + counter(page).update(1) + } + pagebreak(weak: true) + block(height: 2.8cm) + if it.numbering != none { + [#it.supplement #numbering(it.numbering, counter(heading).get().at(0))] + v(0cm) + } + it.body + v(.4cm) + } else { + // compact + pagebreak(to: "odd", weak: true) + if it.numbering == _appendix-numbering { + counter(page).update(1) + } + pagebreak(weak: true) + if it.numbering != none { + it.supplement + [ ] + numbering(it.numbering, counter(heading).get().at(0)) + } + linebreak() + it.body + linebreak() + v(.5cm) + } + } + + //////////////////////////////// + // figures + let figure-supplement(the-figure) = { + if the-figure.func() == raw { + locale.figures.raw + } else if the-figure.func() == table { + locale.figures.table + } else { + locale.figures.figure + } + } + set figure(supplement: figure-supplement) + + //////////////////////////////// + // title page localization + let fields = locale.title-page.fields + let values = locale.title-page.values + + //////////////////////////////// + // process potential multiple supervisors + let supervisors-sk = () + let supervisors-en = () + if type(supervisor) == str { + supervisors-sk = ( + ( + left: if thesis.starts-with("bp") { + slovak.title-page.fields.supervisor-bachelors + } else { slovak.title-page.fields.supervisor-masters }, + right: supervisor, + ), + ) + supervisors-en = ( + ( + left: if thesis.starts-with("bp") { + english.title-page.fields.supervisor-bachelors + } else { english.title-page.fields.supervisor-masters }, + right: supervisor, + ), + ) + } else if type(supervisor) == dictionary { + for pair in supervisor.sk { + supervisors-sk.push((left: pair.at(0), right: pair.at(1))) + } + for pair in supervisor.en { + supervisors-en.push((left: pair.at(0), right: pair.at(1))) + } + } + // localized supervisors + let supervisor-footer = if lang == "en" { supervisors-en } else { + supervisors-sk + } + + //////////////////////////////// + // cover sheet + if not disable-cover and style != "pagecount" { + title-page( + id: id, + author: author, + title: title, + type: values.thesis.at(thesis), + header: [ + #locale.university \ + #locale.faculty + ], + footer: supervisor-footer, + date: [#values.month.at(month) #current-date.display("[year]")], + ) + pagebreak(to: if use-binding { "odd" } else { none }, weak: true) + } + counter(page).update(1) + //////////////////////////////// + // title page + if style != "pagecount" { + title-page( + id: id, + author: author, + title: title, + type: values.thesis.at(thesis), + header: [ + #locale.university \ + #locale.faculty + ], + footer: ( + (left: fields.program, right: values.program.informatics), + (left: fields.field, right: values.field.informatics), + (left: fields.department, right: values.department.upai), + ..supervisor-footer, + ), + date: [#values.month.at(month) #current-date.display("[year]")], + ) + } + + // intentional blank page + pagebreak(to: if use-binding { "odd" } else { none }) + + //////////////////////////////// + // AIS assignment + assert( + assignment == none or type(assignment) == content, + message: "For final stage of your thesis, please provide an assignment PDF file as `image(\"my.pdf\")`.", + ) + if style != "pagecount" and assignment == none { + page( + fill: tiling(size: (40pt, 40pt))[ + #place(line(start: (0%, 0%), end: (100%, 100%), stroke: 2pt + red)) + ], + )[ + #set text(30pt) + #set par(justify: true) + Don't forget to replace this page with your AIS assignment PDF by + specifying `image("assignment.pdf")` into `assignment` argument of the + template! Be careful, the assignment should be in PDF format, not just + an image. + + Typst 0.14 supports inserting PDFs with embedded text! + ] + } else if style != "pagecount" { + set page(margin: 0em) + assignment + } + pagebreak() + pagebreak() // intentional blank page + + //////////////////////////////// + // cestne vyhlasenie + if style != "pagecount" { + v(1fr) + text(1.1em)[ + Čestne vyhlasujem, že som túto prácu vypracoval(a) samostatne, na základe + konzultácií a s použitím uvedenej literatúry. + #v(1.5em) + // TODO: replace this with an appropriate Slovak date + #grid( + columns: (4fr, 3fr), + rows: 2, + gutter: 3pt, + align: (left, center), + row-gutter: .8em, + grid.cell( + rowspan: 2, + align: start, + current-date.display("V Bratislave, [day].[month].[year]"), + ), + repeat("."), + author, + ) + ] + } + pagebreak() + pagebreak() // intentional blank page + + //////////////////////////////// + // acknowledgment + if style != "pagecount" and acknowledgment != none { + v(1fr) + par(text(1.5em)[ *#locale.acknowledgment* ]) + text(1.1em)[ + #acknowledgment + #v(1.5em) + ] + pagebreak() + pagebreak() // intentional blank page + } + + //////////////////////////////// + // even if the language is Slovak, the university requires students to provide + // both versions of the abstract + + //////////////////////////////// + // slovak abstract + if style != "pagecount" { + abstract-page( + title: slovak.annotation.title, + university: slovak.university, + faculty: slovak.faculty, + program: ( + left: slovak.title-page.fields.program, + right: slovak.title-page.values.program.informatics, + ), + author: (left: slovak.annotation.author, right: author), + thesis: (left: slovak.title-page.values.thesis.at(thesis), right: title), + supervisor: supervisors-sk, + date: [#slovak.title-page.values.month.at(month) #( + current-date.display("[year]") + )], + abstract.sk, + ) + } + pagebreak() // intentional blank page + + //////////////////////////////// + // english abstract + if style != "pagecount" { + abstract-page( + title: english.annotation.title, + university: english.university, + faculty: english.faculty, + program: ( + left: english.title-page.fields.program, + right: english.title-page.values.program.informatics, + ), + author: (left: english.annotation.author, right: author), + thesis: (left: english.title-page.values.thesis.at(thesis), right: title), + supervisor: supervisors-en, + date: [#english.title-page.values.month.at(month) #( + current-date.display("[year]") + )], + abstract.en, + ) + } + + pagebreak() // intentional blank page + + //////////////////////////////// + // table of contents + set par( + first-line-indent: first-line-indent, + justify: true, + leading: leading, + spacing: spacing, + ) + set page( + numbering: "i", + number-align: center, + margin: page-margins, + header: header, + footer-descent: footer-descent, + header-ascent: header-ascent, + footer: footer-with-bound-numbering, + ) // Roman numbering until the end of the contents + set text( + size: text-size, + ) + show outline.entry.where( + level: 1, + ): it => { + if it.element.func() == heading { + // outline entry for the contents + set block(above: 1.8em) + show text: it => strong(it) + link( + it.element.location(), + it.indented(it.prefix(), [#it.body()#h(1fr)#it.page()]), + ) + } else { + // outline entry for lists of figures + link( + it.element.location(), + it.indented(strong(it.prefix()), it.inner()), + ) + } + } + show outline.entry: set block(above: 1.2em) + outline(title: locale.contents.title, depth: 3, indent: auto) + if figures-outline { + outline(title: locale.contents.figures, target: figure.where(kind: image)) + } + if tables-outline { + outline(title: locale.contents.tables, target: figure.where(kind: table)) + } + if abbreviations-outline.len() > 0 and style != "pagecount" { + list-of-abbreviations( + title: locale.contents.abbreviations, + abbreviations: abbreviations-outline, + use-binding: use-binding, + ) + } + set page(numbering: none, margin: page-margins) + v(1fr) // if the page is full, this will be a pagebreak + pagebreak(weak: true) // if the page is not full, this will be a pagebreak + counter(page).update(1) // start of the main section + + //////////////////////////////// + // main body + set par( + first-line-indent: first-line-indent, + justify: true, + leading: leading, + spacing: spacing, + ) + set page( + numbering: "1", + number-align: center, + margin: page-margins, + header: header, + footer-descent: footer-descent, + header-ascent: header-ascent, + footer: footer-with-bound-numbering, + ) + + //////////////////////////////// + // assertions + context if thesis == "bp2" or thesis == "dp3" { + // resume and plan of work are mandatory for the final theses + let resume = query( + heading.where(level: 1).and(), + ) + let plan-of-work = query( + heading.where(level: 1).and(), + ) + assert( + resume.len() == 1 and resume.at(0).numbering == none or lang == "sk", + message: "Could not find label in your work. Please create a resume chapter in Slovak and mark it with the label.", + ) + assert( + lang != "sk" or resume.len() == 0, + message: "Theses in Slovak should not have a resume. If for some reason you need to have it, remove the label from its heading.", + ) + assert( + plan-of-work.len() == 1, + message: "Could not find label in your work. Please create a plan of work appendix and mark it with the label.", + ) + assert( + plan-of-work.at(0).numbering == _appendix-numbering, + message: "The plan of work ( label) should be an appendix. Check if its numbering is right, did you forget to use `#show: section-appendices.with()`?", + ) + } + assert( + abstract.keys().contains("sk") and abstract.keys().contains("en"), + message: "Please provide an abstract in both Slovak and English language", + ) + assert( + locale.title-page.values.thesis.keys().contains(thesis), + message: "The thesis type you provided is not supported. Please contact the authors or choose one of the supported types", + ) + if type(supervisor) != str { + assert( + type(supervisor) == dictionary, + message: "Please provide correct supervisor argument: either a string, or localized array of pairs (\"position\", \"name\").", + ) + assert( + supervisor.keys().len() == 2 + and supervisor.keys().contains("sk") + and supervisor.keys().contains("en") + and type(supervisor.sk) == array + and type(supervisor.en) == array, + message: "Please provide correct localization dictionary. Example: `(sk: , en: )`", + ) + assert( + supervisor.sk.len() == supervisor.en.len(), + message: "Supervisor localizations don't match! Number of supervisors differs in localizations.", + ) + for pair in supervisor.sk + supervisor.en { + assert( + type(pair) == array, + message: "Please provide correct supervisor argument: one or more pairs are not arrays. + Tip: if you have only one pair in the array, add a comma (,) after that element. Example: `supervisor: ((\"a\", \"b\"),)`", + ) + assert( + pair.len() == 2, + message: "Please provide correct supervisor argument: one or more pairs do not have exactly 2 elements.", + ) + assert( + type(pair.at(0)) == str and type(pair.at(1)) == str, + message: "Please provide correct supervisor argument: one or more pairs contain elements that are not strings.", + ) + } + } + + assert( + type(abbreviations-outline) == array, + message: "Please provide correct abbreviations-outline argument: either a string, or an array of pairs (\"abbreviation\", \"explanation\").", + ) + for pair in abbreviations-outline { + assert( + type(pair) == array, + message: "Please provide correct abbreviations-outline argument: one or more pairs are not arrays. + Tip: if you have only one pair in the array, try to add a comma (,) after that element. Example: `abbreviations-outline: ((\"a\", \"b\"),)`", + ) + assert( + pair.len() == 2, + message: "Please provide correct abbreviations-outline argument: one or more pairs do not have exactly 2 elements.", + ) + assert( + (type(pair.at(0)) == str or type(pair.at(0)) == content) + and (type(pair.at(1)) == str or type(pair.at(1)) == content), + message: "Please provide correct abbreviations-outline argument: one or more pairs contain elements that are not strings or content.", + ) + } + assert( + type(style) == str + and ( + style == "regular" + or style == "compact" + or style == "legacy" + or style == "legacy-noncompliant" + or style == "pagecount" + ), + message: "Please provide correct style of your thesis, possible options are: \"regular\", \"compact\", \"legacy\", \"legacy-noncompliant\" and \"pagecount\".", + ) + + body +} + +// functions that are used in the thesis + +#let section-appendices(body) = { + let appendix-page-numbering(first, ..) = [ + // here, we don't need the `context` block. If we introduce it, it's going + // to make outline entries dirty: it will assume that we need to use + // current context, instead of the chapter's context + #numbering(_appendix-numbering, counter(heading).get().at(0))-#first + ] + set page(numbering: appendix-page-numbering) + // get the supplement from state + // since getting a state value requires context, wrap the supplement into a + // function + set heading(numbering: _appendix-numbering, supplement: context { + let locale = localization(lang: _lang.get()) + if _style.get() == "legacy" or _style.get() == "legacy-noncompliant" { + locale.legacy-appendix + } else { locale.appendix } + }) + counter(heading).update(0) + // appendices don't add up to page count + show text: it => context if _style.get() == "pagecount" { none } else { it } + body +} + +#let resume(body) = { + pagebreak() + context { + let locale = localization(lang: _lang.get()) + set heading(numbering: none) + [ + = Resumé + ] + } + body +} diff --git a/packages/preview/vintage-fiit-thesis/1.1.0/localization.typ b/packages/preview/vintage-fiit-thesis/1.1.0/localization.typ new file mode 100644 index 0000000000..9af81a62d5 --- /dev/null +++ b/packages/preview/vintage-fiit-thesis/1.1.0/localization.typ @@ -0,0 +1,146 @@ +#let literals = ( + en: ( + university: "Slovak Technical University in Bratislava", + faculty: "Faculty of Informatics and Information Technologies", + title-page: ( + fields: ( + program: "Programme", + field: "Study field", + department: "Department", + supervisor-bachelors: "Supervisor", + supervisor-masters: "Supervisor", + ), + values: ( + month: ( + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December", + ), + thesis: ( + bp2: "Bachelor's thesis", + dp3: "Master's thesis", + bp1: "Interim report on BP1", + dp1: "Interim report on DP1", + dp2: "Interim report on DP2", + ), + program: ( + informatics: "Informatics", + ), + field: ( + informatics: "Informatics", + ), + department: ( + upai: "Institute of Computer Engineering and Applied Informatics", + iise: "Institute of Informatics, Information Systems and Software Engineering", + ), + ), + ), + annotation: ( + title: "Annotation", + author: "Author", + ), + acknowledgment: "Acknowledgment", + contents: ( + title: "Contents", + tables: "List of tables", + figures: "List of figures", + abbreviations: "List of abbreviations", + ), + chapter: ( + title: "Chapter", + ), + figures: ( + raw: "Listing", + table: "Table", + figure: "Figure", + ), + appendix: "Appendix", + legacy-appendix: "Appendix", + bibliography: "Bibliography", + ), + sk: ( + university: "Slovenská technická univerzita v Bratislave", + faculty: "Fakulta informatiky a informačných technológií", + title-page: ( + fields: ( + program: "Študijný program", + field: "Študijný odbor", + department: "Miesto vypracovania", + supervisor-bachelors: "Vedúci bakalárskej práce", + supervisor-masters: "Vedúci diplomovej práce", + ), + values: ( + month: ( + "Január", + "Február", + "Marec", + "Apríl", + "Máj", + "Jún", + "Júl", + "August", + "September", + "Október", + "November", + "December", + ), + thesis: ( + bp2: "Bakalárska práca", + dp3: "Diplomová práca", + bp1: "Priebežná správa o riešení BP1", + dp1: "Priebežná správa o riešení DP1", + dp2: "Priebežná správa o riešení DP2", + ), + program: ( + informatics: "Informatika", + ), + field: ( + informatics: "Informatika", + ), + department: ( + upai: "Ústav informatiky, informačných systémov a softvérového inžinierstva", + iise: "Ústav počítačového inžinierstva a aplikovanej informatiky", + ), + ), + ), + annotation: ( + title: "Anotácia", + author: "Autor", + ), + acknowledgment: "Poďakovanie", + contents: ( + title: "Obsah", + tables: "Zoznam tabuliek", + figures: "Zoznam obrázkov", + abbreviations: "Zoznam použitých skratiek", + ), + chapter: ( + title: "Kapitola", + ), + figures: ( + raw: "Výpis", + table: "Tabuľka", + figure: "Obrázok", + ), + appendix: "Príloha", + legacy-appendix: "Dodatok", + bibliography: "Literatúra", + ), +) + +#let localization(lang: "sk") = { + assert( + lang == "en" or lang == "sk", + message: "please select a valid language for localization to work", + ) + return literals.at(lang) +} diff --git a/packages/preview/vintage-fiit-thesis/1.1.0/pages.typ b/packages/preview/vintage-fiit-thesis/1.1.0/pages.typ new file mode 100644 index 0000000000..86f9a59e6b --- /dev/null +++ b/packages/preview/vintage-fiit-thesis/1.1.0/pages.typ @@ -0,0 +1,144 @@ +#import "_pkgs.typ": hydra.hydra + +#let abstract-page( + title: "Anotácia", + university: "Slovenská technická univerzita v Bratislave", + faculty: "Fakulta informatiky a informačných technológií", + program: (left: "Študijný program", right: "Informatika"), + author: (left: "Autor", right: "Jožko Mrkvička"), + thesis: (left: "Záverečná práca", right: "Téma záverečnej práce"), + supervisor: ( + (left: "Vedúci bakalárskeho projektu", right: "prof. Jožko Mrkvička"), + ), + date: "Máj 2025", + abstract, +) = { + set text(1.1em) + v(1fr) + + par(text(1.5em, weight: 700, title)) + + text(university) + linebreak() + text(upper(faculty)) + linebreak() + text([#program.left: #program.right]) + linebreak() + v(1.5em) + + text([#author.left: #author.right]) + linebreak() + text([#thesis.left: #thesis.right]) + linebreak() + for pair in supervisor { + text([#pair.left: #pair.right]) + linebreak() + } + text(date) + v(1.5em) + + set par(justify: true) + abstract + + v(1fr) + pagebreak() +} + +#let title-page( + header: [ + Slovenská technická univerzita v Bratislave \ + Fakulta informatiky a informačných technológií + ], + id: "FIIT-12345-123456", + author: "Jožko Mrkvička", + title: "Téma záverečnej práce", + type: "Záverečná práca", + date: "Máj 2025", + footer: ( + (left: "Študijný program", right: "Informatika"), + (left: "Študijný odbor", right: "Informatika"), + ( + left: "Miesto vypracovania", + right: "Ústav počítačového inžinierstva a aplikovanej informatiky", + ), + (left: "Vedúci práce", right: "Jožko Mrkvička"), + ), +) = { + // top header + align( + center, + text(1.3em, header), + ) + // ID display + pad( + top: 1.2em, + align( + center, + text(1.3em, id), + ), + ) + + v(15em, weak: false) + + // author information + pad( + top: 0.7em, + align( + center, + text(1.1em, author), + ), + ) + // title of the paper + v(1.2em, weak: false) + align( + center, + text(1.3em, title), + ) + // type of the paper + v(1.2em, weak: false) + align( + center, + text(1.2em, type), + ) + + // other data goes to the bottom + v(1fr, weak: false) + grid( + columns: (auto, 1fr), + row-gutter: 1.2em, + ..( + footer + .map(it => ( + text(1.1em, [#it.left:]), + align(end + top, text(1.1em, it.right)), + )) + .flatten() + ) + ) + + text(1.1em, date) + pagebreak() +} + +#let list-of-abbreviations( + title: "List of Abbreviations", + abbreviations: ("SSL", "Secure socket layer"), + use-binding: false, +) = { + heading(title, numbering: none, outlined: false) + grid( + columns: (auto, 1fr), + column-gutter: 5em, + row-gutter: 1.4em, + ..abbreviations + .map( + it => ( + strong(it.at(0)), + it.at(1), + ), + ) + .flatten() + ) + pagebreak() +} + diff --git a/packages/preview/vintage-fiit-thesis/1.1.0/template/citations.bib b/packages/preview/vintage-fiit-thesis/1.1.0/template/citations.bib new file mode 100644 index 0000000000..94d9f2dcd8 --- /dev/null +++ b/packages/preview/vintage-fiit-thesis/1.1.0/template/citations.bib @@ -0,0 +1,9 @@ +@manual{riscv, + title = {The RISC-V Instruction Set Manual Volume I: Unprivileged ISA}, + author = {RISC-V Foundation}, + organization = {RISC-V International}, + year = {2019}, + note = {Version 20191213}, + url = {https://riscv.org/specifications/}, +} + diff --git a/packages/preview/vintage-fiit-thesis/1.1.0/template/main.typ b/packages/preview/vintage-fiit-thesis/1.1.0/template/main.typ new file mode 100644 index 0000000000..468dded1d6 --- /dev/null +++ b/packages/preview/vintage-fiit-thesis/1.1.0/template/main.typ @@ -0,0 +1,114 @@ +#import "@preview/vintage-fiit-thesis:1.1.0": * + +#show: fiit-thesis.with( + title: "Moja záverečná práca", + thesis: "bp2", + author: "Jožko Mrkvička", + supervisor: "prof. Jozef Mrkva, PhD.", + abstract: ( + sk: lorem(150), + en: lorem(150), + ), // abstract + id: "FIIT-12345-123456", + lang: "sk", // this controls how the layout is presented, be careful! + // remove the argument or made the value none to hide + acknowledgment: [I would like to thank my supervisor for all the help and + guidance I have received. I would also like to thank my friends and family + for supporting during this work.], + // remove the argument or leave the array empty to hide the list of + // abbreviations + abbreviations-outline: ( + ("SSL", "Secure socket layer"), + ("RISC", "Reduced instruction set computer"), + ("ISA", "Instruction set architecture"), + ), + figures-outline: true, + tables-outline: true, + style: "legacy", +) + += Introduction + +#lorem(110) + +#lorem(100) + +#lorem(100) + +#lorem(120) + += Analysis + +== Intro to analysis + +#lorem(250) + +#figure( + caption: [Imagine here FIIT logo in SVG file format for reference.], + pad( + 2em, + block(fill: color.aqua, width: 200pt, height: 100pt, radius: 15pt), + ), +) + +#lorem(150) + += Implementation + +#lorem(250) + +#figure( + caption: [This is an example of a code listing in your thesis.], + [```c + int main() + { + printf("Hello World!\n"); + return 0; + } + ```], +) + +== Citation example + +This is an example of how to reference a paper in your thesis @riscv. +Appendices are the chapters that come at the end, you can reference them too! +Here's an example: the source code for this project is recorded in +@source-code. + +#lorem(150) + +#figure( + caption: [This is an example of a table that you can create using Typst.], + table( + columns: 2, + table.header([*Left column*], [*Right column*]), + [Some label], [Some data], + [Another label], [Another data], + ), +) + +#lorem(200) + +== Another subject + +#lorem(100) + +// has the right format, goes before appendices +#bibliography("citations.bib") +#pagebreak(weak: true) + +// #resume()[ +// #lorem(250) +// ] + +// start the appendices section with this line +#show: section-appendices + += Source code + +#lorem(150) + += Plan of work + +#pagebreak() + diff --git a/packages/preview/vintage-fiit-thesis/1.1.0/thumbnail.png b/packages/preview/vintage-fiit-thesis/1.1.0/thumbnail.png new file mode 100644 index 0000000000..b9a1332ba1 Binary files /dev/null and b/packages/preview/vintage-fiit-thesis/1.1.0/thumbnail.png differ diff --git a/packages/preview/vintage-fiit-thesis/1.1.0/typst.toml b/packages/preview/vintage-fiit-thesis/1.1.0/typst.toml new file mode 100644 index 0000000000..c751f9574b --- /dev/null +++ b/packages/preview/vintage-fiit-thesis/1.1.0/typst.toml @@ -0,0 +1,17 @@ +[package] +name = "vintage-fiit-thesis" +version = "1.1.0" +entrypoint = "lib.typ" +authors = ["Sasetz "] +license = "MIT-0" +description = "Bachelor's or master's thesis at Faculty of Informatics and Information Technologies (FIIT), STU" +repository = "https://github.com/sasetz/fiit_template" +keywords = ["fiit", "stu"] +categories = ["thesis"] +disciplines = ["education"] +exclude = ["/build/*"] + +[template] +path = "template" +entrypoint = "main.typ" +thumbnail = "thumbnail.png"