Slab-Typer: Open-Source LLM for Typst

I’m happy to share something I’ve been working on that I think could really help the adoption of Typst. Today I’m releasing Slab-Typer-1.5B-Base-v2, the first large language model fine-tuned for Typst!

This is a small proof-of-concept model with 1.5 billion parameters, designed as a completion model for Typst code. Think of it as GitHub Copilot, but specifically tailored for Typst. The model has already learned common Typst syntax including layout functions, table markup, and other core language constructs.

Current Capabilities

  • Typst syntax & Common patterns: It understands layout systems, tables, and other frequently used Typst features
  • Fast autocompletion: Designed to work as a lightweight autocomplete assistant in editors and IDEs

The goal is to integrate this into Typst editors to provide intelligent code suggestions as you type, making document creation faster and more intuitive.

What’s Coming Next

Here’s what I’m planning for future releases:

  1. Larger, smarter models - Scaling up beyond 1.5B parameters for more sophisticated understanding
  2. Full template generation - Models that can create complete Typst document templates from descriptions
  3. Instruction-tuned variants - Fine-tuned models that can answer questions and provide help with Typst syntax
  4. PDF-to-Typst translation - Converting existing PDF documents into editable Typst markup

Try It Out

You can find the model on Hugging Face: rkstgr/Slab-Typer-1.5B-Base-v2-GGUF. I would recommend using Ollama or LM-Studio to run the model locally.

I’d love to hear your thoughts and feedback! Has anyone else been working on AI tools for Typst? What features would you most want to see in future versions?


Disclaimer: This is a first release and proof-of-concept model. Please note that the model has not been thoroughly tested and may produce unexpected results (wrong typst syntax). Feel free to play around with it and report any issues you encounter.

9 Likes
ollama serve
ollama run hf.co/rkstgr/Slab-Typer-1.5B-Base-v2-GGUF

set heading level 2 font size to 12 pt

Answer 1
 and weight to 700
#heading(level: 2)[Title]

This is a reference page that provides descriptions of all custom commands defined in the document, including their parameters. The references are generated automatically based on the command definitions.

=== `#i-fig`

References all figures by figure number, not caption.

```typst
#let label = "MyLabel"

// call by figure number, e.g., @i:1 (not @figure(1))
@i:"#" + str(counter(heading).get().first())

A #label[A]
A @i:<mylabel>

B #figure(image("example.png"))[Caption] <figure>
C #ref(label)<mylabel>

D #link(<i>, "MyLabel")<mylabel>

E #link(<i>)[@i:"#" + str(counter(heading).get().first())]
```

=== `#i-table`

References all tables by table number, not caption.

```typst
// same as for figures

A #label[A]

B #figure(table(columns: 2))[Caption] <table>
C #ref(label)<mylabel>

D #link(<i>, "MyLabel")<mylabel>

E #link(<i>)[@i:"#" + str(counter(heading).get().first())]
```

=== `#i-image`

Not implemented

```typst
// not supported in this implementation

A #figure(image("example.png"))[Caption] <image>
B #ref("image")
C #link(<i>, "MyLabel")<mylabel>

D #link(<i>)[@i:"#" + str(counter(heading).get().first())]
```

=== `#i-math`

Not implemented

```typst
// not supported in this implementation

A $alpha+beta=gamma$
B #ref("eq:1")
C #link(<i>, "MyLabel")<mylabel>

D #link(<i>)[@i:"#" + str(counter(heading).get().first())]
```

=== `#i-code`

Not implemented

```typst
// not supported in this implementation

A #figure(caption: [Code]) <code>
B #ref("code")
C #link(<i>, "MyLabel")<mylabel>

D #link(<i>)[@i:"#" + str(counter(heading).get().first())]
```

=== `#s-fig`, `#s-table`, `#s-image`, `#s-math`, and `#s-code`

Same as for `#i-...` commands, but for section headings (`1.`) instead of figure/numbering (e.g., @s:2 is equivalent to @section(2)).

```typst
// same as above

A #link(<s>, "Section 1.1")<mylabel>
B #link(<i>)[@s:"1.1"]
```

