Hello! I’ve been looking to replace Latex and I came across Typst. Overall, I’m loving it, but I’ve encountered one area where Typst seems to be more cumbersome, and I’m wondering how to approach it.
I’ve gotten used to a workflow/document structure where I have (1) a package (a Latex .sty) with custom commands and layouts, (2) a “master document” where I import the package and set the package’s configuration, and (3) other documents that I include in the master document like so: \input{'name of subdocument'}. These subdocuments can use commands from the main package without having to import the package.
I’ve used this structure for submitting creative writing to journals – e.g., each subdocument could be a poem, and the master document would compile a PDF: the header would have my name, plus any other necessary info. Since journals have different requirements, I have a setting for the submission type, which governs things like the kind of info in the header (e.g., a regular submission might include my name, the name of the poem, etc., but a submission to a contest might only include the name of the poem).
With Typst, it seems that I need to include import statements in each document – or have a single file with all import statements, and import that file in each document.
If it’s just a single-line import statement, and if the package(s) only consist of set/show rules, it’s annoying but not a big deal.
The problem comes when I have to configure the package. I’d rather not have to duplicate the configuration across every document, because if I decided to change a setting, I’d have to do so across multiple documents.
Here’s a simplified example of how I have things now in Typst:
// ** manuscript-package.typ ** //
#let custom-linenum = state("custom-linenum", 0)
// layout rules
#let template(
name: "",
font-family: "",
font-size: 12pt,
submission-type: "",
section-style: "",
// etc. //
) = {
set text(
font: font-family,
size: font-size
)
set page(
header: {
if submission-type === "type1" {
// code for type1 header
} else if submission-type === "type2" {
// code for type2 header
}
}
)
show heading.where(level: 2): it => {
if section-style === "style1" {
// style1 heading
} else if section-style === "style2" {
// style2 heading
}
}
}
// functions, default settings, etc.
#let setup(
name: "My Name",
font-family: "Great Font",
font-size: 12pt,
submission-type: "type1",
section-style: "style1",
enable-linenum: true,
linenum-interval: 5,
// etc.//
) = {
#let display-linenum(..options) = {
//custom implementation of line numbering
}
#let line-end(..options) = {
context if enable-linenum {
// only display line number at specified interval
if calc.rem(custom-linenum.get().first(), linenum-interval) == 0 {
display-linenum()
}
// etc. //
linebreak()
}
}
// ...other functions... //
let template = template.with(
name: name,
font-family: font-family,
// etc. //
)
(
line-end: line-end,
// ...other functions... //
template: template
)
}
// ** master document ** //
#import "master-package.typ": setup
#let (line-end, <<...other functions...>>, template) = setup(name: "My Name", font-family: "Wonderful Font", <<etc.>>)
#show: template
#include "subdocument1.typ"
#include "subdocument2.typ"
#include "subdocument2.typ"
I think Typst is overall more concise and easier to handle than Latex (I’ve essentially duplicated my Latex package with far less code in Typst), but I don’t care for the repetition/boilerplate needed to implement my preferred document structure.
I’d appreciate any insights or advice!
EDIT: Corrected some minor mistakes in the code block.