Skip to content

Commit 79d5012

Browse files
typst: generic font families / font stack aliases
this is complete except for choice of fonts for purposes of testing, this commit uses Roboto as the sans-serif font in order to implement this feature we need to ship a variable-width sans-serif font because Typst does not
1 parent b42543e commit 79d5012

File tree

7 files changed

+102
-25
lines changed

7 files changed

+102
-25
lines changed

dev-docs/feature-format-matrix/qmd-files/css-properties/font-family/document.qmd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ _quarto:
1919
typst:
2020
ensureTypstFileRegexMatches:
2121
-
22-
- '#set text\(font: \("Georgia", "serif"\)\); #table\('
22+
- '#set text\(font: \("Georgia", "Linux Libertine"\)\); #table\('
2323
- []
2424
---
2525

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
---
2+
format:
3+
html:
4+
quality: 1
5+
pdf:
6+
quality: na
7+
typst:
8+
quality: 2
9+
comment: "table only"
10+
include-in-header:
11+
text: |
12+
#set text(fallback: false)
13+
dashboard:
14+
quality: 1
15+
docx:
16+
quality: na
17+
pptx:
18+
quality: na
19+
keep-typ: true
20+
_quarto:
21+
tests:
22+
typst:
23+
ensureTypstFileRegexMatches:
24+
-
25+
- '#set text\(font: \("Linux Libertine"\)\); #table\('
26+
- '#show heading: set text\(font: "Roboto", \)'
27+
- '#show raw.where\(block: true\): set text\(font: "DejaVu Sans Mono", \)'
28+
- []
29+
ensurePdfRegexMatches:
30+
-
31+
- 'heading is roboto'
32+
- 'linux libertine'
33+
- 'code should appear in a monospace font'
34+
- []
35+
brand:
36+
typography:
37+
base: serif
38+
headings: sans-serif
39+
monospace: monospace
40+
---
41+
# heading is `#context text.font`{=typst}
42+
43+
base is `#context text.font`{=typst}
44+
45+
```{=html}
46+
<table style="font-family: serif;">
47+
<tr><td>A</td><td>B</td></tr>
48+
</table>
49+
```
50+
51+
```
52+
// This code should appear in a monospace font
53+
```
54+

src/command/render/pandoc.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { Document } from "../../core/deno-dom.ts";
2020
import { execProcess } from "../../core/process.ts";
2121
import { dirAndStem, normalizePath } from "../../core/path.ts";
2222
import { mergeConfigs } from "../../core/config.ts";
23+
import { quartoConfig } from "../../core/quarto.ts";
2324

