mirror of
https://github.com/typst/typst
synced 2025-07-27 22:37:54 +08:00
Refactor "Making a Template" tutorial
This commit is contained in:
parent
7f24cd9253
commit
6daae2e292
@ -25,7 +25,10 @@ You are #amazed[beautiful]!
|
|||||||
|
|
||||||
This function takes a single argument, `term`, and returns a content block with
|
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` 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
|
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
|
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
|
```example
|
||||||
#let amazed(term, color: blue) = {
|
#let amazed(term, color: blue) = {
|
||||||
text(color, box[✨ #term ✨])
|
text(color)[✨~#term~✨]
|
||||||
}
|
}
|
||||||
|
|
||||||
You are #amazed[beautiful]!
|
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
|
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
|
`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
|
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
|
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.
|
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
|
```example
|
||||||
>>> #let amazed(term, color: blue) = {
|
>>> #let amazed(term, color: blue) = {
|
||||||
>>> text(color, box[✨ #term ✨])
|
>>> text(color)[✨~#term~✨]
|
||||||
>>> }
|
>>> }
|
||||||
#show: amazed
|
#show: amazed
|
||||||
I choose to focus on the good
|
I choose to focus on the good
|
||||||
@ -68,69 +71,56 @@ powerful.
|
|||||||
|
|
||||||
## Embedding set and show rules { #set-and-show-rules }
|
## 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`
|
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
|
within a code block in our function and then insert the document into
|
||||||
that content block.
|
that code block.
|
||||||
|
|
||||||
```example
|
```example
|
||||||
#let template(doc) = [
|
#let template(doc) = {
|
||||||
#set text(font: "Inria Serif")
|
set text(font: "Inria Serif")
|
||||||
#show "something cool": [Typst]
|
show "something cool": [Typst]
|
||||||
#doc
|
doc
|
||||||
]
|
}
|
||||||
|
|
||||||
#show: template
|
#show: template
|
||||||
I am learning something cool today.
|
I am learning something cool today.
|
||||||
It's going great so far!
|
It's going great so far!
|
||||||
```
|
```
|
||||||
|
|
||||||
Just like we already discovered in the previous chapter, set rules will apply to
|
Just like we already discovered in the previous chapter, set rules will apply
|
||||||
everything within their content block. Since the everything show rule passes our
|
to everything within their scope. Since the global show rule passes our whole
|
||||||
whole document to the `template` function, the text set rule and string show
|
document to the `template` function, the text set rule and string show rule in
|
||||||
rule in our template will apply to the whole document. Let's use this knowledge
|
our template will apply to the whole document.
|
||||||
to create a template that reproduces the body style of the paper we wrote in the
|
|
||||||
previous chapter.
|
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
|
```example
|
||||||
#let conf(title, doc) = {
|
#let conf(title, doc) = {
|
||||||
set page(
|
set page(
|
||||||
paper: "us-letter",
|
paper: "us-letter",
|
||||||
>>> margin: auto,
|
header: align(right, title),
|
||||||
header: align(
|
|
||||||
right + horizon,
|
|
||||||
title
|
|
||||||
),
|
|
||||||
columns: 2,
|
columns: 2,
|
||||||
<<< ...
|
<<< ...
|
||||||
)
|
)
|
||||||
set par(justify: true)
|
set par(justify: true)
|
||||||
set text(
|
set text(
|
||||||
|
11pt,
|
||||||
font: "Libertinus Serif",
|
font: "Libertinus Serif",
|
||||||
size: 11pt,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Heading show rules.
|
// Heading show rules.
|
||||||
<<< ...
|
<<< ...
|
||||||
>>> show heading.where(
|
>>> show heading.where(level: 1): set align(center)
|
||||||
>>> level: 1
|
>>> show heading.where(level: 1): set text(13pt, weight: "regular")
|
||||||
>>> ): it => block(
|
>>> show heading.where(level: 1): it => block(smallcaps(it.body))
|
||||||
>>> align(center,
|
>>>
|
||||||
>>> text(
|
>>> show heading.where(level: 2): set text(11pt, weight: "regular", style: "italic")
|
||||||
>>> 13pt,
|
>>> show heading.where(level: 2): it => [#it.body.]
|
||||||
>>> weight: "regular",
|
|
||||||
>>> smallcaps(it.body),
|
|
||||||
>>> )
|
|
||||||
>>> ),
|
|
||||||
>>> )
|
|
||||||
>>> show heading.where(
|
|
||||||
>>> level: 2
|
|
||||||
>>> ): it => box(
|
|
||||||
>>> text(
|
|
||||||
>>> 11pt,
|
|
||||||
>>> weight: "regular",
|
|
||||||
>>> style: "italic",
|
|
||||||
>>> it.body + [.],
|
|
||||||
>>> )
|
|
||||||
>>> )
|
|
||||||
|
|
||||||
doc
|
doc
|
||||||
}
|
}
|
||||||
@ -154,24 +144,17 @@ previous chapter.
|
|||||||
>>> #lorem(200)
|
>>> #lorem(200)
|
||||||
```
|
```
|
||||||
|
|
||||||
We copy-pasted most of that code from the previous chapter. The two differences
|
We copied most of that code from the previous chapter. However, now we wrapped
|
||||||
are this:
|
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.
|
Also note where the title comes from: we previously had it inside of a variable.
|
||||||
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.
|
|
||||||
Now, we are receiving it as the first parameter of the template function. To do
|
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
|
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
|
away) to the global show rule. We did that because the `conf` function expects
|
||||||
expects two positional arguments, the title and the body, but the show rule will
|
two positional arguments: the title and the body, but the show rule will only
|
||||||
only pass the body. Therefore, we add a new function definition that allows us
|
pass the body. Therefore, we add a new function definition that allows us to set
|
||||||
to set a paper title and use the single parameter from the show rule.
|
a paper title and use the single parameter from the show rule.
|
||||||
|
|
||||||
## Templates with named arguments { #named-arguments }
|
## Templates with named arguments { #named-arguments }
|
||||||
Our paper in the previous chapter had a title and an author list. Let's add
|
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
|
[`spread` operator]($arguments). It takes an array and applies each of its items
|
||||||
as a separate argument to the function.
|
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:
|
The resulting template function looks like this:
|
||||||
|
|
||||||
```typ
|
```typ
|
||||||
@ -239,31 +225,33 @@ The resulting template function looks like this:
|
|||||||
abstract: [],
|
abstract: [],
|
||||||
doc,
|
doc,
|
||||||
) = {
|
) = {
|
||||||
|
set document(title: title, author: authors.map(author => author.name))
|
||||||
// Set and show rules from before.
|
// Set and show rules from before.
|
||||||
>>> #set page(columns: 2)
|
|
||||||
<<< ...
|
<<< ...
|
||||||
|
|
||||||
set align(center)
|
{
|
||||||
text(17pt, title)
|
set align(center)
|
||||||
|
set par(justify: false)
|
||||||
|
|
||||||
let count = authors.len()
|
block(text(17pt, strong(title)))
|
||||||
let ncols = calc.min(count, 3)
|
|
||||||
grid(
|
|
||||||
columns: (1fr,) * ncols,
|
|
||||||
row-gutter: 24pt,
|
|
||||||
..authors.map(author => [
|
|
||||||
#author.name \
|
|
||||||
#author.affiliation \
|
|
||||||
#link("mailto:" + author.email)
|
|
||||||
]),
|
|
||||||
)
|
|
||||||
|
|
||||||
par(justify: false)[
|
let count = authors.len()
|
||||||
*Abstract* \
|
let ncols = calc.min(count, 3)
|
||||||
#abstract
|
grid(
|
||||||
]
|
columns: (1fr,) * ncols,
|
||||||
|
row-gutter: 24pt,
|
||||||
|
..authors.map(author => [
|
||||||
|
#author.name \
|
||||||
|
#author.affiliation \
|
||||||
|
#link("mailto:" + author.email)
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
|
||||||
|
strong[Abstract]
|
||||||
|
linebreak()
|
||||||
|
abstract
|
||||||
|
}
|
||||||
|
|
||||||
set align(left)
|
|
||||||
doc
|
doc
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -291,72 +279,45 @@ call.
|
|||||||
>>> abstract: [],
|
>>> abstract: [],
|
||||||
>>> doc,
|
>>> doc,
|
||||||
>>> ) = {
|
>>> ) = {
|
||||||
>>> set text(font: "Libertinus Serif", 11pt)
|
>>> set document(title: title, author: authors.map(author => author.name))
|
||||||
>>> set par(justify: true)
|
>>> set page(
|
||||||
>>> set page(
|
>>> "us-letter",
|
||||||
>>> "us-letter",
|
>>> header: align(right, title),
|
||||||
>>> margin: auto,
|
>>> numbering: "1",
|
||||||
>>> header: align(
|
>>> columns: 2,
|
||||||
>>> right + horizon,
|
>>> )
|
||||||
>>> title
|
>>> set par(justify: true)
|
||||||
>>> ),
|
>>> set text(11pt, font: "Libertinus Serif")
|
||||||
>>> numbering: "1",
|
|
||||||
>>> columns: 2,
|
|
||||||
>>> )
|
|
||||||
>>>
|
>>>
|
||||||
>>> show heading.where(
|
>>> show heading.where(level: 1): set align(center)
|
||||||
>>> level: 1
|
>>> show heading.where(level: 1): set text(13pt, weight: "regular")
|
||||||
>>> ): it => block(
|
>>> show heading.where(level: 1): it => block(smallcaps(it.body))
|
||||||
>>> align(center,
|
|
||||||
>>> text(
|
|
||||||
>>> 13pt,
|
|
||||||
>>> weight: "regular",
|
|
||||||
>>> smallcaps(it.body),
|
|
||||||
>>> )
|
|
||||||
>>> ),
|
|
||||||
>>> )
|
|
||||||
>>> show heading.where(
|
|
||||||
>>> level: 2
|
|
||||||
>>> ): it => box(
|
|
||||||
>>> text(
|
|
||||||
>>> 11pt,
|
|
||||||
>>> weight: "regular",
|
|
||||||
>>> style: "italic",
|
|
||||||
>>> it.body + [.],
|
|
||||||
>>> )
|
|
||||||
>>> )
|
|
||||||
>>>
|
>>>
|
||||||
>>> place(
|
>>> show heading.where(level: 2): set text(11pt, weight: "regular", style: "italic")
|
||||||
>>> top,
|
>>> show heading.where(level: 2): it => [#it.body.]
|
||||||
>>> float: true,
|
>>>
|
||||||
>>> scope: "parent",
|
>>> place(top + center, float: true, scope: "parent", clearance: 2em, {
|
||||||
>>> clearance: 2em,
|
>>> set par(justify: false)
|
||||||
>>> {
|
>>> block(text(17pt, title))
|
||||||
>>> set align(center)
|
>>> let count = calc.min(authors.len(), 3)
|
||||||
>>> text(17pt, title)
|
>>> grid(
|
||||||
>>> let count = calc.min(authors.len(), 3)
|
>>> columns: (1fr,) * count,
|
||||||
>>> grid(
|
>>> row-gutter: 24pt,
|
||||||
>>> columns: (1fr,) * count,
|
>>> ..authors.map(author => [
|
||||||
>>> row-gutter: 24pt,
|
>>> #author.name \
|
||||||
>>> ..authors.map(author => [
|
>>> #author.affiliation \
|
||||||
>>> #author.name \
|
>>> #link("mailto:" + author.email)
|
||||||
>>> #author.affiliation \
|
>>> ]),
|
||||||
>>> #link("mailto:" + author.email)
|
>>> )
|
||||||
>>> ]),
|
>>> strong[Abstract]
|
||||||
>>> )
|
>>> linebreak()
|
||||||
>>> par(justify: false)[
|
>>> abstract
|
||||||
>>> *Abstract* \
|
>>> })
|
||||||
>>> #abstract
|
>>> doc
|
||||||
>>> ]
|
>>> }
|
||||||
>>> },
|
|
||||||
>>> )
|
|
||||||
>>> doc
|
|
||||||
>>>}
|
|
||||||
<<< #import "conf.typ": conf
|
<<< #import "conf.typ": conf
|
||||||
#show: conf.with(
|
#show: conf.with(
|
||||||
title: [
|
title: [Towards Improved Modelling],
|
||||||
Towards Improved Modelling
|
|
||||||
],
|
|
||||||
authors: (
|
authors: (
|
||||||
(
|
(
|
||||||
name: "Theresa Tungsten",
|
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.
|
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
|
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/),
|
in the [Forum](https://forum.typst.app/),
|
||||||
on our [Discord server](https://discord.gg/2uDybryKPe),
|
on our [Discord server](https://discord.gg/2uDybryKPe),
|
||||||
on [GitHub](https://github.com/typst/typst/),
|
on [GitHub](https://github.com/typst/typst/),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user