Compare commits
1 Commits
0.1.1
..
56da014b9b
| Author | SHA1 | Date | |
|---|---|---|---|
| 56da014b9b |
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
## General Info
|
## General Info
|
||||||
|
|
||||||
This project contains template functions and some utilities for writing NURE works. All functions include documentation comments inside them, so you can explore all possibilities using LSP.
|
This project contains two template functions and some utilities for writing NURE works. All functions include documentation comments inside them, so you can explore all possibilities using LSP.
|
||||||
|
|
||||||
### Templates
|
### Templates
|
||||||
|
|
||||||
@@ -19,25 +19,20 @@ This template:
|
|||||||
- Typesets the bibliography according to ДСТУ 3008:2015 using custom CSL style;
|
- Typesets the bibliography according to ДСТУ 3008:2015 using custom CSL style;
|
||||||
- Typesets the outline and appendices according to standard requirements.
|
- Typesets the outline and appendices according to standard requirements.
|
||||||
|
|
||||||
#### `coursework-v2` - New Coursework Variant
|
|
||||||
This template keeps the legacy coursework template intact while offering the newer title/task-page layout. See `template/default/coursework-v2.typ` for an example entrypoint.
|
|
||||||
|
|
||||||
### Utilities
|
### Utilities
|
||||||
- `nheading` - For unnumbered headings, such as "Introduction" and "Conclusion".
|
- `nheading` - For unnumbered headings, such as "Introduction" and "Conclusion".
|
||||||
- `hfill` - Fills horizontal space with a filled box instead of just empty space; useful for creating underlines.
|
- `hfill` - Fills horizontal space with a filled box instead of just empty space; useful for creating underlines.
|
||||||
- `uline` - Creates underlined fields that need to be filled, such as the name field on the task list.
|
- `uline` - Creates underlined fields that need to be filled, such as the name field on the task list.
|
||||||
- `bold` - Inserts bold text inside functional environments.
|
- `bold` - Inserts bold text inside functional environments.
|
||||||
- `img` - Inserts images with a caption, automatically deriving the label from the image file name (use via `#import "@local/nure:0.1.1": utils` and call `utils.img`).
|
- `img` - Inserts images with a caption, automatically deriving the label from the image file name.
|
||||||
|
|
||||||
**Note:** `img()` is provided in `template/utils.typ` so you can copy it into your project root for compatibility, until [path() type](https://github.com/typst/typst/pull/7555) is released.
|
**Note:** `img()` is provided in `utils.typ` in project's root directory for compatibility, until [path() type](https://github.com/typst/typst/pull/7555) is released.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
### As a local typst package
|
### As a local typst package
|
||||||
You can install the template as a local Typst package. Choose the instructions for your platform below.
|
1. Clone this repository into ~/.local/share/typst/packages/:
|
||||||
|
|
||||||
#### Unix (Linux / macOS)
|
|
||||||
1. Clone this repository into your local Typst packages folder:
|
|
||||||
```bash
|
```bash
|
||||||
git clone -b 0.1.1 https://gitea.linerds.us/pencelheimer/typst_nure_template.git ~/.local/share/typst/packages/local/nure/0.1.1
|
git clone -b 0.1.1 https://gitea.linerds.us/pencelheimer/typst_nure_template.git ~/.local/share/typst/packages/local/nure/0.1.1
|
||||||
```
|
```
|
||||||
@@ -46,67 +41,21 @@ git clone -b 0.1.1 https://gitea.linerds.us/pencelheimer/typst_nure_template.git
|
|||||||
typst init @local/nure:0.1.1 project-name
|
typst init @local/nure:0.1.1 project-name
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Windows (symlink method)
|
|
||||||
This method creates a symbolic link between the cloned repository and Typst's local packages folder in `%APPDATA%`. The benefit: when the template is updated on GitHub you only need to `git pull` in the cloned folder — VS Code (and Typst) will use the updated files automatically.
|
|
||||||
|
|
||||||
Step 1 — clone the template (for example, into your Documents folder):
|
|
||||||
```powershell
|
|
||||||
cd $HOME\Documents
|
|
||||||
git clone https://github.com/linerds/typst_nure_template.git
|
|
||||||
```
|
|
||||||
|
|
||||||
Step 2 — create the symlink (PowerShell must be run as Administrator):
|
|
||||||
1. Open Start, find PowerShell, right-click and choose "Run as Administrator".
|
|
||||||
2. Run the following commands as a single block:
|
|
||||||
```powershell
|
|
||||||
# Create local packages folder (if it doesn't exist)
|
|
||||||
New-Item -ItemType Directory -Force -Path "$env:APPDATA\typst\packages\local\nure"
|
|
||||||
|
|
||||||
# Point to the folder you cloned
|
|
||||||
$gitFolder = "$HOME\Documents\typst_nure_template"
|
|
||||||
|
|
||||||
# Create a symbolic link for the package version (match the version in this repo)
|
|
||||||
New-Item -ItemType SymbolicLink -Path "$env:APPDATA\typst\packages\local\nure\0.1.1" -Target $gitFolder
|
|
||||||
```
|
|
||||||
|
|
||||||
Step 3 — use in VS Code
|
|
||||||
Open your project folder (for example, your coursework or lab folder) in VS Code with the Tinymist Typst extension installed. Create `main.typ` and import the package using the official `@local` import:
|
|
||||||
|
|
||||||
```typst
|
|
||||||
#import "@local/nure:0.1.1": nure-report, style
|
|
||||||
// If you need specific style variables from the package:
|
|
||||||
#import "@local/nure:0.1.1/src/style.typ": spacing
|
|
||||||
|
|
||||||
#show: nure-report.with(
|
|
||||||
title: "Report for Lab Work",
|
|
||||||
type: "Lab Work #1",
|
|
||||||
discipline: "Object-Oriented Programming",
|
|
||||||
author: "Surname I.I.",
|
|
||||||
supervisor: "Assoc. Prof. Kuznetsov O.V.",
|
|
||||||
)
|
|
||||||
|
|
||||||
= Work progress
|
|
||||||
Your content...
|
|
||||||
```
|
|
||||||
|
|
||||||
The Windows steps above are intentionally minimal and focused on the symlink workflow. If you prefer not to use symlinks, you can copy `src/` to your project root and import `lib.typ` directly (see the "As a standalone file" section).
|
|
||||||
|
|
||||||
### As a standalone file
|
### As a standalone file
|
||||||
Copy `src/` to your project's root directory, optionally renaming `src/` to `lib/` (then import `src/lib.typ` or `lib/lib.typ` accordingly).
|
Copy `src/` to your project's root directory, optionally renaming `src/` to `lib/`.
|
||||||
|
|
||||||
### In your project
|
### In your project
|
||||||
```typst
|
```typst
|
||||||
// Import the template either from a local package...
|
// Import the template either from a local package...
|
||||||
#import "@local/nure:0.1.1": *
|
#import "@local/nure:0.1.0": *
|
||||||
// ...or by importing a lib.typ directly
|
// ...or by importing a lib.typ directly
|
||||||
// #import "/lib/lib.typ": *
|
// #import "/lib/lib.typ": *
|
||||||
|
|
||||||
// NOTE: all template arguments use kebab-case.
|
|
||||||
|
|
||||||
// 1. Setup the document
|
// 1. Setup the document
|
||||||
// by setting values directly...
|
// by setting values directly...
|
||||||
#show: pz-lb.with(
|
#show: pz-lb.with(
|
||||||
title: "Some title",
|
title: "Some title",
|
||||||
|
// etc: "and so on",
|
||||||
// ...
|
// ...
|
||||||
)
|
)
|
||||||
// ...or using a yaml/toml file
|
// ...or using a yaml/toml file
|
||||||
@@ -124,7 +73,7 @@ Some text
|
|||||||
#include "chapters/chapter1.typ"
|
#include "chapters/chapter1.typ"
|
||||||
#include "chapters/chapter2.typ"
|
#include "chapters/chapter2.typ"
|
||||||
// NOTE: if you want to use variables or utils provided by the package,
|
// NOTE: if you want to use variables or utils provided by the package,
|
||||||
// you have to import the package or a lib.typ inside a module (e.g. #import "@local/nure:0.1.1": utils).
|
// you have to import the package or a lib.typ inside a module.
|
||||||
|
|
||||||
|
|
||||||
// If you ever need appendices in pz-lb template use the show rule
|
// If you ever need appendices in pz-lb template use the show rule
|
||||||
@@ -132,8 +81,6 @@ Some text
|
|||||||
// so it can put bibliography before appendices
|
// so it can put bibliography before appendices
|
||||||
#show: style.appendices
|
#show: style.appendices
|
||||||
|
|
||||||
// For coursework appendices, pass them via `appendices:` argument instead.
|
|
||||||
|
|
||||||
= Quote
|
= Quote
|
||||||
#link("https://youtu.be/bJQj1uKtnus")[
|
#link("https://youtu.be/bJQj1uKtnus")[
|
||||||
The art isn't the art, the art is never the art,
|
The art isn't the art, the art is never the art,
|
||||||
@@ -175,7 +122,7 @@ semester = 4
|
|||||||
|
|
||||||
### Notes:
|
### 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.
|
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.1` and specifying file paths in functions handled by the package, the path will be relative to the package root, e.g. setting `#show: coursework.with(bib-path: "bibl.yml")` will evaluate to `~/.local/share/typst/packages/local/nure/0.1.1/bibl.yml`. The same applies to `utils.img` unless you copy `template/utils.typ` into your project root and import from there.
|
2. When importing `@local/nure:0.1.1` 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.1/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.
|
||||||
|
|
||||||
### Bibliography Format
|
### Bibliography Format
|
||||||
The template uses a custom CSL (Citation Style Language) file located at `src/csl/dstu-3008-2015.csl` to format bibliography entries.
|
The template uses a custom CSL (Citation Style Language) file located at `src/csl/dstu-3008-2015.csl` to format bibliography entries.
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
ХНУРЕ:
|
||||||
|
name: Харківський національний університет радіоелектроніки
|
||||||
|
name_en: Kharkiv National University of Radioelectronics
|
||||||
|
edu_programs:
|
||||||
|
ПЗПІ:
|
||||||
|
name_long: Інженерія програмного забезпечення
|
||||||
|
department_gen: Програмної інженерії
|
||||||
|
code: 121 # TODO: change to F2?
|
||||||
|
КУІБ:
|
||||||
|
name_long: Управління інформаційною безпекою
|
||||||
|
department_gen: Інфокомунікаційної інженерії ім. В. В. Поповського
|
||||||
|
code: 125 # TODO: change to F5?
|
||||||
|
КНТ:
|
||||||
|
name_en: CST # computer sciences and technologies
|
||||||
|
name_long: Комп'ютерні науки та технології
|
||||||
|
department_gen: Системотехніки
|
||||||
|
department_en: ST
|
||||||
|
code: 122
|
||||||
|
subjects:
|
||||||
|
DMT: Decision making theory
|
||||||
|
ODS: Основи Dаtа Sсіеnсе # NOTE: Eng O here
|
||||||
|
ІМ: Іноземна мова
|
||||||
|
ІТР: Information Technologies of Reengineering
|
||||||
|
ІТРОІ: Інтернет-технології Розподіленої Обробки Інформації
|
||||||
|
АВпЗ: Аналіз вимог до програмного забезпечення
|
||||||
|
АДан: Аналітика даних
|
||||||
|
АКтаК: Архітектура комп'ютера та комп'ютерних мереж
|
||||||
|
АТСД: Алгоритми та структури даних
|
||||||
|
АтаРК: Аналіз та рефакторинг коду
|
||||||
|
БД: Бази даних
|
||||||
|
БЖД: Безпека життєдіяльності
|
||||||
|
ВДІТБ: Введення до ІТ-бізнесу # NOTE: all in UA
|
||||||
|
ВМ: Вища математика
|
||||||
|
ГТГ: Гіпертекст та гіпермедіа
|
||||||
|
ДМ: Дискретна математика
|
||||||
|
ДПК: Динаміка Проектних Команд
|
||||||
|
ЕРВ: Електрорадіовимірювання
|
||||||
|
КДМА: Комп'ютерна дискретна математика
|
||||||
|
КЗВШ: Креативність з використанням штучного інтелекту
|
||||||
|
КМ: Комп`ютерні мережі
|
||||||
|
ЛМВ: Людино-машинна взаємодія
|
||||||
|
ЛМтБ: Локальні мережі та їх безпека # бидло не знає що українською "їхня"
|
||||||
|
МОКр: Математичні основи криптології
|
||||||
|
МОТДО: Методи оптимізаціі та дослідження операцій
|
||||||
|
МППС: Methodologies of designing software systems
|
||||||
|
МС: Моделювання систем
|
||||||
|
ОІМ: Основи IP-мереж
|
||||||
|
ООАПС: Об'єктно-орієнтований аналіз в проектуванні систем
|
||||||
|
ООП: Об'єктно-орієнтоване програмування
|
||||||
|
ОП: Основи права
|
||||||
|
ОПІ: Основи програмноі інженеріі
|
||||||
|
ОПНJ: Основи програмування на Java
|
||||||
|
ОПр: Основи програмування
|
||||||
|
ОРвІТ: Оцінка Ризиків в IT-проектах
|
||||||
|
ОС: Операційні системи
|
||||||
|
ОТК: Основи теорії кіл
|
||||||
|
ПБІП: Проектування та балансування ігрового процесу
|
||||||
|
ПВJ: Поглиблене вивчення Java
|
||||||
|
ПЕСЕ: Психологія екстремальних стосунків та ефективної адаптації
|
||||||
|
ПНП: Програмування на платформі .NЕТ
|
||||||
|
ПП: Проектний практикум
|
||||||
|
ПРОГ: Програмування
|
||||||
|
ПарП: Параллельне програмування
|
||||||
|
СА: Системний аналіз
|
||||||
|
СМП: Скриптові мови програмування
|
||||||
|
СОАПЗ: Сервіс-Орієнтована Архітектура Програмного Забезпечення
|
||||||
|
СРБД: Серверні рішення баз даних
|
||||||
|
СхТ: Схемотехніка
|
||||||
|
ТВО: Технології Високопродуктивних Обчислень
|
||||||
|
ТЗІ: Технології захисту інформації
|
||||||
|
ТЙтаМ: Теорія ймовірностей та математична # TODO: what?
|
||||||
|
ТКП: Технології комп`ютерного проєктування
|
||||||
|
УФМ: Українське фахове мовлення
|
||||||
|
ФІЗ: Фізика
|
||||||
|
ФІЛ: Філософія
|
||||||
|
ФВС: Фізичне виховання та спорт
|
||||||
|
ХТ: Хмарні технології
|
||||||
@@ -0,0 +1,701 @@
|
|||||||
|
|
||||||
|
// Academic aliases {{{1
|
||||||
|
|
||||||
|
#let universities = yaml("config/universities.yaml")
|
||||||
|
|
||||||
|
// Template formatting functions {{{1
|
||||||
|
|
||||||
|
/// bold text
|
||||||
|
#let bold(content) = text(weight: "bold")[#content]
|
||||||
|
|
||||||
|
/// numberless heading
|
||||||
|
#let nheading(title) = heading(depth: 1, numbering: none, title)
|
||||||
|
|
||||||
|
/// fill horizontal space with a box and not an empty space
|
||||||
|
#let hfill(width) = box(
|
||||||
|
width: width,
|
||||||
|
repeat(" "),
|
||||||
|
) // NOTE: This is a HAIR SPACE (U+200A), not a regular space
|
||||||
|
|
||||||
|
/// make underlined cell with filled value
|
||||||
|
#let uline(align: center, content) = underline[
|
||||||
|
#if align != left { hfill(1fr) }
|
||||||
|
#content
|
||||||
|
#if align != right { hfill(1fr) }
|
||||||
|
]
|
||||||
|
|
||||||
|
/// month name from its number
|
||||||
|
#let month_gen(month) = (
|
||||||
|
"січня",
|
||||||
|
"лютого",
|
||||||
|
"березня",
|
||||||
|
"квітня",
|
||||||
|
"травня",
|
||||||
|
"червня",
|
||||||
|
"липня",
|
||||||
|
"серпня",
|
||||||
|
"вересня",
|
||||||
|
"жовтня",
|
||||||
|
"листопада",
|
||||||
|
"грудня",
|
||||||
|
).at(month - 1)
|
||||||
|
|
||||||
|
#let is-cyr(c) = regex("[\p{Cyrillic}]") in c
|
||||||
|
|
||||||
|
#let gender-form(verb, gender: "p") = {
|
||||||
|
(
|
||||||
|
"author": ("m": "Виконав", "f": "Виконала", "p": "Виконали"),
|
||||||
|
"mentor": ("m": "Перевірив", "f": "Перевірила", "p": "Перевірили"),
|
||||||
|
)
|
||||||
|
.at(verb)
|
||||||
|
.at(if gender == "m" or gender == "f" { gender } else { "p" }, default: "p")
|
||||||
|
}
|
||||||
|
|
||||||
|
#let pz-lb-title(type, number: none) = {
|
||||||
|
let type-title = (
|
||||||
|
"ЛБ": [Звіт \ з лабораторної роботи],
|
||||||
|
"ПЗ": [Звіт \ з практичної роботи],
|
||||||
|
"КР": [Контрольна робота],
|
||||||
|
"РФ": [Реферат], // зрада
|
||||||
|
).at(type, default: type)
|
||||||
|
if number != none { [#type-title №#number] } else { [#type-title] }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper functions {{{1
|
||||||
|
|
||||||
|
/// captioned image with label derived from path:
|
||||||
|
/// - "image.png" = @image
|
||||||
|
/// - "img/image.png" = @image
|
||||||
|
/// - "img/foo/image.png" = @foo_image
|
||||||
|
/// - "img/foo/foo_image.png" = @foo_image
|
||||||
|
/// the caption will be modified based on a conditional positional value:
|
||||||
|
/// - `none`: no change
|
||||||
|
/// - some value: "`caption` (за даними `value`)"
|
||||||
|
/// - no value: "`caption` (рисунок виконано самостійно)"
|
||||||
|
/// additional named arguments will be passed to original `image` function
|
||||||
|
#let img(path, caption, ..sink) = {
|
||||||
|
let parts = path.split(".").first().split("/")
|
||||||
|
|
||||||
|
let label_string = if (
|
||||||
|
parts.len() <= 2 or parts.at(-1).starts-with(parts.at(-2))
|
||||||
|
) {
|
||||||
|
// ("image",), (_, "image") and (.., "img", "img_image")
|
||||||
|
parts.last()
|
||||||
|
} else {
|
||||||
|
// (.., "img", "image") = "img_image"
|
||||||
|
parts.at(-2) + "_" + parts.at(-1)
|
||||||
|
}.replace(" ", "_")
|
||||||
|
|
||||||
|
let caption = if sink.pos().len() == 0 {
|
||||||
|
caption
|
||||||
|
} else if sink.pos().first() == none {
|
||||||
|
caption + " (рисунок виконано самостійно)"
|
||||||
|
} else {
|
||||||
|
[#caption (за даними #sink.pos().first())]
|
||||||
|
}
|
||||||
|
|
||||||
|
[#figure(
|
||||||
|
image(path, ..sink.named()),
|
||||||
|
caption: caption,
|
||||||
|
) #label(label_string)]
|
||||||
|
}
|
||||||
|
|
||||||
|
#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)
|
||||||
|
show figure.where(kind: raw): set figure.caption(position: top)
|
||||||
|
show figure.where(kind: raw): set align(left)
|
||||||
|
|
||||||
|
// Numbering {{{1
|
||||||
|
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))
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
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.where(block: true): it => {
|
||||||
|
let new_spacing = 0.5em
|
||||||
|
set block(spacing: new_spacing)
|
||||||
|
set par(spacing: new_spacing, leading: new_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) = /* {{{ */ {
|
||||||
|
// Numbering
|
||||||
|
counter(heading).update(0)
|
||||||
|
set heading(numbering: (i, ..n) => upper(num-to-alpha.at(i)) + numbering(".1.1", ..n))
|
||||||
|
set figure(numbering: i => upper(num-to-alpha.at(counter(heading).get().at(0))).i)
|
||||||
|
set math.equation(numbering: i => upper(num-to-alpha.at(counter(heading).get().at(0))).i)
|
||||||
|
|
||||||
|
// Heading supplement (Heading name shown when citing with @ref)
|
||||||
|
set heading(supplement: [Додаток])
|
||||||
|
|
||||||
|
// Headings
|
||||||
|
show heading: it => if it.level == 1 {
|
||||||
|
set align(center)
|
||||||
|
set text(size: 14pt, weight: "regular")
|
||||||
|
|
||||||
|
pagebreak(weak: true)
|
||||||
|
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
|
||||||
|
} // }}}
|
||||||
|
|
||||||
|
// Coursework template {{{1
|
||||||
|
|
||||||
|
/// DSTU 3008:2015 Template for NURE
|
||||||
|
/// -> content
|
||||||
|
/// - doc (content): Content to apply the template to.
|
||||||
|
/// - title (str): Title of the document.
|
||||||
|
/// - subject (str): Subject short name.
|
||||||
|
/// - authors ((name: str, full_name_gen: str, variant: int, course: int, semester: int, group: str, gender: str),): List of authors.
|
||||||
|
/// - mentors ((name: str, degree: str),): List of mentors.
|
||||||
|
/// - task_list (done_date: datetime, initial_date: datetime, source: (content | str), content: (content | str), graphics: (content | str)): Task list object.
|
||||||
|
/// - calendar_plan ( plan_table: (content | str), approval_date: datetime): Calendar plan object.
|
||||||
|
/// - abstract (keywords: (str, ), text: (content | str)): Abstract object.
|
||||||
|
/// - bib_path path: Path to the bibliography yaml file.
|
||||||
|
/// - appendices (content): Content with appendices.
|
||||||
|
#let coursework(
|
||||||
|
doc,
|
||||||
|
university: "ХНУРЕ",
|
||||||
|
subject: none,
|
||||||
|
title: none,
|
||||||
|
authors: (),
|
||||||
|
mentors: (),
|
||||||
|
task_list: (),
|
||||||
|
calendar_plan: (),
|
||||||
|
abstract: (),
|
||||||
|
bib_path: none,
|
||||||
|
appendices: (),
|
||||||
|
) = {
|
||||||
|
set document(title: title, author: authors.map(c => c.name))
|
||||||
|
|
||||||
|
show: dstu-style.with(skip: 1)
|
||||||
|
|
||||||
|
let bib-count = state("citation-counter", ())
|
||||||
|
show cite: it => {
|
||||||
|
it
|
||||||
|
bib-count.update(((..c)) => (..c, it.key))
|
||||||
|
}
|
||||||
|
show bibliography: it => {
|
||||||
|
set text(size: 0pt)
|
||||||
|
it
|
||||||
|
}
|
||||||
|
|
||||||
|
let author = authors.first()
|
||||||
|
let head_mentor = mentors.first()
|
||||||
|
let uni = universities.at(university)
|
||||||
|
let edu_prog = uni.edu_programs.at(author.edu_program)
|
||||||
|
|
||||||
|
// page 1 {{{2
|
||||||
|
[
|
||||||
|
#set align(center)
|
||||||
|
МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ\
|
||||||
|
#upper(uni.name)
|
||||||
|
|
||||||
|
\
|
||||||
|
|
||||||
|
Кафедра #edu_prog.department_gen
|
||||||
|
|
||||||
|
\
|
||||||
|
|
||||||
|
ПОЯСНЮВАЛЬНА ЗАПИСКА\
|
||||||
|
ДО КУРСОВОЇ РОБОТИ\
|
||||||
|
з дисципліни: "#uni.subjects.at(subject, default: subject)"\
|
||||||
|
Тема роботи: "#title"
|
||||||
|
|
||||||
|
\ \ \
|
||||||
|
|
||||||
|
#columns(2, gutter: 4cm)[
|
||||||
|
#set align(left)
|
||||||
|
#set par(first-line-indent: 0pt)
|
||||||
|
|
||||||
|
#gender-form("author", gender: author.gender) ст. гр. #author.edu_program\-#author.group
|
||||||
|
|
||||||
|
\
|
||||||
|
Керівник:\
|
||||||
|
#head_mentor.degree
|
||||||
|
|
||||||
|
\
|
||||||
|
Робота захищена на оцінку
|
||||||
|
|
||||||
|
\
|
||||||
|
Комісія:\
|
||||||
|
#for m in mentors { [#m.degree\ ] }
|
||||||
|
|
||||||
|
#colbreak()
|
||||||
|
#set align(left)
|
||||||
|
|
||||||
|
|
||||||
|
#author.name
|
||||||
|
|
||||||
|
\ \
|
||||||
|
#head_mentor.name
|
||||||
|
|
||||||
|
\
|
||||||
|
#underline(" " * 35)
|
||||||
|
|
||||||
|
\ \
|
||||||
|
#for m in mentors { [#m.name\ ] }
|
||||||
|
]
|
||||||
|
|
||||||
|
#v(1fr)
|
||||||
|
|
||||||
|
Харків -- #task_list.done_date.display("[year]")
|
||||||
|
|
||||||
|
#pagebreak()
|
||||||
|
]
|
||||||
|
|
||||||
|
// page 2 {{{2
|
||||||
|
{
|
||||||
|
uline[#uni.name]
|
||||||
|
|
||||||
|
linebreak()
|
||||||
|
linebreak()
|
||||||
|
|
||||||
|
grid(
|
||||||
|
columns: (100pt, 1fr),
|
||||||
|
bold[
|
||||||
|
Кафедра
|
||||||
|
Дисципліна
|
||||||
|
Спеціальність
|
||||||
|
],
|
||||||
|
{
|
||||||
|
uline(align: left, edu_prog.department_gen)
|
||||||
|
linebreak()
|
||||||
|
uline(align: left, uni.subjects.at(subject, default: subject))
|
||||||
|
linebreak()
|
||||||
|
uline(align: left, [#edu_prog.code #edu_prog.name_long])
|
||||||
|
},
|
||||||
|
)
|
||||||
|
grid(
|
||||||
|
columns: (1fr, 1fr, 1fr),
|
||||||
|
gutter: 0.3fr,
|
||||||
|
[#bold[Курс] #uline(author.course)],
|
||||||
|
[#bold[Група] #uline([#author.edu_program\-#author.group])],
|
||||||
|
[#bold[Семестр] #uline(author.semester)],
|
||||||
|
)
|
||||||
|
|
||||||
|
linebreak()
|
||||||
|
linebreak()
|
||||||
|
linebreak()
|
||||||
|
|
||||||
|
align(center, bold[ЗАВДАННЯ \ на курсову роботу студента])
|
||||||
|
|
||||||
|
linebreak()
|
||||||
|
|
||||||
|
uline(align: left)[_#author.full_name_gen _]
|
||||||
|
|
||||||
|
linebreak()
|
||||||
|
linebreak()
|
||||||
|
|
||||||
|
bold[\1. Тема роботи:]
|
||||||
|
uline[#title.]
|
||||||
|
|
||||||
|
linebreak()
|
||||||
|
|
||||||
|
{
|
||||||
|
bold[\2. Строк здачі закінченої роботи:]
|
||||||
|
uline(task_list.done_date.display("[day].[month].[year]"))
|
||||||
|
hfill(10fr)
|
||||||
|
}
|
||||||
|
|
||||||
|
linebreak()
|
||||||
|
|
||||||
|
bold[\3. Вихідні дані для роботи:]
|
||||||
|
uline(task_list.source)
|
||||||
|
|
||||||
|
linebreak()
|
||||||
|
|
||||||
|
bold[\4. Зміст розрахунково-пояснювальної записки:]
|
||||||
|
uline(task_list.content)
|
||||||
|
|
||||||
|
linebreak()
|
||||||
|
|
||||||
|
bold[\5. Перелік графічного матеріалу:]
|
||||||
|
uline(task_list.graphics)
|
||||||
|
|
||||||
|
linebreak()
|
||||||
|
|
||||||
|
{
|
||||||
|
bold[\6. Дата видачі завдання:]
|
||||||
|
uline(task_list.initial_date.display("[day].[month].[year]"))
|
||||||
|
hfill(10fr)
|
||||||
|
}
|
||||||
|
|
||||||
|
pagebreak()
|
||||||
|
}
|
||||||
|
|
||||||
|
// page 3 {{{2
|
||||||
|
{
|
||||||
|
align(center, bold[КАЛЕНДАРНИЙ ПЛАН])
|
||||||
|
set par(first-line-indent: 0pt)
|
||||||
|
|
||||||
|
linebreak()
|
||||||
|
|
||||||
|
calendar_plan.plan_table
|
||||||
|
|
||||||
|
linebreak()
|
||||||
|
|
||||||
|
grid(
|
||||||
|
columns: (5fr, 5fr),
|
||||||
|
grid(
|
||||||
|
columns: (1fr, 2fr, 1fr),
|
||||||
|
gutter: 0.2fr,
|
||||||
|
[
|
||||||
|
Студент \
|
||||||
|
Керівник \
|
||||||
|
#align(center)["#underline[#calendar_plan.approval_date.day()]"]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
#uline(align: center, []) \
|
||||||
|
#uline(align: center, []) \
|
||||||
|
#uline(align: center, month_gen(calendar_plan.approval_date.month()))
|
||||||
|
],
|
||||||
|
[
|
||||||
|
\ \
|
||||||
|
#underline[#calendar_plan.approval_date.year()] р.
|
||||||
|
],
|
||||||
|
),
|
||||||
|
[
|
||||||
|
#author.name, \
|
||||||
|
#head_mentor.degree
|
||||||
|
#head_mentor.name.
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
pagebreak()
|
||||||
|
}
|
||||||
|
|
||||||
|
// page 4 {{{2
|
||||||
|
[
|
||||||
|
#align(center, bold[РЕФЕРАТ]) \
|
||||||
|
|
||||||
|
#context [
|
||||||
|
#let pages = counter(page).final().at(0)
|
||||||
|
#let images = query(figure.where(kind: image)).len()
|
||||||
|
#let tables = query(figure.where(kind: table)).len()
|
||||||
|
#let bibs = bib-count.final().dedup().len()
|
||||||
|
/* TODO: why this stopped working?
|
||||||
|
#let tables = counter(figure.where(kind: table)).final().at(0)
|
||||||
|
#let images = counter(figure.where(kind: image)).final().at(0)*/
|
||||||
|
|
||||||
|
#let counters = ()
|
||||||
|
|
||||||
|
#if pages != 0 { counters.push[#pages с.] }
|
||||||
|
#if tables != 0 { counters.push[#tables табл.] }
|
||||||
|
#if images != 0 { counters.push[#images рис.] }
|
||||||
|
#if bibs != 0 { counters.push[#bibs джерел] }
|
||||||
|
|
||||||
|
Пояснювальна записка до курсової роботи: #counters.join(", ").
|
||||||
|
]
|
||||||
|
|
||||||
|
\
|
||||||
|
|
||||||
|
#(
|
||||||
|
abstract
|
||||||
|
.keywords
|
||||||
|
.map(upper)
|
||||||
|
.sorted(by: (a, b) => {
|
||||||
|
if is-cyr(a) != is-cyr(b) { true } else { a < b }
|
||||||
|
})
|
||||||
|
.join(", ")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
\
|
||||||
|
|
||||||
|
#abstract.text
|
||||||
|
]
|
||||||
|
|
||||||
|
// page 5 {{{2
|
||||||
|
outline(
|
||||||
|
title: [
|
||||||
|
ЗМІСТ
|
||||||
|
#v(spacing * 2, weak: true)
|
||||||
|
],
|
||||||
|
depth: 2,
|
||||||
|
indent: auto,
|
||||||
|
)
|
||||||
|
|
||||||
|
doc
|
||||||
|
|
||||||
|
// bibliography {{{2
|
||||||
|
{
|
||||||
|
heading(depth: 1, numbering: none)[Перелік джерел посилання]
|
||||||
|
|
||||||
|
bibliography(
|
||||||
|
bib_path,
|
||||||
|
style: "ieee",
|
||||||
|
full: true,
|
||||||
|
title: none,
|
||||||
|
)
|
||||||
|
|
||||||
|
let bib_data = yaml(bib_path)
|
||||||
|
|
||||||
|
let format-entry(c) = {
|
||||||
|
if (c.type == "Web") {
|
||||||
|
let date_array = c.url.date.split("-")
|
||||||
|
let date = datetime(
|
||||||
|
year: int(date_array.at(0)),
|
||||||
|
month: int(date_array.at(1)),
|
||||||
|
day: int(date_array.at(2)),
|
||||||
|
)
|
||||||
|
[#c.title. #c.author. URL: #c.url.value (дата звернення: #date.display("[day].[month].[year]")).]
|
||||||
|
} else if (
|
||||||
|
c.type == "Book"
|
||||||
|
) [#c.author #c.title. #c.publisher, #c.date. #c.page-total c. ] else [
|
||||||
|
UNSUPPORTED BIBLIOGRAPHY ENTRY TYPE, PLEASE OPEN AN ISSUE
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
show enum.item: it => {
|
||||||
|
set par(first-line-indent: 0pt)
|
||||||
|
box(width: 1.25cm)
|
||||||
|
box(width: 1em + 0.5cm)[#it.number.]
|
||||||
|
it.body
|
||||||
|
linebreak()
|
||||||
|
}
|
||||||
|
|
||||||
|
context {
|
||||||
|
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)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
appendices-style(appendices)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Practice and Laboratory works template {{{1
|
||||||
|
|
||||||
|
/// DSTU 3008:2015 Template for NURE
|
||||||
|
/// -> content
|
||||||
|
/// - doc (content): Content to apply the template to.
|
||||||
|
/// - university: "ХНУРЕ": University metadata. Optional.
|
||||||
|
/// - subject: str: Subject shortcode.
|
||||||
|
/// - type: ("ЛБ" | "ПЗ" | "КР" | "РФ" | str): Work type.
|
||||||
|
/// - number: int or none: Work number. Optional.
|
||||||
|
/// - title: str or none: Work title. Optional.
|
||||||
|
/// - authors ((name: str, full_name_gen: str or none, edu_program: str, group: str, gender: str, variant: int or none),): List of authors.
|
||||||
|
/// - mentors ((name: str, degree: str, gender: ("m" | "f" | "p" | none)),): List of mentors. Optional.
|
||||||
|
#let pz-lb(
|
||||||
|
doc,
|
||||||
|
university: "ХНУРЕ",
|
||||||
|
subject: none,
|
||||||
|
type: none,
|
||||||
|
number: none,
|
||||||
|
title: none,
|
||||||
|
authors: (),
|
||||||
|
mentors: (),
|
||||||
|
) = {
|
||||||
|
// TODO: add actually relevant asserts
|
||||||
|
|
||||||
|
let edu_program = authors.first().edu_program
|
||||||
|
let uni = universities.at(university)
|
||||||
|
|
||||||
|
set document(title: title, author: authors.map(c => c.name))
|
||||||
|
|
||||||
|
show: dstu-style.with(skip: 1)
|
||||||
|
|
||||||
|
// page 1 {{{2
|
||||||
|
|
||||||
|
align(center)[
|
||||||
|
МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ \
|
||||||
|
#upper(uni.name)
|
||||||
|
|
||||||
|
\ \
|
||||||
|
Кафедра #uni.edu_programs.at(edu_program).department_gen
|
||||||
|
|
||||||
|
\ \ \
|
||||||
|
#pz-lb-title(type, number: number)
|
||||||
|
|
||||||
|
з дисципліни: "#uni.subjects.at(subject, default: subject)"
|
||||||
|
#if title != none [\ з теми: "#eval(title, mode: "markup")"]
|
||||||
|
|
||||||
|
|
||||||
|
\ \ \ \
|
||||||
|
#columns(2)[
|
||||||
|
#set align(left)
|
||||||
|
#set par(first-line-indent: 0pt)
|
||||||
|
|
||||||
|
#if authors.len() == 1 {
|
||||||
|
[#gender-form("author", gender: if "gender" in a.keys() { a.gender } else { none }):\ ]
|
||||||
|
let a = authors.first()
|
||||||
|
[ст. гр. #a.edu_program\-#a.group\ #a.name\ ]
|
||||||
|
if a.variant != none [Варіант: №#a.variant]
|
||||||
|
} else if authors.len() > 1 [
|
||||||
|
#gender-form("author"):\
|
||||||
|
#for a in authors [ст. гр. #a.edu_program\-#a.group\ #a.name\ ]
|
||||||
|
]
|
||||||
|
|
||||||
|
#colbreak()
|
||||||
|
#set align(right)
|
||||||
|
|
||||||
|
#if mentors.len() == 1 {
|
||||||
|
[#gender-form("mentor", gender: if "gender" in m.keys() { m.gender } else { none }):\ ]
|
||||||
|
let m = mentors.first()
|
||||||
|
if "degree" in m.keys() and m.degree != none [#m.degree\ ]
|
||||||
|
[#m.name\ ]
|
||||||
|
} else if mentors.len() > 1 [
|
||||||
|
#gender-form("mentor"):\
|
||||||
|
#for mentor in mentors { [#mentor.degree\ #mentor.name\ ] }]
|
||||||
|
]
|
||||||
|
|
||||||
|
#v(1fr)
|
||||||
|
|
||||||
|
Харків -- #datetime.today().display("[year]")
|
||||||
|
]
|
||||||
|
|
||||||
|
pagebreak(weak: true)
|
||||||
|
|
||||||
|
// TODO(unexplrd): wrap my head around the old way
|
||||||
|
if title == none {
|
||||||
|
if number == none { context counter(heading).update(1) } else {
|
||||||
|
context counter(heading).update(number)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if number != none { context counter(heading).update(number - 1) }
|
||||||
|
heading(eval(title, mode: "markup"))
|
||||||
|
}
|
||||||
|
|
||||||
|
doc
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim:sts=2:sw=2:fdm=marker:cms=/*%s*/
|
||||||
@@ -19,72 +19,49 @@
|
|||||||
code: 122
|
code: 122
|
||||||
subjects:
|
subjects:
|
||||||
DMT: Decision making theory
|
DMT: Decision making theory
|
||||||
NoSQL: NoSQL-системи
|
|
||||||
ODS: Основи Dаtа Sсіеnсе # NOTE: Eng O here
|
ODS: Основи Dаtа Sсіеnсе # NOTE: Eng O here
|
||||||
|
ІМ: Іноземна мова
|
||||||
|
ІТР: Information Technologies of Reengineering
|
||||||
|
ІТРОІ: Інтернет-технології Розподіленої Обробки Інформації
|
||||||
АВпЗ: Аналіз вимог до програмного забезпечення
|
АВпЗ: Аналіз вимог до програмного забезпечення
|
||||||
АДан: Аналітика даних
|
АДан: Аналітика даних
|
||||||
АКС: Архітектура комп'ютерних систем
|
|
||||||
АКтаК: Архітектура комп'ютера та комп'ютерних мереж
|
АКтаК: Архітектура комп'ютера та комп'ютерних мереж
|
||||||
АПЗ: Архітектура програмного забезпечення
|
|
||||||
АтаРК: Аналіз та рефакторинг коду
|
|
||||||
АТСД: Алгоритми та структури даних
|
АТСД: Алгоритми та структури даних
|
||||||
|
АтаРК: Аналіз та рефакторинг коду
|
||||||
БД: Бази даних
|
БД: Бази даних
|
||||||
БЖД: Безпека життєдіяльності
|
БЖД: Безпека життєдіяльності
|
||||||
ВSAP: Введення до SAP-технологій
|
|
||||||
ВДІТБ: Введення до ІТ-бізнесу # NOTE: all in UA
|
ВДІТБ: Введення до ІТ-бізнесу # NOTE: all in UA
|
||||||
ВМ: Вища математика
|
ВМ: Вища математика
|
||||||
ВМПтФ: Високорівневі мови програмування та фреймворки
|
|
||||||
ГТГ: Гіпертекст та гіпермедіа
|
ГТГ: Гіпертекст та гіпермедіа
|
||||||
ДМ: Дискретна математика
|
ДМ: Дискретна математика
|
||||||
ДПК: Динаміка Проектних Команд
|
ДПК: Динаміка Проектних Команд
|
||||||
ЕРВ: Електрорадіовимірювання
|
ЕРВ: Електрорадіовимірювання
|
||||||
ІКС: Інформаційно-комунікаційні системи
|
|
||||||
ІМ: Іноземна мова
|
|
||||||
ІМпк: Іноземна мова для професійної комунікації
|
|
||||||
ІНТ: Історія науки і техніки
|
|
||||||
ІТР: Information Technologies of Reengineering
|
|
||||||
ІТРОІ: Інтернет-технології Розподіленої Обробки Інформації
|
|
||||||
КДМА: Комп'ютерна дискретна математика
|
КДМА: Комп'ютерна дискретна математика
|
||||||
КЗВШ: Креативність з використанням штучного інтелекту
|
КЗВШ: Креативність з використанням штучного інтелекту
|
||||||
КМ: Комп'ютерні мережі
|
КМ: Комп`ютерні мережі
|
||||||
ЛМВ: Людино-машинна взаємодія
|
ЛМВ: Людино-машинна взаємодія
|
||||||
ЛМтБ: Локальні мережі та їх безпека
|
ЛМтБ: Локальні мережі та їх безпека # бидло не знає що українською "їхня"
|
||||||
Лог: Логіка
|
|
||||||
МБ: Мережна безпека
|
|
||||||
МКр: Мережна криміналістика
|
|
||||||
МОКр: Математичні основи криптології
|
МОКр: Математичні основи криптології
|
||||||
МОТДО: Методи оптимізаціі та дослідження операцій
|
МОТДО: Методи оптимізаціі та дослідження операцій
|
||||||
МОТІ: Методи оптимізації та теорія ігор
|
|
||||||
МППЗ: Менеджмент проектів програмного забезпечення
|
|
||||||
МППС: Methodologies of designing software systems
|
МППС: Methodologies of designing software systems
|
||||||
МС: Моделювання систем
|
МС: Моделювання систем
|
||||||
ОІДт: Обробка ігрових даних та звітів
|
|
||||||
ОІМ: Основи IP-мереж
|
ОІМ: Основи IP-мереж
|
||||||
ОКЗІ: Основи криптографічного захисту інформації
|
|
||||||
ООАПС: Об'єктно-орієнтований аналіз в проектуванні систем
|
ООАПС: Об'єктно-орієнтований аналіз в проектуванні систем
|
||||||
ООП: Об'єктно-орієнтоване програмування
|
ООП: Об'єктно-орієнтоване програмування
|
||||||
|
ОП: Основи права
|
||||||
ОПІ: Основи програмноі інженеріі
|
ОПІ: Основи програмноі інженеріі
|
||||||
ОПНJ: Основи програмування на Java
|
ОПНJ: Основи програмування на Java
|
||||||
ОП: Основи права
|
|
||||||
ОПр: Основи програмування
|
ОПр: Основи програмування
|
||||||
ОРвІТ: Оцінка Ризиків в IT-проектах
|
ОРвІТ: Оцінка Ризиків в IT-проектах
|
||||||
ОС: Операційні системи
|
ОС: Операційні системи
|
||||||
ОТК: Основи теорії кіл
|
ОТК: Основи теорії кіл
|
||||||
ПPyt: Програмування мовою Python
|
|
||||||
ПарП: Параллельне програмування
|
|
||||||
ПБІП: Проектування та балансування ігрового процесу
|
ПБІП: Проектування та балансування ігрового процесу
|
||||||
ПВJS: Поглиблене вивчення JavaScript
|
|
||||||
ПВJ: Поглиблене вивчення Java
|
ПВJ: Поглиблене вивчення Java
|
||||||
ПвІТ: Підприємництво в ІТ
|
|
||||||
ПЕСЕ: Психологія екстремальних стосунків та ефективної адаптації
|
ПЕСЕ: Психологія екстремальних стосунків та ефективної адаптації
|
||||||
ПНП: Програмування на платформі .NЕТ
|
ПНП: Програмування на платформі .NЕТ
|
||||||
ПП: Проектний практикум
|
ПП: Проектний практикум
|
||||||
Про1: Програмування (ч. 1)
|
ПРОГ: Програмування
|
||||||
Про2: Програмування (ч. 2)
|
ПарП: Параллельне програмування
|
||||||
Про3: Програмування (ч. 3)
|
|
||||||
Прог: Програмування # NOTE: was "ПРОГ" before
|
|
||||||
РNet: Робота з даними на платформі .Net
|
|
||||||
РХЗ: Розробка хмарних застосувань в AZURE
|
|
||||||
СА: Системний аналіз
|
СА: Системний аналіз
|
||||||
СМП: Скриптові мови програмування
|
СМП: Скриптові мови програмування
|
||||||
СОАПЗ: Сервіс-Орієнтована Архітектура Програмного Забезпечення
|
СОАПЗ: Сервіс-Орієнтована Архітектура Програмного Забезпечення
|
||||||
@@ -92,11 +69,10 @@
|
|||||||
СхТ: Схемотехніка
|
СхТ: Схемотехніка
|
||||||
ТВО: Технології Високопродуктивних Обчислень
|
ТВО: Технології Високопродуктивних Обчислень
|
||||||
ТЗІ: Технології захисту інформації
|
ТЗІ: Технології захисту інформації
|
||||||
ТІК: Теорія інформації та кодування
|
|
||||||
ТЙтаМ: Теорія ймовірностей та математична # TODO: what?
|
ТЙтаМ: Теорія ймовірностей та математична # TODO: what?
|
||||||
ТКП: Технології комп'ютерного проєктування
|
ТКП: Технології комп`ютерного проєктування
|
||||||
УФМ: Українське фахове мовлення
|
УФМ: Українське фахове мовлення
|
||||||
ФВС: Фізичне виховання та спорт
|
|
||||||
ФІЗ: Фізика
|
ФІЗ: Фізика
|
||||||
ФІЛ: Філософія
|
ФІЛ: Філософія
|
||||||
|
ФВС: Фізичне виховання та спорт
|
||||||
ХТ: Хмарні технології
|
ХТ: Хмарні технології
|
||||||
|
|||||||
@@ -1,420 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<style xmlns="http://purl.org/net/xbiblio/csl"
|
|
||||||
class="in-text"
|
|
||||||
version="1.0"
|
|
||||||
default-locale="uk-UA"
|
|
||||||
demote-non-dropping-particle="never">
|
|
||||||
|
|
||||||
<info>
|
|
||||||
<title>ДСТУ 8302:2015 — бібліографічні посилання</title>
|
|
||||||
<title-short>ДСТУ 8302:2015</title-short>
|
|
||||||
<id>dstu-8302-2015-typst</id>
|
|
||||||
<link href="https://online.budstandart.com/ua/catalog/doc-page.html?id_doc=64411" rel="documentation"/>
|
|
||||||
<author>
|
|
||||||
<name>Custom Typst CSL</name>
|
|
||||||
</author>
|
|
||||||
<category citation-format="numeric"/>
|
|
||||||
<category field="generic-base"/>
|
|
||||||
<summary>CSL для оформлення переліку джерел за логікою ДСТУ 8302:2015 у Typst/Pandoc: числові посилання, українські скорочення, DOI/URL, дата звернення, коректні вебджерела, статті та нормативні акти.</summary>
|
|
||||||
<updated>2026-05-25T00:00:00+00:00</updated>
|
|
||||||
<rights license="http://creativecommons.org/licenses/by-sa/4.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 License</rights>
|
|
||||||
</info>
|
|
||||||
|
|
||||||
<locale xml:lang="uk-UA">
|
|
||||||
<terms>
|
|
||||||
<term name="accessed">дата звернення</term>
|
|
||||||
<term name="page" form="short">С.</term>
|
|
||||||
<term name="page" form="symbol">с.</term>
|
|
||||||
<term name="volume" form="short">Т.</term>
|
|
||||||
<term name="issue" form="short">№</term>
|
|
||||||
<term name="edition" form="short">вид.</term>
|
|
||||||
<term name="editor" form="short">ред.</term>
|
|
||||||
<term name="translator" form="short">пер.</term>
|
|
||||||
<term name="et-al">та ін.</term>
|
|
||||||
<term name="and">,</term>
|
|
||||||
</terms>
|
|
||||||
</locale>
|
|
||||||
|
|
||||||
<!-- Ініціали після прізвища: Vergara L. M., Park M. -->
|
|
||||||
<macro name="contributors">
|
|
||||||
<names variable="author">
|
|
||||||
<name name-as-sort-order="all"
|
|
||||||
sort-separator=" "
|
|
||||||
initialize-with=". "
|
|
||||||
delimiter=", "
|
|
||||||
delimiter-precedes-last="never"/>
|
|
||||||
<substitute>
|
|
||||||
<names variable="editor">
|
|
||||||
<name name-as-sort-order="all"
|
|
||||||
sort-separator=" "
|
|
||||||
initialize-with=". "
|
|
||||||
delimiter=", "
|
|
||||||
delimiter-precedes-last="never"/>
|
|
||||||
<label form="short" prefix=" (" suffix=")"/>
|
|
||||||
</names>
|
|
||||||
<names variable="translator">
|
|
||||||
<name name-as-sort-order="all"
|
|
||||||
sort-separator=" "
|
|
||||||
initialize-with=". "
|
|
||||||
delimiter=", "
|
|
||||||
delimiter-precedes-last="never"/>
|
|
||||||
<label form="short" prefix=" (" suffix=")"/>
|
|
||||||
</names>
|
|
||||||
</substitute>
|
|
||||||
</names>
|
|
||||||
</macro>
|
|
||||||
|
|
||||||
<macro name="title">
|
|
||||||
<text variable="title"/>
|
|
||||||
</macro>
|
|
||||||
|
|
||||||
<macro name="container">
|
|
||||||
<text variable="container-title"/>
|
|
||||||
</macro>
|
|
||||||
|
|
||||||
<macro name="site-or-publisher">
|
|
||||||
<choose>
|
|
||||||
<if variable="container-title">
|
|
||||||
<text variable="container-title"/>
|
|
||||||
</if>
|
|
||||||
<else>
|
|
||||||
<text variable="publisher"/>
|
|
||||||
</else>
|
|
||||||
</choose>
|
|
||||||
</macro>
|
|
||||||
|
|
||||||
<macro name="issued-year">
|
|
||||||
<date variable="issued">
|
|
||||||
<date-part name="year"/>
|
|
||||||
</date>
|
|
||||||
</macro>
|
|
||||||
|
|
||||||
<macro name="issued-date">
|
|
||||||
<date variable="issued">
|
|
||||||
<date-part name="day" form="numeric-leading-zeros" suffix="."/>
|
|
||||||
<date-part name="month" form="numeric-leading-zeros" suffix="."/>
|
|
||||||
<date-part name="year"/>
|
|
||||||
</date>
|
|
||||||
</macro>
|
|
||||||
|
|
||||||
<macro name="accessed-date">
|
|
||||||
<date variable="accessed">
|
|
||||||
<date-part name="day" form="numeric-leading-zeros" suffix="."/>
|
|
||||||
<date-part name="month" form="numeric-leading-zeros" suffix="."/>
|
|
||||||
<date-part name="year"/>
|
|
||||||
</date>
|
|
||||||
</macro>
|
|
||||||
|
|
||||||
<macro name="publisher-place">
|
|
||||||
<group delimiter=" : ">
|
|
||||||
<text variable="publisher-place"/>
|
|
||||||
<text variable="publisher"/>
|
|
||||||
</group>
|
|
||||||
</macro>
|
|
||||||
|
|
||||||
<macro name="edition">
|
|
||||||
<group delimiter=" ">
|
|
||||||
<text variable="edition"/>
|
|
||||||
<label variable="edition" form="short"/>
|
|
||||||
</group>
|
|
||||||
</macro>
|
|
||||||
|
|
||||||
<macro name="book-pages">
|
|
||||||
<choose>
|
|
||||||
<if variable="number-of-pages">
|
|
||||||
<group delimiter=" ">
|
|
||||||
<text variable="number-of-pages"/>
|
|
||||||
<text term="page" form="symbol"/>
|
|
||||||
</group>
|
|
||||||
</if>
|
|
||||||
<else-if variable="page">
|
|
||||||
<group delimiter=" ">
|
|
||||||
<text variable="page"/>
|
|
||||||
<text term="page" form="symbol"/>
|
|
||||||
</group>
|
|
||||||
</else-if>
|
|
||||||
</choose>
|
|
||||||
</macro>
|
|
||||||
|
|
||||||
<macro name="pages">
|
|
||||||
<choose>
|
|
||||||
<if variable="page">
|
|
||||||
<group delimiter=" ">
|
|
||||||
<text term="page" form="short"/>
|
|
||||||
<text variable="page"/>
|
|
||||||
</group>
|
|
||||||
</if>
|
|
||||||
</choose>
|
|
||||||
</macro>
|
|
||||||
|
|
||||||
<macro name="volume-issue">
|
|
||||||
<group delimiter=", ">
|
|
||||||
<choose>
|
|
||||||
<if variable="volume">
|
|
||||||
<group delimiter=" ">
|
|
||||||
<text value="Т."/>
|
|
||||||
<text variable="volume"/>
|
|
||||||
</group>
|
|
||||||
</if>
|
|
||||||
</choose>
|
|
||||||
<choose>
|
|
||||||
<if variable="issue">
|
|
||||||
<group delimiter=" ">
|
|
||||||
<text value="№"/>
|
|
||||||
<text variable="issue"/>
|
|
||||||
</group>
|
|
||||||
</if>
|
|
||||||
</choose>
|
|
||||||
</group>
|
|
||||||
</macro>
|
|
||||||
|
|
||||||
<macro name="url-access">
|
|
||||||
<choose>
|
|
||||||
<if variable="URL">
|
|
||||||
<group delimiter=" ">
|
|
||||||
<text variable="URL" prefix="URL: "/>
|
|
||||||
<choose>
|
|
||||||
<if variable="accessed">
|
|
||||||
<group delimiter=": " prefix="(" suffix=")">
|
|
||||||
<text term="accessed"/>
|
|
||||||
<text macro="accessed-date"/>
|
|
||||||
</group>
|
|
||||||
</if>
|
|
||||||
</choose>
|
|
||||||
</group>
|
|
||||||
</if>
|
|
||||||
</choose>
|
|
||||||
</macro>
|
|
||||||
|
|
||||||
<macro name="doi-or-url">
|
|
||||||
<choose>
|
|
||||||
<if variable="DOI">
|
|
||||||
<text variable="DOI" prefix="DOI: "/>
|
|
||||||
</if>
|
|
||||||
<else>
|
|
||||||
<text macro="url-access"/>
|
|
||||||
</else>
|
|
||||||
</choose>
|
|
||||||
</macro>
|
|
||||||
|
|
||||||
<macro name="legal-details">
|
|
||||||
<choose>
|
|
||||||
<if variable="genre">
|
|
||||||
<group delimiter=" : ">
|
|
||||||
<text macro="title"/>
|
|
||||||
<group delimiter=" ">
|
|
||||||
<text variable="genre"/>
|
|
||||||
<choose>
|
|
||||||
<if variable="issued">
|
|
||||||
<group delimiter=" ">
|
|
||||||
<text value="від"/>
|
|
||||||
<text macro="issued-date"/>
|
|
||||||
</group>
|
|
||||||
</if>
|
|
||||||
</choose>
|
|
||||||
<choose>
|
|
||||||
<if variable="number">
|
|
||||||
<group delimiter=" ">
|
|
||||||
<text value="№"/>
|
|
||||||
<text variable="number"/>
|
|
||||||
</group>
|
|
||||||
</if>
|
|
||||||
</choose>
|
|
||||||
</group>
|
|
||||||
</group>
|
|
||||||
</if>
|
|
||||||
<else>
|
|
||||||
<group delimiter=". ">
|
|
||||||
<text macro="title"/>
|
|
||||||
<group delimiter=" ">
|
|
||||||
<choose>
|
|
||||||
<if variable="issued">
|
|
||||||
<group delimiter=" ">
|
|
||||||
<text value="від"/>
|
|
||||||
<text macro="issued-date"/>
|
|
||||||
</group>
|
|
||||||
</if>
|
|
||||||
</choose>
|
|
||||||
<choose>
|
|
||||||
<if variable="number">
|
|
||||||
<group delimiter=" ">
|
|
||||||
<text value="№"/>
|
|
||||||
<text variable="number"/>
|
|
||||||
</group>
|
|
||||||
</if>
|
|
||||||
</choose>
|
|
||||||
</group>
|
|
||||||
</group>
|
|
||||||
</else>
|
|
||||||
</choose>
|
|
||||||
</macro>
|
|
||||||
|
|
||||||
<citation collapse="citation-number">
|
|
||||||
<sort>
|
|
||||||
<key variable="citation-number"/>
|
|
||||||
</sort>
|
|
||||||
<layout delimiter=", " prefix="[" suffix="]">
|
|
||||||
<text variable="citation-number"/>
|
|
||||||
</layout>
|
|
||||||
</citation>
|
|
||||||
|
|
||||||
<bibliography hanging-indent="false" entry-spacing="0" line-spacing="1">
|
|
||||||
<sort>
|
|
||||||
<key variable="citation-number"/>
|
|
||||||
</sort>
|
|
||||||
<layout>
|
|
||||||
<group display="block">
|
|
||||||
<text display="left-margin" variable="citation-number" suffix=". "/>
|
|
||||||
|
|
||||||
<choose>
|
|
||||||
<!-- Нормативні акти: Цивільний кодекс України : Закон України від 16.01.2003 № 435-IV. URL: ... -->
|
|
||||||
<if type="legislation bill legal_case treaty" match="any">
|
|
||||||
<group delimiter=". " suffix=".">
|
|
||||||
<text macro="legal-details"/>
|
|
||||||
<text macro="url-access"/>
|
|
||||||
</group>
|
|
||||||
</if>
|
|
||||||
|
|
||||||
<!-- Наукова стаття -->
|
|
||||||
<else-if type="article-journal">
|
|
||||||
<group delimiter=". " suffix=".">
|
|
||||||
<text macro="contributors"/>
|
|
||||||
<text macro="title"/>
|
|
||||||
<text macro="container"/>
|
|
||||||
<text macro="issued-year"/>
|
|
||||||
<text macro="volume-issue"/>
|
|
||||||
<text macro="pages"/>
|
|
||||||
<text macro="doi-or-url"/>
|
|
||||||
</group>
|
|
||||||
</else-if>
|
|
||||||
|
|
||||||
<!-- Газетна / журнальна стаття без DOI -->
|
|
||||||
<else-if type="article-newspaper article-magazine" match="any">
|
|
||||||
<group delimiter=". " suffix=".">
|
|
||||||
<text macro="contributors"/>
|
|
||||||
<text macro="title"/>
|
|
||||||
<text variable="container-title" font-style="italic"/>
|
|
||||||
<text macro="issued-date"/>
|
|
||||||
<text macro="pages"/>
|
|
||||||
<text macro="url-access"/>
|
|
||||||
</group>
|
|
||||||
</else-if>
|
|
||||||
|
|
||||||
<!-- Вебсторінки: без дублювання назви замість автора -->
|
|
||||||
<else-if type="webpage post post-weblog" match="any">
|
|
||||||
<group delimiter=". " suffix=".">
|
|
||||||
<text macro="contributors"/>
|
|
||||||
<text macro="title"/>
|
|
||||||
<text macro="site-or-publisher"/>
|
|
||||||
<text macro="issued-date"/>
|
|
||||||
<text macro="url-access"/>
|
|
||||||
</group>
|
|
||||||
</else-if>
|
|
||||||
|
|
||||||
<!-- Книга -->
|
|
||||||
<else-if type="book">
|
|
||||||
<group delimiter=". " suffix=".">
|
|
||||||
<text macro="contributors"/>
|
|
||||||
<text macro="title"/>
|
|
||||||
<text macro="edition"/>
|
|
||||||
<group delimiter=", ">
|
|
||||||
<text macro="publisher-place"/>
|
|
||||||
<text macro="issued-year"/>
|
|
||||||
</group>
|
|
||||||
<text macro="book-pages"/>
|
|
||||||
<text macro="doi-or-url"/>
|
|
||||||
</group>
|
|
||||||
</else-if>
|
|
||||||
|
|
||||||
<!-- Розділ у книзі -->
|
|
||||||
<else-if type="chapter">
|
|
||||||
<group delimiter=". " suffix=".">
|
|
||||||
<text macro="contributors"/>
|
|
||||||
<text macro="title"/>
|
|
||||||
<group delimiter=" ">
|
|
||||||
<text value="In:"/>
|
|
||||||
<text variable="container-title" font-style="italic"/>
|
|
||||||
</group>
|
|
||||||
<names variable="editor">
|
|
||||||
<name name-as-sort-order="all"
|
|
||||||
sort-separator=" "
|
|
||||||
initialize-with=". "
|
|
||||||
delimiter=", "
|
|
||||||
delimiter-precedes-last="never"/>
|
|
||||||
<label form="short" prefix=" (" suffix=")"/>
|
|
||||||
</names>
|
|
||||||
<group delimiter=", ">
|
|
||||||
<text macro="publisher-place"/>
|
|
||||||
<text macro="issued-year"/>
|
|
||||||
</group>
|
|
||||||
<text macro="pages"/>
|
|
||||||
<text macro="doi-or-url"/>
|
|
||||||
</group>
|
|
||||||
</else-if>
|
|
||||||
|
|
||||||
<!-- Матеріали конференції -->
|
|
||||||
<else-if type="paper-conference">
|
|
||||||
<group delimiter=". " suffix=".">
|
|
||||||
<text macro="contributors"/>
|
|
||||||
<text macro="title"/>
|
|
||||||
<group delimiter=" ">
|
|
||||||
<text value="In:"/>
|
|
||||||
<text variable="container-title"/>
|
|
||||||
</group>
|
|
||||||
<group delimiter=", ">
|
|
||||||
<text macro="publisher-place"/>
|
|
||||||
<text macro="issued-year"/>
|
|
||||||
</group>
|
|
||||||
<text macro="pages"/>
|
|
||||||
<text macro="doi-or-url"/>
|
|
||||||
</group>
|
|
||||||
</else-if>
|
|
||||||
|
|
||||||
<!-- Дисертації, звіти -->
|
|
||||||
<else-if type="thesis report" match="any">
|
|
||||||
<group delimiter=". " suffix=".">
|
|
||||||
<text macro="contributors"/>
|
|
||||||
<text macro="title"/>
|
|
||||||
<text variable="genre"/>
|
|
||||||
<group delimiter=", ">
|
|
||||||
<text macro="publisher-place"/>
|
|
||||||
<text macro="issued-year"/>
|
|
||||||
</group>
|
|
||||||
<text macro="book-pages"/>
|
|
||||||
<text macro="doi-or-url"/>
|
|
||||||
</group>
|
|
||||||
</else-if>
|
|
||||||
|
|
||||||
<!-- Патенти -->
|
|
||||||
<else-if type="patent">
|
|
||||||
<group delimiter=". " suffix=".">
|
|
||||||
<text macro="contributors"/>
|
|
||||||
<text macro="title"/>
|
|
||||||
<group delimiter=" ">
|
|
||||||
<text value="№"/>
|
|
||||||
<text variable="number"/>
|
|
||||||
</group>
|
|
||||||
<text macro="issued-date"/>
|
|
||||||
<text macro="url-access"/>
|
|
||||||
</group>
|
|
||||||
</else-if>
|
|
||||||
|
|
||||||
<!-- Універсальний fallback -->
|
|
||||||
<else>
|
|
||||||
<group delimiter=". " suffix=".">
|
|
||||||
<text macro="contributors"/>
|
|
||||||
<text macro="title"/>
|
|
||||||
<text variable="container-title" font-style="italic"/>
|
|
||||||
<group delimiter=", ">
|
|
||||||
<text macro="publisher-place"/>
|
|
||||||
<text macro="issued-year"/>
|
|
||||||
</group>
|
|
||||||
<text macro="pages"/>
|
|
||||||
<text macro="doi-or-url"/>
|
|
||||||
</group>
|
|
||||||
</else>
|
|
||||||
</choose>
|
|
||||||
</group>
|
|
||||||
</layout>
|
|
||||||
</bibliography>
|
|
||||||
</style>
|
|
||||||
+1
-1
@@ -14,7 +14,7 @@
|
|||||||
"грудня",
|
"грудня",
|
||||||
).at(month - 1)
|
).at(month - 1)
|
||||||
|
|
||||||
#let is-cyr(c) = regex("^\p{Cyrillic}") in c
|
#let is-cyr(c) = regex("[\p{Cyrillic}]") in c
|
||||||
|
|
||||||
/// type-safe emptiness check
|
/// type-safe emptiness check
|
||||||
#let is-empty(val) = {
|
#let is-empty(val) = {
|
||||||
|
|||||||
+15
-103
@@ -5,9 +5,6 @@
|
|||||||
#import "./style.typ"
|
#import "./style.typ"
|
||||||
#import "./utils.typ"
|
#import "./utils.typ"
|
||||||
|
|
||||||
#let dstu-table = style.dstu-table
|
|
||||||
#let hfill = utils.hfill
|
|
||||||
|
|
||||||
/// Coursework template for NURE
|
/// Coursework template for NURE
|
||||||
/// - university (str): University code, default "ХНУРЕ"
|
/// - university (str): University code, default "ХНУРЕ"
|
||||||
/// - subject (str): Subject short name
|
/// - subject (str): Subject short name
|
||||||
@@ -32,8 +29,7 @@
|
|||||||
bib-path: none,
|
bib-path: none,
|
||||||
appendices: (),
|
appendices: (),
|
||||||
) = {
|
) = {
|
||||||
let doc-title = if type(title) == array { title.join(" ") } else { title }
|
set document(title: title, author: authors.map(c => c.name))
|
||||||
set document(title: doc-title, author: authors.map(c => c.name))
|
|
||||||
|
|
||||||
show: style.dstu.with(skip: 1)
|
show: style.dstu.with(skip: 1)
|
||||||
|
|
||||||
@@ -60,86 +56,6 @@
|
|||||||
style.appendices(appendices)
|
style.appendices(appendices)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Alternative coursework template for NURE.
|
|
||||||
/// - university (str): University code, default "ХНУРЕ"
|
|
||||||
/// - title (str): Work title
|
|
||||||
/// - authors (array): List of author dictionaries
|
|
||||||
/// - mentors (array): List of mentor dictionaries
|
|
||||||
/// - committee-members (array): Optional list of commission member dictionaries for the title page
|
|
||||||
/// - task-list (dict): Task metadata
|
|
||||||
/// - calendar-plan (dict): Calendar plan table
|
|
||||||
/// - abstract (dict): Keywords and abstract text
|
|
||||||
/// - abstract-en (dict): Optional English keywords and abstract text
|
|
||||||
/// - bib-path (str): Path to bibliography file
|
|
||||||
/// - appendices (content): Appendix content
|
|
||||||
#let coursework-v2(
|
|
||||||
doc,
|
|
||||||
university: "ХНУРЕ",
|
|
||||||
title: none,
|
|
||||||
authors: (),
|
|
||||||
mentors: (),
|
|
||||||
committee-members: none,
|
|
||||||
task-list: (),
|
|
||||||
calendar-plan: (),
|
|
||||||
abstract: (),
|
|
||||||
abstract-en: none,
|
|
||||||
bib-path: none,
|
|
||||||
appendices: (),
|
|
||||||
faculty: "комп’ютерних наук",
|
|
||||||
education-level: "перший (бакалаврський)",
|
|
||||||
program-type: "освітньо-професійна",
|
|
||||||
program-name: none,
|
|
||||||
) = {
|
|
||||||
assert(authors.len() > 0, message: "At least one author required")
|
|
||||||
assert(mentors.len() > 0, message: "At least one mentor required")
|
|
||||||
|
|
||||||
let doc-title = if type(title) == array { title.join(" ") } else { title }
|
|
||||||
set document(title: doc-title, author: authors.map(c => c.name))
|
|
||||||
|
|
||||||
show: style.dstu.with(skip: 1)
|
|
||||||
|
|
||||||
let bib-count = state("citation-counter", ())
|
|
||||||
show cite: it => {
|
|
||||||
it
|
|
||||||
bib-count.update(((..c)) => (..c, it.key))
|
|
||||||
}
|
|
||||||
|
|
||||||
let abstract = if abstract-en != none {
|
|
||||||
abstract + (en: abstract-en)
|
|
||||||
} else {
|
|
||||||
abstract
|
|
||||||
}
|
|
||||||
let committee_members = committee-members
|
|
||||||
|
|
||||||
tp.cw-v2.nure(
|
|
||||||
university,
|
|
||||||
title,
|
|
||||||
authors,
|
|
||||||
mentors,
|
|
||||||
committee_members,
|
|
||||||
task-list,
|
|
||||||
calendar-plan,
|
|
||||||
abstract,
|
|
||||||
bib-count,
|
|
||||||
faculty: faculty,
|
|
||||||
education-level: education-level,
|
|
||||||
program-type: program-type,
|
|
||||||
program-name: program-name,
|
|
||||||
)
|
|
||||||
|
|
||||||
doc
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{
|
|
||||||
show regex("^\\d+\\."): it => [#it#h(0.5cm)]
|
|
||||||
show block: it => [#it.body#parbreak()]
|
|
||||||
bibliography(bib-path, title: [Перелік джерел посилання], style: "csl/dstu-8302-2015.csl", full: true)
|
|
||||||
}
|
|
||||||
|
|
||||||
style.appendices(appendices)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Practice and Laboratory works template
|
/// Practice and Laboratory works template
|
||||||
/// - layout (str): "default", "minimal", or "complex"
|
/// - layout (str): "default", "minimal", or "complex"
|
||||||
/// - university (str): University code
|
/// - university (str): University code
|
||||||
@@ -161,7 +77,6 @@
|
|||||||
title: none,
|
title: none,
|
||||||
authors: (),
|
authors: (),
|
||||||
mentors: (),
|
mentors: (),
|
||||||
skip-heading: false,
|
|
||||||
) = {
|
) = {
|
||||||
assert(authors.len() > 0, message: "At least one author required")
|
assert(authors.len() > 0, message: "At least one author required")
|
||||||
|
|
||||||
@@ -174,28 +89,25 @@
|
|||||||
|
|
||||||
// Select layout variant
|
// Select layout variant
|
||||||
let layouts = (
|
let layouts = (
|
||||||
"complex": () => tp.pz-lb.complex(uni, edu-program, subject, type, number, title, authors, mentors),
|
"complex": tp.pz-lb.complex(uni, edu-program, subject, type, number, title, authors, mentors),
|
||||||
"ХНУРЕ": () => tp.pz-lb.nure(uni, edu-program, subject, type, number, title, authors, mentors),
|
"ХНУРЕ": tp.pz-lb.nure(uni, edu-program, subject, type, number, title, authors, mentors),
|
||||||
"default": () => tp.pz-lb.nure(uni, edu-program, subject, type, number, title, authors, mentors),
|
"default": tp.pz-lb.nure(uni, edu-program, subject, type, number, title, authors, mentors),
|
||||||
)
|
)
|
||||||
|
|
||||||
(layouts.at(university, default: layouts.default))()
|
layouts.at(university, default: layouts.default)
|
||||||
|
|
||||||
if not skip-heading {
|
pagebreak(weak: true)
|
||||||
pagebreak(weak: true)
|
|
||||||
|
|
||||||
// Set heading counter based on title/number
|
// Set heading counter based on title/number
|
||||||
if title == none {
|
if title == none {
|
||||||
if number == none { context counter(heading).update(1) } else {
|
if number == none { context counter(heading).update(1) } else {
|
||||||
context counter(heading).update(number)
|
context counter(heading).update(number)
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if number != none {
|
|
||||||
context counter(heading).update(number - 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
heading(eval(title, mode: "markup"))
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if number != none {
|
||||||
|
context counter(heading).update(number - 1)
|
||||||
|
}
|
||||||
|
heading(eval(title, mode: "markup"))
|
||||||
}
|
}
|
||||||
|
|
||||||
doc
|
doc
|
||||||
|
|||||||
+25
-224
@@ -6,11 +6,7 @@
|
|||||||
#let double-half-spacing = spacing * 2.5
|
#let double-half-spacing = spacing * 2.5
|
||||||
|
|
||||||
/// Ukrainian alphabet for DSTU 3008:2015 numbering
|
/// Ukrainian alphabet for DSTU 3008:2015 numbering
|
||||||
#let ukr-enum = "абвгдежиклмнпрстуфхцшщюя".clusters()
|
#let ukr-enum = "абвгдежиклмнпрстуфхцшщюя".split("")
|
||||||
|
|
||||||
#let dstu-table-counter = counter("dstu-table")
|
|
||||||
#let dstu-table-appendix = state("dstu-table-appendix", none)
|
|
||||||
#let dstu-table-caption-gap = 0.65em
|
|
||||||
|
|
||||||
/// Helper for level 2/3 heading blocks
|
/// Helper for level 2/3 heading blocks
|
||||||
#let heading-block(it, num: auto) = {
|
#let heading-block(it, num: auto) = {
|
||||||
@@ -23,125 +19,6 @@
|
|||||||
v(double-spacing, weak: true)
|
v(double-spacing, weak: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
#let _col-count(columns) = {
|
|
||||||
if type(columns) == int {
|
|
||||||
columns
|
|
||||||
} else if type(columns) == array {
|
|
||||||
columns.len()
|
|
||||||
} else {
|
|
||||||
panic("dstu-table: columns must be an int or array, e.g. 2 or (1fr, 3fr)")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#let _required(name, value) = {
|
|
||||||
if value == none {
|
|
||||||
panic("dstu-table: " + name + " is required")
|
|
||||||
}
|
|
||||||
value
|
|
||||||
}
|
|
||||||
|
|
||||||
#let dstu-table-label(it) = {
|
|
||||||
set par(first-line-indent: 0pt)
|
|
||||||
align(left)[#it]
|
|
||||||
}
|
|
||||||
|
|
||||||
#let dstu-table(
|
|
||||||
caption: none,
|
|
||||||
columns: none,
|
|
||||||
header: none,
|
|
||||||
tag: none,
|
|
||||||
..args,
|
|
||||||
) = {
|
|
||||||
let caption = _required("caption", caption)
|
|
||||||
let columns = _required("columns", columns)
|
|
||||||
let header = _required("header", header)
|
|
||||||
|
|
||||||
if type(header) != array {
|
|
||||||
panic("dstu-table: header must be an array, e.g. ([A], [B])")
|
|
||||||
}
|
|
||||||
|
|
||||||
dstu-table-counter.step()
|
|
||||||
|
|
||||||
let named = args.named()
|
|
||||||
let body = args.pos()
|
|
||||||
context {
|
|
||||||
let h = counter(heading).get()
|
|
||||||
let section = if h.len() > 0 { h.at(0) } else { 0 }
|
|
||||||
let n = dstu-table-counter.get().first()
|
|
||||||
let appendix = dstu-table-appendix.get()
|
|
||||||
let num = if appendix == none {
|
|
||||||
numbering("1.1", section, n)
|
|
||||||
} else {
|
|
||||||
upper(ukr-enum.at(appendix - 1)) + "." + str(n)
|
|
||||||
}
|
|
||||||
|
|
||||||
let id = "dstu-table-" + str(section) + "-" + str(n)
|
|
||||||
let start-marker = "start-" + id
|
|
||||||
let end-marker = "end-" + id
|
|
||||||
let cols = _col-count(columns)
|
|
||||||
|
|
||||||
v(double-spacing, weak: true)
|
|
||||||
|
|
||||||
{
|
|
||||||
set block(spacing: dstu-table-caption-gap)
|
|
||||||
|
|
||||||
[#metadata((kind: "dstu-table", number: num)) #if tag != none { label(tag) }]
|
|
||||||
|
|
||||||
block(sticky: true)[
|
|
||||||
#dstu-table-label[Таблиця #num -- #caption]
|
|
||||||
]
|
|
||||||
|
|
||||||
table(
|
|
||||||
columns: columns,
|
|
||||||
..named,
|
|
||||||
|
|
||||||
table.header(
|
|
||||||
repeat: true,
|
|
||||||
|
|
||||||
table.cell(
|
|
||||||
colspan: cols,
|
|
||||||
stroke: none,
|
|
||||||
inset: 0pt,
|
|
||||||
)[
|
|
||||||
#metadata(start-marker)
|
|
||||||
|
|
||||||
#context {
|
|
||||||
let starts = query(metadata.where(value: start-marker))
|
|
||||||
let ends = query(metadata.where(value: end-marker))
|
|
||||||
|
|
||||||
if starts.len() > 0 and ends.len() > 0 {
|
|
||||||
let start-page = starts.first().location().page()
|
|
||||||
let end-page = ends.first().location().page()
|
|
||||||
let current-page = here().page()
|
|
||||||
|
|
||||||
if current-page != start-page {
|
|
||||||
let label = if current-page == end-page {
|
|
||||||
[Кінець таблиці #num]
|
|
||||||
} else {
|
|
||||||
[Продовження таблиці #num]
|
|
||||||
}
|
|
||||||
|
|
||||||
pad(top: dstu-table-caption-gap, bottom: dstu-table-caption-gap)[
|
|
||||||
#dstu-table-label[#label]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
|
|
||||||
..header,
|
|
||||||
),
|
|
||||||
|
|
||||||
..body,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
metadata(end-marker)
|
|
||||||
|
|
||||||
v(double-spacing, weak: true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// DSTU 3008:2015 Style
|
/// DSTU 3008:2015 Style
|
||||||
#let dstu(
|
#let dstu(
|
||||||
it,
|
it,
|
||||||
@@ -158,15 +35,12 @@
|
|||||||
|
|
||||||
// Text and paragraph
|
// Text and paragraph
|
||||||
set text(lang: "uk", size: 14pt, hyphenate: false, font: ("Times New Roman", "Liberation Serif"))
|
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: (
|
set par(justify: true, spacing: spacing, leading: spacing, first-line-indent: (amount: indent-size, all: true))
|
||||||
amount: indent-size,
|
|
||||||
all: true,
|
|
||||||
))
|
|
||||||
set block(spacing: spacing)
|
set block(spacing: spacing)
|
||||||
set underline(evade: false)
|
set underline(evade: false)
|
||||||
|
|
||||||
// Lists
|
// Lists
|
||||||
set enum(indent: indent-size, body-indent: 0.5cm, numbering: i => ukr-enum.at(i - 1) + ")")
|
set enum(indent: indent-size, body-indent: 0.5cm, numbering: i => ukr-enum.at(i) + ")")
|
||||||
show enum: it => {
|
show enum: it => {
|
||||||
set enum(indent: 0em, numbering: "1)")
|
set enum(indent: 0em, numbering: "1)")
|
||||||
it
|
it
|
||||||
@@ -174,63 +48,6 @@
|
|||||||
set list(indent: indent-size + 0.1cm, body-indent: 0.5cm, marker: [--])
|
set list(indent: indent-size + 0.1cm, body-indent: 0.5cm, marker: [--])
|
||||||
|
|
||||||
// Figures
|
// Figures
|
||||||
show ref: it => {
|
|
||||||
let target = it.element
|
|
||||||
|
|
||||||
if target == none {
|
|
||||||
return it
|
|
||||||
}
|
|
||||||
|
|
||||||
// dstu-table refs carry a number already resolved at the table location.
|
|
||||||
if (
|
|
||||||
target.func() == metadata
|
|
||||||
and type(target.value) == dictionary
|
|
||||||
and target.value.at("kind", default: none) == "dstu-table"
|
|
||||||
) {
|
|
||||||
return link(target.location())[#target.value.at("number")]
|
|
||||||
}
|
|
||||||
|
|
||||||
if target.func() != figure and target.func() != math.equation {
|
|
||||||
return it
|
|
||||||
}
|
|
||||||
|
|
||||||
// A figure or equation number must be read at the element itself, not at the citation site.
|
|
||||||
// The default ref display re-runs the numbering function here, where its inner `counter(heading)`
|
|
||||||
// context resolves to the citing chapter and prints the wrong section or appendix letter.
|
|
||||||
// We sample every counter at the target location instead.
|
|
||||||
let loc = target.location()
|
|
||||||
|
|
||||||
let appendix = dstu-table-appendix.at(loc)
|
|
||||||
|
|
||||||
let section = if appendix == none {
|
|
||||||
str(counter(heading).at(loc).first())
|
|
||||||
} else {
|
|
||||||
upper(ukr-enum.at(appendix - 1))
|
|
||||||
}
|
|
||||||
|
|
||||||
let number = if target.func() == figure {
|
|
||||||
let idx = counter(figure.where(kind: target.kind)).at(loc).first()
|
|
||||||
section + "." + str(idx)
|
|
||||||
} else {
|
|
||||||
let idx = counter(math.equation).at(loc).first()
|
|
||||||
"(" + section + "." + str(idx) + ")"
|
|
||||||
}
|
|
||||||
|
|
||||||
let supplement = if it.supplement == auto {
|
|
||||||
target.supplement
|
|
||||||
} else {
|
|
||||||
it.supplement
|
|
||||||
}
|
|
||||||
|
|
||||||
let body = if supplement != auto and supplement != none {
|
|
||||||
[#supplement #number]
|
|
||||||
} else {
|
|
||||||
[#number]
|
|
||||||
}
|
|
||||||
|
|
||||||
link(loc, body)
|
|
||||||
}
|
|
||||||
|
|
||||||
show figure: it => {
|
show figure: it => {
|
||||||
v(double-spacing, weak: true)
|
v(double-spacing, weak: true)
|
||||||
it
|
it
|
||||||
@@ -248,7 +65,6 @@
|
|||||||
counter(figure.where(kind: raw)).update(0)
|
counter(figure.where(kind: raw)).update(0)
|
||||||
counter(figure.where(kind: image)).update(0)
|
counter(figure.where(kind: image)).update(0)
|
||||||
counter(figure.where(kind: table)).update(0)
|
counter(figure.where(kind: table)).update(0)
|
||||||
dstu-table-counter.update(0)
|
|
||||||
it
|
it
|
||||||
}
|
}
|
||||||
set figure(numbering: i => context numbering("1.1", counter(heading).get().at(0), i))
|
set figure(numbering: i => context numbering("1.1", counter(heading).get().at(0), i))
|
||||||
@@ -281,15 +97,6 @@
|
|||||||
v(double-half-spacing, weak: true)
|
v(double-half-spacing, weak: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// blocks `like this` aren't welcome, so ` is replaced with "
|
|
||||||
show raw.where(block: false): it => text(
|
|
||||||
lang: "uk",
|
|
||||||
size: 14pt,
|
|
||||||
hyphenate: false,
|
|
||||||
weight: "regular",
|
|
||||||
font: ("Times New Roman", "Liberation Serif"),
|
|
||||||
)["#it.text"]
|
|
||||||
|
|
||||||
it
|
it
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,35 +104,29 @@
|
|||||||
#let appendices(it) = {
|
#let appendices(it) = {
|
||||||
counter(heading).update(0)
|
counter(heading).update(0)
|
||||||
|
|
||||||
set heading(numbering: (i, ..n) => upper(ukr-enum.at(i - 1)) + numbering(".1.1", ..n))
|
context {
|
||||||
set heading(supplement: [Додаток])
|
let app-letter = upper(ukr-enum.at(counter(heading).get().at(0)))
|
||||||
|
set heading(numbering: (i, ..n) => upper(ukr-enum.at(i)) + numbering(".1.1", ..n))
|
||||||
|
set figure(numbering: i => app-letter + "." + str(i))
|
||||||
|
set math.equation(numbering: i => app-letter + "." + str(i))
|
||||||
|
set heading(supplement: [Додаток])
|
||||||
|
|
||||||
let app-letter = context upper(ukr-enum.at(counter(heading).get().at(0) - 1))
|
show heading: h => {
|
||||||
set figure(numbering: i => app-letter + "." + str(i))
|
set text(size: 14pt)
|
||||||
set math.equation(numbering: i => [(#app-letter.#str(i))])
|
if h.level == 1 {
|
||||||
|
set align(center)
|
||||||
show heading: h => {
|
set text(weight: "regular")
|
||||||
set text(size: 14pt)
|
pagebreak(weak: true)
|
||||||
if h.level == 1 {
|
bold([ДОДАТОК #counter(heading).display(auto)])
|
||||||
counter(math.equation).update(0)
|
linebreak()
|
||||||
counter(figure.where(kind: raw)).update(0)
|
h.body
|
||||||
counter(figure.where(kind: image)).update(0)
|
v(double-spacing, weak: true)
|
||||||
counter(figure.where(kind: table)).update(0)
|
} else {
|
||||||
dstu-table-counter.update(0)
|
set text(weight: "regular")
|
||||||
dstu-table-appendix.update(counter(heading).get().at(0))
|
heading-block(h)
|
||||||
|
}
|
||||||
set align(center)
|
|
||||||
set text(weight: "regular")
|
|
||||||
pagebreak(weak: true)
|
|
||||||
bold([ДОДАТОК #counter(heading).display(auto)])
|
|
||||||
linebreak()
|
|
||||||
h.body
|
|
||||||
v(double-spacing, weak: true)
|
|
||||||
} else {
|
|
||||||
set text(weight: "regular")
|
|
||||||
heading-block(h)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
it
|
it
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
#import "nure.typ": *
|
|
||||||
@@ -1,394 +0,0 @@
|
|||||||
#import "../../shared.typ": universities
|
|
||||||
#import "../../helpers.typ": *
|
|
||||||
#import "../../style.typ": spacing
|
|
||||||
#import "../../utils.typ": bold, uline, filled-lines, hfill
|
|
||||||
|
|
||||||
#let note(content) = block(width: 100%, above: 5pt, below: 0pt)[
|
|
||||||
#set text(size: 10pt)
|
|
||||||
#set par(first-line-indent: 0pt, spacing: 0pt)
|
|
||||||
#align(center)[#content]
|
|
||||||
]
|
|
||||||
|
|
||||||
#let form-field(alignment: center, content) = box(
|
|
||||||
width: 100%,
|
|
||||||
stroke: (bottom: 0.5pt),
|
|
||||||
inset: (bottom: 1.5pt),
|
|
||||||
)[
|
|
||||||
#align(alignment)[#content]
|
|
||||||
]
|
|
||||||
|
|
||||||
#let label-line(label, value, caption: none, label-width: auto) = {
|
|
||||||
set par(first-line-indent: 0pt)
|
|
||||||
if label-width == auto {
|
|
||||||
[#label #form-field(alignment: center, value)]
|
|
||||||
} else {
|
|
||||||
grid(
|
|
||||||
columns: (label-width, 1fr),
|
|
||||||
gutter: 0pt,
|
|
||||||
align: horizon,
|
|
||||||
label, form-field(alignment: center, value),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if caption != none {
|
|
||||||
note(caption)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#let inline-field(value) = form-field(alignment: center, value)
|
|
||||||
|
|
||||||
#let inline-label-line(label, value) = {
|
|
||||||
set par(first-line-indent: 0pt)
|
|
||||||
block(width: 100%, below: 0pt)[
|
|
||||||
#label #uline(align: center, value)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
#let task-head-fields(fields) = {
|
|
||||||
set par(first-line-indent: 0pt)
|
|
||||||
let cells = ()
|
|
||||||
for (label, value) in fields {
|
|
||||||
if type(value) == array {
|
|
||||||
for (i, line) in value.enumerate() {
|
|
||||||
cells.push(if i == 0 { label } else { [] })
|
|
||||||
cells.push(inline-field(line))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cells.push(label)
|
|
||||||
cells.push(inline-field(value))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
grid(
|
|
||||||
columns: (auto, 1fr),
|
|
||||||
gutter: 0pt,
|
|
||||||
row-gutter: 0.65em,
|
|
||||||
align: top,
|
|
||||||
..cells,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#let task-num(n) = box(str(n) + ".")
|
|
||||||
|
|
||||||
#let title-field(value) = {
|
|
||||||
uline(align: center, value.join())
|
|
||||||
uline(align: center, [])
|
|
||||||
note[(тема)]
|
|
||||||
}
|
|
||||||
|
|
||||||
#let commission-lines(members) = {
|
|
||||||
if members.len() > 0 {
|
|
||||||
for (i, member) in members.enumerate() {
|
|
||||||
if i > 0 {
|
|
||||||
linebreak()
|
|
||||||
}
|
|
||||||
let member-display-name = member.at("display-name", default: member.name)
|
|
||||||
let member-degree = member.at("degree", default: "")
|
|
||||||
uline(align: left, [#member-degree #member-display-name])
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
v(0.55em)
|
|
||||||
line(length: 100%, stroke: 0.5pt)
|
|
||||||
v(0.55em)
|
|
||||||
line(length: 100%, stroke: 0.5pt)
|
|
||||||
v(0.55em)
|
|
||||||
line(length: 100%, stroke: 0.5pt)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#let nure(
|
|
||||||
university,
|
|
||||||
title,
|
|
||||||
authors,
|
|
||||||
mentors,
|
|
||||||
committee_members,
|
|
||||||
task-list,
|
|
||||||
calendar-plan,
|
|
||||||
abstract,
|
|
||||||
bib-count,
|
|
||||||
faculty: "комп'ютерних наук",
|
|
||||||
education-level: "перший (бакалаврський)",
|
|
||||||
program-type: "освітньо-професійна",
|
|
||||||
program-name: none,
|
|
||||||
) = {
|
|
||||||
let author = authors.first()
|
|
||||||
let head-mentor = mentors.first()
|
|
||||||
let commission-members = if committee_members == none {
|
|
||||||
mentors.slice(1)
|
|
||||||
} else {
|
|
||||||
committee_members
|
|
||||||
}
|
|
||||||
|
|
||||||
let uni = universities.at(university)
|
|
||||||
let edu-prog = uni.edu-programs.at(author.edu-program)
|
|
||||||
let program-name = if program-name == none {
|
|
||||||
edu-prog.at("program-name", default: edu-prog.name-long)
|
|
||||||
} else {
|
|
||||||
program-name
|
|
||||||
}
|
|
||||||
let group-name = if str(author.group).starts-with(author.edu-program) {
|
|
||||||
str(author.group)
|
|
||||||
} else {
|
|
||||||
author.edu-program + "-" + str(author.group)
|
|
||||||
}
|
|
||||||
let executor-label = if author.gender == "f" or author.gender == "female" or author.gender == "ж" {
|
|
||||||
"Виконала:"
|
|
||||||
} else {
|
|
||||||
"Виконав:"
|
|
||||||
}
|
|
||||||
let author-display-name = author.at("display-name", default: author.name)
|
|
||||||
let author-full-name-dat = author.at("full-name-dat", default: author.full-name-gen)
|
|
||||||
let mentor-display-name = head-mentor.at("display-name", default: head-mentor.name)
|
|
||||||
let mentor-degree = head-mentor.at("degree", default: "")
|
|
||||||
|
|
||||||
[
|
|
||||||
#set par(first-line-indent: 0pt, justify: false, leading: 0.45em)
|
|
||||||
|
|
||||||
#set text(size: 14pt)
|
|
||||||
#set align(center)
|
|
||||||
МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ\
|
|
||||||
#uni.name
|
|
||||||
|
|
||||||
#v(0.7em)
|
|
||||||
|
|
||||||
#set align(left)
|
|
||||||
#inline-label-line(
|
|
||||||
[Факультет],
|
|
||||||
faculty,
|
|
||||||
)
|
|
||||||
#note([(повна назва)])
|
|
||||||
|
|
||||||
#v(0.8em)
|
|
||||||
#inline-label-line(
|
|
||||||
[Кафедра],
|
|
||||||
lower(edu-prog.department-gen),
|
|
||||||
)
|
|
||||||
#note([(повна назва)])
|
|
||||||
|
|
||||||
#v(1.8em)
|
|
||||||
|
|
||||||
#set align(center)
|
|
||||||
#text(size: 20pt, weight: "bold")[КОМПЛЕКСНИЙ КУРСОВИЙ ПРОЄКТ]\
|
|
||||||
#text(size: 20pt, weight: "bold")[Пояснювальна записка]
|
|
||||||
|
|
||||||
#v(0.9em)
|
|
||||||
|
|
||||||
#set align(left)
|
|
||||||
#label-line([рівень вищої освіти], education-level, label-width: 120pt)
|
|
||||||
|
|
||||||
#v(1.0em)
|
|
||||||
#title-field(title)
|
|
||||||
|
|
||||||
#v(3em)
|
|
||||||
|
|
||||||
#grid(
|
|
||||||
columns: (0.36fr, 0.64fr),
|
|
||||||
[],
|
|
||||||
[
|
|
||||||
#executor-label\
|
|
||||||
здобувач #underline([#author.course]) курсу, групи #underline(group-name)\
|
|
||||||
#uline(align: center, author-display-name)
|
|
||||||
#note[(Власне ім'я, ПРІЗВИЩЕ)]
|
|
||||||
|
|
||||||
#v(0.2em)
|
|
||||||
#inline-label-line([Спеціальність], [#edu-prog.code -- #edu-prog.name-long])
|
|
||||||
#note[(код і повна назва спеціальності)]
|
|
||||||
#inline-label-line([Тип програми], program-type)
|
|
||||||
#inline-label-line([Освітня програма], program-name)
|
|
||||||
#note[(повна назва освітньої програми)]
|
|
||||||
|
|
||||||
#v(0.3em)
|
|
||||||
#inline-label-line([Керівник], [#mentor-degree #mentor-display-name])
|
|
||||||
#note[(посада, Власне ім'я, ПРІЗВИЩЕ)]
|
|
||||||
|
|
||||||
#v(0.3em)
|
|
||||||
#pad(left: 75pt)[
|
|
||||||
#set par(first-line-indent: 0pt)
|
|
||||||
Члени комісії (#text(size: 10pt)[Власне ім'я, ПРІЗВИЩЕ, підпис])
|
|
||||||
#v(0.15em)
|
|
||||||
#commission-lines(commission-members)
|
|
||||||
]
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
#v(1fr)
|
|
||||||
|
|
||||||
#set align(center)
|
|
||||||
#task-list.done-date.display("[year]") р.
|
|
||||||
|
|
||||||
#pagebreak()
|
|
||||||
]
|
|
||||||
|
|
||||||
[
|
|
||||||
#set par(first-line-indent: 0pt, justify: false)
|
|
||||||
#align(center)[#uni.name]
|
|
||||||
|
|
||||||
#v(1.1em)
|
|
||||||
#task-head-fields((
|
|
||||||
(
|
|
||||||
[Факультет],
|
|
||||||
(
|
|
||||||
faculty,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
([Кафедра], lower(edu-prog.department-gen)),
|
|
||||||
([Рівень вищої освіти], education-level),
|
|
||||||
([Спеціальність], [#edu-prog.code -- #edu-prog.name-long]),
|
|
||||||
([Тип програми], program-type),
|
|
||||||
([Освітня програма], program-name),
|
|
||||||
))
|
|
||||||
#note[(шифр і назва)]
|
|
||||||
|
|
||||||
#v(1.7em)
|
|
||||||
#grid(
|
|
||||||
columns: (1.1fr, 1.1fr, 1.1fr, 1.7fr, 1.3fr, 1.1fr),
|
|
||||||
gutter: 0pt,
|
|
||||||
align: center + horizon,
|
|
||||||
[Курс], uline(author.course), [Група], uline(group-name), [Семестр], uline(author.semester),
|
|
||||||
)
|
|
||||||
|
|
||||||
#v(2.6em)
|
|
||||||
|
|
||||||
#align(center)[
|
|
||||||
#bold[ЗАВДАННЯ]\
|
|
||||||
#text(style: "italic", weight: "bold")[на курсовий проєкт (роботу) студента]
|
|
||||||
]
|
|
||||||
|
|
||||||
#v(1.0em)
|
|
||||||
|
|
||||||
#label-line([здобувачеві], author-full-name-dat, caption: [(прізвище, ім'я, по батькові)], label-width: 95pt)
|
|
||||||
|
|
||||||
#v(1.0em)
|
|
||||||
|
|
||||||
#task-num(1) Тема роботи #uline(align: left, filled-lines(title))
|
|
||||||
|
|
||||||
#v(0.4em)
|
|
||||||
#task-num(2) Термін здачі студентом закінченої роботи
|
|
||||||
“#underline(task-list.done-date.display("[day]"))” #underline(month-gen(task-list.done-date.month())) #task-list.done-date.display("[year]")р.
|
|
||||||
|
|
||||||
#v(0.4em)
|
|
||||||
#task-num(3) Вихідні дані до проєкту #uline(align: left, filled-lines(task-list.at("source", default: [])))
|
|
||||||
#v(0.4em)
|
|
||||||
#uline(align: left, [])
|
|
||||||
|
|
||||||
#v(0.4em)
|
|
||||||
#task-num(4) Перелік питань, що потрібно опрацювати в роботі\
|
|
||||||
#uline(align: left, filled-lines(task-list.at("content", default: [])))
|
|
||||||
#v(0.4em)
|
|
||||||
#uline(align: left, [])
|
|
||||||
|
|
||||||
#pagebreak()
|
|
||||||
]
|
|
||||||
|
|
||||||
[
|
|
||||||
#align(center, bold[КАЛЕНДАРНИЙ ПЛАН])
|
|
||||||
#set par(first-line-indent: 0pt)
|
|
||||||
|
|
||||||
#v(1.4em)
|
|
||||||
|
|
||||||
#calendar-plan.plan-table
|
|
||||||
|
|
||||||
#v(5.0em)
|
|
||||||
|
|
||||||
Дата видачі завдання “#underline(task-list.initial-date.display("[day]"))” #underline(month-gen(task-list.initial-date.month())) #task-list.initial-date.display("[year]") р.
|
|
||||||
|
|
||||||
#v(1.4em)
|
|
||||||
|
|
||||||
Здобувач #underline([#hfill(6cm)])
|
|
||||||
#note[(підпис) #h(8cm)]
|
|
||||||
|
|
||||||
#v(1.4em)
|
|
||||||
|
|
||||||
Керівник роботи #uline(align: center, []) #h(1cm) #underline[#mentor-degree #mentor-display-name]
|
|
||||||
#note[(підпис) #h(4.5cm) (посада, Власне ім'я, ПРІЗВИЩЕ)]
|
|
||||||
|
|
||||||
#pagebreak()
|
|
||||||
]
|
|
||||||
|
|
||||||
[
|
|
||||||
#let header = if abstract.at("en", default: none) != none {
|
|
||||||
bold[РЕФЕРАТ / ABSTRACT]
|
|
||||||
} else {
|
|
||||||
bold[РЕФЕРАТ]
|
|
||||||
}
|
|
||||||
#align(center, header) \
|
|
||||||
|
|
||||||
#context [
|
|
||||||
#let pages = counter(page).final().at(0)
|
|
||||||
#let images = query(figure.where(kind: image)).len()
|
|
||||||
#let dstu-tables = query(metadata).filter(it => type(it.value) == dictionary and it.value.at("kind", default: none) == "dstu-table").len()
|
|
||||||
#let tables = query(figure.where(kind: table)).len() + dstu-tables
|
|
||||||
#let bibs = bib-count.final().dedup().len()
|
|
||||||
|
|
||||||
#let counters = ()
|
|
||||||
#if pages != 0 { counters.push[#pages с.] }
|
|
||||||
#if tables != 0 { counters.push[#tables табл.] }
|
|
||||||
#if images != 0 { counters.push[#images рис.] }
|
|
||||||
#if bibs != 0 { counters.push[#bibs джерел] }
|
|
||||||
|
|
||||||
Пояснювальна записка містить: #counters.join(", ").
|
|
||||||
]
|
|
||||||
|
|
||||||
\
|
|
||||||
|
|
||||||
#let keyword-pairs = if abstract.keywords.len() > 0 and type(abstract.keywords.first()) == array {
|
|
||||||
abstract.keywords.map(pair => (
|
|
||||||
uk: pair.at(0),
|
|
||||||
en: pair.at(1),
|
|
||||||
))
|
|
||||||
} else if abstract.at("en", default: none) != none and abstract.en.at("keywords", default: none) != none {
|
|
||||||
abstract.keywords.enumerate().map(((i, uk)) => (
|
|
||||||
uk: uk,
|
|
||||||
en: abstract.en.keywords.at(i),
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
abstract.keywords.map(uk => (uk: uk))
|
|
||||||
}
|
|
||||||
#let sorted-keyword-pairs = keyword-pairs.sorted(by: (a, b) => {
|
|
||||||
if is-cyr(a.uk) != is-cyr(b.uk) { is-cyr(a.uk) } else { a.uk < b.uk }
|
|
||||||
})
|
|
||||||
|
|
||||||
#(sorted-keyword-pairs.map(pair => upper(pair.uk)).join(", "))
|
|
||||||
|
|
||||||
\
|
|
||||||
|
|
||||||
#abstract.text
|
|
||||||
|
|
||||||
#if abstract.at("en", default: none) != none or (keyword-pairs.len() > 0 and keyword-pairs.first().at("en", default: none) != none) [
|
|
||||||
\
|
|
||||||
|
|
||||||
#(sorted-keyword-pairs.map(pair => upper(pair.en)).join(", "))
|
|
||||||
|
|
||||||
\
|
|
||||||
|
|
||||||
#abstract.en.text
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
{
|
|
||||||
show outline.entry: it => {
|
|
||||||
let el = it.element
|
|
||||||
|
|
||||||
if el.func() == heading and el.supplement == [Додаток] {
|
|
||||||
if el.level > 1 {
|
|
||||||
none
|
|
||||||
} else {
|
|
||||||
block(width: 100%)[
|
|
||||||
#link(el.location())[
|
|
||||||
Додаток #it.prefix()#h(0.5em)#it.inner()
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
it
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
outline(
|
|
||||||
title: [
|
|
||||||
ЗМІСТ
|
|
||||||
#v(spacing * 2, weak: true)
|
|
||||||
],
|
|
||||||
depth: 2,
|
|
||||||
indent: auto,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -210,8 +210,7 @@
|
|||||||
#context [
|
#context [
|
||||||
#let pages = counter(page).final().at(0)
|
#let pages = counter(page).final().at(0)
|
||||||
#let images = query(figure.where(kind: image)).len()
|
#let images = query(figure.where(kind: image)).len()
|
||||||
#let dstu-tables = query(metadata).filter(it => type(it.value) == dictionary and it.value.at("kind", default: none) == "dstu-table").len()
|
#let tables = query(figure.where(kind: table)).len()
|
||||||
#let tables = query(figure.where(kind: table)).len() + dstu-tables
|
|
||||||
#let bibs = bib-count.final().dedup().len()
|
#let bibs = bib-count.final().dedup().len()
|
||||||
/* TODO: why this stopped working?
|
/* TODO: why this stopped working?
|
||||||
#let tables = counter(figure.where(kind: table)).final().at(0)
|
#let tables = counter(figure.where(kind: table)).final().at(0)
|
||||||
|
|||||||
@@ -1,3 +1,2 @@
|
|||||||
#import "pz-lb/main.typ" as pz-lb
|
#import "pz-lb/main.typ" as pz-lb
|
||||||
#import "coursework/main.typ" as cw
|
#import "coursework/main.typ" as cw
|
||||||
#import "coursework-v2/main.typ" as cw-v2
|
|
||||||
|
|||||||
@@ -20,15 +20,12 @@
|
|||||||
#if authors.len() == 1 {
|
#if authors.len() == 1 {
|
||||||
let a = authors.first()
|
let a = authors.first()
|
||||||
[#gender-form("author", dict: a):\ ]
|
[#gender-form("author", dict: a):\ ]
|
||||||
if ("edu-program" in a) and ("group" in a) [ст. гр. #a.edu-program\-#a.group\ ]
|
[ст. гр. #a.edu-program\-#a.group\ ]
|
||||||
[#a.name\ ]
|
[#a.name\ ]
|
||||||
if ("variant" in a) and (not is-empty(a.variant)) [Варіант: №#a.variant]
|
if not is-empty(a.variant) [Варіант: №#a.variant]
|
||||||
} else if authors.len() > 1 [
|
} else if authors.len() > 1 [
|
||||||
#gender-form("author"):\
|
#gender-form("author"):\
|
||||||
#for a in authors [
|
#for a in authors [ст. гр. #a.edu-program\-#a.group\ #a.name\ ]
|
||||||
#if ("edu-program" in a) and ("group" in a) [ ст. гр. #a.edu-program\-#a.group\ ]
|
|
||||||
#a.name\
|
|
||||||
]
|
|
||||||
]
|
]
|
||||||
|
|
||||||
#colbreak()
|
#colbreak()
|
||||||
|
|||||||
@@ -7,13 +7,6 @@
|
|||||||
/// fill horizontal space with a filled box
|
/// fill horizontal space with a filled box
|
||||||
#let hfill(width) = box(width: width, repeat(" ")) // HAIR SPACE (U+200A)
|
#let hfill(width) = box(width: width, repeat(" ")) // HAIR SPACE (U+200A)
|
||||||
|
|
||||||
/// convert an array of lines into filled lines for underlined task fields
|
|
||||||
#let filled-lines(content) = if type(content) == array {
|
|
||||||
content.map(line => [#line #hfill(1fr)]).join(linebreak())
|
|
||||||
} else {
|
|
||||||
content
|
|
||||||
}
|
|
||||||
|
|
||||||
/// underlined cell with centered content by default
|
/// underlined cell with centered content by default
|
||||||
#let uline(align: center, content) = underline[
|
#let uline(align: center, content) = underline[
|
||||||
#if align != left { hfill(1fr) }
|
#if align != left { hfill(1fr) }
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#import "@local/nure:0.1.1": *
|
#import "@local/nure:0.1.0": *
|
||||||
#import style: spacing
|
#import style: spacing
|
||||||
|
|
||||||
#import "utils.typ": img
|
#import "utils.typ": img
|
||||||
@@ -1,143 +0,0 @@
|
|||||||
#import "@local/nure:0.1.1": *
|
|
||||||
#import style: spacing
|
|
||||||
|
|
||||||
#let authors = (
|
|
||||||
(
|
|
||||||
name: "Сокорчук І. П.",
|
|
||||||
display-name: "Ігор СОКОРЧУК",
|
|
||||||
full-name-gen: "Сокорчука Ігоря Петровича",
|
|
||||||
full-name-dat: "Сокорчуку Ігорю Петровичу",
|
|
||||||
edu-program: "ПЗПІ",
|
|
||||||
group: "23-3",
|
|
||||||
gender: "m",
|
|
||||||
course: 3,
|
|
||||||
semester: 6,
|
|
||||||
variant: 13,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
#let mentors = (
|
|
||||||
(name: "Сокорчук І. П.", display-name: "Ігор СОКОРЧУК", degree: "ст.викл. кафедри ПІ"),
|
|
||||||
)
|
|
||||||
|
|
||||||
#let committee_members = (
|
|
||||||
(name: "Груздо І.В.", degree: "Доц."),
|
|
||||||
(name: "Зибіна К.В.", degree: "Ст. викл."),
|
|
||||||
(name: "Гребенюк В.О.", degree: "Ст. викл."),
|
|
||||||
)
|
|
||||||
|
|
||||||
#let task-list = (
|
|
||||||
done-date: datetime(year: 2026, month: 12, day: 27),
|
|
||||||
initial-date: datetime(year: 2026, month: 9, day: 15),
|
|
||||||
source: (
|
|
||||||
[Узагальнити модель предметної області,],
|
|
||||||
[визначити основні сутності та зв'язки між ними.],
|
|
||||||
[Підготувати демонстраційний набір технологій для шаблону.],
|
|
||||||
),
|
|
||||||
content: (
|
|
||||||
[Опис предметної галузі, формування вимог,],
|
|
||||||
[архітектурне проєктування, тестування та],
|
|
||||||
[перевірка верстки пояснювальної записки.],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
#let calendar-plan = (
|
|
||||||
plan-table: table(
|
|
||||||
columns: (0.7fr, 5.8fr, 2.5fr, 1.6fr),
|
|
||||||
align: (center, left, center, center),
|
|
||||||
[№], [Назва етапів роботи], [Термін виконання етапів роботи], [Примітка],
|
|
||||||
[1], [Аналіз предметної галузі], [], [виконано],
|
|
||||||
[2], [Розробка постановки задачі], [], [виконано],
|
|
||||||
[3], [Проєктування ПЗ], [], [виконано],
|
|
||||||
[4], [Програмна реалізація], [], [виконано],
|
|
||||||
[5], [Аналіз результатів], [], [виконано],
|
|
||||||
[6], [Підготовка пояснювальної записки.], [], [виконано],
|
|
||||||
[7], [Перевірка на наявність ознак академічного плагіату], [], [виконано],
|
|
||||||
[8], [Захист роботи], [], [виконано],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
#let abstract = (
|
|
||||||
keywords: (
|
|
||||||
("веб-застосунок", "WEB APPLICATION"),
|
|
||||||
("інформаційна система", "INFORMATION SYSTEM"),
|
|
||||||
("курсова робота", "COURSEWORK"),
|
|
||||||
("програмна інженерія", "SOFTWARE ENGINEERING"),
|
|
||||||
("тестовий приклад", "DEMO SAMPLE"),
|
|
||||||
),
|
|
||||||
text: [
|
|
||||||
Мета даної роботи -- продемонструвати оформлення пояснювальної записки
|
|
||||||
для комплексного курсового проєкту з використанням нового варіанта шаблону.
|
|
||||||
Приклад містить узагальнену тему, типові сторінки завдання, календарного плану,
|
|
||||||
реферату, змісту, переліку джерел посилання та додатків.
|
|
||||||
|
|
||||||
У роботі наведено умовну структуру програмної системи, що може бути
|
|
||||||
адаптована під конкретну предметну область. Основний акцент зроблено на
|
|
||||||
перевірці полів титульної сторінки, сторінки завдання, службових підписів,
|
|
||||||
нумерації розділів і коректної роботи додатків.
|
|
||||||
|
|
||||||
Результатом є демонстраційний документ, який показує очікуване використання
|
|
||||||
шаблону без прив'язки до реального студента, викладача або завершеної роботи.
|
|
||||||
],
|
|
||||||
)
|
|
||||||
#let abstract_en = (
|
|
||||||
text: [
|
|
||||||
The purpose of this work is to demonstrate the formatting of a coursework
|
|
||||||
explanatory note using the new template variant.
|
|
||||||
|
|
||||||
The sample contains a generalized topic, typical pages for the assignment,
|
|
||||||
calendar plan, abstract, contents, bibliography, and appendices.
|
|
||||||
|
|
||||||
The work presents an illustrative structure of a software system that can be
|
|
||||||
adapted to a specific subject area. The main focus is on checking title-page
|
|
||||||
fields, assignment-page fields, signature blocks, section numbering, and
|
|
||||||
appendix handling.
|
|
||||||
|
|
||||||
The result is a demonstration document that shows the expected template usage
|
|
||||||
without being tied to a real student, supervisor, or completed project.
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
#let appendices = [
|
|
||||||
= Приклад звіту 1
|
|
||||||
#v(-spacing)
|
|
||||||
== Частина 1
|
|
||||||
#lorem(100)
|
|
||||||
== Частина 2
|
|
||||||
#lorem(200)
|
|
||||||
|
|
||||||
= Приклад звіту 2
|
|
||||||
#lorem(200)
|
|
||||||
|
|
||||||
= Приклад звіту 3
|
|
||||||
#lorem(200)
|
|
||||||
]
|
|
||||||
|
|
||||||
#show: coursework-v2.with(
|
|
||||||
title: (
|
|
||||||
"Демонстраційна інформаційна система для комплексного ",
|
|
||||||
"курсового проєкту",
|
|
||||||
),
|
|
||||||
authors: authors,
|
|
||||||
mentors: mentors,
|
|
||||||
committee-members: committee_members,
|
|
||||||
task-list: task-list,
|
|
||||||
calendar-plan: calendar-plan,
|
|
||||||
abstract: abstract,
|
|
||||||
abstract-en: abstract_en,
|
|
||||||
bib-path: bytes(read("bibl.yml")),
|
|
||||||
appendices: appendices,
|
|
||||||
)
|
|
||||||
|
|
||||||
= Моделювання
|
|
||||||
#lorem(250)
|
|
||||||
|
|
||||||
= Імплементація
|
|
||||||
#v(-spacing)
|
|
||||||
== Підготовка
|
|
||||||
#lorem(200)
|
|
||||||
== Процес
|
|
||||||
#lorem(500)
|
|
||||||
|
|
||||||
= Тестування
|
|
||||||
#lorem(300)
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
[settings]
|
|
||||||
quiet = true
|
|
||||||
env_shell_expand = true
|
|
||||||
lockfile = true
|
|
||||||
|
|
||||||
[tools]
|
|
||||||
typst = "latest"
|
|
||||||
typstyle = "latest"
|
|
||||||
tinymist = "latest"
|
|
||||||
yq = "latest"
|
|
||||||
|
|
||||||
[vars]
|
|
||||||
vendor_dir = "{{config_root}}/vendor"
|
|
||||||
package_dir = "{{vars.vendor_dir}}/typst-packages"
|
|
||||||
|
|
||||||
work_doc_config = "src/doc.toml"
|
|
||||||
work_input_file = "src/main.typ"
|
|
||||||
work_output_file = "{{config_root}}/main.pdf"
|
|
||||||
|
|
||||||
nure_package_repo = "https://gitea.linerds.us/pencelheimer/typst_nure_template.git"
|
|
||||||
nure_package_ref = "0.1.1"
|
|
||||||
nure_package_rev = "d6037872ddb6391afec147a679fa05f08cba6bb0"
|
|
||||||
|
|
||||||
nure_package_name = "vendor/nure"
|
|
||||||
nure_package_ver = "{{vars.nure_package_ref}}"
|
|
||||||
|
|
||||||
nure_package_path = "{{vars.package_dir}}/{{vars.nure_package_name}}/{{vars.nure_package_ver}}"
|
|
||||||
|
|
||||||
[env]
|
|
||||||
TYPST_PACKAGE_DIR = "{{vars.package_dir}}"
|
|
||||||
TYPST_PACKAGE_PATH = "$TYPST_PACKAGE_DIR"
|
|
||||||
|
|
||||||
[tasks]
|
|
||||||
compile.depends = ["fetch-nure-package"]
|
|
||||||
watch.depends = ["fetch-nure-package"]
|
|
||||||
compile.run = "mise exec -- typst compile {{vars.work_input_file}} {{vars.work_output_file}}"
|
|
||||||
watch.run = "mise exec -- typst watch {{vars.work_input_file}} {{vars.work_output_file}}"
|
|
||||||
format.run = "mise exec -- typstyle -l 120 -i $MISE_PROJECT_ROOT/src"
|
|
||||||
clean.run = "rm -rvif *.pdf"
|
|
||||||
|
|
||||||
update-package-rev.run = "mise config set vars.nure_package_rev $(git ls-remote {{vars.nure_package_repo}} refs/heads/{{vars.nure_package_ref}} | cut -f1)"
|
|
||||||
|
|
||||||
[tasks.fetch-nure-package]
|
|
||||||
silent = "stdout"
|
|
||||||
run = """
|
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
if [ ! -d {{vars.nure_package_path}}/.git ]; then
|
|
||||||
git clone --depth 1 --revision {{vars.nure_package_rev}} {{vars.nure_package_repo}} {{vars.nure_package_path}}
|
|
||||||
else
|
|
||||||
git -C {{vars.nure_package_path}} fetch --depth 1 origin {{vars.nure_package_rev}}
|
|
||||||
git -C {{vars.nure_package_path}} checkout {{vars.nure_package_rev}}
|
|
||||||
fi
|
|
||||||
"""
|
|
||||||
|
|
||||||
[tasks.rename]
|
|
||||||
depends = ["compile"]
|
|
||||||
run = """
|
|
||||||
#!/usr/bin/env bash
|
|
||||||
# Generates the following name from doc.toml: ПЗ1_Прізвище_ПЗПІ-23-2_ПарП.pdf
|
|
||||||
# Assumes authors.at(0).name to be in the following format: "Прізвище І. Б."
|
|
||||||
|
|
||||||
final_name=$(mise exec -- yq '.type + (.number | tostring) + "_" + (.authors[0].name | split(" "))[0] + "_" + (.authors[0].edu-program + "-" + .authors[0].group) + "_" + .subject + ".pdf"' "{{vars.work_doc_config}}");
|
|
||||||
|
|
||||||
cp -v "{{vars.work_output_file}}" "$final_name"
|
|
||||||
"""
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
[[tools.tinymist]]
|
|
||||||
version = "0.14.14"
|
|
||||||
backend = "aqua:Myriad-Dreamin/tinymist"
|
|
||||||
"platforms.linux-arm64" = { checksum = "sha256:39eb99d290fd1aa0e4508e5d5bbbf5a49648cf26da8e7bc3ff49f75c5fd0dc6c", url = "https://github.com/Myriad-Dreamin/tinymist/releases/download/v0.14.14/tinymist-linux-arm64"}
|
|
||||||
"platforms.linux-x64" = { checksum = "sha256:cda2ba76a455f3577cf2a1bd6340b75491f0c673770f631cf4d3232663860776", url = "https://github.com/Myriad-Dreamin/tinymist/releases/download/v0.14.14/tinymist-linux-x64"}
|
|
||||||
"platforms.macos-arm64" = { checksum = "sha256:ea7a22af0d54a71fbd1ee6c8c9f8434b521549926ae0f53a82391adeea741aba", url = "https://github.com/Myriad-Dreamin/tinymist/releases/download/v0.14.14/tinymist-darwin-arm64"}
|
|
||||||
"platforms.macos-x64" = { checksum = "sha256:f640889414d5030de1f03b966ccb10a84941bc1176980ff956d66714508ccd85", url = "https://github.com/Myriad-Dreamin/tinymist/releases/download/v0.14.14/tinymist-darwin-x64"}
|
|
||||||
"platforms.windows-x64" = { checksum = "sha256:3d39c7b417287d8689c69159b65fbc62427e141b9489500ad81039ee783f2549", url = "https://github.com/Myriad-Dreamin/tinymist/releases/download/v0.14.14/tinymist-win32-x64.exe"}
|
|
||||||
|
|
||||||
[[tools.typst]]
|
|
||||||
version = "0.14.2"
|
|
||||||
backend = "aqua:typst/typst"
|
|
||||||
"platforms.linux-arm64" = { checksum = "sha256:491b101aa40a3a7ea82a3f8a6232cabb4e6a7e233810082e5ac812d43fdcd47a", url = "https://github.com/typst/typst/releases/download/v0.14.2/typst-aarch64-unknown-linux-musl.tar.xz"}
|
|
||||||
"platforms.linux-x64" = { checksum = "sha256:a6044cbad2a954deb921167e257e120ac0a16b20339ec01121194ff9d394996d", url = "https://github.com/typst/typst/releases/download/v0.14.2/typst-x86_64-unknown-linux-musl.tar.xz"}
|
|
||||||
"platforms.macos-arm64" = { checksum = "sha256:470aa49a2298d20b65c119a10e4ff8808550453e0cb4d85625b89caf0cedf048", url = "https://github.com/typst/typst/releases/download/v0.14.2/typst-aarch64-apple-darwin.tar.xz"}
|
|
||||||
"platforms.macos-x64" = { checksum = "sha256:4e91d8e1e33ab164f949c5762e01ee3faa585c8615a2a6bd5e3677fa8506b249", url = "https://github.com/typst/typst/releases/download/v0.14.2/typst-x86_64-apple-darwin.tar.xz"}
|
|
||||||
"platforms.windows-x64" = { checksum = "sha256:51353994ac83218c3497052e89b2c432c53b9d4439cdc1b361e2ea4798ebfc13", url = "https://github.com/typst/typst/releases/download/v0.14.2/typst-x86_64-pc-windows-msvc.zip"}
|
|
||||||
|
|
||||||
[[tools.typstyle]]
|
|
||||||
version = "0.14.4"
|
|
||||||
backend = "aqua:Enter-tainer/typstyle"
|
|
||||||
"platforms.linux-arm64" = { checksum = "sha256:b8c220c0d940d7690fb15ef10415de35fdc115465a7534d8102459c68aeec74d", url = "https://github.com/typstyle-rs/typstyle/releases/download/v0.14.4/typstyle-aarch64-unknown-linux-gnu"}
|
|
||||||
"platforms.linux-x64" = { checksum = "sha256:48d9a9a3885855f1b4f6c2b8ea9739623bc458b99c015b77c4f50a1f342ea091", url = "https://github.com/typstyle-rs/typstyle/releases/download/v0.14.4/typstyle-x86_64-unknown-linux-musl"}
|
|
||||||
"platforms.macos-arm64" = { checksum = "sha256:dda3a162f2457a40570c3552cc9c01004138b33f2f921112b117d72f48bd6d56", url = "https://github.com/typstyle-rs/typstyle/releases/download/v0.14.4/typstyle-aarch64-apple-darwin"}
|
|
||||||
"platforms.macos-x64" = { checksum = "sha256:2343f7a4801d9bbda5d7441e8fea95f98b590d6aa3083da5c4e4ca3de885350f", url = "https://github.com/typstyle-rs/typstyle/releases/download/v0.14.4/typstyle-x86_64-apple-darwin"}
|
|
||||||
"platforms.windows-x64" = { checksum = "sha256:b16aebaed0aa296ef3e055d611f1e917f5849d3eb0f953bbcaa6f09f0503fb5b", url = "https://github.com/typstyle-rs/typstyle/releases/download/v0.14.4/typstyle-x86_64-pc-windows-msvc.exe"}
|
|
||||||
|
|
||||||
[[tools.yq]]
|
|
||||||
version = "4.52.2"
|
|
||||||
backend = "aqua:mikefarah/yq"
|
|
||||||
"platforms.linux-arm64" = { checksum = "sha256:c82856ac30da522f50dcdd4f53065487b5a2927e9b87ff637956900986f1f7c2", url = "https://github.com/mikefarah/yq/releases/download/v4.52.2/yq_linux_arm64"}
|
|
||||||
"platforms.linux-x64" = { checksum = "sha256:a74bd266990339e0c48a2103534aef692abf99f19390d12c2b0ce6830385c459", url = "https://github.com/mikefarah/yq/releases/download/v4.52.2/yq_linux_amd64"}
|
|
||||||
"platforms.macos-arm64" = { checksum = "sha256:34613ea97c4c77e1894a8978dbf72588d187a69a6292c10dab396c767a1ecde7", url = "https://github.com/mikefarah/yq/releases/download/v4.52.2/yq_darwin_arm64"}
|
|
||||||
"platforms.macos-x64" = { checksum = "sha256:54a63555210e73abed09108097072e28bf82a6bb20439a72b55509c4dd42378d", url = "https://github.com/mikefarah/yq/releases/download/v4.52.2/yq_darwin_amd64"}
|
|
||||||
"platforms.windows-x64" = { checksum = "sha256:2b6cd8974004fa0511f6b6b359d2698214fadeb4599f0b00e8d85ae62b3922d4", url = "https://github.com/mikefarah/yq/releases/download/v4.52.2/yq_windows_amd64.exe"}
|
|
||||||
@@ -1,265 +0,0 @@
|
|||||||
# unexplrd's example setup with mise
|
|
||||||
|
|
||||||
This example has the following structure:
|
|
||||||
```
|
|
||||||
.
|
|
||||||
├── .mise/
|
|
||||||
│ ├── config.toml
|
|
||||||
│ └── mise.lock
|
|
||||||
├── vendor/
|
|
||||||
│ └── typst-packages/
|
|
||||||
│ └── ...
|
|
||||||
└── src/
|
|
||||||
├── assets/
|
|
||||||
│ ├── foo.csv
|
|
||||||
│ ├── bar.c
|
|
||||||
│ └── ...
|
|
||||||
├── figures/
|
|
||||||
│ ├── clojure-logo.png
|
|
||||||
│ ├── error-log.jpg
|
|
||||||
│ └── ...
|
|
||||||
├── doc.toml
|
|
||||||
├── main.typ
|
|
||||||
└── utils.typ
|
|
||||||
```
|
|
||||||
|
|
||||||
## Advantages
|
|
||||||
- Minimal
|
|
||||||
- All you need is [`mise`](https://mise.jdx.dev/) and `git`
|
|
||||||
- Declarative
|
|
||||||
- Sets up the environment and dependencies automatically
|
|
||||||
- Every work config is separate to avoid breaking changes in Typst and `nure` package
|
|
||||||
- Customizable
|
|
||||||
- Add your own mise tasks, change existing tasks, it's just a `.toml` file
|
|
||||||
|
|
||||||
## Project structure
|
|
||||||
All work contents are stored in `src/` to avoid clutter.
|
|
||||||
|
|
||||||
### Files
|
|
||||||
- `src/doc.toml`: work-specific settings, could be auto-filled, useful for scripts, see (TODO: add a demo nushell script)
|
|
||||||
- `src/utils.typ`: utilities and functions used across the project
|
|
||||||
- `src/main.typ`: main entry file
|
|
||||||
|
|
||||||
### Directories
|
|
||||||
- `src/chapters/`: for breaking up the project into multiple files, if necessary
|
|
||||||
- `src/figures/`: for images and pictures
|
|
||||||
- `src/assets/`: other non-image, non-typst files
|
|
||||||
|
|
||||||
## Mise
|
|
||||||
|
|
||||||
### Tasks
|
|
||||||
- `compile`: Execute `typst compile` on `src/main.typ`
|
|
||||||
- `watch`: Execute `typst watch` on `src/main.typ`
|
|
||||||
- `rename`: Copy output `.pdf` file with an auto-generated name from metadata in `doc.toml`
|
|
||||||
- `fetch-nure-package`: clone package git repository to a directory specified in `[vars]`
|
|
||||||
- `update-package-rev`: updates `vars.nure_package_rev` with the last commit id from the specified branch (`vars.nure_package_ref`)
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
### Templating
|
|
||||||
|
|
||||||
I have a following per-semester directory structure:
|
|
||||||
```
|
|
||||||
/home/user/Documents/nure/
|
|
||||||
└── .config/
|
|
||||||
├── defaults.yaml
|
|
||||||
├── subjects.yaml
|
|
||||||
├── mise/
|
|
||||||
│ ├── config.toml
|
|
||||||
│ └── mise.lock
|
|
||||||
└── template/
|
|
||||||
├── .mise
|
|
||||||
│ ├── config.toml
|
|
||||||
│ └── mise.lock
|
|
||||||
└── src
|
|
||||||
├── appendices.typ
|
|
||||||
├── assets/
|
|
||||||
├── figures/
|
|
||||||
├── main.typ
|
|
||||||
└── utils.typ
|
|
||||||
```
|
|
||||||
|
|
||||||
<details><summary>Contents of <code>.config/default.yaml</code></summary><p>
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
university: ХНУРЕ
|
|
||||||
default_author:
|
|
||||||
name: Косач Л. П.
|
|
||||||
edu-program: ПЗПІ
|
|
||||||
group: 23-2
|
|
||||||
gender: f
|
|
||||||
variant: 8
|
|
||||||
full-name-gen: Косач Лариси Петрівни
|
|
||||||
course: 2
|
|
||||||
semester: 4
|
|
||||||
work_types:
|
|
||||||
lb: ЛБ
|
|
||||||
pz: ПЗ
|
|
||||||
kr: КР
|
|
||||||
```
|
|
||||||
|
|
||||||
</p></details>
|
|
||||||
|
|
||||||
<details><summary>Contents of <code>.config/subjects.yaml</code></summary><p>
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
smp:
|
|
||||||
name: СМП
|
|
||||||
full_name: Скриптові мови програмування
|
|
||||||
mentors:
|
|
||||||
- name: Шевченко Т. Г.
|
|
||||||
degree: Доцент кафедри ПІ
|
|
||||||
gender: m
|
|
||||||
- name: Франко І. Я.
|
|
||||||
degree: Асистент кафедри ПІ
|
|
||||||
gender: m
|
|
||||||
iks:
|
|
||||||
name: ІКС
|
|
||||||
full_name: Інформаційно-комунікаційні системи
|
|
||||||
mentors:
|
|
||||||
- name: Мартинчук О. О.
|
|
||||||
degree: Доцент кафедри ІКІ
|
|
||||||
gender: m
|
|
||||||
# etc...
|
|
||||||
```
|
|
||||||
|
|
||||||
</p></details>
|
|
||||||
|
|
||||||
<details><summary>Contents of <code>.config/mise/config.toml</code></summary><p>
|
|
||||||
|
|
||||||
```toml
|
|
||||||
[settings]
|
|
||||||
quiet = true
|
|
||||||
env_shell_expand = true
|
|
||||||
lockfile = true
|
|
||||||
|
|
||||||
[tools]
|
|
||||||
"aqua:nushell/nushell" = "latest"
|
|
||||||
|
|
||||||
[tasks.work]
|
|
||||||
usage = '''
|
|
||||||
arg "<subject>" help="Target environment"
|
|
||||||
arg "<type>" help="Target environment"
|
|
||||||
arg "<number>" help="Target environment"
|
|
||||||
'''
|
|
||||||
|
|
||||||
run = '''
|
|
||||||
#!/usr/bin/env nu
|
|
||||||
|
|
||||||
let template_dir = ".config/template"
|
|
||||||
let config_dir = ".config"
|
|
||||||
# let out_dir = $"(pwd)"
|
|
||||||
let out_dir = $"(pwd)/works"
|
|
||||||
|
|
||||||
def not_main [subject: string, shortcode: string, number?: int] {
|
|
||||||
let subject_lower = ($subject | str downcase)
|
|
||||||
let shortcode_lower = ($shortcode | str downcase)
|
|
||||||
|
|
||||||
validate-input $subject $shortcode $number
|
|
||||||
|
|
||||||
let temp_dir = $"/tmp/nure-work-(random chars -l 8)"
|
|
||||||
let final_dir = $"($out_dir)/($subject_lower)/($shortcode_lower)($number)"
|
|
||||||
let subject_dir = $"($out_dir)/($subject_lower)"
|
|
||||||
|
|
||||||
# TODO?: replace with git clone
|
|
||||||
cp -r ($config_dir)/template $temp_dir
|
|
||||||
generate-doc-toml $shortcode_lower $subject_lower $temp_dir $number
|
|
||||||
check-mkdir $out_dir
|
|
||||||
if ($final_dir | path exists) {
|
|
||||||
error make -u {msg: $"Directory ($final_dir) already exists"}
|
|
||||||
}
|
|
||||||
|
|
||||||
check-mkdir $subject_dir; cp -r $temp_dir $final_dir; rm -rf $temp_dir
|
|
||||||
print $"=> Created new work: ($final_dir)"
|
|
||||||
}
|
|
||||||
|
|
||||||
def check-mkdir [path: string] { if not ($path | path exists) { mkdir $path } }
|
|
||||||
|
|
||||||
def validate-input [subject: string, shortcode: string, number?: int] {
|
|
||||||
if not ($config_dir | path exists) {
|
|
||||||
error make -u {msg: $"($config_dir) not found"}
|
|
||||||
}
|
|
||||||
|
|
||||||
let defaults_yaml = $"($config_dir)/defaults.yaml"
|
|
||||||
let subjects_yaml = $"($config_dir)/subjects.yaml"
|
|
||||||
|
|
||||||
if not ($defaults_yaml | path exists) {
|
|
||||||
error make -u {msg: $"defaults.yaml not found in ($config_dir)"}
|
|
||||||
}
|
|
||||||
if not ($subjects_yaml | path exists) {
|
|
||||||
error make -u {msg: $"subjects.yaml not found in ($config_dir)"}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($number != nothing and $number < 1 ) {
|
|
||||||
error make -u {msg: "Work number should be greater than 0"}
|
|
||||||
}
|
|
||||||
|
|
||||||
let subject_lower = ($subject | str downcase)
|
|
||||||
let subjects = (open $subjects_yaml | columns)
|
|
||||||
if $subject_lower not-in $subjects {
|
|
||||||
error make -u {
|
|
||||||
msg: $"Subject '($subject)' not found in configuration"
|
|
||||||
help: $"Available subjects: ($subjects | str join ', ')"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def generate-doc-toml [shortcode: string, subject: string, target_dir: string, number?: int] {
|
|
||||||
let defaults = (open $"($config_dir)/defaults.yaml")
|
|
||||||
let subjects = (open $"($config_dir)/subjects.yaml")
|
|
||||||
|
|
||||||
let subject_data = ($subjects | get $subject)
|
|
||||||
let work_type = ($defaults | get work_types | try { get $shortcode } catch { $shortcode })
|
|
||||||
|
|
||||||
{
|
|
||||||
university: ($defaults | get university)
|
|
||||||
subject: ($subject_data | get name), type: $work_type, number: $number
|
|
||||||
mentors: ($subject_data | get mentors), authors: [($defaults | get default_author)]
|
|
||||||
} | compact --empty | to toml | save $"($target_dir)/src/doc.toml" --force
|
|
||||||
}
|
|
||||||
|
|
||||||
not_main {{usage.subject}} {{usage.type}} {{usage.number}}
|
|
||||||
'''
|
|
||||||
```
|
|
||||||
|
|
||||||
</p></details>
|
|
||||||
|
|
||||||
`template/` is this empty template without `doc.toml`
|
|
||||||
|
|
||||||
Nushell script does two things:
|
|
||||||
- Creates a new work from a template: `works/smp/lb1`
|
|
||||||
- Auto-fills `doc.toml` with data from `defaults.yaml` and mentor data from `subjects.yaml`
|
|
||||||
|
|
||||||
### Patching the package
|
|
||||||
A patch to add new subjects:
|
|
||||||
|
|
||||||
```diff
|
|
||||||
diff --git a/src/config/universities.yaml b/src/config/universities.yaml
|
|
||||||
index 8855a07..1aefc96 100644
|
|
||||||
--- a/src/config/universities.yaml
|
|
||||||
+++ b/src/config/universities.yaml
|
|
||||||
@@ -60,7 +60,6 @@
|
|
||||||
ПЕСЕ: Психологія екстремальних стосунків та ефективної адаптації
|
|
||||||
ПНП: Програмування на платформі .NЕТ
|
|
||||||
ПП: Проектний практикум
|
|
||||||
- ПРОГ: Програмування
|
|
||||||
ПарП: Параллельне програмування
|
|
||||||
СА: Системний аналіз
|
|
||||||
СМП: Скриптові мови програмування
|
|
||||||
@@ -76,3 +75,10 @@
|
|
||||||
ФІЛ: Філософія
|
|
||||||
ФВС: Фізичне виховання та спорт
|
|
||||||
ХТ: Хмарні технології
|
|
||||||
+ АКС: Архітектура комп'ютерних систем
|
|
||||||
+ ІКС: Інформаційно-комунікаційні системи
|
|
||||||
+ МБ: Мережна безпека
|
|
||||||
+ МКр: Мережна криміналістика
|
|
||||||
+ ОКЗІ: Основи криптографічного захисту інформації
|
|
||||||
+ Прог: Програмування
|
|
||||||
+ ТІК: Теорія інформації та кодування
|
|
||||||
```
|
|
||||||
|
|
||||||
To apply it, add the following command to the end of `fetch_nure_package` task:
|
|
||||||
```sh
|
|
||||||
git -C {{vars.nure_package_path}} apply --check --apply --quiet $MISE_PROJECT_ROOT/custom-subjects.patch || exit 0
|
|
||||||
```
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
university = "ХНУРЕ"
|
|
||||||
subject = "АКС"
|
|
||||||
type = "ЛБ"
|
|
||||||
number = 1
|
|
||||||
|
|
||||||
[[mentors]]
|
|
||||||
name = ""
|
|
||||||
degree = ""
|
|
||||||
gender = ""
|
|
||||||
|
|
||||||
[[authors]]
|
|
||||||
name = ""
|
|
||||||
edu-program = "КУІБ"
|
|
||||||
group = "24-1"
|
|
||||||
gender = "m"
|
|
||||||
variant = 6
|
|
||||||
full-name-gen = ""
|
|
||||||
course = 2
|
|
||||||
semester = 4
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
#import "@vendor/nure:0.1.1": *
|
|
||||||
#import "utils.typ": *
|
|
||||||
|
|
||||||
#import style: spacing
|
|
||||||
|
|
||||||
// Apply custom rule from utils.typ
|
|
||||||
// #show: correctly-indent-list-and-enum-items
|
|
||||||
|
|
||||||
// #show: style.dstu
|
|
||||||
#show: pz-lb.with(..toml("doc.toml"), title: "") // set title to none if empty
|
|
||||||
|
|
||||||
/// Useful snippets
|
|
||||||
|
|
||||||
/// Import a .csv table
|
|
||||||
// #figure(
|
|
||||||
// caption: [],
|
|
||||||
// table(
|
|
||||||
// columns: 4,
|
|
||||||
// table.header([], [], [], []),
|
|
||||||
// ..csv("assets/table.csv").flatten(),
|
|
||||||
// ),
|
|
||||||
// )
|
|
||||||
|
|
||||||
/// Appendices
|
|
||||||
// #style.appendices(include "chapters/appendices.typ")
|
|
||||||
// or
|
|
||||||
// #show: style.appendices
|
|
||||||
// = ...
|
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
#import "@vendor/nure:0.1.1": utils
|
|
||||||
|
|
||||||
/// captioned image with auto-generated label from path
|
|
||||||
/// Usage: img("path/to/image.png", "Caption")(optional: "source")
|
|
||||||
#let img(path, caption, ..sink) = {
|
|
||||||
let source = sink.pos().at(0, default: ())
|
|
||||||
[ #figure(image(path, ..sink.named()), caption: utils.img-caption(caption, source)) #utils.img-label(path) ]
|
|
||||||
}
|
|
||||||
|
|
||||||
/// takes in a string of code, e.g. #code(read("foo.c"))
|
|
||||||
#let code(content) = raw(block: true, theme: none, content)
|
|
||||||
|
|
||||||
/// read path as bytes
|
|
||||||
#let b(path) = bytes(read(path, encoding: none))
|
|
||||||
|
|
||||||
/// include chapters by file names from /chapters
|
|
||||||
#let chapters(ch) = (
|
|
||||||
array(ch).map(chapter => include str(chapter) + ".typ").join()
|
|
||||||
)
|
|
||||||
|
|
||||||
/// https://forum.typst.app/t/how-to-make-bullet-list-item-bodies-flow-like-paragraphs/3756/3?u=andrew
|
|
||||||
/// Spacing doesn't work the same way as native solution if par leading and
|
|
||||||
/// spacing are different.
|
|
||||||
#let correctly-indent-list-and-enum-items(doc) = {
|
|
||||||
let first-line-indent() = if type(par.first-line-indent) == dictionary {
|
|
||||||
par.first-line-indent.amount
|
|
||||||
} else {
|
|
||||||
par.first-line-indent
|
|
||||||
}
|
|
||||||
|
|
||||||
show list: li => {
|
|
||||||
for (i, it) in li.children.enumerate() {
|
|
||||||
let nesting = state("list-nesting", 0)
|
|
||||||
let indent = context h((nesting.get() + 1) * li.indent)
|
|
||||||
let get-nesting() = calc.div-euclid(nesting.get(), 10)
|
|
||||||
let marker = context {
|
|
||||||
let n = get-nesting()
|
|
||||||
if type(li.marker) == array {
|
|
||||||
li.marker.at(calc.rem-euclid(n, li.marker.len()))
|
|
||||||
} else if type(li.marker) == content {
|
|
||||||
li.marker
|
|
||||||
} else {
|
|
||||||
li.marker(n)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let parents = state("enum-parents", ()) // Support enum nesting.
|
|
||||||
let body = {
|
|
||||||
parents.update(arr => arr + (-1,))
|
|
||||||
nesting.update(x => x + 10)
|
|
||||||
it.body + parbreak()
|
|
||||||
nesting.update(x => x - 10)
|
|
||||||
parents.update(arr => arr.slice(0, -1))
|
|
||||||
}
|
|
||||||
let content = {
|
|
||||||
marker
|
|
||||||
h(li.body-indent)
|
|
||||||
body
|
|
||||||
}
|
|
||||||
context pad(left: int(nesting.get() != 0) * li.indent, content)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
show enum: en => {
|
|
||||||
let start = if en.start == auto {
|
|
||||||
if en.children.first().has("number") {
|
|
||||||
if en.reversed { en.children.first().number } else { 1 }
|
|
||||||
} else {
|
|
||||||
if en.reversed { en.children.len() } else { 1 }
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
en.start
|
|
||||||
}
|
|
||||||
let number = start
|
|
||||||
for (i, it) in en.children.enumerate() {
|
|
||||||
number = if it.number != auto { it.number } else { number }
|
|
||||||
if en.reversed { number = start - i }
|
|
||||||
let parents = state("enum-parents", ())
|
|
||||||
let get-parents() = parents.get().filter(x => x >= 0)
|
|
||||||
let indent = context h((get-parents().len() + 1) * en.indent)
|
|
||||||
let num = if en.full {
|
|
||||||
context numbering(en.numbering, ..get-parents(), number)
|
|
||||||
} else {
|
|
||||||
numbering(en.numbering, number)
|
|
||||||
}
|
|
||||||
let max-num = if en.full {
|
|
||||||
context numbering(en.numbering, ..get-parents(), en.children.len())
|
|
||||||
} else {
|
|
||||||
numbering(en.numbering, en.children.len())
|
|
||||||
}
|
|
||||||
num = context box(
|
|
||||||
width: measure(max-num).width,
|
|
||||||
align(right, text(overhang: false, num)),
|
|
||||||
)
|
|
||||||
let list-nesting = state("list-nesting", 0) // Support list nesting.
|
|
||||||
let body = {
|
|
||||||
parents.update(arr => arr + (number,))
|
|
||||||
list-nesting.update(x => x + 1)
|
|
||||||
it.body + parbreak()
|
|
||||||
list-nesting.update(x => x - 1)
|
|
||||||
parents.update(arr => arr.slice(0, -1))
|
|
||||||
}
|
|
||||||
if not en.reversed { number += 1 }
|
|
||||||
let content = {
|
|
||||||
num
|
|
||||||
h(en.body-indent)
|
|
||||||
body
|
|
||||||
}
|
|
||||||
context pad(left: int(parents.get().len() != 0) * en.indent, content)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
doc
|
|
||||||
}
|
|
||||||
+1
-1
@@ -7,5 +7,5 @@ license = "GPL-3.0"
|
|||||||
description = "Typst NURE package"
|
description = "Typst NURE package"
|
||||||
|
|
||||||
[template]
|
[template]
|
||||||
path = "template/default"
|
path = "template"
|
||||||
entrypoint = "lab.typ"
|
entrypoint = "lab.typ"
|
||||||
|
|||||||
Reference in New Issue
Block a user