Skip to content

Commit c5d6e82

Browse files
claude: Fix typst two-column layout to use set page(columns:)
Align Quarto's article() function with Pandoc's October 2024 fix (commit e01023c1f) for Typst 0.12+ two-column layout compatibility. Changes: - Replace columns(cols, doc) wrapper with plain doc return (page.typ already sets columns via set page(columns:)) - Change title block wrapper from block() to place(top, float: true, scope: "parent", clearance: 4mm) so title/authors/abstract span both columns - Remove unused cols parameter from typst-show.typ This fixes the error "page configuration is not allowed inside of containers" that occurred when using landscape sections with two-column layouts, since columns() creates a container that prevents set page() directives inside it. Add smoke tests for two-column typst layouts that verify: - Page columns set via set page(columns:) not columns() function - Title block wrapped with place(scope: "parent") for column spanning - Integration with landscape sections - Integration with table of contents - Full title block (title, subtitle, authors, abstract, thanks) Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent ee3f232 commit c5d6e82

File tree

6 files changed

+270
-7
lines changed

6 files changed

+270
-7
lines changed

src/resources/formats/typst/pandoc/quarto/typst-show.typ

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,5 @@ $if(toc-indent)$
9797
toc_indent: $toc-indent$,
9898
$endif$
9999
toc_depth: $toc-depth$,
100-
cols: $if(columns)$$columns$$else$1$endif$,
101100
doc,
102101
)

src/resources/formats/typst/pandoc/quarto/typst-template.typ

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
}
6262
}
6363

