13 Commits
8 changed files with 436 additions and 63 deletions

No files matched your search

+5 -3
View File
@@ -1,12 +1,14 @@
# ktu-paper
This repository contains a Typst template for academic papers at the Kaunas University of Technology, Faculty of Informatics. A final Bachelor's thesis written with this template has successfully passed the formal review.
This repository contains a Typst template for academic papers at the Kaunas University of Technology, Faculty of Informatics.
I successfully wrote and defended a final Bachelor's thesis written with this template and continue to use for writing other reports.
## Initiating the template
Install the downloaded template under the following directory:
- Linux: `~/.local/share/typst/packages/local/ktu-paper/0.4.1/`
- Linux: `~/.local/share/typst/packages/local/ktu-paper/0.5.1/`
And then initiate a new project:
```sh
typst init @local/ktu-paper:0.4.1
typst init @local/ktu-paper:0.5.1
```
+148 -21
View File
@@ -7,7 +7,9 @@
/// Localizations for the recognized referenceable figure kinds, keyed by `repr(func)`.
/// - supplement: used in captions (the caption adds the separator, e.g. "1 pav.").
/// - ref-name: used in references, e.g. "(žr. 1 pav.)".
/// - ref-name: used in references, e.g. "(žr. 1 pav.)". Either a string or a
/// function `count => string`, called with the number of elements mentioned
/// together, e.g. "(žr. 1 priedą)" vs "(žr. 1, 2 priedus)".
/// - single-name: full word used when the figure is the only one of its kind and
/// therefore unnumbered, e.g. "Paveikslas. ..." and "(žr. paveikslas)".
#let __figure-kinds = (
@@ -15,6 +17,12 @@
image: (supplement: "pav", ref-name: "pav.", single-name: "paveikslas"),
raw: (supplement: "kodo frag", ref-name: "kodo frag.", single-name: "kodo fragmentas"),
equation: (supplement: "lygtis", ref-name: "formulė", single-name: "lygtis"),
// Appendices are headings, not figures, but they use the same referencing
appendix: (
supplement: "priedas",
ref-name: count => if count == 1 { "priedą" } else { "priedus" },
single-name: "priedas",
),
)
/// Figure kinds registered by the document author via `ktu-paper(figureKinds: ...)`.
@@ -160,10 +168,32 @@
}
/// Appendix headings carry an "appendix-heading" metadata marker as their
/// first child and are numbered differently from normal headings.
/// first child (or as their whole body, when the appendix has no title) and
/// are numbered separately from normal headings.
#let __is-appendix-heading(item) = {
let body = item.body
body.has("children") and body.children.at(0, default: none) == metadata("appendix-heading")
if body.has("children") {
body.children.at(0, default: none) == metadata("appendix-heading")
} else {
body == metadata("appendix-heading")
}
}
/// Returns the title of an appendix heading element (everything after the
/// marker), or `none` if the appendix has no title.
#let __appendix-title(item) = {
let body = item.body
if not body.has("children") { return none }
let rest = body.children.slice(1)
if rest.len() == 0 { none } else { rest.join() }
}
/// Returns the number (int) of an appendix heading element: its position among
/// all appendices, in document order. Must be called in a context.
#let __appendix-number(item) = {
query(selector(heading).before(item.location(), inclusive: true))
.filter(h => __is-appendix-heading(h))
.len()
}
/// Parses a dotted number such as "12" or "1.12.5" into an array of ints.
@@ -245,20 +275,24 @@
let number = if kind == figure {
if __is-single-unnumbered(item) {
panic(
"ref-no: " + str(target) + " is the only " + __figure-key(item)
"ref-no: "
+ str(target)
+ " is the only "
+ __figure-key(item)
+ " in the document and is therefore unnumbered; "
+ "refer to it with @" + str(target) + " (or custom-ref) instead",
+ "refer to it with @"
+ str(target)
+ " (or custom-ref) instead",
)
}
__get-figure-number(item, loc)
} else if kind == math.equation {
"(" + __get-equation-number(loc) + ")"
} else if kind == heading {
let numbers = counter(heading).at(loc)
if __is-appendix-heading(item) {
str(numbers.at(1))
str(__appendix-number(item))
} else {
numbers.map(str).join(".")
counter(heading).at(loc).map(str).join(".")
}
} else {
panic("referencing unknown type: " + repr(kind))
@@ -270,7 +304,8 @@
/// Create a custom reference for multiple targets of the same type.
/// - targets (label...): Labels to create a custom reference for.
#let custom-ref(..targets) = context {
let group-name = none
let group-key = none
let group-name = none // a string, or a function of the number of mentions
let single-name = none // set when the target is a lone, unnumbered figure
let entries = () // (location, number) pairs
@@ -278,8 +313,9 @@
let item = query(target).first()
let loc = item.location()
let (name, number) = if item.func() == math.equation {
(__figure-kinds.equation.ref-name, __get-equation-number(loc))
// (kind key used for grouping, ref-name spec, number)
let (key, name, number) = if item.func() == math.equation {
("equation", __figure-kinds.equation.ref-name, __get-equation-number(loc))
} else if item.func() == figure {
let kind = __figure-key(item)
let kinds = __all-figure-kinds()
@@ -287,14 +323,17 @@
panic("unregistered figure kind `" + kind + "`: register it with ktu-paper(figureKinds: ...)")
}
if __is-single-unnumbered(item) { single-name = kinds.at(kind).single-name }
(kinds.at(kind).ref-name, __get-figure-number(item, loc))
(kind, kinds.at(kind).ref-name, __get-figure-number(item, loc))
} else if item.func() == heading and __is-appendix-heading(item) {
("appendix", __figure-kinds.appendix.ref-name, str(__appendix-number(item)))
} else {
panic("referencing unknown type: " + repr(item.func()))
}
if group-name != none and group-name != name {
if group-key != none and group-key != key {
panic("custom-ref does not support grouping different elements together")
}
group-key = key
group-name = name
entries.push((loc, number))
}
@@ -305,7 +344,8 @@
[(žr. #link(entries.first().at(0), single-name))]
} else {
let links = __sort-entries(entries).map(e => link(e.at(0), e.at(1)))
[(žr. #links.join(", ") #group-name)]
let name = if type(group-name) == function { group-name(entries.len()) } else { group-name }
[(žr. #links.join(", ") #name)]
}
}
}
@@ -323,6 +363,8 @@
link(loc, "(" + __get-equation-number(loc) + ")")
} else if el.func() == figure and __figure-key(el) in __all-figure-kinds() {
custom-ref(it.target)
} else if el.func() == heading and __is-appendix-heading(el) {
custom-ref(it.target)
} else {
it
}
@@ -332,6 +374,65 @@
// Figure layout
// ---------------------------------------------------------------------------
/// Default layout per figure kind (keyed like `__figure-kinds`; custom kinds
/// and unlisted ones use `__FALLBACK_FIGURE_LAYOUT`).
/// - breakable: whether the body may be split across pages. The caption is then
/// attached to the start of the body (sticky), so it is never left alone at
/// the bottom of a page. If `false`, body and caption form one unbreakable
/// block that moves to the next page as a whole.
/// - caption: `top` or `bottom`.
#let __DEFAULT_FIGURE_LAYOUT = (
table: (breakable: true, caption: top),
raw: (breakable: true, caption: bottom),
)
#let __FALLBACK_FIGURE_LAYOUT = (breakable: false, caption: bottom)
/// Author overrides, set via `ktu-paper(figureLayout: ...)`.
#let __USER_FIGURE_LAYOUT = state("ktu-user-figure-layout", (:))
/// Stack of local overrides set by `breakable-figures` / `unbreakable-figures`.
#let __FIGURE_BREAK_OVERRIDE = state("ktu-figure-break-override", ())
/// Validates author-supplied layouts: `(kind: (breakable: bool, caption: top | bottom))`,
/// every field optional.
#let __normalize-figure-layout(layouts) = {
for (key, spec) in layouts {
for (field, value) in spec {
assert(
field in ("breakable", "caption"),
message: "figureLayout." + key + ": unknown option `" + field + "`, expected `breakable` or `caption`",
)
if field == "breakable" {
assert(type(value) == bool, message: "figureLayout." + key + ".breakable must be a bool")
} else {
assert(
value == top or value == bottom,
message: "figureLayout." + key + ".caption must be `top` or `bottom`",
)
}
}
}
layouts
}
/// Resolves the layout of a figure kind key. Must be called in a context.
#let __figure-layout(key) = {
let layout = __FALLBACK_FIGURE_LAYOUT + __DEFAULT_FIGURE_LAYOUT.at(key, default: (:))
layout = layout + __USER_FIGURE_LAYOUT.get().at(key, default: (:))
let overrides = __FIGURE_BREAK_OVERRIDE.get()
if overrides.len() > 0 {
layout.breakable = overrides.last()
}
layout
}
/// Runs `body` with every figure's `breakable` setting forced to `mode`.
#let __with-break-override(mode, body) = {
__FIGURE_BREAK_OVERRIDE.update(stack => stack + (mode,))
body
__FIGURE_BREAK_OVERRIDE.update(stack => stack.slice(0, -1))
}
/// Formats a figure with a caption and number.
#let __format-figure(it) = {
let caption = it.caption
@@ -342,13 +443,39 @@
set text(size: 11pt)
let caption-line = [*#__caption-label(it)* #caption.body]
let key = __figure-key(it)
// Tables have captions at the top
if it.kind == table {
align(left, caption-line)
it.body
} else {
it.body
align(center, caption-line)
context {
let layout = __figure-layout(key)
let on-top = layout.caption == top
// Entire table is by default left aligned, unlike other figures which are centered
let body = if key == "table" { align(left, it.body) } else { it.body }
let caption-block = block(
sticky: on-top and layout.breakable,
width: 100%,
align(if on-top { left } else { center }, caption-line),
)
if layout.breakable {
// The body may split across pages. A caption on top is sticky and stays
// with the first rows; a caption at the bottom cannot be glued to the end
// of a splittable body, so it may end up alone on the next page.
if on-top {
caption-block
body
} else {
body
caption-block
}
} else {
block(breakable: false, width: 100%, {
if on-top {
caption-block
body
} else {
body
caption-block
}
})
}
}
}
+122
View File
@@ -254,3 +254,125 @@
#h(58%) _Patvirtinta elektroniniu būdu_
]
}
#let ktu-gen-ai-usage-declaration-page(
author: highlight[Vardenis Pavardenis],
faculty: highlight[Informatikos fakultetas],
module: highlight[Studijų modulio pavadinimas (kodas)],
title: highlight[Studijų darbo pavadinimas],
type: highlight[Studijų darbo rūšis],
usageInformation: (
(highlight[...], highlight[...], highlight[...], highlight[...]),
),
showPhysicalSignature: false,
) = {
set text(size: 12pt)
align(center)[
#block([*GENERATYVINIO DIRBTINIO INTELEKTO (GenDI) NAUDOJIMO DEKLARACIJA*])
#block[\_\_\_ \_\_\_ \_\_\_]
]
[*1. Studento duomenys*]
table(
columns: (155pt, 1fr),
align: (x, y) => { horizon + left },
[*Studento vardas, pavardė*], [#author],
[*Studento fakultetas*], [#faculty],
[*Studijų modulis*], [#module],
[*Studijų darbo pavadinimas*], [#title],
[*Studijų darbo rūšis*], [#type],
)
[
#set linebreak(justify: false)
*2. GenDI naudojimo patvirtinimas*\
_Pažymėkite vieną variantą:_
]
let usedAi = usageInformation != none and usageInformation.len() > 0
let checkbox(checked: false) = {
box(
width: 0.8em,
height: 0.8em,
stroke: 0.08em + black,
radius: 0.15em,
if checked {
let size = 0.4em
let margin = 0.2em
// Top-left to bottom-right line
place(top + left, dx: margin, dy: margin, line(end: (size, size), stroke: 0.08em + black))
// Bottom-left to top-right line
place(top + left, dx: margin, dy: margin + size, line(end: (size, -size), stroke: 0.08em + black))
} else {
none
},
)
}
table(
columns: (28pt, 1fr),
align: (x, y) => { horizon + left },
table.cell(rowspan: 2)[#align(top, checkbox(checked: not usedAi))],
[*Rengdamas (-a) šį studijų darbą nenaudojau generatyvinio dirbtinio intelekto įrankių*],
[Patvirtinu, kad studijų darbe pateiktas turinys yra mano autentiškas intelektinis darbas, o naudoti šaltiniai nurodyti pagal citavimo reikalavimus.],
table.cell(rowspan: 2)[#align(top, checkbox(checked: usedAi))],
[*Rengdamas (-a) šį studijų darbą naudojau generatyvinio dirbtinio intelekto įrankius*],
[Patvirtinu, kad GenDI įrankiai buvo naudojami laikantis studijų modulyje nustatytų GenDI naudojimo reikalavimų bei naudojimas yra skaidriai ir sąžiningai deklaruotas.],
)
[
#set linebreak(justify: false)
*3. GenDI naudojimo informacija*\
_Užpildykite, jei rengiant studijų darbą naudojote generatyvinio dirbtinio intelekto įrankius:_
]
let rows = if usedAi {
usageInformation.flatten()
} else {
// hide[x] gives each empty cell the height of one regular line of text
range(3).map(_ => range(4).map(_ => hide[x])).flatten()
}
set par(justify: false)
table(
columns: (91pt, 127pt, 139pt, 1fr),
align: (x, y) => { top + left },
table.header(
[
#set linebreak(justify: false)
*Darbo dalis*\
_(pvz., skyrius, visas darbas)_
],
[*GenDI įrankio naudojimo tikslas*],
[*GenDI įrankio pavadinimas, versija / internetinė nuoroda*],
[
#set linebreak(justify: false)
*Studento indėlis* \
_(kaip GenDI rezultatas buvo patikrintas, redaguotas ar papildytas studento)_
],
),
..rows,
)
let field(size: 12pt, body) = {
set text(size: size)
align(center, body)
}
let underlined-field(min-width: 92pt, body) = context {
let w = calc.max(min-width, measure(body).width)
align(center, box(
width: w,
height: 1.4em,
stroke: (bottom: 0.5pt + black),
inset: (bottom: 2pt),
align(center + bottom, body),
))
}
let maybe(show-it, body) = if show-it { body } else { hide(body) }
align(bottom, table(
stroke: 0pt,
inset: 2pt,
columns: (120pt, 177pt, 1fr),
align: (x, y) => { horizon + left },
[Studentas], [#maybe(showPhysicalSignature, [#underlined-field[]])], [#underlined-field(min-width: 126pt)[#author]],
[], [#maybe(showPhysicalSignature, [#field(size: 10pt)[_(parašas)_]])], [#field(size: 10pt)[(_vardas, pavardė_)]],
))
}
+132 -29
View File
@@ -1,4 +1,4 @@
#import "@preview/codly:1.3.0": codly, codly-init
#import "@preview/codly:2.0.0" as codly
#import "config.typ": debug-author-table, enable-heading-experiment, __HEADING_EXPERIMENT, __FIG_PER_SECTION, __UPPERCASE_SECTION_TITLES
#import "fragments.typ": (
ktu-table,
@@ -7,7 +7,7 @@
ktu-author-table, ktu-title-header-block,
ktu-heading-page, ktu-heading-page-centered, ktu-heading-page-normal,
ktu-academic-honestly-declaration-page
ktu-academic-honestly-declaration-page, ktu-gen-ai-usage-declaration-page
)
#import "figures.typ": (
ref-no, custom-ref,
@@ -17,9 +17,17 @@
__equation-numbering,
__normalize-figure-kinds,
__USER_FIGURE_KINDS,
__USER_FIGURE_LAYOUT,
__normalize-figure-layout,
__with-break-override,
__format-ref,
__format-figure,
__figure-kinds,
__is-appendix-heading,
__appendix-title,
__appendix-number,
)
/**
@@ -53,11 +61,30 @@
heading(level: level, numbering: none, body)
}
#let appendix-item(body) = {
/// Insert an appendix (priedas).
///
/// Appendices are numbered 1, 2, 3, ... in the order they appear in the
/// document, so place them in the order they are first mentioned in the text.
/// Each appendix should start on a new page: put a `#pagebreak()` before it.
/// "N priedas" is written in the top right
/// corner. The optional title is written below it like a chapter title (bold),
/// exactly as given: start it with a capital letter, the rest in lowercase.
/// Appendices are included in the table of contents.
///
/// Give it a label to refer to it from the text: `#appendix-item[Pavadinimas] <pr-konfig>`
/// and then `@pr-konfig` or `#custom-ref(<pr-konfig>)` gives "(žr. 1 priedą)".
/// - title (content | none): Optional appendix title.
/// -> heading
#let appendix-item(..title) = {
assert(
title.named().len() == 0 and title.pos().len() <= 1,
message: "appendix-item takes at most one argument: the appendix title",
)
let title = title.pos().at(0, default: none)
heading(
metadata("appendix-heading") + "priedas. " + body,
if title == none { metadata("appendix-heading") } else { metadata("appendix-heading") + title },
level: 2,
numbering: (..any) => {str(any.at(1))}
numbering: none,
)
}
@@ -116,18 +143,25 @@
show outline.entry: it => {
// Recompute the gap based on the prefix content, so that the outline entry is indented
// from the left regardless of the length of the prefix (based on the requirement)
let prefixContent = it.prefix()
let measurement = measure(prefixContent)
let target = targets.at(it.level - 1, default: 0.64cm)
let newGap = target - measurement.width
if it.element.body.has("children") and it.element.body.children.at(0) == metadata("appendix-heading") {
target = 0.64cm
let isAppendix = __is-appendix-heading(it.element)
// Appendices are listed as "N priedas. Pavadinimas", the number being the prefix
let prefixContent = if isAppendix {
context [#__appendix-number(it.element)]
} else {
it.prefix()
}
let measurement = measure(prefixContent)
let target = if isAppendix { 0.64cm } else { targets.at(it.level - 1, default: 0.64cm) }
let newGap = target - measurement.width
// Uppercase body if need be
let bodyContent = it.element.body
if isUpper and (it.level == 1 or it.element.numbering == none) {
if isAppendix {
let title = __appendix-title(it.element)
let name = __figure-kinds.appendix.supplement
bodyContent = if title == none { [#name] } else { [#name. #title] }
} else if isUpper and (it.level == 1 or it.element.numbering == none) {
bodyContent = upper(bodyContent)
}
@@ -255,16 +289,55 @@
__ktu_outline(title: heading(title, outlined: true), target: figure.where(kind: kind))
}
#let setup-code(body) = {
show: codly-init.with()
codly(
fill: white,
zebra-fill: none,
stroke: none,
display-name: false,
display-icon: false,
/// Lets figures in `body` split across pages: the body may break, the caption stays
/// attached to its start (a caption at the bottom may end up alone, see `figureLayout`).
/// Use it to opt out of keeping a figure on one page, e.g. for a long code listing.
/// - body (content): Content containing figures.
/// -> content
#let breakable-figures(body) = __with-break-override(true, body)
/// Keeps every figure in `body` on one page: body and caption move to the next
/// page together. Use it to opt out of splitting, e.g. for a short table.
/// - body (content): Content containing figures.
/// -> content
#let unbreakable-figures(body) = __with-break-override(false, body)
/// `code` option defaults for the library entrypoint.
#let __CODE_DEFAULTS = (
font: "Hack",
spacing: 80%,
fill: white,
stroke: 0.5pt + black,
numbers: true,
radius: 0pt,
display-name: false,
display-icon: false,
)
/// Applies the code block styling to the body.
/// - code (dictionary | none): Options, merged over `__CODE_DEFAULTS`.
/// `none` leaves raw blocks untouched.
#let __setup-code(code, body) = {
if code == none {
return body
}
let opts = __CODE_DEFAULTS + code
let known = __CODE_DEFAULTS.keys()
for key in opts.keys() {
assert(
key in known,
message: "ktu-paper: unknown `code` option \"" + key + "\", expected one of: " + known.join(", "),
)
}
show raw.where(block: true): codly.new
show: codly.set_(number-enabled: opts.numbers, radius: opts.radius)
show: codly.line-set_(fill: opts.fill, stroke: opts.stroke)
show: codly.lang-set_(
display-name: opts.display-name,
display-icon: opts.display-icon,
)
show raw: set text(font: "Hack", spacing: 80%)
show raw: set text(font: opts.font, spacing: opts.spacing)
body
}
@@ -359,6 +432,19 @@
// TODO: intervalas tarp eilučių – 1,15 kiekvienai antraštei
// Priedas: kiekvienas pradedamas naujame lape, dešiniajame viršutiniame
// kampe rašoma "N priedas", pavadinimas (jei yra) – kaip skyriaus pavadinimas
if __is-appendix-heading(it) {
align(right, block(below: 10pt, text(weight: "regular")[
#__appendix-number(it) #__figure-kinds.appendix.supplement
]))
let title = __appendix-title(it)
if title != none {
block(below: 10pt, title)
}
return
}
// Antraštė be nr.
if it.numbering == none {
// Centruota lygiuotė by default, but can be overridden by the user
@@ -397,14 +483,8 @@
}
}
// Determine whether the heading has appending metadata attached and adjust its display accordingly
let isAppendixHeading = it.body.has("children") and it.body.children.at(0) == metadata("appendix-heading")
if isAppendixHeading {
block[#counter(heading).display(it.numbering) #it.body]
}
// Poskyris ir skyrelis
if not isAppendixHeading and it.numbering != none and it.level != 1 {
if it.numbering != none and it.level != 1 {
// abipusė lygiuotė
set par(justify: true)
@@ -423,6 +503,8 @@
show ref: it => __format-ref(it)
// Figure captions and numbering
// Figure is non breakable by default, actual breaking behaviour is decided per kind in `__format-figure`.
show figure: set block(breakable: true)
show figure: it => __format-figure(it)
// Bibliography citing style
@@ -446,13 +528,33 @@
/// Use them with `figure(kind: "command", ...)`. Keys:
/// - `supplement` (required): text after the number in captions, e.g. "1 komanda.".
/// - `ref-name`: text used in references, e.g. "(žr. 1 komanda)". Defaults to `supplement`.
/// Can also be a function `count => string`, called with the number of elements
/// referenced together, for kinds whose wording depends on it, e.g.
/// `count => if count == 1 { "komandą" } else { "komandas" }`.
/// - `single-name`: full word used when the figure is the only one of its kind
/// and is left unnumbered, e.g. "Komanda." and "(žr. komanda)". Defaults to `supplement`.
/// Currently only tables and images are left unnumbered when single, so this only matters for kinds added there.
/// - figureLayout (dictionary): Page-break behaviour and caption position per figure kind,
/// `(kind: (breakable: bool, caption: top | bottom))`, every field optional. Kinds are
/// `table`, `image`, `raw` (code), or a key of `figureKinds`. Defaults: `table` and `raw`
/// are breakable; everything else is unbreakable. Example: `(raw: (breakable: false, caption: bottom))`.
/// A breakable figure's top caption stays attached to the start of the body.
/// Use `breakable-figures[...]` / `unbreakable-figures[...]` to override it locally.
/// - code (dictionary | none): Code block configuration, or `none` to leave raw blocks unstyled. Keys:
/// - `font` (str): Monospace font. Defaults to "Hack".
/// - `spacing` (relative): Word spacing of code text. Defaults to `80%`.
/// - `fill` (paint): Background of code lines. Defaults to `white`.
/// - `stroke` (stroke | none): Outline around the code block. Defaults to `0.5pt + black`; `none` removes it.
/// - `numbers` (bool): Show line numbers. Defaults to `true`.
/// - `radius` (length): Corner radius of the outline. Defaults to `0pt` (square corners).
/// - `display-name` (bool): Show the language name badge. Defaults to `false`.
/// - `display-icon` (bool): Show the language icon badge. Defaults to `false`.
#let ktu-paper(
font: "Times New Roman",
figureNumberingPerSection: false,
figureKinds: (:),
figureLayout: (:),
code: (:),
// Not sure about formal conformity of deviating
// from the defaults of the next options,
// but some modules may require them
@@ -467,6 +569,7 @@
)
__FIG_PER_SECTION.update(figureNumberingPerSection)
__USER_FIGURE_KINDS.update(__normalize-figure-kinds(figureKinds))
__USER_FIGURE_LAYOUT.update(__normalize-figure-layout(figureLayout))
__UPPERCASE_SECTION_TITLES.update(uppercaseSectionTitles)
body
__setup-code(code, body)
}
+24 -3
View File
@@ -1,7 +1,8 @@
#import "../src/lib.typ": (
ktu-paper, setup-code,
#import "@local/ktu-paper:0.5.1": (
ktu-paper,
ktu-table-of-contents, ktu-picture-list, ktu-table-list, ktu-code-list,
ktu-heading-page-normal,
ktu-gen-ai-usage-declaration-page,
ktu-table,
unnumbered-heading,
custom-ref, ref-no
@@ -13,15 +14,32 @@
figureKinds: (
veryCustomKind: (supplement: "komanda", ref-name: "komanda"),
),
// Code blocks, `code: none` to disable styling
code: (
font: "Hack",
spacing: 80%,
fill: white,
stroke: 0.5pt + black,
numbers: true,
radius: 0pt,
display-name: false,
display-icon: false,
),
)
#show: setup-code.with()
// Replace dots in equations with commas instead so 1.25 becomes 1,25.
#show math.equation: it => {
show regex("\d+\.\d+"): it => {show ".": {","+h(0pt)}
it}
it
}
// To be used for writing purposes to mark TODOs in the document. They will be highlighted in yellow and have a dashed border.
#let todo(desc) = block(
width: 100%, inset: 10pt, stroke: (dash: "dashed"), fill: yellow.lighten(80%),
[*TODO:* #desc],
)
#ktu-heading-page-normal(
faculty: highlight[Informatikos fakultetas],
title: highlight[Laboratorinio darbo ataskaitos pavadinimas],
@@ -148,3 +166,6 @@ Naudotojai tai pat gali apibrėžti savo figūras, pavyzdžiui, komandų fragmen
#pagebreak()
= Išvados
#lorem(50)
#pagebreak()
#ktu-gen-ai-usage-declaration-page()
+2 -3
View File
@@ -1,5 +1,5 @@
#import "@local/ktu-paper:0.4.1": (
ktu-paper, setup-code,
#import "@local/ktu-paper:0.5.1": (
ktu-paper,
ktu-table-of-contents, ktu-picture-list, ktu-table-list,
ktu-heading-page-normal,
ktu-table,
@@ -9,7 +9,6 @@
#show: ktu-paper.with(
font: "Times New Roman",
)
#show: setup-code.with()
#show math.equation: it => {
show regex("\d+\.\d+"): it => {show ".": {","+h(0pt)}
+2 -3
View File
@@ -1,5 +1,5 @@
#import "@local/ktu-paper:0.4.0": (
ktu-paper, setup-code,
#import "@local/ktu-paper:0.5.1": (
ktu-paper,
ktu-table-of-contents, ktu-picture-list, ktu-table-list,
ktu-heading-page-normal,
ktu-table,
@@ -10,7 +10,6 @@
#show: ktu-paper.with(
font: "Times New Roman",
)
#show: setup-code.with()
#show figure: it => {
set block(breakable: true)
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "ktu-paper"
version = "0.4.1"
version = "0.5.1"
compiler = "0.15.0"
entrypoint = "src/lib.typ"
repository = "https://github.com/svetikas/ktu-paper"