Skip to content

Commit e59b35c

Browse files
authored
Merge pull request #11028 from quarto-dev/feature/brand-yaml-html-monospace-fixes
brand,fonts,bootstrap - add support for weight+size+color customization
2 parents 412ea63 + 431ee5d commit e59b35c

File tree

10 files changed

+171
-36
lines changed

10 files changed

+171
-36
lines changed

src/core/sass.ts

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { cssVarsBlock } from "./sass/add-css-vars.ts";
2020
import { md5HashBytes } from "./hash.ts";
2121
import { kSourceMappingRegexes } from "../config/constants.ts";
2222
import { writeTextFileSyncPreserveMode } from "./write.ts";
23+
import { quartoConfig } from "../core/quarto.ts";
2324

2425
export interface SassVariable {
2526
name: string;
@@ -107,35 +108,36 @@ export async function compileSass(
107108
// * Rules may use functions, variables, and mixins
108109
// (theme follows framework so it can override the framework rules)
109110
let scssInput = [
110-
'// quarto-scss-analysis-annotation { "origin": null }',
111+
`// quarto-scss-analysis-annotation { "quarto-version": "${quartoConfig.version()}" }`,
112+
'// quarto-scss-analysis-annotation { "origin": "\'use\' section from format" }',
111113
...frameWorkUses,
112-
'// quarto-scss-analysis-annotation { "origin": null }',
114+
'// quarto-scss-analysis-annotation { "origin": "\'use\' section from Quarto" }',
113115
...quartoUses,
114-
'// quarto-scss-analysis-annotation { "origin": null }',
116+
'// quarto-scss-analysis-annotation { "origin": "\'use\' section from user-defined SCSS" }',
115117
...userUses,
116-
'// quarto-scss-analysis-annotation { "origin": null }',
118+
'// quarto-scss-analysis-annotation { "origin": "\'functions\' section from format" }',
117119
...frameworkFunctions,
118-
'// quarto-scss-analysis-annotation { "origin": null }',
120+
'// quarto-scss-analysis-annotation { "origin": "\'functions\' section from Quarto" }',
119121
...quartoFunctions,
120-
'// quarto-scss-analysis-annotation { "origin": null }',
122+
'// quarto-scss-analysis-annotation { "origin": "\'functions\' section from user-defined SCSS" }',
121123
...userFunctions,
122-
'// quarto-scss-analysis-annotation { "origin": null }',
124+
'// quarto-scss-analysis-annotation { "origin": "Defaults from user-defined SCSS" }',
123125
...userDefaults.reverse(),
124-
'// quarto-scss-analysis-annotation { "origin": null }',
126+
'// quarto-scss-analysis-annotation { "origin": "Defaults from Quarto\'s SCSS" }',
125127
...quartoDefaults.reverse(),
126-
'// quarto-scss-analysis-annotation { "origin": null }',
128+
'// quarto-scss-analysis-annotation { "origin": "Defaults from the format SCSS" }',
127129
...frameworkDefaults.reverse(),
128-
'// quarto-scss-analysis-annotation { "origin": null }',
130+
'// quarto-scss-analysis-annotation { "origin": "\'mixins\' section from format" }',
129131
...frameworkMixins,
130-
'// quarto-scss-analysis-annotation { "origin": null }',
132+
'// quarto-scss-analysis-annotation { "origin": "\'mixins\' section from Quarto" }',
131133
...quartoMixins,
132-
'// quarto-scss-analysis-annotation { "origin": null }',
134+
'// quarto-scss-analysis-annotation { "origin": "\'mixins\' section from user-defined SCSS" }',
133135
...userMixins,
134-
'// quarto-scss-analysis-annotation { "origin": null }',
136+
'// quarto-scss-analysis-annotation { "origin": "\'rules\' section from format" }',
135137
...frameworkRules,
136-
'// quarto-scss-analysis-annotation { "origin": null }',
138+
'// quarto-scss-analysis-annotation { "origin": "\'rules\' section from Quarto" }',
137139
...quartoRules,
138-
'// quarto-scss-analysis-annotation { "origin": null }',
140+
'// quarto-scss-analysis-annotation { "origin": "\'rules\' section from user-defined SCSS" }',
139141
...userRules,
140142
'// quarto-scss-analysis-annotation { "origin": null }',
141143
].join("\n\n");

src/core/sass/analyzer/forward-annotations.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import { annotateNode } from './ast-utils.ts';
1+
import { annotateNode } from "./ast-utils.ts";
22

33
export const forwardAnnotations = (ast: any) => {
44
const pragmaAnnotation = "quarto-scss-analysis-annotation";
5-
const currentAnnotation: Record<string, unknown> = {};
6-
let hasAnnotations: boolean = false
5+
const annotationStack: Record<string, string>[] = [{}];
6+
let currentAnnotation: Record<string, unknown> = annotationStack[0];
7+
let hasAnnotations: boolean = false;
78
for (const node of ast.children) {
89
if (node.type === "comment_singleline") {
910
const value = node?.value?.trim();
@@ -15,7 +16,18 @@ export const forwardAnnotations = (ast: any) => {
1516
console.error("Could not parse annotation payload", e);
1617
continue;
1718
}
19+
if (payload.action === "push") {
20+
annotationStack.push(JSON.parse(JSON.stringify(currentAnnotation)));
21+
currentAnnotation = annotationStack[annotationStack.length - 1];
22+
} else if (payload.action === "pop" && annotationStack.length) {
23+
annotationStack.pop();
24+
currentAnnotation = annotationStack[annotationStack.length - 1];
25+
}
26+
1827
for (const [key, value] of Object.entries(payload)) {
28+
if (key === "action") {
29+
continue;
30+
}
1931
if (value === null) {
2032
delete currentAnnotation[key];
2133
} else {
@@ -30,4 +42,4 @@ export const forwardAnnotations = (ast: any) => {
3042
}
3143
}
3244
return ast;
33-
}
45+
};

src/core/sass/brand.ts

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,10 @@ const brandColorBundle = (
180180
key: string,
181181
nameMap: Record<string, string>,
182182
): SassBundleLayers => {
183-
const colorVariables: string[] = ["/* color variables from _brand.yml */"];
183+
const colorVariables: string[] = [
184+
"/* color variables from _brand.yml */",
185+
'// quarto-scss-analysis-annotation { "action": "push", "origin": "_brand.yml color" }',
186+
];
184187
for (const colorKey of Object.keys(brand.data?.color?.palette ?? {})) {
185188
colorVariables.push(
186189
`$${colorKey}: ${brand.getColor(colorKey)} !default;`,
@@ -204,6 +207,7 @@ const brandColorBundle = (
204207
}
205208
}
206209
// const colorEntries = Object.keys(brand.color);
210+
colorVariables.push('// quarto-scss-analysis-annotation { "action": "pop" }');
207211
const colorBundle: SassBundleLayers = {
208212
key,
209213
// dependency: "bootstrap",
@@ -224,6 +228,7 @@ const brandTypographyBundle = (
224228
): SassBundleLayers => {
225229
const typographyVariables: string[] = [
226230
"/* typography variables from _brand.yml */",
231+
'// quarto-scss-analysis-annotation { "action": "push", "origin": "_brand.yml typography" }',
227232
];
228233
const typographyImports: string[] = [];
229234
const fonts = brand.data?.typography?.fonts ?? [];
@@ -266,7 +271,7 @@ const brandTypographyBundle = (
266271
`Inconsisent Google font families found: ${googleFamily} and ${thisFamily}`,
267272
);
268273
}
269-
typographyVariables.push(googleFontImportString(resolvedFont));
274+
typographyImports.push(googleFontImportString(resolvedFont));
270275
}
271276
if (googleFamily === "") {
272277
return undefined;
@@ -323,12 +328,14 @@ const brandTypographyBundle = (
323328
["family", "font-family-base"],
324329
["size", "font-size-base"],
325330
["line-height", "line-height-base"],
331+
["weight", "font-weight-base"],
326332

327333
// revealjs
328334
["family", "mainFont"],
329335
["size", "presentation-font-size-root"],
330336
["line-height", "presentation-line-height"],
331337
// TBD?
338+
332339
// ["style", "font-style-base"],
333340
// ["weight", "font-weight-base"],
334341
],
@@ -353,8 +360,16 @@ const brandTypographyBundle = (
353360
["family", "font-family-monospace"],
354361
// bootstrap
355362
["size", "code-font-size"],
363+
// forward explicitly to both `code` and `pre`
364+
// because that interacts less with the default bootstrap styles
365+
["color", "code-color"], // this is also revealjs
366+
["color", "pre-color"],
367+
368+
["weight", "font-weight-monospace"],
369+
356370
// revealjs
357371
["size", "code-block-font-size"],
372+
["color", "code-block-color"],
358373
],
359374
"monospace-block": [
360375
// bootstrap + revealjs
@@ -363,6 +378,8 @@ const brandTypographyBundle = (
363378
["line-height", "pre-line-height"],
364379
["color", "pre-color"],
365380
["background-color", "pre-bg"],
381+
["size", "code-block-font-size"],
382+
["weight", "font-weight-monospace-block"],
366383
// revealjs
367384
["line-height", "code-block-line-height"],
368385
["color", "code-block-color"],
@@ -375,18 +392,20 @@ const brandTypographyBundle = (
375392
["background-color", "code-bg"],
376393
// bootstrap
377394
["size", "code-inline-font-size"],
395+
["weight", "font-weight-monospace-inline"],
378396
// revealjs
379-
["size", "code-block-font-size"],
397+
// ["size", "code-block-font-size"],
380398
],
381399
};
382400

383401
for (
384402
const kind of [
385-
"base",
386-
"headings",
387-
"monospace",
403+
// more specific entries go first
388404
"monospace-block",
389405
"monospace-inline",
406+
"monospace",
407+
"headings",
408+
"base",
390409
]
391410
) {
392411
const fontInformation = resolveHTMLFontInformation(
@@ -410,6 +429,9 @@ const brandTypographyBundle = (
410429
}
411430
}
412431

432+
typographyVariables.push(
433+
'// quarto-scss-analysis-annotation { "action": "pop" }',
434+
);
413435
const typographyBundle: SassBundleLayers = {
414436
key,
415437
// dependency: "bootstrap",

src/format/reveal/format-reveal-theme.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {
1818

1919
import { isFileRef } from "../../core/http.ts";
2020
import { pathWithForwardSlashes } from "../../core/path.ts";
21-
import { formatResourcePath } from "../../core/resources.ts";
21+
import { formatResourcePath, resourcePath } from "../../core/resources.ts";
2222
import {
2323
cleanSourceMappingUrl,
2424
compileSass,
@@ -164,6 +164,7 @@ export async function revealTheme(
164164
const quartoLayers = [
165165
quartoBaseLayer(format, true, true, false, true),
166166
quartoLayer(),
167+
quartoRevealBrandLayer(),
167168
];
168169
const titleSlideLayer = titleSlideScss(format);
169170
if (titleSlideLayer) {
@@ -284,3 +285,9 @@ function quartoLayer(): SassLayer {
284285
function themeLayer(theme: string): SassLayer {
285286
return sassLayerFile(theme);
286287
}
288+
289+
function quartoRevealBrandLayer(): SassLayer {
290+
return sassLayerFile(
291+
resourcePath(join("formats", "revealjs", "brand", "brand.scss")),
292+
);
293+
}

src/resources/formats/html/bootstrap/_bootstrap-rules.scss

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2144,3 +2144,20 @@ code.sourceCode a.code-annotation-anchor {
21442144
#quarto-back-to-top {
21452145
z-index: 1000;
21462146
}
2147+
2148+
// override _reboot.scss
2149+
2150+
// code blocks
2151+
pre code {
2152+
font-family: $font-family-monospace-block;
2153+
// I'm really not confident that this is correct
2154+
@include font-size($code-block-font-size);
2155+
font-weight: $font-weight-monospace-block;
2156+
}
2157+
2158+
// code inlines
2159+
p code {
2160+
font-family: $font-family-monospace-inline;
2161+
@include font-size($code-inline-font-size);
2162+
font-weight: $font-weight-monospace-inline;
2163+
}

src/resources/formats/html/bootstrap/_bootstrap-variables.scss

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,4 +244,23 @@ $table-group-separator-color-lighter: lighten(
244244

245245
$bootstrap-version: 5;
246246

247-
$h1h2h3-font-weight: 600 !default;
247+
$h1h2h3-font-weight: 600 !default;
248+
249+
// variables required by _brand.yml
250+
251+
// these variables need to have been defined here already
252+
// and are repeated in the framework's own _variables.scss
253+
// This will require us to monitor framework changes
254+
// to avoid drift
255+
$font-weight-base: 400 !default;
256+
$small-font-size: 0.875em !default;
257+
$code-font-size: $small-font-size !default;
258+
$font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace !default;
259+
260+
$font-family-monospace-block: $font-family-monospace !default;
261+
$font-family-monospace-inline: $font-family-monospace !default;
262+
$font-weight-monospace: $font-weight-base !default;
263+
$font-weight-monospace-block: $font-weight-monospace !default;
264+
$font-weight-monospace-inline: $font-weight-monospace !default;
265+
$code-block-font-size: $code-font-size !default;
266+
$code-inline-font-size: $code-font-size !default;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/*-- scss:uses --*/
2+
3+
// this file is currently intentionally empty
4+
5+
/*-- scss:mixins --*/
6+
7+
/*-- scss:functions --*/
8+
9+
/*-- scss:defaults --*/
10+
11+
/*-- scss:rules --*/

src/resources/formats/revealjs/quarto.scss

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,14 @@ $presentation-font-size-root: 40px !default;
1313
$presentation-font-smaller: 0.7 !default;
1414
$presentation-line-height: 1.3 !default;
1515

16+
// Default variables which exist in bootstrap themes
17+
// and are here to simplify the implementation of _brand.yml and
18+
// user theming customization in general
19+
$font-weight-base: 400 !default;
20+
$code-font-size: $presentation-font-size-root !default;
21+
$font-family-monospace-block: $font-family-monospace !default;
22+
$font-family-monospace-inline: $font-family-monospace !default;
23+
1624
// main colors
1725
$body-bg: #fff !default;
1826
$body-color: #222 !default;
@@ -66,10 +74,11 @@ $presentation-list-bullet-color: $body-color !default;
6674
// code blocks
6775
$code-block-bg: $body-bg !default;
6876
$code-block-border-color: lighten($body-color, 60%) !default;
69-
$code-block-font-size: 0.55em !default;
77+
$code-block-font-size: ($code-font-size * 0.55) !default;
7078
$code-block-height: 500px !default;
7179
$code-block-theme-dark-threshhold: 40% !default;
7280
$code-block-line-height: $presentation-line-height !default;
81+
$code-block-color: $body-color !default;
7382

7483
// inline code
7584
$code-color: var(--quarto-hl-fu-color) !default;
@@ -146,6 +155,8 @@ $heading3Size: $revealjs-h3-font-size !default;
146155
$heading4Size: $revealjs-h4-font-size !default;
147156

148157
$codeFont: $font-family-monospace !default;
158+
$inlineCodeFont: $font-family-monospace-inline !default;
159+
$blockCodeFont: $font-family-monospace-block !default;
149160

150161
// Links and actions
151162
$linkColor: $link-color !default;
@@ -169,6 +180,14 @@ $kbd-font-size: $presentation-font-size-root !default;
169180
$kbd-color: $body-color !default;
170181
$kbd-bg: $gray-100 !default; // like in bootstrap style
171182

183+
// variables required by _brand.yml
184+
$font-family-monospace-block: $font-family-monospace !default;
185+
$font-family-monospace-inline: $font-family-monospace !default;
186+
$font-weight-monospace: $font-weight-base !default;
187+
$font-weight-monospace-block: $font-weight-monospace !default;
188+
$font-weight-monospace-inline: $font-weight-monospace !default;
189+
$code-inline-font-size: $code-font-size !default;
190+
172191
/*-- scss:functions --*/
173192

174193
@function colorToRGB($color) {
@@ -303,6 +322,7 @@ div.reveal div.slides section.quarto-title-block {
303322

304323
.reveal code {
305324
color: $code-color;
325+
font-size: $code-inline-font-size;
306326
background-color: $code-bg;
307327
white-space: pre-wrap;
308328
}
@@ -319,7 +339,8 @@ div.reveal div.slides section.quarto-title-block {
319339

320340
.reveal pre code {
321341
background-color: $body-bg;
322-
color: $body-color;
342+
font-size: $code-block-font-size;
343+
color: $code-block-color;
323344
}
324345

325346
.reveal .column-output-location {
@@ -791,3 +812,16 @@ kbd {
791812
border-radius: 5px;
792813
padding: $kbd-padding-y $kbd-padding-x;
793814
}
815+
816+
:root {
817+
--r-inline-code-font: #{$inlineCodeFont};
818+
--r-block-code-font: #{$blockCodeFont};
819+
}
820+
821+
.reveal code {
822+
font-family: var(--r-inline-code-font);
823+
}
824+
825+
.reveal pre code {
826+
font-family: var(--r-block-code-font);
827+
}

0 commit comments

Comments
 (0)