Skip to content

Commit f82973f

Browse files
bugfix: translate synonym and dashed font weights
from css to typst fixes #11726 also, we were previously failing if brand.typography.headings.weight was a string because it wouldn't be quoted so use a raw typst inline as with color
1 parent 03face3 commit f82973f

File tree

3 files changed

+99
-10
lines changed

3 files changed

+99
-10
lines changed

src/resources/filters/modules/typst_css.lua

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,47 @@ local function quote(s)
593593
return '"' .. s .. '"'
594594
end
595595

596+
local same_weights = {
597+
'thin',
598+
'light',
599+
'normal',
600+
'regular',
601+
'medium',
602+
'bold',
603+
'black',
604+
}
605+
606+
local weight_synonyms = {
607+
['ultra-light'] = 'extra-light',
608+
['demi-bold'] = 'semi-bold',
609+
['ultra-bold'] = 'extra-bold',
610+
}
611+
612+
local dashed_weights = {
613+
'extra-light',
614+
'ultra-light',
615+
'semi-bold',
616+
'demi-bold',
617+
'extra-bold',
618+
'ultra-bold',
619+
}
620+
621+
local function translate_font_weight(w, warnings)
622+
if not w then return nil end
623+
local num = tonumber(w)
624+
if num and 1 <= num and num <= 1000 then
625+
return num
626+
elseif tcontains(same_weights, w) then
627+
return w
628+
elseif tcontains(dashed_weights, w) then
629+
w = weight_synonyms[w] or w
630+
return w:gsub('-', '')
631+
else
632+
output_warning(warnings, 'invalid font weight ' .. tostring(w))
633+
return nil
634+
end
635+
end
636+
596637
local function translate_border_style(v, _warnings)
597638
local dash
598639
if v == 'none' then
@@ -718,6 +759,7 @@ return {
718759
translate_border_width = translate_border_width,
719760
translate_border_style = translate_border_style,
720761
translate_border_color = translate_border_color,
762+
translate_font_weight = translate_font_weight,
721763
consume_width = consume_width,
722764
consume_style = consume_style,
723765
consume_color = consume_color

src/resources/filters/quarto-post/typst-brand-yaml.lua

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ function render_typst_brand_yaml()
5151
end
5252
end
5353

54+
local function quote_string(value)
55+
if type(value) ~= 'string' then return value end
56+
return '"' .. value .. '"'
57+
end
58+
5459
return {
5560
Pandoc = function(pandoc)
5661
local brand = param('brand')
@@ -82,10 +87,6 @@ function render_typst_brand_yaml()
8287
local decl = '// theme colors at opacity ' .. BACKGROUND_OPACITY .. '\n#let brand-color-background = ' .. to_typst_dict_indent(themebk)
8388
quarto.doc.include_text('in-header', decl)
8489
end
85-
local function quote_string(value)
86-
if type(value) ~= 'string' then return value end
87-
return '"' .. value .. '"'
88-
end
8990
local function conditional_entry(key, value, quote_strings)
9091
if quote_strings == null then quote_strings = true end
9192
if not value then return '' end
@@ -98,7 +99,7 @@ function render_typst_brand_yaml()
9899
quarto.doc.include_text('in-header', table.concat({
99100
'#set text(',
100101
-- '#show par: set text(', overrules #show heading!
101-
conditional_entry('weight', base.weight),
102+
conditional_entry('weight', _quarto.modules.typst.css.translate_font_weight(base.weight)),
102103
')'
103104
}))
104105
end
@@ -117,7 +118,7 @@ function render_typst_brand_yaml()
117118
quarto.doc.include_text('in-header', table.concat({
118119
'#show heading: set text(',
119120
conditional_entry('font', headings.family),
120-
conditional_entry('weight', headings.weight),
121+
conditional_entry('weight', _quarto.modules.typst.css.translate_font_weight(headings.weight)),
121122
conditional_entry('style', headings.style),
122123
conditional_entry('fill', headings.color, false),
123124
')'
@@ -138,7 +139,7 @@ function render_typst_brand_yaml()
138139
quarto.doc.include_text('in-header', table.concat({
139140
'#show raw.where(block: false): set text(',
140141
conditional_entry('font', monospaceInline.family),
141-
conditional_entry('weight', monospaceInline.weight),
142+
conditional_entry('weight', _quarto.modules.typst.css.translate_font_weight(monospaceInline.weight)),
142143
conditional_entry('size', monospaceInline.size, false),
143144
conditional_entry('fill', monospaceInline.color, false),
144145
')'
@@ -157,7 +158,7 @@ function render_typst_brand_yaml()
157158
quarto.doc.include_text('in-header', table.concat({
158159
'#show raw.where(block: true): set text(',
159160
conditional_entry('font', monospaceBlock.family),
160-
conditional_entry('weight', monospaceBlock.weight),
161+
conditional_entry('weight', _quarto.modules.typst.css.translate_font_weight(monospaceBlock.weight)),
161162
conditional_entry('size', monospaceBlock.size, false),
162163
conditional_entry('fill', monospaceBlock.color, false),
163164
')'
@@ -187,7 +188,7 @@ function render_typst_brand_yaml()
187188
link = link or {}
188189
quarto.doc.include_text('in-header', table.concat({
189190
'#show link: set text(',
190-
conditional_entry('weight', link.weight),
191+
conditional_entry('weight', _quarto.modules.typst.css.translate_font_weight(link.weight)),
191192
conditional_entry('fill', link.color or primaryColor, false),
192193
')'
193194
}))
@@ -312,9 +313,11 @@ function render_typst_brand_yaml()
312313
headings = headings or {}
313314
local color = headings.color or foregroundColor
314315
color = color and pandoc.RawInline('typst', color)
316+
local weight = _quarto.modules.typst.css.translate_font_weight(headings.weight or base.weight)
317+
weight = weight and pandoc.RawInline('typst', tostring(quote_string(weight)))
315318
meta.brand.typography.headings = {
316319
family = headings.family or base.family,
317-
weight = headings.weight or base.weight,
320+
weight = weight,
318321
style = headings.style or base.style,
319322
decoration = headings.decoration or base.decoration,
320323
color = color,
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
---
2+
title: "Dashed font weights"
3+
format:
4+
typst:
5+
keep-typ: true
6+
brand:
7+
typography:
8+
base:
9+
weight: ultra-light
10+
headings:
11+
weight: ultra-bold
12+
monospace-inline:
13+
weight: light
14+
monospace-block:
15+
weight: semi-bold
16+
_quarto:
17+
tests:
18+
typst:
19+
ensureTypstFileRegexMatches:
20+
-
21+
- '#set text\(weight: "extralight", \)'
22+
- 'heading-weight: "extrabold",'
23+
- '#show raw.where\(block: false\): set text\(weight: "light", \)'
24+
- '#show raw.where\(block: true\): set text\(weight: "semibold", \)'
25+
- []
26+
ensurePdfRegexMatches:
27+
-
28+
- 'base is extralight'
29+
- 'heading-2 is extrabold'
30+
- []
31+
32+
---
33+
34+
## heading-2 is `#context text.weight`{=typst}
35+
36+
```
37+
def fact n:
38+
if n == 1:
39+
return 1
40+
return n * fact(n-1)
41+
```
42+
43+
base is `#context text.weight`{=typst} \
44+
{{< lipsum 1 >}}

0 commit comments

Comments
 (0)