mirror of
https://github.com/typst/typst
synced 2025-07-27 22:37:54 +08:00
Compare commits
5 Commits
a2e87185c1
...
49873b9b43
Author | SHA1 | Date | |
---|---|---|---|
|
49873b9b43 | ||
|
6daae2e292 | ||
|
7f24cd9253 | ||
|
fea153a6fc | ||
|
cdb8a42c68 |
@ -84,8 +84,9 @@ meaning in Typst. We can use `=`, `-`, `+`, and `_` to create headings, lists
|
||||
and emphasized text, respectively. However, having a special symbol for
|
||||
everything we want to insert into our document would soon become cryptic and
|
||||
unwieldy. For this reason, Typst reserves markup symbols only for the most
|
||||
common things. Everything else is inserted with _functions._ For our image to
|
||||
show up on the page, we use Typst's [`image`] function.
|
||||
common things. Everything else is inserted with _functions._ For
|
||||
[our image](https://github.com/typst/typst-dev-assets/blob/main/files/images/glacier.jpg)
|
||||
to show up on the page, we use Typst's [`image`] function.
|
||||
|
||||
```example
|
||||
#image("glacier.jpg")
|
||||
@ -125,19 +126,38 @@ mode. This means, you now have to remove the hash before the image function call
|
||||
The hash is only needed directly in markup (to disambiguate text from function
|
||||
calls).
|
||||
|
||||
The caption consists of arbitrary markup. To give markup to a function, we
|
||||
enclose it in square brackets. This construct is called a _content block._
|
||||
The caption consists of arbitrary markup, and can also be a string. To give
|
||||
markup to a function, we enclose it in square brackets. This construct is called
|
||||
a _content block._
|
||||
|
||||
```example
|
||||
#figure(
|
||||
image("glacier.jpg", width: 70%),
|
||||
caption: [
|
||||
caption: box[
|
||||
_Glaciers_ form an important part
|
||||
of the earth's climate system.
|
||||
],
|
||||
)
|
||||
```
|
||||
|
||||
**Be careful** about putting the square brackets by themselves on separate
|
||||
lines. This will introduce leading and trailing space around inline text inside
|
||||
the brackets, that is hard to notice. Below are several caption examples: one
|
||||
with extra undesired space, and 3 correct ones.
|
||||
|
||||
```example
|
||||
#show rect: none
|
||||
#figure(rect(), caption: [
|
||||
Caption text
|
||||
])
|
||||
#figure(rect(), caption: box[
|
||||
Caption text
|
||||
])
|
||||
#figure(rect(), caption: [Caption
|
||||
text]) // Many spaces in markup counts as one.
|
||||
#figure(rect(), caption: "Caption text") // Spaces in strings are displayed verbatim.
|
||||
```
|
||||
|
||||
You continue to write your report and now want to reference the figure. To do
|
||||
that, first attach a label to figure. A label uniquely identifies an element in
|
||||
your document. Add one after the figure by enclosing some name in angle
|
||||
|
@ -110,8 +110,8 @@ font. For the purposes of the example, we'll also set another page size.
|
||||
margin: (x: 1.8cm, y: 1.5cm),
|
||||
)
|
||||
#set text(
|
||||
size: 10pt,
|
||||
font: "New Computer Modern",
|
||||
size: 10pt
|
||||
)
|
||||
#set par(
|
||||
justify: true,
|
||||
@ -235,19 +235,27 @@ Instead, you could maybe
|
||||
[define a custom function]($function/#defining-functions) that always yields the
|
||||
logo with its image. However, there is an even easier way:
|
||||
|
||||
With show rules, you can redefine how Typst displays certain elements. You
|
||||
With show rules, you can redefine how Typst displays certain elements. You can
|
||||
specify which elements Typst should show differently and how they should look.
|
||||
Show rules can be applied to instances of text, many functions, and even the
|
||||
whole document.
|
||||
|
||||
```example
|
||||
#show "ArtosFlow": name => box[
|
||||
#box(image(
|
||||
// #show "ArtosFlow": name => {
|
||||
// let logo = box(image(
|
||||
// "logo.svg",
|
||||
// height: 0.7em,
|
||||
// ))
|
||||
// [#logo #name]
|
||||
// }
|
||||
#show "ArtosFlow": name => {
|
||||
box(image(
|
||||
"logo.svg",
|
||||
height: 0.7em,
|
||||
))
|
||||
#name
|
||||
]
|
||||
" "
|
||||
name
|
||||
}
|
||||
|
||||
This report is embedded in the
|
||||
ArtosFlow project. ArtosFlow is a
|
||||
@ -256,18 +264,18 @@ project of the Artos Institute.
|
||||
|
||||
There is a lot of new syntax in this example: We write the `{show}` keyword,
|
||||
followed by a string of text we want to show differently and a colon. Then, we
|
||||
write a function that takes the content that shall be shown as an argument.
|
||||
Here, we called that argument `name`. We can now use the `name` variable in the
|
||||
function's body to print the ArtosFlow name. Our show rule adds the logo image
|
||||
in front of the name and puts the result into a box to prevent linebreaks from
|
||||
occurring between logo and name. The image is also put inside of a box, so that
|
||||
it does not appear in its own paragraph.
|
||||
write a function that takes the content as an argument that shall be shown.
|
||||
Here, we called that argument `name`. We can now use the `name` variable in
|
||||
the function's body to display the ArtosFlow name. Our show rule adds the logo
|
||||
image to the left of the name and inserts a single space between the two.
|
||||
The image is put inside of a `box`, so that it does not appear in its own
|
||||
paragraph, because `image` is a block-level element.
|
||||
|
||||
The calls to the first box function and the image function did not require a
|
||||
leading `#` because they were not embedded directly in markup. When Typst
|
||||
expects code instead of markup, the leading `#` is not needed to access
|
||||
functions, keywords, and variables. This can be observed in parameter lists,
|
||||
function definitions, and [code blocks]($scripting).
|
||||
<!-- The calls to the first box function and the image function did not require a -->
|
||||
<!-- leading `#` because they were not embedded directly in markup. When Typst -->
|
||||
<!-- expects code instead of markup, the leading `#` is not needed to access -->
|
||||
<!-- functions, keywords, and variables. This can be observed in parameter lists, -->
|
||||
<!-- function definitions, and [code blocks]($scripting). -->
|
||||
|
||||
## Review
|
||||
You now know how to apply basic formatting to your Typst documents. You learned
|
||||
|
@ -6,7 +6,7 @@ description: Typst's tutorial.
|
||||
In the previous two chapters of this tutorial, you have learned how to write a
|
||||
document in Typst and how to change its formatting. The report you wrote
|
||||
throughout the last two chapters got a straight A and your supervisor wants to
|
||||
base a conference paper on it! The report will of course have to comply with the
|
||||
base a conference paper on it! The paper will of course have to comply with the
|
||||
conference's style guide. Let's see how we can achieve that.
|
||||
|
||||
Before we start, let's create a team, invite your supervisor and add them to the
|
||||
@ -51,7 +51,6 @@ Let's start by writing some set rules for the document.
|
||||
|
||||
```example
|
||||
#set page(
|
||||
>>> margin: auto,
|
||||
paper: "us-letter",
|
||||
header: align(right)[
|
||||
A fluid dynamic model for
|
||||
@ -61,8 +60,8 @@ Let's start by writing some set rules for the document.
|
||||
)
|
||||
#set par(justify: true)
|
||||
#set text(
|
||||
font: "Libertinus Serif",
|
||||
size: 11pt,
|
||||
font: "Libertinus Serif",
|
||||
)
|
||||
|
||||
#lorem(600)
|
||||
@ -72,12 +71,12 @@ You are already familiar with most of what is going on here. We set the text
|
||||
size to `{11pt}` and the font to Libertinus Serif. We also enable paragraph
|
||||
justification and set the page size to US letter.
|
||||
|
||||
The `header` argument is new: With it, we can provide content to fill the top
|
||||
The `header` field is new: with it, we can provide content to fill the top
|
||||
margin of every page. In the header, we specify our paper's title as requested
|
||||
by the conference style guide. We use the `align` function to align the text to
|
||||
the right.
|
||||
|
||||
Last but not least is the `numbering` argument. Here, we can provide a
|
||||
Last but not least is the `numbering` field. Here, we can provide a
|
||||
[numbering pattern]($numbering) that defines how to number the pages. By
|
||||
setting it to `{"1"}`, Typst only displays the bare page number. Setting it to
|
||||
`{"(1/1)"}` would have displayed the current page and total number of pages
|
||||
@ -89,35 +88,65 @@ Now, let's add a title and an abstract. We'll start with the title. We center
|
||||
align it and increase its font weight by enclosing it in `[*stars*]`.
|
||||
|
||||
```example
|
||||
>>> #set page(width: 300pt, margin: 30pt)
|
||||
>>> #set text(font: "Libertinus Serif", 11pt)
|
||||
#align(center, text(17pt)[
|
||||
>>> #set page(
|
||||
>>> // paper: "us-letter",
|
||||
>>> width: 300pt,
|
||||
>>> margin: 30pt,
|
||||
>>> header: align(right)[
|
||||
>>> A fluid dynamic model for
|
||||
>>> glacier flow
|
||||
>>> ],
|
||||
>>> // numbering: "1",
|
||||
>>> )
|
||||
>>> #set par(justify: true)
|
||||
>>> #set text(11pt, font: "Libertinus Serif")
|
||||
<<< ...
|
||||
#align(center, block(text(
|
||||
17pt,
|
||||
hyphenate: false
|
||||
)[
|
||||
*A fluid dynamic model
|
||||
for glacier flow*
|
||||
])
|
||||
]))
|
||||
```
|
||||
|
||||
This looks right. We used the `text` function to override the previous text
|
||||
set rule locally, increasing the size to 17pt for the function's argument. Let's
|
||||
also add the author list: Since we are writing this paper together with our
|
||||
supervisor, we'll add our own and their name.
|
||||
set rule locally, increasing the size to 17 pt.
|
||||
Add explanation about block+hyphenate, which is pretty convoluted.
|
||||
Let's also add the author list: Since we are writing this paper together with
|
||||
our supervisor, we'll add our own and their name.
|
||||
|
||||
```example
|
||||
>>> #set page(width: 300pt, margin: 30pt)
|
||||
>>> #set text(font: "Libertinus Serif", 11pt)
|
||||
>>> #set page(
|
||||
>>> // paper: "us-letter",
|
||||
>>> width: 300pt,
|
||||
>>> margin: 30pt,
|
||||
>>> header: align(right)[
|
||||
>>> A fluid dynamic model for
|
||||
>>> glacier flow
|
||||
>>> ],
|
||||
>>> // numbering: "1",
|
||||
>>> )
|
||||
>>> #set par(justify: true)
|
||||
>>> #set text(11pt, font: "Libertinus Serif")
|
||||
>>>
|
||||
>>> #align(center, text(17pt)[
|
||||
>>> #align(center, block(text(
|
||||
>>> 17pt,
|
||||
>>> hyphenate: false
|
||||
>>> )[
|
||||
>>> *A fluid dynamic model
|
||||
>>> for glacier flow*
|
||||
>>> ])
|
||||
>>> ]))
|
||||
<<< ...
|
||||
#grid(
|
||||
columns: (1fr, 1fr),
|
||||
align(center)[
|
||||
align: center,
|
||||
[
|
||||
Therese Tungsten \
|
||||
Artos Institute \
|
||||
#link("mailto:tung@artos.edu")
|
||||
],
|
||||
align(center)[
|
||||
[
|
||||
Dr. John Doe \
|
||||
Artos Institute \
|
||||
#link("mailto:doe@artos.edu")
|
||||
@ -127,45 +156,49 @@ supervisor, we'll add our own and their name.
|
||||
|
||||
The two author blocks are laid out next to each other. We use the [`grid`]
|
||||
function to create this layout. With a grid, we can control exactly how large
|
||||
each column is and which content goes into which cell. The `columns` argument
|
||||
takes an array of [relative lengths]($relative) or [fractions]($fraction). In
|
||||
this case, we passed it two equal fractional sizes, telling it to split the
|
||||
available space into two equal columns. We then passed two content arguments to
|
||||
the grid function. The first with our own details, and the second with our
|
||||
supervisors'. We again use the `align` function to center the content within the
|
||||
column. The grid takes an arbitrary number of content arguments specifying the
|
||||
cells. Rows are added automatically, but they can also be manually sized with
|
||||
the `rows` argument.
|
||||
each column is and which content goes into which cell. The `columns` field
|
||||
takes the number of columns, or an array of [relative lengths]($relative) or
|
||||
[fractions]($fraction). In this case, we passed it two equal fractional sizes,
|
||||
telling it to split the available space into two equal columns. We then passed
|
||||
two content arguments to the grid function --- the first with our own details,
|
||||
and the second with our supervisor's. With grid, we can avoid using `align` on
|
||||
each cell content to center them, and instead use the `align` field to do this
|
||||
for all cells automatically. The grid takes an arbitrary number of content
|
||||
arguments specifying the cells. Rows are added automatically, but they can also
|
||||
be manually sized with the `rows` field.
|
||||
|
||||
Now, let's add the abstract. Remember that the conference wants the abstract to
|
||||
be set ragged and centered.
|
||||
|
||||
```example:0,0,612,317.5
|
||||
>>> #set text(font: "Libertinus Serif", 11pt)
|
||||
>>> #set par(justify: true)
|
||||
>>> #set page(
|
||||
>>> "us-letter",
|
||||
>>> margin: auto,
|
||||
>>> header: align(right + horizon)[
|
||||
>>> paper: "us-letter",
|
||||
>>> header: align(right)[
|
||||
>>> A fluid dynamic model for
|
||||
>>> glacier flow
|
||||
>>> ],
|
||||
>>> numbering: "1",
|
||||
>>> )
|
||||
>>> #set par(justify: true)
|
||||
>>> #set text(11pt, font: "Libertinus Serif")
|
||||
>>>
|
||||
>>> #align(center, text(17pt)[
|
||||
>>> #align(center, block(text(
|
||||
>>> 17pt,
|
||||
>>> hyphenate: false
|
||||
>>> )[
|
||||
>>> *A fluid dynamic model
|
||||
>>> for glacier flow*
|
||||
>>> ])
|
||||
>>> ]))
|
||||
>>>
|
||||
>>> #grid(
|
||||
>>> columns: (1fr, 1fr),
|
||||
>>> align(center)[
|
||||
>>> align: center,
|
||||
>>> [
|
||||
>>> Therese Tungsten \
|
||||
>>> Artos Institute \
|
||||
>>> #link("mailto:tung@artos.edu")
|
||||
>>> ],
|
||||
>>> align(center)[
|
||||
>>> [
|
||||
>>> Dr. John Doe \
|
||||
>>> Artos Institute \
|
||||
>>> #link("mailto:doe@artos.edu")
|
||||
@ -198,35 +231,33 @@ keyword:
|
||||
for glacier flow
|
||||
]
|
||||
|
||||
<<< ...
|
||||
|
||||
>>> #set text(font: "Libertinus Serif", 11pt)
|
||||
>>> #set par(justify: true)
|
||||
#set page(
|
||||
>>> "us-letter",
|
||||
>>> margin: auto,
|
||||
header: align(
|
||||
right + horizon,
|
||||
title
|
||||
),
|
||||
>>> paper: "us-letter",
|
||||
<<< ...
|
||||
header: align(right, title),
|
||||
<<< ...
|
||||
>>> numbering: "1",
|
||||
)
|
||||
|
||||
#align(center, text(17pt)[
|
||||
*#title*
|
||||
])
|
||||
|
||||
>>> #set par(justify: true)
|
||||
>>> #set text(11pt, font: "Libertinus Serif")
|
||||
<<< ...
|
||||
|
||||
#align(center, block(text(
|
||||
17pt,
|
||||
hyphenate: false,
|
||||
strong(title),
|
||||
)))
|
||||
|
||||
<<< ...
|
||||
>>> #grid(
|
||||
>>> columns: (1fr, 1fr),
|
||||
>>> align(center)[
|
||||
>>> align: center,
|
||||
>>> [
|
||||
>>> Therese Tungsten \
|
||||
>>> Artos Institute \
|
||||
>>> #link("mailto:tung@artos.edu")
|
||||
>>> ],
|
||||
>>> align(center)[
|
||||
>>> [
|
||||
>>> Dr. John Doe \
|
||||
>>> Artos Institute \
|
||||
>>> #link("mailto:doe@artos.edu")
|
||||
@ -247,55 +278,48 @@ and also within markup (prefixed by `#`, like functions). This way, if we decide
|
||||
on another title, we can easily change it in one place.
|
||||
|
||||
## Adding columns and headings { #columns-and-headings }
|
||||
The paper above unfortunately looks like a wall of lead. To fix that, let's add
|
||||
The paper above unfortunately looks like a wall of lead(?). To fix that, let's add
|
||||
some headings and switch our paper to a two-column layout. Fortunately, that's
|
||||
easy to do: We just need to amend our `page` set rule with the `columns`
|
||||
argument.
|
||||
easy to do: we just need to amend our `page` set rule with the `columns` field.
|
||||
|
||||
By adding `{columns: 2}` to the argument list, we have wrapped the whole
|
||||
document in two columns. However, that would also affect the title and authors
|
||||
overview. To keep them spanning the whole page, we can wrap them in a function
|
||||
call to [`{place}`]($place). Place expects an alignment and the content it
|
||||
should place as positional arguments. Using the named `{scope}` argument, we can
|
||||
call to [`{place}`]($place). The `place` expects an alignment and the content it
|
||||
should place as positional arguments. Using the named `scope` field, we can
|
||||
decide if the items should be placed relative to the current column or its
|
||||
parent (the page). There is one more thing to configure: If no other arguments
|
||||
are provided, `{place}` takes its content out of the flow of the document and
|
||||
are provided, `place` takes its content out of the flow of the document and
|
||||
positions it over the other content without affecting the layout of other
|
||||
content in its container:
|
||||
|
||||
```example
|
||||
#place(
|
||||
top + center,
|
||||
rect(fill: black),
|
||||
)
|
||||
#place(top + center, rect())
|
||||
#lorem(30)
|
||||
```
|
||||
|
||||
If we hadn't used `{place}` here, the square would be in its own line, but here
|
||||
it overlaps the few lines of text following it. Likewise, that text acts like as
|
||||
if there was no square. To change this behavior, we can pass the argument
|
||||
`{float: true}` to ensure that the space taken up by the placed item at the top
|
||||
or bottom of the page is not occupied by any other content.
|
||||
If we hadn't used `place` here, the rectangle would be in its own line, but
|
||||
here it overlaps the few lines of text following it. Likewise, that text acts
|
||||
like as if there was no rectangle. To change this behavior, we can pass the
|
||||
argument `{float: true}` to ensure that the space taken up by the placed item
|
||||
at the top or bottom of the page is not occupied by any other content.
|
||||
|
||||
```example:single
|
||||
>>> #let title = [
|
||||
>>> A fluid dynamic model
|
||||
>>> for glacier flow
|
||||
>>> ]
|
||||
>>>
|
||||
>>> #set text(font: "Libertinus Serif", 11pt)
|
||||
>>> #set par(justify: true)
|
||||
>>>
|
||||
<<< ...
|
||||
|
||||
#set page(
|
||||
>>> margin: auto,
|
||||
paper: "us-letter",
|
||||
header: align(
|
||||
right + horizon,
|
||||
title
|
||||
),
|
||||
header: align(right, title),
|
||||
numbering: "1",
|
||||
columns: 2,
|
||||
)
|
||||
>>> #set par(justify: true)
|
||||
>>> #set text(11pt, font: "Libertinus Serif")
|
||||
<<< ...
|
||||
|
||||
#place(
|
||||
top + center,
|
||||
@ -303,11 +327,7 @@ or bottom of the page is not occupied by any other content.
|
||||
scope: "parent",
|
||||
clearance: 2em,
|
||||
)[
|
||||
>>> #text(
|
||||
>>> 17pt,
|
||||
>>> weight: "bold",
|
||||
>>> title,
|
||||
>>> )
|
||||
>>> #block(text(17pt, hyphenate: false, strong(title)))
|
||||
>>>
|
||||
>>> #grid(
|
||||
>>> columns: (1fr, 1fr),
|
||||
@ -324,11 +344,10 @@ or bottom of the page is not occupied by any other content.
|
||||
>>> )
|
||||
<<< ...
|
||||
|
||||
#par(justify: false)[
|
||||
#set par(justify: false) // Put it above to remove hyphenate?
|
||||
*Abstract* \
|
||||
#lorem(80)
|
||||
]
|
||||
]
|
||||
|
||||
= Introduction
|
||||
#lorem(300)
|
||||
@ -337,14 +356,14 @@ or bottom of the page is not occupied by any other content.
|
||||
#lorem(200)
|
||||
```
|
||||
|
||||
In this example, we also used the `clearance` argument of the `{place}` function
|
||||
to provide the space between it and the body instead of using the [`{v}`]($v)
|
||||
In this example, we also used the `clearance` argument of the `place` function
|
||||
to provide the space between it and the body instead of using the [`v`]
|
||||
function. We can also remove the explicit `{align(center, ..)}` calls around the
|
||||
various parts since they inherit the center alignment from the placement.
|
||||
|
||||
Now there is only one thing left to do: Style our headings. We need to make them
|
||||
centered and use small capitals. Because the `heading` function does not offer
|
||||
a way to set any of that, we need to write our own heading show rule.
|
||||
Now there is only one thing left to do: style our headings. We need to make them
|
||||
centered and use small capitals. For centering we can use a show-set rule, but
|
||||
to use small capitals we need to write our own heading show rule.
|
||||
|
||||
```example:50,250,265,270
|
||||
>>> #let title = [
|
||||
@ -352,37 +371,27 @@ a way to set any of that, we need to write our own heading show rule.
|
||||
>>> for glacier flow
|
||||
>>> ]
|
||||
>>>
|
||||
>>> #set text(font: "Libertinus Serif", 11pt)
|
||||
>>> #set par(justify: true)
|
||||
>>> #set page(
|
||||
>>> "us-letter",
|
||||
>>> margin: auto,
|
||||
>>> header: align(
|
||||
>>> right + horizon,
|
||||
>>> title
|
||||
>>> ),
|
||||
>>> paper: "us-letter",
|
||||
>>> header: align(right, title),
|
||||
>>> numbering: "1",
|
||||
>>> columns: 2,
|
||||
>>> )
|
||||
#show heading: it => [
|
||||
#set align(center)
|
||||
#set text(13pt, weight: "regular")
|
||||
#block(smallcaps(it.body))
|
||||
]
|
||||
>>> #set par(justify: true)
|
||||
>>> #set text(11pt, font: "Libertinus Serif")
|
||||
<<< ...
|
||||
#show heading: set align(center)
|
||||
#show heading: set text(13pt, weight: "regular")
|
||||
#show heading: it => block(smallcaps(it.body))
|
||||
|
||||
<<< ...
|
||||
>>>
|
||||
>>> #place(
|
||||
>>> top + center,
|
||||
>>> float: true,
|
||||
>>> scope: "parent",
|
||||
>>> clearance: 2em,
|
||||
>>> )[
|
||||
>>> #text(
|
||||
>>> 17pt,
|
||||
>>> weight: "bold",
|
||||
>>> title,
|
||||
>>> )
|
||||
>>> #block(text(17pt, hyphenate: false, strong(title)))
|
||||
>>>
|
||||
>>> #grid(
|
||||
>>> columns: (1fr, 1fr),
|
||||
@ -398,11 +407,10 @@ a way to set any of that, we need to write our own heading show rule.
|
||||
>>> ]
|
||||
>>> )
|
||||
>>>
|
||||
>>> #par(justify: false)[
|
||||
>>> #set par(justify: false)
|
||||
>>> *Abstract* \
|
||||
>>> #lorem(80)
|
||||
>>> ]
|
||||
>>> ]
|
||||
>>>
|
||||
>>> = Introduction
|
||||
>>> #lorem(35)
|
||||
@ -411,19 +419,26 @@ a way to set any of that, we need to write our own heading show rule.
|
||||
>>> #lorem(45)
|
||||
```
|
||||
|
||||
This looks great! We used a show rule that applies to all headings. We give it a
|
||||
function that gets passed the heading as a parameter. That parameter can be used
|
||||
as content but it also has some fields like `title`, `numbers`, and `level` from
|
||||
which we can compose a custom look. Here, we are center-aligning, setting the
|
||||
font weight to `{"regular"}` because headings are bold by default, and use the
|
||||
[`smallcaps`] function to render the heading's title in small capitals.
|
||||
This looks great! We used a few rules that apply to all headings. First, we
|
||||
made headings centered, then we set font size to 13 pt and removed default
|
||||
heading boldness by setting `weight` to `{"regular"}`. Lastly, there is a show
|
||||
rule with a closure, i.e., a callback function. We gave it a function that
|
||||
passes the heading as argument. That argument can be used as content but it
|
||||
also has some fields like `title`, `numbers`, and `level`, from which we can
|
||||
compose a custom look. Here, we use the [`smallcaps`] function to render the
|
||||
heading's title in small capitals. Note that heading itself is wrapped in a
|
||||
block by default, as it's a block-level element, and by using `{it.body}` we
|
||||
are destroying the default structure of the heading. This means we strip away
|
||||
not only the `block` "shell", but also any potential numbering and other
|
||||
heading features. To restore it's semantic structure, we wrap
|
||||
`{smallcaps(it.body)}` in a `block`. This way it will behave like usual.
|
||||
|
||||
The only remaining problem is that all headings look the same now. The
|
||||
"Motivation" and "Problem Statement" subsections ought to be italic run in
|
||||
headers, but right now, they look indistinguishable from the section headings. We
|
||||
can fix that by using a `where` selector on our set rule: This is a
|
||||
[method]($scripting/#methods) we can call on headings (and other
|
||||
elements) that allows us to filter them by their level. We can use it to
|
||||
The only remaining problem is that all headings now look the same. The
|
||||
"Motivation" and "Problem Statement" subsections ought to be italic run-in
|
||||
headings, but right now, they look indistinguishable from the section headings.
|
||||
We can fix that by using a `where` selector on our show rules: this is a
|
||||
[method]($scripting/#methods) we can call on headings (and other elements) that
|
||||
allows us to filter them by their level (and other fields). We can use it to
|
||||
differentiate between section and subsection headings:
|
||||
|
||||
```example:50,250,265,245
|
||||
@ -432,47 +447,31 @@ differentiate between section and subsection headings:
|
||||
>>> for glacier flow
|
||||
>>> ]
|
||||
>>>
|
||||
>>> #set text(font: "Libertinus Serif", 11pt)
|
||||
>>> #set par(justify: true)
|
||||
>>> #set page(
|
||||
>>> "us-letter",
|
||||
>>> margin: auto,
|
||||
>>> header: align(
|
||||
>>> right + horizon,
|
||||
>>> title
|
||||
>>> ),
|
||||
>>> paper: "us-letter",
|
||||
>>> header: align(right, title),
|
||||
>>> numbering: "1",
|
||||
>>> columns: 2,
|
||||
>>> )
|
||||
>>>
|
||||
#show heading.where(
|
||||
level: 1
|
||||
): it => block(width: 100%)[
|
||||
#set align(center)
|
||||
#set text(13pt, weight: "regular")
|
||||
#smallcaps(it.body)
|
||||
]
|
||||
>>> #set par(justify: true)
|
||||
>>> #set text(11pt, font: "Libertinus Serif")
|
||||
<<< ...
|
||||
|
||||
#show heading.where(
|
||||
level: 2
|
||||
): it => text(
|
||||
size: 11pt,
|
||||
weight: "regular",
|
||||
style: "italic",
|
||||
it.body + [.],
|
||||
)
|
||||
>>>
|
||||
#show heading.where(level: 1): set align(center)
|
||||
#show heading.where(level: 1): set text(13pt, weight: "regular")
|
||||
#show heading.where(level: 1): it => block(smallcaps(it.body))
|
||||
|
||||
#show heading.where(level: 2): set text(11pt, weight: "regular", style: "italic")
|
||||
#show heading.where(level: 2): it => [#it.body.]
|
||||
|
||||
<<< ...
|
||||
>>> #place(
|
||||
>>> top + center,
|
||||
>>> float: true,
|
||||
>>> scope: "parent",
|
||||
>>> clearance: 2em,
|
||||
>>> )[
|
||||
>>> #text(
|
||||
>>> 17pt,
|
||||
>>> weight: "bold",
|
||||
>>> title,
|
||||
>>> )
|
||||
>>> #block(text(17pt, hyphenate: false, strong(title)))
|
||||
>>>
|
||||
>>> #grid(
|
||||
>>> columns: (1fr, 1fr),
|
||||
@ -488,11 +487,10 @@ differentiate between section and subsection headings:
|
||||
>>> ]
|
||||
>>> )
|
||||
>>>
|
||||
>>> #par(justify: false)[
|
||||
>>> #set par(justify: false)
|
||||
>>> *Abstract* \
|
||||
>>> #lorem(80)
|
||||
>>> ]
|
||||
>>> ]
|
||||
>>>
|
||||
>>> = Introduction
|
||||
>>> #lorem(35)
|
||||
@ -501,10 +499,12 @@ differentiate between section and subsection headings:
|
||||
>>> #lorem(45)
|
||||
```
|
||||
|
||||
This looks great! We wrote two show rules that each selectively apply to the
|
||||
first and second level headings. We used a `where` selector to filter the
|
||||
headings by their level. We then rendered the subsection headings as run-ins. We
|
||||
also automatically add a period to the end of the subsection headings.
|
||||
Excellent! We wrote several rules that selectively apply to the first and second
|
||||
level headings. We used a `where` selector to filter the headings by their
|
||||
level. We then rendered the subsection headings as run-ins. We also
|
||||
automatically added a period to the end of the subsection headings. This time
|
||||
we did not wrap result in a `block`, because we need the heading to be inline
|
||||
with the following text.
|
||||
|
||||
Let's review the conference's style guide:
|
||||
- The font should be an 11 pt serif font ✓
|
||||
@ -516,8 +516,9 @@ Let's review the conference's style guide:
|
||||
13 pt ✓
|
||||
- Second level headings are run-ins, italicized and have the same size as the
|
||||
body text ✓
|
||||
- Finally, the pages should be US letter sized, numbered in the center and the
|
||||
top right corner of each page should contain the title of the paper ✓
|
||||
- Finally, the pages should be US letter sized, numbered in the center of the
|
||||
footer and the top right corner of each page should contain the title of the
|
||||
paper ✓
|
||||
|
||||
We are now in compliance with all of these styles and can submit the paper to
|
||||
the conference! The finished paper looks like this:
|
||||
@ -528,6 +529,62 @@ the conference! The finished paper looks like this:
|
||||
style="box-shadow: 0 4px 12px rgb(89 85 101 / 20%); width: 500px; max-width: 100%; display: block; margin: 24px auto;"
|
||||
>
|
||||
|
||||
Here is a full listing of the finished paper:
|
||||
|
||||
```example
|
||||
#let title = [A fluid dynamic model for glacier flow]
|
||||
|
||||
#set page(
|
||||
paper: "us-letter",
|
||||
header: align(right, title),
|
||||
numbering: "1",
|
||||
columns: 2,
|
||||
)
|
||||
#set par(justify: true)
|
||||
#set text(11pt, font: "Libertinus Serif")
|
||||
|
||||
#show heading.where(level: 1): set align(center)
|
||||
#show heading.where(level: 1): set text(13pt, weight: "regular")
|
||||
#show heading.where(level: 1): it => block(smallcaps(it.body))
|
||||
|
||||
#show heading.where(level: 2): set text(11pt, weight: "regular", style: "italic")
|
||||
#show heading.where(level: 2): it => [#it.body.]
|
||||
|
||||
#place(top + center, float: true, scope: "parent", clearance: 2em)[
|
||||
#block(text(17pt, hyphenate: false, strong(title)))
|
||||
|
||||
#grid(
|
||||
columns: (1fr, 1fr),
|
||||
[
|
||||
Therese Tungsten \
|
||||
Artos Institute \
|
||||
#link("mailto:tung@artos.edu")
|
||||
],
|
||||
[
|
||||
Dr. John Doe \
|
||||
Artos Institute \
|
||||
#link("mailto:doe@artos.edu")
|
||||
]
|
||||
)
|
||||
|
||||
#set par(justify: false)
|
||||
*Abstract* \
|
||||
#lorem(80)
|
||||
]
|
||||
|
||||
= Introduction
|
||||
#lorem(90)
|
||||
|
||||
== Motivation
|
||||
#lorem(140)
|
||||
|
||||
== Problem Statement
|
||||
#lorem(50)
|
||||
|
||||
= Related Work
|
||||
#lorem(200)
|
||||
```
|
||||
|
||||
## Review
|
||||
You have now learned how to create headers and footers, how to use functions and
|
||||
scopes to locally override styles, how to create more complex layouts with the
|
||||
|
@ -25,7 +25,10 @@ You are #amazed[beautiful]!
|
||||
|
||||
This function takes a single argument, `term`, and returns a content block with
|
||||
the `term` surrounded by sparkles. We also put the whole thing in a box so that
|
||||
the term we are amazed by cannot be separated from its sparkles by a line break.
|
||||
the term we are amazed by cannot be separated from its sparkles by a line
|
||||
break. Alternatively, you can use a
|
||||
[shorthand](https://typst.app/docs/reference/symbols/#shorthands)
|
||||
for a no-break space and write `{[✨~#term~✨]}`.
|
||||
|
||||
Many functions that come with Typst have optional named parameters. Our
|
||||
functions can also have them. Let's add a parameter to our function that lets us
|
||||
@ -34,7 +37,7 @@ parameter isn't given.
|
||||
|
||||
```example
|
||||
#let amazed(term, color: blue) = {
|
||||
text(color, box[✨ #term ✨])
|
||||
text(color)[✨~#term~✨]
|
||||
}
|
||||
|
||||
You are #amazed[beautiful]!
|
||||
@ -43,7 +46,7 @@ I am #amazed(color: purple)[amazed]!
|
||||
|
||||
Templates now work by wrapping our whole document in a custom function like
|
||||
`amazed`. But wrapping a whole document in a giant function call would be
|
||||
cumbersome! Instead, we can use an "everything" show rule to achieve the same
|
||||
cumbersome! Instead, we can use an "global" show rule to achieve the same
|
||||
with cleaner code. To write such a show rule, put a colon directly after the
|
||||
show keyword and then provide a function. This function is given the rest of the
|
||||
document as a parameter. The function can then do anything with this content.
|
||||
@ -52,7 +55,7 @@ just pass it by name to the show rule. Let's try it:
|
||||
|
||||
```example
|
||||
>>> #let amazed(term, color: blue) = {
|
||||
>>> text(color, box[✨ #term ✨])
|
||||
>>> text(color)[✨~#term~✨]
|
||||
>>> }
|
||||
#show: amazed
|
||||
I choose to focus on the good
|
||||
@ -68,69 +71,56 @@ powerful.
|
||||
|
||||
## Embedding set and show rules { #set-and-show-rules }
|
||||
To apply some set and show rules to our template, we can use `set` and `show`
|
||||
within a content block in our function and then insert the document into
|
||||
that content block.
|
||||
within a code block in our function and then insert the document into
|
||||
that code block.
|
||||
|
||||
```example
|
||||
#let template(doc) = [
|
||||
#set text(font: "Inria Serif")
|
||||
#show "something cool": [Typst]
|
||||
#doc
|
||||
]
|
||||
#let template(doc) = {
|
||||
set text(font: "Inria Serif")
|
||||
show "something cool": [Typst]
|
||||
doc
|
||||
}
|
||||
|
||||
#show: template
|
||||
I am learning something cool today.
|
||||
It's going great so far!
|
||||
```
|
||||
|
||||
Just like we already discovered in the previous chapter, set rules will apply to
|
||||
everything within their content block. Since the everything show rule passes our
|
||||
whole document to the `template` function, the text set rule and string show
|
||||
rule in our template will apply to the whole document. Let's use this knowledge
|
||||
to create a template that reproduces the body style of the paper we wrote in the
|
||||
previous chapter.
|
||||
Just like we already discovered in the previous chapter, set rules will apply
|
||||
to everything within their scope. Since the global show rule passes our whole
|
||||
document to the `template` function, the text set rule and string show rule in
|
||||
our template will apply to the whole document.
|
||||
|
||||
We used a curly-braced code block instead of a content block. This way, we
|
||||
don't need to prefix all set rules and function calls with a `#`. This also
|
||||
removes the implicit spaces that are naturally introduced in the markup mode.
|
||||
In exchange, we cannot write markup directly in the code block anymore.
|
||||
|
||||
Let's use this knowledge to create a template that reproduces the body style of
|
||||
the paper we wrote in the previous chapter.
|
||||
|
||||
```example
|
||||
#let conf(title, doc) = {
|
||||
set page(
|
||||
paper: "us-letter",
|
||||
>>> margin: auto,
|
||||
header: align(
|
||||
right + horizon,
|
||||
title
|
||||
),
|
||||
header: align(right, title),
|
||||
columns: 2,
|
||||
<<< ...
|
||||
)
|
||||
set par(justify: true)
|
||||
set text(
|
||||
11pt,
|
||||
font: "Libertinus Serif",
|
||||
size: 11pt,
|
||||
)
|
||||
|
||||
// Heading show rules.
|
||||
<<< ...
|
||||
>>> show heading.where(
|
||||
>>> level: 1
|
||||
>>> ): it => block(
|
||||
>>> align(center,
|
||||
>>> text(
|
||||
>>> 13pt,
|
||||
>>> weight: "regular",
|
||||
>>> smallcaps(it.body),
|
||||
>>> )
|
||||
>>> ),
|
||||
>>> )
|
||||
>>> show heading.where(
|
||||
>>> level: 2
|
||||
>>> ): it => box(
|
||||
>>> text(
|
||||
>>> 11pt,
|
||||
>>> weight: "regular",
|
||||
>>> style: "italic",
|
||||
>>> it.body + [.],
|
||||
>>> )
|
||||
>>> )
|
||||
>>> show heading.where(level: 1): set align(center)
|
||||
>>> show heading.where(level: 1): set text(13pt, weight: "regular")
|
||||
>>> show heading.where(level: 1): it => block(smallcaps(it.body))
|
||||
>>>
|
||||
>>> show heading.where(level: 2): set text(11pt, weight: "regular", style: "italic")
|
||||
>>> show heading.where(level: 2): it => [#it.body.]
|
||||
|
||||
doc
|
||||
}
|
||||
@ -154,24 +144,17 @@ previous chapter.
|
||||
>>> #lorem(200)
|
||||
```
|
||||
|
||||
We copy-pasted most of that code from the previous chapter. The two differences
|
||||
are this:
|
||||
We copied most of that code from the previous chapter. However, now we wrapped
|
||||
everything in the function `conf` using a global show rule. The function applies
|
||||
a few set and show rules and echoes the content it has been passed at the end.
|
||||
|
||||
1. We wrapped everything in the function `conf` using an everything show rule.
|
||||
The function applies a few set and show rules and echoes the content it has
|
||||
been passed at the end.
|
||||
|
||||
2. Moreover, we used a curly-braced code block instead of a content block. This
|
||||
way, we don't need to prefix all set rules and function calls with a `#`. In
|
||||
exchange, we cannot write markup directly in the code block anymore.
|
||||
|
||||
Also note where the title comes from: We previously had it inside of a variable.
|
||||
Also note where the title comes from: we previously had it inside of a variable.
|
||||
Now, we are receiving it as the first parameter of the template function. To do
|
||||
so, we passed a closure (that's a function without a name that is used right
|
||||
away) to the everything show rule. We did that because the `conf` function
|
||||
expects two positional arguments, the title and the body, but the show rule will
|
||||
only pass the body. Therefore, we add a new function definition that allows us
|
||||
to set a paper title and use the single parameter from the show rule.
|
||||
away) to the global show rule. We did that because the `conf` function expects
|
||||
two positional arguments: the title and the body, but the show rule will only
|
||||
pass the body. Therefore, we add a new function definition that allows us to set
|
||||
a paper title and use the single parameter from the show rule.
|
||||
|
||||
## Templates with named arguments { #named-arguments }
|
||||
Our paper in the previous chapter had a title and an author list. Let's add
|
||||
@ -230,6 +213,9 @@ multiple arguments for the grid. We can do that by using the
|
||||
[`spread` operator]($arguments). It takes an array and applies each of its items
|
||||
as a separate argument to the function.
|
||||
|
||||
Let's also include some PDF metadata. We can achieve this by using
|
||||
the [`document`] function and specifying fields such as `title` and `author`.
|
||||
|
||||
The resulting template function looks like this:
|
||||
|
||||
```typ
|
||||
@ -239,12 +225,15 @@ The resulting template function looks like this:
|
||||
abstract: [],
|
||||
doc,
|
||||
) = {
|
||||
set document(title: title, author: authors.map(author => author.name))
|
||||
// Set and show rules from before.
|
||||
>>> #set page(columns: 2)
|
||||
<<< ...
|
||||
|
||||
{
|
||||
set align(center)
|
||||
text(17pt, title)
|
||||
set par(justify: false)
|
||||
|
||||
block(text(17pt, strong(title)))
|
||||
|
||||
let count = authors.len()
|
||||
let ncols = calc.min(count, 3)
|
||||
@ -258,12 +247,11 @@ The resulting template function looks like this:
|
||||
]),
|
||||
)
|
||||
|
||||
par(justify: false)[
|
||||
*Abstract* \
|
||||
#abstract
|
||||
]
|
||||
strong[Abstract]
|
||||
linebreak()
|
||||
abstract
|
||||
}
|
||||
|
||||
set align(left)
|
||||
doc
|
||||
}
|
||||
```
|
||||
@ -291,49 +279,26 @@ call.
|
||||
>>> abstract: [],
|
||||
>>> doc,
|
||||
>>> ) = {
|
||||
>>> set text(font: "Libertinus Serif", 11pt)
|
||||
>>> set par(justify: true)
|
||||
>>> set document(title: title, author: authors.map(author => author.name))
|
||||
>>> set page(
|
||||
>>> "us-letter",
|
||||
>>> margin: auto,
|
||||
>>> header: align(
|
||||
>>> right + horizon,
|
||||
>>> title
|
||||
>>> ),
|
||||
>>> header: align(right, title),
|
||||
>>> numbering: "1",
|
||||
>>> columns: 2,
|
||||
>>> )
|
||||
>>> set par(justify: true)
|
||||
>>> set text(11pt, font: "Libertinus Serif")
|
||||
>>>
|
||||
>>> show heading.where(
|
||||
>>> level: 1
|
||||
>>> ): it => block(
|
||||
>>> align(center,
|
||||
>>> text(
|
||||
>>> 13pt,
|
||||
>>> weight: "regular",
|
||||
>>> smallcaps(it.body),
|
||||
>>> )
|
||||
>>> ),
|
||||
>>> )
|
||||
>>> show heading.where(
|
||||
>>> level: 2
|
||||
>>> ): it => box(
|
||||
>>> text(
|
||||
>>> 11pt,
|
||||
>>> weight: "regular",
|
||||
>>> style: "italic",
|
||||
>>> it.body + [.],
|
||||
>>> )
|
||||
>>> )
|
||||
>>> show heading.where(level: 1): set align(center)
|
||||
>>> show heading.where(level: 1): set text(13pt, weight: "regular")
|
||||
>>> show heading.where(level: 1): it => block(smallcaps(it.body))
|
||||
>>>
|
||||
>>> place(
|
||||
>>> top,
|
||||
>>> float: true,
|
||||
>>> scope: "parent",
|
||||
>>> clearance: 2em,
|
||||
>>> {
|
||||
>>> set align(center)
|
||||
>>> text(17pt, title)
|
||||
>>> show heading.where(level: 2): set text(11pt, weight: "regular", style: "italic")
|
||||
>>> show heading.where(level: 2): it => [#it.body.]
|
||||
>>>
|
||||
>>> place(top + center, float: true, scope: "parent", clearance: 2em, {
|
||||
>>> set par(justify: false)
|
||||
>>> block(text(17pt, title))
|
||||
>>> let count = calc.min(authors.len(), 3)
|
||||
>>> grid(
|
||||
>>> columns: (1fr,) * count,
|
||||
@ -344,19 +309,15 @@ call.
|
||||
>>> #link("mailto:" + author.email)
|
||||
>>> ]),
|
||||
>>> )
|
||||
>>> par(justify: false)[
|
||||
>>> *Abstract* \
|
||||
>>> #abstract
|
||||
>>> ]
|
||||
>>> },
|
||||
>>> )
|
||||
>>> strong[Abstract]
|
||||
>>> linebreak()
|
||||
>>> abstract
|
||||
>>> })
|
||||
>>> doc
|
||||
>>> }
|
||||
<<< #import "conf.typ": conf
|
||||
#show: conf.with(
|
||||
title: [
|
||||
Towards Improved Modelling
|
||||
],
|
||||
title: [Towards Improved Modelling],
|
||||
authors: (
|
||||
(
|
||||
name: "Theresa Tungsten",
|
||||
@ -397,7 +358,7 @@ that define reusable document styles. You've made it far and learned a lot. You
|
||||
can now use Typst to write your own documents and share them with others.
|
||||
|
||||
We are still a super young project and are looking for feedback. If you have any
|
||||
questions, suggestions or you found a bug, please let us know
|
||||
questions, suggestions, or you found a bug, please let us know
|
||||
in the [Forum](https://forum.typst.app/),
|
||||
on our [Discord server](https://discord.gg/2uDybryKPe),
|
||||
on [GitHub](https://github.com/typst/typst/),
|
||||
|
Loading…
x
Reference in New Issue
Block a user