Skip to content

Commit ec64e11

Browse files
committed
merge
2 parents 8bf2c42 + 7c8fd21 commit ec64e11

File tree

75 files changed

+2716
-1287
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+2716
-1287
lines changed

news/changelog-1.8.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ All changes included in 1.8:
3333

3434
### `revealjs`
3535

36+
- ([#10933](https://github.com/quarto-dev/quarto-cli/issues/10933)): Revealjs supports alt text on logo, as well as customization of light and dark logos at the document level, consistent with other formats.
37+
- ([#12550](https://github.com/quarto-dev/quarto-cli/issues/12550)): Revealjs supports `brand-mode`, allowing to select either the light or the dark brand.
3638
- ([#12598](https://github.com/quarto-dev/quarto-cli/pull/12598)): Ensure `.fragment` on an image with caption applies to whole figure.
3739
- ([#12716](https://github.com/quarto-dev/quarto-cli/issues/12716)): Correctly resolve `"brand"` set in `theme` configuration for document in subdirectory from project root.
3840
- Use `cdn.jsdelivr.net` for mathjax dependencies to ensure consistent CDN usage across formats. Previously, `cdnjs.cloudflare.com` was used for `revealjs` mathjax dependencies, while `cdn.jsdelivr.net` was used for html format.
@@ -43,12 +45,13 @@ All changes included in 1.8:
4345

4446
### `typst`
4547

46-
- ([#12180](https://github.com/quarto-dev/quarto-cli/issues/12180): Typst schema / autocomplete for `logo` option has `path` and `alt`.
48+
- ([#12180](https://github.com/quarto-dev/quarto-cli/issues/12180)): Typst schema / autocomplete for `logo` option has `path` and `alt`.
4749
- ([#12554](https://github.com/quarto-dev/quarto-cli/pull/12554)): CSS properties `font-weight` and `font-style` are translated to Typst `text` properties.
4850
- ([#12695](https://github.com/quarto-dev/quarto-cli/issues/12695)): Resolve Typst `font-paths` that start with `/` relative to project root.
4951
- ([#12739](https://github.com/quarto-dev/quarto-cli/pull/12739)): Remove unused variable `heading-background-color` and `heading-decoration` from Typst's templates. They are leftover from previous change, and not part of Brand.yml schema for typography of headings.
5052
- ([#12815](https://github.com/quarto-dev/quarto-cli/issues/12815)): Do not crash when floats have no content.
5153
- ([#13119](https://github.com/quarto-dev/quarto-cli/pull/13119)): Expose `brand.logo` metadata as Typst dictionaries.
54+
- ([#13133](https://github.com/quarto-dev/quarto-cli/pull/13133)): Allow customization of light and dark logos at document level, consistent with other formats.
5255

5356
### `beamer`
5457

@@ -76,6 +79,7 @@ All changes included in 1.8:
7679
- ([#12727](https://github.com/quarto-dev/quarto-cli/issues/12727)): Do not crash in the presence of malformed tabset contents.
7780
- ([#12806](https://github.com/quarto-dev/quarto-cli/pull/12806)): Use pandoc APIs to handle codepage conversion on Windows.
7881
- ([#12811](https://github.com/quarto-dev/quarto-cli/pull/12811)): Add support for YouTube Shorts in `video` shortcode.
82+
- ([#13128](https://github.com/quarto-dev/quarto-cli/issues/13128)): Meta shortcode could crash on bad input.
7983

8084
## Commands
8185

src/core/brand/brand.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ import { join, relative } from "../../deno_ral/path.ts";
3333
import { warnOnce } from "../log.ts";
3434
import { isCssColorName } from "../css/color-names.ts";
3535
import { assert } from "testing/asserts";
36+
import {
37+
LogoLightDarkSpecifierPathOptional,
38+
LogoOptionsPathOptional,
39+
LogoSpecifier,
40+
LogoSpecifierPathOptional,
41+
} from "../../resources/types/schema-types.ts";
3642

3743
type ProcessedBrandData = {
3844
color: Record<string, string>;
@@ -379,6 +385,62 @@ export function resolveLogo(
379385
};
380386
}
381387

388+
// this a typst workaround but might as well write it as a proper function
389+
export function fillLogoPaths(
390+
brand: LightDarkBrand | undefined,
391+
spec: LogoLightDarkSpecifierPathOptional | undefined,
392+
order: BrandNamedLogo[],
393+
): LogoLightDarkSpecifier | undefined {
394+
function findLogoSize(
395+
mode: "light" | "dark",
396+
): string | undefined {
397+
if (brand?.[mode]) {
398+
for (const size of order) {
399+
if (brand[mode].processedData.logo[size]) {
400+
return size;
401+
}
402+
}
403+
}
404+
return undefined;
405+
}
406+
function resolveMode(
407+
mode: "light" | "dark",
408+
spec: LogoSpecifierPathOptional | undefined,
409+
): LogoSpecifier | undefined {
410+
if (!spec) {
411+
return undefined;
412+
}
413+
if (!spec || typeof spec === "string") {
414+
return spec;
415+
} else if (spec.path) {
416+
return spec as LogoOptions;
417+
} else {
418+
const size = findLogoSize(mode) ||
419+
findLogoSize(mode === "light" ? "dark" : "light");
420+
if (size) {
421+
return {
422+
path: size,
423+
...spec,
424+
};
425+
}
426+
}
427+
return undefined;
428+
}
429+
if (!spec || typeof spec === "string") {
430+
return spec;
431+
}
432+
if ("light" in spec || "dark" in spec) {
433+
return {
434+
light: resolveMode("light", spec.light),
435+
dark: resolveMode("dark", spec.dark),
436+
};
437+
}
438+
return {
439+
light: resolveMode("light", spec as LogoOptionsPathOptional),
440+
dark: resolveMode("dark", spec as LogoOptionsPathOptional),
441+
};
442+
}
443+
382444
function splitColorLightDark(
383445
bcld: BrandColorLightDark,
384446
): LightDarkColor {

src/core/lib/yaml-schema/common.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ export function objectSchema(params: {
281281
);
282282
console.error("This is a bug in quarto's schemas.");
283283
console.error(
284-
"Note that we don't throw in order to allow build-js to finish, but the generated schemas will be invalid.",
284+
"Note that we don't throw in order to allow build-artifacts to finish, but the generated schemas will be invalid.",
285285
);
286286
}
287287

src/core/lib/yaml-schema/definitions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export function defineCached(
3232
let schema: ConcreteSchema;
3333

3434
return async () => {
35-
// when running on the CLI outside of quarto build-js, these
35+
// when running on the CLI outside of quarto dev-call build-artifacts, these
3636
// definitions will already exist.
3737
if (hasSchemaDefinition(schemaId)) {
3838
schema = getSchemaDefinition(schemaId);

src/core/lib/yaml-validation/state.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export async function initState() {
4343
// many entry points. In addition, the CLI itself can have a number
4444
// of different initializers depending on the command being called:
4545
//
46-
// - quarto build-js uses an initializer that skips precompiled modules
46+
// - quarto dev-call build-artifacts uses an initializer that skips precompiled modules
4747
//
4848
// - Some of the test suite uses an initializer with precompiled
4949
// modules and includes tree-sitter (so the behavior is as close to

src/core/sass/brand.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {
2424
} from "../../resources/types/zod/schema-types.ts";
2525
import { Brand } from "../brand/brand.ts";
2626
import { darkModeDefault } from "../../format/html/format-html-info.ts";
27+
import { kBrandMode } from "../../config/constants.ts";
2728

2829
const defaultColorNameMap: Record<string, string> = {
2930
"link-color": "link",
@@ -634,14 +635,18 @@ export async function brandBootstrapSassLayers(
634635

635636
export async function brandRevealSassLayers(
636637
input: string | undefined,
637-
_format: Format,
638+
format: Format,
638639
project: ProjectContext,
639640
): Promise<SassLayer[]> {
641+
let brandMode: "light" | "dark" = "light";
642+
if (format.metadata[kBrandMode] === "dark") {
643+
brandMode = "dark";
644+
}
640645
return (await brandSassLayers(
641646
input,
642647
project,
643648
defaultColorNameMap,
644-
)).light;
649+
))[brandMode];
645650
}
646651

647652
export async function brandSassFormatExtras(

src/core/schema/yaml-schema.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
/*
2-
* yaml-schema.ts
3-
*
4-
* Copyright (C) 2022 Posit Software, PBC
5-
*
6-
*/
2+
* yaml-schema.ts
3+
*
4+
* Copyright (C) 2022 Posit Software, PBC
5+
*/
76

8-
// FIXME needs refactoring. This is mostly only used at build-js time,
7+
// FIXME needs refactoring. This is mostly only used at build-artifacts time,
98
// except for "parseAndValidate".
109

1110
import { YAMLSchema } from "../lib/yaml-validation/yaml-schema.ts";

src/format/reveal/format-reveal.ts

Lines changed: 16 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { join } from "../../deno_ral/path.ts";
77

88
import { Document, Element, NodeType } from "../../core/deno-dom.ts";
99
import {
10+
kBrandMode,
1011
kCodeLineNumbers,
1112
kFrom,
1213
kHtmlMathMethod,
@@ -78,6 +79,7 @@ import { ProjectContext } from "../../project/types.ts";
7879
import { titleSlidePartial } from "./format-reveal-title.ts";
7980
import { registerWriterFormatHandler } from "../format-handlers.ts";
8081
import { pandocNativeStr } from "../../core/pandoc/codegen.ts";
82+
import { resolveLogo } from "../../core/brand/brand.ts";
8183

8284
export function revealResolveFormat(format: Format) {
8385
format.metadata = revealMetadataFilter(format.metadata);
@@ -376,45 +378,25 @@ export function revealjsFormat() {
376378
);
377379
}
378380

379-
const determineRevealLogo = (format: Format): string | undefined => {
380-
const brandData = format.render.brand?.light?.processedData;
381-
if (brandData?.logo) {
382-
// add slide logo if we have one
383-
for (const size of Zod.BrandNamedLogo.options) {
384-
const logoInfo = brandData.logo[size];
385-
if (!logoInfo) {
386-
continue;
387-
}
388-
if (logoInfo) {
389-
return logoInfo.path;
390-
}
391-
}
392-
}
393-
};
394-
395381
function revealMarkdownAfterBody(format: Format) {
382+
let brandMode: "light" | "dark" = "light";
383+
if (format.metadata[kBrandMode] === "dark") {
384+
brandMode = "dark";
385+
}
396386
const lines: string[] = [];
397387
lines.push("::: {.quarto-auto-generated-content style='display: none;'}\n");
398-
let revealLogo = format
388+
const revealLogo = format
399389
.metadata[kSlideLogo] as (string | { path: string } | undefined);
400-
if (revealLogo) {
401-
if (typeof revealLogo === "object") {
402-
revealLogo = revealLogo.path;
403-
}
404-
if (Zod.BrandNamedLogo.options.includes(revealLogo as BrandNamedLogo)) {
405-
const brandData = format.render.brand?.light?.processedData;
406-
const logoInfo = brandData?.logo
407-
?.[revealLogo as BrandNamedLogo];
408-
if (logoInfo) {
409-
revealLogo = logoInfo.path;
410-
}
411-
}
412-
} else {
413-
revealLogo = determineRevealLogo(format);
414-
}
415-
if (revealLogo) {
390+
const logo = resolveLogo(format.render.brand, revealLogo, [
391+
"small",
392+
"medium",
393+
"large",
394+
]);
395+
if (logo && logo[brandMode]) {
396+
const modeLogo = logo[brandMode]!;
397+
const altText = modeLogo.alt ? `alt="${modeLogo.alt}" ` : "";
416398
lines.push(
417-
`<img src="${revealLogo}" class="slide-logo" />`,
399+
`<img src="${modeLogo.path}" ${altText}class="slide-logo" />`,
418400
);
419401
lines.push("\n");
420402
}

src/format/typst/format-typst.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
kFigFormat,
1515
kFigHeight,
1616
kFigWidth,
17+
kLogo,
1718
kNumberSections,
1819
kSectionNumbering,
1920
kShiftHeadingLevelBy,
@@ -30,6 +31,12 @@ import {
3031
import { formatResourcePath } from "../../core/resources.ts";
3132
import { createFormat } from "../formats-shared.ts";
3233
import { hasLevelOneHeadings as hasL1Headings } from "../../core/lib/markdown-analysis/level-one-headings.ts";
34+
import {
35+
BrandNamedLogo,
36+
LogoLightDarkSpecifier,
37+
} from "../../resources/types/schema-types.ts";
38+
import { fillLogoPaths, resolveLogo } from "../../core/brand/brand.ts";
39+
import { LogoLightDarkSpecifierPathOptional } from "../../resources/types/zod/schema-types.ts";
3340

3441
export function typstFormat(): Format {
3542
return createFormat("Typst", "pdf", {
@@ -78,6 +85,19 @@ export function typstFormat(): Format {
7885
pandoc[kShiftHeadingLevelBy] = -1;
7986
}
8087

88+
const brand = format.render.brand;
89+
const logoSpec = format
90+
.metadata[kLogo] as LogoLightDarkSpecifierPathOptional;
91+
const sizeOrder: BrandNamedLogo[] = [
92+
"small",
93+
"medium",
94+
"large",
95+
];
96+
// temporary: if document logo has object or light/dark objects
97+
// without path, do our own findLogo to add the path
98+
// typst is the exception not needing path but we'll probably deprecate this
99+
const logo = fillLogoPaths(brand, logoSpec, sizeOrder);
100+
format.metadata[kLogo] = resolveLogo(brand, logo, sizeOrder);
81101
// force columns to wrap and move any 'columns' setting to metadata
82102
const columns = format.pandoc[kColumns];
83103
if (columns) {

0 commit comments

Comments
 (0)