-
Notifications
You must be signed in to change notification settings - Fork 1.2k
clean-ut:0.1.0 #5221
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
clean-ut:0.1.0 #5221
Changes from all commits
f69e5ea
ac0b720
6ee5c95
19d735f
6a6d49e
acdad4e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| MIT License | ||
|
|
||
| Copyright (c) 2026 Elias Riedling | ||
|
|
||
| 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, subject to the following conditions: | ||
|
|
||
| The above copyright notice and this permission notice shall be included in all | ||
| copies or substantial portions of the Software. | ||
|
|
||
| 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. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| # Typst thesis templates for bachelor and master thesis | ||
|
|
||
| This template is designed to write final theses in the field of life sciences with a clean look, offering 1) the automatic generation of a two-column bibliography 2) automatic subfigure-numbering and 3) allows for the display of short captions for figures in the outline. The biggest downside of this template yet is its pre-defined customization of text, tables, figures... which make this template less flexible. But you are of course free to make changes anytime :) | ||
| The first two pages are generated for the University Tübingen, feel free to change them, too. | ||
|
|
||
| ## Disclaimer | ||
|
|
||
| - This thesis is not official and does not represent the University of Tübingen in any way | ||
| - This is a template and does not have to meet the exact requirements of your university. Check what your thesis should look like! | ||
| - The thesis is currently only supported in English | ||
|
|
||
| ## Custom functions | ||
|
|
||
| The caption-function is a slight modification of the original caption of figures: | ||
|
|
||
| ```typ | ||
| #figure(.., caption: [#caption[short description][more details]]) | ||
|
Check warning on line 17 in packages/preview/clean-ut/0.1.0/README.md
|
||
| ``` | ||
| This will display the short description in the outline of figures and will show the original figure caption as: | ||
|
|
||
| **Figure X: short description.** more details | ||
|
|
||
| Furthermore, the TODO-function is a small QoL-improvement, allowing for highlighting text for later editing: | ||
|
|
||
| ```typ | ||
| #todo[text] | ||
| ``` | ||
|
|
||
| Finally, the custom subfigure-function automatically numbers the subfigures with A,B,C... above the top-left corner of the figure: | ||
|
|
||
| ```typ | ||
| #subfig-grid(columns: 2, | ||
| figure(.., caption: []), | ||
|
Check warning on line 33 in packages/preview/clean-ut/0.1.0/README.md
|
||
| figure(.., caption: []), | ||
|
Check warning on line 34 in packages/preview/clean-ut/0.1.0/README.md
|
||
| .., | ||
|
Check warning on line 35 in packages/preview/clean-ut/0.1.0/README.md
|
||
| caption: [caption describing the whole figure, including subfigures]) | ||
| ``` | ||
|
|
||
| Note that this does **not** allow for captioning of the subfigures directly (this will look ugly), but instead requires a description of subfigures in the total figure caption (as it is usual in the life sciences) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,201 @@ | ||
| #import "@preview/subpar:0.2.2" | ||
| #import "@preview/hydra:0.6.2": hydra | ||
|
|
||
| #let in-outline = state("in-outline", false) | ||
|
|
||
| //custom caption function to show the short version in the outline and the long version in the figure | ||
| #let caption(short, details) = context { | ||
| if in-outline.get() { | ||
| short | ||
| } else { | ||
| [#strong(short). #details] | ||
| } | ||
| } | ||
|
|
||
| // todo helper | ||
| #let todo(stuff) = text(weight: "bold", fill: red, [TODO: ] + stuff) | ||
|
|
||
| // numbered subfigure grid | ||
| #let subfig-grid(..args) = subpar.grid( | ||
| align: top + start, | ||
| numbering-sub: "A", | ||
| numbering-sub-ref: (..nums) => numbering("1A", ..nums), | ||
| show-sub-caption: (num, it) => { | ||
| set text(size: 1.5em) //big numeration | ||
| // subcaption numbering | ||
| text(weight: "bold", num) | ||
| // it.separator | ||
| // subcaption body | ||
| it.body | ||
| }, | ||
| show-sub: it => { | ||
| set figure.caption(position: top) | ||
| it | ||
| }, | ||
| ..args, | ||
| ) | ||
|
|
||
| //numbered subfigure grid, special attachment numbering | ||
| #let subfig-grid-attachments(..args) = subpar.grid( | ||
| align: top + start, | ||
| numbering-sub: "A", | ||
| numbering-sub-ref: (..nums) => numbering("S1A", ..nums), | ||
| show-sub-caption: (num, it) => { | ||
| set text(size: 1.5em) //big numeration | ||
| // subcaption numbering | ||
| text(weight: "bold", num) | ||
| // it.separator | ||
| // subcaption body | ||
| it.body | ||
| }, | ||
| show-sub: it => { | ||
| set figure.caption(position: top) | ||
| it | ||
| }, | ||
| ..args, | ||
| ) | ||
|
|
||
| // shorthand for the upright mu letter | ||
| #let upmu = [~$upright(mu)$] | ||
|
|
||
| //--------------Function to show outline, list of figures, list of tables and list of abbreviations | ||
| #let outlines = { | ||
| //----Table of Contents | ||
| //heading level 1 bold | ||
| page(numbering: "I")[ | ||
| #show outline.entry.where(level: 1): it => { | ||
| set text(1.2em, weight: "bold") | ||
| v(1.5em, weak: true) | ||
| it | ||
| } | ||
|
|
||
| #heading([Table of Contents], numbering: none, outlined: false) | ||
| #v(0.5em) | ||
| #outline(title: none, depth: 3) | ||
| ] | ||
| pagebreak() | ||
|
|
||
| // ONLY SHOW SHORT CAPTION IN OUTLINE | ||
| show outline: it => { | ||
| in-outline.update(true) | ||
| it | ||
| in-outline.update(false) | ||
| } | ||
|
|
||
| show outline.entry: it => link( | ||
| it.element.location(), | ||
| it.indented(strong(it.prefix()), it.inner()), | ||
| ) | ||
|
|
||
| //---------List of Images | ||
| page(numbering: "I")[ | ||
| #heading([List of Images], numbering: none) | ||
| #v(0.5em) | ||
| #outline(title: none, target: figure.where(kind: image)) | ||
| ] | ||
| pagebreak() | ||
|
|
||
| //---------List of Tables | ||
| page(numbering: "I")[ | ||
| #heading([List of Tables], numbering: none) | ||
| #v(0.5em) | ||
| #outline(title: none, target: figure.where(kind: table)) | ||
| ] | ||
| pagebreak() | ||
|
|
||
| show link: it => strong(text(blue, it)) | ||
| } | ||
|
|
||
| //==========================Header design========================= | ||
| #let page-header = { | ||
| set page( | ||
| header: [ | ||
| #set text(size: 12pt) | ||
| //displayed smart heading level one im document header | ||
| #context { strong(hydra(1, skip-starting: false, use-last: true)) } | ||
| #h(1fr) | ||
| #context { strong(counter(page).display()) } | ||
| #v(-0.9em) #line(length: 100%) | ||
| ], | ||
| ) | ||
| } | ||
|
|
||
| // ===========================Template================================ | ||
| #let template = { | ||
| [ | ||
|
|
||
| //=========================Page formatting============================ | ||
| #set page( | ||
| margin: (x: 2.5cm, y: 2.5cm), | ||
| paper: "a4", | ||
| ) | ||
|
|
||
| // blocksatz | ||
| #set par(justify: true, linebreaks: "optimized") | ||
|
|
||
| #set heading(numbering: "1.1.1.a.") | ||
|
|
||
| #set text( | ||
| font: "TeX Gyre Heros", //Helvetica | ||
| lang: "en", | ||
| hyphenate: true, | ||
| size: 12pt, | ||
| ligatures: false, | ||
| region: "US", | ||
| ) | ||
|
|
||
| //===================show rules================================ | ||
|
|
||
| #show heading: it => text(hyphenate: false, it) | ||
|
|
||
| //figure caption left-aligned | ||
| #show figure.caption: set align(start) | ||
|
|
||
| //figure supplement bold, text 10pt | ||
| #show figure.caption: it => context box( | ||
| inset: (left: 1.4em, right: 1.4em), | ||
| align(left)[#text(size: 10pt)[ | ||
| *#it.supplement~#it.counter.display()#it.separator*#it.body | ||
| ]], | ||
| ) | ||
| #set image(fit: "contain", scaling: "smooth") | ||
|
|
||
| #show figure.where(kind: image): set text(size: 10pt) | ||
|
|
||
| //-------------------------table design----------------------- | ||
| #show table.cell.where(y: 0): strong //first table line *bold* | ||
| #set table( | ||
| stroke: (x, y) => ( | ||
| left: if x > 0 { 0.7pt }, | ||
| top: if y == 0 { 1.0pt }, | ||
| bottom: if y == 0 { 0.7pt }, | ||
| ), | ||
| align: (x, y) => center + horizon, | ||
| ) | ||
| #set table.hline(stroke: 0.7pt) | ||
| //caption above table | ||
| #show figure.where(kind: table): set figure.caption(position: top) | ||
|
|
||
| // ------------------------------------------------------------- | ||
|
|
||
| // footnotes definieren | ||
| #set footnote.entry(gap: 0.6em, indent: 0em) | ||
|
|
||
| // references bold and blue | ||
| #show ref: it => strong(text(fill: blue, it)) | ||
| #show link: set text(hyphenate: false) | ||
| #show cite: it => strong(text(fill: blue, it)) | ||
|
|
||
| #show bibliography: it => { | ||
| show link: set text(blue) | ||
| show link: strong | ||
| set text(size: 10pt, costs: (hyphenation: 150%)) | ||
| columns(it) | ||
| } | ||
|
|
||
| #show math.equation: set text(font: "Lete Sans Math") | ||
|
|
||
| #set pagebreak(weak: true) | ||
|
|
||
| ] | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| #set page( | ||
| paper: "a4", | ||
| margin: (top: 3cm, left: 3cm, right: 3cm, bottom: 3cm), | ||
| ) | ||
|
|
||
| #set text(weight: "bold", font: "TeX Gyre Heros", size: 20pt, lang: "de", hyphenate: false) | ||
| #set par(justify: false) | ||
|
|
||
| #place(top + center, text(size: 1.3em, [Your Title])) | ||
| #v(1.1fr) | ||
|
|
||
| #align(center + horizon, [ | ||
| #text([Bachelorarbeit der Mathematisch-Naturwissenschaftlichen Fakultät]) | ||
| #v(0.1em) | ||
| der #smallcaps[Eberhard Karls Universität Tübingen] //kapitälchen | ||
| #v(0.1em) | ||
| #text([im Fach X]) | ||
|
|
||
| #v(1fr) | ||
|
|
||
| vorgelegt von #str("\n\n") Surname, Name #str("\n") Tübingen, November 2025]) | ||
|
|
||
| #pagebreak() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| // declaration of independence | ||
| #set page( | ||
| paper: "a4", | ||
| margin: (top: 3cm, left: 3cm, right: 3cm, bottom: 3cm), | ||
| ) | ||
|
|
||
| #set text( | ||
| size: 12pt, | ||
| font: "TeX Gyre Heros", | ||
| lang: "de", | ||
| hyphenate: false, | ||
| ) | ||
| #set list(marker: "-") | ||
| #set par(justify: true) | ||
|
|
||
| #strong("Erklärung:") | ||
|
|
||
| Hiermit erkläre ich, | ||
|
|
||
| - dass ich diese Arbeit selbst verfasst und keine anderen als die angegebenen Quellen und Hilfsmittel benutzt habe, alle wörtlich oder sinngemäß aus anderen Werken übernommenen Aussagen als solche gekennzeichnet habe, die Arbeit weder vollständig noch in wesentlichen Teilen Gegenstand eines anderen Prüfungsverfahrens gewesen ist und die Arbeit weder vollständig noch in wesentlichen Teilen bereits veröffentlicht ist sowie dass das in Dateiform eingereichte Exemplar mit eingereichten gebundenen Exemplaren übereinstimmt. | ||
|
|
||
| - dass ich die Richtlinien zur Sicherung guter wissenschaftlicher Praxis und zum Umgang mit wissenschaftlichem Fehlverhalten an der Eberhard-Karls-Universität beachtet habe. | ||
| #v(2.5em) | ||
|
|
||
| Tübingen, den #datetime.today().display("[day].[month].[year]") | ||
|
|
||
| Your name | ||
|
|
||
| #pagebreak() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| #counter(page).update(1) //resettet counter so numbering starts only from section "abstract" | ||
|
|
||
| #page(numbering: "I")[ | ||
| // -------------------------englische version | ||
| #align(center + horizon)[ | ||
| #heading("Abstract", depth: 1, numbering: none) | ||
| #v(0.6em) | ||
| ] | ||
| // english abstract... | ||
| #lorem(60) | ||
|
|
||
| #pagebreak() | ||
|
|
||
| // -------------------------deutsche version | ||
| #align(center + horizon)[ | ||
| // #set par(justify: false) sieht manchmal schöner aus | ||
| #heading("Zusammenfassung", depth: 1, numbering: none) | ||
| #v(0.6em) | ||
| ] | ||
| // deutsche zusammenfassung... | ||
|
|
||
| #lorem(60) | ||
| ] | ||
|
|
||
| #pagebreak() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| #page(numbering: "I")[ | ||
| #align(center + horizon)[ | ||
| #heading(depth: 1, numbering: none, outlined: false, "Acknowledgements") | ||
| #v(0.6em) | ||
| ] | ||
|
|
||
| Your text goes here | ||
|
|
||
| ] | ||
|
|
||
| #pagebreak() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| #page(numbering: "I")[ | ||
| #heading([List of Abbreviations], numbering: none) | ||
|
|
||
|
|
||
| #v(0.7em) | ||
| #align(center)[ | ||
|
|
||
| //could look something like this: | ||
| #table( | ||
| columns: 2, | ||
| table.header([Abbreviation], [Meaning]), | ||
| [67], [nonsensical internet expression], | ||
| [...], [...], | ||
| ) | ||
| ] | ||
| ] | ||
|
|
||
| #pagebreak() | ||
|
|
||
| //start latin numbering============================ | ||
| #counter(page).update(1) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| #import "@preview/clean-ut:0.1.0":* | ||
|
|
||
| = Introduction | ||
|
|
||
| == How to Rickroll | ||
| generate a link where nobody expects it | ||
|
|
||
|
|
||
| #pagebreak() | ||
|
|
||
| //this is optional, but sometimes supervisors require this | ||
| = Aims of the thesis |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be a function that takes a
bodyparameter and returns it after having configured the styles. Otherwise,#show: templatewill just replace the whole document with the value of this variable, which is just a bunch of styles and no content to apply it too.