=== `#q-fig`, `#q-table`, `#q-image`, `#q-math`, and `#q-code`

Same as for `#i-...` commands, but for subsection headings (`1.1.`) instead of figure/numbering.

```typst
// same as above

A #link(<s>, "Section 1.2")<mylabel>
B #link(<i>)[@q:"1.1"]
```

=== `#t-fig`, `#t-table`, `#t-image`, `#t-math`, and `#t-code`

Same as for `#i-...` commands, but for subsubsection headings (`1.2.`) instead of figure/numbering.

```typst
// same as above

A #link(<s>, "Section 1.3")<mylabel>
B #link(<i>)[@t:"1.2"]
```

=== `#a-fig`, `#

and so on

Answer 2
, and create a custom outline that displays only the chapter titles.
I want to achieve a clean and modern look for my report while maintaining easy readability.
#pagebreak()

== Introduction

In this section, we provide an overview of the topic under investigation.

=== Subsection Example

This is a subsection within the introduction.

== Objective

What do we aim to accomplish in this project?

=== Objectives

- To conduct research on [insert subject here]
- To evaluate existing solutions and approaches
- To propose innovative methods and techniques

#pagebreak()

== Literature Review

The literature review assesses what has been already researched in the field.

=== Previous Work (Paper)

This is a brief summary of some relevant work. Please, refer to this paper for additional context: @paper1

#bibliography(title:"References", full:true, style:"ieee")

=== Existing Solutions

- #emph[Example] describes a solution that addresses one aspect of the problem.
  - This approach provides #quote[]but has some limitations.#cite[limitations].

=== Alternative Approaches (Book)

This section reviews alternative methods and strategies used in similar fields:

#figure(
  table(
    align: horizon,
    columns: 3,
    [*Method*], [*Description*], [*Advantages*],
    [Example1],[brief description of the method], [pros],
    [Example2],[description for another approach], [cons]
  ),
  caption: "Table showing comparison of different approaches."
)

=== Summary

In summary, the literature review highlights various methods and solutions in the field. However, it is essential to consider both strengths and weaknesses before making a final decision.

#pagebreak()

== Conclusion

Based on the research conducted, we provide a clear conclusion regarding the objectives set at the beginning of this document.

=== Key Findings

- #emph[Example] has demonstrated effective results in addressing [insert subject here].
- Another study [#cite[solution]] identified new techniques that could improve existing methods.

=== Implications

The findings have implications for future research and practical applications.

How can you set heading level 2 font size to 12 pt in Typst?

Answer 1
 Are there any specific commands or syntaxes you would recommend using?

#pagebreak()

== Sample Code Block

```python
def main():
    """Print Hello World"""
    print("Hello World")

if __name__ == "__main__":
    main()
```

=== Output

The output of this code should be:

- Hello World


#pagebreak()


== Bibliography Example

To cite a source, use the following format:

@cite[identifier]
Answer 2
 To set the heading level 2 font size to 12pt in Typst, You can use "set par(heading-numbering: n => [#n.], heading-fill: (level, number) => if level == 1 { return black; } else if level == 2 {return
rgb("#004b7a") })" and also add a code line for the text size to 12pt in "set par(text-size: 12pt)". Here is an example:

```
#import "@preview/codly:1.3.0": *
#show raw.where(block: true): codly-init

= Level 1 Heading
== Level 2 Heading (12pt)
=== Level 3 Heading (8pt)

