From f4a5ebc7fe1396ef911ac7609d64fd63660b16b7 Mon Sep 17 00:00:00 2001 From: Anton Bilous Date: Mon, 12 May 2025 10:31:53 +0300 Subject: [PATCH] feat(style)!: extract styling to style.typ, bump version to 0.2.0 --- README.md | 10 +- lib.typ | 229 ++++------------------------------------ style.typ | 182 +++++++++++++++++++++++++++++++ template/coursework.typ | 2 +- template/lab.typ | 4 +- typst.toml | 2 +- 6 files changed, 209 insertions(+), 220 deletions(-) create mode 100644 style.typ diff --git a/README.md b/README.md index bac2dfd..c4ac99a 100644 --- a/README.md +++ b/README.md @@ -30,11 +30,11 @@ This template: ### As a local typst package 1. Clone this repository into ~/.local/share/typst/packages/: ```bash -git clone -b 0.1.0 https://gitea.linerds.us/pencelheimer/typst_nure_template.git ~/.local/share/typst/packages/local/nure/0.1.0 +git clone https://github.com/noatu/typst-nure-template.git ~/.local/share/typst/packages/local/nure/0.2.0 ``` 2. Init your project with Typst: ```bash -typst init @local/nure:0.1.0 project-name +typst init @local/nure:0.2.0 project-name ``` ### As a standalone file @@ -43,7 +43,7 @@ Copy `lib.typ` to your project's root directory. ### In your project ```typst // Import the template either from a local package... -#import "@local/nure:0.1.0": * +#import "@local/nure:0.2.0": * // ...or by importing a lib.typ directly // #import "/lib.typ": * @@ -75,7 +75,7 @@ Some text // If you ever need appendices in pz-lb template use the show rule // WARNING: when using coursework template use its own argument, // so it can put bibliography before appendices -#show: appendices_style +#show: appendices-style = Quote #link("https://youtu.be/bJQj1uKtnus")[ @@ -86,7 +86,7 @@ Some text ### Notes: 1. Use `#v(-spacing)` to remove vertical spacing between titles (this cannot be automatically handled by the template). Variable `spacing` used here is imported from the template. -2. When importing `@local/nure:0.1.0` and specifying file paths in functions handled by the package, the path will relative to package's root directory, e.g. setting `#show: coursework.with(bib_path: "bibl.yml")` will evaluate to `~/.local/share/typst/packages/local/nure/0.1.0/bibl.yml`, the same is for `#img` function, which makes it quite annoying and forces one to import `lib.typ` file. Please open an issue or contact us in any other way if you have any advice. +2. When importing `@local/nure:0.2.0` and specifying file paths in functions handled by the package, the path will relative to package's root directory, e.g. setting `#show: coursework.with(bib_path: "bibl.yml")` will evaluate to `~/.local/share/typst/packages/local/nure/0.2.0/bibl.yml`, the same is for `#img` function, which makes it quite annoying and forces one to import `lib.typ` file. Please open an issue or contact us in any other way if you have any advice. ### Example Project Structure ``` diff --git a/lib.typ b/lib.typ index 6056706..9cde572 100644 --- a/lib.typ +++ b/lib.typ @@ -1,3 +1,11 @@ +// SPDX-License-Identifier: GPL-3.0 +/* + * typst-nure-template/lib.typ + * + * Typst template for NURE (Kharkiv National University of Radio Electronics) works + */ + +#import "style.typ": spacing, dstu-style, appendices-style // Academic aliases {{{1 @@ -79,211 +87,6 @@ ) #label(label_string)] } -// Styling {{{1 -/// NOTE: may be wrong -#let ua_alpha_numbering = "абвгдежиклмнпрстуфхцшщюя".split("") // 0 = "", 1 = "а" - -// general outlook {{{2 -// spacing between lines -#let spacing = 0.95em - -// main {{{2 -#let style(it) = { - set page( - paper: "a4", - margin: (top: 20mm, right: 10mm, bottom: 20mm, left: 25mm), - number-align: top + right, - numbering: (..numbers) => { - if numbers.pos().at(0) != 1 { - numbering("1", numbers.pos().at(0)) - } - }, - ) - - set text( - font: ("Times New Roman", "Liberation Serif"), - size: 14pt, - hyphenate: false, - lang: "uk", - ) - set par(justify: true, first-line-indent: (amount: 1.25cm, all: true)) - set underline(evade: false) - - // set 1.5 line spacing - set block(spacing: spacing) - set par(spacing: spacing) - set par(leading: spacing) - - // enums and lists {{{3 - set enum( - numbering: i => { ua_alpha_numbering.at(i) + ")" }, - indent: 1.25cm, - body-indent: 0.5cm, - ) - show enum: it => { - set enum(indent: 0em, numbering: "1)") - it - } - - set list(indent: 1.35cm, body-indent: 0.5cm, marker: [--]) - - // figures {{{3 - show figure: it => { - v(spacing * 2, weak: true) - it - v(spacing * 2, weak: true) - } - - set figure.caption(separator: [ -- ]) - show figure.where(kind: table): set figure.caption(position: top) - show figure.caption.where(kind: table): set align(left) - - // figure numbering - show heading.where(level: 1): it => { - counter(math.equation).update(0) - counter(figure.where(kind: image)).update(0) - counter(figure.where(kind: table)).update(0) - counter(figure.where(kind: raw)).update(0) - it - } - set math.equation( - numbering: (..num) => numbering( - "(1.1)", - counter(heading).get().at(0), - num.pos().first(), - ), - ) - set figure( - numbering: (..num) => numbering( - "1.1", - counter(heading).get().at(0), - num.pos().first(), - ), - ) - - // appearance of references to images and tables {{{3 - set ref( - supplement: it => { - if it == none or not it.has("kind") { - it - } else if it.kind == image { - "див. рис." - } else if it.kind == table { - "див. таблицю" - } else { - it - } - }, - ) - show ref: it => { - let el = it.element - - if el == none or not el.has("kind") { - return it - } - if el.kind != image and el.kind != table { - return it - } - - [(#it)] - } - - // headings {{{3 - set heading(numbering: "1.1") - - show heading.where(level: 1): it => { - set align(center) - set text(size: 14pt, weight: "semibold") - - pagebreak(weak: true) - upper(it) - v(spacing * 2, weak: true) - } - show heading.where(level: 2): it => { - set text(size: 14pt, weight: "regular") - - v(spacing * 2, weak: true) - block(width: 100%, spacing: 0em)[ - #h(1.25cm) - #counter(heading).display(it.numbering) - #it.body - ] - v(spacing * 2, weak: true) - } - - show heading.where(level: 3): it => { - set text(size: 14pt, weight: "regular") - - v(spacing * 2, weak: true) - block(width: 100%, spacing: 0em)[ - #h(1.25cm) - #counter(heading).display(it.numbering) - #it.body - ] - v(spacing * 2, weak: true) - } - - // listings {{{3 - show raw: it => { - let new_spacing = 0.5em - set block(spacing: new_spacing) - set par( - spacing: new_spacing, - leading: new_spacing, - ) - set text( - size: 11pt, - font: ("Courier New", "Liberation Mono"), - weight: "semibold", - ) - - v(spacing * 2.5, weak: true) - pad(it, left: 1.25cm) - v(spacing * 2.5, weak: true) - } - - it -} - -// appendices {{{2 -#let appendices_style(it) = { - counter(heading).update(0) - - set heading( - numbering: (i, ..nums) => { - let char = upper(ua_alpha_numbering.at(i)) - if nums.pos().len() == 0 { char } else { - char + "." + nums.pos().map(str).join(".") - } - }, - ) - - show heading.where(level: 1): it => { - set align(center) - set text(size: 14pt, weight: "regular") - - pagebreak(weak: true) - bold[ДОДАТОК #counter(heading).display(it.numbering)] - linebreak() - it.body - v(spacing * 2, weak: true) - } - - show heading.where(level: 2): it => { - set text(size: 14pt, weight: "regular") - - v(spacing * 2, weak: true) - block(width: 100%, spacing: 0em)[ - #h(1.25cm) - #counter(heading).display(it.numbering) - #it.body - ] - v(spacing * 2, weak: true) - } - - it -} - // Coursework template {{{1 /// DSTU 3008:2015 Template for NURE @@ -315,7 +118,7 @@ ) = { set document(title: title, author: author.name) - show: style + show: dstu-style.with(skip: 1) let bib-count = state("citation-counter", ()) show cite: it => { @@ -554,7 +357,8 @@ not is_cyrillic(keywords.at(j)) and is_cyrillic(keywords.at(j + 1)) ) or ( - is_cyrillic(keywords.at(j)) == is_cyrillic(keywords.at(j + 1)) and keywords.at(j) > keywords.at(j + 1) + is_cyrillic(keywords.at(j)) == is_cyrillic(keywords.at(j + 1)) + and keywords.at(j) > keywords.at(j + 1) ) ) { (keywords.at(j), keywords.at(j + 1)) = ( @@ -631,7 +435,10 @@ } context { - for (i, citation) in query(ref.where(element: none)).map(r => str(r.target)).dedup().enumerate() { + for (i, citation) in query(ref.where(element: none)) + .map(r => str(r.target)) + .dedup() + .enumerate() { enum.item( i + 1, format-entry(bib_data.at(citation)), @@ -640,7 +447,7 @@ } } - appendices_style(appendices) + appendices-style(appendices) } // Practice and Laboratory works template {{{1 @@ -668,7 +475,7 @@ ) = { set document(title: title, author: authors.at(0).name) - show: style + show: dstu-style.with(skip: 1) let uni = universities.at(university) let edu_prog = uni.edu_programs.at(edu_program) @@ -685,7 +492,7 @@ з #if doctype == "ЛБ" [лабораторної роботи] else [практичної роботи] #if worknumber != none { - context counter(heading).update(worknumber - if title == none {0} else {1}) + context counter(heading).update(worknumber - if title == none { 0 } else { 1 }) [№#worknumber] } diff --git a/style.typ b/style.typ new file mode 100644 index 0000000..3b19e8d --- /dev/null +++ b/style.typ @@ -0,0 +1,182 @@ +// SPDX-License-Identifier: GPL-3.0 +/* + * style.typ: Styles beneficial beyond the typst-nure-template + */ + +#let spacing = 0.95em // spacing between lines +#let num-to-alpha = "абвгдежиклмнпрстуфхцшщюя".split("") // 0 = "", 1 = "а" + +/// DSTU 3008:2015 Style +/// -> content +/// - it (content): Content to apply the style to. +/// - skip (int): Do not show page number for this number of pages. +/// - offset (int): Adjust all page numbers by this amount. +#let dstu-style( + it, + skip: 0, + offset: 0, +) = { + // General Styling {{{1 + set page( + paper: "a4", + number-align: top + right, + margin: (top: 20mm, right: 10mm, bottom: 20mm, left: 25mm), + numbering: (i, ..) => if i > skip { numbering("1", i + offset) }, + ) + + set text( + lang: "uk", + size: 14pt, + hyphenate: false, + font: ("Times New Roman", "Liberation Serif"), + ) + + set par( + justify: true, + spacing: spacing, + leading: spacing, + first-line-indent: (amount: 1.25cm, all: true), + ) + + set block(spacing: spacing) + set underline(evade: false) + + // Enums & Lists {{{1 + // First level + set enum( + indent: 1.25cm, + body-indent: 0.5cm, + numbering: i => { num-to-alpha.at(i) + ")" }, + ) + + // Second level and further nesting + show enum: it => { + set enum(indent: 0em, numbering: "1)") + it + } + + // Lists are not intended for multiple levels, use `enum` + set list(indent: 1.35cm, body-indent: 0.5cm, marker: [--]) + + // Figures {{{1 + show figure: it => { + v(spacing * 2, weak: true) + it + v(spacing * 2, weak: true) + } + + set figure.caption(separator: [ -- ]) + show figure.where(kind: table): set figure.caption(position: top) + show figure.caption.where(kind: table): set align(left) + + // Numbering + show heading.where(level: 1): it => { + counter(math.equation).update(0) + counter(figure.where(kind: raw)).update(0) + counter(figure.where(kind: image)).update(0) + counter(figure.where(kind: table)).update(0) + it + } + set figure(numbering: i => numbering("1.1", counter(heading).get().at(0), i)) + set math.equation(numbering: i => numbering("(1.1)", counter(heading).get().at(0), i)) + + // References to images and tables {{{1 + // TODO: simplify this to a simple number display? Will become a bit manual tho + set ref( + supplement: it => if it == none or not it.has("kind") { + it + } else if it.kind == image { + "див. рис." + } else if it.kind == table { + "див. таблицю" + } else { + it + }, + ) + show ref: it => { + let el = it.element + + if el == none or not el.has("kind") { + return it + } + if el.kind != image and el.kind != table { + return it + } + + [(#it)] + } + + // Headings {{{1 + set heading(numbering: "1.1") + + show heading: it => if it.level == 1 { + set align(center) + set text(size: 14pt, weight: "semibold") + + pagebreak(weak: true) + upper(it) + v(spacing * 2, weak: true) + } else { + set text(size: 14pt, weight: "regular") + + v(spacing * 2, weak: true) + block(width: 100%, spacing: 0em)[ + #h(1.25cm) + #counter(heading).display(auto) + #it.body + ] + v(spacing * 2, weak: true) + } + + + // Listings {{{1 + show raw: it => { + let raw-spacing = 0.5em + set block(spacing: raw-spacing) + set par(spacing: raw-spacing, leading: raw-spacing) + set text( + size: 11pt, + weight: "semibold", + font: ("Courier New", "Liberation Mono"), + ) + + v(spacing * 2.5, weak: true) + pad(it, left: 1.25cm) + v(spacing * 2.5, weak: true) + } + + it // }}} +} + +/// DSTU 3008:2015 Appendices Style +/// -> content +/// - it (content): Content to apply the style to. +#let appendices-style(it) = /* {{{1 */ { + counter(heading).update(0) + set heading(numbering: (i, ..n) => upper(num-to-alpha.at(i)) + numbering(".1.1", ..n)) + + show heading: it => if it.level == 1 { + set align(center) + set text(size: 14pt, weight: "regular") + + pagebreak(weak: true) + text(weight: "bold")[ДОДАТОК #counter(heading).display(auto)] + linebreak() + it.body + v(spacing * 2, weak: true) + } else { + set text(size: 14pt, weight: "regular") + + v(spacing * 2, weak: true) + block(width: 100%, spacing: 0em)[ + #h(1.25cm) + #counter(heading).display(auto) + #it.body + ] + v(spacing * 2, weak: true) + } + + it +} // }}} + +// vim:sts=2:sw=2:fdl=0:fdm=marker:cms=/*%s*/ diff --git a/template/coursework.typ b/template/coursework.typ index c769191..169653a 100644 --- a/template/coursework.typ +++ b/template/coursework.typ @@ -1,4 +1,4 @@ -#import "@local/nure:0.1.0": * +#import "@local/nure:0.2.0": * #let author = ( name: "Ситник Є. С.", diff --git a/template/lab.typ b/template/lab.typ index 958e3ee..b344add 100644 --- a/template/lab.typ +++ b/template/lab.typ @@ -1,4 +1,4 @@ -#import "@local/nure:0.1.0": * +#import "@local/nure:0.2.0": * #show: pz-lb.with(..yaml("config/doc.yaml")) @@ -30,7 +30,7 @@ - #lorem(42); - #lorem(27). -#show: appendices_style +#show: appendices-style = Quote #link("https://youtu.be/bJQj1uKtnus")[ diff --git a/typst.toml b/typst.toml index c09a9d5..a16806d 100644 --- a/typst.toml +++ b/typst.toml @@ -1,6 +1,6 @@ [package] name = "nure" -version = "0.1.0" +version = "0.2.0" entrypoint = "lib.typ" authors = ["linerds"] license = "GPL-3.0"