2425
import {
2526
Format,
@@ -1513,6 +1514,9 @@ async function resolveExtras(
15131514
}
15141515
fontdirs.add(font_cache);
15151516
}
1517+
const srcDir = Deno.env.get("QUARTO_SRC_PATH") ||
1518+
join(quartoConfig.sharePath(), "../../src");
1519+
fontdirs.add(join(srcDir,'resources/fonts'));
15161520
let fontPaths = format.metadata[kFontPaths] as Array<string> || [];
15171521
if (typeof fontPaths === "string") {
15181522
fontPaths = [fontPaths];

src/resources/filters/modules/typst_css.lua

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,7 @@ local function output_length(length, warnings)
549549
if not csf then
550550
output_warning(warnings, 'unit ' .. length.unit .. ' is not supported in ' .. length.csslen )
551551
return nil
552-
end
552+
end
553553
return csf(length.value, length.unit, length.csslen, warnings)
554554
end
555555

@@ -593,6 +593,10 @@ local function quote(s)
593593
return '"' .. s .. '"'
594594
end
595595

596+
local function dequote(s)
597+
return s:gsub('^["\']', ''):gsub('["\']$', '')
598+
end
599+
596600
local same_weights = {
597601
'thin',
598602
'light',
@@ -634,6 +638,36 @@ local function translate_font_weight(w, warnings)
634638
end
635639
end
636640

641+
local generic_font_families = {
642+
['sans-serif'] = 'Roboto',
643+
serif = 'Linux Libertine', -- would be Libertinus Serif in Typst 0.12 but we also need to choose our own
644+
math = 'New Computer Modern Math',
645+
monospace = 'DejaVu Sans Mono',
646+
}
647+
648+
local gff_synonyms = {
649+
['ui-sans-serif'] = 'sans-serif',
650+
['system-ui'] = 'sans-serif',
651+
['ui-serif'] = 'serif',
652+
['ui-monospace'] = 'monospace'
653+
}
654+
655+
local function translate_font_family(ff)
656+
ff = gff_synonyms[ff] or ff
657+
return generic_font_families[ff] or ff
658+
end
659+
660+
local function translate_font_family_list(sl)
661+
local strings = {}
662+
for s in sl:gmatch('([^,]+)') do
663+
s = dequote(trim(s))
664+
s = translate_font_family(s)
665+
table.insert(strings, quote(s))
666+
end
667+
return '(' .. table.concat(strings, ', ') ..')'
668+
end
669+
670+
637671
local function translate_border_style(v, _warnings)
638672
local dash
639673
if v == 'none' then
@@ -760,6 +794,8 @@ return {
760794
translate_border_style = translate_border_style,
761795
translate_border_color = translate_border_color,
762796
translate_font_weight = translate_font_weight,
797+
translate_font_family = translate_font_family,
798+
translate_font_family_list = translate_font_family_list,
763799
consume_width = consume_width,
764800
consume_style = consume_style,
765801
consume_color = consume_color

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ function render_typst_brand_yaml()
116116
if headings and next(headings) then
117117
quarto.doc.include_text('in-header', table.concat({
118118
'#show heading: set text(',
119-
conditional_entry('font', headings.family),
119+
conditional_entry('font', _quarto.modules.typst.css.translate_font_family(headings.family)),
120120
conditional_entry('weight', _quarto.modules.typst.css.translate_font_weight(headings.weight)),
121121
conditional_entry('style', headings.style),
122122
conditional_entry('fill', headings.color, false),
@@ -137,7 +137,7 @@ function render_typst_brand_yaml()
137137
if monospaceInline and next(monospaceInline) then
138138
quarto.doc.include_text('in-header', table.concat({
139139
'#show raw.where(block: false): set text(',
140-
conditional_entry('font', monospaceInline.family),
140+
conditional_entry('font', _quarto.modules.typst.css.translate_font_family(monospaceInline.family)),
141141
conditional_entry('weight', _quarto.modules.typst.css.translate_font_weight(monospaceInline.weight)),
142142
conditional_entry('size', monospaceInline.size, false),
143143
conditional_entry('fill', monospaceInline.color, false),
@@ -156,7 +156,7 @@ function render_typst_brand_yaml()
156156
if monospaceBlock and next(monospaceBlock) then
157157
quarto.doc.include_text('in-header', table.concat({
158158
'#show raw.where(block: true): set text(',
159-
conditional_entry('font', monospaceBlock.family),
159+
conditional_entry('font', _quarto.modules.typst.css.translate_font_family(monospaceBlock.family)),
160160
conditional_entry('weight', _quarto.modules.typst.css.translate_font_weight(monospaceBlock.weight)),
161161
conditional_entry('size', monospaceBlock.size, false),
162162
conditional_entry('fill', monospaceBlock.color, false),
@@ -307,7 +307,7 @@ function render_typst_brand_yaml()
307307
local base = _quarto.modules.brand.get_typography('base')
308308
if base and next(base) then
309309
meta.brand.typography.base = {
310-
family = base.family,
310+
family = _quarto.modules.typst.css.translate_font_family(base.family),
311311
size = base.size,
312312
}
313313
end
@@ -322,7 +322,7 @@ function render_typst_brand_yaml()
322322
local weight = _quarto.modules.typst.css.translate_font_weight(headings.weight or base.weight)
323323
weight = weight and pandoc.RawInline('typst', tostring(quote_string(weight)))
324324
meta.brand.typography.headings = {
325-
family = headings.family or base.family,
325+
family = _quarto.modules.typst.css.translate_font_family(headings.family or base.family),
326326
weight = weight,
327327
style = headings.style or base.style,
328328
decoration = headings.decoration or base.decoration,

src/resources/filters/quarto-post/typst-css-property-processing.lua

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,6 @@ function render_typst_css_property_processing()
3232
end
3333
end
3434

35-
local function dequote(s)
36-
return s:gsub('^["\']', ''):gsub('["\']$', '')
37-
end
38-
39-
local function quote(s)
40-
return '"' .. s .. '"'
41-
end
42-
4335
local function translate_vertical_align(va)
4436
if va == 'top' then
4537
return 'top'
@@ -270,15 +262,6 @@ function render_typst_css_property_processing()
270262
end
271263
return span
272264
end
273-
274-
local function translate_string_list(sl)
275-
local strings = {}
276-
for s in sl:gmatch('([^,]+)') do
277-
s = s:gsub('^%s+', '')
278-
table.insert(strings, quote(dequote(s)))
279-
end
280-
return '(' .. table.concat(strings, ', ') ..')'
281-
end
282265

283266
return {
284267
Table = function(tab)
@@ -289,7 +272,7 @@ function render_typst_css_property_processing()
289272
for clause in tabstyle:gmatch('([^;]+)') do
290273
local k, v = to_kv(clause)
291274
if k == 'font-family' then
292-
tab.attributes['typst:text:font'] = translate_string_list(v)
275+
tab.attributes['typst:text:font'] = _quarto.format.typst.css.translate_font_family_list(v)
293276
has_typst_text = true
294277
end
295278
if k == 'font-size' then
164 KB
Binary file not shown.

0 commit comments

Comments
 (0)