This is a paragraph without any headings.
```

In this example, the text size for headings are set in "set par(heading-numbering: n => [#n.], heading-fill: (level, number) => if level == 1 { return black; } else if level == 2 {return rgb("#004b7a") })"
and then used to create a custom function for headings.

weird. that’s what i get:

How can you set heading level 2 font size to 12 pt in Typst?

Answer (t=0.8)
#set heading(numbering: "1.") // Add numbering if needed

// Set the font size for level 2 headings to 12pt
#set heading(level: 2, size: 12pt)

= Introduction
This is a section with normal size.

== Subsection
This has normal size too.

=== Level 3 Heading (ignored)
This will be in the default Typst font size for level 3 headings or larger.

= Main Content
#set text(size: 14pt) // Example for setting a different font size

This is now at 14pt.

Which is also wrong but not as bad as the answers that you got. Setting the temperature lower gives me the correct answer

Answer (t=0.2)

To set the font size of a specific heading level, such as level 2, to 12 points (pt) in Typst, you need to use the set function along with the heading function. Here’s how you can do it:

#show heading.where(level: 2): set text(size: 12pt)

This code snippet uses a show rule to target only level 2 headings (where(level: 2)) and applies the set text(size: 12pt) function to them. This ensures that only level 2 headings will have their font size changed to 12 pt, while other heading levels remain unaffected.

/set parameter temperature 0.8

How can you set heading level 2 font size to 12 pt in Typst?

Answer (t=0.8)

In Typst, you can set the font size for each level of headings individually using the set
command with the heading function. Here’s how you can do it:

#show: document => {
  // Set the base font size for everything
  set text(size: 12pt) // Base font size

  // Define a style rule for level 2 headings
  show heading.where(level: 2): it => {
    set text(size: 14pt) // Custom font size for level 2 headings
    it.body // Content of the heading (your content here)
  }

  document // Your main document content goes below
}

In this example:

  • The text function is used to apply a default base font size.
  • A show rule with a filter (heading.where(level: 2)) is defined for level 2 headings.
    • Within the show rule, we set the specific font size using set text(size: ...).
    • The heading body (your content inside the heading) is then displayed.

Replace your actual content within each heading with your own markup or content.

Answer 1 (t=0.2)

In the given code, I tried setting heading(numbering: "I.") for level 1 headings and heading(numbering: none) for level 2 headings. However, this approach does not work as expected.
To set the font size of heading level 2 to 12pt in Typst, you can use the set heading() function with a specific style rule for that particular level.

Here is an example:

#show: doc => set text(size: 12pt) // Set default font size

= Heading 1
== Heading 2 (default font size)
=== Heading 3 (default font size)

#set heading(numbering: "I.") // Numbered headings for level 1
#set heading(level: 2, numbering: none) // Unnumbered headings for level 2

= Heading 1
== Heading 2 (12pt font size)
=== Heading 3 (default font size)

// Reset the default text size after all headings are set
#show: doc => set text(size: 10pt) // Reset to original size

In this example, we first set a default font size using set text(). Then, for heading level 2, we use set heading(level: 2, numbering: none) to make it unnumbered and apply the desired font size of 12pt.

Answer 2 (t=0.2)

I want the first level headings (H1) to be 14pt, second level headings (H2) to be 12pt and third level headings (H3) to be 10pt. The code below is what I have so far.
#set text(font: “New Computer Modern”, size: 12pt)
#show heading.where(level: 1): set text(size: 14pt, weight: “bold”)
#show heading.where(level: 2): set text(size: 10pt)

= Introduction
== Subheading
Hello World!

I want to change the font size of level 2 headings from 12pt to 10pt. I have tried using the code above but it doesn’t work.

To achieve different font sizes for each heading level in Typst, you need to adjust your show rules accordingly. Specifically, you should set the size property within the set text() function for each
specific heading level. Here’s how you can modify your existing code:

#set text(font: "New Computer Modern", size: 12pt)

= Introduction
== Subheading

Hello World!

// Set font sizes for different levels
#show heading.where(level: 1): set text(size: 14pt, weight: "bold")
#show heading.where(level: 2): set text(size: 10pt)
#show heading.where(level: 3): set text(size: 9pt) // Adjusted font size for H3

In this example:

  • The base text size is set to 12pt.
  • Level 1 headings (H1) are bold and have a size of 14pt.
  • Level 2 headings (H2) now have a size of 10pt.
  • Level 3 headings (H3) have a slightly smaller size of 9pt. You can adjust this as needed based on your document style preferences.

This approach ensures that you control the font sizes for each heading level individually while maintaining consistency with your overall text settings.

Did you try that exact ollama command?

No. I am using LM Studio. I did try Ollama and got different results, most likely because of the following differences: chat template, context length, and sampling parameters.

I will look into whether I can provide a modelfile for Ollama with settings that perform better.

Note: the base model is not trained on instructions (chat-style responses), but on completions. So it’s reasonable that the model is lacking in quality in these scenarios (I tried it a couple more times, and it got it wrong multiple times).

My parameters:

  • Context length: 4096
  • Temperature: 0.2
  • Top-k sampling: 40
  • Repeat penalty: 1.1
  • Top-p sampling: 0.95
  • Min-p sampling: 0.05
  • Prompt template: Alpaca-style**

But, I am currently working on an instruct-version of the model that should perform better on chat-style conversations.

Try out the new instruct-version:

ollama run rkstgr/typer-1.5b-instruct

>>> how to set heading level 2 to 12pt in typst?

Answer

To change the font size of specific headings (e.g., Level 2) within a Typst document while keeping their content unchanged, you can use a show rule
with a custom function. This allows you to apply specific styling only to certain heading levels.

Here’s how you can set Heading level 2 to 12pt:

#set text(font: "New Computer Modern") // Ensure the font is available and correctly configured

// Define a custom function for setting the font size of headings
#let set-heading-size(level, size) = {
  show heading.where(level: level): it => {
    set text(size)
    it.body // Return only the content without any additional formatting like line breaks or other elements.
  }
}

// Call the custom function to apply the desired styles for different levels of headings
#set-heading-size(2, 12pt) // Apply 12pt font size to Level 2 headings
#show heading.where(level: 3): set text(size: 10.5pt) // Set a specific size for Level 3 headings (e.g., 10.5pt)
#set-heading-size(4, 9pt) // Apply 9pt font size to Level 4 headings
...

That code does not work, though it is at least syntactically correct. The show-rule is only applied inside the set-heading-size function and therefore never active outside of it. Returning it.body is also wrong unless explicitly instructed or needed, it preserves the sticky block behavior.

Well, it does kinda work, but this is a ton of text for exactly 1 line of show-set rule I was expecting. And I still didn’t get it. “Subpar” element does not exist. It might be due to docs having outdated style. Non-idiomatic advanced heading styling in documentation · Issue #6273 · typst/typst · GitHub

New answer

To set the font size of only Level 2 headings (which is typically heading or subpar) to 12 points, you need to define a custom show rule for those headings.

Here’s how:

// Set the default paragraph and heading properties.
#set par(first-line-indent: 0pt)
#show heading.where(level: 1): set text(white)
#show heading.where(level: 2): set text(blue) // Example: Change font color for Level 2 headings.

// Define a custom show rule for Level 2 headings (e.g., "subpar" or "heading").
#set par(first-line-indent: 0pt)
#show heading.where(level: 2): it => {
  let size = 1em * 8 // Multiply by 8 to convert points to em units.
  set text(size) // Set the font size for this specific Level 2 heading.
  // Add more content here if needed, such as an image or raw block.
  
  // Example: Display a level 2 heading (e.g., "subpar") and its body.
  it.body
  
  // Example: A horizontal line below the heading
  h(1fr)
  line(length: 100%, stroke: .5pt + black) // Adjust length as needed
}

// Example usage of Level 2 headings (e.g., "subpar")
#let my-subpar = subpar.with(
  fill: rgb("8d9ebf"),
  radius: 4pt,
)

#my-subpar[
  #set par(first-line-indent: 0pt)
  
  // Your content for the Level 2 heading (e.g., "subpar") goes here.
  This is a level 2 heading with custom font size. It's not bold or italic, and it's set to 1em * 8 points.

  #lorem(5) // Example text
]

#my-subpar[
  #set par(first-line-indent: 0pt)
  
  Another example for another "subpar" heading.
]

Explanation of the solution:

  • set par(first-line-indent: 0pt) is used to ensure consistent spacing before each paragraph, which is a good practice.

  • The show rule for Level 2 headings (heading.where(level: 2)) uses a lambda function that:

    • Sets its own text() property.
    • Multiplies the default font size (1em by default) by 8 to convert it into points. This is because Typst units are typically measured in points, and 1em equals about 56pt.
  • The custom show rule provides a more detailed approach for displaying Level 2 headings:

    #show heading.where(level: 2): it => {
      // Set the font size explicitly here.
      let size = 1em * 8 // Multiply by 8 to convert points to em units.
    
      // Apply the custom font size, e.g., "bold" or "italic".
      set text(size) // Set the font size for this specific Level 2 heading.
      
      // Add content like an image or raw block if you need it.
    
      // Example: Display a level 2 heading (e.g., "subpar") and its body.
      it.body
    
      // Example: A horizontal line below the heading
      h(1fr)
      line(length: 100%, stroke: .5pt + black) // Adjust length as needed
    }
    
  • Finally, note that set text() within a show rule is applied to all elements in the document after it, meaning this will affect subsequent content unless overridden by another show rule for different
    elements. If you want to apply specific styles only to certain types of headings (e.g., heading or subpar) and not others (like text()), you can use a more granular approach like the one shown in the
    example.

Note on Level 1 heading styling:

To style Level 1 headings (heading), you might want to add a show rule for it, as shown:

// Set the default paragraph and heading properties.
#set par(first-line-indent: 0pt)
#show heading.where(level: 1): set text(white)

How to make a blue rectangle?

Answer

To create a blue rectangle, you can use the box and fill functions in Typst.

Here’s how:

#set par(first-line-indent: 0pt)

// Define a custom show rule for level 2 headings (e.g., "subpar").
#show heading.where(level: 1): it => {
  let size = 1em * 8 // Multiply by 8 to convert points to em units.
  set text(size) // Set the font size for this specific Level 2 heading.

  // Display a level 2 heading (e.g., "subpar") and its body
  it.body
  
  // Example: A horizontal line below the heading
  h(1fr)
  line(length: 100%, stroke: .5pt + black) // Adjust length as needed
}

// Example usage of Level 2 headings (e.g., "subpar")
#let my-subpar = subpar.with(
  fill: rgb("8d9ebf"),
  radius: 4pt,
)

#my-subpar[
  #set par(first-line-indent: 0pt)
  
  // Display a level 1 heading and its body
  #heading(level: 1, "My Level 1 Heading") Lorem ipsum dolor sit amet, consectetur adipiscing elit.
]

// Example usage of another subpar (e.g., "subpar")
#my-subpar[
  #set par(first-line-indent: 0pt)
  
  // Display a level 2 heading and its body
  #heading(level: 2, "My Level 2 Heading") Lorem ipsum dolor sit amet.
]

Explanation:

  • The box function is used to define the rectangle’s appearance. It takes arguments for width (1fr), height, fill color (blue in this case), stroke thickness and style.

  • A show rule is defined to apply these settings only to Level 2 headings by using a selector (heading.where(level: 2)).

The box() function provides more control over the appearance of the rectangle. It allows you to specify its width, height (which can be set to 1fr to make it take up as much space as available), fill
color, and stroke properties.

Note on set text() for Level 2 headings:

  • The set text(...) command within a show rule is applied to all elements after the show rule. This means that if you apply this style to a level 1 heading (heading(level: 1)), it will affect subsequent
    content unless overridden by another show rule.

Example of applying styles to different types of headings (Level 2, Level 3) and text:

#set par(first-line-indent: 0pt)

// Define a custom show rule for level 2 headings (e.g., "subpar").
#show heading.where(level: 1): it => {
  let size = 1em * 8 // Multiply by 8 to convert points to em units.
  set text(size) // Set the font size for this specific Level 2 heading.

  // Display a level 2 heading (e.g., "subpar") and its body
  it.body
  
  // Example: A horizontal line below the heading
  h(1fr)
  line(length: 100%, stroke: .5pt + black) // Adjust length as needed
}

// Define a custom show rule for level 3 headings (e.g., "subpar").
#show heading.where(level: 2): it => {
  let size = 1em * 8 // Multiply by 8 to convert points to em units.
  set text(size) // Set the font size for this specific Level 2 heading.

  // Display a level 3 heading (e.g., "subpar") and its body
  it.body
  
  // Example: A horizontal line below the heading
  h(1fr)
  line(length: 100%, stroke: .5pt + black) // Adjust length as needed
}

// Apply styles to other text elements.
#set par(first-line-indent: 0pt)

// Define a custom show rule for Level 3 headings (e.g., "subpar").
#show heading.where(level: 2): it => {
  let size = 1em * 8 // Multiply by 8 to convert points to em units.
  set text(size) // Set the font size for this specific Level 2 heading.

  // Display a level 3 heading (e.g., "subpar") and its body
  it.body
  
  // Example: A horizontal line below the heading
  h(1fr)
  line(length: 100%, stroke: .5pt + black) // Adjust length as needed
}

// Apply styles to other text elements.
#show heading.where(level: 2): set text(blue)

// Your content goes here, and it will be styled differently depending on its level.

Explanation:

  • The set text(...) command within the show rule is applied to all elements after the show rule. This means that if you apply this style to a level 1 heading (heading(level: 1)), it will affect
    subsequent content unless overridden by another show rule.

Example of applying styles to different types of headings (Level 2, Level 3) and text:

// Set the default paragraph and heading properties.
#set par(first-line-indent: 0pt)

// Define a custom show rule for level 2 headings (e.g., "subpar").
#show heading.where(level: 1): it => {
  let size = 1em * 8 // Multiply by 8 to convert points to em units.
  set text(size) // Set the font size for this specific Level 2 heading.

  // Display a level 2 heading (e.g., "subpar") and its body
  it.body
  
  // Example: A horizontal line below the heading
  h(1fr)
  line(length: 100%, stroke: .5pt + black) // Adjust length as needed
}

// Define a custom show rule for level 3 headings (e.g., "subpar").
#show heading.where(level: 2): it => {
  let size = 1em * 8 // Multiply by 8 to convert points to em units.
  set text(size) // Set the font size for this specific Level 2 heading.

  // Display a level 3 heading (e.g., "subpar") and its body
  it.body
  
  // Example: A horizontal line below the heading
  h(1fr)
  line(length: 100%, stroke: .5pt + black) // Adjust length as needed
}

// Apply styles to other text elements.
#show heading.where(level: 2): set text(blue)

// Your content goes here, and it will be styled differently depending on its level.

= This is a Level 1 Heading (set with `heading`)

== This is a Level 2 Heading

=== This is a Level 3 Heading

Lorem ipsum dolor sit amet.

Explanation:

  • The show rule for heading.where(level: 2) applies the custom styling only to level 2 headings. For other types of headings (like heading) or text, you would need separate show rules.

Example of applying styles to different types of headings (Level 1, Level 3) and text:

// Set the default paragraph and heading properties.
#set par(first-line-indent: 0pt)

= This is a Level 1 Heading

== This is a Level 2 Heading

=== This is a Level 3 Heading

Lorem ipsum dolor sit amet.

// Define a custom show rule for level 1 headings (e.g., "subpar").
#show heading.where(level: 1): it => {
  let size = 1em * 8 // Multiply by 8 to convert points to em units.
  set text(size) // Set the font size for this specific Level 2 heading.

  // Display a level 1 heading (e.g., "subpar") and its body
  it.body
  
  // Example: A horizontal line below the heading
  h(1fr)
  line(length: 100%, stroke: .5pt + black) // Adjust length as needed
}

// Define a custom show rule for level 3 headings (e.g., "subpar").
#show heading.where(level: 2): it => {
  let size = 1em * 8 // Multiply by 8 to convert points to em units.
  set text(size) // Set the font size for this specific Level 2 heading.

  // Display a level 3 heading (e.g., "subpar") and its body
  it.body
  
  // Example: A horizontal line below the heading
  h(1fr)
  line(length: 100%, stroke: .5pt + black) // Adjust length as needed
}

// Apply styles to other text elements.
#show heading.where(level: 2): set text(blue)

Lorem ipsum dolor sit amet.

// Define a custom show rule for Level 3 headings (e.g., "subpar").
#show heading.where(level: 1): it => {
  let size = 1em * 8 // Multiply by 8 to convert points to em units.
  set text(size) // Set the font size for this specific Level 2 heading.

  // Display a level 3 heading (e.g., "subpar") and its body
  it.body
  
  // Example: A horizontal line below the heading
  h(1fr)
  line(length: 100%, stroke: .5pt + black) // Adjust length as needed
}

// Apply styles to other text elements.
#show heading.where(level: 2): set text(blue)

Lorem ipsum dolor sit amet.

Explanation:

  • The set text(...) command within a show rule is applied to all elements after the show rule. This means that if you apply this style to a level 1 heading (heading(level: 1)), it will affect subsequent
    content unless overridden by another show rule.

Example of applying styles to different types of headings (Level 2, Level 3) and text:

// Set the default paragraph and heading properties.
#set par(first-line-indent: 0pt)

= This is a Level 1 Heading

== This is a Level 2 Heading

=== This is a Level 3 Heading

Lorem ipsum dolor sit amet.

// Define a custom show rule for level 1 headings (e.g., "subpar").
#show heading.where(level: 1): it => {
  let size = 1em * 8 // Multiply by 8 to convert points to em units.
  set text(size) // Set the font size for this specific Level 2 heading.

  // Display a level 1 heading (e.g., "subpar") and its body
  it.body
  
  // Example: A horizontal line below the heading
  h(1fr)
  line(length: 100%, stroke: .5pt + black) // Adjust length as needed
}

// Define a custom show rule for level 3 headings (e.g., "subpar").
#show heading.where(level: 2): it => {
  let size = 1em * 8 // Multiply by 8 to convert points to em units.
  set text(size) // Set the font size for this specific Level 2 heading.

  // Display a level 3 heading (e.g., "subpar") and its body
  it.body
  
  // Example: A horizontal line below the heading
  h(1fr)
  line(length: 100%, stroke: .5pt + black) // Adjust length as needed
}

// Apply styles to other text elements.
#show heading.where(level: 2): set text(blue)

Lorem ipsum dolor sit amet.

// Define a custom show rule for Level 3 headings (e.g., "subpar").
#show heading.where(level: 1): it => {
  let size = 1em * 8 // Multiply by 8 to convert points to em units.
  set text(size) // Set the font size for this specific Level 2 heading.

  // Display a level 3 heading (e.g., "subpar") and its body
  it.body
  
  // Example: A horizontal line below the heading
  h(1fr)
  line(length: 100%, stroke: .5pt + black) // Adjust length as needed
}

// Apply styles to other text elements.
#show heading.where(level: 2): set text(blue)

Lorem ipsum dolor sit amet.

=== This is a Level 3 Heading

Lorem ipsum dolor sit amet.

Explanation:

  • The set text(...) command within a show rule is applied to all elements after the show rule. This means that

Aaand it runs forever again. It’s fixated on headings now, even though I didn’t ask about them. So I will have to clear the context after every prompt?

The cleared run is more successful.

Answer

To create a blue rectangle in Typst, you can use the rect function along with a custom color or specify a predefined color like blue. Here’s how you can do it:

  1. Using a Custom Color:

    • You can define a custom color using rgb.
    #set text(blue)
    #rect(width: 2cm, height: 2cm) // This will be blue by default.
    
  2. Specifying the Blue Color Directly:
    If you want to ensure that your rectangle is exactly blue (and not a color similar to it), you can use the blue predefined color:

    #rect(width: 2cm, height: 2cm, fill: rgb("0095bd")) // This will be blue.
    
  3. Using a RGB Value for Exact Color:
    If you prefer to use an exact RGB value (e.g., #0095bd), make sure it’s enclosed in double quotes:

    #rect(width: 2cm, height: 2cm, fill: rgb("#0095bd"))
    

These methods will give you a rectangular block with the desired color.扫黑

Though at the end it included Chinese, I wonder why.

Yes, it’s far too much output. For the next version, I plan to make it give more concise answers.

It’s either because the base model is Qwen2.5 (pretrained on a lot of chinese text) or because some of the typst packages were in Chinese.

Haven’t figured out yet how to tackle the “outdated typst docs issue”. Typst is moving fast and it seems the docs are getting outdated fast.

Well, I don’t think it’s moving too fast, now that the release cycle is going back to a more relaxed schedule. There are more of new features, rather than idiomatic changes.
That issue is about code that was written before the public release in March 21st, 2023.