|
32 | 32 |
|
33 | 33 | /// Helper for custom footnote symbols |
34 | 34 | let titlenotenumbering(i) = { |
35 | | - if i < 6 { ("*", "#", "§", "¶", "‡").at(i - 1) + " " } |
36 | | - else { (i - 4)*"*" + " " } |
| 35 | + if i < 6 { ("*", "#", "§", "¶", "‡").at(i - 1)} |
| 36 | + else { (i - 4)*"*" } |
37 | 37 | } |
38 | 38 |
|
39 | 39 | /// Capitalize all characters in the text, e.g. "THIS IS AN ALLCAPS HEADING" |
|
71 | 71 |
|
72 | 72 | // layout |
73 | 73 |
|
74 | | - set page(..{ |
| 74 | + set page(columns: 2, ..{ |
75 | 75 | if paper-size == "a4" { |
76 | 76 | (paper: "a4", margin: (top: 37mm, bottom: 19mm, x: 20mm)) |
77 | 77 | } else if paper-size == "us-letter" { |
|
83 | 83 | }} |
84 | 84 | ) |
85 | 85 |
|
| 86 | + set columns(gutter: 0.2in) |
| 87 | + |
86 | 88 | set text( |
87 | 89 | font: "TeX Gyre Termes", |
88 | 90 | size: 10pt |
|
96 | 98 | ) |
97 | 99 |
|
98 | 100 |
|
99 | | - // TODO: footnotes should not span both columns, but be in left column only |
| 101 | + // Note: footnotes not working in parent scoped placement with two column mode. |
| 102 | + // See https://github.com/typst/typst/issues/1337#issuecomment-1565376701 |
| 103 | + // As a workaround, we handle footnotes in the title area manually. |
| 104 | + // An alternative is to not use place and use "show: columns.with(2, gutter: 0.2in)" after the title area instead of "page(columns: 2)", |
| 105 | + // but then footnotes span the full page and not just the left column. |
| 106 | + //let titlefootnote(text) = { footnote(numbering: titlenotenumbering, text) } |
| 107 | + let footnotes = state("titlefootnotes", (:)) |
| 108 | + let titlefootnote(text) = { |
| 109 | + footnotes.update(footnotes => { |
| 110 | + footnotes.insert(titlenotenumbering(footnotes.len()+1), text) |
| 111 | + footnotes |
| 112 | + }) |
| 113 | + h(0pt, weak: true) |
| 114 | + context{super(footnotes.get().keys().at(-1))} |
| 115 | + } |
| 116 | + |
100 | 117 | show footnote.entry: set align(left) |
101 | 118 | set footnote.entry( |
| 119 | + indent: 0em, |
102 | 120 | separator: [ |
103 | 121 | #set align(left) |
104 | | - #line(length: 20%, stroke: 0.5pt) |
| 122 | + #line(length: 40%, stroke: 0.5pt) |
105 | 123 | ] |
106 | 124 | ) |
107 | 125 |
|
108 | 126 |
|
| 127 | + place( |
| 128 | + top + center, |
| 129 | + scope: "parent", |
| 130 | + float: true, |
| 131 | + { |
| 132 | + |
| 133 | + |
| 134 | + /* |
| 135 | + * Title |
| 136 | + */ |
| 137 | + |
| 138 | + set align(center) |
| 139 | + text(size: 14pt, weight: "bold", [ |
| 140 | + #allcaps(title) |
| 141 | + #if funding != none { titlefootnote(funding) } |
| 142 | + ]) |
| 143 | + v(8pt) |
| 144 | + |
| 145 | + |
| 146 | + /* |
| 147 | + * Author list |
| 148 | + */ |
| 149 | + |
| 150 | + text(size: 12pt, { |
| 151 | + let also_at = (); |
| 152 | + for aff in authors.map(a => a.affiliation.at(0)).dedup() { |
| 153 | + for auth in authors.filter(a => a.affiliation.at(0) == aff) { |
| 154 | + // author name with superscripts |
| 155 | + auth.name |
| 156 | + for aff2 in auth.affiliation.slice(1) { |
| 157 | + if aff2 not in also_at { also_at += (aff2,) } |
| 158 | + super(str(also_at.len())) |
| 159 | + } |
| 160 | + if "email" in auth { titlefootnote(auth.email) } |
| 161 | + ", " |
| 162 | + } |
| 163 | + // primary affiliations |
| 164 | + affiliations.at(aff) + "\n" |
| 165 | + }; |
| 166 | + // secondary affiliations |
| 167 | + for i in range(also_at.len()) { |
| 168 | + super(str(i + 1)) |
| 169 | + "also at " + affiliations.at(also_at.at(i)) + "\n" |
| 170 | + }; |
| 171 | + }) |
| 172 | + v(1pt) |
109 | 173 |
|
110 | | - /* |
111 | | - * Title |
112 | | - */ |
113 | 174 |
|
114 | | - set align(center) |
115 | | - text(size: 14pt, weight: "bold", [ |
116 | | - #allcaps(title) |
117 | | - #if funding!=none{ |
118 | | - footnote(numbering: titlenotenumbering, funding) |
119 | 175 | } |
120 | | - ]) |
121 | | - v(8pt) |
122 | | - |
123 | | - |
| 176 | + ) |
124 | 177 |
|
125 | | - /* |
126 | | - * Author list |
127 | | - */ |
128 | 178 |
|
129 | | - text(size: 12pt, { |
130 | | - let also_at = (); |
131 | | - for aff in authors.map(a => a.affiliation.at(0)).dedup() { |
132 | | - for auth in authors.filter(a => a.affiliation.at(0) == aff) { |
133 | | - // author name with superscripts |
134 | | - auth.name |
135 | | - for aff2 in auth.affiliation.slice(1) { |
136 | | - if aff2 not in also_at { also_at += (aff2,) } |
137 | | - super(str(also_at.len())) |
138 | | - } |
139 | | - if "email" in auth {footnote(numbering: titlenotenumbering, auth.email)} |
140 | | - ", " |
141 | | - } |
142 | | - // primary affiliations |
143 | | - affiliations.at(aff) + "\n" |
144 | | - }; |
145 | | - // secondary affiliations |
146 | | - for i in range(also_at.len()) { |
147 | | - super(str(i + 1)) |
148 | | - "also at " + affiliations.at(also_at.at(i)) + "\n" |
149 | | - }; |
150 | | - }) |
151 | | - v(8pt) |
| 179 | + context{ |
| 180 | + for (symbol, text) in footnotes.get() { |
| 181 | + place(footnote(numbering: it => "", {super(symbol) + " " + text})) |
| 182 | + } |
| 183 | + } |
152 | 184 |
|
153 | 185 |
|
154 | 186 |
|
|
158 | 190 |
|
159 | 191 | // paragraph |
160 | 192 | set align(left) |
161 | | - show: columns.with(2, gutter: 0.2in) |
| 193 | + //show: columns.with(2, gutter: 0.2in) |
162 | 194 |
|
163 | 195 |
|
164 | 196 | // SECTION HEADINGS |
|
0 commit comments