64-
block(below: 1em, width: 100%)[
64+
place(top, float: true, scope: "parent", clearance: 4mm)[
6565
#if title != none {
6666
align(center, block(inset: 2em)[
6767
#set par(leading: heading-line-height) if heading-line-height != none
@@ -125,11 +125,7 @@
125125
]
126126
}
127127

128-
if cols == 1 {
129-
doc
130-
} else {
131-
columns(cols, doc)
132-
}
128+
doc
133129
}
134130

135131
#set table(
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
---
2+
title: "Basic Two Column Layout"
3+
format:
4+
typst:
5+
columns: 2
6+
keep-typ: true
7+
_quarto:
8+
tests:
9+
typst:
10+
ensureTypstFileRegexMatches:
11+
- # Patterns that MUST be found
12+
# Page columns set via set page()
13+
- 'columns: 2,'
14+
# Title block wrapped with place(scope: "parent") for column spanning
15+
- 'place\(top, float: true, scope: "parent", clearance: 4mm\)'
16+
- # Patterns that must NOT be found
17+
# Should NOT have columns() function call wrapping doc at end of article()
18+
- 'columns\(cols, doc\)\n\}'
19+
---
20+
21+
## Introduction
22+
23+
This document tests the basic two-column layout in Typst. The title should span both columns, while the body content flows in two columns.
24+
25+
## First Section
26+
27+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.
28+
29+
## Second Section
30+
31+
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident.
32+
33+
## Third Section
34+
35+
Sunt in culpa qui officia deserunt mollit anim id est laborum. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium.
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
---
2+
title: "Two Column with Landscape Section"
3+
subtitle: "Testing Column Layout with Page Orientation Changes"
4+
author:
5+
- name: Alice Smith
6+
7+
affiliation: University A
8+
- name: Bob Jones
9+
10+
affiliation: University B
11+
date: "2025-01-08"
12+
abstract: "This document tests combining two-column layout with landscape page sections. The title block should span both columns, and content should flow correctly when switching between portrait and landscape orientations."
13+
format:
14+
typst:
15+
columns: 2
16+
keep-typ: true
17+
_quarto:
18+
tests:
19+
typst:
20+
ensureTypstFileRegexMatches:
21+
- # Patterns that MUST be found
22+
# Page columns set via set page()
23+
- 'columns: 2,'
24+
# Title block wrapped with place(scope: "parent") for column spanning
25+
- 'place\(top, float: true, scope: "parent", clearance: 4mm\)'
26+
# Landscape page start
27+
- '#set page\(flipped: true\)'
28+
# Landscape page end
29+
- '#set page\(flipped: false\)'
30+
- # Patterns that must NOT be found
31+
# Should NOT have columns() function call wrapping doc at end of article()
32+
- 'columns\(cols, doc\)\n\}'
33+
---
34+
35+
## Introduction
36+
37+
This document tests the interaction between two-column layout and landscape page sections. The title block above should span the full page width, while this body content flows in two columns.
38+
39+
## Portrait Section
40+
41+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
42+
43+
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
44+
45+
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.
46+
47+
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt.
48+
49+
::: {.landscape}
50+
51+
## Landscape Section
52+
53+
This section appears in landscape orientation. The two-column layout should persist but now on a rotated page, giving more horizontal space for wide content like tables.
54+
55+
### The Bug This Test Catches
56+
57+
When Quarto's `article()` function used `columns(cols, doc)` to wrap the document content (the old approach), landscape sections would crash with the error:
58+
59+
```
60+
error: page configuration is not allowed inside of containers
61+
┌─ two-column-landscape.typ:351:1
62+
63+
351 │ #set page(flipped: true)
64+
│ ^^^^^^^^^^^^^^^^^^^^^^^
65+
```
66+
67+
This happened because `columns()` creates a container, and Typst does not allow `set page()` directives inside containers. The landscape filter emits `#set page(flipped: true)` to rotate the page, which fails when nested inside a `columns()` call.
68+
69+
### The Fix
70+
71+
Pandoc fixed this in October 2024 (commit e01023c1f) for Typst 0.12+ compatibility. They changed from:
72+
73+
```typst
74+
if cols == 1 { doc } else { columns(cols, doc) }
75+
```
76+
77+
to using `set page(columns: cols)` at page level, which allows page configuration changes anywhere in the document. This approach also requires wrapping the title block with `place(top, float: true, scope: "parent")` so it spans both columns.
78+
79+
Quarto updated its copy of `template.typst` but missed updating the `article()` function in `typst-template.typ`, leaving the old `columns()` approach in place until this fix.
80+
81+
| Column A | Column B | Column C | Column D | Column E | Column F |
82+
|----------|----------|----------|----------|----------|----------|
83+
| Data 1 | Data 2 | Data 3 | Data 4 | Data 5 | Data 6 |
84+
| Data 7 | Data 8 | Data 9 | Data 10 | Data 11 | Data 12 |
85+
| Data 13 | Data 14 | Data 15 | Data 16 | Data 17 | Data 18 |
86+
87+
:::
88+
89+
## Back to Portrait
90+
91+
This section returns to portrait orientation with two columns. The content should continue flowing normally after the landscape section.
92+
93+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
94+
95+
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
96+
97+
## Conclusion
98+
99+
The document demonstrates that two-column layouts work correctly with landscape page sections when using `set page(columns:)` instead of the `columns()` function wrapper.
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
---
2+
title: "Two Column with Full Title Block"
3+
subtitle: "Testing Column-Spanning Title Elements"
4+
author:
5+
- name: Alice Smith
6+
7+
affiliation: University A
8+
- name: Bob Jones
9+
10+
affiliation: University B
11+
- name: Carol White
12+
13+
affiliation: University C
14+
date: "2025-01-08"
15+
keywords:
16+
- columns
17+
- typst
18+
- title-block
19+
thanks: "We thank the Quarto team for their work."
20+
abstract: "This document tests that the full title block (title, subtitle, authors, date, abstract, and thanks) correctly spans both columns in a two-column layout."
21+
format:
22+
typst:
23+
columns: 2
24+
keep-typ: true
25+
_quarto:
26+
tests:
27+
typst:
28+
ensureTypstFileRegexMatches:
29+
- # Patterns that MUST be found
30+
# Page columns set via set page()
31+
- 'columns: 2,'
32+
# Title block wrapped with place(scope: "parent") for column spanning
33+
- 'place\(top, float: true, scope: "parent", clearance: 4mm\)'
34+
# Title passed to article()
35+
- 'title: \[Two Column with Full Title Block\]'
36+
# Subtitle passed to article()
37+
- 'subtitle: \[Testing Column-Spanning Title Elements\]'
38+
# Thanks parameter passed to article()
39+
- 'thanks: \[We thank the Quarto team'
40+
# Abstract passed to article()
41+
- 'abstract: \[This document tests that the full title block'
42+
# Authors grid (3 authors = 3 columns)
43+
- 'columns: \(1fr,\) \* ncols'
44+
- # Patterns that must NOT be found
45+
# Should NOT have columns() function call wrapping doc at end of article()
46+
- 'columns\(cols, doc\)\n\}'
47+
---
48+
49+
## Introduction
50+
51+
This document verifies that all title block elements span both columns correctly in a two-column layout.
52+
53+
## First Section
54+
55+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
56+
57+
## Second Section
58+
59+
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
60+
61+
## Third Section
62+
63+
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
64+
65+
## Conclusion
66+
67+
The title block should appear above both columns, spanning the full page width.
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
---
2+
title: "Two Column with Table of Contents"
3+
abstract: "This document tests that the table of contents works correctly with a two-column layout."
4+
toc: true
5+
toc-title: "Contents"
6+
toc-depth: 2
7+
format:
8+
typst:
9+
columns: 2
10+
keep-typ: true
11+
_quarto:
12+
tests:
13+
typst:
14+
ensureTypstFileRegexMatches:
15+
- # Patterns that MUST be found
16+
# Page columns set via set page()
17+
- 'columns: 2,'
18+
# Title block wrapped with place(scope: "parent") for column spanning
19+
- 'place\(top, float: true, scope: "parent", clearance: 4mm\)'
20+
# TOC enabled in article() call
21+
- 'toc: true'
22+
# TOC title passed
23+
- 'toc_title: \[Contents\]'
24+
# TOC depth passed
25+
- 'toc_depth: 2'
26+
# Outline function call in article()
27+
- '#outline\('
28+
- # Patterns that must NOT be found
29+
# Should NOT have columns() function call wrapping doc at end of article()
30+
- 'columns\(cols, doc\)\n\}'
31+
---
32+
33+
## Introduction
34+
35+
This document tests that the table of contents is rendered correctly in a two-column layout.
36+
37+
## First Chapter
38+
39+
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
40+
41+
### First Subsection
42+
43+
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
44+
45+
### Second Subsection
46+
47+
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.
48+
49+
## Second Chapter
50+
51+
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore.
52+
53+
### Third Subsection
54+
55+
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia.
56+
57+
### Fourth Subsection
58+
59+
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium.
60+
61+
## Third Chapter
62+
63+
At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis.
64+
65+
## Conclusion
66+
67+
The TOC should appear after the title block and before the main content.

0 commit comments

Comments
 (0)