mirror of
https://github.com/JustAnyones/ktu-paper.git
synced 2026-11-04 00:30:18 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ed5a62c659
|
||
|
|
f078b8ae00
|
||
|
|
321703ddbc
|
||
|
|
c15747ce98
|
||
|
|
ada5bc3f63
|
||
|
|
e5c774f96c
|
No files matched your search
@@ -1,12 +1,14 @@
|
|||||||
# ktu-paper
|
# 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
|
## Initiating the template
|
||||||
Install the downloaded template under the following directory:
|
Install the downloaded template under the following directory:
|
||||||
- Linux: `~/.local/share/typst/packages/local/ktu-paper/0.4.0/`
|
- Linux: `~/.local/share/typst/packages/local/ktu-paper/0.5.0/`
|
||||||
|
|
||||||
And then initiate a new project:
|
And then initiate a new project:
|
||||||
```sh
|
```sh
|
||||||
typst init @local/ktu-paper:0.4.0
|
typst init @local/ktu-paper:0.5.0
|
||||||
```
|
```
|
||||||
+114
-20
@@ -7,12 +7,22 @@
|
|||||||
|
|
||||||
/// Localizations for the recognized referenceable figure kinds, keyed by `repr(func)`.
|
/// Localizations for the recognized referenceable figure kinds, keyed by `repr(func)`.
|
||||||
/// - supplement: used in captions (the caption adds the separator, e.g. "1 pav.").
|
/// - 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 = (
|
#let __figure-kinds = (
|
||||||
table: (supplement: "lentelė", ref-name: "lentelė"),
|
table: (supplement: "lentelė", ref-name: "lentelė", single-name: "lentelė"),
|
||||||
image: (supplement: "pav", ref-name: "pav."),
|
image: (supplement: "pav", ref-name: "pav.", single-name: "paveikslas"),
|
||||||
raw: (supplement: "kodo frag", ref-name: "kodo frag."),
|
raw: (supplement: "kodo frag", ref-name: "kodo frag.", single-name: "kodo fragmentas"),
|
||||||
equation: (supplement: "lygtis", ref-name: "formulė"),
|
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: ...)`.
|
/// Figure kinds registered by the document author via `ktu-paper(figureKinds: ...)`.
|
||||||
@@ -30,6 +40,7 @@
|
|||||||
normalized.insert(key, (
|
normalized.insert(key, (
|
||||||
supplement: spec.supplement,
|
supplement: spec.supplement,
|
||||||
ref-name: spec.at("ref-name", default: spec.supplement),
|
ref-name: spec.at("ref-name", default: spec.supplement),
|
||||||
|
single-name: spec.at("single-name", default: spec.supplement),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
normalized
|
normalized
|
||||||
@@ -157,10 +168,32 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Appendix headings carry an "appendix-heading" metadata marker as their
|
/// 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 __is-appendix-heading(item) = {
|
||||||
let body = item.body
|
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.
|
/// Parses a dotted number such as "12" or "1.12.5" into an array of ints.
|
||||||
@@ -186,11 +219,49 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Single-figure handling
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/// Figure kinds that are left unnumbered when the document contains only one
|
||||||
|
/// captioned figure of that kind: "Lentelė. Aprašas" and "(žr. lentelė)"
|
||||||
|
/// instead of "1 lentelė. Aprašas" and "(žr. 1 lentelė)". The word used comes
|
||||||
|
/// from the kind's `single-name`.
|
||||||
|
/// Keys are `__figure-key` values.
|
||||||
|
#let __UNNUMBERED_WHEN_SINGLE = ("table", "image")
|
||||||
|
|
||||||
|
/// Whether `fig` is the only captioned figure of its kind in the document and
|
||||||
|
/// its kind is listed in `__UNNUMBERED_WHEN_SINGLE`. Must be called in a context.
|
||||||
|
#let __is-single-unnumbered(fig) = {
|
||||||
|
if __figure-key(fig) not in __UNNUMBERED_WHEN_SINGLE { return false }
|
||||||
|
query(figure.where(kind: fig.kind)).filter(f => f.caption != none).len() == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Capitalizes the first letter of `value` ("lentelė" -> "Lentelė").
|
||||||
|
#let __capitalize(value) = {
|
||||||
|
let first = value.first()
|
||||||
|
upper(first) + value.slice(first.len())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Caption label of a figure element: "1 lentelė." normally, or
|
||||||
|
/// "Lentelė." for a single unnumbered figure.
|
||||||
|
#let __caption-label(fig) = context {
|
||||||
|
let supplement = __figure-supplement-of(fig)
|
||||||
|
if __is-single-unnumbered(fig) {
|
||||||
|
let name = __all-figure-kinds().at(__figure-key(fig)).single-name
|
||||||
|
[#__capitalize(name).]
|
||||||
|
} else {
|
||||||
|
[#__get-figure-number(fig, fig.location()) #supplement.]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// References
|
// References
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
/// Returns a number for the given reference target.
|
/// Returns a number for the given reference target.
|
||||||
|
/// Panics for a figure that is the only one of its kind,
|
||||||
|
/// since such figures have no number.
|
||||||
/// - target (label): Label to get the reference number for.
|
/// - target (label): Label to get the reference number for.
|
||||||
#let ref-no(target) = context {
|
#let ref-no(target) = context {
|
||||||
if type(target) != label {
|
if type(target) != label {
|
||||||
@@ -202,15 +273,26 @@
|
|||||||
let kind = item.func()
|
let kind = item.func()
|
||||||
|
|
||||||
let number = if kind == figure {
|
let number = if kind == figure {
|
||||||
|
if __is-single-unnumbered(item) {
|
||||||
|
panic(
|
||||||
|
"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",
|
||||||
|
)
|
||||||
|
}
|
||||||
__get-figure-number(item, loc)
|
__get-figure-number(item, loc)
|
||||||
} else if kind == math.equation {
|
} else if kind == math.equation {
|
||||||
"(" + __get-equation-number(loc) + ")"
|
"(" + __get-equation-number(loc) + ")"
|
||||||
} else if kind == heading {
|
} else if kind == heading {
|
||||||
let numbers = counter(heading).at(loc)
|
|
||||||
if __is-appendix-heading(item) {
|
if __is-appendix-heading(item) {
|
||||||
str(numbers.at(1))
|
str(__appendix-number(item))
|
||||||
} else {
|
} else {
|
||||||
numbers.map(str).join(".")
|
counter(heading).at(loc).map(str).join(".")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
panic("referencing unknown type: " + repr(kind))
|
panic("referencing unknown type: " + repr(kind))
|
||||||
@@ -222,36 +304,49 @@
|
|||||||
/// Create a custom reference for multiple targets of the same type.
|
/// Create a custom reference for multiple targets of the same type.
|
||||||
/// - targets (label...): Labels to create a custom reference for.
|
/// - targets (label...): Labels to create a custom reference for.
|
||||||
#let custom-ref(..targets) = context {
|
#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
|
let entries = () // (location, number) pairs
|
||||||
|
|
||||||
for target in targets.pos() {
|
for target in targets.pos() {
|
||||||
let item = query(target).first()
|
let item = query(target).first()
|
||||||
let loc = item.location()
|
let loc = item.location()
|
||||||
|
|
||||||
let (name, number) = if item.func() == math.equation {
|
// (kind key used for grouping, ref-name spec, number)
|
||||||
(__figure-kinds.equation.ref-name, __get-equation-number(loc))
|
let (key, name, number) = if item.func() == math.equation {
|
||||||
|
("equation", __figure-kinds.equation.ref-name, __get-equation-number(loc))
|
||||||
} else if item.func() == figure {
|
} else if item.func() == figure {
|
||||||
let kind = __figure-key(item)
|
let kind = __figure-key(item)
|
||||||
let kinds = __all-figure-kinds()
|
let kinds = __all-figure-kinds()
|
||||||
if kind not in kinds {
|
if kind not in kinds {
|
||||||
panic("unregistered figure kind `" + kind + "`: register it with ktu-paper(figureKinds: ...)")
|
panic("unregistered figure kind `" + kind + "`: register it with ktu-paper(figureKinds: ...)")
|
||||||
}
|
}
|
||||||
(kinds.at(kind).ref-name, __get-figure-number(item, loc))
|
if __is-single-unnumbered(item) { single-name = kinds.at(kind).single-name }
|
||||||
|
(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 {
|
} else {
|
||||||
panic("referencing unknown type: " + repr(item.func()))
|
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")
|
panic("custom-ref does not support grouping different elements together")
|
||||||
}
|
}
|
||||||
|
group-key = key
|
||||||
group-name = name
|
group-name = name
|
||||||
entries.push((loc, number))
|
entries.push((loc, number))
|
||||||
}
|
}
|
||||||
|
|
||||||
if entries.len() > 0 {
|
if entries.len() > 0 {
|
||||||
|
if single-name != none {
|
||||||
|
// The only figure of its kind: no number, e.g. "(žr. lentelė)"
|
||||||
|
[(žr. #link(entries.first().at(0), single-name))]
|
||||||
|
} else {
|
||||||
let links = __sort-entries(entries).map(e => link(e.at(0), e.at(1)))
|
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)]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,6 +363,8 @@
|
|||||||
link(loc, "(" + __get-equation-number(loc) + ")")
|
link(loc, "(" + __get-equation-number(loc) + ")")
|
||||||
} else if el.func() == figure and __figure-key(el) in __all-figure-kinds() {
|
} else if el.func() == figure and __figure-key(el) in __all-figure-kinds() {
|
||||||
custom-ref(it.target)
|
custom-ref(it.target)
|
||||||
|
} else if el.func() == heading and __is-appendix-heading(el) {
|
||||||
|
custom-ref(it.target)
|
||||||
} else {
|
} else {
|
||||||
it
|
it
|
||||||
}
|
}
|
||||||
@@ -286,10 +383,7 @@
|
|||||||
|
|
||||||
set text(size: 11pt)
|
set text(size: 11pt)
|
||||||
|
|
||||||
let supplement = __figure-supplement-of(it)
|
let caption-line = [*#__caption-label(it)* #caption.body]
|
||||||
let separator = [.]
|
|
||||||
let fig-num = context __get-figure-number(it, here())
|
|
||||||
let caption-line = [*#fig-num #supplement#separator* #caption.body]
|
|
||||||
|
|
||||||
// Tables have captions at the top
|
// Tables have captions at the top
|
||||||
if it.kind == table {
|
if it.kind == table {
|
||||||
|
|||||||
+114
-34
@@ -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 "config.typ": debug-author-table, enable-heading-experiment, __HEADING_EXPERIMENT, __FIG_PER_SECTION, __UPPERCASE_SECTION_TITLES
|
||||||
#import "fragments.typ": (
|
#import "fragments.typ": (
|
||||||
ktu-table,
|
ktu-table,
|
||||||
@@ -12,9 +12,7 @@
|
|||||||
#import "figures.typ": (
|
#import "figures.typ": (
|
||||||
ref-no, custom-ref,
|
ref-no, custom-ref,
|
||||||
|
|
||||||
__fig-supplement,
|
__caption-label,
|
||||||
__figure-supplement-of,
|
|
||||||
__get-locatable-element-number,
|
|
||||||
__reset-figure-counters,
|
__reset-figure-counters,
|
||||||
__equation-numbering,
|
__equation-numbering,
|
||||||
__normalize-figure-kinds,
|
__normalize-figure-kinds,
|
||||||
@@ -22,6 +20,11 @@
|
|||||||
|
|
||||||
__format-ref,
|
__format-ref,
|
||||||
__format-figure,
|
__format-figure,
|
||||||
|
__figure-kinds,
|
||||||
|
|
||||||
|
__is-appendix-heading,
|
||||||
|
__appendix-title,
|
||||||
|
__appendix-number,
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -55,11 +58,30 @@
|
|||||||
heading(level: level, numbering: none, body)
|
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(
|
heading(
|
||||||
metadata("appendix-heading") + "priedas. " + body,
|
if title == none { metadata("appendix-heading") } else { metadata("appendix-heading") + title },
|
||||||
level: 2,
|
level: 2,
|
||||||
numbering: (..any) => {str(any.at(1))}
|
numbering: none,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,18 +140,25 @@
|
|||||||
show outline.entry: it => {
|
show outline.entry: it => {
|
||||||
// Recompute the gap based on the prefix content, so that the outline entry is indented
|
// 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)
|
// from the left regardless of the length of the prefix (based on the requirement)
|
||||||
let prefixContent = it.prefix()
|
let isAppendix = __is-appendix-heading(it.element)
|
||||||
let measurement = measure(prefixContent)
|
|
||||||
let target = targets.at(it.level - 1, default: 0.64cm)
|
// Appendices are listed as "N priedas. Pavadinimas", the number being the prefix
|
||||||
let newGap = target - measurement.width
|
let prefixContent = if isAppendix {
|
||||||
if it.element.body.has("children") and it.element.body.children.at(0) == metadata("appendix-heading") {
|
context [#__appendix-number(it.element)]
|
||||||
target = 0.64cm
|
} 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
|
let newGap = target - measurement.width
|
||||||
|
|
||||||
// Uppercase body if need be
|
// Uppercase body if need be
|
||||||
let bodyContent = it.element.body
|
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)
|
bodyContent = upper(bodyContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,7 +187,7 @@
|
|||||||
show outline.entry: it => link(
|
show outline.entry: it => link(
|
||||||
it.element.location(),
|
it.element.location(),
|
||||||
it.indented(
|
it.indented(
|
||||||
[*#__get-locatable-element-number(it.element) #__fig-supplement(image).*],
|
[*#__caption-label(it.element)*],
|
||||||
[ #it.inner()], gap: 0pt
|
[ #it.inner()], gap: 0pt
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@@ -169,7 +198,7 @@
|
|||||||
show outline.entry: it => link(
|
show outline.entry: it => link(
|
||||||
it.element.location(),
|
it.element.location(),
|
||||||
it.indented(
|
it.indented(
|
||||||
[*#__get-locatable-element-number(it.element) #__fig-supplement(table).*],
|
[*#__caption-label(it.element)*],
|
||||||
[ #it.inner()], gap: 0pt
|
[ #it.inner()], gap: 0pt
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@@ -180,7 +209,7 @@
|
|||||||
show outline.entry: it => link(
|
show outline.entry: it => link(
|
||||||
it.element.location(),
|
it.element.location(),
|
||||||
it.indented(
|
it.indented(
|
||||||
[*#__get-locatable-element-number(it.element) #__fig-supplement(raw).*],
|
[*#__caption-label(it.element)*],
|
||||||
[ #it.inner()], gap: 0pt
|
[ #it.inner()], gap: 0pt
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@@ -202,7 +231,7 @@
|
|||||||
show outline.entry: it => link(
|
show outline.entry: it => link(
|
||||||
it.element.location(),
|
it.element.location(),
|
||||||
it.indented(
|
it.indented(
|
||||||
[*#__get-locatable-element-number(it.element) #__figure-supplement-of(it.element).*],
|
[*#__caption-label(it.element)*],
|
||||||
[ #it.inner()], gap: 0pt
|
[ #it.inner()], gap: 0pt
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@@ -257,16 +286,41 @@
|
|||||||
__ktu_outline(title: heading(title, outlined: true), target: figure.where(kind: kind))
|
__ktu_outline(title: heading(title, outlined: true), target: figure.where(kind: kind))
|
||||||
}
|
}
|
||||||
|
|
||||||
#let setup-code(body) = {
|
/// `code` option defaults for the library entrypoint.
|
||||||
show: codly-init.with()
|
#let __CODE_DEFAULTS = (
|
||||||
codly(
|
font: "Hack",
|
||||||
|
spacing: 80%,
|
||||||
fill: white,
|
fill: white,
|
||||||
zebra-fill: none,
|
stroke: 0.5pt + black,
|
||||||
stroke: none,
|
numbers: true,
|
||||||
display-name: false,
|
display-name: false,
|
||||||
display-icon: 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: set text(font: "Hack", spacing: 80%)
|
}
|
||||||
|
|
||||||
|
show raw.where(block: true): codly.new
|
||||||
|
show: codly.set_(number-enabled: opts.numbers)
|
||||||
|
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: opts.font, spacing: opts.spacing)
|
||||||
body
|
body
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,6 +374,8 @@
|
|||||||
body
|
body
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#let setup-code(body, ..ignored) = body
|
||||||
|
|
||||||
#let setup-page(
|
#let setup-page(
|
||||||
font: "Times New Roman",
|
font: "Times New Roman",
|
||||||
uppercaseSectionTitles: false,
|
uppercaseSectionTitles: false,
|
||||||
@@ -361,6 +417,19 @@
|
|||||||
|
|
||||||
// TODO: intervalas tarp eilučių – 1,15 kiekvienai antraštei
|
// 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.
|
// Antraštė be nr.
|
||||||
if it.numbering == none {
|
if it.numbering == none {
|
||||||
// Centruota lygiuotė by default, but can be overridden by the user
|
// Centruota lygiuotė by default, but can be overridden by the user
|
||||||
@@ -399,14 +468,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
|
// Poskyris ir skyrelis
|
||||||
if not isAppendixHeading and it.numbering != none and it.level != 1 {
|
if it.numbering != none and it.level != 1 {
|
||||||
// abipusė lygiuotė
|
// abipusė lygiuotė
|
||||||
set par(justify: true)
|
set par(justify: true)
|
||||||
|
|
||||||
@@ -444,12 +507,29 @@
|
|||||||
/// - uppercaseSectionTitles (bool): Whether to uppercase section titles.
|
/// - uppercaseSectionTitles (bool): Whether to uppercase section titles.
|
||||||
/// - unnumberedHeadingAlignment (alignment): Alignment for unnumbered headings.
|
/// - unnumberedHeadingAlignment (alignment): Alignment for unnumbered headings.
|
||||||
/// - figureKinds (dictionary): Extra figure kinds, e.g.
|
/// - figureKinds (dictionary): Extra figure kinds, e.g.
|
||||||
/// `(command: (supplement: "komanda", ref-name: "komanda"))`. `ref-name`
|
/// `(command: (supplement: "komanda", ref-name: "komanda", single-name: "komanda"))`.
|
||||||
/// defaults to `supplement`. Use them with `figure(kind: "command", ...)`.
|
/// 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.
|
||||||
|
/// - 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`.
|
||||||
|
/// - `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(
|
#let ktu-paper(
|
||||||
font: "Times New Roman",
|
font: "Times New Roman",
|
||||||
figureNumberingPerSection: false,
|
figureNumberingPerSection: false,
|
||||||
figureKinds: (:),
|
figureKinds: (:),
|
||||||
|
code: (:),
|
||||||
// Not sure about formal conformity of deviating
|
// Not sure about formal conformity of deviating
|
||||||
// from the defaults of the next options,
|
// from the defaults of the next options,
|
||||||
// but some modules may require them
|
// but some modules may require them
|
||||||
@@ -465,5 +545,5 @@
|
|||||||
__FIG_PER_SECTION.update(figureNumberingPerSection)
|
__FIG_PER_SECTION.update(figureNumberingPerSection)
|
||||||
__USER_FIGURE_KINDS.update(__normalize-figure-kinds(figureKinds))
|
__USER_FIGURE_KINDS.update(__normalize-figure-kinds(figureKinds))
|
||||||
__UPPERCASE_SECTION_TITLES.update(uppercaseSectionTitles)
|
__UPPERCASE_SECTION_TITLES.update(uppercaseSectionTitles)
|
||||||
body
|
__setup-code(code, body)
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,159 @@
|
|||||||
|
#import "@local/ktu-paper:0.5.0": (
|
||||||
|
ktu-paper,
|
||||||
|
ktu-table-of-contents, ktu-picture-list, ktu-table-list, ktu-code-list,
|
||||||
|
ktu-heading-page-normal,
|
||||||
|
ktu-table,
|
||||||
|
unnumbered-heading,
|
||||||
|
custom-ref, ref-no
|
||||||
|
)
|
||||||
|
|
||||||
|
#show: ktu-paper.with(
|
||||||
|
font: "Times New Roman", // or Arial
|
||||||
|
figureNumberingPerSection: true,
|
||||||
|
figureKinds: (
|
||||||
|
veryCustomKind: (supplement: "komanda", ref-name: "komanda"),
|
||||||
|
),
|
||||||
|
// Code blocks, optional, `code: none` disables styling
|
||||||
|
code: (
|
||||||
|
font: "Hack",
|
||||||
|
spacing: 80%,
|
||||||
|
fill: white,
|
||||||
|
stroke: 0.5pt + black,
|
||||||
|
numbers: true,
|
||||||
|
display-name: false,
|
||||||
|
display-icon: false,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
#show math.equation: it => {
|
||||||
|
show regex("\d+\.\d+"): it => {show ".": {","+h(0pt)}
|
||||||
|
it}
|
||||||
|
it
|
||||||
|
}
|
||||||
|
|
||||||
|
#ktu-heading-page-normal(
|
||||||
|
faculty: highlight[Informatikos fakultetas],
|
||||||
|
title: highlight[Laboratorinio darbo ataskaitos pavadinimas],
|
||||||
|
subtitles: (
|
||||||
|
"Laboratorinio darbo ataskaita",
|
||||||
|
highlight[Studijų modulio pavadinimas (kodas)]
|
||||||
|
),
|
||||||
|
authors: (
|
||||||
|
(highlight[Vardenis Pavardenis], "Ataskaitą parengė"),
|
||||||
|
(highlight[Pareigų ir mokslo laipsnio sutrumpinimas Vardenis Pavardenis], "Laboratoriniam darbui vadovavo"),
|
||||||
|
),
|
||||||
|
authorNamesFirst: false,
|
||||||
|
place: "Kaunas",
|
||||||
|
year: datetime.today().year(),
|
||||||
|
)
|
||||||
|
#pagebreak()
|
||||||
|
#set page(numbering: "1")
|
||||||
|
|
||||||
|
#ktu-table-of-contents()
|
||||||
|
#pagebreak()
|
||||||
|
|
||||||
|
#ktu-picture-list()
|
||||||
|
#pagebreak()
|
||||||
|
|
||||||
|
#ktu-table-list()
|
||||||
|
#pagebreak()
|
||||||
|
|
||||||
|
#ktu-code-list()
|
||||||
|
#pagebreak()
|
||||||
|
|
||||||
|
#unnumbered-heading[= Įvadas]
|
||||||
|
#lorem(50)
|
||||||
|
|
||||||
|
#pagebreak()
|
||||||
|
= Skyrius
|
||||||
|
#lorem(50)
|
||||||
|
|
||||||
|
== Poskyrius
|
||||||
|
#lorem(50)
|
||||||
|
|
||||||
|
=== Dalis
|
||||||
|
#lorem(50)
|
||||||
|
|
||||||
|
#pagebreak()
|
||||||
|
= Komponentai
|
||||||
|
|
||||||
|
== Paveikslai
|
||||||
|
Galima gauti paveikslo numerį #ref-no(<image-label>) arba visą paveikslo nuorodą #custom-ref(<image-label>).
|
||||||
|
|
||||||
|
#figure(
|
||||||
|
image("images/santaka.png", width: 70%),
|
||||||
|
caption: [
|
||||||
|
Paveikslo pavadinimas
|
||||||
|
],
|
||||||
|
) <image-label>
|
||||||
|
|
||||||
|
|
||||||
|
== Paveikslų "grid" išdėstymas
|
||||||
|
Paveikslus taip pat galima sudėti į "grid" išdėstymą, į jį kreiptis kaip numerį #ref-no(<image-grid-label>) arba visą nuorodą #custom-ref(<image-grid-label>).
|
||||||
|
|
||||||
|
#figure(grid(
|
||||||
|
columns: 2,
|
||||||
|
gutter: 2mm,
|
||||||
|
image("images/santaka.png", width: 100%),
|
||||||
|
image("images/santaka.png", width: 100%),
|
||||||
|
), caption: [
|
||||||
|
Paveikslėliai "grid'e"
|
||||||
|
]) <image-grid-label>
|
||||||
|
|
||||||
|
|
||||||
|
== Lentelės
|
||||||
|
|
||||||
|
Galima gauti lentelės numerį /*#ref-no(<table-label>)*/ arba visą lentelės nuorodą #custom-ref(<table-label>).
|
||||||
|
|
||||||
|
#figure(
|
||||||
|
ktu-table(
|
||||||
|
columns: (auto, 1fr, 1fr, 1fr),
|
||||||
|
align: (x, y) => { horizon + left },
|
||||||
|
table.header([*Stulpelio pavadinimas*], [*Stulpelio pavadinimas*], [*Stulpelio pavadinimas*], [*Stulpelio pavadinimas*]),
|
||||||
|
[Eilutė 1], [...], [...], [...],
|
||||||
|
[Eilutė 2], [...], [...], [...],
|
||||||
|
[Eilutė 3], [...], [...], [...],
|
||||||
|
[Eilutė 4], [...], [...], [...],
|
||||||
|
),
|
||||||
|
caption: [Lentelės pavadinimas],
|
||||||
|
) <table-label>
|
||||||
|
|
||||||
|
|
||||||
|
== Formulės
|
||||||
|
Formules galima išreikšti eilutėje, pavyzdžiui $E = m c^2$ arba atskiroje eilutėje, pavyzdžiui:
|
||||||
|
$
|
||||||
|
E = m c^2
|
||||||
|
$ <formula-label>
|
||||||
|
|
||||||
|
// TODO: fix
|
||||||
|
Formulės atskiroje eilutėje numeruojamos besąlygiškai, galima gauti formulės numerį #ref-no(<formula-label>) arba visą formulės nuorodą #custom-ref(<formula-label>).
|
||||||
|
|
||||||
|
== Kodo fragmentai
|
||||||
|
Kodo fragmentus galima išreikšti eilutėje, pavyzdžiui `print("Hello, world!")` arba atskiroje eilutėje, pavyzdžiui:
|
||||||
|
#figure(```python
|
||||||
|
def main():
|
||||||
|
print("Hello, world!")
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
```, caption: [
|
||||||
|
Python kodas
|
||||||
|
]) <code-label>
|
||||||
|
|
||||||
|
Galima gauti kodo fragmento numerį #ref-no(<code-label>) arba visą kodo fragmento nuorodą #custom-ref(<code-label>).
|
||||||
|
|
||||||
|
== Naudotojo apibrėžtos figūros
|
||||||
|
|
||||||
|
Naudotojai tai pat gali apibrėžti savo figūras, pavyzdžiui, komandų fragmentus. Pavyzdžiui, galima apibrėžti komandų fragmentą su papildoma informacija ir naudoti jį dokumente. Galima gauti kodo fragmento numerį #ref-no(<custom-figure-label>) arba visą kodo fragmento nuorodą #custom-ref(<custom-figure-label>).
|
||||||
|
|
||||||
|
#figure(
|
||||||
|
```sh
|
||||||
|
npm install foo
|
||||||
|
```,
|
||||||
|
kind: "veryCustomKind",
|
||||||
|
supplement: "...",
|
||||||
|
caption: [Diegimo komanda],
|
||||||
|
) <custom-figure-label>
|
||||||
|
|
||||||
|
#pagebreak()
|
||||||
|
= Išvados
|
||||||
|
#lorem(50)
|
||||||
+2
-3
@@ -1,5 +1,5 @@
|
|||||||
#import "@local/ktu-paper:0.4.0": (
|
#import "@local/ktu-paper:0.5.0": (
|
||||||
ktu-paper, setup-code,
|
ktu-paper,
|
||||||
ktu-table-of-contents, ktu-picture-list, ktu-table-list,
|
ktu-table-of-contents, ktu-picture-list, ktu-table-list,
|
||||||
ktu-heading-page-normal,
|
ktu-heading-page-normal,
|
||||||
ktu-table,
|
ktu-table,
|
||||||
@@ -9,7 +9,6 @@
|
|||||||
#show: ktu-paper.with(
|
#show: ktu-paper.with(
|
||||||
font: "Times New Roman",
|
font: "Times New Roman",
|
||||||
)
|
)
|
||||||
#show: setup-code.with()
|
|
||||||
|
|
||||||
#show math.equation: it => {
|
#show math.equation: it => {
|
||||||
show regex("\d+\.\d+"): it => {show ".": {","+h(0pt)}
|
show regex("\d+\.\d+"): it => {show ".": {","+h(0pt)}
|
||||||
|
|||||||
+2
-3
@@ -1,5 +1,5 @@
|
|||||||
#import "@local/ktu-paper:0.4.0": (
|
#import "@local/ktu-paper:0.5.0": (
|
||||||
ktu-paper, setup-code,
|
ktu-paper,
|
||||||
ktu-table-of-contents, ktu-picture-list, ktu-table-list,
|
ktu-table-of-contents, ktu-picture-list, ktu-table-list,
|
||||||
ktu-heading-page-normal,
|
ktu-heading-page-normal,
|
||||||
ktu-table,
|
ktu-table,
|
||||||
@@ -10,7 +10,6 @@
|
|||||||
#show: ktu-paper.with(
|
#show: ktu-paper.with(
|
||||||
font: "Times New Roman",
|
font: "Times New Roman",
|
||||||
)
|
)
|
||||||
#show: setup-code.with()
|
|
||||||
|
|
||||||
#show figure: it => {
|
#show figure: it => {
|
||||||
set block(breakable: true)
|
set block(breakable: true)
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ktu-paper"
|
name = "ktu-paper"
|
||||||
version = "0.4.0"
|
version = "0.5.0"
|
||||||
compiler = "0.15.0"
|
compiler = "0.15.0"
|
||||||
entrypoint = "src/lib.typ"
|
entrypoint = "src/lib.typ"
|
||||||
repository = "https://github.com/svetikas/ktu-paper"
|
repository = "https://github.com/svetikas/ktu-paper"
|
||||||
|
|||||||
Reference in new issue
Block a user