Trying Typst, an alternative to LaTeX
vline
. I thought it would be implemented vline
I'll find the answer, but… vline
hardcoded in rust code.Now we can go to main.typ
import the file with the function and call the latter, passing it the values we need.
#set page(margin: (left: 3cm, right: 1cm, y: 2cm))
#set text(size: 14pt, font: "Times New Roman", lang: "ru")
#set par(justify: true)
#import "title.typ": title
#title(
"Прикладная математика и информатика",
"Прикладная информатика",
"Бизнес-информатика",
"Разработка веб–приложения для обработки заказов предприятия проката оборудования (на примере ООО «Айсберг»)",
"М.Ю. Родькина",
"Н.Н. Казаченок"
)
![](https://habrastorage.org/getpro/habr/upload_files/2be/c2f/a48/2bec2fa48649c5203a9ff500e29dc4c7.png)
Looks great, even better than the original. I propose to move on, but we will omit the annotation and introduction and make only part of the first chapter by creating a file src/chapters/chapter1.typ
. IN main.typ
I will already use it include
instead of import
which was used for the title page.
I won’t give the chapter code, you can look it up in the repository, I’ll only show the features that interest us. First things first, tags and links:
Программа «Прокат–Эксперт» создана для автоматизации пунктов проката любых предметов и оборудования. Программа производит учет выдаваемых предметов, платежей и взаиморасчетов с клиентами и подготавливает к печати документы и отчеты. Интерфейс программы представлен на @общ-вид-прокат-эксперт.
#figure(
image("../images/Скриншот Общий вид программы проката «Прокат Эксперт».png"),
caption: "Скриншот Общий вид программы проката «Прокат Эксперт»"
) <общ-вид-прокат-эксперт>
For those who are not familiar with labels and links, this is an incredibly convenient thing that allows you to automatically link to the desired image, table, etc. So the code above becomes this:
![](https://habrastorage.org/getpro/habr/upload_files/e9b/f90/a2d/e9bf90a2dff35edf0a64645d71767305.png)
Typst also has the ability to make tags on both headings and regular blocks of text (but this is not exact), which can be used in links.
Regarding styling
figure
, then it's a little inconvenient… It's completely inconvenient. I have not found a solution to remove the centering of labels above tables, for example, without completely reworking the componentfigure.caption
. I think that in LaTeX it is much more convenient and simpler, no matter how strange it may sound.
I would also like to highlight the problems with Typst that the developers cannot fix problem with no indentation on the first line of the first paragraph. That is, if you don’t set up the headings as shown below, then either not at all, or manually indent each time before the first paragraph in the section.
#set par(first-line-indent: 1.25cm) # Отступы во всех параграфах, кроме первого
#show heading.where(level: 3): it => [#it #h(1.25cm)] # Переопределение заголовка
# с отступом после него
So that the style settings do not get in the way in the main file, I will move them to the file preambule.typ
.
#let conf(doc) = {
set par(first-line-indent: 1.25cm)
set list(indent: 1.25cm)
set heading(numbering: "1.")
show heading.where(level: 1): it => [Глава #(counter(heading).display(it.numbering)) #it.body]
show heading.where(level: 3): it => [#it #h(1.25cm)]
show table: set text(size: 12pt)
show table.cell.where(y: 0): strong
show figure: it => [#it #h(1.25cm)]
show figure.where(
kind: table
): set figure.caption(position: top)
[#doc]
}
You probably want to ask what the argument is doc
used? The answer lies in main.typ
. If you use a statement show
without an explicit selector, the entire document will be selected. That is, it turns out that we are passing to the template conf
content that comes after the statement show
and which the template already renders using styles.
#import "preambule.typ": conf
#import "title.typ": title
#title(
"Прикладная математика и информатика",
"Прикладная информатика",
"Бизнес-информатика",
"Разработка веб–приложения для обработки заказов предприятия проката оборудования (на примере ООО «Айсберг»)",
"М.Ю. Родькина",
"Н.Н. Казаченок"
)
#show: conf # то же самое, что show: doc => conf(doc)
#include "chapters/chapter1.typ"
#include "end.typ"
We need a table of contents and lists of materials used. There is a function for this outline. If you do not explicitly specify the type of objects, it will create a table of contents.
#import "utils.typ": t
# ...
#show: conf
#t(outlined: false)[Оглавление]
#outline(title: none)
#pagebreak()
#include "chapters/chapter1.typ"
#include "end.typ"
Due to the fact that the heading styles have been changed, the heading output by the component outline
breaks the project. Therefore, I had to disable the header and write my own component. Due to the fact that if you declare it in a file main.typ
and try to use it end.typ
, then the compiler naturally throws a looped import error. Therefore the file was created utils.typ
with a description of the component t
from “title”.
#let t(outlined: true, body) = {
align(center)[
#block(below: 26pt)[
#show heading: it => [
#set text(size: 16pt)
#it.body
]
#heading(outlined: outlined)[
#upper(body)
]
]
]
}
In turn, I will create a separate file for lists of images and tables lists.typ
.
#import "utils.typ": t
#let list(title, kind) = [
#pagebreak()
#t()[#title]
#outline(
title: none,
target: figure.where(kind: kind)
)
]
#list("Список таблиц", table)
#list("Список изображений", image)
![](https://habrastorage.org/getpro/habr/upload_files/e8a/c76/2f0/e8ac762f0d15a45f0d39ea8ec3975d5d.png)
![](https://habrastorage.org/getpro/habr/upload_files/0ff/cf2/4e6/0ffcf24e684b9c89254e0dd5f35c721c.png)
As for the bibliography, the function is used for it bibliographywhich can work with files like .bib (BibLaTeX) and new file format Hayagriva .yml maintained by Typst developers. For example, we’ll make a small file, but I recommend opening the documentation on the format, it’s not very large.
harry:
type: Book
title: Harry Potter and the Order of the Phoenix
author: Rowling, J. K.
volume: 5
page-total: 768
date: 2003-06-21
language: en-US
electronic:
type: Web
title: Ishkur's Guide to Electronic Music
serial-number: v2.5
author: Ishkur
url: http://www.techno.org/electronic-music-guide/
language: en-US
dostoevsky:
type: Book
title: Преступление и наказание
author: Достоевский, Ф.М.
page-total: 400
date: 2003-06-21
language: ru-RU
Let's change the component a little list
and use the function bibliography
. As you can see, there is even stylization according to GOST, but the problem is that this is only stylization, without sorting by language and type of source. Therefore, you will have to configure the sorting yourself.
#import "utils.typ": t
#let list(title, kind, body: none) = [
#pagebreak()
#t()[#title]
#if body == none {
outline(
title: none,
target: figure.where(kind: kind)
)
} else {
body
}
]
#list("Список таблиц", table)
#list("Список изображений", image)
#list(
"Список источников", none,
body: bibliography("books.yml", full: true, title: none, style: "gost-r-705-2008-numeric")
)
![](https://habrastorage.org/getpro/habr/upload_files/718/684/814/7186848149b618d2afb32c24a6eb6bb8.png)
Using ChatGPT, a simple Python script was generated for priority sorting of a YML file with a bibliography. The script may not work as you expect, because it was made literally in a minute and was not tested. If you use foreign sources, I recommend specifying the parameter language
mandatory for normal sorting. If anyone knows a normal implementation, please write in the comments.
import yaml
import argparse
def sort_key(item):
value = item[1]
# Priority for books
type_priority = 0 if value.get('type', '') == 'Book' else 1
# Priority for Russian language sources
language_priority = 0 if value.get('language', '').startswith('ru') else 1
return (type_priority, language_priority, value.get('author', ''), value.get('date', ''), value.get('language', ''))
def sort_yaml(in_file, out_file):
# Read YAML data from the input file
with open(in_file, 'r', encoding='utf-8') as file:
data = yaml.safe_load(file)
# Sort the data
sorted_data = dict(sorted(data.items(), key=sort_key))
# Generate sorted YAML content
sorted_yaml_content = yaml.dump(sorted_data, allow_unicode=True, sort_keys=False, default_flow_style=False)
# Save the sorted YAML content to the output file
with open(out_file, 'w', encoding='utf-8') as file:
file.write(sorted_yaml_content)
if __name__ == "__main__":
# Command line arguments setup
parser = argparse.ArgumentParser(description='Sort YAML file according to ГОСТ Р 7.0.5–2008')
parser.add_argument('inFile', type=str, help='Input YAML file')
parser.add_argument('outFile', type=str, help='Output YAML file')
args = parser.parse_args()
# Sort the YAML file
sort_yaml(args.inFile, args.outFile)
![](https://habrastorage.org/getpro/habr/upload_files/dd4/890/3af/dd48903af5c9dfb0eb7fdde116341f7f.png)
I wanted to implement it in PowerShell, like the previous script, but for some reason not a single module for working with YAML wanted to work, spitting out a billion errors for all sorts of reasons.
After this, you can use references to sources in the text in two ways:
Using a link by key. That is, the source in your .yml file is written as
the-best-book
then the link will have the same name@the-best-book
.Using a direct function call
cite(label("the best book"))
. Used if the source name contains characters that are not supported in Typst links.
По мнению экспертов, рынок проката в России сейчас переживает небывалый рост, а такая область как прокат строительного инструмента набирает с каждым днем всё большую популярность. Как известно, для ремонта, строительства, как и других работ оптимально применять наиболее качественное оборудование и инструменты. Это помогает значительно сэкономить время и силы. @dostoevsky
Очевидно, что приобрести для себя профессиональный инструмент может далеко не каждый, это, как правило требует значительных вложений и при этом, в подавляющем большинстве случаев, оборудование или инструмент требуются на короткий промежуток времени. Таким образом, приобретать его для себя совершенно экономически не выгодно. @electronic
Именно поэтому пункты проката различного оборудования для стройки, ремонта, дачных работ пользуются значительной популярностью, именно прокат может значительно уменьшить стоимость ремонтных, строительных или дачных работ. По оценкам экспертов товарного рынка, услугами подобных пунктов проката готово пользоваться около 10% жителей современных городов. @harry
![](https://habrastorage.org/getpro/habr/upload_files/c69/522/1bc/c695221bc532fc1929c6b62a84267138.png)
Regarding formulas in Typst, I recommend just opening documentationthere are not many functions there, they are easy to remember, but here’s an example:
$ "Формула" arrow(a) = frac(x^3, x-1) $
![](https://habrastorage.org/getpro/habr/upload_files/fa4/7fa/816/fa47fa8165e5be7fbcad06c98dc25b8b.png)
You may notice that if the code is inserted via #
then the formulas are written between $$
.
Typst also has module for drawing, there are not very many functions there either, mainly for drawing primitives, because there are packages, for example, SetZallowing you to draw advanced graphs.
#import "@preview/cetz:0.2.2"
#align(center)[
#cetz.canvas({
import cetz.draw: *
circle((90deg, 3), radius: 0, name: "content")
circle((210deg, 3), radius: 0, name: "structure")
circle((-30deg, 3), radius: 0, name: "form")
for (c, a) in (
("content", "south"),
("structure", "north"),
("form", "north")
) {
content(c, align(center, c + [\ oriented]), padding: .1, anchor: a)
}
stroke(gray + 1.2pt)
line("content", "structure", "form", close: true)
for (c, s, f, cont) in (
(0.5, 0.1, 1, "Typst"),
(1, 0, 0.4, "DVI"),
(0.5, 0.5, 1, "PDF"),
(0, 0.25, 1, "CSS"),
(0.5, 1, 0, "XML"),
(0.5, 1, 0.4, "HTML"),
(1, 0.2, 0.8, "LaTeX"),
(1, 0.6, 0.8, "TeX"),
(0.8, 0.8, 1, "Word"),
(1, 0.05, 0.05, "ASCII")
) {
content(
(bary: (
content: c,
structure: s,
form: f
)),
cont,
fill: rgb(50, 50, 255, 100),
stroke: none,
frame: "circle"
)
}
})
]
![](https://habrastorage.org/getpro/habr/upload_files/181/683/0f3/1816830f3a2a7bff63abd9bfffd7bc05.png)
Total
Typst has proven itself to be a good alternative to LaTeX. However, as far as we could understand, it has some problems at the current stage of development, although the project is a little over a year old, if I understand correctly. But even if this is the case, it is quite viable and usable.
I tried not to dump everything at once, but gradually introduce new Typst features using examples. Somewhere I might have been confused in concepts or even shown incorrect examples, so please write about this in private messages, as well as about errors.
All the code given in the article can be found in repositories. I don’t claim that my options are reference templates, so if there is anything to improve, be sure to write in the comments!